diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index b634592537a5b0..82714a408dfed2 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "10.0.0-prerelease.25103.1", + "version": "10.0.0-prerelease.25164.1", "commands": [ "xharness" ] diff --git a/Directory.Build.props b/Directory.Build.props index 03f77f38f6dc4b..d13e0749062eaf 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -82,9 +82,6 @@ 10.0 net$(AspNetCoreAppCurrentVersion) - net462 - net48 - net472 diff --git a/docs/area-owners.md b/docs/area-owners.md index 7c7d703d0e4563..2aeaa8770f42dd 100644 --- a/docs/area-owners.md +++ b/docs/area-owners.md @@ -42,8 +42,8 @@ Note: Editing this file doesn't update the mapping used by `@dotnet-policy-servi | area-Extensions-Primitives | @ericstj | @dotnet/area-extensions-primitives | | | area-GC-coreclr | @mangod9 | @Maoni0 | | | area-GC-mono | @mangod9 | @mangod9 | @BrzVlad to consult | -| area-Host | @agocke | @jeffschwMSFT @vitek-karas @vsadov | Issues with dotnet.exe including bootstrapping, framework detection, hostfxr.dll and hostpolicy.dll | -| area-HostModel | @agocke | @vitek-karas | | +| area-Host | @agocke | @jeffschwMSFT @elinor-fung @vsadov | Issues with dotnet.exe including bootstrapping, framework detection, hostfxr.dll and hostpolicy.dll | +| area-HostModel | @agocke | @elinor-fung | | | area-ILTools-coreclr | @JulieLeeMSFT | @BruceForstall @dotnet/jit-contrib | | | area-Infrastructure | @agocke | @jeffschwMSFT @MichaelSimons | | | area-Infrastructure-coreclr | @agocke | @jeffschwMSFT | | @@ -62,7 +62,7 @@ Note: Editing this file doesn't update the mapping used by `@dotnet-policy-servi | area-ReadyToRun-coreclr | @steveisok | @dotnet/area-type-system-and-startup | | | area-Serialization | @HongGit | @StephenMolloy @HongGit | Packages: Excluded: | | area-Setup | @MichaelSimons | @NikolaMilosavljevic | Distro-specific (Linux, Mac and Windows) setup packages and msi files | -| area-Single-File | @agocke | @vitek-karas @vsadov | | +| area-Single-File | @agocke | @elinor-fung @vsadov | | | area-Snap | @MichaelSimons | @NikolaMilosavljevic @leecow @MichaelSimons | | | area-System.Buffers | @jeffhandley | @dotnet/area-system-buffers | | | area-System.ClientModel | @terrajobst | @dotnet/fxdc | Bugs and feature requests should go to https://github.com/Azure/azure-sdk-for-net/issues. We don't own the code, but FXDC reviews changes to determine overlap with other `System` concepts. The Azure SDK team will post API updates in this repo for us to review. | diff --git a/docs/coding-guidelines/project-guidelines.md b/docs/coding-guidelines/project-guidelines.md index 35059779fa370b..0006e111fa1a83 100644 --- a/docs/coding-guidelines/project-guidelines.md +++ b/docs/coding-guidelines/project-guidelines.md @@ -69,7 +69,7 @@ When building an individual project the `BuildTargetFramework` and `TargetOS` wi ## Supported full build settings - .NET Core latest on current OS (default) -> `$(NetCoreAppCurrent)-[RunningOS]` -- .NET Framework latest -> `net48` +- .NET Framework latest -> `net481` # Library project guidelines diff --git a/docs/design/coreclr/botr/clr-abi.md b/docs/design/coreclr/botr/clr-abi.md index 9b69c69e67d82b..62e75ab0f7a125 100644 --- a/docs/design/coreclr/botr/clr-abi.md +++ b/docs/design/coreclr/botr/clr-abi.md @@ -452,7 +452,7 @@ The code this finally returns to looks like this: In this case, it zeros out the ShadowSP slot that it previously set to 0xFC, then jumps to the address that is the actual target of the leave from the finally. -The JIT does this "end finally restore" by creating a GT_END_LFIN tree node, with the appropriate stack level as an operand, that generates this code. +The JIT does this "end finally restore" by creating a GT_END_LFIN tree node, with the appropriate EH region ID as an operand, that generates this code. In the case of an exceptional 'finally' invocation, the VM sets up the 'return address' to whatever address it wants the JIT to return to. @@ -476,7 +476,7 @@ The VM walks the ShadowSP slots in the function `GetHandlerFrameInfo()`, and set An aside on the JIT implementation for x86. -The JIT creates BBJ_CALLFINALLY/BBJ_ALWAYS pairs for calling the 'finally' clause. The BBJ_CALLFINALLY block will have a series of CORINFO_JIT_ENDCATCH calls appended at the end, if we need to "leave" a series of nested catches before calling the finally handler (due to a single 'leave' opcode attempting to leave multiple levels of different types of handlers). Then, a GT_END_LFIN statement with the finally clause handler nesting level as an argument is added to the step block where the finally returns to. This is used to generate code to zero out the appropriate level of the ShadowSP slot array after the finally has been executed. The BBJ_CALLFINALLY block itself generates the code to insert the 0xFC value into the ShadowSP slot array. If the 'finally' is invoked by the VM, in exceptional cases, then the VM itself updates the ShadowSP slot array before invoking the 'finally'. +The JIT creates BBJ_CALLFINALLY/BBJ_ALWAYS pairs for calling the 'finally' clause. The BBJ_CALLFINALLY block will have a series of CORINFO_JIT_ENDCATCH calls appended at the end, if we need to "leave" a series of nested catches before calling the finally handler (due to a single 'leave' opcode attempting to leave multiple levels of different types of handlers). Then, a GT_END_LFIN statement with EH region ID as an argument is added to the step block where the finally returns to. This is used to generate code to zero out the appropriate level of the ShadowSP slot array after the finally has been executed and the final EH nesting depth is known. The BBJ_CALLFINALLY block itself generates the code to insert the 0xFC value into the ShadowSP slot array. If the 'finally' is invoked by the VM, in exceptional cases, then the VM itself updates the ShadowSP slot array before invoking the 'finally'. At the end of a finally or filter, a GT_RETFILT is inserted. For a finally, this is a TYP_VOID which is just a placeholder. For a filter, it takes an argument which evaluates to the return value from the filter. On legacy JIT, this tree triggers the generation of both the return value load (for filters) and the "funclet" exit sequence, which is either a "pop eax; jmp eax" for a finally, or a "ret" for a filter. When processing the BBJ_EHFINALLYRET or BBJ_EHFILTERRET block itself (at the end of code generation for the block), nothing is generated. In RyuJIT, the GT_RETFILT only loads up the return value (for filters) and does nothing for finally, and the block type processing after all the tree processing triggers the exit sequence to be generated. There is no real difference between these, except to centralize all "exit sequence" generation in the same place. diff --git a/docs/design/datacontracts/PrecodeStubs.md b/docs/design/datacontracts/PrecodeStubs.md index b9448ed0507f7c..83f593fcf2c0ad 100644 --- a/docs/design/datacontracts/PrecodeStubs.md +++ b/docs/design/datacontracts/PrecodeStubs.md @@ -9,7 +9,7 @@ This contract provides support for examining [precode](../coreclr/botr/method-de TargetPointer GetMethodDescFromStubAddress(TargetCodePointer entryPoint); ``` -## Version 1 +## Version 1 and 2 Data descriptors used: | Data Descriptor Name | Field | Meaning | @@ -24,9 +24,12 @@ Data descriptors used: | PrecodeMachineDescriptor | PInvokeImportPrecodeType| precode sort byte for PInvoke precode stubs, if supported | | PrecodeMachineDescriptor | HasFixupPrecode | 1 if platform supports fixup precode stubs | | PrecodeMachineDescriptor | FixupPrecodeType| precode sort byte for fixup precode stubs, if supported | -| StubPrecodeData | MethodDesc | pointer to the MethodDesc associated with this stub precode | +| PrecodeMachineDescriptor | ThisPointerRetBufPrecodeType | precode sort byte for this pointer ret buf precodes | +| StubPrecodeData | MethodDesc | pointer to the MethodDesc associated with this stub precode (Version 1 only) | +| StubPrecodeData | SecretParam | pointer to the MethodDesc associated with this stub precode or a second stub data pointer for other types (Version 2 only) | | StubPrecodeData | Type | precise sort of stub precode | | FixupPrecodeData | MethodDesc | pointer to the MethodDesc associated with this fixup precode | +| ThisPtrRetBufPrecodeData | MethodDesc | pointer to the MethodDesc associated with the ThisPtrRetBufPrecode (Version 2 only) | arm32 note: the `CodePointerToInstrPointerMask` is used to convert IP values that may include an arm Thumb bit (for example extracted from disassembling a call instruction or from a snapshot of the registers) into an address. On other architectures applying the mask is a no-op. @@ -145,7 +148,10 @@ After the initial precode type is determined, for stub precodes a refined precod internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) { TargetPointer stubPrecodeDataAddress = InstrPointer + precodeMachineDescriptor.StubCodePageSize; - return target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.MethodDesc */ ); + if (ContractVersion(PrecodeStubs) == 1) + return target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.MethodDesc */ ); + else + return target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.SecretParam */ ); } } @@ -170,7 +176,10 @@ After the initial precode type is determined, for stub precodes a refined precod internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) { - throw new NotImplementedException(); // TODO(cdac) + if (ContractVersion(PrecodeStubs) == 1) + throw new NotImplementedException(); // TODO(cdac) + else + return target.ReadPointer(target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.SecretParam */ ) + /*offset of ThisPtrRetBufPrecodeData.MethodDesc*/); } } diff --git a/docs/design/datacontracts/StackWalk.md b/docs/design/datacontracts/StackWalk.md index d76aece42731f9..774be93cdf7ea6 100644 --- a/docs/design/datacontracts/StackWalk.md +++ b/docs/design/datacontracts/StackWalk.md @@ -41,11 +41,25 @@ This contract depends on the following descriptors: | `InlinedCallFrame` | `CalleeSavedFP` | FP saved in Frame | | `SoftwareExceptionFrame` | `TargetContext` | Context object saved in Frame | | `SoftwareExceptionFrame` | `ReturnAddress` | Return address saved in Frame | +| `FramedMethodFrame` | `TransitionBlockPtr` | Pointer to Frame's TransitionBlock | +| `TransitionBlock` | `ReturnAddress` | Return address associated with the TransitionBlock | +| `TransitionBlock` | `CalleeSavedRegisters` | Platform specific CalleeSavedRegisters struct associated with the TransitionBlock | +| `FuncEvalFrame` | `DebuggerEvalPtr` | Pointer to the Frame's DebuggerEval object | +| `DebuggerEval` | `TargetContext` | Context saved inside DebuggerEval | +| `DebuggerEval` | `EvalDuringException` | Flag used in processing FuncEvalFrame | +| `ResumableFrame` | `TargetContextPtr` | Pointer to the Frame's Target Context | +| `FaultingExceptionFrame` | `TargetContext` | Frame's Target Context | +| `HijackFrame` | `ReturnAddress` | Frame's stored instruction pointer | +| `HijackFrame` | `HijackArgsPtr` | Pointer to the Frame's stored HijackArgs | +| `HijackArgs` (amd64) | `CalleeSavedRegisters` | CalleeSavedRegisters data structure | +| `HijackArgs` (amd64 Windows) | `Rsp` | Saved stack pointer | +| `HijackArgs` (arm64) | For each register `r` saved in HijackArgs, `r` | Register names associated with stored register values | +| `CalleeSavedRegisters` | For each callee saved register `r`, `r` | Register names associated with stored register values | Global variables used: | Global Name | Type | Purpose | | --- | --- | --- | -| For each FrameType ``, `##Identifier` | FrameIdentifier enum value | Identifier used to determine concrete type of Frames | +| For each FrameType ``, `##Identifier` | `FrameIdentifier` enum value | Identifier used to determine concrete type of Frames | Contracts used: | Contract Name | @@ -215,6 +229,71 @@ private static void bar() } ``` +### Capital 'F' Frame Handling + +Capital 'F' Frame's store context data in a number of different ways. Of the couple dozen Frame types defined in `src/coreclr/vm/frames.h` several do not store any context data or update the context, signified by `NeedsUpdateRegDisplay_Impl() == false`. Of that Frames that do update the context, several share implementations of `UpdateRegDisplay_Impl` through inheritance. This leaves us with 9 distinct mechanisms to update the context that will be detailed below. Each mechanism is referred to using the Frame class that implements the mechanism and may be used by subclasses. + +Most of the handlers are implemented in `BaseFrameHandler`. Platform specific components are implemented/overridden in `FrameHandler`. + +#### InlinedCallFrame + +InlinedCallFrames store and update only the IP, SP, and FP of a given context. If the stored IP (CallerReturnAddress) is 0 then the InlinedCallFrame does not have an active call and should not update the context. + +#### SoftwareExceptionFrame + +SoftwareExceptionFrames store a copy of the context struct. The IP, SP, and all ABI specified (platform specific) callee-saved registers are copied from the stored context to the working context. + +#### TransitionFrame + +TransitionFrames hold a pointer to a `TransitionBlock`. The TransitionBlock holds a return address along with a `CalleeSavedRegisters` struct which has values for all ABI specified callee-saved registers. The SP can be found using the address of the TransitionBlock. Since the TransitionBlock will be the lowest element on the stack, the SP is the address of the TransitionBlock + sizeof(TransitionBlock). + +When updating the context from a TransitionFrame, the IP, SP, and all ABI specified callee-saved registers are copied over. + +The following Frame types also use this mechanism: +* FramedMethodFrame +* CLRToCOMMethodFrame +* PInvokeCallIFrame +* PrestubMethodFrame +* StubDispatchFrame +* CallCountingHelperFrame +* ExternalMethodFrame +* DynamicHelperFrame + +#### FuncEvalFrame + +FuncEvalFrames hold a pointer to a `DebuggerEval`. The DebuggerEval holds a full context which is completely copied over to the working context when updating. + +#### ResumableFrame + +ResumableFrames hold a pointer to a context object (Note this is different from SoftwareExceptionFrames which hold the context directly). The entire context object is copied over to the working context when updating. + +RedirectedThreadFrames also use this mechanism. + +#### FaultingExceptionFrame + +FaultingExceptionFrames have two different implementations. One for Windows x86 and another for all other builds (with funclets). + +Given the cDAC does not yet support Windows x86, this version is not supported. + +The other version stores a context struct. To update the working context, the entire stored context is copied over. In addition the `ContextFlags` are updated to ensure the `CONTEXT_XSTATE` bit is not set given the debug version of the contexts can not store extended state. This bit is architecture specific. + +#### HijackFrame + +HijackFrames carry a IP (ReturnAddress) and a pointer to `HijackArgs`. All platforms update the IP and use the platform specific HijackArgs to update further registers. The following details currently implemented platforms. + +* x64 - On x64, HijackArgs contains a CalleeSavedRegister struct. The saved registers values contained in the struct are copied over to the working context. + * Windows - On Windows, HijackArgs also contains the SP value directly which is copied over to the working context. + * Non-Windows - On OS's other than Windows, HijackArgs does not contain an SP value. Instead since the HijackArgs struct lives on the stack, the SP is `&hijackArgs + sizeof(HijackArgs)`. This value is also copied over. +* arm64 - Unlike on x64, on arm64 HijackArgs contains a list of register values instead of the CalleeSavedRegister struct. These values are copied over to the working context. The SP is fetched using the same technique as on x64 non-Windows where `SP = &hijackArgs + sizeof(HijackArgs)` and is copied over to the working context. + +#### TailCallFrame + +TailCallFrames are only used on Windows x86 which is not yet supported in the cDAC and therefore not implemented. + +#### HelperMethodFrame + +HelperMethodFrames are on the way to being removed. They are not currently supported in the cDAC. + ### APIs The majority of the contract's complexity is the stack walking algorithm (detailed above) implemented as part of `CreateStackWalk`. diff --git a/docs/design/specs/runtime-async.md b/docs/design/specs/runtime-async.md index 0929c6d931ad5d..fc229b0ac78031 100644 --- a/docs/design/specs/runtime-async.md +++ b/docs/design/specs/runtime-async.md @@ -49,6 +49,15 @@ Async methods support suspension using one of the following methods: public static T Await(Task task); [MethodImpl(MethodImplOptions.Async)] public static T Await(ValueTask task); + + [MethodImpl(MethodImplOptions.Async)] + public static void Await(ConfiguredTaskAwaitable configuredAwaitable); + [MethodImpl(MethodImplOptions.Async)] + public static void Await(ConfiguredValueTaskAwaitable configuredAwaitable); + [MethodImpl(MethodImplOptions.Async)] + public static T Await(ConfiguredTaskAwaitable configuredAwaitable); + [MethodImpl(MethodImplOptions.Async)] + public static T Await(ConfiguredValueTaskAwaitable configuredAwaitable); } } ``` diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 7bed18fa502dcc..c40d4a50b30025 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -112,7 +112,7 @@ The PR that reveals the implementation of the ` true - true $(ArtifactsDir)staging/ $(ArtifactsStagingDir)SymStore diff --git a/eng/Signing.props b/eng/Signing.props index f98f72e13c1d43..0623aaa1c18cc1 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -58,16 +58,6 @@ - - - - - - + https://github.com/dotnet/source-build-reference-packages - 232bcf31aad21949f80d6706720540b85e43fff3 + c3d4c372a15c2de79a2f26fe2b6b3644996d8550 @@ -336,17 +336,17 @@ https://github.com/dotnet/runtime 088d199063dd1bf7fa00a445d23f93f915f84b31 - + https://github.com/dotnet/xharness - cf1b2925785f504d4d52773bcab470044e35ea15 + 6df4f3a2cd57adbde1607bba67f50613102d8bd9 - + https://github.com/dotnet/xharness - cf1b2925785f504d4d52773bcab470044e35ea15 + 6df4f3a2cd57adbde1607bba67f50613102d8bd9 - + https://github.com/dotnet/xharness - cf1b2925785f504d4d52773bcab470044e35ea15 + 6df4f3a2cd57adbde1607bba67f50613102d8bd9 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index e37c9e11d95bbd..24a6a7432c10d6 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,12 +7,12 @@ 0 0 $(MajorVersion).0.100 - 9.0.2 + 9.0.3 8.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet9)').Build),11)) 7.0.20 6.0.36 preview - 3 + 4 false release @@ -158,9 +158,9 @@ 10.0.0-beta.25126.1 10.0.0-beta.25126.1 - 10.0.0-prerelease.25103.1 - 10.0.0-prerelease.25103.1 - 10.0.0-prerelease.25103.1 + 10.0.0-prerelease.25164.1 + 10.0.0-prerelease.25164.1 + 10.0.0-prerelease.25164.1 10.0.0-alpha.0.25126.1 @@ -201,7 +201,7 @@ 1.0.2 2.0.4 4.18.4 - 6.7.0 + 8.0.2 2.14.3 2.9.1 diff --git a/eng/build-analysis-configuration.json b/eng/build-analysis-configuration.json index 06bf441873e2dc..208e753c836201 100644 --- a/eng/build-analysis-configuration.json +++ b/eng/build-analysis-configuration.json @@ -15,6 +15,10 @@ { "PipelineId": 157, "PipelineName": "runtime-llvm" + }, + { + "PipelineId": 265, + "PipelineName": "runtime-nativeaot-outerloop" } ] } diff --git a/eng/build.ps1 b/eng/build.ps1 index e38be81d660ecd..dd41e2cf85fbe9 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -78,7 +78,7 @@ function Get-Help() { Write-Host "Libraries settings:" Write-Host " -coverage Collect code coverage when testing." - Write-Host " -framework (-f) Build framework: net10.0 or net48." + Write-Host " -framework (-f) Build framework: net10.0 or net481." Write-Host " [Default: net10.0]" Write-Host " -testnobuild Skip building tests when invoking -test." Write-Host " -testscope Scope tests, allowed values: innerloop, outerloop, all." diff --git a/eng/build.sh b/eng/build.sh index 1cab7739726fa3..a4e36af19ee956 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -66,7 +66,7 @@ usage() echo "Libraries settings:" echo " --coverage Collect code coverage when testing." - echo " --framework (-f) Build framework: net10.0 or net48." + echo " --framework (-f) Build framework: net10.0 or net481." echo " [Default: net10.0]" echo " --testnobuild Skip building tests when invoking -test." echo " --testscope Test scope, allowed values: innerloop, outerloop, all." @@ -542,6 +542,10 @@ fi if [[ "$os" == "browser" ]]; then # override default arch for Browser, we only support wasm arch=wasm + # because on docker instance without swap file, MSBuild nodes need to make some room for LLVM + # https://github.com/dotnet/runtime/issues/113724 + # this is hexa percentage: 46-> 70% + export DOTNET_GCHeapHardLimitPercent="46" fi if [[ "$os" == "wasi" ]]; then # override default arch for wasi, we only support wasm diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index 274ab363bf7905..b04bfc9ca1397c 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -522,7 +522,7 @@ if (CLR_CMAKE_TARGET_ANDROID OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET set(CLR_CMAKE_USE_SYSTEM_ZLIB 1) endif() -if (NOT CLR_CMAKE_TARGET_ANDROID) +if (NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_TARGET_BROWSER) # opt into building tools like ildasm/ilasm set(CLR_CMAKE_BUILD_TOOLS 1) endif() diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index 0eb33099d4aa8a..bdf11a5c903610 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -17,118 +17,118 @@ extends: containers: linux_arm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm@sha256:b42b92a3a7d04f0761698680dd8601c91e74124097ab6c43f364bd420f5abe46 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm env: ROOTFS_DIR: /crossrootfs/arm linux_armv6: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-cross-armv6-raspbian-10@sha256:b3292e7f26790c74f3a5d311fc8294e3886199cfa31f499f34386b948dc37b0d + image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-cross-armv6-raspbian-10 env: ROOTFS_DIR: /crossrootfs/armv6 linux_arm64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm64@sha256:e8ec62a221b9e1a07abb73eb1ddd3b86802fd50a14462142e9b13f2bf9208cd8 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm64 env: ROOTFS_DIR: /crossrootfs/arm64 linux_musl_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64-musl@sha256:f244847db10686f8286961ef719957e1203142e274501be9a0fc28d44c81229c + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64-musl env: ROOTFS_DIR: /crossrootfs/x64 linux_musl_arm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm-musl@sha256:9b4c7dfb39577eecb0c44128a92bc8ac779afc5d1f400e6d478998f18faa3e1d + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm-musl env: ROOTFS_DIR: /crossrootfs/arm linux_musl_arm64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm64-musl@sha256:1a3ba98d92ba0242ede509deec9064df9593dc31f54cbe233d76a3475fa2897f + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-arm64-musl env: ROOTFS_DIR: /crossrootfs/arm64 # This container contains all required toolsets to build for Android and for Linux with bionic libc. android: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-android-amd64@sha256:e9bb28569eebdea5122dc487874004f28b16c6168b6e02ceac1a341b002ab01e + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-android-amd64 # This container contains all required toolsets to build for Android and for Linux with bionic libc and a special layout of OpenSSL. linux_bionic: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-android-openssl-amd64@sha256:20753705df1a6a799f26c2b5b00d400d5e261f4c60989539946d80cc92cb19d5 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-android-openssl-amd64 # This container contains all required toolsets to build for Android as well as tooling to build docker images. android_docker: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-android-docker-amd64@sha256:b41b35c3254f975bf06d778ce457c6109cca6765926ad1e76e8fc7d5ba162698 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-android-docker-amd64 linux_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64@sha256:a851d98c330f4e5eaa32f694f29bfed82e8047cf90bfb8a5000aa3fbdda47b4a + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64 env: ROOTFS_DIR: /crossrootfs/x64 linux_x86: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-x86@sha256:fa77d0239e3d511423ac85103636a666fe0da67ba2f25d4aa2044390b2662688 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-x86 env: ROOTFS_DIR: /crossrootfs/x86 linux_x64_dev_innerloop: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04@sha256:7458abba1a433923652d04b474bc26d488064801ed7bf395c3edd8746d78b146 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04 linux_musl_x64_dev_innerloop: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-WithNode@sha256:e2f2dddab2466124917a0fe09c5f8bf6678dac9d6e23b364dc6042819a1125a0 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-WithNode linux_x64_sanitizer: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64-sanitizer@sha256:a1b002dcb764fc63ac34f305b465cbc0461ba7ef9a2e7e0fa3b9dd0feb429182 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-amd64-sanitizer env: ROOTFS_DIR: /crossrootfs/x64 # We use a CentOS Stream 8 image here to test building from source on CentOS Stream 9. SourceBuild_centos_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9@sha256:6725e979e408951fd2f0ce9533ea0120f29d2fc086152af2d830a1c40f49c975 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9 # AlmaLinux 8 is a RHEL 8 rebuild, so we use it to test building from source on RHEL 8. SourceBuild_linux_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:almalinux-8-source-build@sha256:17fc48c23af4e41e909004cd474a6a799518d6b4d1335bb0b4fb4d01ea69cc4a + image: mcr.microsoft.com/dotnet-buildtools/prereqs:almalinux-8-source-build linux_s390x: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-s390x@sha256:a6ff63ad83425b2003a7a7b4e8e0732d7cf9b12bce9e1c1ced91a76d289c5123 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-s390x env: ROOTFS_DIR: /crossrootfs/s390x linux_ppc64le: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-ppc64le@sha256:8959695d5db2658e41af659b612e921a00fc490ba07fb1d4c1304724bacbe1c4 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-ppc64le env: ROOTFS_DIR: /crossrootfs/ppc64le linux_riscv64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-riscv64@sha256:d64f90c040c32f36ba4e90be5a276afb6adbd2daa92528906fed90140ea17137 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-riscv64 env: ROOTFS_DIR: /crossrootfs/riscv64 linux_loongarch64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-loongarch64@sha256:9587c99b1523cc074dd68bf6145200797fdd0d0c97b0ececf782c250ef0cfae4 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-loongarch64 env: ROOTFS_DIR: /crossrootfs/loongarch64 debian-12-gcc14-amd64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-gcc14-amd64@sha256:c3cf02c77cabebcfd53055315335c7a5ff46a4dde539bfdfa570c7e4ba2281c3 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-gcc14-amd64 linux_x64_llvmaot: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8@sha256:c7f8108d3c0dcf35c258f735de42082f52415a53a75788e75c054cd593210b29 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8 browser_wasm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-webassembly-amd64@sha256:b56cd247f05b5b1353bb1b1f2f22061d4bbff1ee0f0c8e6d49e3a382b728d0ba + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-webassembly-amd64 env: ROOTFS_DIR: /crossrootfs/x64 wasi_wasm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-webassembly-amd64@sha256:b56cd247f05b5b1353bb1b1f2f22061d4bbff1ee0f0c8e6d49e3a382b728d0ba + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-webassembly-amd64 env: ROOTFS_DIR: /crossrootfs/x64 freebsd_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-freebsd-14-amd64@sha256:9a13870c8778c0791e7329cf9339de2c6460b2d3bb271d5e9821d7b4ec2a3eca + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net10.0-cross-freebsd-14-amd64 env: ROOTFS_DIR: /crossrootfs/x64 tizen_armel: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-cross-armel-tizen@sha256:325453b3c4d3d6cae2abc22ce2735bd92d224f20e5ab35b27758c965c4f69c8d + image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-cross-armel-tizen env: ROOTFS_DIR: /crossrootfs/armel diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index 551a502ae9ed60..4171b5bcc33e57 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -386,6 +386,9 @@ jobs: - jitstress_isas_x86_nosse41 - jitstress_isas_x86_nosse42 - jitstress_isas_x86_nossse3 + - jitstress_isas_x86_vectort128 + - jitstress_isas_x86_vectort512 + - jitstress_isas_x86_noavx512_vectort128 - jitstress_isas_1_x86_noaes - jitstress_isas_1_x86_noavx - jitstress_isas_1_x86_noavx2 @@ -540,7 +543,6 @@ jobs: - jitpartialcompilation_pgo - jitpartialcompilation_pgo_stress_random - jitoptrepeat - - jitoldlayout ${{ else }}: scenarios: - jitosr_stress @@ -554,7 +556,6 @@ jobs: - jitphysicalpromotion_full - jitrlcse - jitoptrepeat - - jitoldlayout ${{ if in(parameters.testGroup, 'jit-cfg') }}: scenarios: - jitcfg diff --git a/eng/pipelines/common/templates/wasm-library-tests.yml b/eng/pipelines/common/templates/wasm-library-tests.yml index 51cf40074ff5bd..149215ea501937 100644 --- a/eng/pipelines/common/templates/wasm-library-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-tests.yml @@ -80,7 +80,7 @@ jobs: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} testGroup: innerloop nameSuffix: LibraryTests${{ parameters.nameSuffix }} - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:MonoEnableAssertMessages=true /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) $(chromeInstallArg) $(firefoxInstallArg) $(v8InstallArg) ${{ parameters.extraBuildArgs }} + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:MonoEnableAssertMessages=true /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) $(chromeInstallArg) $(firefoxInstallArg) $(v8InstallArg) /maxcpucount:1 ${{ parameters.extraBuildArgs }} timeoutInMinutes: 240 # if !alwaysRun, then: # if this is runtime-wasm (isWasmOnlyBuild): diff --git a/eng/pipelines/coreclr/libraries-pgo.yml b/eng/pipelines/coreclr/libraries-pgo.yml index 00a050da0e6210..a8f0e16b01f35c 100644 --- a/eng/pipelines/coreclr/libraries-pgo.yml +++ b/eng/pipelines/coreclr/libraries-pgo.yml @@ -71,4 +71,3 @@ extends: - syntheticpgo - syntheticpgo_blend - jitrlcse - - jitoldlayout diff --git a/eng/pipelines/coreclr/superpmi-replay.yml b/eng/pipelines/coreclr/superpmi-replay.yml index 7ec31af8732eeb..eb907287a6a0a8 100644 --- a/eng/pipelines/coreclr/superpmi-replay.yml +++ b/eng/pipelines/coreclr/superpmi-replay.yml @@ -1,20 +1,20 @@ -# This pipeline only runs on GitHub PRs, not on merges. trigger: none -# Only run on changes to the JIT directory. Don't run if the JIT-EE GUID has changed, -# since there won't be any SuperPMI collections with the new GUID until the collection -# pipeline completes after this PR is merged. pr: branches: include: - main paths: include: - - src/coreclr/jit/* - - src/coreclr/gcinfo/* - - src/coreclr/tools/superpmi/* - exclude: - - src/coreclr/inc/jiteeversionguid.h + - src/coreclr/jit/lsra*.* + +schedules: +- cron: "0 7 * * *" + displayName: Daily at 11:00 PM (UTC-8:00) + branches: + include: + - main + always: true variables: - template: /eng/pipelines/common/variables.yml diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml index e47cb4996cc704..d4c755945c0372 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml @@ -40,7 +40,7 @@ jobs: eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(variables['isRollingBuild'], true)) -# Run net48 tests on win-x64 +# Run net481 tests on win-x64 - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml @@ -49,16 +49,16 @@ jobs: - windows_x64 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: - framework: net48 - buildArgs: -s tools+libs+libs.tests -framework net48 -c $(_BuildConfig) -testscope innerloop /p:ArchiveTests=true - nameSuffix: Libraries_NET48 + framework: net481 + buildArgs: -s tools+libs+libs.tests -framework net481 -c $(_BuildConfig) -testscope innerloop /p:ArchiveTests=true + nameSuffix: Libraries_NET481 timeoutInMinutes: 150 postBuildSteps: - template: /eng/pipelines/libraries/helix.yml parameters: creator: dotnet-bot - testRunNamePrefixSuffix: NET48_$(_BuildConfig) - extraHelixArguments: /p:BuildTargetFramework=net48 + testRunNamePrefixSuffix: NET481_$(_BuildConfig) + extraHelixArguments: /p:BuildTargetFramework=net481 isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} condition: >- or( diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index f5b94c910c9dec..817c66b36286c5 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -34,7 +34,7 @@ jobs: # Linux arm64 - ${{ if eq(parameters.platform, 'linux_arm64') }}: - - (Ubuntu.2410.Arm64.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-24.10-helix-arm64v8 + - (Ubuntu.2504.Arm64.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-25.04-helix-arm64v8 - ${{ if or(ne(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Debian.13.Arm64.Open)Ubuntu.2204.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-13-helix-arm64v8 @@ -56,7 +56,7 @@ jobs: - SLES.15.Amd64.Open - (Centos.10.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream-10-helix-amd64 - (Fedora.41.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-41-helix - - (Ubuntu.2404.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-24.04-helix-amd64 + - (Ubuntu.2504.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-25.04-helix-amd64 - (Debian.13.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-13-helix-amd64 - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: @@ -115,7 +115,7 @@ jobs: # windows x64 - ${{ if eq(parameters.platform, 'windows_x64') }}: # netcoreapp - - ${{ if notIn(parameters.jobParameters.framework, 'net48') }}: + - ${{ if notIn(parameters.jobParameters.framework, 'net481') }}: # libraries on mono outerloop - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - Windows.Amd64.Server2022.Open @@ -137,14 +137,14 @@ jobs: - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64 # .NETFramework - - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: + - ${{ if eq(parameters.jobParameters.framework, 'net481') }}: - Windows.11.Amd64.Client.Open # windows x86 - ${{ if eq(parameters.platform, 'windows_x86') }}: # netcoreapp - - ${{ if notIn(parameters.jobParameters.framework, 'net48') }}: + - ${{ if notIn(parameters.jobParameters.framework, 'net481') }}: # mono outerloop - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - Windows.11.Amd64.Client.Open @@ -155,7 +155,7 @@ jobs: - Windows.11.Amd64.Client.Open # .NETFramework - - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: + - ${{ if eq(parameters.jobParameters.framework, 'net481') }}: - Windows.10.Amd64.Client.Open # windows arm64 diff --git a/eng/pipelines/libraries/outerloop.yml b/eng/pipelines/libraries/outerloop.yml index 597f298c37a3e0..bbb1adc12cde55 100644 --- a/eng/pipelines/libraries/outerloop.yml +++ b/eng/pipelines/libraries/outerloop.yml @@ -92,10 +92,10 @@ extends: - ${{ if eq(variables['isRollingBuild'], true) }}: - windows_x64 jobParameters: - framework: net48 + framework: net481 testScope: outerloop - nameSuffix: NET48 - buildArgs: -s libs+libs.tests -c $(_BuildConfig) -testscope outerloop /p:ArchiveTests=true -f net48 + nameSuffix: NET481 + buildArgs: -s libs+libs.tests -c $(_BuildConfig) -testscope outerloop /p:ArchiveTests=true -f net481 timeoutInMinutes: 180 includeAllPlatforms: ${{ variables['isRollingBuild'] }} # extra steps, run tests @@ -104,4 +104,4 @@ extends: parameters: testScope: outerloop creator: dotnet-bot - extraHelixArguments: /p:BuildTargetFramework=net48 + extraHelixArguments: /p:BuildTargetFramework=net481 diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml index 257334fce3e99c..e083bbac2a6e43 100644 --- a/eng/pipelines/libraries/stress/http.yml +++ b/eng/pipelines/libraries/stress/http.yml @@ -8,11 +8,11 @@ pr: schedules: - cron: "0 13 * * *" # 1PM UTC => 5 AM PST displayName: HttpStress nightly run + always: true branches: include: - main - - release/8.0 - - release/9.0 + - release/*-staging variables: - template: ../variables.yml diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml index 360e67a86c98d4..eb2088242dcd2d 100644 --- a/eng/pipelines/libraries/stress/ssl.yml +++ b/eng/pipelines/libraries/stress/ssl.yml @@ -8,11 +8,11 @@ pr: schedules: - cron: "0 13 * * *" # 1PM UTC => 5 AM PST displayName: SslStress nightly run + always: true branches: include: - main - - release/8.0 - - release/9.0 + - release/*-staging variables: - template: ../variables.yml diff --git a/eng/pipelines/performance/perf-build.yml b/eng/pipelines/performance/perf-build.yml new file mode 100644 index 00000000000000..de9a7674c15937 --- /dev/null +++ b/eng/pipelines/performance/perf-build.yml @@ -0,0 +1,236 @@ +parameters: +- name: runPrivateJobs + displayName: Upload artifacts to blob storage + type: boolean + default: false +- name: mauiFramework + type: string + default: 'net9.0' +- name: coreclr_arm64_linux + displayName: Build Coreclr Arm64 Linux + type: boolean + default: true +- name: coreclr_arm64_windows + displayName: Build Coreclr Arm64 Windows + type: boolean + default: true +- name: coreclr_muslx64_linux + displayName: Build Coreclr Musl x64 Linux + type: boolean + default: true +- name: coreclr_x64_linux + displayName: Build Coreclr x64 Linux + type: boolean + default: true +- name: coreclr_x64_windows + displayName: Build Coreclr x64 Windows + type: boolean + default: true +- name: coreclr_x86_windows + displayName: Build Coreclr x86 Windows + type: boolean + default: true +- name: coreclr_arm64_android + displayName: Build Coreclr Arm64 Android + type: boolean + default: true +- name: wasm + displayName: Build WebAssembly (wasm) + type: boolean + default: true +- name: monoAot_arm64_linux + displayName: Build Mono AOT Arm64 Linux + type: boolean + default: true +- name: monoAot_x64_linux + displayName: Build Mono AOT x64 Linux + type: boolean + default: true +- name: mono_x64_linux + displayName: Build Mono x64 Linux + type: boolean + default: true +- name: mono_arm64_linux + displayName: Build Mono Arm64 Linux + type: boolean + default: true +- name: mono_arm64_android + displayName: Build Mono Arm64 Android + type: boolean + default: true +- name: mono_arm64_ios + displayName: Build Mono Arm64 iOS + type: boolean + default: true +- name: monoBDN_arm64_android + displayName: Build Mono Arm64 Android BDN (Not working) + type: boolean + default: false # currently not working +- name: nativeAot_arm64_ios + displayName: Build native AOT Arm64 iOS + type: boolean + default: true + +trigger: + batch: false # we want to build every single commit + branches: + include: + - main + - release/9.0 + - release/8.0 + paths: + include: + - '*' + exclude: + - '**.md' + - .devcontainer/* + - .github/* + - docs/* + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + +resources: + repositories: + - repository: performance + type: git + name: internal/dotnet-performance + +variables: + - template: /eng/pipelines/common/variables.yml + +extends: + template: /eng/pipelines/common/templates/pipeline-with-resources.yml + parameters: + stages: + - ${{ if and(ne(variables['System.TeamProject'], 'public'), or(eq(variables['Build.Reason'], 'IndividualCI'), parameters.runPrivateJobs)) }}: + - stage: RegisterBuild + displayName: 'Register Build' + jobs: + - template: /eng/pipelines/register-build-jobs.yml@performance + parameters: + runtimeRepoAlias: self + performanceRepoAlias: performance + buildType: + - ${{ if eq(parameters.coreclr_arm64_linux, true) }}: + - coreclr_arm64_linux + - ${{ if eq(parameters.coreclr_arm64_windows, true) }}: + - coreclr_arm64_windows + - ${{ if eq(parameters.coreclr_muslx64_linux, true) }}: + - coreclr_muslx64_linux + - ${{ if eq(parameters.coreclr_x64_linux, true) }}: + - coreclr_x64_linux + - ${{ if eq(parameters.coreclr_x64_windows, true) }}: + - coreclr_x64_windows + - ${{ if eq(parameters.coreclr_x86_windows, true) }}: + - coreclr_x86_windows + - ${{ if eq(parameters.coreclr_arm64_android, true) }}: + - coreclr_arm64_android + - ${{ if eq(parameters.wasm, true) }}: + - wasm + - ${{ if eq(parameters.monoAot_arm64_linux, true) }}: + - monoAot_arm64_linux + - ${{ if eq(parameters.monoAot_x64_linux, true) }}: + - monoAot_x64_linux + - ${{ if eq(parameters.mono_x64_linux, true) }}: + - mono_x64_linux + - ${{ if eq(parameters.mono_arm64_linux, true) }}: + - mono_arm64_linux + - ${{ if eq(parameters.mono_arm64_android, true) }}: + - mono_arm64_android + - ${{ if eq(parameters.mono_arm64_ios, true) }}: + - mono_arm64_ios + - ${{ if eq(parameters.monoBDN_arm64_android, true) }}: + - monoBDN_arm64_android + - ${{ if eq(parameters.nativeAot_arm64_ios, true) }}: + - nativeAot_arm64_ios + + - stage: Build + displayName: 'Build' + dependsOn: [] # so it runs in parallel with the RegisterBuild stage + jobs: + - template: /eng/pipelines/runtime-perf-build-jobs.yml@performance + parameters: + runtimeRepoAlias: self + performanceRepoAlias: performance + buildType: + - ${{ if eq(parameters.coreclr_arm64_linux, true) }}: + - coreclr_arm64_linux + - ${{ if eq(parameters.coreclr_arm64_windows, true) }}: + - coreclr_arm64_windows + - ${{ if eq(parameters.coreclr_muslx64_linux, true) }}: + - coreclr_muslx64_linux + - ${{ if eq(parameters.coreclr_x64_linux, true) }}: + - coreclr_x64_linux + - ${{ if eq(parameters.coreclr_x64_windows, true) }}: + - coreclr_x64_windows + - ${{ if eq(parameters.coreclr_x86_windows, true) }}: + - coreclr_x86_windows + - ${{ if eq(parameters.coreclr_arm64_android, true) }}: + - coreclr_arm64_android + - ${{ if eq(parameters.wasm, true) }}: + - wasm + - ${{ if eq(parameters.monoAot_arm64_linux, true) }}: + - monoAot_arm64_linux + - ${{ if eq(parameters.monoAot_x64_linux, true) }}: + - monoAot_x64_linux + - ${{ if eq(parameters.mono_x64_linux, true) }}: + - mono_x64_linux + - ${{ if eq(parameters.mono_arm64_linux, true) }}: + - mono_arm64_linux + - ${{ if eq(parameters.mono_arm64_android, true) }}: + - mono_arm64_android + - ${{ if eq(parameters.mono_arm64_ios, true) }}: + - mono_arm64_ios + - ${{ if eq(parameters.monoBDN_arm64_android, true) }}: + - monoBDN_arm64_android + - ${{ if eq(parameters.nativeAot_arm64_ios, true) }}: + - nativeAot_arm64_ios + ${{ if parameters.mauiFramework }}: + mauiFramework: ${{ parameters.mauiFramework }} + + - ${{ if and(ne(variables['System.TeamProject'], 'public'), or(eq(variables['Build.Reason'], 'IndividualCI'), parameters.runPrivateJobs)) }}: + - stage: UploadArtifacts + displayName: 'Upload Artifacts' + condition: always() + dependsOn: + - Build + - RegisterBuild + jobs: + - template: /eng/pipelines/upload-build-artifacts-jobs.yml@performance + parameters: + runtimeRepoAlias: self + performanceRepoAlias: performance + buildType: + - ${{ if eq(parameters.coreclr_arm64_linux, true) }}: + - coreclr_arm64_linux + - ${{ if eq(parameters.coreclr_arm64_windows, true) }}: + - coreclr_arm64_windows + - ${{ if eq(parameters.coreclr_muslx64_linux, true) }}: + - coreclr_muslx64_linux + - ${{ if eq(parameters.coreclr_x64_linux, true) }}: + - coreclr_x64_linux + - ${{ if eq(parameters.coreclr_x64_windows, true) }}: + - coreclr_x64_windows + - ${{ if eq(parameters.coreclr_x86_windows, true) }}: + - coreclr_x86_windows + - ${{ if eq(parameters.coreclr_arm64_android, true) }}: + - coreclr_arm64_android + - ${{ if eq(parameters.wasm, true) }}: + - wasm + - ${{ if eq(parameters.monoAot_arm64_linux, true) }}: + - monoAot_arm64_linux + - ${{ if eq(parameters.monoAot_x64_linux, true) }}: + - monoAot_x64_linux + - ${{ if eq(parameters.mono_x64_linux, true) }}: + - mono_x64_linux + - ${{ if eq(parameters.mono_arm64_linux, true) }}: + - mono_arm64_linux + - ${{ if eq(parameters.mono_arm64_android, true) }}: + - mono_arm64_android + - ${{ if eq(parameters.mono_arm64_ios, true) }}: + - mono_arm64_ios + - ${{ if eq(parameters.monoBDN_arm64_android, true) }}: + - monoBDN_arm64_android + - ${{ if eq(parameters.nativeAot_arm64_ios, true) }}: + - nativeAot_arm64_ios diff --git a/eng/pipelines/performance/perf-slow.yml b/eng/pipelines/performance/perf-slow.yml index d30ecea46d79a5..84ca1836ff2321 100644 --- a/eng/pipelines/performance/perf-slow.yml +++ b/eng/pipelines/performance/perf-slow.yml @@ -15,10 +15,10 @@ trigger: include: - main - release/9.0 + - release/8.0 paths: include: - '*' - - src/libraries/System.Private.CoreLib/* exclude: - '**.md' - .devcontainer/* @@ -62,4 +62,4 @@ extends: performanceRepoAlias: performance jobParameters: ${{ if parameters.onlySanityCheck }}: - onlySanityCheck: true \ No newline at end of file + onlySanityCheck: true diff --git a/eng/pipelines/performance/perf.yml b/eng/pipelines/performance/perf.yml index e717fbe4915927..01b80b580db2bd 100644 --- a/eng/pipelines/performance/perf.yml +++ b/eng/pipelines/performance/perf.yml @@ -13,7 +13,6 @@ trigger: paths: include: - '*' - - src/libraries/System.Private.CoreLib/* exclude: - '**.md' - .devcontainer/* diff --git a/eng/pipelines/performance/templates/perf-bdn-build-jobs.yml b/eng/pipelines/performance/templates/perf-bdn-build-jobs.yml index 3355ceeedb9d2b..c6ffc983f8c175 100644 --- a/eng/pipelines/performance/templates/perf-bdn-build-jobs.yml +++ b/eng/pipelines/performance/templates/perf-bdn-build-jobs.yml @@ -18,7 +18,7 @@ jobs: - ios_arm64 jobParameters: dependsOn: - - Build_android_arm64_release_Mono_Packs + - build_android_arm64_release_Mono_Packs buildArgs: -s mono -c $(_BuildConfig) nameSuffix: PerfBDNApp isOfficialBuild: false diff --git a/eng/pipelines/performance/templates/perf-build-jobs.yml b/eng/pipelines/performance/templates/perf-build-jobs.yml index 4a77a9796eaa75..4defede2528db2 100644 --- a/eng/pipelines/performance/templates/perf-build-jobs.yml +++ b/eng/pipelines/performance/templates/perf-build-jobs.yml @@ -9,7 +9,7 @@ jobs: windows_x64: true windows_x86: true linux_musl_x64: true - coreclrAndroid: true + android_arm64: true # build mono for AOT - template: /eng/pipelines/performance/templates/perf-mono-build-jobs.yml diff --git a/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml b/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml index 96792aab986a07..ddf103aaf4c0d9 100644 --- a/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml +++ b/eng/pipelines/performance/templates/perf-coreclr-build-jobs.yml @@ -1,11 +1,11 @@ parameters: linux_x64: false linux_musl_x64: false + linux_arm64: false windows_x64: false windows_x86: false - linux_arm64: false windows_arm64: false - coreclrAndroid: false + android_arm64: false jobs: - ${{ if or(eq(parameters.linux_x64, true), eq(parameters.windows_x64, true), eq(parameters.windows_x86, true), eq(parameters.linux_musl_x64, true), eq(parameters.linux_arm64, true), eq(parameters.windows_arm64, true)) }}: @@ -42,7 +42,7 @@ jobs: artifactName: BuildArtifacts_$(osGroup)$(osSubgroup)_$(archType)_$(_BuildConfig)_coreclr displayName: Build Assets - - ${{ if eq(parameters.coreclrAndroid, true) }}: + - ${{ if eq(parameters.android_arm64, true) }}: # build CoreCLR Android scenarios - template: /eng/pipelines/common/platform-matrix.yml parameters: diff --git a/eng/pipelines/performance/templates/perf-ios-scenarios-build-jobs.yml b/eng/pipelines/performance/templates/perf-ios-scenarios-build-jobs.yml index 10b2d79a8d03bc..85cff56fdc4c62 100644 --- a/eng/pipelines/performance/templates/perf-ios-scenarios-build-jobs.yml +++ b/eng/pipelines/performance/templates/perf-ios-scenarios-build-jobs.yml @@ -1,7 +1,7 @@ parameters: hybridGlobalization: true - mono: true - nativeAot: true + mono: false + nativeAot: false jobs: - ${{ if eq(parameters.mono, true) }}: diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index fe9c980fbb9354..3dca7fedc2467b 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -125,7 +125,7 @@ extends: - browser_wasm jobParameters: nameSuffix: AllSubsets_CoreCLR - buildArgs: -s mono.emsdk+clr.paltests -rc Release -c Release -lc $(_BuildConfig) + buildArgs: -s mono.emsdk+clr.runtime -rc Release -c Release -lc $(_BuildConfig) timeoutInMinutes: 120 condition: >- or( @@ -1234,16 +1234,16 @@ extends: - windows_x86 helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml jobParameters: - framework: net48 - buildArgs: -s tools+libs+libs.tests -framework net48 -c $(_BuildConfig) -testscope innerloop /p:ArchiveTests=true - nameSuffix: Libraries_NET48 + framework: net481 + buildArgs: -s tools+libs+libs.tests -framework net481 -c $(_BuildConfig) -testscope innerloop /p:ArchiveTests=true + nameSuffix: Libraries_NET481 timeoutInMinutes: 150 postBuildSteps: - template: /eng/pipelines/libraries/helix.yml parameters: creator: dotnet-bot - testRunNamePrefixSuffix: NET48_$(_BuildConfig) - extraHelixArguments: /p:BuildTargetFramework=net48 + testRunNamePrefixSuffix: NET481_$(_BuildConfig) + extraHelixArguments: /p:BuildTargetFramework=net481 condition: >- or( eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), diff --git a/eng/testing/BrowserVersions.props b/eng/testing/BrowserVersions.props index 3f9754af2065f0..1dda520b8e1b1e 100644 --- a/eng/testing/BrowserVersions.props +++ b/eng/testing/BrowserVersions.props @@ -1,10 +1,10 @@ - 134.0.6998.35 + 134.0.6998.88 1415337 https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1415339 13.4.115 - 134.0.6998.35 + 134.0.6998.89 1415337 https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1415350 13.4.115 diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 65ab8ed35de7f8..0fc4926a782a41 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -87,7 +87,9 @@ - + + + public sealed partial class Mutex : WaitHandle { - private void CreateMutexCore(bool initiallyOwned, string? name, out bool createdNew) + private unsafe void CreateMutexCore(bool initiallyOwned) { - SafeWaitHandle mutexHandle = CreateMutexCore(initiallyOwned, name, out int errorCode, out string? errorDetails); + SafeWaitHandle handle = + CreateMutex( + initiallyOwned, + name: null, + currentUserOnly: false, + systemCallErrors: null, + systemCallErrorsBufferSize: 0); + if (handle.IsInvalid) + { + int errorCode = Marshal.GetLastPInvokeError(); + handle.SetHandleAsInvalid(); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + + SafeWaitHandle = handle; + } + + private void CreateMutexCore( + bool initiallyOwned, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) + { + bool currentUserOnly = false; + if (!string.IsNullOrEmpty(name) && options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + currentUserOnly = options.CurrentUserOnly; + } + + SafeWaitHandle mutexHandle = + CreateMutexCore(initiallyOwned, name, currentUserOnly, out int errorCode, out string? errorDetails); if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); @@ -33,16 +64,26 @@ private void CreateMutexCore(bool initiallyOwned, string? name, out bool created SafeWaitHandle = mutexHandle; } - private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out Mutex? result) { ArgumentException.ThrowIfNullOrEmpty(name); + bool currentUserOnly = false; + if (options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + currentUserOnly = options.CurrentUserOnly; + } + result = null; // To allow users to view & edit the ACL's, call OpenMutex // with parameters to allow us to view & edit the ACL. This will // fail if we don't have permission to view or edit the ACL's. // If that happens, ask for less permissions. - SafeWaitHandle myHandle = OpenMutexCore(name, out int errorCode, out string? errorDetails); + SafeWaitHandle myHandle = OpenMutexCore(name, currentUserOnly, out int errorCode, out string? errorDetails); if (myHandle.IsInvalid) { @@ -86,11 +127,13 @@ public void ReleaseMutex() private static unsafe SafeWaitHandle CreateMutexCore( bool initialOwner, string? name, + bool currentUserOnly, out int errorCode, out string? errorDetails) { byte* systemCallErrors = stackalloc byte[SystemCallErrorsBufferSize]; - SafeWaitHandle mutexHandle = CreateMutex(initialOwner, name, systemCallErrors, SystemCallErrorsBufferSize); + SafeWaitHandle mutexHandle = + CreateMutex(initialOwner, name, currentUserOnly, systemCallErrors, SystemCallErrorsBufferSize); // Get the error code even if the handle is valid, as it could be ERROR_ALREADY_EXISTS, indicating that the mutex // already exists and was opened @@ -100,10 +143,10 @@ private static unsafe SafeWaitHandle CreateMutexCore( return mutexHandle; } - private static unsafe SafeWaitHandle OpenMutexCore(string name, out int errorCode, out string? errorDetails) + private static unsafe SafeWaitHandle OpenMutexCore(string name, bool currentUserOnly, out int errorCode, out string? errorDetails) { byte* systemCallErrors = stackalloc byte[SystemCallErrorsBufferSize]; - SafeWaitHandle mutexHandle = OpenMutex(name, systemCallErrors, SystemCallErrorsBufferSize); + SafeWaitHandle mutexHandle = OpenMutex(name, currentUserOnly, systemCallErrors, SystemCallErrorsBufferSize); errorCode = mutexHandle.IsInvalid ? Marshal.GetLastPInvokeError() : Interop.Errors.ERROR_SUCCESS; errorDetails = mutexHandle.IsInvalid ? GetErrorDetails(systemCallErrors) : null; return mutexHandle; @@ -127,9 +170,9 @@ private static unsafe SafeWaitHandle OpenMutexCore(string name, out int errorCod } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PAL_CreateMutexW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] - private static unsafe partial SafeWaitHandle CreateMutex([MarshalAs(UnmanagedType.Bool)] bool initialOwner, string? name, byte* systemCallErrors, uint systemCallErrorsBufferSize); + private static unsafe partial SafeWaitHandle CreateMutex([MarshalAs(UnmanagedType.Bool)] bool initialOwner, string? name, [MarshalAs(UnmanagedType.Bool)] bool currentUserOnly, byte* systemCallErrors, uint systemCallErrorsBufferSize); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PAL_OpenMutexW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] - private static unsafe partial SafeWaitHandle OpenMutex(string name, byte* systemCallErrors, uint systemCallErrorsBufferSize); + private static unsafe partial SafeWaitHandle OpenMutex(string name, [MarshalAs(UnmanagedType.Bool)] bool currentUserOnly, byte* systemCallErrors, uint systemCallErrorsBufferSize); } } diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index d5b2d29d2e5d5a..550ce70a14ef7a 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -58,7 +58,7 @@ if(CLR_CMAKE_HOST_WIN32) add_compile_definitions(NOMINMAX) endif(CLR_CMAKE_HOST_WIN32) -if (NOT (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX)) +if (NOT ((CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) OR CLR_CMAKE_TARGET_ARCH_WASM)) add_compile_definitions(FEATURE_METADATA_UPDATER) endif() if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32)) @@ -119,9 +119,9 @@ if(CLR_CMAKE_TARGET_LINUX) add_definitions(-DFEATURE_EVENTSOURCE_XPLAT) endif(CLR_CMAKE_TARGET_LINUX) # NetBSD doesn't implement this feature -if(NOT CLR_CMAKE_TARGET_NETBSD) +if(NOT CLR_CMAKE_TARGET_NETBSD AND NOT CLR_CMAKE_TARGET_ARCH_WASM) add_definitions(-DFEATURE_HIJACK) -endif(NOT CLR_CMAKE_TARGET_NETBSD) +endif(NOT CLR_CMAKE_TARGET_NETBSD AND NOT CLR_CMAKE_TARGET_ARCH_WASM) if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) add_definitions(-DFEATURE_INTEROP_DEBUGGING) endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) @@ -188,9 +188,9 @@ if (CLR_CMAKE_TARGET_ARCH_AMD64) add_definitions(-DUNIX_AMD64_ABI_ITF) endif (CLR_CMAKE_TARGET_ARCH_AMD64) add_definitions(-DFEATURE_USE_ASM_GC_WRITE_BARRIERS) -if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64) +if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64 OR CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) -endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64) +endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64 OR CLR_CMAKE_TARGET_ARCH_ARM) if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64) add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES) endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64) @@ -213,6 +213,9 @@ if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ add_definitions(-DFEATURE_SPECIAL_USER_MODE_APC) endif() +if (FEATURE_STUBPRECODE_DYNAMIC_HELPERS) + add_definitions(-DFEATURE_STUBPRECODE_DYNAMIC_HELPERS) +endif() # Use this function to enable building with a specific target OS and architecture set of defines # This is known to work for the set of defines used by the JIT and gcinfo, it is not likely correct for diff --git a/src/coreclr/clrfeatures.cmake b/src/coreclr/clrfeatures.cmake index d6a8965843e585..a51d5e9eca1791 100644 --- a/src/coreclr/clrfeatures.cmake +++ b/src/coreclr/clrfeatures.cmake @@ -52,7 +52,7 @@ if (CLR_CMAKE_TARGET_WIN32) endif(CLR_CMAKE_TARGET_WIN32) -if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) +if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS OR CLR_CMAKE_TARGET_ARCH_WASM) set(FEATURE_CORECLR_CACHED_INTERFACE_DISPATCH 1) set(FEATURE_CORECLR_VIRTUAL_STUB_DISPATCH 0) else() @@ -70,3 +70,7 @@ if (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_HOST_ARCH_AMD64) # Allow 16 byte compare-exchange (cmpxchg16b) add_compile_options($<${FEATURE_CORECLR_CACHED_INTERFACE_DISPATCH}:-mcx16>) endif() + +if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) + set(FEATURE_STUBPRECODE_DYNAMIC_HELPERS 1) +endif() diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index d43689d6dba9b4..06b00e4ffa75f2 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -3674,6 +3674,9 @@ static const char *LoaderAllocatorLoaderHeapNames[] = "ExecutableHeap", "FixupPrecodeHeap", "NewStubPrecodeHeap", +#if defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) + "DynamicHelpersStubHeap", +#endif // defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) "IndcellHeap", #ifdef FEATURE_VIRTUAL_STUB_DISPATCH "CacheEntryHeap", @@ -3711,7 +3714,9 @@ HRESULT ClrDataAccess::GetLoaderAllocatorHeaps(CLRDATA_ADDRESS loaderAllocatorAd pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetExecutableHeap()); pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetFixupPrecodeHeap()); pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetNewStubPrecodeHeap()); - +#if defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) + pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetDynamicHelpersStubHeap()); +#endif // defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) VirtualCallStubManager *pVcsMgr = pLoaderAllocator->GetVirtualCallStubManager(); if (pVcsMgr == nullptr) { diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index 6c39939f00307e..9ff25d86edf185 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -1938,6 +1938,9 @@ C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); C_ASSERT(DBG_TARGET_REGNUM_SP == ICorDebugInfo::REGNUM_SP); C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); #endif +#elif defined(TARGET_WASM) +#define DBG_TARGET_REGNUM_SP 0 +#define DBG_TARGET_REGNUM_AMBIENT_SP 0 #else #error Target registers are not defined for this platform #endif diff --git a/src/coreclr/debug/inc/dbgtargetcontext.h b/src/coreclr/debug/inc/dbgtargetcontext.h index dab7ca29c7db33..ea374cf8b6def6 100644 --- a/src/coreclr/debug/inc/dbgtargetcontext.h +++ b/src/coreclr/debug/inc/dbgtargetcontext.h @@ -58,6 +58,8 @@ #define DTCONTEXT_IS_LOONGARCH64 #elif defined (TARGET_RISCV64) #define DTCONTEXT_IS_RISCV64 +#elif defined (TARGET_WASM) +#define DTCONTEXT_IS_WASM #endif #define CONTEXT_AREA_MASK 0xffff @@ -614,6 +616,10 @@ typedef struct DECLSPEC_ALIGN(16) { static_assert(sizeof(DT_CONTEXT) == sizeof(T_CONTEXT), "DT_CONTEXT size must equal the T_CONTEXT size"); +#elif defined(DTCONTEXT_IS_WASM) +// no context for wasm +typedef struct { +} DT_CONTEXT; #else #error Unsupported platform #endif diff --git a/src/coreclr/debug/inc/wasm/primitives.h b/src/coreclr/debug/inc/wasm/primitives.h new file mode 100644 index 00000000000000..5c428fe76ceb62 --- /dev/null +++ b/src/coreclr/debug/inc/wasm/primitives.h @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +//***************************************************************************** +// File: primitives.h +// + +// +// Platform-specific debugger primitives +// +//***************************************************************************** + +#ifndef PRIMITIVES_H_ +#define PRIMITIVES_H_ + +inline CORDB_ADDRESS GetPatchEndAddr(CORDB_ADDRESS patchAddr) +{ + _ASSERTE("The function is not implemented on wasm"); + return patchAddr; +} + +typedef const BYTE CORDB_ADDRESS_TYPE; +typedef DPTR(CORDB_ADDRESS_TYPE) PTR_CORDB_ADDRESS_TYPE; + +//This is an abstraction to keep x86/ia64 patch data separate +#define PRD_TYPE USHORT + +#define MAX_INSTRUCTION_LENGTH 2 // update once we have codegen + +#define CORDbg_BREAK_INSTRUCTION_SIZE 1 +#define CORDbg_BREAK_INSTRUCTION 0 // unreachable intruction + +inline bool PRDIsEmpty(PRD_TYPE p1) +{ + LIMITED_METHOD_CONTRACT; + + return p1 == 0; +} + +#endif diff --git a/src/coreclr/debug/runtimeinfo/contracts.jsonc b/src/coreclr/debug/runtimeinfo/contracts.jsonc index 8d0ecf9f679ff2..dc20297b01bed1 100644 --- a/src/coreclr/debug/runtimeinfo/contracts.jsonc +++ b/src/coreclr/debug/runtimeinfo/contracts.jsonc @@ -17,7 +17,7 @@ "Loader": 1, "Object": 1, "PlatformMetadata": 1, - "PrecodeStubs": 1, + "PrecodeStubs": 2, "ReJIT": 1, "RuntimeTypeSystem": 1, "StackWalk": 1, diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.cpp b/src/coreclr/debug/runtimeinfo/datadescriptor.cpp index 72a1ee18304578..c4d0aa3d42b645 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.cpp +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.cpp @@ -13,6 +13,8 @@ #include "methodtable.h" #include "threads.h" +#include "../debug/ee/debugger.h" + #ifdef HAVE_GCCOVER #include "gccover.h" #endif // HAVE_GCCOVER diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h index dc6e45baf9bf8c..b23b5ea39eb00d 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.h +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -492,10 +492,17 @@ CDAC_TYPE_END(PlatformMetadata) CDAC_TYPE_BEGIN(StubPrecodeData) CDAC_TYPE_INDETERMINATE(StubPrecodeData) -CDAC_TYPE_FIELD(StubPrecodeData, /*pointer*/, MethodDesc, offsetof(StubPrecodeData, SecretParam)) +CDAC_TYPE_FIELD(StubPrecodeData, /*pointer*/, SecretParam, offsetof(StubPrecodeData, SecretParam)) CDAC_TYPE_FIELD(StubPrecodeData, /*uint8*/, Type, offsetof(StubPrecodeData, Type)) CDAC_TYPE_END(StubPrecodeData) +#ifdef HAS_THISPTR_RETBUF_PRECODE +CDAC_TYPE_BEGIN(ThisPtrRetBufPrecodeData) +CDAC_TYPE_INDETERMINATE(ThisPtrRetBufPrecodeData) +CDAC_TYPE_FIELD(ThisPtrRetBufPrecodeData, /*pointer*/, MethodDesc, offsetof(ThisPtrRetBufPrecodeData, MethodDesc)) +CDAC_TYPE_END(ThisPtrRetBufPrecodeData) +#endif + CDAC_TYPE_BEGIN(FixupPrecodeData) CDAC_TYPE_INDETERMINATE(FixupPrecodeData) CDAC_TYPE_FIELD(FixupPrecodeData, /*pointer*/, MethodDesc, offsetof(FixupPrecodeData, MethodDesc)) @@ -645,6 +652,108 @@ CDAC_TYPE_FIELD(SoftwareExceptionFrame, /*pointer*/, ReturnAddress, cdac_data::TransitionBlockPtr) +CDAC_TYPE_END(FramedMethodFrame) + +CDAC_TYPE_BEGIN(TransitionBlock) +CDAC_TYPE_SIZE(sizeof(TransitionBlock)) +CDAC_TYPE_FIELD(TransitionBlock, /*pointer*/, ReturnAddress, offsetof(TransitionBlock, m_ReturnAddress)) +CDAC_TYPE_FIELD(TransitionBlock, /*CalleeSavedRegisters*/, CalleeSavedRegisters, offsetof(TransitionBlock, m_calleeSavedRegisters)) +CDAC_TYPE_END(TransitionBlock) + +#ifdef DEBUGGING_SUPPORTED +CDAC_TYPE_BEGIN(FuncEvalFrame) +CDAC_TYPE_SIZE(sizeof(FuncEvalFrame)) +CDAC_TYPE_FIELD(FuncEvalFrame, /*pointer*/, DebuggerEvalPtr, cdac_data::DebuggerEvalPtr) +CDAC_TYPE_END(FuncEvalFrame) + +CDAC_TYPE_BEGIN(DebuggerEval) +CDAC_TYPE_SIZE(sizeof(DebuggerEval)) +CDAC_TYPE_FIELD(DebuggerEval, /*T_CONTEXT*/, TargetContext, offsetof(DebuggerEval, m_context)) +CDAC_TYPE_FIELD(DebuggerEval, /*bool*/, EvalDuringException, offsetof(DebuggerEval, m_evalDuringException)) +CDAC_TYPE_END(DebuggerEval) +#endif // DEBUGGING_SUPPORTED + +#ifdef FEATURE_HIJACK +CDAC_TYPE_BEGIN(ResumableFrame) +CDAC_TYPE_SIZE(sizeof(ResumableFrame)) +CDAC_TYPE_FIELD(ResumableFrame, /*pointer*/, TargetContextPtr, cdac_data::TargetContextPtr) +CDAC_TYPE_END(ResumableFrame) + +CDAC_TYPE_BEGIN(HijackFrame) +CDAC_TYPE_SIZE(sizeof(HijackFrame)) +CDAC_TYPE_FIELD(HijackFrame, /*pointer*/, ReturnAddress, cdac_data::ReturnAddress) +CDAC_TYPE_FIELD(HijackFrame, /*pointer*/, HijackArgsPtr, cdac_data::HijackArgsPtr) +CDAC_TYPE_END(HijackFrame) + +// HijackArgs struct is different on each platform +CDAC_TYPE_BEGIN(HijackArgs) +CDAC_TYPE_SIZE(sizeof(HijackArgs)) +#if defined(TARGET_AMD64) + +CDAC_TYPE_FIELD(HijackArgs, /*CalleeSavedRegisters*/, CalleeSavedRegisters, offsetof(HijackArgs, Regs)) +#ifdef TARGET_WINDOWS +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Rsp, offsetof(HijackArgs, Rsp)) +#endif // TARGET_WINDOWS + +#elif defined(TARGET_ARM64) + +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X0, offsetof(HijackArgs, X0)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X1, offsetof(HijackArgs, X1)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X19, offsetof(HijackArgs, X19)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X20, offsetof(HijackArgs, X20)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X21, offsetof(HijackArgs, X21)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X22, offsetof(HijackArgs, X22)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X23, offsetof(HijackArgs, X23)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X24, offsetof(HijackArgs, X24)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X25, offsetof(HijackArgs, X25)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X26, offsetof(HijackArgs, X26)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X27, offsetof(HijackArgs, X27)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, X28, offsetof(HijackArgs, X28)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Fp, offsetof(HijackArgs, X29)) +CDAC_TYPE_FIELD(HijackArgs, /*pointer*/, Lr, offsetof(HijackArgs, Lr)) + +#endif // Platform switch +CDAC_TYPE_END(HijackArgs) +#endif // FEATURE_HIJACK + +CDAC_TYPE_BEGIN(FaultingExceptionFrame) +CDAC_TYPE_SIZE(sizeof(FaultingExceptionFrame)) +#ifdef FEATURE_EH_FUNCLETS +CDAC_TYPE_FIELD(FaultingExceptionFrame, /*T_CONTEXT*/, TargetContext, cdac_data::TargetContext) +#endif // FEATURE_EH_FUNCLETS +CDAC_TYPE_END(FaultingExceptionFrame) + +// CalleeSavedRegisters struct is different on each platform +CDAC_TYPE_BEGIN(CalleeSavedRegisters) +CDAC_TYPE_SIZE(sizeof(CalleeSavedRegisters)) +#if defined(TARGET_AMD64) + +#define CALLEE_SAVED_REGISTER(regname) \ + CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, regname, offsetof(CalleeSavedRegisters, regname)) +ENUM_CALLEE_SAVED_REGISTERS() +#undef CALLEE_SAVED_REGISTER + +#elif defined(TARGET_ARM64) + +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X19, offsetof(CalleeSavedRegisters, x19)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X20, offsetof(CalleeSavedRegisters, x20)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X21, offsetof(CalleeSavedRegisters, x21)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X22, offsetof(CalleeSavedRegisters, x22)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X23, offsetof(CalleeSavedRegisters, x23)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X24, offsetof(CalleeSavedRegisters, x24)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X25, offsetof(CalleeSavedRegisters, x25)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X26, offsetof(CalleeSavedRegisters, x26)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X27, offsetof(CalleeSavedRegisters, x27)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, X28, offsetof(CalleeSavedRegisters, x28)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, Fp, offsetof(CalleeSavedRegisters, x29)) +CDAC_TYPE_FIELD(CalleeSavedRegisters, /*nuint*/, Lr, offsetof(CalleeSavedRegisters, x30)) + +#endif // Platform switch +CDAC_TYPE_END(CalleeSavedRegisters) + CDAC_TYPES_END() CDAC_GLOBALS_BEGIN() diff --git a/src/coreclr/dlls/CMakeLists.txt b/src/coreclr/dlls/CMakeLists.txt index 9bd79f94d6fd91..0a2ab14d8db82f 100644 --- a/src/coreclr/dlls/CMakeLists.txt +++ b/src/coreclr/dlls/CMakeLists.txt @@ -2,9 +2,13 @@ if(CLR_CMAKE_TARGET_WIN32 AND FEATURE_EVENT_TRACE) add_subdirectory(clretwrc) endif(CLR_CMAKE_TARGET_WIN32 AND FEATURE_EVENT_TRACE) if (NOT (CLR_CMAKE_TARGET_WIN32 AND FEATURE_CROSSBITNESS)) - add_subdirectory(mscordbi) - add_subdirectory(mscordac) + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(mscordbi) + add_subdirectory(mscordac) + endif() add_subdirectory(mscoree) endif() -add_subdirectory(mscorpe) +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(mscorpe) +endif() add_subdirectory(mscorrc) diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index 0857ba2884f78f..206ae4091b7c82 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -61,7 +61,6 @@ nativeStringResourceTable_mscorrc #memcpy_s #sscanf_s -#CopyFileW #CreateFileMappingW #CreateFileA #CreateFileW @@ -101,7 +100,6 @@ nativeStringResourceTable_mscorrc #GetSystemInfo #GetSystemTime #GetSystemTimeAsFileTime -#GetTempFileNameW #GetTempPathA #GetTempPathW #InitializeCriticalSection diff --git a/src/coreclr/gc/env/gcenv.base.h b/src/coreclr/gc/env/gcenv.base.h index 1603448ae2a4f8..94d88e46466940 100644 --- a/src/coreclr/gc/env/gcenv.base.h +++ b/src/coreclr/gc/env/gcenv.base.h @@ -143,7 +143,10 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter); #pragma intrinsic(__dmb) #define MemoryBarrier() { __dmb(_ARM64_BARRIER_SY); } - #elif defined(HOST_AMD64) + #elif defined(HOST_BROWSER) + #define YieldProcessor() + #define MemoryBarrier __sync_synchronize +#elif defined(HOST_AMD64) extern "C" void _mm_pause ( diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 43588c66eb015a..5a199f4b7db69e 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -35,6 +35,9 @@ #define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__) #elif HAVE_SYS_MEMBARRIER_H #include +#ifdef TARGET_BROWSER +#define membarrier(cmd, flags, cpu_id) 0 // browser/wasm is currently single threaded +#endif #endif #include diff --git a/src/coreclr/gcinfo/gcinfoencoder.cpp b/src/coreclr/gcinfo/gcinfoencoder.cpp index b512e92a6e3f28..ffac0f713ab77e 100644 --- a/src/coreclr/gcinfo/gcinfoencoder.cpp +++ b/src/coreclr/gcinfo/gcinfoencoder.cpp @@ -10,6 +10,9 @@ #include #include "gcinfoencoder.h" + +using namespace GcInfoEncoderExt; + #include "targetosarch.h" #ifdef _DEBUG @@ -428,7 +431,7 @@ void GcInfoSize::Log(DWORD level, const char * header) #endif -GcInfoEncoder::GcInfoEncoder( +template TGcInfoEncoder::TGcInfoEncoder( ICorJitInfo* pCorJitInfo, CORINFO_METHOD_INFO* pMethodInfo, IAllocator* pJitAllocator, @@ -498,7 +501,7 @@ GcInfoEncoder::GcInfoEncoder( } #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED -void GcInfoEncoder::DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UINT32 numCallSites) +template void TGcInfoEncoder::DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UINT32 numCallSites) { m_pCallSites = pCallSites; m_pCallSiteSizes = pCallSiteSizes; @@ -507,7 +510,7 @@ void GcInfoEncoder::DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UI for(UINT32 i=0; i 0); - _ASSERTE(DENORMALIZE_CODE_OFFSET(NORMALIZE_CODE_OFFSET(pCallSites[i])) == pCallSites[i]); + _ASSERTE(GcInfoEncoding::DENORMALIZE_CODE_OFFSET(GcInfoEncoding::NORMALIZE_CODE_OFFSET(pCallSites[i])) == pCallSites[i]); if(i > 0) { UINT32 prevEnd = pCallSites[i-1] + pCallSiteSizes[i-1]; @@ -519,7 +522,7 @@ void GcInfoEncoder::DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UI } #endif -GcSlotId GcInfoEncoder::GetRegisterSlotId( UINT32 regNum, GcSlotFlags flags ) +template GcSlotId TGcInfoEncoder::GetRegisterSlotId( UINT32 regNum, GcSlotFlags flags ) { // We could lookup an existing identical slot in the slot table (via some hashtable mechanism). // We just create duplicates for now. @@ -544,7 +547,7 @@ GcSlotId GcInfoEncoder::GetRegisterSlotId( UINT32 regNum, GcSlotFlags flags ) return newSlotId; } -GcSlotId GcInfoEncoder::GetStackSlotId( INT32 spOffset, GcSlotFlags flags, GcStackSlotBase spBase ) +template GcSlotId TGcInfoEncoder::GetStackSlotId( INT32 spOffset, GcSlotFlags flags, GcStackSlotBase spBase ) { // We could lookup an existing identical slot in the slot table (via some hashtable mechanism). // We just create duplicates for now. @@ -580,7 +583,7 @@ GcSlotId GcInfoEncoder::GetStackSlotId( INT32 spOffset, GcSlotFlags flags, GcSta return newSlotId; } -void GcInfoEncoder::GrowSlotTable() +template void TGcInfoEncoder::GrowSlotTable() { m_SlotTableSize *= 2; GcSlotDesc* newSlotTable = (GcSlotDesc*) m_pAllocator->Alloc( m_SlotTableSize * sizeof(GcSlotDesc) ); @@ -593,7 +596,7 @@ void GcInfoEncoder::GrowSlotTable() m_SlotTable = newSlotTable; } -void GcInfoEncoder::WriteSlotStateVector(BitStreamWriter &writer, const BitArray& vector) +template void TGcInfoEncoder::WriteSlotStateVector(BitStreamWriter &writer, const BitArray& vector) { for(UINT32 i = 0; i < m_NumSlots && !m_SlotTable[i].IsUntracked(); i++) { @@ -604,12 +607,12 @@ void GcInfoEncoder::WriteSlotStateVector(BitStreamWriter &writer, const BitArray } } -void GcInfoEncoder::DefineInterruptibleRange( UINT32 startInstructionOffset, UINT32 length ) +template void TGcInfoEncoder::DefineInterruptibleRange( UINT32 startInstructionOffset, UINT32 length ) { UINT32 stopInstructionOffset = startInstructionOffset + length; - UINT32 normStartOffset = NORMALIZE_CODE_OFFSET(startInstructionOffset); - UINT32 normStopOffset = NORMALIZE_CODE_OFFSET(stopInstructionOffset); + UINT32 normStartOffset = GcInfoEncoding::NORMALIZE_CODE_OFFSET(startInstructionOffset); + UINT32 normStopOffset = GcInfoEncoding::NORMALIZE_CODE_OFFSET(stopInstructionOffset); // Ranges must not overlap and must be passed sorted by increasing offset _ASSERTE( @@ -644,7 +647,7 @@ void GcInfoEncoder::DefineInterruptibleRange( UINT32 startInstructionOffset, UIN // // For inputs, pass zero as offset // -void GcInfoEncoder::SetSlotState( +template void TGcInfoEncoder::SetSlotState( UINT32 instructionOffset, GcSlotId slotId, GcSlotState slotState @@ -665,19 +668,19 @@ void GcInfoEncoder::SetSlotState( } -void GcInfoEncoder::SetIsVarArg() +template void TGcInfoEncoder::SetIsVarArg() { m_IsVarArg = true; } -void GcInfoEncoder::SetCodeLength( UINT32 length ) +template void TGcInfoEncoder::SetCodeLength( UINT32 length ) { _ASSERTE( length > 0 ); _ASSERTE( m_CodeLength == 0 || m_CodeLength == length ); m_CodeLength = length; } -void GcInfoEncoder::SetPrologSize( UINT32 prologSize ) +template void TGcInfoEncoder::SetPrologSize( UINT32 prologSize ) { _ASSERTE(prologSize != 0); _ASSERTE(m_GSCookieValidRangeStart == 0 || m_GSCookieValidRangeStart == prologSize); @@ -688,7 +691,7 @@ void GcInfoEncoder::SetPrologSize( UINT32 prologSize ) m_GSCookieValidRangeEnd = prologSize+1; } -void GcInfoEncoder::SetGSCookieStackSlot( INT32 spOffsetGSCookie, UINT32 validRangeStart, UINT32 validRangeEnd ) +template void TGcInfoEncoder::SetGSCookieStackSlot( INT32 spOffsetGSCookie, UINT32 validRangeStart, UINT32 validRangeEnd ) { _ASSERTE( spOffsetGSCookie != NO_GS_COOKIE ); _ASSERTE( m_GSCookieStackSlot == NO_GS_COOKIE || m_GSCookieStackSlot == spOffsetGSCookie ); @@ -699,7 +702,7 @@ void GcInfoEncoder::SetGSCookieStackSlot( INT32 spOffsetGSCookie, UINT32 validRa m_GSCookieValidRangeEnd = validRangeEnd; } -void GcInfoEncoder::SetPSPSymStackSlot( INT32 spOffsetPSPSym ) +template void TGcInfoEncoder::SetPSPSymStackSlot( INT32 spOffsetPSPSym ) { _ASSERTE( spOffsetPSPSym != NO_PSP_SYM ); _ASSERTE( m_PSPSymStackSlot == NO_PSP_SYM || m_PSPSymStackSlot == spOffsetPSPSym ); @@ -707,7 +710,7 @@ void GcInfoEncoder::SetPSPSymStackSlot( INT32 spOffsetPSPSym ) m_PSPSymStackSlot = spOffsetPSPSym; } -void GcInfoEncoder::SetGenericsInstContextStackSlot( INT32 spOffsetGenericsContext, GENERIC_CONTEXTPARAM_TYPE type) +template void TGcInfoEncoder::SetGenericsInstContextStackSlot( INT32 spOffsetGenericsContext, GENERIC_CONTEXTPARAM_TYPE type) { _ASSERTE( spOffsetGenericsContext != NO_GENERICS_INST_CONTEXT); _ASSERTE( m_GenericsInstContextStackSlot == NO_GENERICS_INST_CONTEXT || m_GenericsInstContextStackSlot == spOffsetGenericsContext ); @@ -716,10 +719,10 @@ void GcInfoEncoder::SetGenericsInstContextStackSlot( INT32 spOffsetGenericsConte m_contextParamType = type; } -void GcInfoEncoder::SetStackBaseRegister( UINT32 regNum ) +template void TGcInfoEncoder::SetStackBaseRegister( UINT32 regNum ) { _ASSERTE( regNum != NO_STACK_BASE_REGISTER ); - _ASSERTE(DENORMALIZE_STACK_BASE_REGISTER(NORMALIZE_STACK_BASE_REGISTER(regNum)) == regNum); + _ASSERTE(GcInfoEncoding::DENORMALIZE_STACK_BASE_REGISTER(GcInfoEncoding::NORMALIZE_STACK_BASE_REGISTER(regNum)) == regNum); _ASSERTE( m_StackBaseRegister == NO_STACK_BASE_REGISTER || m_StackBaseRegister == regNum ); #if defined(TARGET_LOONGARCH64) assert(regNum == 3 || 22 == regNum); @@ -729,7 +732,7 @@ void GcInfoEncoder::SetStackBaseRegister( UINT32 regNum ) m_StackBaseRegister = regNum; } -void GcInfoEncoder::SetSizeOfEditAndContinuePreservedArea( UINT32 slots ) +template void TGcInfoEncoder::SetSizeOfEditAndContinuePreservedArea( UINT32 slots ) { _ASSERTE( slots != NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA ); _ASSERTE( m_SizeOfEditAndContinuePreservedArea == NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA ); @@ -737,26 +740,26 @@ void GcInfoEncoder::SetSizeOfEditAndContinuePreservedArea( UINT32 slots ) } #ifdef TARGET_ARM64 -void GcInfoEncoder::SetSizeOfEditAndContinueFixedStackFrame( UINT32 size ) +template void TGcInfoEncoder::SetSizeOfEditAndContinueFixedStackFrame( UINT32 size ) { m_SizeOfEditAndContinueFixedStackFrame = size; } #endif #ifdef TARGET_AMD64 -void GcInfoEncoder::SetWantsReportOnlyLeaf() +template void TGcInfoEncoder::SetWantsReportOnlyLeaf() { m_WantsReportOnlyLeaf = true; } #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -void GcInfoEncoder::SetHasTailCalls() +template void TGcInfoEncoder::SetHasTailCalls() { m_HasTailCalls = true; } #endif // TARGET_AMD64 #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA -void GcInfoEncoder::SetSizeOfStackOutgoingAndScratchArea( UINT32 size ) +template void TGcInfoEncoder::SetSizeOfStackOutgoingAndScratchArea( UINT32 size ) { _ASSERTE( size != (UINT32)-1 ); _ASSERTE( m_SizeOfStackOutgoingAndScratchArea == (UINT32)-1 || m_SizeOfStackOutgoingAndScratchArea == size ); @@ -764,7 +767,7 @@ void GcInfoEncoder::SetSizeOfStackOutgoingAndScratchArea( UINT32 size ) } #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA -void GcInfoEncoder::SetReversePInvokeFrameSlot(INT32 spOffset) +template void TGcInfoEncoder::SetReversePInvokeFrameSlot(INT32 spOffset) { m_ReversePInvokeFrameSlot = spOffset; } @@ -819,7 +822,7 @@ struct CompareSlotDescAndIdBySlotDesc struct CompareLifetimeTransitionsByOffsetThenSlot { - bool operator()(const GcInfoEncoder::LifetimeTransition& first, const GcInfoEncoder::LifetimeTransition& second) + bool operator()(const GcInfoEncoderExt::LifetimeTransition& first, const GcInfoEncoderExt::LifetimeTransition& second) { UINT32 firstOffset = first.CodeOffset; UINT32 secondOffset = second.CodeOffset; @@ -837,12 +840,13 @@ struct CompareLifetimeTransitionsByOffsetThenSlot struct CompareLifetimeTransitionsBySlot { - bool operator()(const GcInfoEncoder::LifetimeTransition& first, const GcInfoEncoder::LifetimeTransition& second) + bool operator()(const GcInfoEncoderExt::LifetimeTransition& first, const GcInfoEncoderExt::LifetimeTransition& second) { UINT32 firstOffset = first.CodeOffset; UINT32 secondOffset = second.CodeOffset; - _ASSERTE(GetNormCodeOffsetChunk(firstOffset) == GetNormCodeOffsetChunk(secondOffset)); + // FIXME: GcInfoEncoding:: + // _ASSERTE(GetNormCodeOffsetChunk(firstOffset) == GetNormCodeOffsetChunk(secondOffset)); // Sort them by slot if( first.SlotId != second.SlotId) @@ -902,19 +906,19 @@ void BitStreamWriter::MemoryBlockList::Dispose(IAllocator* allocator) #endif } -void GcInfoEncoder::FinalizeSlotIds() +template void TGcInfoEncoder::FinalizeSlotIds() { #ifdef _DEBUG m_IsSlotTableFrozen = TRUE; #endif } -void GcInfoEncoder::Build() +template void TGcInfoEncoder::Build() { #ifdef _DEBUG _ASSERTE(m_IsSlotTableFrozen || m_NumSlots == 0); - _ASSERTE((1 << NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2) == NUM_NORM_CODE_OFFSETS_PER_CHUNK); + _ASSERTE((1 << GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2) == GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK); char methodName[256]; m_pCorJitInfo->printMethodName(m_pMethodInfo->ftn, methodName, sizeof(methodName)); @@ -939,7 +943,7 @@ void GcInfoEncoder::Build() BOOL slimHeader = (!m_IsVarArg && !hasGSCookie && (m_PSPSymStackSlot == NO_PSP_SYM) && !hasContextParamType && (m_InterruptibleRanges.Count() == 0) && !hasReversePInvokeFrame && - ((m_StackBaseRegister == NO_STACK_BASE_REGISTER) || (NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister) == 0))) && + ((m_StackBaseRegister == NO_STACK_BASE_REGISTER) || (GcInfoEncoding::NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister) == 0))) && #ifdef TARGET_AMD64 !m_WantsReportOnlyLeaf && #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) @@ -984,8 +988,8 @@ void GcInfoEncoder::Build() } _ASSERTE( m_CodeLength > 0 ); - _ASSERTE(DENORMALIZE_CODE_LENGTH(NORMALIZE_CODE_LENGTH(m_CodeLength)) == m_CodeLength); - GCINFO_WRITE_VARL_U(m_Info1, NORMALIZE_CODE_LENGTH(m_CodeLength), CODE_LENGTH_ENCBASE, CodeLengthSize); + _ASSERTE(GcInfoEncoding::DENORMALIZE_CODE_LENGTH(GcInfoEncoding::NORMALIZE_CODE_LENGTH(m_CodeLength)) == m_CodeLength); + GCINFO_WRITE_VARL_U(m_Info1, GcInfoEncoding::NORMALIZE_CODE_LENGTH(m_CodeLength), GcInfoEncoding::CODE_LENGTH_ENCBASE, CodeLengthSize); if(hasGSCookie) { @@ -999,13 +1003,13 @@ void GcInfoEncoder::Build() _ASSERTE(intersectionStart > 0 && intersectionStart < m_CodeLength); _ASSERTE(intersectionEnd > 0 && intersectionEnd <= m_CodeLength); _ASSERTE(intersectionStart <= intersectionEnd); - UINT32 normPrologSize = NORMALIZE_CODE_OFFSET(intersectionStart); - UINT32 normEpilogSize = NORMALIZE_CODE_OFFSET(m_CodeLength) - NORMALIZE_CODE_OFFSET(intersectionEnd); + UINT32 normPrologSize = GcInfoEncoding::NORMALIZE_CODE_OFFSET(intersectionStart); + UINT32 normEpilogSize = GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength) - GcInfoEncoding::NORMALIZE_CODE_OFFSET(intersectionEnd); _ASSERTE(normPrologSize > 0 && normPrologSize < m_CodeLength); _ASSERTE(normEpilogSize < m_CodeLength); - GCINFO_WRITE_VARL_U(m_Info1, normPrologSize-1, NORM_PROLOG_SIZE_ENCBASE, ProEpilogSize); - GCINFO_WRITE_VARL_U(m_Info1, normEpilogSize, NORM_EPILOG_SIZE_ENCBASE, ProEpilogSize); + GCINFO_WRITE_VARL_U(m_Info1, normPrologSize-1, GcInfoEncoding::NORM_PROLOG_SIZE_ENCBASE, ProEpilogSize); + GCINFO_WRITE_VARL_U(m_Info1, normEpilogSize, GcInfoEncoding::NORM_EPILOG_SIZE_ENCBASE, ProEpilogSize); } else if (hasContextParamType) { @@ -1013,10 +1017,10 @@ void GcInfoEncoder::Build() // Save the prolog size, to be used for determining when it is not safe // to report generics param context and the security object _ASSERTE(m_GSCookieValidRangeStart > 0 && m_GSCookieValidRangeStart < m_CodeLength); - UINT32 normPrologSize = NORMALIZE_CODE_OFFSET(m_GSCookieValidRangeStart); + UINT32 normPrologSize = GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_GSCookieValidRangeStart); _ASSERTE(normPrologSize > 0 && normPrologSize < m_CodeLength); - GCINFO_WRITE_VARL_U(m_Info1, normPrologSize-1, NORM_PROLOG_SIZE_ENCBASE, ProEpilogSize); + GCINFO_WRITE_VARL_U(m_Info1, normPrologSize-1, GcInfoEncoding::NORM_PROLOG_SIZE_ENCBASE, ProEpilogSize); } // Encode the offset to the GS cookie. @@ -1029,7 +1033,7 @@ void GcInfoEncoder::Build() )); #endif - GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_GSCookieStackSlot), GS_COOKIE_STACK_SLOT_ENCBASE, GsCookieSize); + GCINFO_WRITE_VARL_S(m_Info1, GcInfoEncoding::NORMALIZE_STACK_SLOT(m_GSCookieStackSlot), GcInfoEncoding::GS_COOKIE_STACK_SLOT_ENCBASE, GsCookieSize); } @@ -1041,7 +1045,7 @@ void GcInfoEncoder::Build() #ifdef _DEBUG LOG((LF_GCINFO, LL_INFO1000, "Parent PSP at " FMT_STK "\n", DBG_STK(m_PSPSymStackSlot))); #endif - GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_PSPSymStackSlot), PSP_SYM_STACK_SLOT_ENCBASE, PspSymSize); + GCINFO_WRITE_VARL_S(m_Info1, GcInfoEncoding::NORMALIZE_STACK_SLOT(m_PSPSymStackSlot), GcInfoEncoding::PSP_SYM_STACK_SLOT_ENCBASE, PspSymSize); } // Encode the offset to the generics type context. @@ -1053,7 +1057,7 @@ void GcInfoEncoder::Build() DBG_STK(m_GenericsInstContextStackSlot) )); #endif - GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_GenericsInstContextStackSlot), GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE, GenericsCtxSize); + GCINFO_WRITE_VARL_S(m_Info1, GcInfoEncoding::NORMALIZE_STACK_SLOT(m_GenericsInstContextStackSlot), GcInfoEncoding::GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE, GenericsCtxSize); } if(!slimHeader && (m_StackBaseRegister != NO_STACK_BASE_REGISTER)) @@ -1063,28 +1067,28 @@ void GcInfoEncoder::Build() #elif defined(TARGET_RISCV64) assert(m_StackBaseRegister == 8 || 2 == m_StackBaseRegister); #endif - GCINFO_WRITE_VARL_U(m_Info1, NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister), STACK_BASE_REGISTER_ENCBASE, StackBaseSize); + GCINFO_WRITE_VARL_U(m_Info1, GcInfoEncoding::NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister), GcInfoEncoding::STACK_BASE_REGISTER_ENCBASE, StackBaseSize); } if (m_SizeOfEditAndContinuePreservedArea != NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA) { - GCINFO_WRITE_VARL_U(m_Info1, m_SizeOfEditAndContinuePreservedArea, SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, EncInfoSize); + GCINFO_WRITE_VARL_U(m_Info1, m_SizeOfEditAndContinuePreservedArea, GcInfoEncoding::SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, EncInfoSize); #ifdef TARGET_ARM64 - GCINFO_WRITE_VARL_U(m_Info1, m_SizeOfEditAndContinueFixedStackFrame, SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE, EncInfoSize); + GCINFO_WRITE_VARL_U(m_Info1, m_SizeOfEditAndContinueFixedStackFrame, GcInfoEncoding::SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE, EncInfoSize); #endif } if (hasReversePInvokeFrame) { _ASSERTE(!slimHeader); - GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_ReversePInvokeFrameSlot), REVERSE_PINVOKE_FRAME_ENCBASE, ReversePInvokeFrameSize); + GCINFO_WRITE_VARL_S(m_Info1, GcInfoEncoding::NORMALIZE_STACK_SLOT(m_ReversePInvokeFrameSlot), GcInfoEncoding::REVERSE_PINVOKE_FRAME_ENCBASE, ReversePInvokeFrameSize); } #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA if (!slimHeader) { _ASSERTE( m_SizeOfStackOutgoingAndScratchArea != (UINT32)-1 ); - GCINFO_WRITE_VARL_U(m_Info1, NORMALIZE_SIZE_OF_STACK_AREA(m_SizeOfStackOutgoingAndScratchArea), SIZE_OF_STACK_AREA_ENCBASE, FixedAreaSize); + GCINFO_WRITE_VARL_U(m_Info1, GcInfoEncoding::NORMALIZE_SIZE_OF_STACK_AREA(m_SizeOfStackOutgoingAndScratchArea), GcInfoEncoding::SIZE_OF_STACK_AREA_ENCBASE, FixedAreaSize); } #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA @@ -1117,12 +1121,12 @@ void GcInfoEncoder::Build() UINT32 callSite = m_pCallSites[callSiteIndex]; callSite += m_pCallSiteSizes[callSiteIndex]; - _ASSERTE(DENORMALIZE_CODE_OFFSET(NORMALIZE_CODE_OFFSET(callSite)) == callSite); - UINT32 normOffset = NORMALIZE_CODE_OFFSET(callSite); + _ASSERTE(GcInfoEncoding::DENORMALIZE_CODE_OFFSET(GcInfoEncoding::NORMALIZE_CODE_OFFSET(callSite)) == callSite); + UINT32 normOffset = GcInfoEncoding::NORMALIZE_CODE_OFFSET(callSite); m_pCallSites[numCallSites++] = normOffset; } - GCINFO_WRITE_VARL_U(m_Info1, NORMALIZE_NUM_SAFE_POINTS(numCallSites), NUM_SAFE_POINTS_ENCBASE, NumCallSitesSize); + GCINFO_WRITE_VARL_U(m_Info1, numCallSites, GcInfoEncoding::NUM_SAFE_POINTS_ENCBASE, NumCallSitesSize); m_NumCallSites = numCallSites; #endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -1132,7 +1136,7 @@ void GcInfoEncoder::Build() } else { - GCINFO_WRITE_VARL_U(m_Info1, NORMALIZE_NUM_INTERRUPTIBLE_RANGES(numInterruptibleRanges), NUM_INTERRUPTIBLE_RANGES_ENCBASE, NumRangesSize); + GCINFO_WRITE_VARL_U(m_Info1, numInterruptibleRanges, GcInfoEncoding::NUM_INTERRUPTIBLE_RANGES_ENCBASE, NumRangesSize); } @@ -1142,7 +1146,7 @@ void GcInfoEncoder::Build() // Encode call site offsets /////////////////////////////////////////////////////////////////////// - UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + UINT32 numBitsPerOffset = CeilOfLog2(GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength)); for(UINT32 callSiteIndex = 0; callSiteIndex < m_NumCallSites; callSiteIndex++) { @@ -1173,9 +1177,9 @@ void GcInfoEncoder::Build() lastStopOffset = normStopOffset; - GCINFO_WRITE_VARL_U(m_Info1, normStartDelta, INTERRUPTIBLE_RANGE_DELTA1_ENCBASE, RangeSize); + GCINFO_WRITE_VARL_U(m_Info1, normStartDelta, GcInfoEncoding::INTERRUPTIBLE_RANGE_DELTA1_ENCBASE, RangeSize); - GCINFO_WRITE_VARL_U(m_Info1, normStopDelta-1, INTERRUPTIBLE_RANGE_DELTA2_ENCBASE, RangeSize); + GCINFO_WRITE_VARL_U(m_Info1, normStopDelta-1, GcInfoEncoding::INTERRUPTIBLE_RANGE_DELTA2_ENCBASE, RangeSize); } } @@ -1260,14 +1264,14 @@ void GcInfoEncoder::Build() #endif } -#if CODE_OFFSETS_NEED_NORMALIZATION - // Do a pass to normalize transition offsets - for(pCurrent = pTransitions; pCurrent < pEndTransitions; pCurrent++) - { - _ASSERTE(pCurrent->CodeOffset <= m_CodeLength); - pCurrent->CodeOffset = NORMALIZE_CODE_OFFSET(pCurrent->CodeOffset); + if (GcInfoEncoding::CODE_OFFSETS_NEED_NORMALIZATION) { + // Do a pass to normalize transition offsets + for(pCurrent = pTransitions; pCurrent < pEndTransitions; pCurrent++) + { + _ASSERTE(pCurrent->CodeOffset <= m_CodeLength); + pCurrent->CodeOffset = GcInfoEncoding::NORMALIZE_CODE_OFFSET(pCurrent->CodeOffset); + } } -#endif /////////////////////////////////////////////////////////////////// // Find out which slots are really used @@ -1444,7 +1448,7 @@ void GcInfoEncoder::Build() if (numRegisters) { GCINFO_WRITE(m_Info1, 1, 1, FlagsSize); - GCINFO_WRITE_VARL_U(m_Info1, numRegisters, NUM_REGISTERS_ENCBASE, NumRegsSize); + GCINFO_WRITE_VARL_U(m_Info1, numRegisters, GcInfoEncoding::NUM_REGISTERS_ENCBASE, NumRegsSize); } else { @@ -1453,8 +1457,8 @@ void GcInfoEncoder::Build() if (numStackSlots || numUntrackedSlots) { GCINFO_WRITE(m_Info1, 1, 1, FlagsSize); - GCINFO_WRITE_VARL_U(m_Info1, numStackSlots, NUM_STACK_SLOTS_ENCBASE, NumStackSize); - GCINFO_WRITE_VARL_U(m_Info1, numUntrackedSlots, NUM_UNTRACKED_SLOTS_ENCBASE, NumUntrackedSize); + GCINFO_WRITE_VARL_U(m_Info1, numStackSlots, GcInfoEncoding::NUM_STACK_SLOTS_ENCBASE, NumStackSize); + GCINFO_WRITE_VARL_U(m_Info1, numUntrackedSlots, GcInfoEncoding::NUM_UNTRACKED_SLOTS_ENCBASE, NumUntrackedSize); } else { @@ -1478,8 +1482,8 @@ void GcInfoEncoder::Build() _ASSERTE(pSlotDesc->IsRegister()); // Encode slot identification - UINT32 currentNormRegNum = NORMALIZE_REGISTER(pSlotDesc->Slot.RegisterNumber); - GCINFO_WRITE_VARL_U(m_Info1, currentNormRegNum, REGISTER_ENCBASE, RegSlotSize); + UINT32 currentNormRegNum = pSlotDesc->Slot.RegisterNumber; + GCINFO_WRITE_VARL_U(m_Info1, currentNormRegNum, GcInfoEncoding::REGISTER_ENCBASE, RegSlotSize); GCINFO_WRITE(m_Info1, pSlotDesc->Flags, 2, RegSlotSize); for(UINT32 j = 1; j < numRegisters; j++) @@ -1495,17 +1499,17 @@ void GcInfoEncoder::Build() while(pSlotDesc->IsDeleted()); _ASSERTE(pSlotDesc->IsRegister()); - currentNormRegNum = NORMALIZE_REGISTER(pSlotDesc->Slot.RegisterNumber); + currentNormRegNum = pSlotDesc->Slot.RegisterNumber; if(lastFlags != GC_SLOT_IS_REGISTER) { - GCINFO_WRITE_VARL_U(m_Info1, currentNormRegNum, REGISTER_ENCBASE, RegSlotSize); + GCINFO_WRITE_VARL_U(m_Info1, currentNormRegNum, GcInfoEncoding::REGISTER_ENCBASE, RegSlotSize); GCINFO_WRITE(m_Info1, pSlotDesc->Flags, 2, RegSlotSize); } else { _ASSERTE(pSlotDesc->Flags == GC_SLOT_IS_REGISTER); - GCINFO_WRITE_VARL_U(m_Info1, currentNormRegNum - lastNormRegNum - 1, REGISTER_DELTA_ENCBASE, RegSlotSize); + GCINFO_WRITE_VARL_U(m_Info1, currentNormRegNum - lastNormRegNum - 1, GcInfoEncoding::REGISTER_DELTA_ENCBASE, RegSlotSize); } } } @@ -1525,8 +1529,8 @@ void GcInfoEncoder::Build() // Encode slot identification _ASSERTE((pSlotDesc->Slot.Stack.Base & ~3) == 0); GCINFO_WRITE(m_Info1, pSlotDesc->Slot.Stack.Base, 2, StackSlotSize); - INT32 currentNormStackSlot = NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); - GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, STACK_SLOT_ENCBASE, StackSlotSize); + INT32 currentNormStackSlot = GcInfoEncoding::NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); + GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, GcInfoEncoding::STACK_SLOT_ENCBASE, StackSlotSize); GCINFO_WRITE(m_Info1, pSlotDesc->Flags, 2, StackSlotSize); @@ -1544,20 +1548,20 @@ void GcInfoEncoder::Build() _ASSERTE(!pSlotDesc->IsRegister()); _ASSERTE(!pSlotDesc->IsUntracked()); - currentNormStackSlot = NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); + currentNormStackSlot = GcInfoEncoding::NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); _ASSERTE((pSlotDesc->Slot.Stack.Base & ~3) == 0); GCINFO_WRITE(m_Info1, pSlotDesc->Slot.Stack.Base, 2, StackSlotSize); if(lastFlags != GC_SLOT_BASE) { - GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, STACK_SLOT_ENCBASE, StackSlotSize); + GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, GcInfoEncoding::STACK_SLOT_ENCBASE, StackSlotSize); GCINFO_WRITE(m_Info1, pSlotDesc->Flags, 2, StackSlotSize); } else { _ASSERTE(pSlotDesc->Flags == GC_SLOT_BASE); - GCINFO_WRITE_VARL_U(m_Info1, currentNormStackSlot - lastNormStackSlot, STACK_SLOT_DELTA_ENCBASE, StackSlotSize); + GCINFO_WRITE_VARL_U(m_Info1, currentNormStackSlot - lastNormStackSlot, GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE, StackSlotSize); } } } @@ -1577,8 +1581,8 @@ void GcInfoEncoder::Build() // Encode slot identification _ASSERTE((pSlotDesc->Slot.Stack.Base & ~3) == 0); GCINFO_WRITE(m_Info1, pSlotDesc->Slot.Stack.Base, 2, UntrackedSlotSize); - INT32 currentNormStackSlot = NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); - GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, STACK_SLOT_ENCBASE, UntrackedSlotSize); + INT32 currentNormStackSlot = GcInfoEncoding::NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); + GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, GcInfoEncoding::STACK_SLOT_ENCBASE, UntrackedSlotSize); GCINFO_WRITE(m_Info1, pSlotDesc->Flags, 2, UntrackedSlotSize); @@ -1596,20 +1600,20 @@ void GcInfoEncoder::Build() _ASSERTE(!pSlotDesc->IsRegister()); _ASSERTE(pSlotDesc->IsUntracked()); - currentNormStackSlot = NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); + currentNormStackSlot = GcInfoEncoding::NORMALIZE_STACK_SLOT(pSlotDesc->Slot.Stack.SpOffset); _ASSERTE((pSlotDesc->Slot.Stack.Base & ~3) == 0); GCINFO_WRITE(m_Info1, pSlotDesc->Slot.Stack.Base, 2, UntrackedSlotSize); if(lastFlags != GC_SLOT_UNTRACKED) { - GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, STACK_SLOT_ENCBASE, UntrackedSlotSize); + GCINFO_WRITE_VARL_S(m_Info1, currentNormStackSlot, GcInfoEncoding::STACK_SLOT_ENCBASE, UntrackedSlotSize); GCINFO_WRITE(m_Info1, pSlotDesc->Flags, 2, UntrackedSlotSize); } else { _ASSERTE(pSlotDesc->Flags == GC_SLOT_UNTRACKED); - GCINFO_WRITE_VARL_U(m_Info1, currentNormStackSlot - lastNormStackSlot, STACK_SLOT_DELTA_ENCBASE, UntrackedSlotSize); + GCINFO_WRITE_VARL_U(m_Info1, currentNormStackSlot - lastNormStackSlot, GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE, UntrackedSlotSize); } } } @@ -1701,13 +1705,13 @@ void GcInfoEncoder::Build() for (LiveStateHashTable::KeyIterator iter = hashMap.Begin(), end = hashMap.End(); !iter.Equal(end); iter.Next()) { largestSetOffset = sizeofSets; - sizeofSets += SizeofSlotStateVarLengthVector(*iter.Get(), LIVESTATE_RLE_SKIP_ENCBASE, LIVESTATE_RLE_RUN_ENCBASE); + sizeofSets += SizeofSlotStateVarLengthVector(*iter.Get(), GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE, GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE); } // Now that we know the largest offset, we can figure out how much the indirection // will cost us and commit UINT32 numBitsPerPointer = ((largestSetOffset < 2) ? 1 : CeilOfLog2(largestSetOffset + 1)); - const size_t sizeofEncodedNumBitsPerPointer = BitStreamWriter::SizeofVarLengthUnsigned(numBitsPerPointer, POINTER_SIZE_ENCBASE); + const size_t sizeofEncodedNumBitsPerPointer = BitStreamWriter::SizeofVarLengthUnsigned(numBitsPerPointer, GcInfoEncoding::POINTER_SIZE_ENCBASE); const size_t sizeofNoIndirection = m_NumCallSites * (numRegisters + numStackSlots); const size_t sizeofIndirection = sizeofEncodedNumBitsPerPointer // Encode the pointer sizes + (m_NumCallSites * numBitsPerPointer) // Encode the pointers @@ -1723,14 +1727,14 @@ void GcInfoEncoder::Build() { // we are using an indirection GCINFO_WRITE(m_Info1, 1, 1, FlagsSize); - GCINFO_WRITE_VARL_U(m_Info1, numBitsPerPointer - 1, POINTER_SIZE_ENCBASE, CallSiteStateSize); + GCINFO_WRITE_VARL_U(m_Info1, numBitsPerPointer - 1, GcInfoEncoding::POINTER_SIZE_ENCBASE, CallSiteStateSize); // Now encode the live sets and record the real offset for (LiveStateHashTable::KeyIterator iter = hashMap.Begin(), end = hashMap.End(); !iter.Equal(end); iter.Next()) { _ASSERTE(FitsIn(m_Info2.GetBitCount())); iter.SetValue((UINT32)m_Info2.GetBitCount()); - GCINFO_WRITE_VAR_VECTOR(m_Info2, *iter.Get(), LIVESTATE_RLE_SKIP_ENCBASE, LIVESTATE_RLE_RUN_ENCBASE, CallSiteStateSize); + GCINFO_WRITE_VAR_VECTOR(m_Info2, *iter.Get(), GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE, GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE, CallSiteStateSize); } _ASSERTE(sizeofSets == m_Info2.GetBitCount()); @@ -1843,7 +1847,7 @@ void GcInfoEncoder::Build() InterruptibleRange *pRange = &pRanges[i]; totalInterruptibleLength += pRange->NormStopOffset - pRange->NormStartOffset; } - _ASSERTE(totalInterruptibleLength <= NORMALIZE_CODE_OFFSET(m_CodeLength)); + _ASSERTE(totalInterruptibleLength <= GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength)); liveState.ClearAll(); // Re-use couldBeLive @@ -1944,14 +1948,14 @@ void GcInfoEncoder::Build() pEndTransitions = pNextFree; #else - UINT32 totalInterruptibleLength = NORMALIZE_CODE_OFFSET(m_CodeLength); + UINT32 totalInterruptibleLength = GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength); #endif //PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED // // Initialize chunk pointers // - UINT32 numChunks = (totalInterruptibleLength + NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 numChunks = (totalInterruptibleLength + GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; _ASSERTE(numChunks > 0); size_t* pChunkPointers = (size_t*) m_pAllocator->Alloc(numChunks*sizeof(size_t)); @@ -2008,12 +2012,12 @@ void GcInfoEncoder::Build() pChunkPointers[currentChunk] = m_Info2.GetBitCount() + 1; // Write couldBeLive slot map - GCINFO_WRITE_VAR_VECTOR(m_Info2, couldBeLive, LIVESTATE_RLE_SKIP_ENCBASE, LIVESTATE_RLE_RUN_ENCBASE, ChunkMaskSize); + GCINFO_WRITE_VAR_VECTOR(m_Info2, couldBeLive, GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE, GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE, ChunkMaskSize); LOG((LF_GCINFO, LL_INFO100000, "Chunk %d couldBeLive (%04x-%04x):\n", currentChunk, - currentChunk * NUM_NORM_CODE_OFFSETS_PER_CHUNK, - ((currentChunk + 1) * NUM_NORM_CODE_OFFSETS_PER_CHUNK) - 1 + currentChunk * GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK, + ((currentChunk + 1) * GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK) - 1 )); // Write final state @@ -2039,7 +2043,7 @@ void GcInfoEncoder::Build() } // Write transitions offsets - UINT32 normChunkBaseCodeOffset = currentChunk * NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 normChunkBaseCodeOffset = currentChunk * GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; LifetimeTransition* pT = pCurrent - numTransitionsInCurrentChunk; @@ -2068,10 +2072,10 @@ void GcInfoEncoder::Build() // Don't encode transitions at offset 0 as they are useless if(normCodeOffsetDelta) { - _ASSERTE(normCodeOffsetDelta < NUM_NORM_CODE_OFFSETS_PER_CHUNK); + _ASSERTE(normCodeOffsetDelta < GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK); GCINFO_WRITE(m_Info2, 1, 1, ChunkTransitionSize); - GCINFO_WRITE(m_Info2, normCodeOffsetDelta, NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2, ChunkTransitionSize); + GCINFO_WRITE(m_Info2, normCodeOffsetDelta, GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2, ChunkTransitionSize); #ifdef MEASURE_GCINFO m_CurrentMethodSize.NumTransitions++; @@ -2105,7 +2109,7 @@ void GcInfoEncoder::Build() } UINT32 numBitsPerPointer = CeilOfLog2(largestPointer + 1); - GCINFO_WRITE_VARL_U(m_Info1, numBitsPerPointer, POINTER_SIZE_ENCBASE, ChunkPtrSize); + GCINFO_WRITE_VARL_U(m_Info1, numBitsPerPointer, GcInfoEncoding::POINTER_SIZE_ENCBASE, ChunkPtrSize); if(numBitsPerPointer) { @@ -2173,7 +2177,7 @@ lExitSuccess:; #endif } -void GcInfoEncoder::SizeofSlotStateVarLengthVector(const BitArray &vector, +template void TGcInfoEncoder::SizeofSlotStateVarLengthVector(const BitArray &vector, UINT32 baseSkip, UINT32 baseRun, UINT32 *pSizeofSimple, @@ -2248,7 +2252,7 @@ void GcInfoEncoder::SizeofSlotStateVarLengthVector(const BitArray &vector, *pSizeofRLENeg = sizeofRLENeg; } -UINT32 GcInfoEncoder::SizeofSlotStateVarLengthVector(const BitArray &vector, +template UINT32 TGcInfoEncoder::SizeofSlotStateVarLengthVector(const BitArray &vector, UINT32 baseSkip, UINT32 baseRun) { @@ -2265,7 +2269,7 @@ UINT32 GcInfoEncoder::SizeofSlotStateVarLengthVector(const BitArray &vector, return sizeofRLENeg; } -UINT32 GcInfoEncoder::WriteSlotStateVarLengthVector(BitStreamWriter &writer, +template UINT32 TGcInfoEncoder::WriteSlotStateVarLengthVector(BitStreamWriter &writer, const BitArray &vector, UINT32 baseSkip, UINT32 baseRun) @@ -2355,7 +2359,7 @@ UINT32 GcInfoEncoder::WriteSlotStateVarLengthVector(BitStreamWriter &writer, } -void GcInfoEncoder::EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTransitions, +template void TGcInfoEncoder::EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTransitions, size_t* pNumTransitions, LifetimeTransition** ppEndTransitions) { @@ -2410,7 +2414,7 @@ void GcInfoEncoder::EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTrans // Write encoded information to its final destination and frees temporary buffers. // The encoder shouldn't be used anymore after calling this method. // -BYTE* GcInfoEncoder::Emit() +template BYTE* TGcInfoEncoder::Emit() { size_t cbGcInfoSize = m_Info1.GetByteCount() + m_Info2.GetByteCount(); @@ -2439,13 +2443,13 @@ BYTE* GcInfoEncoder::Emit() return destBuffer; } -void * GcInfoEncoder::eeAllocGCInfo (size_t blockSize) +template void * TGcInfoEncoder::eeAllocGCInfo (size_t blockSize) { m_BlockSize = blockSize; return m_pCorJitInfo->allocGCInfo(blockSize); } -size_t GcInfoEncoder::GetEncodedGCInfoSize() const +template size_t TGcInfoEncoder::GetEncodedGCInfoSize() const { return m_BlockSize; } @@ -2616,3 +2620,5 @@ int BitStreamWriter::EncodeVarLengthSigned( SSIZE_T n, UINT32 base ) } } +// Instantiate the encoder so other files can use it +template class TGcInfoEncoder; diff --git a/src/coreclr/inc/check.h b/src/coreclr/inc/check.h index 21d717c13e6bb7..5a7218cc652d77 100644 --- a/src/coreclr/inc/check.h +++ b/src/coreclr/inc/check.h @@ -723,7 +723,9 @@ CHECK CheckOverflow(UINT64 value1, UINT64 value2); #ifdef __APPLE__ CHECK CheckOverflow(SIZE_T value1, SIZE_T value2); #endif +#ifndef __wasm__ CHECK CheckOverflow(PTR_CVOID address, UINT offset); +#endif #if defined(_MSC_VER) CHECK CheckOverflow(const void *address, ULONG offset); #endif diff --git a/src/coreclr/inc/check.inl b/src/coreclr/inc/check.inl index 34a2956d1be6e2..b0f65c5d218bbd 100644 --- a/src/coreclr/inc/check.inl +++ b/src/coreclr/inc/check.inl @@ -156,7 +156,7 @@ inline CHECK CheckAligned(UINT64 value, UINT alignment) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline CHECK CheckAligned(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; @@ -237,7 +237,7 @@ inline CHECK CheckOverflow(const void *address, UINT64 offset) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline CHECK CheckOverflow(const void *address, SIZE_T offset) { CHECK((UINT64) address + offset >= (UINT64) address); @@ -316,10 +316,11 @@ inline CHECK CheckUnderflow(const void *address, UINT64 offset) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline CHECK CheckUnderflow(const void *address, SIZE_T offset) { -#if POINTER_BITS == 32 + // SIZE_T is 32bit on wasm32 +#if !defined(__wasm__) && POINTER_BITS == 32 CHECK(offset >> 32 == 0); CHECK((UINT) (SIZE_T) address - (UINT) offset <= (UINT) (SIZE_T) address); #else diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index bf28ce3fc3e757..8bdde4c7baa642 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -688,6 +688,9 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_GDBJitEmitDebugFrame, W("GDBJitEmitDebugFrame" #endif RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_MaxVectorTBitWidth, W("MaxVectorTBitWidth"), 0, "The maximum decimal width, in bits, that Vector is allowed to be. A value less than 128 is treated as the system default.", CLRConfig::LookupOptions::ParseIntegerAsBase10) +#if defined(TARGET_AMD64) || defined(TARGET_X86) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PreferredVectorBitWidth, W("PreferredVectorBitWidth"), 0, "The maximum decimal width, in bits, of fixed-width vectors that may be considered hardware accelerated. A value less than 128 is treated as the system default.", CLRConfig::LookupOptions::ParseIntegerAsBase10) +#endif // defined(TARGET_AMD64) || defined(TARGET_X86) // // Hardware Intrinsic ISAs; keep in sync with jitconfigvalues.h diff --git a/src/coreclr/inc/clrnt.h b/src/coreclr/inc/clrnt.h index 2d935a95317e69..bcd4427538babe 100644 --- a/src/coreclr/inc/clrnt.h +++ b/src/coreclr/inc/clrnt.h @@ -501,4 +501,48 @@ RtlVirtualUnwind( #endif // TARGET_RISCV64 +#ifdef TARGET_WASM +// +// Define unwind information flags. +// + +#define UNW_FLAG_NHANDLER 0x0 /* any handler */ +#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ +#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ + +PEXCEPTION_ROUTINE +RtlVirtualUnwind ( + _In_ DWORD HandlerType, + _In_ DWORD ImageBase, + _In_ DWORD ControlPc, + _In_ PRUNTIME_FUNCTION FunctionEntry, + __inout PT_CONTEXT ContextRecord, + _Out_ PVOID *HandlerData, + _Out_ PDWORD EstablisherFrame, + __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers + ); + +FORCEINLINE +ULONG +RtlpGetFunctionEndAddress ( + _In_ PT_RUNTIME_FUNCTION FunctionEntry, + _In_ TADDR ImageBase + ) +{ + _ASSERTE("The function RtlpGetFunctionEndAddress is not implemented on wasm"); + return 0; +} + +#define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ((FunctionEntry)->BeginAddress) +#define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = (address)) + +#define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) (RtlpGetFunctionEndAddress(FunctionEntry, (ULONG64)(ImageBase))) + +#define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) + +typedef struct _UNWIND_INFO { + // dummy +} UNWIND_INFO, *PUNWIND_INFO; +#endif + #endif // CLRNT_H_ diff --git a/src/coreclr/inc/clrtypes.h b/src/coreclr/inc/clrtypes.h index 9094e4932a2527..b1990054c48738 100644 --- a/src/coreclr/inc/clrtypes.h +++ b/src/coreclr/inc/clrtypes.h @@ -338,7 +338,7 @@ inline UINT64 AlignUp(UINT64 value, UINT alignment) return (value+alignment-1)&~(UINT64)(alignment-1); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline SIZE_T AlignUp(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; @@ -399,13 +399,13 @@ inline UINT AlignmentPad(UINT64 value, UINT alignment) return (UINT) (AlignUp(value, alignment) - value); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline UINT AlignmentPad(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; return (UINT) (AlignUp(value, alignment) - value); } -#endif // __APPLE__ +#endif // __APPLE__ || __wasm__ inline UINT AlignmentTrim(UINT value, UINT alignment) { @@ -432,7 +432,7 @@ inline UINT AlignmentTrim(UINT64 value, UINT alignment) return ((UINT)value)&(alignment-1); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline UINT AlignmentTrim(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; diff --git a/src/coreclr/inc/corcompile.h b/src/coreclr/inc/corcompile.h index 845b72465c3439..57ca94832e6be7 100644 --- a/src/coreclr/inc/corcompile.h +++ b/src/coreclr/inc/corcompile.h @@ -56,6 +56,11 @@ inline ReadyToRunCrossModuleInlineFlags operator &( const ReadyToRunCrossModuleI return static_cast(static_cast(left) & static_cast(right)); } +#ifdef TARGET_WASM +// why was it defined only for x86 before? +typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; +#endif + #ifdef TARGET_X86 typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; diff --git a/src/coreclr/inc/cordebuginfo.h b/src/coreclr/inc/cordebuginfo.h index b3125060f308eb..b6979c52f3ac5c 100644 --- a/src/coreclr/inc/cordebuginfo.h +++ b/src/coreclr/inc/cordebuginfo.h @@ -213,6 +213,8 @@ class ICorDebugInfo REGNUM_T5, REGNUM_T6, REGNUM_PC, +#elif TARGET_WASM + REGNUM_PC, // wasm doesn't have registers #else PORTABILITY_WARNING("Register numbers not defined on this platform") #endif diff --git a/src/coreclr/inc/corjitflags.h b/src/coreclr/inc/corjitflags.h index b7de9711f07f79..f6eb983953f95e 100644 --- a/src/coreclr/inc/corjitflags.h +++ b/src/coreclr/inc/corjitflags.h @@ -64,10 +64,6 @@ class CORJIT_FLAGS CORJIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention #endif -#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 - }; CORJIT_FLAGS() diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index c3c1f97ddeedea..36081dee778ab4 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -721,6 +721,8 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { #define DAC_CS_NATIVE_DATA_SIZE 48 #elif defined(TARGET_HAIKU) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 56 +#elif defined(TARGET_WASM) +#define DAC_CS_NATIVE_DATA_SIZE 76 #else #warning #error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)). diff --git a/src/coreclr/inc/debugmacros.h b/src/coreclr/inc/debugmacros.h index 35592ea36b1214..d5ed757ae77aab 100644 --- a/src/coreclr/inc/debugmacros.h +++ b/src/coreclr/inc/debugmacros.h @@ -13,6 +13,7 @@ #include "stacktrace.h" #include "debugmacrosext.h" #include "palclr.h" +#include #undef _ASSERTE #undef VERIFY diff --git a/src/coreclr/inc/debugreturn.h b/src/coreclr/inc/debugreturn.h index d052364ff89057..7047b19ed0f3c0 100644 --- a/src/coreclr/inc/debugreturn.h +++ b/src/coreclr/inc/debugreturn.h @@ -96,11 +96,13 @@ typedef __SafeToReturn __ReturnOK; // build. (And, in fastchecked, there is no penalty at all.) // #ifdef _MSC_VER -#define return if (0 && __ReturnOK::safe_to_return()) { } else return +#define debug_instrumented_return if (0 && __ReturnOK::safe_to_return()) { } else return #else // _MSC_VER -#define return for (;1;__ReturnOK::safe_to_return()) return +#define debug_instrumented_return for (;1;__ReturnOK::safe_to_return()) return #endif // _MSC_VER +#define return debug_instrumented_return + #define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { typedef __YouCannotUseAReturnStatementHere __ReturnOK; if (0 && __ReturnOK::used()) { } else { #define DEBUG_ASSURE_NO_RETURN_END(arg) } } diff --git a/src/coreclr/inc/gcinfodecoder.h b/src/coreclr/inc/gcinfodecoder.h index 0b51833ee19d5e..2e3b8e7b6b905c 100644 --- a/src/coreclr/inc/gcinfodecoder.h +++ b/src/coreclr/inc/gcinfodecoder.h @@ -465,6 +465,8 @@ struct GcSlotDesc GcSlotFlags Flags; }; + +template class GcSlotDecoder { public: @@ -507,12 +509,13 @@ class GcSlotDecoder }; #ifdef USE_GC_INFO_DECODER -class GcInfoDecoder +template +class TGcInfoDecoder { public: // If you are not interested in interruptibility or gc lifetime information, pass 0 as instructionOffset - GcInfoDecoder( + TGcInfoDecoder( GCInfoToken gcInfoToken, GcInfoDecoderFlags flags = DECODE_EVERYTHING, UINT32 instructionOffset = 0 @@ -532,7 +535,7 @@ class GcInfoDecoder // This is used for gcinfodumper bool IsSafePoint(UINT32 codeOffset); - typedef void EnumerateSafePointsCallback (GcInfoDecoder* decoder, UINT32 offset, void * hCallback); + typedef void EnumerateSafePointsCallback (TGcInfoDecoder * decoder, UINT32 offset, void * hCallback); void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback); #endif @@ -661,7 +664,7 @@ class GcInfoDecoder bool IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD); void ReportUntrackedSlots( - GcSlotDecoder& slotDecoder, + GcSlotDecoder& slotDecoder, PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, @@ -689,7 +692,7 @@ class GcInfoDecoder inline void ReportSlotToGC( - GcSlotDecoder& slotDecoder, + GcSlotDecoder& slotDecoder, UINT32 slotIndex, PREGDISPLAY pRD, bool reportScratchSlots, @@ -746,6 +749,9 @@ class GcInfoDecoder } } }; + +typedef TGcInfoDecoder GcInfoDecoder; + #endif // USE_GC_INFO_DECODER diff --git a/src/coreclr/inc/gcinfoencoder.h b/src/coreclr/inc/gcinfoencoder.h index 3777e1b7064bb2..f147d9566e9e87 100644 --- a/src/coreclr/inc/gcinfoencoder.h +++ b/src/coreclr/inc/gcinfoencoder.h @@ -315,16 +315,6 @@ class BitStreamWriter typedef UINT32 GcSlotId; -inline UINT32 GetNormCodeOffsetChunk(UINT32 normCodeOffset) -{ - return normCodeOffset / NUM_NORM_CODE_OFFSETS_PER_CHUNK; -} - -inline UINT32 GetCodeOffsetChunk(UINT32 codeOffset) -{ - return (NORMALIZE_CODE_OFFSET(codeOffset)) / NUM_NORM_CODE_OFFSETS_PER_CHUNK; -} - enum GENERIC_CONTEXTPARAM_TYPE { GENERIC_CONTEXTPARAM_NONE = 0, @@ -335,18 +325,8 @@ enum GENERIC_CONTEXTPARAM_TYPE extern void DECLSPEC_NORETURN ThrowOutOfMemory(); -class GcInfoEncoder +namespace GcInfoEncoderExt { -public: - typedef void (*NoMemoryFunction)(void); - - GcInfoEncoder( - ICorJitInfo* pCorJitInfo, - CORINFO_METHOD_INFO* pMethodInfo, - IAllocator* pJitAllocator, - NoMemoryFunction pNoMem = ::ThrowOutOfMemory - ); - struct LifetimeTransition { UINT32 CodeOffset; @@ -354,7 +334,20 @@ class GcInfoEncoder BYTE BecomesLive; BYTE IsDeleted; }; +} +template +class TGcInfoEncoder +{ +public: + typedef void (*NoMemoryFunction)(void); + + TGcInfoEncoder( + ICorJitInfo* pCorJitInfo, + CORINFO_METHOD_INFO* pMethodInfo, + IAllocator* pJitAllocator, + NoMemoryFunction pNoMem = ::ThrowOutOfMemory + ); #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED void DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UINT32 numCallSites); @@ -488,7 +481,7 @@ class GcInfoEncoder BitStreamWriter m_Info2; // Used for chunk encodings GcInfoArrayList m_InterruptibleRanges; - GcInfoArrayList m_LifetimeTransitions; + GcInfoArrayList m_LifetimeTransitions; bool m_IsVarArg; #if defined(TARGET_AMD64) @@ -548,9 +541,14 @@ class GcInfoEncoder // new array, and copying the non-removed elements into it. If it does this, sets "*ppTransitions" to // point to the new array, "*pNumTransitions" to its shorted length, and "*ppEndTransitions" to // point one beyond the used portion of this array. - void EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTransitions, + void EliminateRedundantLiveDeadPairs(GcInfoEncoderExt::LifetimeTransition** ppTransitions, size_t* pNumTransitions, - LifetimeTransition** ppEndTransitions); + GcInfoEncoderExt::LifetimeTransition** ppEndTransitions); + + static inline UINT32 GetNormCodeOffsetChunk(UINT32 normCodeOffset) + { + return normCodeOffset / GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; + } #ifdef _DEBUG bool m_IsSlotTableFrozen; @@ -561,4 +559,6 @@ class GcInfoEncoder #endif }; +typedef TGcInfoEncoder GcInfoEncoder; + #endif // !__GCINFOENCODER_H__ diff --git a/src/coreclr/inc/gcinfotypes.h b/src/coreclr/inc/gcinfotypes.h index e1f7b517897a3f..36164759e54429 100644 --- a/src/coreclr/inc/gcinfotypes.h +++ b/src/coreclr/inc/gcinfotypes.h @@ -5,6 +5,11 @@ #ifndef __GCINFOTYPES_H__ #define __GCINFOTYPES_H__ +// HACK: debugreturn.h breaks constexpr +#ifdef debug_instrumented_return +#undef return +#endif // debug_instrumented_return + #ifndef FEATURE_NATIVEAOT #include "gcinfo.h" #endif @@ -14,7 +19,7 @@ #endif // _MSC_VER // ***************************************************************************** -// WARNING!!!: These values and code are used in the runtime repo and SOS in the +// WARNING!!!: These values and code are used in the runtime repo and SOS in the // diagnostics repo. Should updated in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfotypes.h // https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcinfotypes.h @@ -612,274 +617,283 @@ void FASTCALL decodeCallPattern(int pattern, #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) (x) -#define DENORMALIZE_CODE_LENGTH(x) (x) -// Encode RBP as 0 -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) -#define DENORMALIZE_CODE_OFFSET(x) (x) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define STACK_BASE_REGISTER_ENCBASE 3 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 2 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 2 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding AMD64GcInfoEncoding + +struct AMD64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + + // Encode RBP as 0 + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) ^ 5); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) ^ 5); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = false; + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + static const int STACK_BASE_REGISTER_ENCBASE = 3; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 2; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 2; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_ARM) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>2) -#define DENORMALIZE_STACK_SLOT(x) ((x)<<2) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>1) -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<1) -// Encode R11 as zero -#define NORMALIZE_STACK_BASE_REGISTER(x) ((((x) - 4) & 7) ^ 7) -#define DENORMALIZE_STACK_BASE_REGISTER(x) (((x) ^ 7) + 4) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>2) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<2) -#define CODE_OFFSETS_NEED_NORMALIZATION 1 -#define NORMALIZE_CODE_OFFSET(x) ((x)>>1) // Instructions are 2/4 bytes long in Thumb/ARM states, -#define DENORMALIZE_CODE_OFFSET(x) ((x)<<1) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -// The choices of these encoding bases only affects space overhead -// and performance, not semantics/correctness. -#define PSP_SYM_STACK_SLOT_ENCBASE 5 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 5 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 5 -#define GS_COOKIE_STACK_SLOT_ENCBASE 5 -#define CODE_LENGTH_ENCBASE 7 -#define STACK_BASE_REGISTER_ENCBASE 1 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 -#define REVERSE_PINVOKE_FRAME_ENCBASE 5 -#define NUM_REGISTERS_ENCBASE 2 -#define NUM_STACK_SLOTS_ENCBASE 3 -#define NUM_UNTRACKED_SLOTS_ENCBASE 3 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 4 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 2 -#define REGISTER_DELTA_ENCBASE 1 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 2 -#define NUM_EH_CLAUSES_ENCBASE 3 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding ARM32GcInfoEncoding + +struct ARM32GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>2); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<2); } + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>1); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<1); } + // Encode R11 as zero + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((((x) - 4) & 7) ^ 7); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return (((x) ^ 7) + 4); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<2); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>1) /* Instructions are 2/4 bytes long in Thumb/ARM states */; } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<1); } + + // The choices of these encoding bases only affects space overhead + // and performance, not semantics/correctness. + static const int PSP_SYM_STACK_SLOT_ENCBASE = 5; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 5; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 5; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 5; + static const int CODE_LENGTH_ENCBASE = 7; + static const int STACK_BASE_REGISTER_ENCBASE = 1; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 3; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 5; + static const int NUM_REGISTERS_ENCBASE = 2; + static const int NUM_STACK_SLOTS_ENCBASE = 3; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 3; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 4; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 2; + static const int REGISTER_DELTA_ENCBASE = 1; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 2; + static const int NUM_EH_CLAUSES_ENCBASE = 3; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_ARM64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) // Encode Frame pointer X29 as zero -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 1 -#define NORMALIZE_CODE_OFFSET(x) ((x)>>2) // Instructions are 4 bytes long -#define DENORMALIZE_CODE_OFFSET(x) ((x)<<2) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define STACK_BASE_REGISTER_ENCBASE 2 // FP encoded as 0, SP as 2. -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding ARM64GcInfoEncoding + +struct ARM64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + // GC Pointers are 8-bytes aligned + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + // All Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // Encode Frame pointer X29 as zero + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x)^29); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x)^29); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + // Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + // FP encoded as 0, SP as 2. + static const int STACK_BASE_REGISTER_ENCBASE = 2; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_LOONGARCH64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 22 ? 0u : 1u) // Encode Frame pointer fp=$22 as zero -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 22u : 3u) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 1 -#define NORMALIZE_CODE_OFFSET(x) ((x)>>2) // Instructions are 4 bytes long -#define DENORMALIZE_CODE_OFFSET(x) ((x)<<2) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -// FP/SP encoded as 0 or 1. -#define STACK_BASE_REGISTER_ENCBASE 2 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding LoongArch64GcInfoEncoding + +struct LoongArch64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + // GC Pointers are 8-bytes aligned + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + // All Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // Encode Frame pointer fp=$22 as zero + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 22 ? 0u : 1u); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 0 ? 22u : 3u); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + // Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + // FP/SP encoded as 0 or 1. + static const int STACK_BASE_REGISTER_ENCBASE = 2; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_RISCV64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 8 ? 0u : 1u) // Encode Frame pointer X8 as zero, sp/x2 as 1 -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 8u : 2u) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 1 -#define NORMALIZE_CODE_OFFSET(x) ((x)>>2) // Instructions are 4 bytes long -#define DENORMALIZE_CODE_OFFSET(x) ((x)<<2) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define STACK_BASE_REGISTER_ENCBASE 2 -// FP encoded as 0, SP as 1 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 +#define TargetGcInfoEncoding RISCV64GcInfoEncoding + +struct RISCV64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + // GC Pointers are 8-bytes aligned + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + // All Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // Encode Frame pointer X8 as zero, sp/x2 as 1 + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 8 ? 0u : 1u); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 0 ? 8u : 2u); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + // Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + static const int STACK_BASE_REGISTER_ENCBASE = 2; + // FP encoded as 0, SP as 1 + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; -#else +#else // defined(TARGET_xxx) #ifndef TARGET_X86 #ifdef PORTABILITY_WARNING @@ -890,55 +904,58 @@ PORTABILITY_WARNING("Please specialize these definitions for your platform!") #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) (x) -#define DENORMALIZE_STACK_SLOT(x) (x) -#define NORMALIZE_CODE_LENGTH(x) (x) -#define DENORMALIZE_CODE_LENGTH(x) (x) -#define NORMALIZE_STACK_BASE_REGISTER(x) (x) -#define DENORMALIZE_STACK_BASE_REGISTER(x) (x) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) (x) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) (x) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) -#define DENORMALIZE_CODE_OFFSET(x) (x) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 6 -#define STACK_BASE_REGISTER_ENCBASE 3 -#define SIZE_OF_STACK_AREA_ENCBASE 6 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 5 -#define NUM_UNTRACKED_SLOTS_ENCBASE 5 -#define NORM_PROLOG_SIZE_ENCBASE 4 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 5 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 5 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE REGISTER_ENCBASE -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 4 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 -#endif +#define TargetGcInfoEncoding X86GcInfoEncoding + +struct X86GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return (x); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return (x); } + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return (x); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return (x); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = false; + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 6; + static const int STACK_BASE_REGISTER_ENCBASE = 3; + static const int SIZE_OF_STACK_AREA_ENCBASE = 6; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 3; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 5; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 5; + static const int NORM_PROLOG_SIZE_ENCBASE = 4; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 5; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 5; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = REGISTER_ENCBASE; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 4; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; + +#endif // defined(TARGET_xxx) + +#ifdef debug_instrumented_return +#define return debug_instrumented_return +#endif // debug_instrumented_return #endif // !__GCINFOTYPES_H__ diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index ca025f62a7ec4d..c62b79a09b3976 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* 4463d6ac-dfcb-4ab0-a941-c53b56089b7c */ - 0x4463d6ac, - 0xdfcb, - 0x4ab0, - {0xa9, 0x41, 0xc5, 0x3b, 0x56, 0x08, 0x9b, 0x7c} +constexpr GUID JITEEVersionIdentifier = { /* 78acb599-d9be-4ea1-8e93-546ec43e0487 */ + 0x78acb599, + 0xd9be, + 0x4ea1, + {0x8e, 0x93, 0x54, 0x6e, 0xc4, 0x3e, 0x04, 0x87} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 38114a9bbfcada..72748e42cbde03 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -92,7 +92,7 @@ DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,METHOD__NIL) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_ALIGN8, JIT_NewArr1,METHOD__NIL) - JITHELPER(CORINFO_HELP_STRCNS, JIT_StrCns, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_STRCNS, NULL, METHOD__STRING__STRCNS) // Object model DYNAMICJITHELPER(CORINFO_HELP_INITCLASS, NULL, METHOD__INITHELPERS__INITCLASS) @@ -150,7 +150,7 @@ // GC support DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper, METHOD__NIL) DYNAMICJITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, METHOD__THREAD__POLLGC) - + JITHELPER(CORINFO_HELP_CHECK_OBJ, JIT_CheckObj, METHOD__NIL) // GC Write barrier support diff --git a/src/coreclr/inc/longfilepathwrappers.h b/src/coreclr/inc/longfilepathwrappers.h index 6407680900dc14..82046987ee6e48 100644 --- a/src/coreclr/inc/longfilepathwrappers.h +++ b/src/coreclr/inc/longfilepathwrappers.h @@ -25,11 +25,6 @@ CreateFileWrapper( _In_opt_ HANDLE hTemplateFile ); -DWORD -GetFileAttributesWrapper( - _In_ LPCWSTR lpFileName - ); - BOOL GetFileAttributesExWrapper( _In_ LPCWSTR lpFileName, diff --git a/src/coreclr/inc/palclr.h b/src/coreclr/inc/palclr.h index c5628a1b9eee6e..410c0a7c06d12c 100644 --- a/src/coreclr/inc/palclr.h +++ b/src/coreclr/inc/palclr.h @@ -48,8 +48,6 @@ #endif // !_MSC_VER #endif // !NOINLINE -#define ANALYZER_NORETURN - #ifdef _MSC_VER #define EMPTY_BASES_DECL __declspec(empty_bases) #else diff --git a/src/coreclr/inc/pedecoder.h b/src/coreclr/inc/pedecoder.h index 057dfa9a25de61..6b13de957bfb93 100644 --- a/src/coreclr/inc/pedecoder.h +++ b/src/coreclr/inc/pedecoder.h @@ -89,6 +89,8 @@ inline CHECK CheckOverflow(RVA value1, COUNT_T value2) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_UNKNOWN #elif defined(TARGET_RISCV64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_RISCV64 +#elif defined(TARGET_WASM) +#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_UNKNOWN #else #error "port me" #endif diff --git a/src/coreclr/inc/regdisp.h b/src/coreclr/inc/regdisp.h index 07d3f1f6d5e057..3aa4be6fd9e60c 100644 --- a/src/coreclr/inc/regdisp.h +++ b/src/coreclr/inc/regdisp.h @@ -345,6 +345,25 @@ inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { return GetSP(display->pCallerContext); } +#elif defined(TARGET_WASM) +struct REGDISPLAY : public REGDISPLAY_BASE { + REGDISPLAY() + { + // Initialize + memset(this, 0, sizeof(REGDISPLAY)); + } +}; + +inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD) +{ +} + +// This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame +inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { + _ASSERTE("IsInCalleesFrames is not implemented on wasm"); + return FALSE; +} + #else // none of the above processors #error "RegDisplay functions are not implemented on this platform." #endif diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 06fdaa5f397510..9534511ef2a99d 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -43,7 +43,7 @@ #define GC_STATS #endif -#if defined(TARGET_X86) || defined(TARGET_ARM) +#if defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_BROWSER) #define USE_LAZY_PREFERRED_RANGE 0 #elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) || defined(TARGET_RISCV64) diff --git a/src/coreclr/inc/targetosarch.h b/src/coreclr/inc/targetosarch.h index 00fe5b70647e7d..217db1de7b6fa3 100644 --- a/src/coreclr/inc/targetosarch.h +++ b/src/coreclr/inc/targetosarch.h @@ -95,6 +95,14 @@ class TargetArchitecture static const bool IsArmArch = false; static const bool IsLoongArch64 = false; static const bool IsRiscV64 = true; +#elif defined(TARGET_WASM) + static const bool IsX86 = false; + static const bool IsX64 = false; + static const bool IsArm64 = false; + static const bool IsArm32 = false; + static const bool IsArmArch = false; + static const bool IsLoongArch64 = false; + static const bool IsRiscV64 = false; #else #error Unknown architecture #endif diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index 9b8e1ee3dfd704..0221afafe08c9b 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -37,6 +37,7 @@ using std::nothrow; #include #include +#include #include #include "clrnt.h" diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index e5d3648306bf23..a301e5d5119d39 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "interpreter.h" -#include "openum.h" - static const StackType g_stackTypeFromInterpType[] = { StackTypeI4, // I1 @@ -15,21 +13,24 @@ static const StackType g_stackTypeFromInterpType[] = StackTypeR4, // R4 StackTypeR8, // R8 StackTypeO, // O - StackTypeVT // VT + StackTypeVT, // VT + StackTypeByRef, // ByRef }; static const InterpType g_interpTypeFromStackType[] = { - InterpTypeI4, // I4, - InterpTypeI8, // I8, - InterpTypeR4, // R4, - InterpTypeR8, // R8, - InterpTypeO, // O, - InterpTypeVT, // VT, - InterpTypeI, // MP, - InterpTypeI, // F + InterpTypeI4, // I4, + InterpTypeI8, // I8, + InterpTypeR4, // R4, + InterpTypeR8, // R8, + InterpTypeO, // O, + InterpTypeVT, // VT, + InterpTypeByRef, // MP, + InterpTypeI, // F }; +static const char *g_stackTypeString[] = { "I4", "I8", "R4", "R8", "O ", "VT", "MP", "F " }; + // FIXME Use specific allocators for their intended purpose // Allocator for data that is kept alive throughout application execution, // being freed only if the associated method gets freed. @@ -45,6 +46,13 @@ void* InterpCompiler::AllocMemPool(size_t numBytes) return malloc(numBytes); } +void* InterpCompiler::AllocMemPool0(size_t numBytes) +{ + void *ptr = AllocMemPool(numBytes); + memset(ptr, 0, numBytes); + return ptr; +} + // Allocator for potentially larger chunks of data, that we might want to free // eagerly, before method is finished compiling, to prevent excessive memory usage. void* InterpCompiler::AllocTemporary(size_t numBytes) @@ -52,6 +60,13 @@ void* InterpCompiler::AllocTemporary(size_t numBytes) return malloc(numBytes); } +void* InterpCompiler::AllocTemporary0(size_t numBytes) +{ + void *ptr = AllocTemporary(numBytes); + memset(ptr, 0, numBytes); + return ptr; +} + void* InterpCompiler::ReallocTemporary(void* ptr, size_t numBytes) { return realloc(ptr, numBytes); @@ -94,7 +109,7 @@ InterpInst* InterpCompiler::NewIns(int opcode, int dataLen) InterpInst *ins = (InterpInst*)AllocMemPool(insSize); memset(ins, 0, insSize); ins->opcode = opcode; - ins->ilOffset = -1; + ins->ilOffset = m_currentILOffset; m_pLastIns = ins; return ins; } @@ -172,7 +187,14 @@ bool InterpCompiler::InsIsNop(InterpInst *ins) int32_t InterpCompiler::GetInsLength(InterpInst *ins) { - return g_interpOpLen[ins->opcode]; + int len = g_interpOpLen[ins->opcode]; + if (len == 0) + { + assert(ins->opcode == INTOP_SWITCH); + len = 3 + ins->data[0]; + } + + return len; } void InterpCompiler::ForEachInsSVar(InterpInst *ins, void *pData, void (InterpCompiler::*callback)(int*, void*)) @@ -186,7 +208,7 @@ void InterpCompiler::ForEachInsSVar(InterpInst *ins, void *pData, void (InterpCo { if (ins->info.pCallInfo && ins->info.pCallInfo->pCallArgs) { int *callArgs = ins->info.pCallInfo->pCallArgs; - while (*callArgs != -1) + while (*callArgs != CALL_ARGS_TERMINATOR) { (this->*callback) (callArgs, pData); callArgs++; @@ -210,14 +232,12 @@ void InterpCompiler::ForEachInsVar(InterpInst *ins, void *pData, void (InterpCom } -InterpBasicBlock* InterpCompiler::AllocBB() +InterpBasicBlock* InterpCompiler::AllocBB(int32_t ilOffset) { InterpBasicBlock *bb = (InterpBasicBlock*)AllocMemPool(sizeof(InterpBasicBlock)); - memset(bb, 0, sizeof(InterpBasicBlock)); - bb->ilOffset = -1; - bb->nativeOffset = -1; - bb->stackHeight = -1; - bb->index = m_BBCount++; + + new (bb) InterpBasicBlock (m_BBCount, ilOffset); + m_BBCount++; return bb; } @@ -227,9 +247,8 @@ InterpBasicBlock* InterpCompiler::GetBB(int32_t ilOffset) if (!bb) { - bb = AllocBB (); + bb = AllocBB(ilOffset); - bb->ilOffset = ilOffset; m_ppOffsetToBB[ilOffset] = bb; } @@ -339,7 +358,103 @@ void InterpCompiler::UnlinkBBs(InterpBasicBlock *from, InterpBasicBlock *to) to->inCount--; } -int32_t InterpCompiler::CreateVarExplicit(InterpType mt, CORINFO_CLASS_HANDLE clsHnd, int size) +// These are moves between vars, operating only on the interpreter stack +int32_t InterpCompiler::InterpGetMovForType(InterpType interpType, bool signExtend) +{ + switch (interpType) + { + case InterpTypeI1: + case InterpTypeU1: + case InterpTypeI2: + case InterpTypeU2: + if (signExtend) + return INTOP_MOV_I4_I1 + interpType; + else + return INTOP_MOV_4; + case InterpTypeI4: + case InterpTypeR4: + return INTOP_MOV_4; + case InterpTypeI8: + case InterpTypeR8: + return INTOP_MOV_8; + case InterpTypeO: + case InterpTypeByRef: + return INTOP_MOV_P; + case InterpTypeVT: + return INTOP_MOV_VT; + default: + assert(0); + } + return -1; +} + +// This method needs to be called when the current basic blocks ends and execution can +// continue into pTargetBB. When the stack state of a basic block is initialized, the vars +// associated with the stack state are set. When another bblock will continue execution +// into this bblock, it will first have to emit moves from the vars in its stack state +// to the vars of the target bblock stack state. +void InterpCompiler::EmitBBEndVarMoves(InterpBasicBlock *pTargetBB) +{ + if (pTargetBB->stackHeight <= 0) + return; + + for (int i = 0; i < pTargetBB->stackHeight; i++) + { + int sVar = m_pStackPointer[i].var; + int dVar = pTargetBB->pStackState[i].var; + if (sVar != dVar) + { + InterpType interpType = m_pVars[sVar].interpType; + int32_t movOp = InterpGetMovForType(interpType, false); + + AddIns(movOp); + m_pLastIns->SetSVar(m_pStackPointer[i].var); + m_pLastIns->SetDVar(pTargetBB->pStackState[i].var); + + if (interpType == InterpTypeVT) + { + assert(m_pVars[sVar].size == m_pVars[dVar].size); + m_pLastIns->data[0] = m_pVars[sVar].size; + } + } + } +} + +static void MergeStackTypeInfo(StackInfo *pState1, StackInfo *pState2, int len) +{ + // Discard type information if we have type conflicts for stack contents + for (int i = 0; i < len; i++) + { + if (pState1[i].clsHnd != pState2[i].clsHnd) + { + pState1[i].clsHnd = NULL; + pState2[i].clsHnd = NULL; + } + } +} + +// Initializes stack state at entry to bb, based on the current stack state +void InterpCompiler::InitBBStackState(InterpBasicBlock *pBB) +{ + if (pBB->stackHeight >= 0) + { + // Already initialized, update stack information + MergeStackTypeInfo(m_pStackBase, pBB->pStackState, pBB->stackHeight); + } + else + { + pBB->stackHeight = (int32_t)(m_pStackPointer - m_pStackBase); + if (pBB->stackHeight > 0) + { + int size = pBB->stackHeight * sizeof (StackInfo); + pBB->pStackState = (StackInfo*)AllocMemPool(size); + memcpy (pBB->pStackState, m_pStackBase, size); + } + } +} + + +int32_t InterpCompiler::CreateVarExplicit(InterpType interpType, CORINFO_CLASS_HANDLE clsHnd, int size) { if (m_varsSize == m_varsCapacity) { m_varsCapacity *= 2; @@ -349,12 +464,7 @@ int32_t InterpCompiler::CreateVarExplicit(InterpType mt, CORINFO_CLASS_HANDLE cl } InterpVar *var = &m_pVars[m_varsSize]; - var->mt = mt; - var->clsHnd = clsHnd; - var->size = size; - var->indirects = 0; - var->offset = -1; - var->liveStart = -1; + new (var) InterpVar(interpType, clsHnd, size); m_varsSize++; return m_varsSize - 1; @@ -375,7 +485,25 @@ void InterpCompiler::EnsureStack(int additional) do \ { \ if (!CheckStackHelper (n)) \ - goto exit; \ + goto exit_bad_code; \ + } while (0) + +#define CHECK_STACK_RET_VOID(n) \ + do { \ + if (!CheckStackHelper(n)) \ + return; \ + } while (0) + +#define CHECK_STACK_RET(n, ret) \ + do { \ + if (!CheckStackHelper(n)) \ + return ret; \ + } while (0) + +#define INVALID_CODE_RET_VOID \ + do { \ + m_hasInvalidCode = true; \ + return; \ } while (0) bool InterpCompiler::CheckStackHelper(int n) @@ -400,12 +528,17 @@ void InterpCompiler::PushTypeExplicit(StackType stackType, CORINFO_CLASS_HANDLE m_pStackPointer++; } -void InterpCompiler::PushType(StackType stackType, CORINFO_CLASS_HANDLE clsHnd) +void InterpCompiler::PushStackType(StackType stackType, CORINFO_CLASS_HANDLE clsHnd) { // We don't really care about the exact size for non-valuetypes PushTypeExplicit(stackType, clsHnd, INTERP_STACK_SLOT_SIZE); } +void InterpCompiler::PushInterpType(InterpType interpType, CORINFO_CLASS_HANDLE clsHnd) +{ + PushStackType(g_stackTypeFromInterpType[interpType], clsHnd); +} + void InterpCompiler::PushTypeVT(CORINFO_CLASS_HANDLE clsHnd, int size) { PushTypeExplicit(StackTypeVT, clsHnd, size); @@ -426,42 +559,109 @@ int32_t InterpCompiler::ComputeCodeSize() return codeSize; } -int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins) +int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins, TArray *relocs) { int32_t opcode = ins->opcode; int32_t *startIp = ip; *ip++ = opcode; - if (g_interpOpDVars[opcode]) - *ip++ = m_pVars[ins->dVar].offset; - - if (g_interpOpSVars[opcode]) + if (opcode == INTOP_SWITCH) + { + int32_t numLabels = ins->data [0]; + *ip++ = m_pVars[ins->sVars[0]].offset; + *ip++ = numLabels; + // Add relocation for each label + for (int32_t i = 0; i < numLabels; i++) + { + Reloc *reloc = (Reloc*)AllocMemPool(sizeof(Reloc)); + new (reloc) Reloc(RelocSwitch, (int32_t)(ip - m_pMethodCode), ins->info.ppTargetBBTable[i], 0); + relocs->Add(reloc); + *ip++ = (int32_t)0xdeadbeef; + } + } + else if (InterpOpIsUncondBranch(opcode) || InterpOpIsCondBranch(opcode)) { + int32_t brBaseOffset = (int32_t)(startIp - m_pMethodCode); for (int i = 0; i < g_interpOpSVars[opcode]; i++) + *ip++ = m_pVars[ins->sVars[i]].offset; + + if (ins->info.pTargetBB->nativeOffset >= 0) { - if (ins->sVars[i] == CALL_ARGS_SVAR) - { - *ip++ = m_paramAreaOffset + ins->info.pCallInfo->callOffset; - } - else + *ip++ = ins->info.pTargetBB->nativeOffset - brBaseOffset; + } + else if (opcode == INTOP_BR && ins->info.pTargetBB == m_pCBB->pNextBB) + { + // Ignore branch to the next basic block. Revert the added INTOP_BR. + ip--; + } + else + { + // We don't know yet the IR offset of the target, add a reloc instead + Reloc *reloc = (Reloc*)AllocMemPool(sizeof(Reloc)); + new (reloc) Reloc(RelocLongBranch, brBaseOffset, ins->info.pTargetBB, g_interpOpSVars[opcode]); + relocs->Add(reloc); + *ip++ = (int32_t)0xdeadbeef; + } + } + else + { + // Default code emit for an instruction. The opcode was already emitted above. + // We emit the offset for the instruction destination, then for every single source + // variable we emit another offset. Finally, we will emit any additional data needed + // by the instruction. + if (g_interpOpDVars[opcode]) + *ip++ = m_pVars[ins->dVar].offset; + + if (g_interpOpSVars[opcode]) + { + for (int i = 0; i < g_interpOpSVars[opcode]; i++) { - *ip++ = m_pVars[ins->sVars[i]].offset; + if (ins->sVars[i] == CALL_ARGS_SVAR) + { + *ip++ = m_paramAreaOffset + ins->info.pCallInfo->callOffset; + } + else + { + *ip++ = m_pVars[ins->sVars[i]].offset; + } } } - } - int left = GetInsLength(ins) - (int32_t)(ip - startIp); - // Emit the rest of the data - for (int i = 0; i < left; i++) - *ip++ = ins->data[i]; + int left = GetInsLength(ins) - (int32_t)(ip - startIp); + // Emit the rest of the data + for (int i = 0; i < left; i++) + *ip++ = ins->data[i]; + } return ip; } +void InterpCompiler::PatchRelocations(TArray *relocs) +{ + int32_t size = relocs->GetSize(); + + for (int32_t i = 0; i < size; i++) + { + Reloc *reloc = relocs->Get(i); + int32_t offset = reloc->pTargetBB->nativeOffset - reloc->offset; + int32_t *pSlot = NULL; + + if (reloc->type == RelocLongBranch) + pSlot = m_pMethodCode + reloc->offset + reloc->skip + 1; + else if (reloc->type == RelocSwitch) + pSlot = m_pMethodCode + reloc->offset; + else + assert(0); + + assert(*pSlot == (int32_t)0xdeadbeef); + *pSlot = offset; + } +} void InterpCompiler::EmitCode() { + TArray relocs; int32_t codeSize = ComputeCodeSize(); m_pMethodCode = (int32_t*)AllocMethodData(codeSize * sizeof(int32_t)); @@ -469,117 +669,1833 @@ void InterpCompiler::EmitCode() for (InterpBasicBlock *bb = m_pEntryBB; bb != NULL; bb = bb->pNextBB) { bb->nativeOffset = (int32_t)(ip - m_pMethodCode); + m_pCBB = bb; for (InterpInst *ins = bb->pFirstIns; ins != NULL; ins = ins->pNext) { - ip = EmitCodeIns(ip, ins); + ip = EmitCodeIns(ip, ins, &relocs); } } - m_MethodCodeSize = (int32_t)(ip - m_pMethodCode); + m_methodCodeSize = (int32_t)(ip - m_pMethodCode); + + PatchRelocations(&relocs); } InterpMethod* InterpCompiler::CreateInterpMethod() { - InterpMethod *pMethod = new InterpMethod(m_methodHnd, m_totalVarsStackSize); + int numDataItems = m_dataItems.GetSize(); + void **pDataItems = (void**)AllocMethodData(numDataItems * sizeof(void*)); + + for (int i = 0; i < numDataItems; i++) + pDataItems[i] = m_dataItems.Get(i); + + InterpMethod *pMethod = new InterpMethod(m_methodHnd, m_totalVarsStackSize, pDataItems); return pMethod; } int32_t* InterpCompiler::GetCode(int32_t *pCodeSize) { - *pCodeSize = m_MethodCodeSize; + *pCodeSize = m_methodCodeSize; return m_pMethodCode; } InterpCompiler::InterpCompiler(COMP_HANDLE compHnd, - CORINFO_METHOD_INFO* methodInfo) + CORINFO_METHOD_INFO* methodInfo, + bool verbose) { m_methodHnd = methodInfo->ftn; + m_compScopeHnd = methodInfo->scope; m_compHnd = compHnd; m_methodInfo = methodInfo; + m_verbose = verbose; } InterpMethod* InterpCompiler::CompileMethod() { +#ifdef DEBUG + if (m_verbose) + { + printf("Interpreter compile method "); + PrintMethodName(m_methodHnd); + printf("\n"); + } +#endif + + CreateILVars(); + GenerateCode(m_methodInfo); +#ifdef DEBUG + if (m_verbose) + { + printf("\nUnoptimized IR:\n"); + PrintCode(); + } +#endif + AllocOffsets(); EmitCode(); +#ifdef DEBUG + if (m_verbose) + { + printf("\nCompiled method: "); + PrintMethodName(m_methodHnd); + printf("\nLocals size %d\n", m_totalVarsStackSize); + PrintCompiledCode(); + printf("\n"); + } +#endif + return CreateInterpMethod(); } -int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) +// Adds a conversion instruction for the value pointed to by sp, also updating the stack information +void InterpCompiler::EmitConv(StackInfo *sp, InterpInst *prevIns, StackType type, InterpOpcode convOp) { - uint8_t *ip = methodInfo->ILCode; - uint8_t *codeEnd = ip + methodInfo->ILCodeSize; + InterpInst *newInst; + if (prevIns) + newInst = InsertIns(prevIns, convOp); + else + newInst = AddIns(convOp); - m_ppOffsetToBB = (InterpBasicBlock**)AllocMemPool(sizeof(InterpBasicBlock*) * (methodInfo->ILCodeSize + 1)); - m_stackCapacity = methodInfo->maxStack + 1; - m_pStackBase = m_pStackPointer = (StackInfo*)AllocTemporary(sizeof(StackInfo) * m_stackCapacity); + newInst->SetSVar(sp->var); + new (sp) StackInfo(type); + int32_t var = CreateVarExplicit(g_interpTypeFromStackType[type], NULL, INTERP_STACK_SLOT_SIZE); + sp->var = var; + newInst->SetDVar(var); +} + +static InterpType GetInterpType(CorInfoType corInfoType) +{ + switch (corInfoType) + { + case CORINFO_TYPE_BYTE: + return InterpTypeI1; + case CORINFO_TYPE_UBYTE: + case CORINFO_TYPE_BOOL: + return InterpTypeU1; + case CORINFO_TYPE_CHAR: + case CORINFO_TYPE_USHORT: + return InterpTypeU2; + case CORINFO_TYPE_SHORT: + return InterpTypeI2; + case CORINFO_TYPE_INT: + case CORINFO_TYPE_UINT: + return InterpTypeI4; + case CORINFO_TYPE_LONG: + case CORINFO_TYPE_ULONG: + return InterpTypeI8; + case CORINFO_TYPE_NATIVEINT: + case CORINFO_TYPE_NATIVEUINT: + return InterpTypeI; + case CORINFO_TYPE_FLOAT: + return InterpTypeR4; + case CORINFO_TYPE_DOUBLE: + return InterpTypeR8; + case CORINFO_TYPE_STRING: + case CORINFO_TYPE_CLASS: + return InterpTypeO; + case CORINFO_TYPE_PTR: + return InterpTypeI; + case CORINFO_TYPE_BYREF: + return InterpTypeByRef; + case CORINFO_TYPE_VALUECLASS: + case CORINFO_TYPE_REFANY: + return InterpTypeVT; + case CORINFO_TYPE_VOID: + return InterpTypeVoid; + default: + assert(0); + break; + } + return InterpTypeVoid; +} + +int32_t InterpCompiler::GetInterpTypeStackSize(CORINFO_CLASS_HANDLE clsHnd, InterpType interpType, int32_t *pAlign) +{ + int32_t size, align; + if (interpType == InterpTypeVT) + { + size = m_compHnd->getClassSize(clsHnd); + align = m_compHnd->getClassAlignmentRequirement(clsHnd); + + assert(align <= INTERP_STACK_ALIGNMENT); + + // All vars are stored at 8 byte aligned offsets + if (align < INTERP_STACK_SLOT_SIZE) + align = INTERP_STACK_SLOT_SIZE; + } + else + { + size = INTERP_STACK_SLOT_SIZE; // not really + align = INTERP_STACK_SLOT_SIZE; + } + *pAlign = align; + return size; +} + + +void InterpCompiler::CreateILVars() +{ + bool hasThis = m_methodInfo->args.hasThis(); + int32_t offset, size, align; + int numArgs = hasThis + m_methodInfo->args.numArgs; + int numILLocals = m_methodInfo->locals.numArgs; + int numILVars = numArgs + numILLocals; + + // add some starting extra space for new vars + m_varsCapacity = numILVars + 64; + m_pVars = (InterpVar*)AllocTemporary0(m_varsCapacity * sizeof (InterpVar)); + m_varsSize = numILVars; + + offset = 0; + + INTERP_DUMP("\nCreate IL Vars:\n"); + + CORINFO_ARG_LIST_HANDLE sigArg = m_methodInfo->args.args; + for (int i = 0; i < numArgs; i++) { + InterpType interpType; + CORINFO_CLASS_HANDLE argClass; + if (hasThis && i == 0) + { + argClass = m_compHnd->getMethodClass(m_methodInfo->ftn); + if (m_compHnd->isValueClass(argClass)) + interpType = InterpTypeByRef; + else + interpType = InterpTypeO; + } + else + { + CorInfoType argCorType; + argCorType = strip(m_compHnd->getArgType(&m_methodInfo->args, sigArg, &argClass)); + interpType = GetInterpType(argCorType); + sigArg = m_compHnd->getArgNext(sigArg); + } + size = GetInterpTypeStackSize(argClass, interpType, &align); + + new (&m_pVars[i]) InterpVar(interpType, argClass, size); + + m_pVars[i].global = true; + m_pVars[i].ILGlobal = true; + m_pVars[i].size = size; + offset = ALIGN_UP_TO(offset, align); + m_pVars[i].offset = offset; + INTERP_DUMP("alloc arg var %d to offset %d\n", i, offset); + offset += size; + } + + offset = ALIGN_UP_TO(offset, INTERP_STACK_ALIGNMENT); + + sigArg = m_methodInfo->locals.args; + m_ILLocalsOffset = offset; + for (int i = 0; i < numILLocals; i++) { + int index = numArgs + i; + InterpType interpType; + CORINFO_CLASS_HANDLE argClass; + + CorInfoType argCorType = strip(m_compHnd->getArgType(&m_methodInfo->locals, sigArg, &argClass)); + interpType = GetInterpType(argCorType); + size = GetInterpTypeStackSize(argClass, interpType, &align); + + new (&m_pVars[index]) InterpVar(interpType, argClass, size); + + m_pVars[index].global = true; + m_pVars[index].ILGlobal = true; + offset = ALIGN_UP_TO(offset, align); + m_pVars[index].offset = offset; + INTERP_DUMP("alloc local var %d to offset %d\n", index, offset); + offset += size; + sigArg = m_compHnd->getArgNext(sigArg); + } + offset = ALIGN_UP_TO(offset, INTERP_STACK_ALIGNMENT); + + m_ILLocalsSize = offset - m_ILLocalsOffset; + m_totalVarsStackSize = offset; +} - m_pCBB = m_pEntryBB = AllocBB(); +bool InterpCompiler::CreateBasicBlocks(CORINFO_METHOD_INFO* methodInfo) +{ + int32_t codeSize = methodInfo->ILCodeSize; + uint8_t *codeStart = methodInfo->ILCode; + uint8_t *codeEnd = codeStart + codeSize; + const uint8_t *ip = codeStart; + + m_ppOffsetToBB = (InterpBasicBlock**)AllocMemPool0(sizeof(InterpBasicBlock*) * (methodInfo->ILCodeSize + 1)); + GetBB(0); + + for (unsigned int i = 0; i < methodInfo->EHcount; i++) + { + CORINFO_EH_CLAUSE clause; + m_compHnd->getEHinfo(methodInfo->ftn, i, &clause); + + if ((codeStart + clause.TryOffset) > codeEnd || + (codeStart + clause.TryOffset + clause.TryLength) > codeEnd) + { + return false; + } + GetBB(clause.TryOffset); + + if ((codeStart + clause.HandlerOffset) > codeEnd || + (codeStart + clause.HandlerOffset + clause.HandlerLength) > codeEnd) + { + return false; + } + GetBB(clause.HandlerOffset); + + if (clause.Flags == CORINFO_EH_CLAUSE_FILTER) + { + if ((codeStart + clause.FilterOffset) > codeEnd) + return false; + GetBB(clause.FilterOffset); + } + } while (ip < codeEnd) { - uint8_t opcode = *ip; - switch (opcode) + int32_t insOffset = (int32_t)(ip - codeStart); + OPCODE opcode = CEEDecodeOpcode(&ip); + OPCODE_FORMAT opArgs = g_CEEOpArgs[opcode]; + int32_t target; + + switch (opArgs) { - case CEE_NOP: - ip++; - break; - case CEE_LDC_I4_M1: - case CEE_LDC_I4_0: - case CEE_LDC_I4_1: - case CEE_LDC_I4_2: - case CEE_LDC_I4_3: - case CEE_LDC_I4_4: - case CEE_LDC_I4_5: - case CEE_LDC_I4_6: - case CEE_LDC_I4_7: - case CEE_LDC_I4_8: - AddIns(INTOP_LDC_I4); - m_pLastIns->data[0] = opcode - CEE_LDC_I4_0; - PushType(StackTypeI4, NULL); - m_pLastIns->SetDVar(m_pStackPointer[-1].var); - ip++; - break; - case CEE_LDC_I4_S: - AddIns(INTOP_LDC_I4); - m_pLastIns->data[0] = (int8_t)ip[1]; - PushType(StackTypeI4, NULL); - m_pLastIns->SetDVar(m_pStackPointer[-1].var); - ip += 2; - break; - case CEE_RET: + case InlineNone: + ip++; + break; + case InlineString: + case InlineType: + case InlineField: + case InlineMethod: + case InlineTok: + case InlineSig: + case ShortInlineR: + case InlineI: + ip += 5; + break; + case InlineVar: + ip += 3; + break; + case ShortInlineVar: + case ShortInlineI: + ip += 2; + break; + case ShortInlineBrTarget: + target = insOffset + 2 + (int8_t)ip [1]; + if (target >= codeSize) + return false; + GetBB(target); + ip += 2; + GetBB((int32_t)(ip - codeStart)); + break; + case InlineBrTarget: + target = insOffset + 5 + getI4LittleEndian(ip + 1); + if (target >= codeSize) + return false; + GetBB(target); + ip += 5; + GetBB((int32_t)(ip - codeStart)); + break; + case InlineSwitch: { + uint32_t n = getI4LittleEndian(ip + 1); + ip += 5; + insOffset += 5 + 4 * n; + target = insOffset; + if (target >= codeSize) + return false; + GetBB(target); + for (uint32_t i = 0; i < n; i++) { - CORINFO_SIG_INFO sig = methodInfo->args; - if (sig.retType == CORINFO_TYPE_VOID) - { - AddIns(INTOP_RET_VOID); - } - else if (sig.retType == CORINFO_TYPE_INT) - { - CHECK_STACK(1); - AddIns(INTOP_RET); - m_pStackPointer--; - m_pLastIns->SetSVar(m_pStackPointer[0].var); - } - else - { - // FIXME - assert(0); - } - ip++; - break; + target = insOffset + getI4LittleEndian(ip); + if (target >= codeSize) + return false; + GetBB(target); + ip += 4; } - default: - assert(0); - break; + GetBB((int32_t)(ip - codeStart)); + break; + } + case InlineR: + case InlineI8: + ip += 9; + break; + default: + assert(0); } + if (opcode == CEE_THROW || opcode == CEE_ENDFINALLY || opcode == CEE_RETHROW) + GetBB((int32_t)(ip - codeStart)); } -exit: - return CORJIT_OK; + return true; +} + +// ilOffset represents relative branch offset +void InterpCompiler::EmitBranch(InterpOpcode opcode, int32_t ilOffset) +{ + int32_t target = (int32_t)(m_ip - m_pILCode) + ilOffset; + if (target < 0 || target >= m_ILCodeSize) + assert(0); + + InterpBasicBlock *pTargetBB = m_ppOffsetToBB[target]; + assert(pTargetBB != NULL); + + EmitBBEndVarMoves(pTargetBB); + InitBBStackState(pTargetBB); + + AddIns(opcode); + m_pLastIns->info.pTargetBB = pTargetBB; +} + +void InterpCompiler::EmitOneArgBranch(InterpOpcode opcode, int32_t ilOffset, int insSize) +{ + CHECK_STACK_RET_VOID(1); + StackType argType = (m_pStackPointer[-1].type == StackTypeO || m_pStackPointer[-1].type == StackTypeByRef) ? StackTypeI : m_pStackPointer[-1].type; + // offset the opcode to obtain the type specific I4/I8/R4/R8 variant. + InterpOpcode opcodeArgType = (InterpOpcode)(opcode + argType - StackTypeI4); + m_pStackPointer--; + if (ilOffset) + { + EmitBranch(opcodeArgType, ilOffset + insSize); + m_pLastIns->SetSVar(m_pStackPointer[0].var); + } + else + { + AddIns(INTOP_NOP); + } +} + +void InterpCompiler::EmitTwoArgBranch(InterpOpcode opcode, int32_t ilOffset, int insSize) +{ + CHECK_STACK_RET_VOID(2); + StackType argType1 = (m_pStackPointer[-1].type == StackTypeO || m_pStackPointer[-1].type == StackTypeByRef) ? StackTypeI : m_pStackPointer[-1].type; + StackType argType2 = (m_pStackPointer[-2].type == StackTypeO || m_pStackPointer[-2].type == StackTypeByRef) ? StackTypeI : m_pStackPointer[-2].type; + + // Since branch opcodes only compare args of the same type, handle implicit conversions before + // emitting the conditional branch + if (argType1 == StackTypeI4 && argType2 == StackTypeI8) + { + EmitConv(m_pStackPointer - 1, m_pLastIns, StackTypeI8, INTOP_CONV_I8_I4); + argType1 = StackTypeI8; + } + else if (argType1 == StackTypeI8 && argType2 == StackTypeI4) + { + EmitConv(m_pStackPointer - 2, m_pLastIns, StackTypeI8, INTOP_CONV_I8_I4); + } + else if (argType1 == StackTypeR4 && argType2 == StackTypeR8) + { + EmitConv(m_pStackPointer - 1, m_pLastIns, StackTypeR8, INTOP_CONV_R8_R4); + argType1 = StackTypeR8; + } + else if (argType1 == StackTypeR8 && argType2 == StackTypeR4) + { + EmitConv(m_pStackPointer - 2, m_pLastIns, StackTypeR8, INTOP_CONV_R8_R4); + } + else if (argType1 != argType2) + { + m_hasInvalidCode = true; + return; + } + + // offset the opcode to obtain the type specific I4/I8/R4/R8 variant. + InterpOpcode opcodeArgType = (InterpOpcode)(opcode + argType1 - StackTypeI4); + m_pStackPointer -= 2; + + if (ilOffset) + { + EmitBranch(opcodeArgType, ilOffset + insSize); + m_pLastIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var); + } + else + { + AddIns(INTOP_NOP); + } +} + + +void InterpCompiler::EmitLoadVar(int32_t var) +{ + InterpType interpType = m_pVars[var].interpType; + int32_t size = m_pVars[var].size; + CORINFO_CLASS_HANDLE clsHnd = m_pVars[var].clsHnd; + + if (interpType == InterpTypeVT) + PushTypeVT(clsHnd, size); + else + PushInterpType(interpType, clsHnd); + + AddIns(InterpGetMovForType(interpType, true)); + m_pLastIns->SetSVar(var); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + if (interpType == InterpTypeVT) + m_pLastIns->data[0] = size; +} + +void InterpCompiler::EmitStoreVar(int32_t var) +{ + InterpType interpType = m_pVars[var].interpType; + CHECK_STACK_RET_VOID(1); + +#ifdef TARGET_64BIT + // nint and int32 can be used interchangeably. Add implicit conversions. + if (m_pStackPointer[-1].type == StackTypeI4 && g_stackTypeFromInterpType[interpType] == StackTypeI8) + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_I4); +#endif + if (m_pStackPointer[-1].type == StackTypeR4 && g_stackTypeFromInterpType[interpType] == StackTypeR8) + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_R4); + else if (m_pStackPointer[-1].type == StackTypeR8 && g_stackTypeFromInterpType[interpType] == StackTypeR4) + EmitConv(m_pStackPointer - 1, NULL, StackTypeR4, INTOP_CONV_R4_R8); + + m_pStackPointer--; + AddIns(InterpGetMovForType(interpType, false)); + m_pLastIns->SetSVar(m_pStackPointer[0].var); + m_pLastIns->SetDVar(var); + if (interpType == InterpTypeVT) + m_pLastIns->data[0] = m_pVars[var].size; +} + +void InterpCompiler::EmitBinaryArithmeticOp(int32_t opBase) +{ + CHECK_STACK_RET_VOID(2); + StackType type1 = m_pStackPointer[-2].type; + StackType type2 = m_pStackPointer[-1].type; + + StackType typeRes; + + if (opBase == INTOP_ADD_I4 && (type1 == StackTypeByRef || type2 == StackTypeByRef)) + { + if (type1 == type2) + INVALID_CODE_RET_VOID; + if (type1 == StackTypeByRef) + { + if (type2 == StackTypeI4) + { +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_I4); + type2 = StackTypeI8; +#endif + typeRes = StackTypeByRef; + } + else if (type2 == StackTypeI) + { + typeRes = StackTypeByRef; + } + else + { + INVALID_CODE_RET_VOID; + } + } + else + { + // type2 == StackTypeByRef + if (type1 == StackTypeI4) + { +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 2, NULL, StackTypeI8, INTOP_CONV_I8_I4); + type1 = StackTypeI8; +#endif + typeRes = StackTypeByRef; + } + else if (type1 == StackTypeI) + { + typeRes = StackTypeByRef; + } + else + { + INVALID_CODE_RET_VOID; + } + } + } + else if (opBase == INTOP_SUB_I4 && type1 == StackTypeByRef) + { + if (type2 == StackTypeI4) + { +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_I4); + type2 = StackTypeI8; +#endif + typeRes = StackTypeByRef; + } + else if (type2 == StackTypeI) + { + typeRes = StackTypeByRef; + } + else if (type2 == StackTypeByRef) + { + typeRes = StackTypeI; + } + else + { + INVALID_CODE_RET_VOID; + } + } + else + { +#if SIZEOF_VOID_P == 8 + if (type1 == StackTypeI8 && type2 == StackTypeI4) + { + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_I4); + type2 = StackTypeI8; + } + else if (type1 == StackTypeI4 && type2 == StackTypeI8) + { + EmitConv(m_pStackPointer - 2, NULL, StackTypeI8, INTOP_CONV_I8_I4); + type1 = StackTypeI8; + } +#endif + if (type1 == StackTypeR8 && type2 == StackTypeR4) + { + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_R4); + type2 = StackTypeR8; + } + else if (type1 == StackTypeR4 && type2 == StackTypeR8) + { + EmitConv(m_pStackPointer - 2, NULL, StackTypeR8, INTOP_CONV_R8_R4); + type1 = StackTypeR8; + } + if (type1 != type2) + INVALID_CODE_RET_VOID; + + typeRes = type1; + } + + // The argument opcode is for the base _I4 instruction. Depending on the type of the result + // we compute the specific variant, _I4/_I8/_R4 or R8. + int32_t typeOffset = ((typeRes == StackTypeByRef) ? StackTypeI : typeRes) - StackTypeI4; + int32_t finalOpcode = opBase + typeOffset; + + m_pStackPointer -= 2; + AddIns(finalOpcode); + m_pLastIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var); + PushStackType(typeRes, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); +} + +void InterpCompiler::EmitUnaryArithmeticOp(int32_t opBase) +{ + CHECK_STACK_RET_VOID(1); + StackType stackType = m_pStackPointer[-1].type; + int32_t finalOpcode = opBase + (stackType - StackTypeI4); + + if (stackType == StackTypeByRef || stackType == StackTypeO) + INVALID_CODE_RET_VOID; + if (opBase == INTOP_NOT_I4 && (stackType != StackTypeI4 && stackType != StackTypeI8)) + INVALID_CODE_RET_VOID; + + m_pStackPointer--; + AddIns(finalOpcode); + m_pLastIns->SetSVar(m_pStackPointer[0].var); + PushStackType(stackType, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); +} + +void InterpCompiler::EmitShiftOp(int32_t opBase) +{ + CHECK_STACK_RET_VOID(2); + StackType stackType = m_pStackPointer[-2].type; + StackType shiftAmountType = m_pStackPointer[-1].type; + int32_t typeOffset = stackType - StackTypeI4; + int32_t finalOpcode = opBase + typeOffset; + + if ((stackType != StackTypeI4 && stackType != StackTypeI8) || + (shiftAmountType != StackTypeI4 && shiftAmountType != StackTypeI)) + INVALID_CODE_RET_VOID; + + m_pStackPointer -= 2; + AddIns(finalOpcode); + m_pLastIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var); + PushStackType(stackType, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); +} + +void InterpCompiler::EmitCompareOp(int32_t opBase) +{ + CHECK_STACK_RET_VOID(2); + if (m_pStackPointer[-1].type == StackTypeO || m_pStackPointer[-1].type == StackTypeByRef) + { + AddIns(opBase + StackTypeI - StackTypeI4); + } + else + { + if (m_pStackPointer[-1].type == StackTypeR4 && m_pStackPointer[-2].type == StackTypeR8) + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_R4); + if (m_pStackPointer[-1].type == StackTypeR8 && m_pStackPointer[-2].type == StackTypeR4) + EmitConv(m_pStackPointer - 2, NULL, StackTypeR8, INTOP_CONV_R8_R4); + AddIns(opBase + m_pStackPointer[-1].type - StackTypeI4); + } + m_pStackPointer -= 2; + m_pLastIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var); + PushStackType(StackTypeI4, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); +} + +int32_t InterpCompiler::GetDataItemIndex(void *data) +{ + int32_t index = m_dataItems.Find(data); + if (index != -1) + return index; + + return m_dataItems.Add(data); +} + +int32_t InterpCompiler::GetMethodDataItemIndex(CORINFO_METHOD_HANDLE mHandle) +{ + size_t data = (size_t)mHandle | INTERP_METHOD_DESC_TAG; + return GetDataItemIndex((void*)data); +} + +bool InterpCompiler::EmitCallIntrinsics(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO sig) +{ + const char *className = NULL; + const char *namespaceName = NULL; + const char *methodName = m_compHnd->getMethodNameFromMetadata(method, &className, &namespaceName, NULL, 0); + int32_t opcode = -1; + + if (namespaceName && !strcmp(namespaceName, "System")) + { + if (className && !strcmp(className, "Environment")) + { + if (methodName && !strcmp(methodName, "FailFast")) + opcode = INTOP_FAILFAST; // to be removed, not really an intrisic + } + } + + if (opcode != -1) + { + AddIns(opcode); + return true; + } + + return false; +} + +void InterpCompiler::EmitCall(CORINFO_CLASS_HANDLE constrainedClass, bool readonly, bool tailcall) +{ + uint32_t token = getU4LittleEndian(m_ip + 1); + CORINFO_RESOLVED_TOKEN resolvedToken; + + resolvedToken.tokenScope = m_compScopeHnd; + resolvedToken.tokenContext = METHOD_BEING_COMPILED_CONTEXT(); + resolvedToken.token = token; + resolvedToken.tokenType = CORINFO_TOKENKIND_Method; + m_compHnd->resolveToken(&resolvedToken); + + CORINFO_METHOD_HANDLE targetMethod = resolvedToken.hMethod; + + CORINFO_SIG_INFO targetSignature; + m_compHnd->getMethodSig(targetMethod, &targetSignature); + + if (EmitCallIntrinsics(targetMethod, targetSignature)) + { + m_ip += 5; + return; + } + + // Process sVars + int numArgs = targetSignature.numArgs + targetSignature.hasThis(); + m_pStackPointer -= numArgs; + + int *callArgs = (int*) AllocMemPool((numArgs + 1) * sizeof(int)); + for (int i = 0; i < numArgs; i++) + callArgs[i] = m_pStackPointer [i].var; + callArgs[numArgs] = -1; + + // Process dVar + int32_t dVar; + if (targetSignature.retType != CORINFO_TYPE_VOID) + { + InterpType interpType = GetInterpType(targetSignature.retType); + + if (interpType == InterpTypeVT) + { + int32_t size = m_compHnd->getClassSize(targetSignature.retTypeClass); + PushTypeVT(targetSignature.retTypeClass, size); + } + else + { + PushInterpType(interpType, NULL); + } + dVar = m_pStackPointer[-1].var; + } + else + { + // Create a new dummy var to serve as the dVar of the call + // FIXME Consider adding special dVar type (ex -1), that is + // resolved to null offset. The opcode shouldn't really write to it + PushStackType(StackTypeI4, NULL); + m_pStackPointer--; + dVar = m_pStackPointer[0].var; + } + + // Emit call instruction + AddIns(INTOP_CALL); + m_pLastIns->SetDVar(dVar); + m_pLastIns->SetSVar(CALL_ARGS_SVAR); + m_pLastIns->data[0] = GetMethodDataItemIndex(targetMethod); + + m_pLastIns->flags |= INTERP_INST_FLAG_CALL; + m_pLastIns->info.pCallInfo = (InterpCallInfo*)AllocMemPool0(sizeof (InterpCallInfo)); + m_pLastIns->info.pCallInfo->pCallArgs = callArgs; + + m_ip += 5; +} + +int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) +{ + bool readonly = false; + bool tailcall = false; + CORINFO_CLASS_HANDLE constrainedClass = NULL; + uint8_t *codeEnd; + int numArgs = m_methodInfo->args.hasThis() + m_methodInfo->args.numArgs; + bool emittedBBlocks, linkBBlocks, needsRetryEmit; + m_ip = m_pILCode = methodInfo->ILCode; + m_ILCodeSize = (int32_t)methodInfo->ILCodeSize; + + m_stackCapacity = methodInfo->maxStack + 1; + m_pStackBase = m_pStackPointer = (StackInfo*)AllocTemporary(sizeof(StackInfo) * m_stackCapacity); + + m_pEntryBB = AllocBB(0); + m_pEntryBB->emitState = BBStateEmitting; + m_pEntryBB->stackHeight = 0; + m_pCBB = m_pEntryBB; + + if (!CreateBasicBlocks(methodInfo)) + { + m_hasInvalidCode = true; + goto exit_bad_code; + } + + codeEnd = m_ip + m_ILCodeSize; + + linkBBlocks = true; + needsRetryEmit = false; +retry_emit: + emittedBBlocks = false; + while (m_ip < codeEnd) + { + // Check here for every opcode to avoid code bloat + if (m_hasInvalidCode) + goto exit_bad_code; + + int32_t insOffset = (int32_t)(m_ip - m_pILCode); + m_currentILOffset = insOffset; + + InterpBasicBlock *pNewBB = m_ppOffsetToBB[insOffset]; + if (pNewBB != NULL && m_pCBB != pNewBB) + { + INTERP_DUMP("BB%d (IL_%04x):\n", pNewBB->index, pNewBB->ilOffset); + // If we were emitting into previous bblock, we are finished now + if (m_pCBB->emitState == BBStateEmitting) + m_pCBB->emitState = BBStateEmitted; + // If the new bblock was already emitted, skip its instructions + if (pNewBB->emitState == BBStateEmitted) + { + if (linkBBlocks) + { + LinkBBs(m_pCBB, pNewBB); + // Further emitting can only start at a point where the bblock is not fallthrough + linkBBlocks = false; + } + // If the bblock was fully emitted it means we already iterated at least once over + // all instructions so we have `pNextBB` initialized, unless it is the last bblock. + // Skip through all emitted bblocks. + m_pCBB = pNewBB; + while (m_pCBB->pNextBB && m_pCBB->pNextBB->emitState == BBStateEmitted) + m_pCBB = m_pCBB->pNextBB; + + if (m_pCBB->pNextBB) + m_ip = m_pILCode + m_pCBB->pNextBB->ilOffset; + else + m_ip = codeEnd; + + continue; + } + else + { + assert (pNewBB->emitState == BBStateNotEmitted); + } + // We are starting a new basic block. Change cbb and link them together + if (linkBBlocks) + { + // By default we link cbb with the new starting bblock, unless the previous + // instruction is an unconditional branch (BR, LEAVE, ENDFINALLY) + LinkBBs(m_pCBB, pNewBB); + EmitBBEndVarMoves(pNewBB); + pNewBB->emitState = BBStateEmitting; + emittedBBlocks = true; + if (pNewBB->stackHeight >= 0) + { + MergeStackTypeInfo(m_pStackBase, pNewBB->pStackState, pNewBB->stackHeight); + // This is relevant only for copying the vars associated with the values on the stack + memcpy(m_pStackBase, pNewBB->pStackState, pNewBB->stackHeight * sizeof(StackInfo)); + m_pStackPointer = m_pStackBase + pNewBB->stackHeight; + } + else + { + // This bblock has not been branched to yet. Initialize its stack state + InitBBStackState(pNewBB); + } + // linkBBlocks remains true, which is the default + } + else + { + if (pNewBB->stackHeight >= 0) + { + // This is relevant only for copying the vars associated with the values on the stack + memcpy (m_pStackBase, pNewBB->pStackState, pNewBB->stackHeight * sizeof(StackInfo)); + m_pStackPointer = m_pStackBase + pNewBB->stackHeight; + pNewBB->emitState = BBStateEmitting; + emittedBBlocks = true; + linkBBlocks = true; + } + else + { + INTERP_DUMP("BB%d without initialized stack\n", pNewBB->index); + assert(pNewBB->emitState == BBStateNotEmitted); + needsRetryEmit = true; + // linking to its next bblock, if its the case, will only happen + // after we actually emit the bblock + linkBBlocks = false; + // If we had pNewBB->pNextBB initialized, here we could skip to its il offset directly. + // We will just skip all instructions instead, since it doesn't seem that problematic. + } + } + if (!m_pCBB->pNextBB) + m_pCBB->pNextBB = pNewBB; + m_pCBB = pNewBB; + } + + int32_t opcodeSize = CEEOpcodeSize(m_ip, codeEnd); + if (m_pCBB->emitState != BBStateEmitting) + { + // If we are not really emitting, just skip the instructions in the bblock + m_ip += opcodeSize; + continue; + } + + m_ppOffsetToBB[insOffset] = m_pCBB; + +#ifdef DEBUG + if (m_verbose) + { + const uint8_t *ip = m_ip; + printf("IL_%04x %-10s, sp %d, %s", + (int32_t)(m_ip - m_pILCode), + CEEOpName(CEEDecodeOpcode(&ip)), (int32_t)(m_pStackPointer - m_pStackBase), + m_pStackPointer > m_pStackBase ? g_stackTypeString[m_pStackPointer[-1].type] : " "); + if (m_pStackPointer > m_pStackBase && + (m_pStackPointer[-1].type == StackTypeO || m_pStackPointer[-1].type == StackTypeVT) && + m_pStackPointer[-1].clsHnd != NULL) + PrintClassName(m_pStackPointer[-1].clsHnd); + printf("\n"); + } +#endif + + uint8_t opcode = *m_ip; + switch (opcode) + { + case CEE_NOP: + m_ip++; + break; + case CEE_LDC_I4_M1: + case CEE_LDC_I4_0: + case CEE_LDC_I4_1: + case CEE_LDC_I4_2: + case CEE_LDC_I4_3: + case CEE_LDC_I4_4: + case CEE_LDC_I4_5: + case CEE_LDC_I4_6: + case CEE_LDC_I4_7: + case CEE_LDC_I4_8: + AddIns(INTOP_LDC_I4); + m_pLastIns->data[0] = opcode - CEE_LDC_I4_0; + PushStackType(StackTypeI4, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_ip++; + break; + case CEE_LDC_I4_S: + AddIns(INTOP_LDC_I4); + m_pLastIns->data[0] = (int8_t)m_ip[1]; + PushStackType(StackTypeI4, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_ip += 2; + break; + case CEE_LDC_I4: + AddIns(INTOP_LDC_I4); + m_pLastIns->data[0] = getI4LittleEndian(m_ip + 1); + PushStackType(StackTypeI4, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_ip += 5; + break; + case CEE_LDNULL: + AddIns(INTOP_LDNULL); + PushStackType(StackTypeO, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_ip++; + break; + + case CEE_LDARG_S: + EmitLoadVar(m_ip[1]); + m_ip += 2; + break; + case CEE_LDARG_0: + case CEE_LDARG_1: + case CEE_LDARG_2: + case CEE_LDARG_3: + EmitLoadVar(*m_ip - CEE_LDARG_0); + m_ip++; + break; + case CEE_STARG_S: + EmitStoreVar(m_ip[1]); + m_ip += 2; + break; + case CEE_LDLOC_S: + EmitLoadVar(numArgs + m_ip[1]); + m_ip += 2; + break; + case CEE_LDLOC_0: + case CEE_LDLOC_1: + case CEE_LDLOC_2: + case CEE_LDLOC_3: + EmitLoadVar(numArgs + *m_ip - CEE_LDLOC_0); + m_ip++; + break; + case CEE_STLOC_S: + EmitStoreVar(numArgs + m_ip[1]); + m_ip += 2; + break; + case CEE_STLOC_0: + case CEE_STLOC_1: + case CEE_STLOC_2: + case CEE_STLOC_3: + EmitStoreVar(numArgs + *m_ip - CEE_STLOC_0); + m_ip++; + break; + + case CEE_RET: + { + CORINFO_SIG_INFO sig = methodInfo->args; + InterpType retType = GetInterpType(sig.retType); + + if (retType == InterpTypeVoid) + { + AddIns(INTOP_RET_VOID); + } + else if (retType == InterpTypeVT) + { + CHECK_STACK(1); + AddIns(INTOP_RET_VT); + m_pStackPointer--; + int32_t retVar = m_pStackPointer[0].var; + m_pLastIns->SetSVar(retVar); + m_pLastIns->data[0] = m_pVars[retVar].size; + } + else + { + CHECK_STACK(1); + AddIns(INTOP_RET); + m_pStackPointer--; + m_pLastIns->SetSVar(m_pStackPointer[0].var); + } + m_ip++; + break; + } + case CEE_CONV_U1: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U1_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U1_R8); + break; + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U1_I4); + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U1_I8); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_I1: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I1_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I1_R8); + break; + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I1_I4); + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I1_I8); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_U2: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U2_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U2_R8); + break; + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U2_I4); + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U2_I8); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_I2: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I2_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I2_R8); + break; + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I2_I4); + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I2_I8); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_U: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR8: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_U8_R8); +#else + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_U4_R8); +#endif + break; + case StackTypeR4: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_U8_R4); +#else + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_U4_R4); +#endif + break; + case StackTypeI4: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_I8_U4); +#endif + break; + case StackTypeI8: +#ifndef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_MOV_8); +#endif + break; + case StackTypeByRef: + case StackTypeO: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_MOV_8); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_I: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR8: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_I8_R8); +#else + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_I4_R8); +#endif + break; + case StackTypeR4: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_I8_R4); +#else + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_I4_R4); +#endif + break; + case StackTypeI4: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_CONV_I8_I4); +#endif + break; + case StackTypeO: + case StackTypeByRef: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_MOV_8); + break; + case StackTypeI8: +#ifndef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI, INTOP_MOV_8); +#endif + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_U4: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U4_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_U4_R8); + break; + case StackTypeI4: + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_MOV_8); + break; + case StackTypeByRef: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_MOV_P); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_I4: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I4_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_CONV_I4_R8); + break; + case StackTypeI4: + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_MOV_8); + break; + case StackTypeByRef: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI4, INTOP_MOV_P); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_I8: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_R8); + break; + case StackTypeI4: { + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_I4); + break; + } + case StackTypeI8: + break; + case StackTypeByRef: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_MOV_8); +#else + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_I4); +#endif + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_R4: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR4, INTOP_CONV_R4_R8); + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR4, INTOP_CONV_R4_I8); + break; + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR4, INTOP_CONV_R4_I4); + break; + case StackTypeR4: + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_R8: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_I4); + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_I8); + break; + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_R4); + break; + case StackTypeR8: + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_U8: + CHECK_STACK(1); + switch (m_pStackPointer[-1].type) + { + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_U4); + break; + case StackTypeI8: + break; + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_U8_R4); + break; + case StackTypeR8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_U8_R8); + break; + case StackTypeByRef: +#ifdef TARGET_64BIT + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_MOV_8); +#else + EmitConv(m_pStackPointer - 1, NULL, StackTypeI8, INTOP_CONV_I8_U4); +#endif + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_CONV_R_UN: + switch (m_pStackPointer[-1].type) + { + case StackTypeR4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R8_R4); + break; + case StackTypeR8: + break; + case StackTypeI8: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R_UN_I8); + break; + case StackTypeI4: + EmitConv(m_pStackPointer - 1, NULL, StackTypeR8, INTOP_CONV_R_UN_I4); + break; + default: + assert(0); + } + m_ip++; + break; + case CEE_SWITCH: + { + m_ip++; + uint32_t n = getU4LittleEndian(m_ip); + // Format of switch instruction is opcode + srcVal + n + T1 + T2 + ... + Tn + AddInsExplicit(INTOP_SWITCH, n + 3); + m_pLastIns->data[0] = n; + m_ip += 4; + const uint8_t *nextIp = m_ip + n * 4; + m_pStackPointer--; + m_pLastIns->SetSVar(m_pStackPointer->var); + InterpBasicBlock **targetBBTable = (InterpBasicBlock**)AllocMemPool(sizeof (InterpBasicBlock*) * n); + + for (uint32_t i = 0; i < n; i++) + { + int32_t offset = getU4LittleEndian(m_ip); + uint32_t target = (uint32_t)(nextIp - m_pILCode + offset); + InterpBasicBlock *targetBB = m_ppOffsetToBB[target]; + assert(targetBB); + + InitBBStackState(targetBB); + targetBBTable[i] = targetBB; + LinkBBs(m_pCBB, targetBB); + m_ip += 4; + } + m_pLastIns->info.ppTargetBBTable = targetBBTable; + break; + } + case CEE_BR: + { + int32_t offset = getI4LittleEndian(m_ip + 1); + if (offset) + { + EmitBranch(INTOP_BR, 5 + offset); + linkBBlocks = false; + } + m_ip += 5; + break; + } + case CEE_BR_S: + { + int32_t offset = (int8_t)m_ip [1]; + if (offset) + { + EmitBranch(INTOP_BR, 2 + (int8_t)m_ip [1]); + linkBBlocks = false; + } + m_ip += 2; + break; + } + case CEE_BRFALSE: + EmitOneArgBranch(INTOP_BRFALSE_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BRFALSE_S: + EmitOneArgBranch(INTOP_BRFALSE_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BRTRUE: + EmitOneArgBranch(INTOP_BRTRUE_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BRTRUE_S: + EmitOneArgBranch(INTOP_BRTRUE_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BEQ: + EmitTwoArgBranch(INTOP_BEQ_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BEQ_S: + EmitTwoArgBranch(INTOP_BEQ_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BGE: + EmitTwoArgBranch(INTOP_BGE_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BGE_S: + EmitTwoArgBranch(INTOP_BGE_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BGT: + EmitTwoArgBranch(INTOP_BGT_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BGT_S: + EmitTwoArgBranch(INTOP_BGT_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BLT: + EmitTwoArgBranch(INTOP_BLT_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BLT_S: + EmitTwoArgBranch(INTOP_BLT_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BLE: + EmitTwoArgBranch(INTOP_BLE_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BLE_S: + EmitTwoArgBranch(INTOP_BLE_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BNE_UN: + EmitTwoArgBranch(INTOP_BNE_UN_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BNE_UN_S: + EmitTwoArgBranch(INTOP_BNE_UN_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BGE_UN: + EmitTwoArgBranch(INTOP_BGE_UN_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BGE_UN_S: + EmitTwoArgBranch(INTOP_BGE_UN_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BGT_UN: + EmitTwoArgBranch(INTOP_BGT_UN_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BGT_UN_S: + EmitTwoArgBranch(INTOP_BGT_UN_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BLE_UN: + EmitTwoArgBranch(INTOP_BLE_UN_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BLE_UN_S: + EmitTwoArgBranch(INTOP_BLE_UN_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + case CEE_BLT_UN: + EmitTwoArgBranch(INTOP_BLT_UN_I4, getI4LittleEndian(m_ip + 1), 5); + m_ip += 5; + break; + case CEE_BLT_UN_S: + EmitTwoArgBranch(INTOP_BLT_UN_I4, (int8_t)m_ip [1], 2); + m_ip += 2; + break; + + case CEE_ADD: + EmitBinaryArithmeticOp(INTOP_ADD_I4); + m_ip++; + break; + case CEE_SUB: + EmitBinaryArithmeticOp(INTOP_SUB_I4); + m_ip++; + break; + case CEE_MUL: + EmitBinaryArithmeticOp(INTOP_MUL_I4); + m_ip++; + break; + case CEE_AND: + EmitBinaryArithmeticOp(INTOP_AND_I4); + m_ip++; + break; + case CEE_OR: + EmitBinaryArithmeticOp(INTOP_OR_I4); + m_ip++; + break; + case CEE_XOR: + EmitBinaryArithmeticOp(INTOP_XOR_I4); + m_ip++; + break; + case CEE_SHL: + EmitShiftOp(INTOP_SHL_I4); + m_ip++; + break; + case CEE_SHR: + EmitShiftOp(INTOP_SHR_I4); + m_ip++; + break; + case CEE_SHR_UN: + EmitShiftOp(INTOP_SHR_UN_I4); + m_ip++; + break; + case CEE_NEG: + EmitUnaryArithmeticOp(INTOP_NEG_I4); + m_ip++; + break; + case CEE_NOT: + EmitUnaryArithmeticOp(INTOP_NOT_I4); + m_ip++; + break; + case CEE_CALL: + EmitCall(constrainedClass, readonly, tailcall); + constrainedClass = NULL; + readonly = false; + tailcall = false; + break; + + case CEE_PREFIX1: + m_ip++; + switch (*m_ip + 256) + { + case CEE_LDARG: + EmitLoadVar(getU2LittleEndian(m_ip + 1)); + m_ip += 3; + break; + case CEE_STARG: + EmitStoreVar(getU2LittleEndian(m_ip + 1)); + m_ip += 3; + break; + case CEE_LDLOC: + EmitLoadVar(numArgs + getU2LittleEndian(m_ip + 1)); + m_ip += 3; + break; + case CEE_STLOC: + EmitStoreVar(numArgs + getU2LittleEndian(m_ip + 1));\ + m_ip += 3; + break; + case CEE_CEQ: + EmitCompareOp(INTOP_CEQ_I4); + m_ip++; + break; + case CEE_CGT: + EmitCompareOp(INTOP_CGT_I4); + m_ip++; + break; + case CEE_CGT_UN: + EmitCompareOp(INTOP_CGT_UN_I4); + m_ip++; + break; + case CEE_CLT: + EmitCompareOp(INTOP_CLT_I4); + m_ip++; + break; + case CEE_CLT_UN: + EmitCompareOp(INTOP_CLT_UN_I4); + m_ip++; + break; + case CEE_CONSTRAINED: + { + uint32_t token = getU4LittleEndian(m_ip + 1); + CORINFO_RESOLVED_TOKEN resolvedToken; + + resolvedToken.tokenScope = m_compScopeHnd; + resolvedToken.tokenContext = METHOD_BEING_COMPILED_CONTEXT(); + resolvedToken.token = token; + resolvedToken.tokenType = CORINFO_TOKENKIND_Constrained; + m_compHnd->resolveToken(&resolvedToken); + constrainedClass = resolvedToken.hClass; + m_ip += 5; + break; + } + case CEE_READONLY: + readonly = true; + m_ip++; + break; + case CEE_TAILCALL: + tailcall = true; + m_ip++; + break; + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + } + + if (m_pCBB->emitState == BBStateEmitting) + m_pCBB->emitState = BBStateEmitted; + + // If no bblocks were emitted during the last iteration, there is no point to try again + // Some bblocks are just unreachable in the code. + if (needsRetryEmit && emittedBBlocks) + { + m_ip = m_pILCode; + m_pCBB = m_pEntryBB; + + linkBBlocks = false; + needsRetryEmit = false; + INTERP_DUMP("retry emit\n"); + goto retry_emit; + } + + UnlinkUnreachableBBlocks(); + + return CORJIT_OK; +exit_bad_code: + return CORJIT_BADCODE; +} + +void InterpCompiler::UnlinkUnreachableBBlocks() +{ + // Unlink unreachable bblocks, prevBB is always an emitted bblock + InterpBasicBlock *prevBB = m_pEntryBB; + InterpBasicBlock *nextBB = prevBB->pNextBB; + while (nextBB != NULL) + { + if (nextBB->emitState == BBStateNotEmitted) + { + m_ppOffsetToBB[nextBB->ilOffset] = NULL; + prevBB->pNextBB = nextBB->pNextBB; + nextBB = prevBB->pNextBB; + } + else + { + prevBB = nextBB; + nextBB = nextBB->pNextBB; + } + } +} + +void InterpCompiler::PrintClassName(CORINFO_CLASS_HANDLE cls) +{ + char className[100]; + m_compHnd->printClassName(cls, className, 100); + printf("%s", className); +} + +void InterpCompiler::PrintMethodName(CORINFO_METHOD_HANDLE method) +{ + char methodName[100]; + + CORINFO_CLASS_HANDLE cls = m_compHnd->getMethodClass(method); + PrintClassName(cls); + + m_compHnd->printMethodName(method, methodName, 100); + printf(".%s", methodName); +} + +void InterpCompiler::PrintCode() +{ + for (InterpBasicBlock *pBB = m_pEntryBB; pBB != NULL; pBB = pBB->pNextBB) + PrintBBCode(pBB); +} + +void InterpCompiler::PrintBBCode(InterpBasicBlock *pBB) +{ + printf("BB%d:\n", pBB->index); + for (InterpInst *ins = pBB->pFirstIns; ins != NULL; ins = ins->pNext) + PrintIns(ins); +} + +void InterpCompiler::PrintIns(InterpInst *ins) +{ + int32_t opcode = ins->opcode; + if (ins->ilOffset == -1) + printf("IL_----: %-14s", InterpOpName(opcode)); + else + printf("IL_%04x: %-14s", ins->ilOffset, InterpOpName(opcode)); + + if (g_interpOpDVars[opcode] > 0) + printf(" [%d <-", ins->dVar); + else + printf(" [nil <-"); + + if (g_interpOpSVars[opcode] > 0) + { + for (int i = 0; i < g_interpOpSVars[opcode]; i++) + { + if (ins->sVars[i] == CALL_ARGS_SVAR) + { + printf(" c:"); + if (ins->info.pCallInfo && ins->info.pCallInfo->pCallArgs) + { + int *callArgs = ins->info.pCallInfo->pCallArgs; + while (*callArgs != CALL_ARGS_TERMINATOR) + { + printf(" %d", *callArgs); + callArgs++; + } + } + } + else + { + printf(" %d", ins->sVars[i]); + } + } + printf("],"); + } + else + { + printf(" nil],"); + } + + // LDLOCA has special semantics, it has data in sVars[0], but it doesn't have any sVars + if (opcode == INTOP_LDLOCA) + printf(" %d", ins->sVars[0]); + else + PrintInsData(ins, ins->ilOffset, &ins->data[0], ins->opcode); + printf("\n"); +} + +void InterpCompiler::PrintInsData(InterpInst *ins, int32_t insOffset, const int32_t *pData, int32_t opcode) +{ + switch (g_interpOpArgType[opcode]) { + case InterpOpNoArgs: + break; + case InterpOpInt: + printf(" %d", *pData); + break; + case InterpOpBranch: + if (ins) + printf(" BB%d", ins->info.pTargetBB->index); + else + printf(" IR_%04x", insOffset + *pData); + break; + case InterpOpSwitch: + { + int32_t n = *pData; + printf(" ("); + for (int i = 0; i < n; i++) + { + if (i > 0) + printf(", "); + + if (ins) + printf("BB%d", ins->info.ppTargetBBTable[i]->index); + else + printf("IR_%04x", insOffset + 3 + i + *(pData + 1 + i)); + } + printf(")"); + break; + } + case InterpOpMethodToken: + { + CORINFO_METHOD_HANDLE mh = (CORINFO_METHOD_HANDLE)((size_t)m_dataItems.Get(*pData) & ~INTERP_METHOD_DESC_TAG); + printf(" "); + PrintMethodName(mh); + break; + } + default: + assert(0); + break; + } +} + +void InterpCompiler::PrintCompiledCode() +{ + const int32_t *ip = m_pMethodCode; + const int32_t *end = m_pMethodCode + m_methodCodeSize; + + while (ip < end) + { + PrintCompiledIns(ip, m_pMethodCode); + ip = InterpNextOp(ip); + } +} + +void InterpCompiler::PrintCompiledIns(const int32_t *ip, const int32_t *start) +{ + int32_t opcode = *ip; + int32_t insOffset = (int32_t)(ip - start); + + printf("IR_%04x: %-14s", insOffset, InterpOpName(opcode)); + ip++; + + if (g_interpOpDVars[opcode] > 0) + printf(" [%d <-", *ip++); + else + printf(" [nil <-"); + + if (g_interpOpSVars[opcode] > 0) + { + for (int i = 0; i < g_interpOpSVars[opcode]; i++) + printf(" %d", *ip++); + printf("],"); + } + else + { + printf(" nil],"); + } + + PrintInsData(NULL, insOffset, ip, opcode); + printf("\n"); } diff --git a/src/coreclr/interpreter/compiler.h b/src/coreclr/interpreter/compiler.h index fac63198fcb2d9..1f93a9a308f255 100644 --- a/src/coreclr/interpreter/compiler.h +++ b/src/coreclr/interpreter/compiler.h @@ -5,6 +5,7 @@ #define _COMPILER_H_ #include "intops.h" +#include "datastructs.h" // Types that can exist on the IL execution stack. They are used only during // IL import compilation stage. @@ -15,8 +16,13 @@ enum StackType { StackTypeR8, StackTypeO, StackTypeVT, - StackTypeMP, - StackTypeF + StackTypeByRef, + StackTypeF, +#ifdef TARGET_64BIT + StackTypeI = StackTypeI8 +#else + StackTypeI = StackTypeI4 +#endif }; // Types relevant for interpreter vars and opcodes. They are used in the final @@ -32,7 +38,8 @@ enum InterpType { InterpTypeR8, InterpTypeO, InterpTypeVT, - InterpTypeVOID, + InterpTypeByRef, + InterpTypeVoid, #ifdef TARGET_64BIT InterpTypeI = InterpTypeI8 #else @@ -40,16 +47,40 @@ enum InterpType { #endif }; +#ifdef DEBUG +#define INTERP_DUMP(...) \ + { \ + if (m_verbose) \ + printf(__VA_ARGS__); \ + } +#else +#define INTERP_DUMP(...) +#endif + +struct InterpInst; +struct InterpBasicBlock; + struct InterpCallInfo { // For call instructions, this represents an array of all call arg vars // in the order they are pushed to the stack. This makes it easy to find // all source vars for these types of opcodes. This is terminated with -1. - int *pCallArgs; - int callOffset; + int32_t *pCallArgs; + int32_t callOffset; + union { + // Array of call dependencies that need to be resolved before + TSList *callDeps; + // Stack end offset of call arguments + int32_t callEndOffset; + }; }; -struct InterpBasicBlock; +enum InterpInstFlags +{ + INTERP_INST_FLAG_CALL = 0x01, + // Flag used internally by the var offset allocator + INTERP_INST_FLAG_ACTIVE_CALL = 0x02 +}; struct InterpInst { @@ -94,13 +125,23 @@ struct InterpInst }; #define CALL_ARGS_SVAR -2 +#define CALL_ARGS_TERMINATOR -1 +struct StackInfo; + +enum InterpBBState +{ + BBStateNotEmitted, + BBStateEmitting, + BBStateEmitted +}; struct InterpBasicBlock { int32_t index; int32_t ilOffset, nativeOffset; int32_t stackHeight; + StackInfo *pStackState; InterpInst *pFirstIns, *pLastIns; InterpBasicBlock *pNextBB; @@ -108,18 +149,66 @@ struct InterpBasicBlock int inCount, outCount; InterpBasicBlock **ppInBBs; InterpBasicBlock **ppOutBBs; + + InterpBBState emitState; + + InterpBasicBlock(int32_t index) : InterpBasicBlock(index, 0) { } + + InterpBasicBlock(int32_t index, int32_t ilOffset) + { + this->index = index; + this->ilOffset = ilOffset; + nativeOffset = -1; + stackHeight = -1; + + pFirstIns = pLastIns = NULL; + pNextBB = NULL; + + inCount = 0; + outCount = 0; + + emitState = BBStateNotEmitted; + } }; struct InterpVar { CORINFO_CLASS_HANDLE clsHnd; - InterpType mt; + InterpType interpType; int indirects; int offset; int size; // live_start and live_end are used by the offset allocator int liveStart; int liveEnd; + // index of first basic block where this var is used + int bbIndex; + // If var is callArgs, this is the call instruction using it. + // Only used by the var offset allocator + InterpInst *call; + + unsigned int callArgs : 1; // Var used as argument to a call + unsigned int noCallArgs : 1; // Var can't be used as argument to a call, needs to be copied to temp + unsigned int global : 1; // Dedicated stack offset throughout method execution + unsigned int ILGlobal : 1; // Args and IL locals + unsigned int alive : 1; // Used internally by the var offset allocator + + InterpVar(InterpType interpType, CORINFO_CLASS_HANDLE clsHnd, int size) + { + this->interpType = interpType; + this->clsHnd = clsHnd; + this->size = size; + offset = -1; + liveStart = -1; + bbIndex = -1; + indirects = 0; + + callArgs = false; + noCallArgs = false; + global = false; + ILGlobal = false; + alive = false; + } }; struct StackInfo @@ -133,6 +222,38 @@ struct StackInfo // The var associated with the value of this stack entry. Every time we push on // the stack a new var is created. int var; + + StackInfo(StackType type) + { + this->type = type; + clsHnd = NULL; + size = 0; + var = -1; + } +}; + +enum RelocType +{ + RelocLongBranch, + RelocSwitch +}; + +struct Reloc +{ + RelocType type; + // For branch relocation, how many sVar slots to skip + int skip; + // Base offset that the relative offset to be embedded in IR applies to + int32_t offset; + InterpBasicBlock *pTargetBB; + + Reloc(RelocType type, int32_t offset, InterpBasicBlock *pTargetBB, int skip) + { + this->type = type; + this->offset = offset; + this->pTargetBB = pTargetBB; + this->skip = skip; + } }; typedef class ICorJitInfo* COMP_HANDLE; @@ -141,14 +262,36 @@ class InterpCompiler { private: CORINFO_METHOD_HANDLE m_methodHnd; + CORINFO_MODULE_HANDLE m_compScopeHnd; COMP_HANDLE m_compHnd; CORINFO_METHOD_INFO* m_methodInfo; + bool m_verbose; + + static int32_t InterpGetMovForType(InterpType interpType, bool signExtend); + + uint8_t* m_ip; + uint8_t* m_pILCode; + int32_t m_ILCodeSize; + int32_t m_currentILOffset; + + // This represents a mapping from indexes to pointer sized data. During compilation, an + // instruction can request an index for some data (like a MethodDesc pointer), that it + // will then embed in the instruction stream. The data item table will be referenced + // from the interpreter code header during execution. + // FIXME during compilation this should be a hashtable for fast lookup of duplicates + TArray m_dataItems; + int32_t GetDataItemIndex(void* data); + int32_t GetMethodDataItemIndex(CORINFO_METHOD_HANDLE mHandle); int GenerateCode(CORINFO_METHOD_INFO* methodInfo); void* AllocMethodData(size_t numBytes); + // FIXME Mempool allocation currently leaks. We need to add an allocator and then + // free all memory when method is finished compilling. void* AllocMemPool(size_t numBytes); + void* AllocMemPool0(size_t numBytes); void* AllocTemporary(size_t numBytes); + void* AllocTemporary0(size_t numBytes); void* ReallocTemporary(void* ptr, size_t numBytes); void FreeTemporary(void* ptr); @@ -175,23 +318,34 @@ class InterpCompiler int m_BBCount = 0; InterpBasicBlock** m_ppOffsetToBB; - InterpBasicBlock* AllocBB(); + InterpBasicBlock* AllocBB(int32_t ilOffset); InterpBasicBlock* GetBB(int32_t ilOffset); void LinkBBs(InterpBasicBlock *from, InterpBasicBlock *to); void UnlinkBBs(InterpBasicBlock *from, InterpBasicBlock *to); + void EmitBranch(InterpOpcode opcode, int ilOffset); + void EmitOneArgBranch(InterpOpcode opcode, int ilOffset, int insSize); + void EmitTwoArgBranch(InterpOpcode opcode, int ilOffset, int insSize); + + void EmitBBEndVarMoves(InterpBasicBlock *pTargetBB); + void InitBBStackState(InterpBasicBlock *pBB); + void UnlinkUnreachableBBlocks(); + // Vars InterpVar *m_pVars = NULL; int32_t m_varsSize = 0; int32_t m_varsCapacity = 0; - int32_t CreateVarExplicit(InterpType mt, CORINFO_CLASS_HANDLE clsHnd, int size); + int32_t CreateVarExplicit(InterpType interpType, CORINFO_CLASS_HANDLE clsHnd, int size); - int32_t m_totalVarsStackSize = 0; + int32_t m_totalVarsStackSize; int32_t m_paramAreaOffset = 0; + int32_t m_ILLocalsOffset, m_ILLocalsSize; void AllocVarOffsetCB(int *pVar, void *pData); int32_t AllocVarOffset(int var, int32_t *pPos); + int32_t GetInterpTypeStackSize(CORINFO_CLASS_HANDLE clsHnd, InterpType interpType, int32_t *pAlign); + void CreateILVars(); // Stack StackInfo *m_pStackPointer, *m_pStackBase; @@ -201,21 +355,59 @@ class InterpCompiler bool CheckStackHelper(int n); void EnsureStack(int additional); void PushTypeExplicit(StackType stackType, CORINFO_CLASS_HANDLE clsHnd, int size); - void PushType(StackType stackType, CORINFO_CLASS_HANDLE clsHnd); + void PushStackType(StackType stackType, CORINFO_CLASS_HANDLE clsHnd); + void PushInterpType(InterpType interpType, CORINFO_CLASS_HANDLE clsHnd); void PushTypeVT(CORINFO_CLASS_HANDLE clsHnd, int size); + // Code emit + void EmitConv(StackInfo *sp, InterpInst *prevIns, StackType type, InterpOpcode convOp); + void EmitLoadVar(int var); + void EmitStoreVar(int var); + void EmitBinaryArithmeticOp(int32_t opBase); + void EmitUnaryArithmeticOp(int32_t opBase); + void EmitShiftOp(int32_t opBase); + void EmitCompareOp(int32_t opBase); + void EmitCall(CORINFO_CLASS_HANDLE constrainedClass, bool readonly, bool tailcall); + bool EmitCallIntrinsics(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO sig); + + // Var Offset allocator + TArray *m_pActiveCalls; + TArray *m_pActiveVars; + TSList *m_pDeferredCalls; + + int32_t AllocGlobalVarOffset(int var); + void SetVarLiveRange(int32_t var, int insIndex); + void SetVarLiveRangeCB(int32_t *pVar, void *pData); + void InitializeGlobalVar(int32_t var, int bbIndex); + void InitializeGlobalVarCB(int32_t *pVar, void *pData); + void InitializeGlobalVars(); + void EndActiveCall(InterpInst *call); + void CompactActiveVars(int32_t *current_offset); + // Passes int32_t* m_pMethodCode; - int32_t m_MethodCodeSize; // in int32_t + int32_t m_methodCodeSize; // code size measured in int32_t slots, instead of bytes void AllocOffsets(); int32_t ComputeCodeSize(); void EmitCode(); - int32_t* EmitCodeIns(int32_t *ip, InterpInst *pIns); + int32_t* EmitCodeIns(int32_t *ip, InterpInst *pIns, TArray *relocs); + void PatchRelocations(TArray *relocs); InterpMethod* CreateInterpMethod(); + bool CreateBasicBlocks(CORINFO_METHOD_INFO* methodInfo); + + // Debug + void PrintClassName(CORINFO_CLASS_HANDLE cls); + void PrintMethodName(CORINFO_METHOD_HANDLE method); + void PrintCode(); + void PrintBBCode(InterpBasicBlock *pBB); + void PrintIns(InterpInst *ins); + void PrintInsData(InterpInst *ins, int32_t offset, const int32_t *pData, int32_t opcode); + void PrintCompiledCode(); + void PrintCompiledIns(const int32_t *ip, const int32_t *start); public: - InterpCompiler(COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo); + InterpCompiler(COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo, bool verbose); InterpMethod* CompileMethod(); diff --git a/src/coreclr/interpreter/compileropt.cpp b/src/coreclr/interpreter/compileropt.cpp index 9e1f83ac34a1ed..cc188d53101a57 100644 --- a/src/coreclr/interpreter/compileropt.cpp +++ b/src/coreclr/interpreter/compileropt.cpp @@ -18,23 +18,386 @@ int32_t InterpCompiler::AllocVarOffset(int var, int32_t *pPos) return m_pVars[var].offset; } -void InterpCompiler::AllocVarOffsetCB(int *pVar, void *pData) +// Global vars are variables that are referenced from multiple basic blocks. We reserve +// a dedicated slot for each such variable. +int32_t InterpCompiler::AllocGlobalVarOffset(int var) { - AllocVarOffset(*pVar, &m_totalVarsStackSize); + return AllocVarOffset(var, &m_totalVarsStackSize); +} + +// For a var that is local to the current bblock that we process, as we iterate +// over instructions we mark the first and last intruction using it. +void InterpCompiler::SetVarLiveRange(int32_t var, int insIndex) +{ + // We don't track liveness yet for global vars + if (m_pVars[var].global) + return; + if (m_pVars[var].liveStart == -1) + m_pVars[var].liveStart = insIndex; + m_pVars[var].liveEnd = insIndex; +} + +void InterpCompiler::SetVarLiveRangeCB(int32_t *pVar, void *pData) +{ + SetVarLiveRange(*pVar, (int)(size_t)pData); +} + +void InterpCompiler::InitializeGlobalVar(int32_t var, int bbIndex) +{ + // Check if already handled + if (m_pVars[var].global) + return; + + if (m_pVars[var].bbIndex == -1) + { + m_pVars[var].bbIndex = bbIndex; + } + else if (m_pVars[var].bbIndex != bbIndex) + { + AllocGlobalVarOffset(var); + m_pVars[var].global = true; + INTERP_DUMP("alloc global var %d to offset %d\n", var, m_pVars[var].offset); + } +} + +void InterpCompiler::InitializeGlobalVarCB(int32_t *pVar, void *pData) +{ + InitializeGlobalVar(*pVar, (int)(size_t)pData); +} + +void InterpCompiler::InitializeGlobalVars() +{ + InterpBasicBlock *pBB; + for (pBB = m_pEntryBB; pBB != NULL; pBB = pBB->pNextBB) + { + InterpInst *pIns; + + for (pIns = pBB->pFirstIns; pIns != NULL; pIns = pIns->pNext) { + + int32_t opcode = pIns->opcode; + if (opcode == INTOP_NOP) + continue; + if (opcode == INTOP_LDLOCA) + { + int var = pIns->sVars[0]; + // If global flag is set, it means its offset was already allocated + if (!m_pVars[var].global) + { + AllocGlobalVarOffset(var); + m_pVars[var].global = true; + INTERP_DUMP("alloc global var %d to offset %d\n", var, m_pVars[var].offset); + } + } + ForEachInsVar(pIns, (void*)(size_t)pBB->index, &InterpCompiler::InitializeGlobalVarCB); + } + } + m_totalVarsStackSize = ALIGN_UP_TO(m_totalVarsStackSize, INTERP_STACK_ALIGNMENT); +} + +// In the final codegen, each call instruction will receive a single offset as an argument. At this +// offset all the call arguments will be located. This offset will point into the param area. Vars +// allocated here have special constraints compared to normal local/global vars. +// +// For each call instruction, this method computes its args offset. The call offset is computed as +// the max offset of all call offsets on which the call depends. Stack ensures that all call offsets +// on which the call depends are calculated before the call in question, by deferring calls from the +// last to the first one. +// +// This method allocates offsets of resolved calls following a constraint where the base offset +// of a call must be greater than the offset of any argument of other active call args. It first +// removes the call from an array of active calls. If a match is found, the call is removed from +// the array by moving the last entry into its place. Otherwise, it is a call without arguments. +// +// If there are active calls, the call in question is pushed onto the stack as a deferred call. +// The call contains a list of other active calls on which it depends. Those calls need to be +// resolved first in order to determine optimal base offset for the call in question. Otherwise, +// if there are no active calls, we resolve the call in question and deferred calls from the stack. +// +// For better understanding, consider a simple example: +// a <- _ +// b <- _ +// call1 c <- b +// d <- _ +// call2 _ <- a c d +// +// When `a` is defined, call2 becomes an active call, since `a` is part of call2 arguments. +// When `b` is defined, call1 also becomes an active call, +// When reaching call1, we attempt to resolve it. The problem with this is that call2 is already +// active, and all arguments of call1 should be placed after any arguments of call2 (in this example +// it would be enough for them to be placed after `a`, but for simplicity we place them after all +// arguments, so after `d` offset). Given call1 offset depends on call2 offset, we initialize its +// callDeps (to call2) and add call1 to the set of currently deferred calls. Call1 is no longer an +// an active call at this point. +// When reaching call2, we see we have no remaining active calls, so we will resolve its offset. +// Once the offset is resolved, we continue to resolve each remaining call from the deferred list. +// Processing call1, we iterate over each call dependency (in our case just call2) and allocate its +// offset accordingly so it doesn't overlap with any call2 args offsets. +void InterpCompiler::EndActiveCall(InterpInst *call) +{ + // Remove call from array + m_pActiveCalls->Remove(call); + + // Push active call that should be resolved onto the stack + if (m_pActiveCalls->GetSize()) + { + TSList *callDeps = NULL; + for (int i = 0; i < m_pActiveCalls->GetSize(); i++) + callDeps = TSList::Push(callDeps, m_pActiveCalls->Get(i)); + call->info.pCallInfo->callDeps = callDeps; + + m_pDeferredCalls = TSList::Push(m_pDeferredCalls, call); + } + else + { + call->info.pCallInfo->callDeps = NULL; + // If no other active calls, current active call and all deferred calls can be resolved from the stack + InterpInst *deferredCall = call; + while (deferredCall) { + // `base_offset` is a relative offset (to the start of the call args stack) where the args for this + // call reside. The deps for a call represent the list of active calls at the moment when the call ends. + // This means that all deps for a call end after the call in question. Given we iterate over the list + // of deferred calls from the last to the first one to end, all deps of a call are guaranteed to have + // been processed at this point. + int32_t baseOffset = 0; + for (TSList *list = deferredCall->info.pCallInfo->callDeps; list; list = list->pNext) + { + int32_t endOffset = list->data->info.pCallInfo->callEndOffset; + if (endOffset > baseOffset) + baseOffset = endOffset; + } + deferredCall->info.pCallInfo->callOffset = baseOffset; + // Compute to offset of each call argument + int32_t *callArgs = deferredCall->info.pCallInfo->pCallArgs; + if (callArgs && (*callArgs != -1)) + { + int32_t var = *callArgs; + while (var != CALL_ARGS_TERMINATOR) + { + AllocVarOffset(var, &baseOffset); + callArgs++; + var = *callArgs; + } + } + deferredCall->info.pCallInfo->callEndOffset = ALIGN_UP_TO(baseOffset, INTERP_STACK_ALIGNMENT); + + if (m_pDeferredCalls) + { + deferredCall = m_pDeferredCalls->data; + m_pDeferredCalls = TSList::Pop(m_pDeferredCalls); + } + else + { + deferredCall = NULL; + } + } + } +} + +// Remove dead vars from the end of the active vars array and update the current offset +// to point immediately after the first found alive var. The space that used to belong +// to the now dead vars will be reused for future defined local vars in the same bblock. +void InterpCompiler::CompactActiveVars(int32_t *pCurrentOffset) +{ + int32_t size = m_pActiveVars->GetSize(); + if (!size) + return; + int32_t i = size - 1; + while (i >= 0) + { + int32_t var = m_pActiveVars->Get(i); + // If var is alive we can't compact anymore + if (m_pVars[var].alive) + return; + *pCurrentOffset = m_pVars[var].offset; + m_pActiveVars->RemoveAt(i); + i--; + } } void InterpCompiler::AllocOffsets() { - // FIXME add proper offset allocator InterpBasicBlock *pBB; + m_pActiveVars = new TArray(); + m_pActiveCalls = new TArray(); + m_pDeferredCalls = NULL; + + InitializeGlobalVars(); + + INTERP_DUMP("\nAllocating var offsets\n"); + + int finalVarsStackSize = m_totalVarsStackSize; + // We now have the top of stack offset. All local regs are allocated after this offset, with each basic block for (pBB = m_pEntryBB; pBB != NULL; pBB = pBB->pNextBB) { InterpInst *pIns; + int insIndex = 0; + + INTERP_DUMP("BB%d\n", pBB->index); + + // All data structs should be left empty after a bblock iteration + assert(m_pActiveVars->GetSize() == 0); + assert(m_pActiveCalls->GetSize() == 0); + assert(m_pDeferredCalls == NULL); for (pIns = pBB->pFirstIns; pIns != NULL; pIns = pIns->pNext) - ForEachInsSVar(pIns, NULL, &InterpCompiler::AllocVarOffsetCB); + { + if (pIns->opcode == INTOP_NOP) + continue; + + // TODO NewObj will be marked as noCallArgs + if (pIns->flags & INTERP_INST_FLAG_CALL) + { + if (pIns->info.pCallInfo && pIns->info.pCallInfo->pCallArgs) + { + int32_t *callArgs = pIns->info.pCallInfo->pCallArgs; + int32_t var = *callArgs; + + while (var != -1) + { + if (m_pVars[var].global || m_pVars[var].noCallArgs) + { + // Some vars can't be allocated on the call args stack, since the constraint is that + // call args vars die after the call. This isn't necessarily true for global vars or + // vars that are used by other instructions aside from the call. + // We need to copy the var into a new tmp var + int newVar = CreateVarExplicit(m_pVars[var].interpType, m_pVars[var].clsHnd, m_pVars[var].size); + m_pVars[newVar].call = pIns; + m_pVars[newVar].callArgs = true; + + int32_t opcode = InterpGetMovForType(m_pVars[newVar].interpType, false); + InterpInst *newInst = InsertInsBB(pBB, pIns->pPrev, opcode); + newInst->SetDVar(newVar); + newInst->SetSVar(newVar); + if (opcode == INTOP_MOV_VT) + newInst->data[0] = m_pVars[var].size; + // The arg of the call is no longer global + *callArgs = newVar; + // Also update liveness for this instruction + ForEachInsVar(newInst, (void*)(size_t)insIndex, &InterpCompiler::SetVarLiveRangeCB); + insIndex++; + } + else + { + // Flag this var as it has special storage on the call args stack + m_pVars[var].call = pIns; + m_pVars[var].callArgs = true; + } + callArgs++; + var = *callArgs; + } + } + } + // Set liveStart and liveEnd for every referenced local that is not global + ForEachInsVar(pIns, (void*)(size_t)insIndex, &InterpCompiler::SetVarLiveRangeCB); + insIndex++; + } + int32_t currentOffset = m_totalVarsStackSize; + + insIndex = 0; + for (pIns = pBB->pFirstIns; pIns != NULL; pIns = pIns->pNext) { + int32_t opcode = pIns->opcode; + bool isCall = pIns->flags & INTERP_INST_FLAG_CALL; + + if (opcode == INTOP_NOP) + continue; + +#ifdef DEBUG + if (m_verbose) + { + printf("\tins_index %d\t", insIndex); + PrintIns(pIns); + } +#endif + + // Expire source vars. We first mark them as not alive and then compact the array + for (int i = 0; i < g_interpOpSVars[opcode]; i++) + { + int32_t var = pIns->sVars[i]; + if (var == CALL_ARGS_SVAR) + continue; + if (!m_pVars[var].global && m_pVars[var].liveEnd == insIndex) + { + // Mark the var as no longer being alive + assert(!m_pVars[var].callArgs); + m_pVars[var].alive = false; + } + } + + if (isCall) + EndActiveCall(pIns); + + CompactActiveVars(¤tOffset); + + // Alloc dreg local starting at the stack_offset + if (g_interpOpDVars[opcode]) + { + int32_t var = pIns->dVar; + + if (m_pVars[var].callArgs) + { + InterpInst *call = m_pVars[var].call; + // Check if already added + if (!(call->flags & INTERP_INST_FLAG_ACTIVE_CALL)) + { + m_pActiveCalls->Add(call); + // Mark a flag on it so we don't have to lookup the array with every argument store. + call->flags |= INTERP_INST_FLAG_ACTIVE_CALL; + } + } + else if (!m_pVars[var].global && m_pVars[var].offset == -1) + { + AllocVarOffset(var, ¤tOffset); + INTERP_DUMP("alloc var %d to offset %d\n", var, m_pVars[var].offset); + + if (currentOffset > finalVarsStackSize) + finalVarsStackSize = currentOffset; + + if (m_pVars[var].liveEnd > insIndex) + { + // If dVar is still used in the basic block, add it to the active list + m_pActiveVars->Add(var); + m_pVars[var].alive = true; + } + else + { + // Otherwise dealloc it + currentOffset = m_pVars[var].offset; + } + } + } + +#ifdef DEBUG + if (m_verbose) + { + printf("active vars:"); + for (int i = 0; i < m_pActiveVars->GetSize(); i++) + { + int32_t var = m_pActiveVars->Get(i); + if (m_pVars[var].alive) + printf(" %d (end %d),", var, m_pVars[var].liveEnd); + } + printf("\n"); + } +#endif + insIndex++; + } } - m_totalVarsStackSize = ALIGN_UP_TO(m_totalVarsStackSize, INTERP_STACK_ALIGNMENT); - m_paramAreaOffset = m_totalVarsStackSize; + finalVarsStackSize = ALIGN_UP_TO(finalVarsStackSize, INTERP_STACK_ALIGNMENT); + + // Iterate over all call args locals, update their final offset (aka add td->total_locals_size to them) + // then also update td->total_locals_size to account for this space. + m_paramAreaOffset = finalVarsStackSize; + for (int32_t i = 0; i < m_varsSize; i++) + { + // These are allocated separately at the end of the stack + if (m_pVars[i].callArgs) + { + m_pVars[i].offset += m_paramAreaOffset; + int32_t topOffset = m_pVars[i].offset + m_pVars[i].size; + if (finalVarsStackSize < topOffset) + finalVarsStackSize = topOffset; + } + } + m_totalVarsStackSize = ALIGN_UP_TO(finalVarsStackSize, INTERP_STACK_ALIGNMENT); } diff --git a/src/coreclr/interpreter/datastructs.h b/src/coreclr/interpreter/datastructs.h new file mode 100644 index 00000000000000..14d7f376e8fb5a --- /dev/null +++ b/src/coreclr/interpreter/datastructs.h @@ -0,0 +1,128 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef _DATASTRUCTS_H_ +#define _DATASTRUCTS_H_ + +template +class TArray +{ +private: + int32_t m_size, m_capacity; + T *m_array; + + void Grow() + { + if (m_capacity) + m_capacity *= 2; + else + m_capacity = 16; + + m_array = (T*)realloc(m_array, m_capacity * sizeof(T)); + } +public: + TArray() + { + m_size = 0; + m_capacity = 0; + m_array = NULL; + } + + ~TArray() + { + if (m_capacity > 0) + free(m_array); + } + + int32_t GetSize() + { + return m_size; + } + + int32_t Add(T element) + { + if (m_size == m_capacity) + Grow(); + m_array[m_size] = element; + return m_size++; + } + + T Get(int32_t index) + { + assert(index < m_size); + return m_array[index]; + } + + int32_t Find(T element) + { + for (int i = 0; i < m_size; i++) + { + if (element == m_array[i]) + return i; + } + return -1; + } + + // Assumes elements are unique + void RemoveAt(int32_t index) + { + assert(index < m_size); + m_size--; + // Since this entry is removed, move the last entry into it + if (m_size > 0 && index < m_size) + m_array[index] = m_array[m_size]; + } + + // Assumes elements are unique + void Remove(T element) + { + for (int32_t i = 0; i < m_size; i++) + { + if (element == m_array[i]) + { + RemoveAt(i); + break; + } + } + } + + void Clear() + { + m_size = 0; + } +}; + +// Singly linked list, implemented as a stack +template +struct TSList +{ + T data; + TSList *pNext; + + TSList(T data, TSList *pNext) + { + this->data = data; + this->pNext = pNext; + } + + static TSList* Push(TSList *head, T data) + { + TSList *newHead = new TSList(data, head); + return newHead; + } + + static TSList* Pop(TSList *head) + { + TSList *next = head->pNext; + delete head; + return next; + } + + static void Free(TSList *head) + { + while (head != NULL) + head = Pop(head); + } +}; + +#endif diff --git a/src/coreclr/interpreter/eeinterp.cpp b/src/coreclr/interpreter/eeinterp.cpp index 8af5a051381e6a..7d7960e5ebc88a 100644 --- a/src/coreclr/interpreter/eeinterp.cpp +++ b/src/coreclr/interpreter/eeinterp.cpp @@ -40,6 +40,9 @@ extern "C" INTERP_API ICorJitCompiler* getJit() return &g_CILInterp; } + +static CORINFO_MODULE_HANDLE g_interpModule = NULL; + //**************************************************************************** CorJitResult CILInterp::compileMethod(ICorJitInfo* compHnd, CORINFO_METHOD_INFO* methodInfo, @@ -48,20 +51,34 @@ CorJitResult CILInterp::compileMethod(ICorJitInfo* compHnd, uint32_t* nativeSizeOfCode) { - const char *methodName = compHnd->getMethodNameFromMetadata(methodInfo->ftn, nullptr, nullptr, nullptr, 0); + bool doInterpret; - // TODO: replace this by something like the JIT does to support multiple methods being specified and we don't - // keep fetching it on each call to compileMethod - const char *methodToInterpret = g_interpHost->getStringConfigValue("AltJit"); - bool doInterpret = (methodName != NULL && strcmp(methodName, methodToInterpret) == 0); - g_interpHost->freeStringConfigValue(methodToInterpret); + if (g_interpModule != NULL) + { + if (methodInfo->scope == g_interpModule) + doInterpret = true; + else + doInterpret = false; + } + else + { + const char *methodName = compHnd->getMethodNameFromMetadata(methodInfo->ftn, nullptr, nullptr, nullptr, 0); + + // TODO: replace this by something like the JIT does to support multiple methods being specified and we don't + // keep fetching it on each call to compileMethod + const char *methodToInterpret = g_interpHost->getStringConfigValue("AltJit"); + doInterpret = (methodName != NULL && strcmp(methodName, methodToInterpret) == 0); + g_interpHost->freeStringConfigValue(methodToInterpret); + if (doInterpret) + g_interpModule = methodInfo->scope; + } if (!doInterpret) { return CORJIT_SKIPPED; } - InterpCompiler compiler(compHnd, methodInfo); + InterpCompiler compiler(compHnd, methodInfo, false /* verbose */); InterpMethod *pMethod = compiler.CompileMethod(); int32_t IRCodeSize; diff --git a/src/coreclr/interpreter/interpretershared.h b/src/coreclr/interpreter/interpretershared.h index f977aac32b8dbc..5e8928b840bafd 100644 --- a/src/coreclr/interpreter/interpretershared.h +++ b/src/coreclr/interpreter/interpretershared.h @@ -6,26 +6,24 @@ #ifndef _INTERPRETERSHARED_H_ #define _INTERPRETERSHARED_H_ +#include "intopsshared.h" + #define INTERP_STACK_SLOT_SIZE 8 // Alignment of each var offset on the interpreter stack #define INTERP_STACK_ALIGNMENT 16 // Alignment of interpreter stack at the start of a frame -#define OPDEF(a,b,c,d,e,f) a, -typedef enum -{ -#include "intops.def" - INTOP_LAST -} InterpOpcode; -#undef OPDEF +#define INTERP_METHOD_DESC_TAG 4 // Tag of a MethodDesc in the interp method dataItems struct InterpMethod { CORINFO_METHOD_HANDLE methodHnd; int32_t allocaSize; + void** pDataItems; - InterpMethod(CORINFO_METHOD_HANDLE methodHnd, int32_t allocaSize) + InterpMethod(CORINFO_METHOD_HANDLE methodHnd, int32_t allocaSize, void** pDataItems) { this->methodHnd = methodHnd; this->allocaSize = allocaSize; + this->pDataItems = pDataItems; } }; diff --git a/src/coreclr/interpreter/intops.cpp b/src/coreclr/interpreter/intops.cpp index 7f94eb4a363c2a..94f259d14d10bc 100644 --- a/src/coreclr/interpreter/intops.cpp +++ b/src/coreclr/interpreter/intops.cpp @@ -4,6 +4,7 @@ #include "intops.h" #include +#include // This, instead of an array of pointers, to optimize away a pointer and a relocation per string. struct InterpOpNameCharacters @@ -49,9 +50,15 @@ const InterpOpArgType g_interpOpArgType[] = { #undef OPDEF }; -const uint8_t* InterpNextOp(const uint8_t *ip) +const int32_t* InterpNextOp(const int32_t *ip) { int len = g_interpOpLen[*ip]; + if (len == 0) + { + assert(*ip == INTOP_SWITCH); + len = 3 + ip[2]; + } + return ip + len; } @@ -60,3 +67,105 @@ const char* InterpOpName(int op) return ((const char*)&g_interpOpNameCharacters) + g_interpOpNameOffsets[op]; } +// Information about IL opcodes + +OPCODE_FORMAT const g_CEEOpArgs[] = { +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) args, +#include "opcode.def" +#undef OPDEF +}; + +struct CEEOpNameCharacters +{ +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) char c[sizeof(s)]; +#include "opcode.def" +#undef OPDEF +}; + +const struct CEEOpNameCharacters g_CEEOpNameCharacters = { +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) s, +#include "opcode.def" +#undef OPDEF +}; + +const uint32_t g_CEEOpNameOffsets[] = { +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) offsetof(CEEOpNameCharacters, c), +#include "opcode.def" +#undef OPDEF +}; + +const char* CEEOpName(OPCODE op) +{ + return ((const char*)&g_CEEOpNameCharacters) + g_CEEOpNameOffsets[op]; +} + +// Also updates ip to skip over prefix, if any +OPCODE CEEDecodeOpcode(const uint8_t **pIp) +{ + OPCODE res; + const uint8_t *ip = *pIp; + + if (*ip == 0xFE) + { + // Double byte encoding, offset + ip++; + res = (OPCODE)(*ip + CEE_ARGLIST); + } + else + { + res = (OPCODE)*ip; + } + *pIp = ip; + return res; +} + +int32_t CEEOpcodeSize(const uint8_t *ip, const uint8_t *codeEnd) +{ + const uint8_t *p = ip; + OPCODE opcode = CEEDecodeOpcode(&p); + OPCODE_FORMAT opArgs = g_CEEOpArgs[opcode]; + + size_t size = 0; + + switch (opArgs) + { + case InlineNone: + size = 1; + break; + case InlineString: + case InlineType: + case InlineField: + case InlineMethod: + case InlineTok: + case InlineSig: + case ShortInlineR: + case InlineI: + case InlineBrTarget: + size = 5; + break; + case InlineVar: + size = 3; + break; + case ShortInlineVar: + case ShortInlineI: + case ShortInlineBrTarget: + size = 2; + break; + case InlineR: + case InlineI8: + size = 9; + break; + case InlineSwitch: { + size_t entries = getI4LittleEndian(p + 1); + size = 5 + 4 * entries; + break; + } + default: + assert(0); + } + + if ((ip + size) >= codeEnd) + return -1; + + return (int32_t)((p - ip) + size); +} diff --git a/src/coreclr/interpreter/intops.def b/src/coreclr/interpreter/intops.def index 78cbf4909e74f7..fcdf33aa11575c 100644 --- a/src/coreclr/interpreter/intops.def +++ b/src/coreclr/interpreter/intops.def @@ -8,6 +8,190 @@ OPDEF(INTOP_NOP, "nop", 1, 0, 0, InterpOpNoArgs) OPDEF(INTOP_RET, "ret", 2, 0, 1, InterpOpNoArgs) +OPDEF(INTOP_RET_VT, "ret.vt", 3, 0, 1, InterpOpInt) OPDEF(INTOP_RET_VOID, "ret.void", 1, 0, 0, InterpOpNoArgs) OPDEF(INTOP_LDC_I4, "ldc.i4", 3, 1, 0, InterpOpInt) +OPDEF(INTOP_LDC_I4_0, "ldc.i4.0", 2, 1, 0, InterpOpNoArgs) +OPDEF(INTOP_LDC_I8_0, "ldc.i8.0", 2, 1, 0, InterpOpNoArgs) + +OPDEF(INTOP_MOV_I4_I1, "mov.i4.i1", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_MOV_I4_U1, "mov.i4.u1", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_MOV_I4_I2, "mov.i4.i2", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_MOV_I4_U2, "mov.i4.u2", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_MOV_4, "mov.4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_MOV_8, "mov.8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_MOV_VT, "mov.vt", 4, 1, 1, InterpOpInt) + +OPDEF(INTOP_LDLOCA, "ldloca", 3, 1, 0, InterpOpInt) + +OPDEF(INTOP_SWITCH, "switch", 0, 0, 1, InterpOpSwitch) + +OPDEF(INTOP_BR, "br", 2, 0, 0, InterpOpBranch) + +OPDEF(INTOP_BRFALSE_I4, "brfalse.i4", 3, 0, 1, InterpOpBranch) +OPDEF(INTOP_BRFALSE_I8, "brfalse.i8", 3, 0, 1, InterpOpBranch) +OPDEF(INTOP_BRTRUE_I4, "brtrue.i4", 3, 0, 1, InterpOpBranch) +OPDEF(INTOP_BRTRUE_I8, "brtrue.i8", 3, 0, 1, InterpOpBranch) + +OPDEF(INTOP_BEQ_I4, "beq.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BEQ_I8, "beq.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BEQ_R4, "beq.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BEQ_R8, "beq.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_I4, "bge.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_I8, "bge.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_R4, "bge.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_R8, "bge.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_I4, "bgt.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_I8, "bgt.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_R4, "bgt.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_R8, "bgt.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_I4, "blt.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_I8, "blt.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_R4, "blt.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_R8, "blt.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_I4, "ble.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_I8, "ble.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_R4, "ble.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_R8, "ble.r8", 4, 0, 2, InterpOpBranch) + +OPDEF(INTOP_BNE_UN_I4, "bne.un.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BNE_UN_I8, "bne.un.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BNE_UN_R4, "bne.un.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BNE_UN_R8, "bne.un.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_UN_I4, "bge.un.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_UN_I8, "bge.un.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_UN_R4, "bge.un.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGE_UN_R8, "bge.un.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_UN_I4, "bgt.un.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_UN_I8, "bgt.un.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_UN_R4, "bgt.un.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BGT_UN_R8, "bgt.un.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_UN_I4, "ble.un.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_UN_I8, "ble.un.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_UN_R4, "ble.un.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLE_UN_R8, "ble.un.r8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_UN_I4, "blt.un.i4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_UN_I8, "blt.un.i8", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_UN_R4, "blt.un.r4", 4, 0, 2, InterpOpBranch) +OPDEF(INTOP_BLT_UN_R8, "blt.un.r8", 4, 0, 2, InterpOpBranch) + +// Unary operations + +OPDEF(INTOP_NEG_I4, "neg.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_NEG_I8, "neg.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_NEG_R4, "neg.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_NEG_R8, "neg.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_NOT_I4, "not.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_NOT_I8, "not.i8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_R_UN_I4, "conv.r.un.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_R_UN_I8, "conv.r.un.i8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_I1_I4, "conv.i1.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I1_I8, "conv.i1.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I1_R4, "conv.i1.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I1_R8, "conv.i1.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_U1_I4, "conv.u1.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U1_I8, "conv.u1.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U1_R4, "conv.u1.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U1_R8, "conv.u1.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_I2_I4, "conv.i2.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I2_I8, "conv.i2.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I2_R4, "conv.i2.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I2_R8, "conv.i2.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_U2_I4, "conv.u2.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U2_I8, "conv.u2.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U2_R4, "conv.u2.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U2_R8, "conv.u2.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_I4_R4, "conv.i4.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I4_R8, "conv.i4.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_U4_R4, "conv.u4.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U4_R8, "conv.u4.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_I8_I4, "conv.i8.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I8_U4, "conv.i8.u4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I8_R4, "conv.i8.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_I8_R8, "conv.i8.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_R4_I4, "conv.r4.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_R4_I8, "conv.r4.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_R4_R8, "conv.r4.r8", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_R8_I4, "conv.r8.i4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_R8_I8, "conv.r8.i8", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_R8_R4, "conv.r8.r4", 3, 1, 1, InterpOpNoArgs) + +OPDEF(INTOP_CONV_U8_R4, "conv.u8.r4", 3, 1, 1, InterpOpNoArgs) +OPDEF(INTOP_CONV_U8_R8, "conv.u8.r8", 3, 1, 1, InterpOpNoArgs) +// Unary operations end + +// Binary operations + +OPDEF(INTOP_ADD_I4, "add.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_ADD_I8, "add.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_ADD_R4, "add.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_ADD_R8, "add.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_SUB_I4, "sub.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SUB_I8, "sub.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SUB_R4, "sub.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SUB_R8, "sub.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_MUL_I4, "mul.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_MUL_I8, "mul.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_MUL_R4, "mul.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_MUL_R8, "mul.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_AND_I4, "and.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_AND_I8, "and.i8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_OR_I4, "or.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_OR_I8, "or.i8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_XOR_I4, "xor.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_XOR_I8, "xor.i8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_SHR_UN_I4, "shr.un.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SHR_UN_I8, "shr.un.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SHL_I4, "shl.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SHL_I8, "shl.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SHR_I4, "shr.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_SHR_I8, "shr.i8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_CEQ_I4, "ceq.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CEQ_I8, "ceq.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CEQ_R4, "ceq.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CEQ_R8, "ceq.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_CGT_I4, "cgt.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CGT_I8, "cgt.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CGT_R4, "cgt.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CGT_R8, "cgt.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_CGT_UN_I4, "cgt.un.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CGT_UN_I8, "cgt.un.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CGT_UN_R4, "cgt.un.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CGT_UN_R8, "cgt.un.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_CLT_I4, "clt.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CLT_I8, "clt.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CLT_R4, "clt.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CLT_R8, "clt.r8", 4, 1, 2, InterpOpNoArgs) + +OPDEF(INTOP_CLT_UN_I4, "clt.un.i4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CLT_UN_I8, "clt.un.i8", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CLT_UN_R4, "clt.un.r4", 4, 1, 2, InterpOpNoArgs) +OPDEF(INTOP_CLT_UN_R8, "clt.un.r8", 4, 1, 2, InterpOpNoArgs) +// Binary operations end + +// Calls +OPDEF(INTOP_CALL, "call", 4, 1, 1, InterpOpMethodToken) + +OPDEF(INTOP_FAILFAST, "failfast", 1, 0, 0, InterpOpNoArgs) diff --git a/src/coreclr/interpreter/intops.h b/src/coreclr/interpreter/intops.h index d058602508f50d..fa64b28a971974 100644 --- a/src/coreclr/interpreter/intops.h +++ b/src/coreclr/interpreter/intops.h @@ -4,19 +4,25 @@ #ifndef _INTOPS_H #define _INTOPS_H +#include "openum.h" #include +#include "intopsshared.h" + typedef enum { InterpOpNoArgs, InterpOpInt, + InterpOpBranch, + InterpOpSwitch, + InterpOpMethodToken, } InterpOpArgType; extern const uint8_t g_interpOpLen[]; extern const int g_interpOpDVars[]; extern const int g_interpOpSVars[]; extern const InterpOpArgType g_interpOpArgType[]; -extern const uint8_t* InterpNextOp(const uint8_t* ip); +extern const int32_t* InterpNextOp(const int32_t* ip); // This, instead of an array of pointers, to optimize away a pointer and a relocation per string. extern const uint32_t g_interpOpNameOffsets[]; @@ -25,4 +31,65 @@ extern const InterpOpNameCharacters g_interpOpNameCharacters; const char* InterpOpName(int op); +extern OPCODE_FORMAT const g_CEEOpArgs[]; +const char* CEEOpName(OPCODE op); +OPCODE CEEDecodeOpcode(const uint8_t **ip); +int CEEOpcodeSize(const uint8_t *ip, const uint8_t *codeEnd); + +#ifdef TARGET_64BIT +#define INTOP_MOV_P INTOP_MOV_8 +#define INTOP_LDNULL INTOP_LDC_I8_0 +#else +#define INTOP_MOV_P INTOP_MOV_4 +#define INTOP_LDNULL INTOP_LDC_I4_0 +#endif + +static inline bool InterpOpIsUncondBranch(int32_t opcode) +{ + return opcode == INTOP_BR; +} + +static inline bool InterpOpIsCondBranch(int32_t opcode) +{ + return opcode >= INTOP_BRFALSE_I4 && opcode <= INTOP_BLT_UN_R8; +} + +// Helpers for reading data from uint8_t code stream +inline uint16_t getU2LittleEndian(const uint8_t* ptr) +{ + return *ptr | *(ptr + 1) << 8; +} + +inline uint32_t getU4LittleEndian(const uint8_t* ptr) +{ + return *ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24; +} + +inline int16_t getI2LittleEndian(const uint8_t* ptr) +{ + return (int16_t)getU2LittleEndian(ptr); +} + +inline int32_t getI4LittleEndian(const uint8_t* ptr) +{ + return (int32_t)getU4LittleEndian(ptr); +} + +inline int64_t getI8LittleEndian(const uint8_t* ptr) +{ + return (int64_t)getI4LittleEndian(ptr) | ((int64_t)getI4LittleEndian(ptr + 4)) << 32; +} + +inline float getR4LittleEndian(const uint8_t* ptr) +{ + int32_t val = getI4LittleEndian(ptr); + return *(float*)&val; +} + +inline double getR8LittleEndian(const uint8_t* ptr) +{ + int64_t val = getI8LittleEndian(ptr); + return *(double*)&val; +} + #endif diff --git a/src/coreclr/interpreter/intopsshared.h b/src/coreclr/interpreter/intopsshared.h new file mode 100644 index 00000000000000..80be6d2f53d946 --- /dev/null +++ b/src/coreclr/interpreter/intopsshared.h @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef _INTOPSSHARED_H_ +#define _INTOPSSHARED_H_ + +#define OPDEF(a,b,c,d,e,f) a, +typedef enum +{ +#include "intops.def" + INTOP_LAST +} InterpOpcode; +#undef OPDEF + +#endif diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 134b749e084fee..6c4a631652e838 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -755,8 +755,8 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse { printf("Copy "); } - else if ((curAssertion->op2.kind == O2K_CONST_INT) || (curAssertion->op2.kind == O2K_CONST_LONG) || - (curAssertion->op2.kind == O2K_CONST_DOUBLE) || (curAssertion->op2.kind == O2K_ZEROOBJ)) + else if ((curAssertion->op2.kind == O2K_CONST_INT) || (curAssertion->op2.kind == O2K_CONST_DOUBLE) || + (curAssertion->op2.kind == O2K_ZEROOBJ)) { printf("Constant "); } @@ -950,10 +950,6 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse } break; - case O2K_CONST_LONG: - printf("0x%016llx", curAssertion->op2.lconVal); - break; - case O2K_CONST_DOUBLE: if (FloatingPointUtils::isNegativeZero(curAssertion->op2.dconVal)) { @@ -1130,39 +1126,28 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser AssertionDsc assertion = {OAK_INVALID}; assert(assertion.assertionKind == OAK_INVALID); - if (op1->OperIs(GT_BOUNDS_CHECK)) + if (op1->OperIs(GT_BOUNDS_CHECK) && (assertionKind == OAK_NO_THROW)) { - if (assertionKind == OAK_NO_THROW) - { - GenTreeBoundsChk* arrBndsChk = op1->AsBoundsChk(); - assertion.assertionKind = assertionKind; - assertion.op1.kind = O1K_ARR_BND; - assertion.op1.bnd.vnIdx = optConservativeNormalVN(arrBndsChk->GetIndex()); - assertion.op1.bnd.vnLen = optConservativeNormalVN(arrBndsChk->GetArrayLength()); - - if ((assertion.op1.bnd.vnIdx == ValueNumStore::NoVN) || (assertion.op1.bnd.vnLen == ValueNumStore::NoVN)) - { - // Don't make an assertion if one of the operands has no VN - return NO_ASSERTION_INDEX; - } - - goto DONE_ASSERTION; - } + GenTreeBoundsChk* arrBndsChk = op1->AsBoundsChk(); + assertion.assertionKind = assertionKind; + assertion.op1.kind = O1K_ARR_BND; + assertion.op1.bnd.vnIdx = optConservativeNormalVN(arrBndsChk->GetIndex()); + assertion.op1.bnd.vnLen = optConservativeNormalVN(arrBndsChk->GetArrayLength()); } - // // Are we trying to make a non-null assertion? // - if (op2 == nullptr) + else if (op2 == nullptr) { - // + if (!varTypeIsGC(op1)) + { + return NO_ASSERTION_INDEX; // Don't make an assertion + } + // Must be an OAK_NOT_EQUAL assertion - // - noway_assert(assertionKind == OAK_NOT_EQUAL); + assert(assertionKind == OAK_NOT_EQUAL); - // // Set op1 to the instance pointer of the indirection - // op1 = op1->gtEffectiveVal(); ssize_t offset = 0; @@ -1184,39 +1169,18 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser } } - if (fgIsBigOffset(offset) || op1->gtOper != GT_LCL_VAR) - { - goto DONE_ASSERTION; // Don't make an assertion - } - - unsigned lclNum = op1->AsLclVarCommon()->GetLclNum(); - LclVarDsc* lclVar = lvaGetDesc(lclNum); - - ValueNum vn; - - // We only perform null-checks on byrefs and GC refs - if (!varTypeIsGC(lclVar->TypeGet())) - { - goto DONE_ASSERTION; // Don't make an assertion - } - - // If the local variable has its address exposed then bail - if (lclVar->IsAddressExposed()) + if (!fgIsBigOffset(offset) && op1->OperIs(GT_LCL_VAR) && !lvaVarAddrExposed(op1->AsLclVar()->GetLclNum())) { - goto DONE_ASSERTION; // Don't make an assertion + assertion.op1.kind = O1K_LCLVAR; + assertion.op1.lcl.lclNum = op1->AsLclVarCommon()->GetLclNum(); + assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); + assertion.op1.vn = optConservativeNormalVN(op1); + assertion.assertionKind = assertionKind; + assertion.op2.kind = O2K_CONST_INT; + assertion.op2.vn = ValueNumStore::VNForNull(); + assertion.op2.u1.iconVal = 0; + assertion.op2.SetIconFlag(GTF_EMPTY); } - - assertion.op1.kind = O1K_LCLVAR; - assertion.op1.lcl.lclNum = lclNum; - assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); - vn = optConservativeNormalVN(op1); - - assertion.op1.vn = vn; - assertion.assertionKind = assertionKind; - assertion.op2.kind = O2K_CONST_INT; - assertion.op2.vn = ValueNumStore::VNForNull(); - assertion.op2.u1.iconVal = 0; - assertion.op2.SetIconFlag(GTF_EMPTY); } // // Are we making an assertion about a local variable? @@ -1264,10 +1228,6 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser } goto CNS_COMMON; - case GT_CNS_LNG: - op2Kind = O2K_CONST_LONG; - goto CNS_COMMON; - case GT_CNS_DBL: op2Kind = O2K_CONST_DOUBLE; goto CNS_COMMON; @@ -1290,9 +1250,8 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser goto DONE_ASSERTION; // Don't make an assertion } - assertion.op2.kind = op2Kind; - assertion.op2.lconVal = 0; - assertion.op2.vn = optConservativeNormalVN(op2); + assertion.op2.kind = op2Kind; + assertion.op2.vn = optConservativeNormalVN(op2); if (op2->gtOper == GT_CNS_INT) { @@ -1308,10 +1267,6 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser assertion.op2.u1.iconVal = iconVal; assertion.op2.SetIconFlag(op2->GetIconHandleFlag(), op2->AsIntCon()->gtFieldSeq); } - else if (op2->gtOper == GT_CNS_LNG) - { - assertion.op2.lconVal = op2->AsLngCon()->gtLconVal; - } else { noway_assert(op2->gtOper == GT_CNS_DBL); @@ -1431,8 +1386,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser ValueNum op2VN = optConservativeNormalVN(op2); // For TP reasons, limited to 32-bit constants on the op2 side. - if ((op1VN != ValueNumStore::NoVN) && (op2VN != ValueNumStore::NoVN) && vnStore->IsVNInt32Constant(op2VN) && - !vnStore->IsVNHandle(op2VN)) + if (vnStore->IsVNInt32Constant(op2VN) && !vnStore->IsVNHandle(op2VN)) { assert(assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL); assertion.assertionKind = assertionKind; @@ -1477,12 +1431,6 @@ AssertionIndex Compiler::optFinalizeCreatingAssertion(AssertionDsc* assertion) { return NO_ASSERTION_INDEX; } - - // TODO: only copy assertions rely on valid SSA number so we could generate more assertions here - if (assertion->op1.lcl.ssaNum == SsaConfig::RESERVED_SSA_NUM) - { - return NO_ASSERTION_INDEX; - } } // Now add the assertion to our assertion table @@ -1764,10 +1712,6 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) switch (assertion->op1.kind) { - case O1K_LCLVAR: - assert(optLocalAssertionProp || - lvaGetDesc(assertion->op1.lcl.lclNum)->lvPerSsaData.IsValidSsaNum(assertion->op1.lcl.ssaNum)); - break; case O1K_ARR_BND: // It would be good to check that bnd.vnIdx and bnd.vnLen are valid value numbers. assert(!optLocalAssertionProp); @@ -1805,14 +1749,6 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) } break; - case O2K_CONST_LONG: - { - // All handles should be represented by O2K_CONST_INT, - // so no handle bits should be set here. - assert(!assertion->op2.HasIconFlag()); - } - break; - case O2K_ZEROOBJ: { // We only make these assertion for stores (not control flow). @@ -1885,8 +1821,8 @@ void Compiler::optCreateComplementaryAssertion(AssertionIndex assertionIndex, Ge if ((candidateAssertion.op1.kind == O1K_LCLVAR) || (candidateAssertion.op1.kind == O1K_VN)) { // "LCLVAR != CNS" is not a useful assertion (unless CNS is 0/1) - if (((candidateAssertion.op2.kind == O2K_CONST_INT) || (candidateAssertion.op2.kind == O2K_CONST_LONG)) && - (candidateAssertion.op2.u1.iconVal != 0) && (candidateAssertion.op2.u1.iconVal != 1)) + if (((candidateAssertion.op2.kind == O2K_CONST_INT)) && (candidateAssertion.op2.u1.iconVal != 0) && + (candidateAssertion.op2.u1.iconVal != 1)) { return; } @@ -1914,59 +1850,6 @@ void Compiler::optCreateComplementaryAssertion(AssertionIndex assertionIndex, Ge } } -// optAssertionGenCast: Create a tentative subrange assertion for a cast. -// -// This function will try to create an assertion that the cast's operand -// is within the "input" range for the cast, so that this assertion can -// later be proven via implication and the cast removed. Such assertions -// are only generated during global propagation, and only for LCL_VARs. -// -// Arguments: -// cast - the cast node for which to create the assertion -// -// Return Value: -// Index of the generated assertion, or NO_ASSERTION_INDEX if it was not -// legal, profitable, or possible to create one. -// -AssertionIndex Compiler::optAssertionGenCast(GenTreeCast* cast) -{ - if (optLocalAssertionProp || !varTypeIsIntegral(cast) || !varTypeIsIntegral(cast->CastOp())) - { - return NO_ASSERTION_INDEX; - } - - // This condition exists to preserve previous behavior. - if (!cast->CastOp()->OperIs(GT_LCL_VAR)) - { - return NO_ASSERTION_INDEX; - } - - GenTreeLclVar* lclVar = cast->CastOp()->AsLclVar(); - LclVarDsc* varDsc = lvaGetDesc(lclVar); - - // It is not useful to make assertions about address-exposed variables, they will never be proven. - if (varDsc->IsAddressExposed()) - { - return NO_ASSERTION_INDEX; - } - - // A representation-changing cast cannot be simplified if it is not checked. - if (!cast->gtOverflow() && (genActualType(cast) != genActualType(lclVar))) - { - return NO_ASSERTION_INDEX; - } - - AssertionDsc assertion = {OAK_SUBRANGE}; - assertion.op1.kind = O1K_LCLVAR; - assertion.op1.vn = vnStore->VNConservativeNormalValue(lclVar->gtVNPair); - assertion.op1.lcl.lclNum = lclVar->GetLclNum(); - assertion.op1.lcl.ssaNum = lclVar->GetSsaNum(); - assertion.op2.kind = O2K_SUBRANGE; - assertion.op2.u2 = IntegralRange::ForCastInput(cast); - - return optFinalizeCreatingAssertion(&assertion); -} - //------------------------------------------------------------------------ // optCreateJtrueAssertions: Create assertions about a JTRUE's relop operands. // @@ -2172,21 +2055,21 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree) // See if we have IND(obj) ==/!= TypeHandle // - if (!optLocalAssertionProp && op1->OperIs(GT_IND)) + if (!optLocalAssertionProp && op1->OperIs(GT_IND) && op1->gtGetOp1()->TypeIs(TYP_REF)) { - ssize_t cnsValue = 0; - GenTreeFlags iconFlags = GTF_EMPTY; - if (op1->gtGetOp1()->TypeIs(TYP_REF) && - optIsTreeKnownIntValue(!optLocalAssertionProp, op2, &cnsValue, &iconFlags)) + ValueNum objVN = optConservativeNormalVN(op1->gtGetOp1()); + ValueNum typeHndVN = optConservativeNormalVN(op2); + + if ((objVN != ValueNumStore::NoVN) && vnStore->IsVNTypeHandle(typeHndVN)) { AssertionDsc assertion; assertion.assertionKind = OAK_EQUAL; assertion.op1.kind = O1K_EXACT_TYPE; - assertion.op1.vn = optConservativeNormalVN(op1->gtGetOp1()); + assertion.op1.vn = objVN; assertion.op2.kind = O2K_CONST_INT; - assertion.op2.u1.iconVal = cnsValue; - assertion.op2.vn = optConservativeNormalVN(op2); - assertion.op2.SetIconFlag(iconFlags); + assertion.op2.u1.iconVal = vnStore->CoercedConstantValue(typeHndVN); + assertion.op2.vn = typeHndVN; + assertion.op2.SetIconFlag(GTF_ICON_CLASS_HDL); AssertionIndex index = optAddAssertion(&assertion); // We don't need to create a complementary assertion here. We're only interested @@ -2293,15 +2176,18 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree) assert(objectNode->TypeIs(TYP_REF, TYP_I_IMPL)); assert(methodTableNode->TypeIs(TYP_I_IMPL)); - if (methodTableNode->OperIs(GT_CNS_INT)) + ValueNum objVN = optConservativeNormalVN(objectNode); + ValueNum typeHndVN = optConservativeNormalVN(methodTableNode); + + if ((objVN != ValueNumStore::NoVN) && vnStore->IsVNTypeHandle(typeHndVN)) { AssertionDsc assertion; assertion.op1.kind = O1K_SUBTYPE; - assertion.op1.vn = optConservativeNormalVN(objectNode); + assertion.op1.vn = objVN; assertion.op2.kind = O2K_CONST_INT; - assertion.op2.u1.iconVal = methodTableNode->AsIntCon()->IconValue(); - assertion.op2.vn = optConservativeNormalVN(methodTableNode); - assertion.op2.SetIconFlag(op2->GetIconHandleFlag()); + assertion.op2.u1.iconVal = vnStore->CoercedConstantValue(typeHndVN); + assertion.op2.vn = typeHndVN; + assertion.op2.SetIconFlag(GTF_ICON_CLASS_HDL); assertion.assertionKind = OAK_EQUAL; AssertionIndex index = optAddAssertion(&assertion); @@ -2343,9 +2229,6 @@ void Compiler::optAssertionGen(GenTree* tree) optAssertionPropCurrentTree = tree; #endif - // For most of the assertions that we create below - // the assertion is true after the tree is processed - bool assertionProven = true; AssertionInfo assertionInfo; switch (tree->OperGet()) { @@ -2370,7 +2253,11 @@ void Compiler::optAssertionGen(GenTree* tree) case GT_ARR_LENGTH: case GT_MDARR_LENGTH: case GT_MDARR_LOWER_BOUND: - assertionInfo = optCreateAssertion(tree->GetIndirOrArrMetaDataAddr(), nullptr, OAK_NOT_EQUAL); + // These indirs (esp. GT_IND and GT_STOREIND) are the most popular sources of assertions. + if (tree->IndirMayFault(this)) + { + assertionInfo = optCreateAssertion(tree->GetIndirOrArrMetaDataAddr(), nullptr, OAK_NOT_EQUAL); + } break; case GT_INTRINSIC: @@ -2408,14 +2295,6 @@ void Compiler::optAssertionGen(GenTree* tree) } break; - case GT_CAST: - // This represets an assertion that we would like to prove to be true. - // If we can prove this assertion true then we can eliminate this cast. - // We only create this assertion for global assertion propagation. - assertionInfo = optAssertionGenCast(tree->AsCast()); - assertionProven = false; - break; - case GT_JTRUE: assertionInfo = optAssertionGenJtrue(tree); break; @@ -2425,7 +2304,7 @@ void Compiler::optAssertionGen(GenTree* tree) break; } - if (assertionInfo.HasAssertion() && assertionProven) + if (assertionInfo.HasAssertion()) { tree->SetAssertionInfo(assertionInfo); } @@ -3355,17 +3234,6 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, newTree->BashToConst(curAssertion->op2.dconVal, tree->TypeGet()); break; - case O2K_CONST_LONG: - if (newTree->TypeIs(TYP_LONG)) - { - newTree->BashToConst(curAssertion->op2.lconVal); - } - else - { - newTree->BashToConst(static_cast(curAssertion->op2.lconVal)); - } - break; - case O2K_CONST_INT: // Don't propagate handles if we need to report relocs. @@ -3760,30 +3628,26 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL continue; } - // Constant prop. - // - // The case where the tree type could be different than the LclVar type is caused by - // gtFoldExpr, specifically the case of a cast, where the fold operation changes the type of the LclVar - // node. In such a case is not safe to perform the substitution since later on the JIT will assert mismatching - // types between trees. - // - if (curAssertion->op1.lcl.lclNum == lclNum) + // Verify types match + if (tree->TypeGet() != lvaGetRealType(lclNum)) { - LclVarDsc* const lclDsc = lvaGetDesc(lclNum); - // Verify types match - if (tree->TypeGet() == lclDsc->lvType) - { - // If local assertion prop, just perform constant prop. - if (optLocalAssertionProp) - { - return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); - } + continue; + } - // If global assertion, perform constant propagation only if the VN's match. - if (curAssertion->op1.vn == vnStore->VNConservativeNormalValue(tree->gtVNPair)) - { - return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); - } + if (optLocalAssertionProp) + { + // Check lclNum in Local Assertion Prop + if (curAssertion->op1.lcl.lclNum == lclNum) + { + return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); + } + } + else + { + // Check VN in Global Assertion Prop + if (curAssertion->op1.vn == vnStore->VNConservativeNormalValue(tree->gtVNPair)) + { + return optConstantAssertionProp(curAssertion, tree, stmt DEBUGARG(assertionIndex)); } } } @@ -6063,10 +5927,6 @@ void Compiler::optImpliedByCopyAssertion(AssertionDsc* copyAssertion, AssertionD usable = op1MatchesCopy && impAssertion->op2.u2.Contains(depAssertion->op2.u2); break; - case O2K_CONST_LONG: - usable = op1MatchesCopy && (impAssertion->op2.lconVal == depAssertion->op2.lconVal); - break; - case O2K_CONST_DOUBLE: // Exact memory match because of positive and negative zero usable = op1MatchesCopy && diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index 49b7ebc20576b8..4fbf60d14169b4 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -574,10 +574,6 @@ enum class BasicBlockVisit // The bbPreds list is initially created by Compiler::fgLinkBasicBlocks() // and is incrementally kept up to date. // -// The edge weight are computed by Compiler::fgComputeEdgeWeights() -// the edge weights are used to straighten conditional branches -// by Compiler::fgReorderBlocks() -// struct FlowEdge { private: diff --git a/src/coreclr/jit/clrjit.natvis b/src/coreclr/jit/clrjit.natvis index 54661833ef8552..58fadf2251da47 100644 --- a/src/coreclr/jit/clrjit.natvis +++ b/src/coreclr/jit/clrjit.natvis @@ -266,6 +266,7 @@ Documentation for VS debugger format specifiers: https://learn.microsoft.com/vis (LcJaggedArrayOptInfo*)this,nd (LcMdArrayOptInfo*)this,nd + (LcSpanOptInfo*)this,nd diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index b26c93534b2f9d..fabf3ec922bf42 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -425,10 +425,6 @@ class CodeGen final : public CodeGenInterface void genOSRSaveRemainingCalleeSavedRegisters(); #endif // TARGET_AMD64 -#if defined(TARGET_RISCV64) - void genStackProbe(ssize_t frameSize, regNumber rOffset, regNumber rLimit, regNumber rPageSize); -#endif - void genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn); void genPoisonFrame(regMaskTP bbRegLiveIn); @@ -1059,6 +1055,8 @@ class CodeGen final : public CodeGenInterface template void genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsic, + instruction ins, + emitAttr attr, regNumber nonConstImmReg, regNumber baseReg, regNumber offsReg, diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index f51023c4305221..01843d0c8b6128 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -2484,8 +2484,11 @@ CodeGen::GenIntCastDesc::GenIntCastDesc(GenTreeCast* cast) } #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // For LoongArch64's ISA which is same with the MIPS64 ISA, even the instructions of 32bits operation need - // the upper 32bits be sign-extended to 64 bits. + // TODO-LOONGARCH64: + // TODO-RISCV64: + // LoongArch64 and RiscV64 ABIs require 32-bit values to be sign-extended to 64-bits. + // We apply the sign-extension unconditionally here to avoid corner case bugs, even + // though it may not be strictly necessary in all cases. m_extendKind = SIGN_EXTEND_INT; #else m_extendKind = COPY; diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index de929110cf7eb1..f7840c2f144a9c 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -1924,7 +1924,40 @@ void CodeGen::genCodeForNegNot(GenTree* tree) // void CodeGen::genCodeForBswap(GenTree* tree) { - NYI_LOONGARCH64("genCodeForBswap unimpleement yet"); + assert(tree->OperIs(GT_BSWAP, GT_BSWAP16)); + + emitAttr attr = emitActualTypeSize(tree); + regNumber targetReg = tree->GetRegNum(); + emitter* emit = GetEmitter(); + + GenTree* operand = tree->gtGetOp1(); + assert(!operand->isContained()); + // The src must be a register. + regNumber operandReg = genConsumeReg(operand); + instruction ins; + + if (tree->OperIs(GT_BSWAP16)) + { + ins = INS_revb_4h; + } + else if (attr == EA_8BYTE) + { + ins = INS_revb_d; + } + else + { + assert(attr == EA_4BYTE); + ins = INS_revb_2w; + } + + emit->emitIns_R_R(ins, attr, targetReg, operandReg); + + if (tree->OperIs(GT_BSWAP16) && !genCanOmitNormalizationForBswap16(tree)) + { + emit->emitIns_R_R_I_I(INS_bstrpick_d, EA_8BYTE, targetReg, targetReg, 15, 0); + } + + genProduceReg(tree); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index b57ffe66b6af5b..7e279ac369dc9d 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -1627,7 +1627,7 @@ void CodeGen::genLclHeap(GenTree* tree) // The SP might already be in the guard page, so we must touch it BEFORE // the alloc, not after. - // ld_w r0, 0(SP) + // tickle the page - this triggers a page fault when on the guard page emit->emitIns_R_R_I(INS_lw, EA_4BYTE, REG_R0, REG_SP, 0); lastTouchDelta = amount; @@ -1672,8 +1672,7 @@ void CodeGen::genLclHeap(GenTree* tree) // and localloc size is a multiple of STACK_ALIGN. // Loop: - ssize_t imm = -16; - emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, imm); + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -16); emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, REG_SPBASE, 8); emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, REG_SPBASE, 0); @@ -1685,8 +1684,8 @@ void CodeGen::genLclHeap(GenTree* tree) emit->emitIns_R_R_I(INS_addi, emitActualTypeSize(type), regCnt, regCnt, -16); - assert(imm == (-4 << 2)); // goto loop. - emit->emitIns_R_R_I(INS_bne, EA_PTRSIZE, regCnt, REG_R0, (-4 << 2)); + // goto Loop + emit->emitIns_R_R_I(INS_bne, EA_PTRSIZE, regCnt, REG_R0, -4 << 2); lastTouchDelta = 0; } @@ -1700,7 +1699,6 @@ void CodeGen::genLclHeap(GenTree* tree) // case SP is on the last byte of the guard page. Thus you must // touch SP-0 first not SP-0x1000. // - // This is similar to the prolog code in CodeGen::genAllocLclFrame(). // // Note that we go through a few hoops so that SP never points to // illegal pages at any time during the tickling process. @@ -1711,23 +1709,20 @@ void CodeGen::genLclHeap(GenTree* tree) // addi regCnt, REG_R0, 0 // // Skip: - // lui regTmp, eeGetPageSize()>>12 + // lui regPageSize, eeGetPageSize()>>12 + // addi regTmp, SP, 0 // Loop: - // lw r0, 0(SP) // tickle the page - read from the page - // sub RA, SP, regTmp // decrement SP by eeGetPageSize() - // bltu RA, regCnt, Done - // sub SP, SP,regTmp - // j Loop + // lw r0, 0(regTmp) // tickle the page - read from the page + // sub regTmp, regTmp, regPageSize + // bgeu regTmp, regCnt, Loop // // Done: - // mov SP, regCnt + // addi SP, regCnt, 0 // if (tempReg == REG_NA) tempReg = internalRegisters.Extract(tree); - regNumber rPageSize = internalRegisters.GetSingle(tree); - assert(regCnt != tempReg); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, tempReg, REG_SPBASE, regCnt); @@ -1738,35 +1733,24 @@ void CodeGen::genLclHeap(GenTree* tree) emit->emitIns_R_R_I(INS_beq, EA_PTRSIZE, tempReg, REG_R0, 2 << 2); emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, regCnt, REG_R0, 0); - emit->emitIns_R_I(INS_lui, EA_PTRSIZE, rPageSize, pageSize >> 12); - - // genDefineTempLabel(loop); - - // tickle the page - Read from the updated SP - this triggers a page fault when on the guard page - emit->emitIns_R_R_I(INS_lw, EA_4BYTE, REG_R0, REG_SPBASE, 0); - - // decrement SP by eeGetPageSize() - emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, tempReg, REG_SPBASE, rPageSize); - - assert(rPageSize != tempReg); - - ssize_t imm = 3 << 2; // goto done. - emit->emitIns_R_R_I(INS_bltu, EA_PTRSIZE, tempReg, regCnt, imm); + regNumber rPageSize = internalRegisters.GetSingle(tree); - emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, rPageSize); + noway_assert(rPageSize != tempReg); - imm = -4 << 2; - // Jump to loop and tickle new stack address - emit->emitIns_I(INS_j, EA_PTRSIZE, imm); + emit->emitIns_R_I(INS_lui, EA_PTRSIZE, rPageSize, pageSize >> 12); + regSet.verifyRegUsed(rPageSize); + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, tempReg, REG_SPBASE, 0); - // Done with stack tickle loop - // genDefineTempLabel(done); + // tickle the page - this triggers a page fault when on the guard page + emit->emitIns_R_R_I(INS_lw, EA_4BYTE, REG_R0, tempReg, 0); + emit->emitIns_R_R_R(INS_sub, EA_4BYTE, tempReg, tempReg, rPageSize); - // Now just move the final value to SP - emit->emitIns_R_R_I(INS_ori, EA_PTRSIZE, REG_SPBASE, regCnt, 0); + emit->emitIns_R_R_I(INS_bgeu, EA_PTRSIZE, tempReg, regCnt, -2 << 2); // lastTouchDelta is dynamic, and can be up to a page. So if we have outgoing arg space, // we're going to assume the worst and probe. + // Move the final value to SP + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, regCnt, 0); } ALLOC_DONE: @@ -6672,175 +6656,6 @@ void CodeGen::genEstablishFramePointer(int delta, bool reportUnwindData) }; } -//------------------------------------------------------------------------ -// genStackProbe: Probe the stack without changing it -// -// Notes: -// This function is using loop to probe each memory page. -// -// Arguments: -// frameSize - total frame size -// rOffset - usually initial register number -// rLimit - an extra register for comparison -// rPageSize - register for storing page size -// -void CodeGen::genStackProbe(ssize_t frameSize, regNumber rOffset, regNumber rLimit, regNumber rPageSize) -{ - // make sure frameSize safely fits within 4 bytes - noway_assert((ssize_t)(int)frameSize == (ssize_t)frameSize); - - const target_size_t pageSize = compiler->eeGetPageSize(); - - // According to RISC-V Privileged ISA page size should be equal 4KiB - noway_assert(pageSize == 0x1000); - - emitter* emit = GetEmitter(); - - emit->emitLoadImmediate(EA_PTRSIZE, rLimit, -frameSize); - regSet.verifyRegUsed(rLimit); - - emit->emitIns_R_R_R(INS_add, EA_PTRSIZE, rLimit, rLimit, REG_SPBASE); - - emit->emitIns_R_I(INS_lui, EA_PTRSIZE, rPageSize, pageSize >> 12); - regSet.verifyRegUsed(rPageSize); - - emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, rOffset, REG_SPBASE, rPageSize); - - // Loop: - // tickle the page - Read from the updated SP - this triggers a page fault when on the guard page - emit->emitIns_R_R_I(INS_lw, EA_4BYTE, REG_R0, rOffset, 0); - emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, rOffset, rOffset, rPageSize); - - // each instr is 4 bytes - // if (rOffset >= rLimit) goto Loop; - emit->emitIns_R_R_I(INS_bge, EA_PTRSIZE, rOffset, rLimit, -2 << 2); -} - -//------------------------------------------------------------------------ -// genAllocLclFrame: Probe the stack. -// -// Notes: -// This only does the probing; allocating the frame is done when callee-saved registers are saved. -// This is done before anything has been pushed. The previous frame might have a large outgoing argument -// space that has been allocated, but the lowest addresses have not been touched. Our frame setup might -// not touch up to the first 504 bytes. This means we could miss a guard page. On Windows, however, -// there are always three guard pages, so we will not miss them all. On Linux, there is only one guard -// page by default, so we need to be more careful. We do an extra probe if we might not have probed -// recently enough. That is, if a call and prolog establishment might lead to missing a page. We do this -// on Windows as well just to be consistent, even though it should not be necessary. -// -// Arguments: -// frameSize - the size of the stack frame being allocated. -// initReg - register to use as a scratch register. -// pInitRegZeroed - OUT parameter. *pInitRegZeroed is set to 'false' if and only if -// this call sets 'initReg' to a non-zero value. Otherwise, it is unchanged. -// maskArgRegsLiveIn - incoming argument registers that are currently live. -// -// Return value: -// None -// -void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn) -{ - assert(compiler->compGeneratingProlog); - - if (frameSize == 0) - { - return; - } - - // According to RISC-V Privileged ISA page size should be equal 4KiB - const target_size_t pageSize = compiler->eeGetPageSize(); - - assert(!compiler->info.compPublishStubParam || (REG_SECRET_STUB_PARAM != initReg)); - - target_size_t lastTouchDelta = 0; - - emitter* emit = GetEmitter(); - - // Emit the following sequence to 'tickle' the pages. - // Note it is important that stack pointer not change until this is complete since the tickles - // could cause a stack overflow, and we need to be able to crawl the stack afterward - // (which means the stack pointer needs to be known). - - if (frameSize < pageSize) - { - // no probe needed - lastTouchDelta = frameSize; - } - else if (frameSize < 3 * pageSize) - { - // between 1 and 3 pages we will probe each page without a loop, - // because it is faster that way and doesn't cost us much - lastTouchDelta = frameSize; - - for (target_size_t probeOffset = pageSize; probeOffset <= frameSize; probeOffset += pageSize) - { - emit->emitIns_R_I(INS_lui, EA_PTRSIZE, initReg, probeOffset >> 12); - regSet.verifyRegUsed(initReg); - - emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, initReg, REG_SPBASE, initReg); - emit->emitIns_R_R_I(INS_lw, EA_4BYTE, REG_R0, initReg, 0); - - lastTouchDelta -= pageSize; - } - - assert(pInitRegZeroed != nullptr); - *pInitRegZeroed = false; // The initReg does not contain zero - - assert(lastTouchDelta == frameSize % pageSize); - compiler->unwindPadding(); - } - else - { - // probe each page, that we need to allocate large stack frame - assert(frameSize >= 3 * pageSize); - - regMaskTP availMask = RBM_ALLINT & (regSet.rsGetModifiedRegsMask() | ~RBM_INT_CALLEE_SAVED); - availMask &= ~maskArgRegsLiveIn; // Remove all of the incoming argument registers - // as they are currently live - availMask &= ~genRegMask(initReg); // Remove the pre-calculated initReg - - noway_assert(availMask != RBM_NONE); - - regMaskTP regMask = genFindLowestBit(availMask); - regNumber rLimit = genRegNumFromMask(regMask); - - availMask &= ~regMask; // Remove rLimit register - - noway_assert(availMask != RBM_NONE); - - regMask = genFindLowestBit(availMask); - regNumber rPageSize = genRegNumFromMask(regMask); - - genStackProbe((ssize_t)frameSize, initReg, rLimit, rPageSize); - - assert(pInitRegZeroed != nullptr); - *pInitRegZeroed = false; // The initReg does not contain zero - - lastTouchDelta = frameSize % pageSize; - compiler->unwindPadding(); - } - -#if STACK_PROBE_BOUNDARY_THRESHOLD_BYTES != 0 - // if the last page was too far, we will make an extra probe at the bottom - if (lastTouchDelta + STACK_PROBE_BOUNDARY_THRESHOLD_BYTES > pageSize) - { - assert(lastTouchDelta + STACK_PROBE_BOUNDARY_THRESHOLD_BYTES < pageSize << 1); - - emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, initReg, REG_R0, frameSize); - regSet.verifyRegUsed(initReg); - - emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, initReg, REG_SPBASE, initReg); - emit->emitIns_R_R_I(INS_lw, EA_4BYTE, REG_R0, initReg, 0); - - assert(pInitRegZeroed != nullptr); - *pInitRegZeroed = false; // The initReg does not contain zero - - compiler->unwindPadding(); - } -#endif -} - void CodeGen::genJumpToThrowHlpBlk_la( SpecialCodeKind codeKind, instruction ins, regNumber reg1, BasicBlock* failBlk, regNumber reg2) { diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 4b14b8d1c451dd..0f41ad622f8e82 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -2200,13 +2200,22 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) #if defined(FEATURE_EH_WINDOWS_X86) case GT_END_LFIN: + { + // Find the eh table entry via the eh ID + // + unsigned const ehID = (unsigned)treeNode->AsVal()->gtVal1; + assert(ehID < compiler->compEHID); + assert(compiler->m_EHIDtoEHblkDsc != nullptr); + + EHblkDsc* HBtab = nullptr; + bool found = compiler->m_EHIDtoEHblkDsc->Lookup(ehID, &HBtab); + assert(found); + assert(HBtab != nullptr); // Have to clear the ShadowSP of the nesting level which encloses the finally. Generates: // mov dword ptr [ebp-0xC], 0 // for some slot of the ShadowSP local var - - size_t finallyNesting; - finallyNesting = treeNode->AsVal()->gtVal1; - noway_assert(treeNode->AsVal()->gtVal1 < compiler->compHndBBtabCount); + // + const size_t finallyNesting = HBtab->ebdHandlerNestingLevel; noway_assert(finallyNesting < compiler->compHndBBtabCount); // The last slot is reserved for ICodeManager::FixContext(ppEndRegion) @@ -2220,6 +2229,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) GetEmitter()->emitIns_S_I(INS_mov, EA_PTRSIZE, compiler->lvaShadowSPslotsVar, (unsigned)curNestingSlotOffs, 0); break; + } #endif // FEATURE_EH_WINDOWS_X86 case GT_PINVOKE_PROLOG: @@ -4798,17 +4808,16 @@ instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type) // tree - the bit shift node (that specifies the type of bit shift to perform). // // Assumptions: -// a) All GenTrees are register allocated. -// b) The shift-by-amount in tree->AsOp()->gtOp2 is either a contained constant or -// it's a register-allocated expression. If it is in a register that is -// not RCX, it will be moved to RCX (so RCX better not be in use!). +// The shift-by-amount in tree->AsOp()->gtOp2 is either a contained constant or it's a +// register-allocated expression. If not using BMI2 instructions and op2 is in a register +// that is not RCX, it will be moved to RCX (so RCX better not be in use!). // void CodeGen::genCodeForShift(GenTree* tree) { // Only the non-RMW case here. assert(tree->OperIsShiftOrRotate()); - assert(tree->AsOp()->gtOp1->isUsedFromReg()); assert(tree->GetRegNum() != REG_NA); + assert(tree->AsOp()->gtOp1->isUsedFromReg() || compiler->compIsaSupportedDebugOnly(InstructionSet_BMI2)); genConsumeOperands(tree->AsOp()); @@ -4819,12 +4828,13 @@ void CodeGen::genCodeForShift(GenTree* tree) regNumber operandReg = operand->GetRegNum(); GenTree* shiftBy = tree->gtGetOp2(); + emitAttr size = emitTypeSize(tree); if (shiftBy->isContainedIntOrIImmed()) { - emitAttr size = emitTypeSize(tree); + assert(tree->OperIsRotate() || (operandReg != REG_NA)); - bool mightOptimizeLsh = tree->OperIs(GT_LSH) && !tree->gtOverflowEx() && !tree->gtSetFlags(); + bool mightOptimizeLsh = tree->OperIs(GT_LSH) && !tree->gtSetFlags(); // Optimize "X<<1" to "lea [reg+reg]" or "add reg, reg" if (mightOptimizeLsh && shiftBy->IsIntegralConst(1)) @@ -4838,14 +4848,14 @@ void CodeGen::genCodeForShift(GenTree* tree) GetEmitter()->emitIns_R_ARX(INS_lea, size, tree->GetRegNum(), operandReg, operandReg, 1, 0); } } - // Optimize "X<<2" to "lea [reg*4]" - we only do this when the dst and src registers are different since it will - // remove a 'mov'. + // Optimize "X<<2" to "lea [reg*4]" + // We only do this when the dst and src registers are different since it will remove a 'mov'. else if (mightOptimizeLsh && shiftBy->IsIntegralConst(2) && tree->GetRegNum() != operandReg) { GetEmitter()->emitIns_R_ARX(INS_lea, size, tree->GetRegNum(), REG_NA, operandReg, 4, 0); } - // Optimize "X<<3" to "lea [reg*8]" - we only do this when the dst and src registers are different since it will - // remove a 'mov'. + // Optimize "X<<3" to "lea [reg*8]" + // We only do this when the dst and src registers are different since it will remove a 'mov'. else if (mightOptimizeLsh && shiftBy->IsIntegralConst(3) && tree->GetRegNum() != operandReg) { GetEmitter()->emitIns_R_ARX(INS_lea, size, tree->GetRegNum(), REG_NA, operandReg, 8, 0); @@ -4854,53 +4864,54 @@ void CodeGen::genCodeForShift(GenTree* tree) { int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue(); -#if defined(TARGET_64BIT) - // Try to emit rorx if BMI2 is available instead of mov+rol - // it makes sense only for 64bit integers - if ((genActualType(targetType) == TYP_LONG) && (tree->GetRegNum() != operandReg) && - compiler->compOpportunisticallyDependsOn(InstructionSet_BMI2) && tree->OperIs(GT_ROL, GT_ROR) && - (shiftByValue > 0) && (shiftByValue < 64)) + if (tree->OperIsRotate() && compiler->compOpportunisticallyDependsOn(InstructionSet_BMI2)) { - const int value = tree->OperIs(GT_ROL) ? (64 - shiftByValue) : shiftByValue; - GetEmitter()->emitIns_R_R_I(INS_rorx, size, tree->GetRegNum(), operandReg, value); - genProduceReg(tree); - return; + // If we have a contained source operand, we must emit rorx. + // We may also use rorx for 64bit values when a mov would otherwise be required, + // because rorx is smaller than mov+rol/ror when REX prefix is included. + + if ((operandReg == REG_NA) || ((varTypeIsLong(targetType) && (tree->GetRegNum() != operandReg)))) + { + // There is no 'rolx', so for rol, we use rorx with the shift value adjusted. + if (tree->OperIs(GT_ROL)) + { + shiftByValue &= (size * BITS_PER_BYTE - 1); + shiftByValue = (size * BITS_PER_BYTE - shiftByValue); + } + + inst_RV_TT_IV(INS_rorx, size, tree->GetRegNum(), operand, shiftByValue, INS_OPTS_NONE); + genProduceReg(tree); + return; + } } -#endif + ins = genMapShiftInsToShiftByConstantIns(ins, shiftByValue); GetEmitter()->emitIns_BASE_R_R_I(ins, emitTypeSize(tree), tree->GetRegNum(), operandReg, shiftByValue); genProduceReg(tree); return; } } -#if defined(TARGET_64BIT) else if (tree->OperIsShift() && compiler->compOpportunisticallyDependsOn(InstructionSet_BMI2)) { - // Try to emit shlx, sarx, shrx if BMI2 is available instead of mov+shl, mov+sar, mov+shr. + // Emit shlx, sarx, shrx if BMI2 is available instead of mov+shl, mov+sar, mov+shr. switch (tree->OperGet()) { case GT_LSH: ins = INS_shlx; break; - case GT_RSH: ins = INS_sarx; break; - case GT_RSZ: ins = INS_shrx; break; - default: unreached(); } - regNumber shiftByReg = shiftBy->GetRegNum(); - emitAttr size = emitTypeSize(tree); - // The order of operandReg and shiftByReg are swapped to follow shlx, sarx and shrx encoding spec. - GetEmitter()->emitIns_R_R_R(ins, size, tree->GetRegNum(), shiftByReg, operandReg); + // The order of operand and shiftBy are swapped to follow shlx, sarx and shrx encoding spec. + inst_RV_RV_TT(ins, size, tree->GetRegNum(), shiftBy->GetRegNum(), operand, /*isRMW*/ false, INS_OPTS_NONE); } -#endif else { // We must have the number of bits to shift stored in ECX, since we constrained this node to @@ -5674,6 +5685,13 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree) // These intrinsics are "ins reg/mem, xmm" ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); attr = emitActualTypeSize(baseType); +#if defined(TARGET_X86) + if (varTypeIsLong(baseType)) + { + ins = INS_movq; + attr = EA_8BYTE; + } +#endif // TARGET_X86 break; } @@ -9126,10 +9144,6 @@ void CodeGen::genAmd64EmitterUnitTestsApx() theEmitter->emitIns_R_R_I(INS_shld, EA_4BYTE, REG_EAX, REG_ECX, 5); theEmitter->emitIns_R_R_I(INS_shrd, EA_2BYTE, REG_EAX, REG_ECX, 5); - // TODO-XArch-apx: S_R_I path only accepts SEE or VEX instructions, - // so I assuem shld/shrd will not be taking the first argument from stack. - // theEmitter->emitIns_S_R_I(INS_shld, EA_2BYTE, 1, 2, REG_EAX, 5); - // theEmitter->emitIns_S_R_I(INS_shrd, EA_2BYTE, 1, 2, REG_EAX, 5); theEmitter->emitIns_AR_R(INS_cmpxchg, EA_2BYTE, REG_EAX, REG_EDX, 2); @@ -9299,6 +9313,51 @@ void CodeGen::genAmd64EmitterUnitTestsApx() theEmitter->emitIns_BASE_R_R(INS_inc, EA_4BYTE, REG_R11, REG_R12); theEmitter->emitIns_BASE_R_R_I(INS_add, EA_4BYTE, REG_R11, REG_R12, 5); + + // testing for EGPR encodings. + GenTreePhysReg eGPR(REG_R16); + eGPR.SetRegNum(REG_R16); + GenTreeIndir loadGPR = indirForm(TYP_SIMD32, &eGPR); + + // // SIMD instructions + // // In most of the cases, EGPR will only be used as BASE/INDEX registers in SIMD instructions. + theEmitter->emitIns_R_R_A(INS_addps, EA_32BYTE, REG_XMM16, REG_XMM16, &loadGPR); + + // // Legacy instructions + theEmitter->emitIns_R_ARX(INS_add, EA_4BYTE, REG_R16, REG_R17, REG_R18, 1, 0); + + theEmitter->emitIns_AR_R(INS_movnti, EA_8BYTE, REG_R17, REG_R16, 10); + theEmitter->emitIns_R_R_R(INS_andn, EA_8BYTE, REG_R17, REG_R16, REG_R18); + + theEmitter->emitIns_Mov(INS_kmovb_gpr, EA_4BYTE, REG_R16, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovb_msk, EA_4BYTE, REG_K5, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovw_gpr, EA_4BYTE, REG_R16, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovw_msk, EA_4BYTE, REG_K5, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovd_gpr, EA_4BYTE, REG_R16, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovd_msk, EA_4BYTE, REG_K5, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovq_gpr, EA_8BYTE, REG_R16, REG_K0, false); + theEmitter->emitIns_Mov(INS_kmovq_msk, EA_8BYTE, REG_K5, REG_K0, false); + + theEmitter->emitIns_R_R(INS_crc32_apx, EA_1BYTE, REG_R16, REG_R17); + theEmitter->emitIns_R_R(INS_crc32_apx, EA_2BYTE, REG_R16, REG_R17); + theEmitter->emitIns_R_R(INS_crc32_apx, EA_8BYTE, REG_R16, REG_R17); + theEmitter->emitIns_R_A(INS_crc32_apx, EA_8BYTE, REG_R18, &loadGPR); + theEmitter->emitIns_R_S(INS_crc32_apx, EA_8BYTE, REG_R18, 0, 0); + + // Note that BZHI has a reversed src operands due to special handling at import. + theEmitter->emitIns_R_R_R(INS_bzhi, EA_4BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_bzhi, EA_8BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_mulx, EA_4BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_mulx, EA_8BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_pdep, EA_4BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_pdep, EA_8BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_pext, EA_4BYTE, REG_R16, REG_R18, REG_R17); + theEmitter->emitIns_R_R_R(INS_pext, EA_8BYTE, REG_R16, REG_R18, REG_R17); + + theEmitter->emitIns_Mov(INS_movd, EA_4BYTE, REG_R16, REG_XMM0, false); + theEmitter->emitIns_Mov(INS_movd, EA_4BYTE, REG_R16, REG_XMM16, false); + theEmitter->emitIns_Mov(INS_movq, EA_8BYTE, REG_R16, REG_XMM0, false); + theEmitter->emitIns_Mov(INS_movq, EA_8BYTE, REG_R16, REG_XMM16, false); } void CodeGen::genAmd64EmitterUnitTestsAvx10v2() diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index b0797e1b27334f..adf582247da3e2 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1984,9 +1984,34 @@ void Compiler::compSetProcessor() // don't actually exist. The JIT is in charge of adding those and ensuring // the total sum of flags is still valid. #if defined(TARGET_XARCH) - // Get the preferred vector bitwidth, rounding down to the nearest multiple of 128-bits - uint32_t preferredVectorBitWidth = (ReinterpretHexAsDecimal(JitConfig.PreferredVectorBitWidth()) / 128) * 128; - uint32_t preferredVectorByteLength = preferredVectorBitWidth / 8; + // If the VM passed in a virtual vector ISA, it was done to communicate PreferredVectorBitWidth. + // No check is done for the validity of the value, since it will be clamped to max supported by + // hardware and config when queried. We will, therefore, remove the marker ISA and allow it to + // be re-added if appropriate based on the hardware ISA evaluations below. + + uint32_t preferredVectorBitWidth = 0; + if (instructionSetFlags.HasInstructionSet(InstructionSet_Vector128)) + { + instructionSetFlags.RemoveInstructionSet(InstructionSet_Vector128); + preferredVectorBitWidth = 128; + } + else if (instructionSetFlags.HasInstructionSet(InstructionSet_Vector256)) + { + instructionSetFlags.RemoveInstructionSet(InstructionSet_Vector256); + preferredVectorBitWidth = 256; + } + else if (instructionSetFlags.HasInstructionSet(InstructionSet_Vector512)) + { + instructionSetFlags.RemoveInstructionSet(InstructionSet_Vector512); + preferredVectorBitWidth = 512; + } + + opts.preferredVectorByteLength = preferredVectorBitWidth / BITS_PER_BYTE; + + // Only one marker ISA should have been passed in, and it should now be cleared. + assert(!instructionSetFlags.HasInstructionSet(InstructionSet_Vector128) && + !instructionSetFlags.HasInstructionSet(InstructionSet_Vector256) && + !instructionSetFlags.HasInstructionSet(InstructionSet_Vector512)); if (instructionSetFlags.HasInstructionSet(InstructionSet_SSE)) { @@ -2018,20 +2043,6 @@ void Compiler::compSetProcessor() assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512DQ_VL)); instructionSetFlags.AddInstructionSet(InstructionSet_Vector512); - - if ((preferredVectorByteLength == 0) && jitFlags.IsSet(JitFlags::JIT_FLAG_VECTOR512_THROTTLING)) - { - // Some architectures can experience frequency throttling when - // executing 512-bit width instructions. To account for this we set the - // default preferred vector width to 256-bits in some scenarios. Power - // users can override this with `DOTNET_PreferredVectorBitWidth=512` to - // allow using such instructions where hardware support is available. - // - // Do not condition this based on stress mode as it makes the support - // reported inconsistent across methods and breaks expectations/functionality - - preferredVectorByteLength = 256 / 8; - } } else { @@ -2039,8 +2050,6 @@ void Compiler::compSetProcessor() assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX10v1)); } } - - opts.preferredVectorByteLength = preferredVectorByteLength; #elif defined(TARGET_ARM64) if (instructionSetFlags.HasInstructionSet(InstructionSet_AdvSimd)) { @@ -2574,6 +2583,18 @@ void Compiler::compInitOptions(JitFlags* jitFlags) #endif // DEBUG } + bool enableInliningMethodsWithEH = JitConfig.JitInlineMethodsWithEH() > 0; + +#ifdef DEBUG + static ConfigMethodRange JitInlineMethodsWithEHRange; + JitInlineMethodsWithEHRange.EnsureInit(JitConfig.JitInlineMethodsWithEHRange()); + const unsigned hash = impInlineRoot()->info.compMethodHash(); + const bool inRange = JitInlineMethodsWithEHRange.Contains(hash); + enableInliningMethodsWithEH &= inRange; +#endif + + opts.compInlineMethodsWithEH = enableInliningMethodsWithEH; + if (compIsForInlining()) { return; @@ -5021,17 +5042,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // We won't introduce new blocks from here on out, // so run the new block layout. // - if (JitConfig.JitDoReversePostOrderLayout()) - { - DoPhase(this, PHASE_OPTIMIZE_LAYOUT, &Compiler::fgSearchImprovedLayout); - } - else - { - // If we didn't run 3-opt, we might still have a profile-aware DFS tree computed during LSRA available. - // This tree's presence can trigger asserts if pre/postorder numbers are recomputed, - // so invalidate the tree either way. - fgInvalidateDfsTree(); - } + DoPhase(this, PHASE_OPTIMIZE_LAYOUT, &Compiler::fgSearchImprovedLayout); // Now that the flowgraph is finalized, run post-layout optimizations. // @@ -5207,6 +5218,21 @@ void Compiler::FinalizeEH() lvaSetVarAddrExposed(lvaShadowSPslotsVar DEBUGARG(AddressExposedReason::EXTERNALLY_VISIBLE_IMPLICITLY)); } + // Build up a mapping from EH IDs to EHblkDsc* + // + assert(m_EHIDtoEHblkDsc == nullptr); + + if (compHndBBtabCount > 0) + { + m_EHIDtoEHblkDsc = new (getAllocator()) EHIDtoEHblkDscMap(getAllocator()); + + for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) + { + EHblkDsc* const HBtab = &compHndBBtab[XTnum]; + m_EHIDtoEHblkDsc->Set(HBtab->ebdID, HBtab); + } + } + #endif // FEATURE_EH_WINDOWS_X86 // We should not make any more alterations to the EH table structure. diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 9d265af58c019f..1be19a765767c7 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -506,19 +506,6 @@ enum class AddressExposedReason class LclVarDsc { public: - // The constructor. Most things can just be zero'ed. - // - // Initialize the ArgRegs to REG_STK. - LclVarDsc() - : _lvArgReg(REG_STK) -#if FEATURE_MULTIREG_ARGS - , _lvOtherArgReg(REG_STK) -#endif // FEATURE_MULTIREG_ARGS - , lvClassHnd(NO_CLASS_HANDLE) - , lvPerSsaData() - { - } - // note this only packs because var_types is a typedef of unsigned char var_types lvType : 5; // TYP_INT/LONG/FLOAT/DOUBLE/REF @@ -778,13 +765,6 @@ class LclVarDsc regNumberSmall _lvOtherReg; // Used for "upper half" of long var. #endif // !defined(TARGET_64BIT) - regNumberSmall _lvArgReg; // The (first) register in which this argument is passed. - -#if FEATURE_MULTIREG_ARGS - regNumberSmall _lvOtherArgReg; // Used for the second part of the struct passed in a register. - // Note this is defined but not used by ARM32 -#endif // FEATURE_MULTIREG_ARGS - regNumberSmall _lvArgInitReg; // the register into which the argument is moved at entry public: @@ -997,7 +977,7 @@ class LclVarDsc unsigned lvSlotNum; // original slot # (if remapped) // class handle for the local or null if not known or not a class - CORINFO_CLASS_HANDLE lvClassHnd; + CORINFO_CLASS_HANDLE lvClassHnd = NO_CLASS_HANDLE; private: ClassLayout* m_layout; // layout info for structs @@ -2722,8 +2702,12 @@ class Compiler // etc. unsigned ehMaxHndNestingCount = 0; + typedef JitHashTable, EHblkDsc*> EHIDtoEHblkDscMap; + EHIDtoEHblkDscMap* m_EHIDtoEHblkDsc = nullptr; + #endif // FEATURE_EH_WINDOWS_X86 + EHblkDsc* ehFindEHblkDscById(unsigned short ehID); bool ehTableFinalized = false; void FinalizeEH(); @@ -3356,11 +3340,19 @@ class Compiler GenTree* gtNewSimdRoundNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdShuffleVariableNode(var_types type, + GenTree* op1, + GenTree* op2, + CorInfoType simdBaseJitType, + unsigned simdSize, + bool isShuffleNative); + GenTree* gtNewSimdShuffleNode(var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, - unsigned simdSize); + unsigned simdSize, + bool isShuffleNative); GenTree* gtNewSimdSqrtNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); @@ -3963,7 +3955,7 @@ class Compiler unsigned lvaInlineeReturnSpillTemp = BAD_VAR_NUM; // The temp to spill the non-VOID return expression // in case there are multiple BBJ_RETURN blocks in the inlinee // or if the inlinee has GC ref locals. - + bool lvaInlineeReturnSpillTempFreshlyCreated = false; // True if the temp was freshly created for the inlinee return #if FEATURE_FIXED_OUT_ARGS @@ -4491,7 +4483,7 @@ class Compiler CompAllocator alloc(compiler->getAllocator(CMK_Generic)); compiler->impEnumeratorGdvLocalMap = new (alloc) NodeToUnsignedMap(alloc); } - + return compiler->impEnumeratorGdvLocalMap; } @@ -4685,7 +4677,11 @@ class Compiler bool mustExpand); #ifdef FEATURE_HW_INTRINSICS - bool IsValidForShuffle(GenTreeVecCon* vecCon, unsigned simdSize, var_types simdBaseType) const; + bool IsValidForShuffle(GenTree* indices, + unsigned simdSize, + var_types simdBaseType, + bool* canBecomeValid, + bool isShuffleNative) const; GenTree* impHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, @@ -5505,6 +5501,7 @@ class Compiler void fgExpandQmarkNodes(); bool fgSimpleLowerCastOfSmpOp(LIR::Range& range, GenTreeCast* cast); + bool fgSimpleLowerBswap16(LIR::Range& range, GenTree* op); #if FEATURE_LOOP_ALIGN bool shouldAlignLoop(FlowGraphNaturalLoop* loop, BasicBlock* top); @@ -6188,7 +6185,6 @@ class Compiler PhaseStatus fgComputeBlockWeights(); bool fgComputeMissingBlockWeights(); - bool fgReorderBlocks(bool useProfile); PhaseStatus fgSearchImprovedLayout(); template @@ -6670,7 +6666,7 @@ class Compiler GenTree* fgMorphCopyBlock(GenTree* tree); private: GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr); - void fgTryReplaceStructLocalWithFields(GenTree** use); + bool fgTryReplaceStructLocalWithFields(GenTree** use); GenTree* fgMorphFinalizeIndir(GenTreeIndir* indir); GenTree* fgOptimizeCast(GenTreeCast* cast); GenTree* fgOptimizeCastOnStore(GenTree* store); @@ -7741,7 +7737,6 @@ class Compiler O2K_INVALID, O2K_LCLVAR_COPY, O2K_CONST_INT, - O2K_CONST_LONG, O2K_CONST_DOUBLE, O2K_ZEROOBJ, O2K_SUBRANGE, @@ -7780,17 +7775,13 @@ class Compiler ValueNum vn; struct IntVal { - ssize_t iconVal; // integer -#if !defined(HOST_64BIT) - unsigned padding; // unused; ensures iconFlags does not overlap lconVal -#endif + ssize_t iconVal; // integer FieldSeq* fieldSeq; }; union { SsaVar lcl; IntVal u1; - int64_t lconVal; double dconVal; IntegralRange u2; }; @@ -7932,9 +7923,6 @@ class Compiler case O2K_CONST_INT: return ((op2.u1.iconVal == that->op2.u1.iconVal) && (op2.GetIconFlag() == that->op2.GetIconFlag())); - case O2K_CONST_LONG: - return (op2.lconVal == that->op2.lconVal); - case O2K_CONST_DOUBLE: // exact match because of positive and negative zero. return (memcmp(&op2.dconVal, &that->op2.dconVal, sizeof(double)) == 0); @@ -8182,6 +8170,7 @@ class Compiler bool optIsStackLocalInvariant(FlowGraphNaturalLoop* loop, unsigned lclNum); bool optExtractArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsNum, bool* topLevelIsFinal); + bool optExtractSpanIndex(GenTree* tree, SpanIndex* result); bool optReconstructArrIndexHelp(GenTree* tree, ArrIndex* result, unsigned lhsNum, bool* topLevelIsFinal); bool optReconstructArrIndex(GenTree* tree, ArrIndex* result); bool optIdentifyLoopOptInfo(FlowGraphNaturalLoop* loop, LoopCloneContext* context); @@ -10474,6 +10463,9 @@ class Compiler // Collect 64 bit counts for PGO data. bool compCollect64BitCounts; + // Allow inlining of methods with EH. + bool compInlineMethodsWithEH; + } opts; static bool s_pAltJitExcludeAssembliesListInitialized; @@ -10977,9 +10969,10 @@ class Compiler size_t compInfoBlkSize; BYTE* compInfoBlkAddr; - EHblkDsc* compHndBBtab = nullptr; // array of EH data - unsigned compHndBBtabCount = 0; // element count of used elements in EH data array - unsigned compHndBBtabAllocCount = 0; // element count of allocated elements in EH data array + EHblkDsc* compHndBBtab = nullptr; // array of EH data + unsigned compHndBBtabCount = 0; // element count of used elements in EH data array + unsigned compHndBBtabAllocCount = 0; // element count of allocated elements in EH data array + unsigned short compEHID = 0; // unique ID for EH data array entries #if defined(FEATURE_EH_WINDOWS_X86) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index a1e706fde6083e..ec44e86e45ef04 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1110,6 +1110,31 @@ inline regNumber genFirstRegNumFromMaskAndToggle(SingleTypeRegSet& mask, var_typ return regNum; } +//------------------------------------------------------------------------------ +// genFirstRegNumFromMaskAndToggle : Maps first bit set in the register mask to a +// register number and also toggle the bit in the `mask`. +// Arguments: +// mask - the register mask +// type - type of the register mask +// +// Return Value: +// The number of the first register contained in the mask and updates the `mask` to toggle +// the bit. +// + +inline regNumber genFirstRegNumFromMaskAndToggle(SingleTypeRegSet& mask) +{ + assert(mask != RBM_NONE); // Must have one bit set, so can't have a mask of zero + + /* Convert the mask to a register number */ + + regNumber regNum = (regNumber)BitOperations::BitScanForward(mask); + + mask ^= genSingleTypeRegMask(regNum); + + return regNum; +} + /***************************************************************************** * * Return the size in bytes of the given type. diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp index 844263d400cfdb..0461a12d181d3a 100644 --- a/src/coreclr/jit/decomposelongs.cpp +++ b/src/coreclr/jit/decomposelongs.cpp @@ -78,11 +78,11 @@ void DecomposeLongs::DecomposeBlock(BasicBlock* block) // Return Value: // None. // -void DecomposeLongs::DecomposeRange(Compiler* compiler, LIR::Range& range) +void DecomposeLongs::DecomposeRange(Compiler* compiler, Lowering* lowering, LIR::Range& range) { assert(compiler != nullptr); - DecomposeLongs decomposer(compiler); + DecomposeLongs decomposer(compiler, lowering); decomposer.m_range = ⦥ decomposer.DecomposeRangeHelper(); @@ -90,7 +90,7 @@ void DecomposeLongs::DecomposeRange(Compiler* compiler, LIR::Range& range) //------------------------------------------------------------------------ // DecomposeLongs::DecomposeRangeHelper: -// Decompiose each node in the current range. +// Decompose each node in the current range. // // Decomposition is done as an execution-order walk. Decomposition of // a particular node can create new nodes that need to be further @@ -122,44 +122,76 @@ void DecomposeLongs::DecomposeRangeHelper() GenTree* DecomposeLongs::DecomposeNode(GenTree* tree) { // Handle the case where we are implicitly using the lower half of a long lclVar. - if ((tree->TypeGet() == TYP_INT) && tree->OperIsLocal()) + if (tree->TypeIs(TYP_INT) && tree->OperIsLocal()) { LclVarDsc* varDsc = m_compiler->lvaGetDesc(tree->AsLclVarCommon()); if (varTypeIsLong(varDsc) && varDsc->lvPromoted) { -#ifdef DEBUG - if (m_compiler->verbose) - { - printf("Changing implicit reference to lo half of long lclVar to an explicit reference of its promoted " - "half:\n"); - m_compiler->gtDispTreeRange(Range(), tree); - } -#endif // DEBUG + JITDUMP("Changing implicit reference to lo half of long lclVar to an explicit reference of its promoted " + "half:\n"); + DISPTREERANGE(Range(), tree); + unsigned loVarNum = varDsc->lvFieldLclStart; tree->AsLclVarCommon()->SetLclNum(loVarNum); return tree->gtNext; } } - if (tree->TypeGet() != TYP_LONG) + if (!tree->TypeIs(TYP_LONG)) { return tree->gtNext; } -#ifdef DEBUG - if (m_compiler->verbose) - { - printf("Decomposing TYP_LONG tree. BEFORE:\n"); - m_compiler->gtDispTreeRange(Range(), tree); - } -#endif // DEBUG - LIR::Use use; if (!Range().TryGetUse(tree, &use)) { LIR::Use::MakeDummyUse(Range(), tree, &use); } +#if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_X86) + if (!use.IsDummyUse()) + { + // HWIntrinsics can consume/produce a long directly, provided its source/target is memory. + // Here we do a conservative check for specific cases where it is certain the load/store + // can be contained. In those cases, we can skip decomposition. + + GenTree* user = use.User(); + + if (user->OperIsHWIntrinsic()) + { + if (tree->OperIs(GT_CNS_LNG) || + (tree->OperIs(GT_IND, GT_LCL_FLD) && m_lowering->IsSafeToContainMem(user, tree))) + { + NamedIntrinsic intrinsicId = user->AsHWIntrinsic()->GetHWIntrinsicId(); + assert(HWIntrinsicInfo::IsVectorCreate(intrinsicId) || + HWIntrinsicInfo::IsVectorCreateScalar(intrinsicId) || + HWIntrinsicInfo::IsVectorCreateScalarUnsafe(intrinsicId)); + + return tree->gtNext; + } + } + else if (user->OperIs(GT_STOREIND) && tree->OperIsHWIntrinsic() && m_compiler->opts.OptimizationEnabled()) + { + NamedIntrinsic intrinsicId = tree->AsHWIntrinsic()->GetHWIntrinsicId(); + if (HWIntrinsicInfo::IsVectorToScalar(intrinsicId) && m_lowering->IsSafeToContainMem(user, tree)) + { + return tree->gtNext; + } + } + } + + if (tree->OperIs(GT_STOREIND) && tree->AsStoreInd()->Data()->OperIsHWIntrinsic()) + { + // We should only get here if we matched the second pattern above. + assert(HWIntrinsicInfo::IsVectorToScalar(tree->AsStoreInd()->Data()->AsHWIntrinsic()->GetHWIntrinsicId())); + + return tree->gtNext; + } +#endif // FEATURE_HW_INTRINSICS && TARGET_X86 + + JITDUMP("Decomposing TYP_LONG tree. BEFORE:\n"); + DISPTREERANGE(Range(), tree); + GenTree* nextNode = nullptr; switch (tree->OperGet()) { @@ -270,19 +302,14 @@ GenTree* DecomposeLongs::DecomposeNode(GenTree* tree) // If we replaced the argument to a GT_FIELD_LIST element with a GT_LONG node, split that field list // element into two elements: one for each half of the GT_LONG. - if ((use.Def()->OperGet() == GT_LONG) && !use.IsDummyUse() && (use.User()->OperGet() == GT_FIELD_LIST)) + if (use.Def()->OperIs(GT_LONG) && !use.IsDummyUse() && use.User()->OperIs(GT_FIELD_LIST)) { DecomposeFieldList(use.User()->AsFieldList(), use.Def()->AsOp()); } -#ifdef DEBUG - if (m_compiler->verbose) - { - // NOTE: st_lcl_var doesn't dump properly afterwards. - printf("Decomposing TYP_LONG tree. AFTER:\n"); - m_compiler->gtDispTreeRange(Range(), use.Def()); - } -#endif + // NOTE: st_lcl_var doesn't dump properly afterwards. + JITDUMP("Decomposing TYP_LONG tree. AFTER:\n"); + DISPTREERANGE(Range(), use.Def()); // When casting from a decomposed long to a smaller integer we can discard the high part. if (m_compiler->opts.OptimizationEnabled() && !use.IsDummyUse() && use.User()->OperIs(GT_CAST) && @@ -1707,6 +1734,13 @@ GenTree* DecomposeLongs::DecomposeHWIntrinsic(LIR::Use& use) return DecomposeHWIntrinsicGetElement(use, hwintrinsicTree); } + case NI_Vector128_ToScalar: + case NI_Vector256_ToScalar: + case NI_Vector512_ToScalar: + { + return DecomposeHWIntrinsicToScalar(use, hwintrinsicTree); + } + case NI_EVEX_MoveMask: { return DecomposeHWIntrinsicMoveMask(use, hwintrinsicTree); @@ -1751,9 +1785,7 @@ GenTree* DecomposeLongs::DecomposeHWIntrinsicGetElement(LIR::Use& use, GenTreeHW { assert(node == use.Def()); assert(varTypeIsLong(node)); - assert((node->GetHWIntrinsicId() == NI_Vector128_GetElement) || - (node->GetHWIntrinsicId() == NI_Vector256_GetElement) || - (node->GetHWIntrinsicId() == NI_Vector512_GetElement)); + assert(HWIntrinsicInfo::IsVectorGetElement(node->GetHWIntrinsicId())); GenTree* op1 = node->Op(1); GenTree* op2 = node->Op(2); @@ -1835,6 +1867,75 @@ GenTree* DecomposeLongs::DecomposeHWIntrinsicGetElement(LIR::Use& use, GenTreeHW return FinalizeDecomposition(use, loResult, hiResult, hiResult); } +//------------------------------------------------------------------------ +// DecomposeHWIntrinsicToScalar: Decompose GT_HWINTRINSIC -- NI_Vector*_ToScalar. +// +// create: +// +// tmp_simd_var = simd_var +// lo_result = GT_HWINTRINSIC{ToScalar}[int](tmp_simd_var) +// hi_result = GT_HWINTRINSIC{GetElement}[int](tmp_simd_var, 1) +// - or - +// GT_HWINTRINSIC{ToScalar}[int](GT_RSZ(tmp_simd_var, 32)) +// return: GT_LONG(lo_result, hi_result) +// +// Arguments: +// use - the LIR::Use object for the def that needs to be decomposed. +// node - the hwintrinsic node to decompose +// +// Return Value: +// The GT_LONG node wrapping the upper and lower halves. +// +GenTree* DecomposeLongs::DecomposeHWIntrinsicToScalar(LIR::Use& use, GenTreeHWIntrinsic* node) +{ + assert(node == use.Def()); + assert(varTypeIsLong(node)); + assert(HWIntrinsicInfo::IsVectorToScalar(node->GetHWIntrinsicId())); + + GenTree* op1 = node->Op(1); + NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); + var_types simdBaseType = node->GetSimdBaseType(); + unsigned simdSize = node->GetSimdSize(); + + assert(varTypeIsLong(simdBaseType)); + assert(varTypeIsSIMD(op1)); + + GenTree* simdTmpVar = RepresentOpAsLocalVar(op1, node, &node->Op(1)); + unsigned simdTmpVarNum = simdTmpVar->AsLclVarCommon()->GetLclNum(); + JITDUMP("[DecomposeHWIntrinsicToScalar]: Saving op1 tree to a temp var:\n"); + DISPTREERANGE(Range(), simdTmpVar); + + GenTree* loResult = m_compiler->gtNewSimdToScalarNode(TYP_INT, simdTmpVar, CORINFO_TYPE_INT, simdSize); + Range().InsertAfter(simdTmpVar, loResult); + + simdTmpVar = m_compiler->gtNewLclLNode(simdTmpVarNum, simdTmpVar->TypeGet()); + Range().InsertAfter(loResult, simdTmpVar); + + GenTree* hiResult; + if (m_compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + GenTree* one = m_compiler->gtNewIconNode(1); + hiResult = m_compiler->gtNewSimdGetElementNode(TYP_INT, simdTmpVar, one, CORINFO_TYPE_INT, simdSize); + + Range().InsertAfter(simdTmpVar, one, hiResult); + } + else + { + assert(m_compiler->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + GenTree* thirtyTwo = m_compiler->gtNewIconNode(32); + GenTree* shift = m_compiler->gtNewSimdBinOpNode(GT_RSZ, op1->TypeGet(), simdTmpVar, thirtyTwo, + node->GetSimdBaseJitType(), simdSize); + hiResult = m_compiler->gtNewSimdToScalarNode(TYP_INT, shift, CORINFO_TYPE_INT, simdSize); + + Range().InsertAfter(simdTmpVar, thirtyTwo, shift, hiResult); + } + + Range().Remove(node); + + return FinalizeDecomposition(use, loResult, hiResult, hiResult); +} + //------------------------------------------------------------------------ // DecomposeHWIntrinsicMoveMask: Decompose GT_HWINTRINSIC -- NI_EVEX_MoveMask // @@ -2262,6 +2363,13 @@ void DecomposeLongs::TryPromoteLongVar(unsigned lclNum) { return; } +#if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_X86) + if (varDsc->lvIsParam) + { + // Promotion blocks combined read optimizations for SIMD loads of long params + return; + } +#endif // FEATURE_HW_INTRINSICS && TARGET_X86 varDsc->lvFieldCnt = 2; varDsc->lvFieldLclStart = m_compiler->lvaCount; diff --git a/src/coreclr/jit/decomposelongs.h b/src/coreclr/jit/decomposelongs.h index 02681322a552e9..e879292abf4996 100644 --- a/src/coreclr/jit/decomposelongs.h +++ b/src/coreclr/jit/decomposelongs.h @@ -14,19 +14,21 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #define _DECOMPOSELONGS_H_ #include "compiler.h" +#include "lower.h" class DecomposeLongs { public: - DecomposeLongs(Compiler* compiler) + DecomposeLongs(Compiler* compiler, Lowering* lowering) : m_compiler(compiler) + , m_lowering(lowering) { } void PrepareForDecomposition(); void DecomposeBlock(BasicBlock* block); - static void DecomposeRange(Compiler* compiler, LIR::Range& range); + static void DecomposeRange(Compiler* compiler, Lowering* lowering, LIR::Range& range); private: inline LIR::Range& Range() const @@ -64,6 +66,7 @@ class DecomposeLongs #ifdef FEATURE_HW_INTRINSICS GenTree* DecomposeHWIntrinsic(LIR::Use& use); GenTree* DecomposeHWIntrinsicGetElement(LIR::Use& use, GenTreeHWIntrinsic* node); + GenTree* DecomposeHWIntrinsicToScalar(LIR::Use& use, GenTreeHWIntrinsic* node); GenTree* DecomposeHWIntrinsicMoveMask(LIR::Use& use, GenTreeHWIntrinsic* node); #endif // FEATURE_HW_INTRINSICS @@ -80,6 +83,7 @@ class DecomposeLongs // Data Compiler* m_compiler; + Lowering* m_lowering; LIR::Range* m_range; }; diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 3d251f4e7bd192..9df0a0c29e56be 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -29,9 +29,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #define DLLEXPORT #endif // !DLLEXPORT -#if defined(HOST_ANDROID) -#include -#endif +#include "minipal/log.h" /*****************************************************************************/ @@ -150,16 +148,19 @@ FILE* jitstdout() // Like printf/logf, but only outputs to jitstdout -- skips call back into EE. int jitprintf(const char* fmt, ...) { + int status; va_list vl; va_start(vl, fmt); -#if defined(HOST_ANDROID) - int status = jitstdout() == procstdout() - ? __android_log_vprint(ANDROID_LOG_VERBOSE, MAIN_CLR_MODULE_NAME_A, fmt, vl) - : vfprintf(jitstdout(), fmt, vl); -#else - int status = vfprintf(jitstdout(), fmt, vl); -#endif + if (jitstdout() == procstdout()) + { + status = minipal_log_vprint_verbose(fmt, vl); + } + else + { + status = vfprintf(jitstdout(), fmt, vl); + } va_end(vl); + return status; } diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 5574fc0b439194..ef1fd2f701fc15 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1403,6 +1403,13 @@ class emitter { return idHasMemGenWrite() || idHasMemStkWrite() || idHasMemAdrWrite(); } + + bool idHasMemAndCns() const + { + assert((unsigned)idInsFmt() < emitFmtCount); + ID_OPS idOp = (ID_OPS)emitFmtToOps[idInsFmt()]; + return ((idOp == ID_OP_CNS) || (idOp == ID_OP_DSP_CNS) || (idOp == ID_OP_AMD_CNS)); + } #endif // defined(TARGET_XARCH) #ifdef TARGET_ARMARCH insOpts idInsOpt() const @@ -4060,10 +4067,7 @@ emitAttr emitter::emitGetMemOpSize(instrDesc* id, bool ignoreEmbeddedBroadcast) // which case we load either a scalar or full vector; otherwise, // we load a 128-bit vector - assert((unsigned)id->idInsFmt() < emitFmtCount); - ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()]; - - if ((idOp != ID_OP_CNS) && (idOp != ID_OP_SCNS) && (idOp != ID_OP_DSP_CNS) && (idOp != ID_OP_AMD_CNS)) + if (!id->idHasMemAndCns()) { memSize = 16; } @@ -4098,10 +4102,7 @@ emitAttr emitter::emitGetMemOpSize(instrDesc* id, bool ignoreEmbeddedBroadcast) // Embedded broadcast is never supported so if we have a cns operand // we load a full vector; otherwise, we load a 128-bit vector - assert((unsigned)id->idInsFmt() < emitFmtCount); - ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()]; - - if ((idOp != ID_OP_CNS) && (idOp != ID_OP_SCNS) && (idOp != ID_OP_DSP_CNS) && (idOp != ID_OP_AMD_CNS)) + if (!id->idHasMemAndCns()) { memSize = 16; } diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 2b008b2f669e6f..0c5e32c9dbda59 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -92,7 +92,6 @@ size_t emitter::emitSizeOfInsDsc(instrDesc* id) const return sizeof(instrDesc); } - case INS_OPTS_I: case INS_OPTS_RC: case INS_OPTS_RL: case INS_OPTS_RELOC: @@ -2978,56 +2977,6 @@ BYTE* emitter::emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruc return dst; } -BYTE* emitter::emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id) -{ - ssize_t immediate = reinterpret_cast(id->idAddr()->iiaAddr); - const regNumber reg1 = id->idReg1(); - - switch (id->idCodeSize()) - { - case 8: - return emitOutputInstr_OptsI8(dst, id, immediate, reg1); - case 32: - return emitOutputInstr_OptsI32(dst, immediate, reg1); - default: - break; - } - unreached(); - return nullptr; -} - -BYTE* emitter::emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1) -{ - if (id->idReg2()) - { - // special for INT64_MAX or UINT32_MAX - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_R0, WordMask(12)); - const unsigned shiftValue = (immediate == INT64_MAX) ? 1 : 32; - dst += emitOutput_ITypeInstr(dst, INS_srli, reg1, reg1, shiftValue); - } - else - { - dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(immediate)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(immediate)); - } - return dst; -} - -BYTE* emitter::emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber reg1) -{ - const unsigned upperWord = UpperWordOfDoubleWord(immediate); - dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, UpperNBitsOfWordSignExtend<20>(upperWord)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<12>(upperWord)); - const unsigned lowerWord = LowerWordOfDoubleWord(immediate); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 21)); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 11); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<11>(lowerWord >> 10)); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 10); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, reg1, LowerNBitsOfWord<10>(lowerWord)); - return dst; -} - BYTE* emitter::emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins) { assert(id->idAddr()->iiaIsJitDataOffset()); @@ -3282,11 +3231,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dst = emitOutputInstr_OptsReloc(dst, id, &ins); sz = sizeof(instrDesc); break; - case INS_OPTS_I: - dst = emitOutputInstr_OptsI(dst, id); - ins = INS_addi; - sz = sizeof(instrDesc); - break; case INS_OPTS_RC: dst = emitOutputInstr_OptsRc(dst, id, &ins); sz = sizeof(instrDesc); @@ -3366,31 +3310,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) if (vt == TYP_REF || vt == TYP_BYREF) emitGCvarDeadUpd(adr + ofs, dst2 DEBUG_ARG(varNum)); } - // if (emitInsWritesToLclVarStackLocPair(id)) - //{ - // unsigned ofs2 = ofs + TARGET_POINTER_SIZE; - // if (id->idGCrefReg2() != GCT_NONE) - // { - // emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), *dp); - // } - // else - // { - // // If the type of the local is a gc ref type, update the liveness. - // var_types vt; - // if (varNum >= 0) - // { - // // "Regular" (non-spill-temp) local. - // vt = var_types(emitComp->lvaTable[varNum].lvType); - // } - // else - // { - // TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum); - // vt = tmpDsc->tdTempType(); - // } - // if (vt == TYP_REF || vt == TYP_BYREF) - // emitGCvarDeadUpd(adr + ofs2, *dp); - // } - //} } #ifdef DEBUG @@ -3543,6 +3462,22 @@ bool emitter::emitDispBranch( void emitter::emitDispIllegalInstruction(code_t instructionCode) { printf("RISCV64 illegal instruction: 0x%08X\n", instructionCode); + assert(!"RISCV64 illegal instruction"); +} + +void emitter::emitDispImmediate(ssize_t imm, bool newLine /*= true*/, unsigned regBase /*= REG_ZERO*/) +{ + if (emitComp->opts.disDiffable && (regBase != REG_FP) && (regBase != REG_SP)) + { + printf("0xD1FFAB1E"); + } + else + { + printf("%li", imm); + } + + if (newLine) + printf("\n"); } //---------------------------------------------------------------------------------------- @@ -3587,7 +3522,8 @@ void emitter::emitDispInsName( { imm20 |= 0xfff00000; } - printf("lui %s, %d\n", rd, imm20); + printf("lui %s, ", rd); + emitDispImmediate(imm20); return; } case MajorOpcode::Auipc: @@ -3598,7 +3534,8 @@ void emitter::emitDispInsName( { imm20 |= 0xfff00000; } - printf("auipc %s, %d\n", rd, imm20); + printf("auipc %s, ", rd); + emitDispImmediate(imm20); return; } case MajorOpcode::OpImm: @@ -3684,10 +3621,18 @@ void emitter::emitDispInsName( assert(printLength > 0); int paddingLength = kMaxInstructionLength - printLength; - printf("%*s %s, %s", paddingLength, "", RegNames[rd], RegNames[rs1]); + printf("%*s %s, %s, ", paddingLength, "", RegNames[rd], RegNames[rs1]); if (hasImmediate) { - printf(isHex ? ", 0x%x" : ", %d", imm12); + if (opcode2 == 0x0) // ADDI + { + assert(!isHex); + emitDispImmediate(imm12, false, rs1); + } + else + { + printf(isHex ? "0x%x" : "%d", imm12); + } } printf("\n"); @@ -3698,11 +3643,7 @@ void emitter::emitDispInsName( unsigned int opcode2 = (code >> 12) & 0x7; const char* rd = RegNames[(code >> 7) & 0x1f]; const char* rs1 = RegNames[(code >> 15) & 0x1f]; - int imm12 = (((int)code) >> 20); // & 0xfff; - // if (imm12 & 0x800) - //{ - // imm12 |= 0xfffff000; - //} + int imm12 = (((int)code) >> 20); switch (opcode2) { case 0x0: // ADDIW & SEXT.W @@ -3712,7 +3653,8 @@ void emitter::emitDispInsName( } else { - printf("addiw %s, %s, %d\n", rd, rs1, imm12); + printf("addiw %s, %s, ", rd, rs1); + emitDispImmediate(imm12); } return; case 0x1: // SLLIW @@ -3912,44 +3854,29 @@ void emitter::emitDispInsName( case MajorOpcode::Store: { unsigned int opcode2 = (code >> 12) & 0x7; - const char* rs1 = RegNames[(code >> 15) & 0x1f]; - const char* rs2 = RegNames[(code >> 20) & 0x1f]; - int offset = (((code >> 25) & 0x7f) << 5) | ((code >> 7) & 0x1f); + if (opcode2 >= 4) + return emitDispIllegalInstruction(code); + + unsigned rs1Num = (code >> 15) & 0x1f; + const char* rs1 = RegNames[rs1Num]; + const char* rs2 = RegNames[(code >> 20) & 0x1f]; + int offset = (((code >> 25) & 0x7f) << 5) | ((code >> 7) & 0x1f); if (offset & 0x800) { offset |= 0xfffff000; } - switch (opcode2) - { - case 0: // SB - printf("sb %s, %d(%s)\n", rs2, offset, rs1); - return; - case 1: // SH - printf("sh %s, %d(%s)\n", rs2, offset, rs1); - return; - case 2: // SW - printf("sw %s, %d(%s)\n", rs2, offset, rs1); - return; - case 3: // SD - printf("sd %s, %d(%s)\n", rs2, offset, rs1); - return; - default: - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; - } + char width = "bhwd"[opcode2]; + printf("s%c %s, ", width, rs2); + emitDispImmediate(offset, false, rs1Num); + printf("(%s)\n", rs1); + return; } case MajorOpcode::Branch: { unsigned opcode2 = (code >> 12) & 0x7; unsigned rs1 = (code >> 15) & 0x1f; unsigned rs2 = (code >> 20) & 0x1f; - // int offset = (((code >> 31) & 0x1) << 12) | (((code >> 7) & 0x1) << 11) | (((code >> 25) & 0x3f) << 5) | - // (((code >> 8) & 0xf) << 1); - // if (offset & 0x800) - // { - // offset |= 0xfffff000; - // } if (!emitDispBranch(opcode2, rs1, rs2, id, ig)) { emitDispIllegalInstruction(code); @@ -3959,7 +3886,8 @@ void emitter::emitDispInsName( case MajorOpcode::Load: { unsigned int opcode2 = (code >> 12) & 0x7; - const char* rs1 = RegNames[(code >> 15) & 0x1f]; + unsigned rs1Num = (code >> 15) & 0x1f; + const char* rs1 = RegNames[rs1Num]; const char* rd = RegNames[(code >> 7) & 0x1f]; int offset = ((code >> 20) & 0xfff); if (offset & 0x800) @@ -3967,33 +3895,15 @@ void emitter::emitDispInsName( offset |= 0xfffff000; } - switch (opcode2) - { - case 0: // LB - printf("lb %s, %d(%s)\n", rd, offset, rs1); - return; - case 1: // LH - printf("lh %s, %d(%s)\n", rd, offset, rs1); - return; - case 2: // LW - printf("lw %s, %d(%s)\n", rd, offset, rs1); - return; - case 3: // LD - printf("ld %s, %d(%s)\n", rd, offset, rs1); - return; - case 4: // LBU - printf("lbu %s, %d(%s)\n", rd, offset, rs1); - return; - case 5: // LHU - printf("lhu %s, %d(%s)\n", rd, offset, rs1); - return; - case 6: // LWU - printf("lwu %s, %d(%s)\n", rd, offset, rs1); - return; - default: - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; - } + char width = "bhwd"[opcode2 & 0b011]; + char unsign = ((opcode2 & 0b100) != 0) ? 'u' : ' '; + if (width == 'd' && unsign == 'u') + return emitDispIllegalInstruction(code); + + printf("l%c%c %s, ", width, unsign, rd); + emitDispImmediate(offset, false, rs1Num); + printf("(%s)\n", rs1); + return; } case MajorOpcode::Jalr: { @@ -4005,13 +3915,23 @@ void emitter::emitDispInsName( offset |= 0xfffff000; } - if ((rs1 == REG_RA) && (rd == REG_ZERO)) + if ((offset == 0) && (rs1 == REG_RA) && (rd == REG_ZERO)) { printf("ret"); return; } - printf("jalr %s, %d(%s)", RegNames[rd], offset, RegNames[rs1]); + if ((offset == 0) && ((rd == REG_RA) || (rd == REG_ZERO))) + { + const char* name = (rd == REG_RA) ? "jalr" : "jr "; + printf("%s %s", name, RegNames[rs1]); + } + else + { + printf("jalr %s, ", RegNames[rd]); + emitDispImmediate(offset, false); + printf("(%s)", RegNames[rs1]); + } CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie; // Target for ret call is unclear, e.g.: // jalr zero, 0(ra) @@ -4034,9 +3954,10 @@ void emitter::emitDispInsName( { offset |= 0xfff00000; } - if (rd == REG_ZERO) + if ((rd == REG_ZERO) || (rd == REG_RA)) { - printf("j "); + const char* name = (rd == REG_RA) ? "jal" : "j "; + printf("%s ", name); if (id->idIsBound()) { @@ -4044,12 +3965,15 @@ void emitter::emitDispInsName( } else { - printf("pc%+d instructions", offset >> 2); + printf("pc%+"); + emitDispImmediate(offset / sizeof(code_t)); + printf(" instructions"); } } else { - printf("jal %s, %d", RegNames[rd], offset); + printf("jal %s, ", RegNames[rd]); + emitDispImmediate(offset, false); } CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie; if (handle != 0) @@ -4430,50 +4354,43 @@ void emitter::emitDispInsName( case MajorOpcode::StoreFp: { unsigned int opcode2 = (code >> 12) & 0x7; + if ((opcode2 != 2) && (opcode2 != 3)) + return emitDispIllegalInstruction(code); - const char* rs1 = RegNames[(code >> 15) & 0x1f]; + unsigned rs1Num = (code >> 15) & 0x1f; + const char* rs1 = RegNames[rs1Num]; const char* rs2 = RegNames[((code >> 20) & 0x1f) | 0x20]; int offset = (((code >> 25) & 0x7f) << 5) | ((code >> 7) & 0x1f); if (offset & 0x800) { offset |= 0xfffff000; } - if (opcode2 == 2) // FSW - { - printf("fsw %s, %d(%s)\n", rs2, offset, rs1); - } - else if (opcode2 == 3) // FSD - { - printf("fsd %s, %d(%s)\n", rs2, offset, rs1); - } - else - { - NYI_RISCV64("illegal ins within emitDisInsName!"); - } + + char width = "bhwd"[opcode2]; + printf("fs%c %s, ", width, rs2); + emitDispImmediate(offset, false, rs1Num); + printf("(%s)\n", rs1); return; } case MajorOpcode::LoadFp: { unsigned int opcode2 = (code >> 12) & 0x7; - const char* rs1 = RegNames[(code >> 15) & 0x1f]; - const char* rd = RegNames[((code >> 7) & 0x1f) | 0x20]; - int offset = ((code >> 20) & 0xfff); + if ((opcode2 != 2) && (opcode2 != 3)) + return emitDispIllegalInstruction(code); + + unsigned rs1Num = (code >> 15) & 0x1f; + const char* rs1 = RegNames[rs1Num]; + const char* rd = RegNames[((code >> 7) & 0x1f) | 0x20]; + int offset = ((code >> 20) & 0xfff); if (offset & 0x800) { offset |= 0xfffff000; } - if (opcode2 == 2) // FLW - { - printf("flw %s, %d(%s)\n", rd, offset, rs1); - } - else if (opcode2 == 3) // FLD - { - printf("fld %s, %d(%s)\n", rd, offset, rs1); - } - else - { - NYI_RISCV64("illegal ins within emitDisInsName!"); - } + + char width = "bhwd"[opcode2]; + printf("fl%c %s, ", width, rd); + emitDispImmediate(offset, false, rs1Num); + printf("(%s)\n", rs1); return; } case MajorOpcode::Amo: diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 5006645c74a0bb..bcc87538f3b18d 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -68,6 +68,7 @@ void emitDispBranchOffset(const instrDesc* id, const insGroup* ig) const; void emitDispBranchLabel(const instrDesc* id) const; bool emitDispBranchInstrType(unsigned opcode2, bool is_zero_reg, bool& print_second_reg) const; void emitDispIllegalInstruction(code_t instructionCode); +void emitDispImmediate(ssize_t imm, bool newLine = true, unsigned regBase = REG_ZERO); emitter::code_t emitInsCode(instruction ins /*, insFormat fmt*/) const; @@ -119,9 +120,6 @@ unsigned emitOutput_BTypeInstr_InvertComparation( unsigned emitOutput_JTypeInstr(BYTE* dst, instruction ins, regNumber rd, unsigned imm21) const; BYTE* emitOutputInstr_OptsReloc(BYTE* dst, const instrDesc* id, instruction* ins); -BYTE* emitOutputInstr_OptsI(BYTE* dst, const instrDesc* id); -BYTE* emitOutputInstr_OptsI8(BYTE* dst, const instrDesc* id, ssize_t immediate, regNumber reg1); -BYTE* emitOutputInstr_OptsI32(BYTE* dst, ssize_t immediate, regNumber reg1); BYTE* emitOutputInstr_OptsRc(BYTE* dst, const instrDesc* id, instruction* ins); BYTE* emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1); BYTE* emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1); diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 7682b98a3a68ab..178d1b0232b20e 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -359,12 +359,13 @@ bool emitter::IsApxNFEncodableInstruction(instruction ins) const // bool emitter::IsApxExtendedEvexInstruction(instruction ins) const { +#ifdef TARGET_AMD64 if (!UsePromotedEVEXEncoding()) { return false; } - if (HasApxNdd(ins) || HasApxNf(ins)) + if (HasApxNdd(ins) || HasApxNf(ins) || (ins == INS_crc32_apx)) { return true; } @@ -375,6 +376,9 @@ bool emitter::IsApxExtendedEvexInstruction(instruction ins) const } return false; +#else // !TARGET_AMD64 + return false; +#endif } //------------------------------------------------------------------------ @@ -1711,6 +1715,14 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const if (HasHighSIMDReg(id) || (id->idOpSize() == EA_64BYTE) || HasMaskReg(id)) { // Requires the EVEX encoding due to used registers + // A special case here is KMOV, the original KMOV introduced in Avx512 can only be encoded in VEX, APX promoted + // them to EVEX, so only return true when APX is available. + if ((ins == INS_kmovb_msk) || (ins == INS_kmovw_msk) || (ins == INS_kmovd_msk) || (ins == INS_kmovq_msk) || + (ins == INS_kmovb_gpr) || (ins == INS_kmovw_gpr) || (ins == INS_kmovd_gpr) || (ins == INS_kmovq_gpr)) + { + // Use EVEX only when needed. + return HasExtendedGPReg(id); + } return true; } @@ -1720,6 +1732,14 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const return true; } + if (HasExtendedGPReg(id)) + { + // TODO-XArch-apx: + // revisit this part: this may have some conflicts with REX2 prefix, we may prefer REX2 if only EGPR is + // involved. + return true; + } + if (id->idIsEvexNfContextSet() && IsBMIInstruction(ins)) { // Only a few BMI instructions shall be promoted to APX-EVEX due to NF feature. @@ -1759,6 +1779,15 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const return id->idHasMem(); } + if ((insTupleTypeInfo(ins) & INS_TT_MEM128) != 0) + { + assert((ins == INS_pslld) || (ins == INS_psllq) || (ins == INS_psllw) || (ins == INS_psrad) || + (ins == INS_psraw) || (ins == INS_psrld) || (ins == INS_psrlq) || (ins == INS_psrlw)); + + // Memory operand with immediate can only be encoded using EVEX + return id->idHasMemAndCns(); + } + return false; } @@ -1773,6 +1802,7 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const // bool emitter::TakesRex2Prefix(const instrDesc* id) const { +#ifdef TARGET_AMD64 // Return true iff the instruction supports REX2 encoding, and it requires to access EGPRs. // TODO-xarch-apx: @@ -1803,6 +1833,9 @@ bool emitter::TakesRex2Prefix(const instrDesc* id) const #endif // DEBUG return false; +#else // !TARGET_AMD64 + return false; +#endif } //------------------------------------------------------------------------ @@ -1816,9 +1849,7 @@ bool emitter::TakesRex2Prefix(const instrDesc* id) const // bool emitter::TakesApxExtendedEvexPrefix(const instrDesc* id) const { - // TODO-XArch-APX: - // Isolating legacy-promoted-EVEX case out from VEX/EVEX-promoted-EVEX, - // as the latter ones are relatively simple, providing EGPRs functionality, +#ifdef TARGET_AMD64 instruction ins = id->idIns(); if (!IsApxExtendedEvexInstruction(ins)) { @@ -1846,6 +1877,11 @@ bool emitter::TakesApxExtendedEvexPrefix(const instrDesc* id) const return true; } + if (ins == INS_crc32_apx) + { + return true; + } + #if defined(DEBUG) if (emitComp->DoJitStressPromotedEvexEncoding()) { @@ -1858,6 +1894,9 @@ bool emitter::TakesApxExtendedEvexPrefix(const instrDesc* id) const } return false; +#else // !TARGET_AMD64 + return false; +#endif } // Intel AVX-512 encoding is defined in "Intel 64 and ia-32 architectures software developer's manual volume 2", Section @@ -2229,11 +2268,7 @@ bool emitter::TakesRexWPrefix(const instrDesc* id) const switch (ins) { case INS_cvtss2si: - case INS_cvttss2si32: - case INS_cvttss2si64: case INS_cvtsd2si: - case INS_cvttsd2si32: - case INS_cvttsd2si64: case INS_movd: case INS_movnti: case INS_andn: @@ -2246,11 +2281,9 @@ bool emitter::TakesRexWPrefix(const instrDesc* id) const case INS_pdep: case INS_pext: case INS_rorx: -#if defined(TARGET_AMD64) case INS_sarx: case INS_shlx: case INS_shrx: -#endif // TARGET_AMD64 case INS_vcvtsd2usi: case INS_vcvtss2usi: { @@ -2387,7 +2420,12 @@ bool emitter::HasMaskReg(const instrDesc* id) const } #if defined(DEBUG) - assert(!isMaskReg(id->idReg2())); + // After APX, KMOV instructions can be encoded in EVEX. + if (isMaskReg(id->idReg2())) + { + assert(IsKInstruction(id->idIns())); + return UsePromotedEVEXEncoding(); + } if (!id->idIsSmallDsc()) { @@ -2733,7 +2771,7 @@ emitter::code_t emitter::AddRexPrefix(instruction ins, code_t code) emitter::code_t emitter::AddEvexVPrimePrefix(code_t code) { #if defined(TARGET_AMD64) - assert(UseEvexEncoding() && hasEvexPrefix(code)); + assert((UseEvexEncoding() || UsePromotedEVEXEncoding()) && hasEvexPrefix(code)); return emitter::code_t(code & 0xFFFFFFF7FFFFFFFFULL); #else unreached(); @@ -2753,7 +2791,7 @@ emitter::code_t emitter::AddEvexVPrimePrefix(code_t code) emitter::code_t emitter::AddEvexRPrimePrefix(code_t code) { #if defined(TARGET_AMD64) - assert(UseEvexEncoding() && hasEvexPrefix(code)); + assert((UseEvexEncoding() || UsePromotedEVEXEncoding()) && hasEvexPrefix(code)); return emitter::code_t(code & 0xFFEFFFFFFFFFFFFFULL); #else unreached(); @@ -2822,13 +2860,38 @@ emitter::code_t emitter::emitExtractEvexPrefix(instruction ins, code_t& code) co { case 0x66: { - // None of the existing BMI instructions should be EVEX encoded. - // After APX, BMI instructions can be EVEX encoded with NF feature. + // After APX, BMI instructions can be encoded in EVEX. if (IsBMIInstruction(ins)) { - // if BMI instructions reaches this part, then it should be APX-EVEX. - // although the opcode of all the BMI instructions are defined with 0x66, - // but it should not, skip this check. + switch (ins) + { + case INS_rorx: + case INS_pdep: + case INS_mulx: + case INS_shrx: + { + evexPrefix |= (0x03 << 8); + break; + } + + case INS_pext: + case INS_sarx: + { + evexPrefix |= (0x02 << 8); + break; + } + + case INS_shlx: + { + evexPrefix |= (0x01 << 8); + break; + } + + default: + { + break; + } + } break; } assert(!IsBMIInstruction(ins)); @@ -3012,32 +3075,25 @@ emitter::code_t emitter::emitExtractVexPrefix(instruction ins, code_t& code) con case INS_rorx: case INS_pdep: case INS_mulx: -// TODO: Unblock when enabled for x86 -#ifdef TARGET_AMD64 case INS_shrx: -#endif { vexPrefix |= 0x03; break; } case INS_pext: -// TODO: Unblock when enabled for x86 -#ifdef TARGET_AMD64 case INS_sarx: -#endif { vexPrefix |= 0x02; break; } -// TODO: Unblock when enabled for x86 -#ifdef TARGET_AMD64 + case INS_shlx: { vexPrefix |= 0x01; break; } -#endif + default: { vexPrefix |= 0x00; @@ -3755,11 +3811,9 @@ bool emitter::emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id) case INS_pextrw: case INS_pextrw_sse41: case INS_rorx: -#ifdef TARGET_AMD64 case INS_shlx: case INS_sarx: case INS_shrx: -#endif case INS_vcvtsd2usi: case INS_vcvtss2usi: case INS_vcvttsd2usi32: @@ -4008,10 +4062,8 @@ unsigned emitter::emitGetVexPrefixSize(instrDesc* id) const switch (ins) { case INS_crc32: -#if defined(TARGET_AMD64) case INS_sarx: case INS_shrx: -#endif // TARGET_AMD64 { // When the prefix is 0x0F38 or 0x0F3A, we must use the 3-byte encoding // These are special cases where the pp-bit is 0xF2 or 0xF3 and not 0x66 @@ -4231,8 +4283,19 @@ inline unsigned emitter::insEncodeReg012(const instrDesc* id, regNumber reg, emi if (IsExtendedGPReg(reg)) { // Seperate the encoding for REX2.B3/B4, REX2.B3 will be handled in `AddRexBPrefix`. - assert(TakesRex2Prefix(id)); - *code |= 0x001000000000ULL; // REX2.B4 + assert(TakesRex2Prefix(id) || TakesApxExtendedEvexPrefix(id) || TakesEvexPrefix(id)); + if (hasRex2Prefix(*code)) + { + *code |= 0x001000000000ULL; // REX2.B4 + } + else if (hasEvexPrefix(*code)) + { + *code |= 0x8000000000000ULL; // EVEX.B4 + } + else + { + // There are cases when this method is called before prefix is attached. + } } } else if ((EA_SIZE(size) == EA_1BYTE) && (reg > REG_RBX) && (code != nullptr)) @@ -4280,8 +4343,19 @@ inline unsigned emitter::insEncodeReg345(const instrDesc* id, regNumber reg, emi if (IsExtendedGPReg(reg)) { // Seperate the encoding for REX2.R3/R4, REX2.R3 will be handled in `AddRexRPrefix`. - assert(TakesRex2Prefix(id)); - *code |= 0x004000000000ULL; // REX2.R4 + assert(TakesRex2Prefix(id) || TakesApxExtendedEvexPrefix(id) || TakesEvexPrefix(id)); + if (hasRex2Prefix(*code)) + { + *code |= 0x004000000000ULL; // REX2.R4 + } + else if (hasEvexPrefix(*code)) + { + *code = AddEvexRPrimePrefix(*code); // EVEX.R4 + } + else + { + // There are cases when this method is called before prefix is attached. + } } } else if ((EA_SIZE(size) == EA_1BYTE) && (reg > REG_RBX) && (code != nullptr)) @@ -4339,6 +4413,12 @@ inline emitter::code_t emitter::insEncodeReg3456(const instrDesc* id, regNumber // Have to set the EVEX V' bit code = AddEvexVPrimePrefix(code); } + + if (isHighGPReg(reg) && IsBMIInstruction(ins)) + { + // APX: BMI instructions use RVM operand encoding + code = AddEvexVPrimePrefix(code); + } #endif // Shift count = 5-bytes of opcode + 0-2 bits for EVEX @@ -4364,7 +4444,7 @@ inline emitter::code_t emitter::insEncodeReg3456(const instrDesc* id, regNumber // Rather see these paths cleaned up. regBits = HighAwareRegEncoding(reg); - if (false /*reg >= REG_R16 && reg <= REG_R31*/) + if (isHighGPReg(reg)) { // Have to set the EVEX V' bit code = AddEvexVPrimePrefix(code); @@ -4410,8 +4490,21 @@ inline unsigned emitter::insEncodeRegSIB(const instrDesc* id, regNumber reg, cod if (IsExtendedGPReg(reg)) { // Separate the encoding for REX2.X3/X4, REX2.X3 will be handled in `AddRexXPrefix`. - assert(TakesRex2Prefix(id)); - *code |= 0x002000000000ULL; // REX2.X4 + assert(TakesRex2Prefix(id) || TakesApxExtendedEvexPrefix(id) || TakesEvexPrefix(id)); + if (hasRex2Prefix(*code)) + { + *code |= 0x002000000000ULL; // REX2.X4 + } + else if (hasEvexPrefix(*code)) + { + // Note that APX-EVEX use EVEX.X4 as the MSB of the INDEX register to address GPRs, and the original + // EVEX.V4 is used for VSIB addressing. + *code &= 0xFFFFFBFFFFFFFFFFULL; // EVEX.X4 + } + else + { + // There are cases when this method is called before prefix is attached. + } } } unsigned regBits = RegEncoding(reg); @@ -8512,7 +8605,7 @@ void emitter::emitIns_R_R_C_R(instruction ins, } //------------------------------------------------------------------------ -// emitIns_R_R_R_S: emits the code for a instruction that takes a register operand, a variable index + +// emitIns_R_R_S_R: emits the code for a instruction that takes a register operand, a variable index + // offset, another register operand, and that returns a value in register // // Arguments: @@ -12780,6 +12873,19 @@ void emitter::emitDispIns( case IF_RRW_RRD_ARD: case IF_RWR_RWR_ARD: { + if ((ins == INS_bextr) || (ins == INS_bzhi) || (ins == INS_sarx) || (ins == INS_shlx) || (ins == INS_shrx)) + { + // These instructions have their operands swapped to simplify the emitter implementation. + // They will appear here as IF_RWR_RRD_ARD but should actually + // display as if they were IF_RWR_ARD_RRD. + + printf("%s", emitRegName(id->idReg1(), attr)); + printf(", %s", sstr); + emitDispAddrMode(id); + printf(", %s", emitRegName(id->idReg2(), attr)); + break; + } + printf("%s", emitRegName(id->idReg1(), attr)); emitDispEmbMasking(id); printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); @@ -13077,6 +13183,20 @@ void emitter::emitDispIns( case IF_RRW_RRD_SRD: case IF_RWR_RWR_SRD: { + if ((ins == INS_bextr) || (ins == INS_bzhi) || (ins == INS_sarx) || (ins == INS_shlx) || (ins == INS_shrx)) + { + // These instructions have their operands swapped to simplify the emitter implementation. + // They will appear here as IF_RWR_RRD_SRD but should actually + // display as if they were IF_RWR_SRD_RRD. + + printf("%s", emitRegName(id->idReg1(), attr)); + printf(", %s", sstr); + emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), + id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + printf(", %s", emitRegName(id->idReg2(), attr)); + break; + } + printf("%s", emitRegName(id->idReg1(), attr)); emitDispEmbMasking(id); printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); @@ -13303,21 +13423,16 @@ void emitter::emitDispIns( regNumber reg2 = id->idReg2(); regNumber reg3 = id->idReg3(); - if (ins == INS_bextr || ins == INS_bzhi -#ifdef TARGET_AMD64 - || ins == INS_shrx || ins == INS_shlx || ins == INS_sarx -#endif - ) + if ((ins == INS_bextr) || (ins == INS_bzhi) || (ins == INS_sarx) || (ins == INS_shlx) || (ins == INS_shrx)) { - // BMI bextr,bzhi, shrx, shlx and sarx encode the reg2 in VEX.vvvv and reg3 in modRM, - // which is different from most of other instructions - regNumber tmp = reg2; - reg2 = reg3; - reg3 = tmp; + // These instructions have their operands swapped to simplify the emitter implementation. + // They encode reg3 in VEX.vvvv and reg2 in modRM, which is opposite most instructions. + // We swap them back here so they will display in the correct order. + std::swap(reg2, reg3); } emitAttr attr3 = attr; - if (hasTupleTypeInfo(ins) && ((insTupleTypeInfo(ins) & INS_TT_MEM128) != 0)) + if ((insTupleTypeInfo(ins) & INS_TT_MEM128) != 0) { // Shift instructions take xmm for the 3rd operand regardless of instruction size. attr3 = EA_16BYTE; @@ -13660,6 +13775,20 @@ void emitter::emitDispIns( case IF_RRW_RRD_MRD: case IF_RWR_RWR_MRD: { + if ((ins == INS_bextr) || (ins == INS_bzhi) || (ins == INS_sarx) || (ins == INS_shlx) || (ins == INS_shrx)) + { + // These instructions have their operands swapped to simplify the emitter implementation. + // They will appear here as IF_RWR_RRD_MRD but should actually + // display as if they were IF_RWR_MRD_RRD. + + printf("%s", emitRegName(id->idReg1(), attr)); + printf(", %s", sstr); + offs = emitGetInsDsp(id); + emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + printf(", %s", emitRegName(id->idReg2(), attr)); + break; + } + printf("%s", emitRegName(id->idReg1(), attr)); emitDispEmbMasking(id); printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); @@ -14534,6 +14663,12 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) NO_WAY("unexpected size"); break; } +#ifdef TARGET_AMD64 + if (ins == INS_crc32_apx) + { + code |= (insEncodeReg345(id, id->idReg1(), size, &code) << 8); + } +#endif // TARGET_AMD64 } // Output the REX prefix @@ -15356,6 +15491,12 @@ BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) { dst += emitOutputByte(dst, 0x66); } +#ifdef TARGET_AMD64 + else + { + code |= EXTENDED_EVEX_PP_BITS; + } +#endif // TARGET_AMD64 } FALLTHROUGH; @@ -15401,6 +15542,14 @@ BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) NO_WAY("unexpected size"); break; } +#ifdef TARGET_AMD64 + if (ins == INS_crc32_apx) + { + // The promoted CRC32 is in 1-byte opcode, unlike other instructions on this path, the register encoding for + // CRC32 need to be done here. + code |= (insEncodeReg345(id, id->idReg1(), size, &code) << 8); + } +#endif // TARGET_AMD64 } // Output the REX prefix @@ -16513,7 +16662,7 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) else if ((ins == INS_bsf) || (ins == INS_bsr) || (ins == INS_crc32) || (ins == INS_lzcnt) || (ins == INS_popcnt) || (ins == INS_tzcnt) #ifdef TARGET_AMD64 - || (ins == INS_lzcnt_apx) || (ins == INS_tzcnt_apx) || (ins == INS_popcnt_apx) + || (ins == INS_lzcnt_apx) || (ins == INS_tzcnt_apx) || (ins == INS_popcnt_apx) || (ins == INS_crc32_apx) #endif // TARGET_AMD64 ) { @@ -16525,11 +16674,24 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) { code |= 0x0100; } +#ifdef TARGET_AMD64 + if ((ins == INS_crc32_apx) && (size > EA_1BYTE)) + { + code |= 0x01; + } +#endif // TARGET_AMD64 - if (size == EA_2BYTE && !TakesApxExtendedEvexPrefix(id)) + if (size == EA_2BYTE) { - assert(ins == INS_crc32); - dst += emitOutputByte(dst, 0x66); + if (!TakesApxExtendedEvexPrefix(id)) + { + assert(ins == INS_crc32); + dst += emitOutputByte(dst, 0x66); + } + else + { + code |= EXTENDED_EVEX_PP_BITS; + } } else if (size == EA_8BYTE) { @@ -16982,14 +17144,13 @@ BYTE* emitter::emitOutputRI(BYTE* dst, instrDesc* id) code = insCodeACC(ins); assert(code < 0x100); - code |= 0x08; // Set the 'w' bit - unsigned regcode = insEncodeReg012(id, reg, size, &code); - code |= regcode; - // This is INS_mov and will not take VEX prefix assert(!TakesVexPrefix(ins)); code = AddX86PrefixIfNeededAndNotPresent(id, code, size); + code |= 0x08; // Set the 'w' bit + unsigned regcode = insEncodeReg012(id, reg, size, &code); + code |= regcode; if (TakesRexWPrefix(id)) { @@ -20611,22 +20772,31 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins break; case INS_movd: - case INS_movq: // only MOVQ xmm, xmm is different (emitted by Sse2.MoveScalar, should use MOVDQU instead) + case INS_movq: if (memAccessKind == PERFSCORE_MEMORY_NONE) { - // movd r32, xmm or xmm, r32 - result.insThroughput = PERFSCORE_THROUGHPUT_1C; - result.insLatency = PERFSCORE_LATENCY_3C; + if (isFloatReg(id->idReg1()) && isFloatReg(id->idReg2())) + { + // movq xmm, xmm + result.insThroughput = PERFSCORE_THROUGHPUT_3X; + result.insLatency = PERFSCORE_LATENCY_1C; + } + else + { + // movd r32/64, xmm or xmm, r32/64 + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + result.insLatency = PERFSCORE_LATENCY_3C; + } } else if (memAccessKind == PERFSCORE_MEMORY_READ) { - // movd xmm, m32 + // ins xmm, m32/64 result.insThroughput = PERFSCORE_THROUGHPUT_2X; result.insLatency += PERFSCORE_LATENCY_2C; } else { - // movd m32, xmm + // ins m32/64, xmm assert(memAccessKind == PERFSCORE_MEMORY_WRITE); result.insThroughput = PERFSCORE_THROUGHPUT_1C; result.insLatency += PERFSCORE_LATENCY_2C; @@ -21345,6 +21515,7 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins case INS_popcnt_apx: case INS_lzcnt_apx: case INS_tzcnt_apx: + case INS_crc32_apx: #endif // TARGET_AMD64 { result.insThroughput = PERFSCORE_THROUGHPUT_1C; @@ -21753,7 +21924,6 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins break; } -#ifdef TARGET_AMD64 case INS_shlx: case INS_sarx: case INS_shrx: @@ -21762,7 +21932,6 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins result.insThroughput = PERFSCORE_THROUGHPUT_2X; break; } -#endif case INS_vpmovb2m: case INS_vpmovw2m: diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index 93bd131f5a3472..583ff4c8f93bc3 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -297,6 +297,11 @@ bool HasKMaskRegisterDest(instruction ins) const case INS_vgatherqps: case INS_vgatherdpd: case INS_vgatherqpd: + // KMOV can be promoted to EVEX with APX. + case INS_kmovb_msk: + case INS_kmovw_msk: + case INS_kmovd_msk: + case INS_kmovq_msk: { return true; } diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index 5ae6cea056efeb..d04585cef94965 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -15,6 +15,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #pragma hdrstop #endif #include "compiler.h" +#include "minipal/log.h" #if MEASURE_FATAL unsigned fatal_badCode; @@ -318,7 +319,14 @@ int vflogf(FILE* file, const char* fmt, va_list args) // 0-length string means flush if (fmt[0] == '\0') { - fflush(file); + if (file == procstdout()) + { + minipal_log_flush_verbose(); + } + else + { + fflush(file); + } return 0; } @@ -331,8 +339,15 @@ int vflogf(FILE* file, const char* fmt, va_list args) OutputDebugStringA(buffer); } - // We use fputs here so that this executes as fast a possible - fputs(&buffer[0], file); + if (file == procstdout()) + { + minipal_log_write_verbose(buffer); + } + else + { + fputs(&buffer[0], file); + } + return written; } diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index e593b92c6b7da6..f6dda4d6a85764 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -3425,20 +3425,54 @@ void Compiler::fgFindBasicBlocks() unsigned XTnum; - /* Are there any exception handlers? */ - + // Are there any exception handlers? + // if (info.compXcptnsCount > 0) { - noway_assert(!compIsForInlining()); + assert(!compIsForInlining() || opts.compInlineMethodsWithEH); - /* Check and mark all the exception handlers */ + if (compIsForInlining()) + { + // Verify we can expand the EH table as needed to incorporate the callee's EH clauses. + // Failing here should be extremely rare. + // + EHblkDsc* const dsc = fgTryAddEHTableEntries(0, info.compXcptnsCount, /* deferAdding */ true); + if (dsc == nullptr) + { + compInlineResult->NoteFatal(InlineObservation::CALLSITE_EH_TABLE_FULL); + } + } + // Check and mark all the exception handlers + // for (XTnum = 0; XTnum < info.compXcptnsCount; XTnum++) { CORINFO_EH_CLAUSE clause; info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause); noway_assert(clause.HandlerLength != (unsigned)-1); + // If we're inlining, and the inlinee has a catch clause, we are currently + // unable to convey the type of the catch properly, as it is represented + // by a token. So, abandon inlining. + // + // TODO: if inlining methods with catches is rare, consider + // transforming class catches into runtime filters like we do in + // fgCreateFiltersForGenericExceptions + // + if (compIsForInlining()) + { + const bool isFinallyFaultOrFilter = + (clause.Flags & (CORINFO_EH_CLAUSE_FINALLY | CORINFO_EH_CLAUSE_FAULT | CORINFO_EH_CLAUSE_FILTER)) != + 0; + + if (!isFinallyFaultOrFilter) + { + JITDUMP("Inlinee EH clause %u is a catch; we can't inline these (yet)\n", XTnum); + compInlineResult->NoteFatal(InlineObservation::CALLEE_HAS_EH); + return; + } + } + if (clause.TryLength <= 0) { BADCODE("try block length <=0"); @@ -3577,8 +3611,6 @@ void Compiler::fgFindBasicBlocks() lvaInlineeReturnSpillTempFreshlyCreated = true; } } - - return; } /* Mark all blocks within 'try' blocks as such */ @@ -3646,6 +3678,7 @@ void Compiler::fgFindBasicBlocks() BADCODE3("end of hnd block beyond end of method for try", " at offset %04X", tryBegOff); } + HBtab->ebdID = impInlineRoot()->compEHID++; HBtab->ebdTryBegOffset = tryBegOff; HBtab->ebdTryEndOffset = tryEndOff; HBtab->ebdFilterBegOffset = filterBegOff; diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index 6e0b726266bad6..4dc20dcd8d2511 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -690,7 +690,9 @@ PhaseStatus Compiler::fgRemoveEmptyTry() // Handler index of any nested blocks will update when we // remove the EH table entry. Change handler exits to jump to // the continuation. Clear catch type on handler entry. - // Decrement nesting level of enclosed GT_END_LFINs. + // + // GT_END_LFIN no longer need updates here, now their gtVal1 fields refer to EH IDs. + // for (BasicBlock* const block : Blocks(firstHandlerBlock, lastHandlerBlock)) { if (block == firstHandlerBlock) @@ -725,25 +727,6 @@ PhaseStatus Compiler::fgRemoveEmptyTry() } } } - -#if defined(FEATURE_EH_WINDOWS_X86) - if (!UsesFunclets()) - { - // If we're in a non-funclet model, decrement the nesting - // level of any GT_END_LFIN we find in the handler region, - // since we're removing the enclosing handler. - for (Statement* const stmt : block->Statements()) - { - GenTree* expr = stmt->GetRootNode(); - if (expr->gtOper == GT_END_LFIN) - { - const size_t nestLevel = expr->AsVal()->gtVal1; - assert(nestLevel > 0); - expr->AsVal()->gtVal1 = nestLevel - 1; - } - } - } -#endif // FEATURE_EH_WINDOWS_X86 } // (6) Update any impacted ACDs. @@ -2697,8 +2680,8 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, if (bbIsTryBeg(block)) { assert(added); - JITDUMP("==> found try entry for EH#%02u nested in handler at " FMT_BB "\n", block->bbNum, - block->getTryIndex()); + JITDUMP("==> found try entry for EH#%02u nested in handler at " FMT_BB "\n", block->getTryIndex(), + block->bbNum); regionsToProcess.Push(block->getTryIndex()); } } @@ -2778,6 +2761,12 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, assert(insertBeforeIndex == enclosingTryIndex); } + if (insertBeforeIndex != compHndBBtabCount) + { + JITDUMP("Existing EH region(s) EH#%02u...EH#%02u will become EH#%02u...EH#%02u\n", insertBeforeIndex, + compHndBBtabCount - 1, insertBeforeIndex + regionCount, compHndBBtabCount + regionCount - 1); + } + // Once we call fgTryAddEHTableEntries with deferCloning = false, // all the EH indicies at or above insertBeforeIndex will shift, // and the EH table may reallocate. @@ -2870,12 +2859,14 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, compHndBBtab[XTnum] = compHndBBtab[originalXTnum]; EHblkDsc* const ebd = &compHndBBtab[XTnum]; + ebd->ebdID = impInlineRoot()->compEHID++; + // Note the outermost region enclosing indices stay the same, because the original // clause entries got adjusted when we inserted the new clauses. // if (ebd->ebdEnclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX) { - if (XTnum < clonedOutermostRegionIndex) + if (ebd->ebdEnclosingTryIndex < clonedOutermostRegionIndex) { ebd->ebdEnclosingTryIndex += (unsigned short)indexShift; } @@ -2888,7 +2879,7 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, if (ebd->ebdEnclosingHndIndex != EHblkDsc::NO_ENCLOSING_INDEX) { - if (XTnum < clonedOutermostRegionIndex) + if (ebd->ebdEnclosingHndIndex < clonedOutermostRegionIndex) { ebd->ebdEnclosingHndIndex += (unsigned short)indexShift; } @@ -3028,6 +3019,22 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, newBlock->bbRefs++; } } + +#if defined(FEATURE_EH_WINDOWS_X86) + // Update the EH ID for any cloned GT_END_LFIN. + // + for (Statement* const stmt : newBlock->Statements()) + { + GenTree* const rootNode = stmt->GetRootNode(); + if (rootNode->OperIs(GT_END_LFIN)) + { + GenTreeVal* const endNode = rootNode->AsVal(); + EHblkDsc* const oldEbd = ehFindEHblkDscById((unsigned short)endNode->gtVal1); + EHblkDsc* const newEbd = oldEbd + indexShift; + endNode->gtVal1 = newEbd->ebdID; + } + } +#endif } JITDUMP("Done fixing region indices\n"); diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 3d1e34a5aa1a19..e6be97f1d38e74 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -1035,6 +1035,19 @@ void Compiler::fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result, // Don't expect any surprises here. assert(result->IsCandidate()); +#if defined(DEBUG) + // Fail if we're inlining and we've reached the acceptance limit. + // + int limit = JitConfig.JitInlineLimit(); + unsigned current = m_inlineStrategy->GetInlineCount(); + + if ((limit >= 0) && (current >= static_cast(limit))) + { + result->NoteFatal(InlineObservation::CALLSITE_OVER_INLINE_LIMIT); + return; + } +#endif // defined(DEBUG) + if (lvaCount >= MAX_LV_NUM_COUNT_FOR_INLINING) { // For now, attributing this to call site, though it's really @@ -1165,7 +1178,7 @@ void Compiler::fgNoteNonInlineCandidate(Statement* stmt, GenTreeCall* call) return; } - InlineResult inlineResult(this, call, nullptr, "fgNoteNonInlineCandidate", false); + InlineResult inlineResult(this, call, nullptr, "fgNoteNonInlineCandidate", true); InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE; // Try and recover the reason left behind when the jit decided @@ -1568,13 +1581,179 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // bottomBlock->RemoveFlags(BBF_DONT_REMOVE); + // If the inlinee has EH, merge the EH tables, and figure out how much of + // a shift we need to make in the inlinee blocks EH indicies. + // + unsigned const inlineeRegionCount = InlineeCompiler->compHndBBtabCount; + const bool inlineeHasEH = inlineeRegionCount > 0; + unsigned inlineeIndexShift = 0; + + if (inlineeHasEH) + { + // If the call site also has EH, we need to insert the inlinee clauses + // so they are a child of the call site's innermost enclosing region. + // Figure out what this is. + // + bool inTryRegion = false; + unsigned const enclosingRegion = ehGetMostNestedRegionIndex(iciBlock, &inTryRegion); + + // We will insert the inlinee clauses in bulk before this index. + // + unsigned insertBeforeIndex = 0; + + if (enclosingRegion == 0) + { + // The call site is not in an EH region, so we can put the inlinee EH clauses + // at the end of root method's the EH table. + // + // For example, if the root method already has EH#0, and the inlinee has 2 regions + // + // enclosingRegion will be 0 + // inlineeIndexShift will be 1 + // insertBeforeIndex will be 1 + // + // inlinee eh0 -> eh1 + // inlinee eh1 -> eh2 + // + // root eh0 -> eh0 + // + inlineeIndexShift = compHndBBtabCount; + insertBeforeIndex = compHndBBtabCount; + } + else + { + // The call site is in an EH region, so we can put the inlinee EH clauses + // just before the enclosing region + // + // Note enclosingRegion is region index + 1. So EH#0 will be represented by 1 here. + // + // For example, if the enclosing EH regions are try#2 and hnd#3, and the inlinee has 2 eh clauses + // + // enclosingRegion will be 3 (try2 + 1) + // inlineeIndexShift will be 2 + // insertBeforeIndex will be 2 + // + // inlinee eh0 -> eh2 + // inlinee eh1 -> eh3 + // + // root eh0 -> eh0 + // root eh1 -> eh1 + // + // root eh2 -> eh4 + // root eh3 -> eh5 + // + inlineeIndexShift = enclosingRegion - 1; + insertBeforeIndex = enclosingRegion - 1; + } + + JITDUMP( + "Inlinee has EH. In root method, inlinee's %u EH region indices will shift by %u and become EH#%02u ... EH#%02u (%p)\n", + inlineeRegionCount, inlineeIndexShift, insertBeforeIndex, insertBeforeIndex + inlineeRegionCount - 1, + &inlineeIndexShift); + + if (enclosingRegion != 0) + { + JITDUMP("Inlinee is nested within current %s EH#%02u (which will become EH#%02u)\n", + inTryRegion ? "try" : "hnd", enclosingRegion - 1, enclosingRegion - 1 + inlineeRegionCount); + } + else + { + JITDUMP("Inlinee is not nested inside any EH region\n"); + } + + // Grow the EH table. + // + // TODO: verify earlier that this won't fail... + // + EHblkDsc* const outermostEbd = + fgTryAddEHTableEntries(insertBeforeIndex, inlineeRegionCount, /* deferAdding */ false); + assert(outermostEbd != nullptr); + + // fgTryAddEHTableEntries has adjusted the indices of all root method blocks and EH clauses + // to accommodate the new entries. No other changes to those are needed. + // + // We just need to add in and fix up the new entries from the inlinee. + // + // Fetch the new enclosing try/handler table indicies. + // + const unsigned enclosingTryIndex = + iciBlock->hasTryIndex() ? iciBlock->getTryIndex() : EHblkDsc::NO_ENCLOSING_INDEX; + const unsigned enclosingHndIndex = + iciBlock->hasHndIndex() ? iciBlock->getHndIndex() : EHblkDsc::NO_ENCLOSING_INDEX; + + // Copy over the EH table entries from inlinee->root and adjust their enclosing indicies. + // + for (unsigned XTnum = 0; XTnum < inlineeRegionCount; XTnum++) + { + unsigned newXTnum = XTnum + inlineeIndexShift; + compHndBBtab[newXTnum] = InlineeCompiler->compHndBBtab[XTnum]; + EHblkDsc* const ebd = &compHndBBtab[newXTnum]; + + if (ebd->ebdEnclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX) + { + ebd->ebdEnclosingTryIndex += (unsigned short)inlineeIndexShift; + } + else + { + ebd->ebdEnclosingTryIndex = (unsigned short)enclosingTryIndex; + } + + if (ebd->ebdEnclosingHndIndex != EHblkDsc::NO_ENCLOSING_INDEX) + { + ebd->ebdEnclosingHndIndex += (unsigned short)inlineeIndexShift; + } + else + { + ebd->ebdEnclosingHndIndex = (unsigned short)enclosingHndIndex; + } + } + } + + // Fetch the new enclosing try/handler indicies for blocks. + // Note these are represented differently than the EH table indices. + // + const unsigned blockEnclosingTryIndex = iciBlock->hasTryIndex() ? iciBlock->getTryIndex() + 1 : 0; + const unsigned blockEnclosingHndIndex = iciBlock->hasHndIndex() ? iciBlock->getHndIndex() + 1 : 0; + // Set the try and handler index and fix the jump types of inlinee's blocks. // for (BasicBlock* const block : InlineeCompiler->Blocks()) { - noway_assert(!block->hasTryIndex()); - noway_assert(!block->hasHndIndex()); - block->copyEHRegion(iciBlock); + if (block->hasTryIndex()) + { + JITDUMP("Inlinee " FMT_BB " has old try index %u, shift %u, new try index %u\n", block->bbNum, + (unsigned)block->bbTryIndex, inlineeIndexShift, + (unsigned)(block->bbTryIndex + inlineeIndexShift)); + block->bbTryIndex += (unsigned short)inlineeIndexShift; + } + else + { + block->bbTryIndex = (unsigned short)blockEnclosingTryIndex; + } + + if (block->hasHndIndex()) + { + block->bbHndIndex += (unsigned short)inlineeIndexShift; + } + else + { + block->bbHndIndex = (unsigned short)blockEnclosingHndIndex; + } + + // Sanity checks + // + if (iciBlock->hasTryIndex()) + { + assert(block->hasTryIndex()); + assert(block->getTryIndex() <= iciBlock->getTryIndex()); + } + + if (iciBlock->hasHndIndex()) + { + assert(block->hasHndIndex()); + assert(block->getHndIndex() <= iciBlock->getHndIndex()); + } + block->CopyFlags(iciBlock, BBF_BACKWARD_JUMP | BBF_PROF_WEIGHT); // Update block nums appropriately @@ -1763,9 +1942,6 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // If the call site is not in a try and the callee has a throw, // we may introduce inconsistency. // - // Technically we should check if the callee has a throw not in a try, but since - // we can't inline methods with EH yet we don't see those. - // if (InlineeCompiler->fgThrowCount > 0) { JITDUMP("INLINER: may-throw inlinee\n"); diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index ca8b79bcbf9ae9..35ed6ab2a6b0f0 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -2519,17 +2519,13 @@ void Compiler::fgRemoveConditionalJump(BasicBlock* block) // bool Compiler::fgOptimizeBranch(BasicBlock* bJump) { - if (opts.MinOpts()) - { - return false; - } + assert(opts.OptimizationEnabled()); if (!bJump->KindIs(BBJ_ALWAYS)) { return false; } - // We might be able to compact blocks that always jump to the next block. if (bJump->JumpsToNext()) { return false; @@ -2540,7 +2536,7 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) return false; } - BasicBlock* bDest = bJump->GetTarget(); + BasicBlock* const bDest = bJump->GetTarget(); if (!bDest->KindIs(BBJ_COND)) { @@ -2559,17 +2555,13 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) return false; } - // do not jump into another try region - BasicBlock* bDestNormalTarget = bDest->GetFalseTarget(); - if (bDestNormalTarget->hasTryIndex() && !BasicBlock::sameTryRegion(bJump, bDestNormalTarget)) - { - return false; - } + // We should have already compacted 'bDest' into 'bJump', if it is possible. + assert(!fgCanCompactBlock(bJump)); - // This function is only called by fgReorderBlocks, which we do not run in the backend. - // If we wanted to run block reordering in the backend, we would need to be able to - // calculate cost information for LIR on a per-node basis in order for this function - // to work. + BasicBlock* const trueTarget = bDest->GetTrueTarget(); + BasicBlock* const falseTarget = bDest->GetFalseTarget(); + + // This function is only called in the frontend. assert(!bJump->IsLIR()); assert(!bDest->IsLIR()); @@ -2593,10 +2585,10 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) bool haveProfileWeights = false; weight_t weightJump = bJump->bbWeight; weight_t weightDest = bDest->bbWeight; - weight_t weightNext = bJump->Next()->bbWeight; + weight_t weightNext = trueTarget->bbWeight; bool rareJump = bJump->isRunRarely(); bool rareDest = bDest->isRunRarely(); - bool rareNext = bJump->Next()->isRunRarely(); + bool rareNext = trueTarget->isRunRarely(); // If we have profile data then we calculate the number of time // the loop will iterate into loopIterations @@ -2607,7 +2599,7 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) // if (bJump->HasAnyFlag(BBF_PROF_WEIGHT | BBF_RUN_RARELY) && bDest->HasAnyFlag(BBF_PROF_WEIGHT | BBF_RUN_RARELY) && - bJump->Next()->HasAnyFlag(BBF_PROF_WEIGHT | BBF_RUN_RARELY)) + trueTarget->HasAnyFlag(BBF_PROF_WEIGHT | BBF_RUN_RARELY)) { haveProfileWeights = true; @@ -2721,7 +2713,7 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) noway_assert(condTree->gtOper == GT_JTRUE); // Set condTree to the operand to the GT_JTRUE. - condTree = condTree->AsOp()->gtOp1; + condTree = condTree->gtGetOp1(); // This condTree has to be a RelOp comparison. if (condTree->OperIsCompare() == false) @@ -2773,12 +2765,11 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) // because the comparison in 'bJump' is flipped. // Similarly, we will derive the true edge's likelihood from 'destFalseEdge'. // - BasicBlock* const bDestFalseTarget = bJump->Next(); - FlowEdge* const falseEdge = fgAddRefPred(bDestFalseTarget, bJump, destTrueEdge); + FlowEdge* const falseEdge = fgAddRefPred(trueTarget, bJump, destTrueEdge); // bJump now jumps to bDest's normal jump target // - fgRedirectTargetEdge(bJump, bDestNormalTarget); + fgRedirectTargetEdge(bJump, falseTarget); bJump->GetTargetEdge()->setLikelihood(destFalseEdge->getLikelihood()); bJump->SetCond(bJump->GetTargetEdge(), falseEdge); @@ -2793,10 +2784,10 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) // Propagate bJump's weight into its new successors // - bDestNormalTarget->setBBProfileWeight(bDestNormalTarget->computeIncomingWeight()); - bDestFalseTarget->setBBProfileWeight(bDestFalseTarget->computeIncomingWeight()); + trueTarget->setBBProfileWeight(trueTarget->computeIncomingWeight()); + falseTarget->setBBProfileWeight(falseTarget->computeIncomingWeight()); - if ((bDestNormalTarget->NumSucc() > 0) || (bDestFalseTarget->NumSucc() > 0)) + if ((trueTarget->NumSucc() > 0) || (falseTarget->NumSucc() > 0)) { JITDUMP("fgOptimizeBranch: New flow out of " FMT_BB " needs to be propagated. Data %s inconsistent.\n", bJump->bbNum, fgPgoConsistent ? "is now" : "was already"); @@ -2821,6 +2812,14 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) } #endif // DEBUG + // Removing flow from 'bJump' into 'bDest' may have made it possible to compact the latter. + BasicBlock* const uniquePred = bDest->GetUniquePred(this); + if ((uniquePred != nullptr) && fgCanCompactBlock(uniquePred)) + { + JITDUMP(FMT_BB " can now be compacted into its remaining predecessor.\n", bDest->bbNum); + fgCompactBlock(uniquePred); + } + return true; } @@ -3244,1163 +3243,6 @@ bool Compiler::fgExpandRarelyRunBlocks() return result; } -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable : 21000) // Suppress PREFast warning about overly large function -#endif - -//----------------------------------------------------------------------------- -// fgReorderBlocks: reorder blocks to favor frequent fall through paths -// and move rare blocks to the end of the method/eh region. -// -// Arguments: -// useProfile - if true, use profile data (if available) to more aggressively -// reorder the blocks. -// -// Returns: -// True if anything got reordered. Reordering blocks may require changing -// IR to reverse branch conditions. -// -// Notes: -// We currently allow profile-driven switch opts even when useProfile is false, -// as they are unlikely to lead to reordering.. -// -bool Compiler::fgReorderBlocks(bool useProfile) -{ - noway_assert(opts.compDbgCode == false); - - // We can't relocate anything if we only have one block - if (fgFirstBB->IsLast()) - { - return false; - } - - bool newRarelyRun = false; - bool movedBlocks = false; - bool optimizedSwitches = false; - bool optimizedBranches = false; - - // First let us expand the set of run rarely blocks - newRarelyRun |= fgExpandRarelyRunBlocks(); - - if (useProfile) - { - // Don't run the new layout until we get to the backend, - // since LSRA can introduce new blocks, and lowering can churn the flowgraph. - // - if (JitConfig.JitDoReversePostOrderLayout()) - { - return (newRarelyRun || movedBlocks || optimizedSwitches); - } - - // We will be reordering blocks, so ensure the false target of a BBJ_COND block is its next block - for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->Next()) - { - if (block->KindIs(BBJ_COND) && !block->NextIs(block->GetFalseTarget())) - { - if (block->CanRemoveJumpToTarget(block->GetTrueTarget(), this)) - { - // Reverse the jump condition - GenTree* test = block->lastNode(); - assert(test->OperIsConditionalJump()); - test->AsOp()->gtOp1 = gtReverseCond(test->AsOp()->gtOp1); - - FlowEdge* const newFalseEdge = block->GetTrueEdge(); - FlowEdge* const newTrueEdge = block->GetFalseEdge(); - block->SetTrueEdge(newTrueEdge); - block->SetFalseEdge(newFalseEdge); - assert(block->CanRemoveJumpToTarget(block->GetFalseTarget(), this)); - } - else - { - BasicBlock* jmpBlk = fgConnectFallThrough(block, block->GetFalseTarget()); - assert(jmpBlk != nullptr); - assert(block->NextIs(jmpBlk)); - - // Skip next block - block = jmpBlk; - } - } - } - } - -#ifdef DEBUG - if (verbose) - { - printf("*************** In fgReorderBlocks()\n"); - - printf("\nInitial BasicBlocks"); - fgDispBasicBlocks(verboseTrees); - printf("\n"); - } -#endif // DEBUG - - BasicBlock* bNext; - BasicBlock* bPrev; - BasicBlock* block; - unsigned XTnum; - EHblkDsc* HBtab; - - // Iterate over every block, remembering our previous block in bPrev - for (bPrev = fgFirstBB, block = bPrev->Next(); block != nullptr; bPrev = block, block = block->Next()) - { - // - // Consider relocating the rarely run blocks such that they are at the end of the method. - // We also consider reversing conditional branches so that they become a not taken forwards branch. - // - - // Don't consider BBJ_CALLFINALLYRET; it should be processed together with BBJ_CALLFINALLY. - if (block->KindIs(BBJ_CALLFINALLYRET)) - { - continue; - } - - // If block is marked with a BBF_KEEP_BBJ_ALWAYS flag then we don't move the block - if (block->HasFlag(BBF_KEEP_BBJ_ALWAYS)) - { - continue; - } - - // Finally and handlers blocks are to be kept contiguous. - // TODO-CQ: Allow reordering within the handler region - if (block->hasHndIndex()) - { - continue; - } - - bool reorderBlock = useProfile; - const bool isRare = block->isRunRarely(); - BasicBlock* bDest = nullptr; - bool forwardBranch = false; - bool backwardBranch = false; - - // Setup bDest - if (bPrev->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET)) - { - bDest = bPrev->GetTarget(); - forwardBranch = fgIsForwardBranch(bPrev, bDest); - backwardBranch = !forwardBranch; - } - else if (bPrev->KindIs(BBJ_COND)) - { - // fgReorderBlocks is called in more than one optimization phase, - // but only does any reordering in optOptimizeLayout. - // At that point, we expect implicit fallthrough to be restored for BBJ_COND blocks. - assert(bPrev->FalseTargetIs(block) || !reorderBlock); - bDest = bPrev->GetTrueTarget(); - forwardBranch = fgIsForwardBranch(bPrev, bDest); - backwardBranch = !forwardBranch; - } - - // We will look for bPrev as a non rarely run block followed by block as a rarely run block - // - if (bPrev->isRunRarely()) - { - reorderBlock = false; - } - - // If the weights of the bPrev, block and bDest were all obtained from a profile run - // then we can use them to decide if it is useful to reverse this conditional branch - - weight_t profHotWeight = -1; - - if (useProfile && bPrev->hasProfileWeight() && block->hasProfileWeight() && - ((bDest == nullptr) || bDest->hasProfileWeight())) - { - // - // All blocks have profile information - // - if (forwardBranch) - { - if (bPrev->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET)) - { - if (bPrev->JumpsToNext()) - { - bDest = nullptr; - goto CHECK_FOR_RARE; - } - // We can pull up the blocks that the unconditional jump branches to - // if the weight of bDest is greater or equal to the weight of block - // also the weight of bDest can't be zero. - // Don't reorder if bPrev's jump destination is the next block. - // - else if ((bDest->bbWeight < block->bbWeight) || (bDest->bbWeight == BB_ZERO_WEIGHT)) - { - reorderBlock = false; - } - else - { - // - // If this remains true then we will try to pull up bDest to succeed bPrev - // - bool moveDestUp = true; - - // - // The edge bPrev -> bDest must have a higher weight - // than every other edge into bDest - // - weight_t const weightToBeat = bPrev->GetTargetEdge()->getLikelyWeight(); - - // Examine all of the other edges into bDest - for (FlowEdge* const edge : bDest->PredEdges()) - { - if (edge->getLikelyWeight() > weightToBeat) - { - moveDestUp = false; - break; - } - } - - // Are we still good to move bDest up to bPrev? - if (moveDestUp) - { - // - // We will consider all blocks that have less weight than profHotWeight to be - // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest - // - profHotWeight = bDest->bbWeight - 1; - } - else - { - if (block->isRunRarely()) - { - // We will move any rarely run blocks blocks - profHotWeight = 0; - } - else - { - // We will move all blocks that have a weight less or equal to our fall through block - profHotWeight = block->bbWeight + 1; - } - // But we won't try to connect with bDest - bDest = nullptr; - } - } - } - else // (bPrev->KindIs(BBJ_COND)) - { - noway_assert(bPrev->KindIs(BBJ_COND)); - // - // We will reverse branch if the true edge's likelihood is more than 51%. - // - // We will set up profHotWeight to be maximum bbWeight that a block - // could have for us not to want to reverse the conditional branch. - // - // We will consider all blocks that have less weight than profHotWeight to be - // uncommonly run blocks compared to the weight of bPrev's true edge. - // - // We will check if bPrev's true edge weight - // is more than twice bPrev's false edge weight. - // - // bPrev --> [BB04, weight 100] - // | \. - // falseEdge ---------------> O \. - // [likelihood=0.33] V \. - // block --> [BB05, weight 33] \. - // \. - // trueEdge ------------------------------> O - // [likelihood=0.67] | - // V - // bDest ---------------> [BB08, weight 67] - // - assert(bPrev->FalseTargetIs(block)); - FlowEdge* trueEdge = bPrev->GetTrueEdge(); - FlowEdge* falseEdge = bPrev->GetFalseEdge(); - noway_assert(trueEdge != nullptr); - noway_assert(falseEdge != nullptr); - - // If we take the true branch more than half the time, we will reverse the branch. - if (trueEdge->getLikelihood() < 0.51) - { - reorderBlock = false; - } - else - { - // set profHotWeight - profHotWeight = falseEdge->getLikelyWeight() - 1; - } - } - } - else // not a forwardBranch - { - if (bPrev->bbFallsThrough()) - { - goto CHECK_FOR_RARE; - } - - // Here we should pull up the highest weight block remaining - // and place it here since bPrev does not fall through. - - weight_t highestWeight = 0; - BasicBlock* candidateBlock = nullptr; - BasicBlock* lastNonFallThroughBlock = bPrev; - BasicBlock* bTmp = bPrev->Next(); - - while (bTmp != nullptr) - { - // Don't try to split a call finally pair - // - if (bTmp->isBBCallFinallyPair()) - { - // Move bTmp forward - bTmp = bTmp->Next(); - } - - // - // Check for loop exit condition - // - if (bTmp == nullptr) - { - break; - } - - // - // if its weight is the highest one we've seen and - // the EH regions allow for us to place bTmp after bPrev - // - if ((bTmp->bbWeight > highestWeight) && fgEhAllowsMoveBlock(bPrev, bTmp)) - { - // When we have a current candidateBlock that is a conditional (or unconditional) jump - // to bTmp (which is a higher weighted block) then it is better to keep our current - // candidateBlock and have it fall into bTmp - // - if ((candidateBlock == nullptr) || !candidateBlock->KindIs(BBJ_COND, BBJ_ALWAYS) || - (candidateBlock->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET) && - (!candidateBlock->TargetIs(bTmp) || candidateBlock->JumpsToNext())) || - (candidateBlock->KindIs(BBJ_COND) && !candidateBlock->TrueTargetIs(bTmp))) - { - // otherwise we have a new candidateBlock - // - highestWeight = bTmp->bbWeight; - candidateBlock = lastNonFallThroughBlock->Next(); - } - } - - const bool bTmpJumpsToNext = bTmp->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET) && bTmp->JumpsToNext(); - if ((!bTmp->bbFallsThrough() && !bTmpJumpsToNext) || (bTmp->bbWeight == BB_ZERO_WEIGHT)) - { - lastNonFallThroughBlock = bTmp; - } - - bTmp = bTmp->Next(); - } - - // If we didn't find a suitable block then skip this - if (highestWeight == 0) - { - reorderBlock = false; - } - else - { - noway_assert(candidateBlock != nullptr); - - // If the candidateBlock is the same a block then skip this - if (candidateBlock == block) - { - reorderBlock = false; - } - else - { - // Set bDest to the block that we want to come after bPrev - bDest = candidateBlock; - - // set profHotWeight - profHotWeight = highestWeight - 1; - } - } - } - } - else // we don't have good profile info (or we are falling through) - { - - CHECK_FOR_RARE:; - - /* We only want to reorder when we have a rarely run */ - /* block right after a normal block, */ - /* (bPrev is known to be a normal block at this point) */ - if (!isRare) - { - if (block->NextIs(bDest) && block->KindIs(BBJ_RETURN) && bPrev->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET)) - { - // This is a common case with expressions like "return Expr1 && Expr2" -- move the return - // to establish fall-through. - } - else - { - reorderBlock = false; - } - } - else - { - /* If the jump target bDest is also a rarely run block then we don't want to do the reversal */ - if (bDest && bDest->isRunRarely()) - { - reorderBlock = false; /* Both block and bDest are rarely run */ - } - else - { - // We will move any rarely run blocks blocks - profHotWeight = 0; - } - } - } - - if (reorderBlock == false) - { - // - // Check for an unconditional branch to a conditional branch - // which also branches back to our next block - // - const bool optimizedBranch = fgOptimizeBranch(bPrev); - if (optimizedBranch) - { - noway_assert(bPrev->KindIs(BBJ_COND)); - optimizedBranches = true; - } - continue; - } - - // Now we need to determine which blocks should be moved - // - // We consider one of two choices: - // - // 1. Moving the fall-through blocks (or rarely run blocks) down to - // later in the method and hopefully connecting the jump dest block - // so that it becomes the fall through block - // - // And when bDest is not NULL, we also consider: - // - // 2. Moving the bDest block (or blocks) up to bPrev - // so that it could be used as a fall through block - // - // We will prefer option #1 if we are able to connect the jump dest - // block as the fall though block otherwise will we try to use option #2 - // - - // - // Consider option #1: relocating blocks starting at 'block' - // to later in flowgraph - // - // We set bStart to the first block that will be relocated - // and bEnd to the last block that will be relocated - - BasicBlock* bStart = block; - BasicBlock* bEnd = bStart; - bNext = bEnd->Next(); - bool connected_bDest = false; - - if ((backwardBranch && !isRare) || block->HasFlag(BBF_DONT_REMOVE)) // Don't choose option #1 when block is the - // start of a try region - { - bStart = nullptr; - bEnd = nullptr; - } - else - { - while (true) - { - // Don't try to split a call finally pair - // - if (bEnd->isBBCallFinallyPair()) - { - // Move bEnd and bNext forward - bEnd = bNext; - bNext = bNext->Next(); - } - - // - // Check for loop exit condition - // - if (bNext == nullptr) - { - break; - } - - // Check if we've reached the funclets region, at the end of the function - if (bEnd->NextIs(fgFirstFuncletBB)) - { - break; - } - - if (bNext == bDest) - { - connected_bDest = true; - break; - } - - // All the blocks must have the same try index - // and must not have the BBF_DONT_REMOVE flag set - - if (!BasicBlock::sameTryRegion(bStart, bNext) || bNext->HasFlag(BBF_DONT_REMOVE)) - { - // exit the loop, bEnd is now set to the - // last block that we want to relocate - break; - } - - // If we are relocating rarely run blocks.. - if (isRare) - { - // ... then all blocks must be rarely run - if (!bNext->isRunRarely()) - { - // exit the loop, bEnd is now set to the - // last block that we want to relocate - break; - } - } - else - { - // If we are moving blocks that are hot then all - // of the blocks moved must be less than profHotWeight */ - if (bNext->bbWeight >= profHotWeight) - { - // exit the loop, bEnd is now set to the - // last block that we would relocate - break; - } - } - - // Move bEnd and bNext forward - bEnd = bNext; - bNext = bNext->Next(); - } - - // Set connected_bDest to true if moving blocks [bStart .. bEnd] - // connects with the jump dest of bPrev (i.e bDest) and - // thus allows bPrev fall through instead of jump. - if (bNext == bDest) - { - connected_bDest = true; - } - } - - // Now consider option #2: Moving the jump dest block (or blocks) - // up to bPrev - // - // The variables bStart2, bEnd2 and bPrev2 are used for option #2 - // - // We will setup bStart2 to the first block that will be relocated - // and bEnd2 to the last block that will be relocated - // and bPrev2 to be the lexical pred of bDest - // - // If after this calculation bStart2 is NULL we cannot use option #2, - // otherwise bStart2, bEnd2 and bPrev2 are all non-NULL and we will use option #2 - - BasicBlock* bStart2 = nullptr; - BasicBlock* bEnd2 = nullptr; - BasicBlock* bPrev2 = nullptr; - - // If option #1 didn't connect bDest and bDest isn't NULL - if ((connected_bDest == false) && (bDest != nullptr) && - // The jump target cannot be moved if it has the BBF_DONT_REMOVE flag set - !bDest->HasFlag(BBF_DONT_REMOVE)) - { - // We will consider option #2: relocating blocks starting at 'bDest' to succeed bPrev - // - // setup bPrev2 to be the lexical pred of bDest - - bPrev2 = block; - while (bPrev2 != nullptr) - { - if (bPrev2->NextIs(bDest)) - { - break; - } - - bPrev2 = bPrev2->Next(); - } - - if ((bPrev2 != nullptr) && fgEhAllowsMoveBlock(bPrev, bDest)) - { - // We have decided that relocating bDest to be after bPrev is best - // Set bStart2 to the first block that will be relocated - // and bEnd2 to the last block that will be relocated - // - // Assigning to bStart2 selects option #2 - // - bStart2 = bDest; - bEnd2 = bStart2; - bNext = bEnd2->Next(); - - while (true) - { - // Don't try to split a call finally pair - // - if (bEnd2->isBBCallFinallyPair()) - { - noway_assert(bNext->KindIs(BBJ_CALLFINALLYRET)); - // Move bEnd2 and bNext forward - bEnd2 = bNext; - bNext = bNext->Next(); - } - - // Check for the Loop exit conditions - - if (bNext == nullptr) - { - break; - } - - if (bEnd2->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET) && bEnd2->JumpsToNext()) - { - // Treat jumps to next block as fall-through - } - else if (bEnd2->bbFallsThrough() == false) - { - break; - } - - // If we are relocating rarely run blocks.. - // All the blocks must have the same try index, - // and must not have the BBF_DONT_REMOVE flag set - - if (!BasicBlock::sameTryRegion(bStart2, bNext) || bNext->HasFlag(BBF_DONT_REMOVE)) - { - // exit the loop, bEnd2 is now set to the - // last block that we want to relocate - break; - } - - if (isRare) - { - /* ... then all blocks must not be rarely run */ - if (bNext->isRunRarely()) - { - // exit the loop, bEnd2 is now set to the - // last block that we want to relocate - break; - } - } - else - { - // If we are relocating hot blocks - // all blocks moved must be greater than profHotWeight - if (bNext->bbWeight <= profHotWeight) - { - // exit the loop, bEnd2 is now set to the - // last block that we want to relocate - break; - } - } - - // Move bEnd2 and bNext forward - bEnd2 = bNext; - bNext = bNext->Next(); - } - } - } - - // If we are using option #1 then ... - if (bStart2 == nullptr) - { - // Don't use option #1 for a backwards branch - if (bStart == nullptr) - { - continue; - } - - // .... Don't move a set of blocks that are already at the end of the main method - if (bEnd == fgLastBBInMainFunction()) - { - continue; - } - } - -#ifdef DEBUG - if (verbose) - { - if (bDest != nullptr) - { - if (bPrev->KindIs(BBJ_COND)) - { - printf("Decided to reverse conditional branch at block " FMT_BB " branch to " FMT_BB " ", - bPrev->bbNum, bDest->bbNum); - } - else if (bPrev->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET)) - { - printf("Decided to straighten unconditional branch at block " FMT_BB " branch to " FMT_BB " ", - bPrev->bbNum, bDest->bbNum); - } - else - { - printf("Decided to place hot code after " FMT_BB ", placed " FMT_BB " after this block ", - bPrev->bbNum, bDest->bbNum); - } - - if (profHotWeight > 0) - { - printf("because of IBC profile data\n"); - } - else - { - if (bPrev->bbFallsThrough()) - { - printf("since it falls into a rarely run block\n"); - } - else - { - printf("since it is succeeded by a rarely run block\n"); - } - } - } - else - { - printf("Decided to relocate block(s) after block " FMT_BB " since they are %s block(s)\n", bPrev->bbNum, - block->isRunRarely() ? "rarely run" : "uncommonly run"); - } - } -#endif // DEBUG - - // We will set insertAfterBlk to the block the precedes our insertion range - // We will set bStartPrev to be the block that precedes the set of blocks that we are moving - BasicBlock* insertAfterBlk; - BasicBlock* bStartPrev; - - if (bStart2 != nullptr) - { - // Option #2: relocating blocks starting at 'bDest' to follow bPrev - - // Update bStart and bEnd so that we can use these two for all later operations - bStart = bStart2; - bEnd = bEnd2; - - // Set bStartPrev to be the block that comes before bStart - bStartPrev = bPrev2; - - // We will move [bStart..bEnd] to immediately after bPrev - insertAfterBlk = bPrev; - } - else - { - // option #1: Moving the fall-through blocks (or rarely run blocks) down to later in the method - - // Set bStartPrev to be the block that come before bStart - bStartPrev = bPrev; - - // We will move [bStart..bEnd] but we will pick the insert location later - insertAfterBlk = nullptr; - } - - // We are going to move [bStart..bEnd] so they can't be NULL - noway_assert(bStart != nullptr); - noway_assert(bEnd != nullptr); - - // bEnd can't be a BBJ_CALLFINALLY unless it is a RETLESS call - noway_assert(!bEnd->KindIs(BBJ_CALLFINALLY) || bEnd->HasFlag(BBF_RETLESS_CALL)); - - // bStartPrev must be set to the block that precedes bStart - noway_assert(bStartPrev->NextIs(bStart)); - - // Since we will be unlinking [bStart..bEnd], - // we need to compute and remember if bStart is in each of - // the try and handler regions - // - bool* fStartIsInTry = nullptr; - bool* fStartIsInHnd = nullptr; - - if (compHndBBtabCount > 0) - { - fStartIsInTry = new (this, CMK_Generic) bool[compHndBBtabCount]; - fStartIsInHnd = new (this, CMK_Generic) bool[compHndBBtabCount]; - - for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) - { - fStartIsInTry[XTnum] = HBtab->InTryRegionBBRange(bStart); - fStartIsInHnd[XTnum] = HBtab->InHndRegionBBRange(bStart); - } - } - - /* Temporarily unlink [bStart..bEnd] from the flow graph */ - const bool bStartPrevJumpsToNext = bStartPrev->KindIs(BBJ_ALWAYS) && bStartPrev->JumpsToNext(); - fgUnlinkRange(bStart, bEnd); - - if (insertAfterBlk == nullptr) - { - // Find new location for the unlinked block(s) - // Set insertAfterBlk to the block which will precede the insertion point - - if (!bStart->hasTryIndex() && isRare) - { - // We'll just insert the blocks at the end of the method. If the method - // has funclets, we will insert at the end of the main method but before - // any of the funclets. Note that we create funclets before we call - // fgReorderBlocks(). - - insertAfterBlk = fgLastBBInMainFunction(); - noway_assert(insertAfterBlk != bPrev); - } - else - { - BasicBlock* startBlk; - BasicBlock* lastBlk; - EHblkDsc* ehDsc = ehInitTryBlockRange(bStart, &startBlk, &lastBlk); - - BasicBlock* endBlk; - - /* Setup startBlk and endBlk as the range to search */ - - if (ehDsc != nullptr) - { - endBlk = lastBlk->Next(); - - /* - Multiple (nested) try regions might start from the same BB. - For example, - - try3 try2 try1 - |--- |--- |--- BB01 - | | | BB02 - | | |--- BB03 - | | BB04 - | |------------ BB05 - | BB06 - |------------------- BB07 - - Now if we want to insert in try2 region, we will start with startBlk=BB01. - The following loop will allow us to start from startBlk==BB04. - */ - while (!BasicBlock::sameTryRegion(startBlk, bStart) && (startBlk != endBlk)) - { - startBlk = startBlk->Next(); - } - - // startBlk cannot equal endBlk as it must come before endBlk - if (startBlk == endBlk) - { - goto CANNOT_MOVE; - } - - // we also can't start searching the try region at bStart - if (startBlk == bStart) - { - // if bEnd is the last block in the method or - // or if bEnd->bbNext is in a different try region - // then we cannot move the blocks - // - if (bEnd->IsLast() || !BasicBlock::sameTryRegion(startBlk, bEnd->Next())) - { - goto CANNOT_MOVE; - } - - startBlk = bEnd->Next(); - - // Check that the new startBlk still comes before endBlk - - // startBlk cannot equal endBlk as it must come before endBlk - if (startBlk == endBlk) - { - goto CANNOT_MOVE; - } - - BasicBlock* tmpBlk = startBlk; - while ((tmpBlk != endBlk) && (tmpBlk != nullptr)) - { - tmpBlk = tmpBlk->Next(); - } - - // when tmpBlk is NULL that means startBlk is after endBlk - // so there is no way to move bStart..bEnd within the try region - if (tmpBlk == nullptr) - { - goto CANNOT_MOVE; - } - } - } - else - { - noway_assert(isRare == false); - - /* We'll search through the entire main method */ - startBlk = fgFirstBB; - endBlk = fgEndBBAfterMainFunction(); - } - - // Calculate nearBlk and jumpBlk and then call fgFindInsertPoint() - // to find our insertion block - // - { - // If the set of blocks that we are moving ends with a BBJ_ALWAYS to - // another [rarely run] block that comes after bPrev (forward branch) - // then we can set up nearBlk to eliminate this jump sometimes - // - BasicBlock* nearBlk = nullptr; - BasicBlock* jumpBlk = nullptr; - - if (bEnd->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLYRET) && !bEnd->JumpsToNext() && - (!isRare || bEnd->GetTarget()->isRunRarely()) && - fgIsForwardBranch(bEnd, bEnd->GetTarget(), bPrev)) - { - // Set nearBlk to be the block in [startBlk..endBlk] - // such that nearBlk->NextIs(bEnd->JumpDest) - // if no such block exists then set nearBlk to NULL - nearBlk = startBlk; - jumpBlk = bEnd; - do - { - // We do not want to set nearBlk to bPrev - // since then we will not move [bStart..bEnd] - // - if (nearBlk != bPrev) - { - // Check if nearBlk satisfies our requirement - if (nearBlk->NextIs(bEnd->GetTarget())) - { - break; - } - } - - // Did we reach the endBlk? - if (nearBlk == endBlk) - { - nearBlk = nullptr; - break; - } - - // advance nearBlk to the next block - nearBlk = nearBlk->Next(); - - } while (nearBlk != nullptr); - } - - // if nearBlk is NULL then we set nearBlk to be the - // first block that we want to insert after. - if (nearBlk == nullptr) - { - if (bDest != nullptr) - { - // we want to insert after bDest - nearBlk = bDest; - } - else - { - // we want to insert after bPrev - nearBlk = bPrev; - } - } - - /* Set insertAfterBlk to the block which we will insert after. */ - - insertAfterBlk = - fgFindInsertPoint(bStart->bbTryIndex, - true, // Insert in the try region. - startBlk, endBlk, nearBlk, jumpBlk, bStart->bbWeight == BB_ZERO_WEIGHT); - } - - /* See if insertAfterBlk is the same as where we started, */ - /* or if we could not find any insertion point */ - - if ((insertAfterBlk == bPrev) || (insertAfterBlk == nullptr)) - { - CANNOT_MOVE:; - /* We couldn't move the blocks, so put everything back */ - /* relink [bStart .. bEnd] into the flow graph */ - - bPrev->SetNext(bStart); - if (!bEnd->IsLast()) - { - bEnd->Next()->SetPrev(bEnd); - } -#ifdef DEBUG - if (verbose) - { - if (bStart != bEnd) - { - printf("Could not relocate blocks (" FMT_BB " .. " FMT_BB ")\n", bStart->bbNum, - bEnd->bbNum); - } - else - { - printf("Could not relocate block " FMT_BB "\n", bStart->bbNum); - } - } -#endif // DEBUG - continue; - } - } - } - - noway_assert(insertAfterBlk != nullptr); - noway_assert(bStartPrev != nullptr); - noway_assert(bStartPrev != insertAfterBlk); - -#ifdef DEBUG - movedBlocks = true; - - if (verbose) - { - const char* msg; - if (bStart2 != nullptr) - { - msg = "hot"; - } - else - { - if (isRare) - { - msg = "rarely run"; - } - else - { - msg = "uncommon"; - } - } - - printf("Relocated %s ", msg); - if (bStart != bEnd) - { - printf("blocks (" FMT_BB " .. " FMT_BB ")", bStart->bbNum, bEnd->bbNum); - } - else - { - printf("block " FMT_BB, bStart->bbNum); - } - - if (bPrev->KindIs(BBJ_COND)) - { - printf(" by reversing conditional jump at " FMT_BB "\n", bPrev->bbNum); - } - else - { - printf("\n", bPrev->bbNum); - } - } -#endif // DEBUG - - if (bPrev->KindIs(BBJ_COND)) - { - /* Reverse the bPrev jump condition */ - Statement* const condTestStmt = bPrev->lastStmt(); - GenTree* const condTest = condTestStmt->GetRootNode(); - - noway_assert(condTest->gtOper == GT_JTRUE); - condTest->AsOp()->gtOp1 = gtReverseCond(condTest->AsOp()->gtOp1); - - FlowEdge* const trueEdge = bPrev->GetTrueEdge(); - FlowEdge* const falseEdge = bPrev->GetFalseEdge(); - bPrev->SetTrueEdge(falseEdge); - bPrev->SetFalseEdge(trueEdge); - - // may need to rethread - // - if (fgNodeThreading == NodeThreading::AllTrees) - { - JITDUMP("Rethreading " FMT_STMT "\n", condTestStmt->GetID()); - gtSetStmtInfo(condTestStmt); - fgSetStmtSeq(condTestStmt); - } - - if (bStart2 != nullptr) - { - noway_assert(insertAfterBlk == bPrev); - noway_assert(insertAfterBlk->NextIs(block)); - } - } - - // If we are moving blocks that are at the end of a try or handler - // we will need to shorten ebdTryLast or ebdHndLast - // - ehUpdateLastBlocks(bEnd, bStartPrev); - - // If we are moving blocks into the end of a try region or handler region - // we will need to extend ebdTryLast or ebdHndLast so the blocks that we - // are moving are part of this try or handler region. - // - for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) - { - // Are we moving blocks to the end of a try region? - if (HBtab->ebdTryLast == insertAfterBlk) - { - if (fStartIsInTry[XTnum]) - { - // bStart..bEnd is in the try, so extend the try region - fgSetTryEnd(HBtab, bEnd); - } - } - - // Are we moving blocks to the end of a handler region? - if (HBtab->ebdHndLast == insertAfterBlk) - { - if (fStartIsInHnd[XTnum]) - { - // bStart..bEnd is in the handler, so extend the handler region - fgSetHndEnd(HBtab, bEnd); - } - } - } - - /* We have decided to insert the block(s) after 'insertAfterBlk' */ - fgMoveBlocksAfter(bStart, bEnd, insertAfterBlk); - - if (bDest) - { - /* We may need to insert an unconditional branch after bPrev to bDest */ - fgConnectFallThrough(bPrev, bDest); - } - else - { - /* If bPrev falls through, we must insert a jump to block */ - fgConnectFallThrough(bPrev, block); - } - - BasicBlock* bSkip = bEnd->Next(); - - /* If bEnd falls through, we must insert a jump to bNext */ - fgConnectFallThrough(bEnd, bNext); - - if (bStart2 == nullptr) - { - /* If insertAfterBlk falls through, we are forced to */ - /* add a jump around the block(s) we just inserted */ - fgConnectFallThrough(insertAfterBlk, bSkip); - } - else - { - /* We may need to insert an unconditional branch after bPrev2 to bStart */ - fgConnectFallThrough(bPrev2, bStart); - } - -#if DEBUG - if (verbose) - { - printf("\nAfter this change in fgReorderBlocks the BB graph is:"); - fgDispBasicBlocks(verboseTrees); - printf("\n"); - } - fgVerifyHandlerTab(); - - // Make sure that the predecessor lists are accurate - if (expensiveDebugCheckLevel >= 2) - { - fgDebugCheckBBlist(); - } -#endif // DEBUG - - // Set our iteration point 'block' to be the new bPrev->bbNext - // It will be used as the next bPrev - block = bPrev->Next(); - - } // end of for loop(bPrev,block) - - const bool changed = movedBlocks || newRarelyRun || optimizedSwitches || optimizedBranches; - - if (changed) - { -#if DEBUG - // Make sure that the predecessor lists are accurate - if (expensiveDebugCheckLevel >= 2) - { - fgDebugCheckBBlist(); - } -#endif // DEBUG - } - - return changed; -} -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - //----------------------------------------------------------------------------- // Compiler::ThreeOptLayout::EdgeCmp: Comparator for the 'cutPoints' priority queue. // If 'left' has a bigger edge weight than 'right', 3-opt will consider it first. diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index c900ae003fe1dc..08ac83188ccf85 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -1463,6 +1463,7 @@ void Compiler::fgAddSyncMethodEnterExit() // Initialize the new entry + newEntry->ebdID = impInlineRoot()->compEHID++; newEntry->ebdHandlerType = EH_HANDLER_FAULT; newEntry->ebdTryBeg = tryBegBB; @@ -1963,13 +1964,12 @@ class MergedReturns // True if any returns were impacted. // // Notes: - // The goal is to set things up favorably for a reasonable layout without - // putting too much burden on fgReorderBlocks; in particular, since that - // method doesn't (currently) shuffle non-profile, non-rare code to create - // fall-through and reduce gotos, this method places each const return - // block immediately after its last predecessor, so that the flow from - // there to it can become fallthrough without requiring any motion to be - // performed by fgReorderBlocks. + // Prematurely optimizing the block layout is unnecessary. + // However, 'ReturnCountHardLimit' is small enough such that + // any throughput savings from skipping this pass are negated + // by the need to emit branches to these blocks in MinOpts. + // If we decide to increase the number of epilogues allowed, + // we should consider removing this pass. // bool PlaceReturns() { @@ -2808,6 +2808,58 @@ bool Compiler::fgSimpleLowerCastOfSmpOp(LIR::Range& range, GenTreeCast* cast) return false; } +//------------------------------------------------------------------------ +// fgSimpleLowerBswap16 : Optimization to remove CAST nodes from operands of small ops that depents on +// lower bits only (currently only BSWAP16). +// Example: +// BSWAP16(CAST(x)) transforms to BSWAP16(x) +// +// Returns: +// True or false, representing changes were made. +// +// Notes: +// This optimization could be done in morph, but it cannot because there are correctness +// problems with NOLs (normalized-on-load locals) and how they are handled in VN. +// Simple put, you cannot remove a CAST from CAST(LCL_VAR{nol}) in HIR. +// +// Because the optimization happens during rationalization, turning into LIR, it is safe to remove the CAST. +// +bool Compiler::fgSimpleLowerBswap16(LIR::Range& range, GenTree* op) +{ + assert(op->OperIs(GT_BSWAP16)); + + if (opts.OptimizationDisabled()) + return false; + + // When openrand is a integral cast + // When both source and target sizes are at least the operation size + bool madeChanges = false; + + if (op->gtGetOp1()->OperIs(GT_CAST)) + { + GenTreeCast* op1 = op->gtGetOp1()->AsCast(); + + if (!op1->gtOverflow() && (genTypeSize(op1->CastToType()) >= 2) && + genActualType(op1->CastFromType()) == TYP_INT) + { + // This cast does not affect the lower 16 bits. It can be removed. + op->AsOp()->gtOp1 = op1->CastOp(); + range.Remove(op1); + madeChanges = true; + } + } + +#ifdef DEBUG + if (madeChanges) + { + JITDUMP("Lower - Downcast of Small Op %s:\n", GenTree::OpName(op->OperGet())); + DISPTREE(op); + } +#endif // DEBUG + + return madeChanges; +} + //------------------------------------------------------------------------------ // fgGetDomSpeculatively: Try determine a more accurate dominator than cached bbIDom // @@ -6140,14 +6192,30 @@ bool FlowGraphNaturalLoop::CanDuplicateWithEH(INDEBUG(const char** reason)) // Check if this is an "outermost" try within the loop. // If so, we have more checking to do later on. // - const bool headerInTry = header->hasTryIndex(); - unsigned blockIndex = block->getTryIndex(); - unsigned outermostBlockIndex = comp->ehTrueEnclosingTryIndex(blockIndex); + bool const headerIsInTry = header->hasTryIndex(); + unsigned const blockTryIndex = block->getTryIndex(); + unsigned const enclosingTryIndex = comp->ehTrueEnclosingTryIndex(blockTryIndex); - if ((headerInTry && (outermostBlockIndex == header->getTryIndex())) || - (!headerInTry && (outermostBlockIndex == EHblkDsc::NO_ENCLOSING_INDEX))) + if ((headerIsInTry && (enclosingTryIndex == header->getTryIndex())) || + (!headerIsInTry && (enclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX))) { - tryRegionsToClone.Push(block); + // When we clone a try we also clone its handler. + // + // This try may be enclosed in a handler whose try begin is in the loop. + // If so we'll clone this try when we clone (the handler of) that try. + // + bool isInHandlerOfInLoopTry = false; + if (block->hasHndIndex()) + { + unsigned const enclosingHndIndex = block->getHndIndex(); + BasicBlock* const associatedTryBeg = comp->ehGetDsc(enclosingHndIndex)->ebdTryBeg; + isInHandlerOfInLoopTry = this->ContainsBlock(associatedTryBeg); + } + + if (!isInHandlerOfInLoopTry) + { + tryRegionsToClone.Push(block); + } } } diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 86357b0536c09b..022c750bdc89ea 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12333,7 +12333,7 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) #if defined(FEATURE_EH_WINDOWS_X86) case GT_END_LFIN: - printf(" endNstLvl=%d", tree->AsVal()->gtVal1); + printf(" ehID=%d", tree->AsVal()->gtVal1); break; #endif // FEATURE_EH_WINDOWS_X86 @@ -18412,9 +18412,14 @@ unsigned GenTreeVecCon::ElementCount(unsigned simdSize, var_types simdBaseType) return simdSize / genTypeSize(simdBaseType); } -bool Compiler::IsValidForShuffle(GenTreeVecCon* vecCon, unsigned simdSize, var_types simdBaseType) const +bool Compiler::IsValidForShuffle( + GenTree* indices, unsigned simdSize, var_types simdBaseType, bool* canBecomeValid, bool isShuffleNative) const { #if defined(TARGET_XARCH) + if (canBecomeValid != nullptr) + { + *canBecomeValid = false; + } size_t elementSize = genTypeSize(simdBaseType); size_t elementCount = simdSize / elementSize; @@ -18426,45 +18431,10 @@ bool Compiler::IsValidForShuffle(GenTreeVecCon* vecCon, unsigned simdSize, var_t // it's likely not worth it overall given that IsHardwareAccelerated reports false return false; } - else if ((varTypeIsByte(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_AVX512VBMI_VL)) || - (varTypeIsShort(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_AVX512BW_VL))) - { - bool crossLane = false; - - for (size_t index = 0; index < elementCount; index++) - { - uint64_t value = vecCon->GetIntegralVectorConstElement(index, simdBaseType); - - if (value >= elementCount) - { - continue; - } - - if (index < (elementCount / 2)) - { - if (value >= (elementCount / 2)) - { - crossLane = true; - break; - } - } - else if (value < (elementCount / 2)) - { - crossLane = true; - break; - } - } - - if (crossLane) - { - // TODO-XARCH-CQ: We should emulate cross-lane shuffling for byte/sbyte and short/ushort - return false; - } - } } else if (simdSize == 64) { - if (varTypeIsByte(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_AVX512VBMI)) + if (varTypeIsByte(simdBaseType) && (!compOpportunisticallyDependsOn(InstructionSet_AVX512VBMI))) { // TYP_BYTE, TYP_UBYTE need AVX512VBMI. return false; @@ -18474,14 +18444,43 @@ bool Compiler::IsValidForShuffle(GenTreeVecCon* vecCon, unsigned simdSize, var_t { assert(simdSize == 16); - if (varTypeIsSmall(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_SSSE3)) + if (varTypeIsSmall(simdBaseType) && (!compOpportunisticallyDependsOn(InstructionSet_SSSE3))) { // TYP_BYTE, TYP_UBYTE, TYP_SHORT, and TYP_USHORT need SSSE3 to be able to shuffle any operation return false; } + + bool isVariableShuffle = !indices->IsCnsVec(); + if ((!isVariableShuffle) && isShuffleNative) + { + // ShuffleNative with constant indices with 1 or more out of range indices is emitted as variable indices. + for (size_t index = 0; index < elementCount; index++) + { + uint64_t value = indices->GetIntegralVectorConstElement(index, simdBaseType); + if (value >= elementCount) + { + isVariableShuffle = true; + break; + } + } + } + if (isVariableShuffle && (!compOpportunisticallyDependsOn(InstructionSet_SSSE3))) + { + // the variable implementation for Vector128 Shuffle always needs SSSE3 + // however, this can become valid later if it becomes constant + if (canBecomeValid != nullptr) + { + *canBecomeValid = true; + } + return false; + } } #endif // TARGET_XARCH + if (canBecomeValid != nullptr) + { + *canBecomeValid = true; + } return true; } @@ -20260,7 +20259,7 @@ var_types GenTreeJitIntrinsic::GetSimdBaseType() const // isCommutativeHWIntrinsic: Checks if the intrinsic is commutative // // Return Value: -// true if the intrisic is commutative +// true if the intrinsic is commutative // bool GenTree::isCommutativeHWIntrinsic() const { @@ -20422,6 +20421,9 @@ bool GenTree::isContainableHWIntrinsic() const return true; } + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: case NI_Vector512_CreateScalarUnsafe: @@ -21568,7 +21570,7 @@ GenTree* Compiler::gtNewSimdCeilNode(var_types type, GenTree* op1, CorInfoType s #if defined(FEATURE_MASKED_HW_INTRINSICS) //------------------------------------------------------------------------ -// gtNewSimdCvtMaskToVectorNode: Convert a HW instrinsic mask node to a vector +// gtNewSimdCvtMaskToVectorNode: Convert a HW intrinsic mask node to a vector // // Arguments: // type -- The type of the node to convert to @@ -21993,7 +21995,7 @@ GenTree* Compiler::gtNewSimdCvtNativeNode(var_types type, #if defined(FEATURE_MASKED_HW_INTRINSICS) //------------------------------------------------------------------------ -// gtNewSimdCvtVectorToMaskNode: Convert a HW instrinsic vector node to a mask +// gtNewSimdCvtVectorToMaskNode: Convert a HW intrinsic vector node to a mask // // Arguments: // type -- The type of the mask to produce. @@ -22747,16 +22749,6 @@ GenTree* Compiler::gtNewSimdCreateBroadcastNode(var_types type, } #if defined(TARGET_XARCH) -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !op1->IsIntegralConst()) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - unreached(); - } -#endif // TARGET_X86 - if (simdSize == 64) { hwIntrinsicID = NI_Vector512_Create; @@ -22860,16 +22852,6 @@ GenTree* Compiler::gtNewSimdCreateScalarNode(var_types type, } #if defined(TARGET_XARCH) -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !op1->IsIntegralConst()) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - unreached(); - } -#endif // TARGET_X86 - if (simdSize == 32) { hwIntrinsicID = NI_Vector256_CreateScalar; @@ -23005,16 +22987,6 @@ GenTree* Compiler::gtNewSimdCreateScalarUnsafeNode(var_types type, } #if defined(TARGET_XARCH) -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !op1->IsIntegralConst()) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - unreached(); - } -#endif // TARGET_X86 - if (simdSize == 32) { hwIntrinsicID = NI_Vector256_CreateScalarUnsafe; @@ -23051,7 +23023,7 @@ GenTree* Compiler::gtNewSimdCreateScalarUnsafeNode(var_types type, GenTree* Compiler::gtNewSimdCreateSequenceNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { - // This effectively doees: (Indices * op2) + Create(op1) + // This effectively does: (Indices * op2) + Create(op1) // // When both op2 and op1 are constant we can fully fold this to a constant. Additionally, // if only op2 is a constant we can simplify the computation by a lot. However, if only op1 @@ -23383,14 +23355,7 @@ GenTree* Compiler::gtNewSimdGetElementNode( assert(varTypeIsArithmetic(simdBaseType)); #if defined(TARGET_XARCH) - bool useToScalar = op2->IsIntegralConst(0); - -#if defined(TARGET_X86) - // We handle decomposition via GetElement for simplicity - useToScalar &= !varTypeIsLong(simdBaseType); -#endif // TARGET_X86 - - if (useToScalar) + if (op2->IsIntegralConst(0)) { return gtNewSimdToScalarNode(type, op1, simdBaseJitType, simdSize); } @@ -25463,8 +25428,24 @@ GenTree* Compiler::gtNewSimdRoundNode(var_types type, GenTree* op1, CorInfoType return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); } -GenTree* Compiler::gtNewSimdShuffleNode( - var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) +//------------------------------------------------------------------------ +// gtNewSimdShuffleVariableNode: Creates a new simd shuffle node (with variable indices, or a case isn't handled in +// gtNewSimdShuffleNode for ShuffleUnsafe with out of bounds indices) - this is a helper function for +// gtNewSimdShuffleNode & should just be invoked by it indirectly, instead of other callers using it +// +// Arguments: +// type -- The type of the node +// op1 -- The values to shuffle +// op2 -- The indices to pick from (variable) +// simdBaseJitType -- The base jit type of the node +// simdSize -- The simd size of the node +// isShuffleNative -- Whether we're making a ShuffleNative node vs a Shuffle one +// +// Return Value: +// The shuffle node +// +GenTree* Compiler::gtNewSimdShuffleVariableNode( + var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize, bool isShuffleNative) { assert(IsBaselineSimdIsaSupportedDebugOnly()); @@ -25474,166 +25455,948 @@ GenTree* Compiler::gtNewSimdShuffleNode( assert(op1 != nullptr); assert(op1->TypeIs(type)); + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); assert(op2 != nullptr); assert(op2->TypeIs(type)); - assert(op2->IsCnsVec()); + assert((!op2->IsCnsVec()) || isShuffleNative); - var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); - assert(varTypeIsArithmetic(simdBaseType)); + GenTree* retNode = nullptr; + GenTree* cnsNode = nullptr; + + size_t elementSize = genTypeSize(simdBaseType); + size_t elementCount = simdSize / elementSize; - if (op2->IsVectorAllBitsSet()) + // duplicate operand 2 for non-ShuffleNative implementation later + // (also, on arm64, byte ShuffleNative is same as Shuffle) + GenTree* op2DupSafe = nullptr; +#if defined(TARGET_XARCH) + if (!isShuffleNative) +#elif defined(TARGET_ARM64) + if ((!isShuffleNative) && (elementSize > 1)) +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 { - // AllBitsSet represents indices that are always "out of range" which means zero should be - // selected for every element. We can special-case this down to just returning a zero node - return gtNewZeroConNode(type); + op2DupSafe = fgMakeMultiUse(&op2); } - if (op2->IsVectorZero()) +#if defined(TARGET_XARCH) + // on xarch, signed comparison is cheaper, so whenever we are able to use it in the + // result & (indices < elementCount) step for Shuffle, we do. Specifically, we are + // able to use it when the top bit causes zeroing (then we can compare indices as + // if they were signed, since negative cases are already handled). + bool canUseSignedComparisonHint = false; + + // TODO-XARCH-CQ: If we have known set/unset bits for the indices, we could further optimise many cases + // below. + + bool isV512Supported = false; + if (simdSize == 64) { - // TODO-XARCH-CQ: Zero represents indices that select the first element of op1 each time. We can simplify - // this down to basically a broadcast equivalent. + if (elementSize == 1) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512VBMI)); + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX512VBMI_PermuteVar64x8, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else if (elementSize == 2) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512BW)); + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX512BW_PermuteVar32x16, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else if (elementSize == 4) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F)); + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX512F_PermuteVar16x32, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else + { + assert(elementSize == 8); + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F)); + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX512F_PermuteVar8x64, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } } + else if ((elementSize == 1) && (simdSize == 16)) + { + assert(compIsaSupportedDebugOnly(InstructionSet_SSSE3)); - GenTree* retNode = nullptr; - GenTreeIntConCommon* cnsNode = nullptr; + retNode = gtNewSimdHWIntrinsicNode(type, op1, op2, NI_SSSE3_Shuffle, simdBaseJitType, simdSize); - size_t elementSize = genTypeSize(simdBaseType); - size_t elementCount = simdSize / elementSize; + // high bit on index gives 0 already + canUseSignedComparisonHint = true; + } + else if ((elementSize == 1) && (simdSize == 32) && + compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512VBMI_VL)) + { + NamedIntrinsic intrinsic = isV512Supported ? NI_AVX512VBMI_VL_PermuteVar32x8 : NI_AVX10v1_PermuteVar32x8; -#if defined(TARGET_XARCH) - uint8_t control = 0; - bool crossLane = false; - bool needsZero = varTypeIsSmall(simdBaseType) && (simdSize <= 16); - uint64_t value = 0; - simd_t vecCns = {}; - simd_t mskCns = {}; + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, intrinsic, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else if ((elementSize == 2) && compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512BW_VL)) + { + assert((simdSize == 16) || (simdSize == 32)); + NamedIntrinsic intrinsic; + if (isV512Supported) + { + intrinsic = (simdSize == 16) ? NI_AVX512BW_VL_PermuteVar8x16 : NI_AVX512BW_VL_PermuteVar16x16; + } + else + { + intrinsic = (simdSize == 16) ? NI_AVX10v1_PermuteVar8x16 : NI_AVX10v1_PermuteVar16x16; + } - for (size_t index = 0; index < elementCount; index++) + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, intrinsic, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else if ((elementSize == 4) && ((simdSize == 32) || compOpportunisticallyDependsOn(InstructionSet_AVX))) { - value = op2->GetIntegralVectorConstElement(index, simdBaseType); + assert((simdSize == 16) || (simdSize == 32)); - if (value < elementCount) + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX2_PermuteVar8x32, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + + retNode = gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX_PermuteVar, CORINFO_TYPE_FLOAT, simdSize); + } + } + else if ((elementSize == 8) && (simdSize == 32) && + compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512F_VL)) + { + NamedIntrinsic intrinsic = isV512Supported ? NI_AVX512F_VL_PermuteVar4x64 : NI_AVX10v1_PermuteVar4x64; + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, intrinsic, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else if ((elementSize == 8) && (simdSize == 16) && + compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512F_VL)) + { + GenTree* op1Copy = fgMakeMultiUse(&op1); // just use op1 again for the other variable + NamedIntrinsic intrinsic = isV512Supported ? NI_AVX512F_VL_PermuteVar2x64x2 : NI_AVX10v1_PermuteVar2x64x2; + retNode = gtNewSimdHWIntrinsicNode(type, op1, op2, op1Copy, intrinsic, simdBaseJitType, simdSize); + } + else + { + assert(((elementSize == 1) && (simdSize == 32)) || (elementSize == 2) || + ((elementSize == 4) && (simdSize == 16)) || (elementSize == 8)); + + if ((elementSize == 8) && ((simdSize == 32) || compOpportunisticallyDependsOn(InstructionSet_AVX))) { + assert((simdSize == 16) || (simdSize == 32)); + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + } + else + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + } + + // the below is implemented for integral types + if (varTypeIsFloating(simdBaseType)) + { + assert(elementSize == 8); + simdBaseJitType = CORINFO_TYPE_LONG; + } + + // shift all indices to the left by 1 (long to int index, first step of converting long->int indices) + cnsNode = gtNewIconNode(1, TYP_INT); if (simdSize == 32) { - // Most of the 256-bit shuffle/permute instructions operate as if - // the inputs were 2x 128-bit values. If the selected indices cross - // the respective 128-bit "lane" we may need to specialize the codegen + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_AVX2_ShiftLeftLogical, simdBaseJitType, simdSize); + } + else + { + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_SSE2_ShiftLeftLogical, simdBaseJitType, simdSize); + } + + // the below are implemented with float/int/uint + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UINT : CORINFO_TYPE_INT; + if (varTypeIsFloating(simdBaseType)) + { + simdBaseJitType = CORINFO_TYPE_FLOAT; + } - if (index < (elementCount / 2)) + // shuffle & manipulate the long indices to int indices (e.g., 3 2 1 0 -> 6 7 4 5 2 3 0 1) + unsigned immediate = 0b10100000; + cnsNode = gtNewIconNode(immediate); + if (simdSize == 32) + { + if (varTypeIsFloating(simdBaseType)) + { + GenTree* op2Dup = fgMakeMultiUse(&op2); + op2 = + gtNewSimdHWIntrinsicNode(type, op2, op2Dup, cnsNode, NI_AVX_Shuffle, simdBaseJitType, simdSize); + } + else + { + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + } + } + else + { + if (varTypeIsFloating(simdBaseType)) { - crossLane |= (value >= (elementCount / 2)); + GenTree* op2Dup = fgMakeMultiUse(&op2); + op2 = + gtNewSimdHWIntrinsicNode(type, op2, op2Dup, cnsNode, NI_SSE_Shuffle, simdBaseJitType, simdSize); } else { - crossLane |= (value < (elementCount / 2)); + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_SSE2_Shuffle, simdBaseJitType, simdSize); } } - // Setting the control for byte/sbyte and short/ushort is unnecessary - // and will actually compute an incorrect control word. But it simplifies - // the overall logic needed here and will remain unused. + simd_t orCns = {}; + for (size_t index = 0; index < simdSize / 4; index++) + { + orCns.u32[index] = index & 1; + } - control |= (value << (index * (elementCount / 2))); + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = orCns; - // When Ssse3 is supported, we may need vecCns to accurately select the relevant - // bytes if some index is outside the valid range. Since x86/x64 is little-endian - // we can simplify this down to a for loop that scales the value and selects count - // sequential bytes. + op2 = gtNewSimdBinOpNode(GT_OR, type, op2, cnsNode, simdBaseJitType, simdSize); - for (uint32_t i = 0; i < elementSize; i++) + // perform the shuffle with our int indices + if (simdSize == 32) { - vecCns.u8[(index * elementSize) + i] = (uint8_t)((value * elementSize) + i); - - // When Ssse3 is not supported, we need to adjust the constant to be AllBitsSet - // so that we can emit a ConditionalSelect(op2, retNode, zeroNode). - - mskCns.u8[(index * elementSize) + i] = 0xFF; + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX2_PermuteVar8x32, simdBaseJitType, simdSize); + retNode->SetReverseOp(); + } + else + { + retNode = gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX_PermuteVar, CORINFO_TYPE_FLOAT, simdSize); } } - else + else if (simdSize == 32) { - needsZero = true; + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + assert(elementSize <= 2); - // When Ssse3 is supported, we may need vecCns to accurately select the relevant - // bytes if some index is outside the valid range. We can do this by just zeroing - // out each byte in the element. This only requires the most significant bit to be - // set, but we use 0xFF instead since that will be the equivalent of AllBitsSet + // the idea is the following (for bytes, short indices are first converted to byte indices): + // 1. we have vector, and we create a vectorSwapped from it (for which the 128-bit lanes are swapped) + // 2. we then shuffle each using Avx2.Shuffle + // 3. we now have vector and vectorSwapped shuffled with Avx2.Shuffle - which only shuffles within the lane + // 4. for Shuffle, invalid indices are explicitly zeroed later, so no need to worry about anything outside + // [0, 31], and for ShuffleNative, we don't guarantee any particular index (or 0 value) is selected. + // 5. since we only care about [0, 31], notably we have that for each element either vector or vectorSwapped + // (not both) will have the value we actually want, since one is effectively index A = i & 0x0F, and + // the other is effectively B = (i & 0x0F) | 0x10. (vector is A for left lane and B for right lane, + // and vectorSwapped is B for left lane and A for right lane) + // 6. we can use a conditional select to get the appropriate value if we know what mask to use. + // 7. we can use the following mask: + // (indices ^ V256.Create(V128.Create((byte)0), V128.Create((byte)0x10))) > V256.Create((byte)0x0F) + // since this detects whether the index value is in the same lane as V256.Indices + // would be (which we know we can always use vector for). this is because it normalises the 0x10 bit + // to mean '0 = in vector, 1 = in vectorSwapped', and then we can use > 0x0F to detect when this is + // the case (we use > on sbyte, since it is the primitive operation on x86/x64 avx2 hardware). + // 8. for Shuffle, we explicitly normalise the out of range indices later, so we are done. - for (uint32_t i = 0; i < elementSize; i++) + // high bit on index gives 0 already + if (elementSize == 1) { - vecCns.u8[(index * elementSize) + i] = 0xFF; - - // When Ssse3 is not supported, we need to adjust the constant to be Zero - // so that we can emit a ConditionalSelect(op2, retNode, zeroNode). - - mskCns.u8[(index * elementSize) + i] = 0x00; + canUseSignedComparisonHint = true; } - } - } - if (simdSize == 32) - { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); - bool isV512Supported = false; - if ((varTypeIsByte(simdBaseType) && - !compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512VBMI_VL)) || - (varTypeIsShort(simdBaseType) && - !compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512BW_VL))) - { - if (crossLane) - { - // TODO-XARCH-CQ: We should emulate cross-lane shuffling for byte/sbyte and short/ushort - unreached(); - } + // declare required clones of op2 + GenTree *op2Dup1, *op2Dup2; - // If we aren't crossing lanes, then we can decompose the byte/sbyte - // and short/ushort operations into 2x 128-bit operations + // if we have elementSize > 1, we need to convert op2 (short indices) to byte indices + if (elementSize > 1) + { + // shift all indices to the left by tzcnt(size) = 1 + cnsNode = gtNewIconNode(1, TYP_INT); + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_AVX2_ShiftLeftLogical, simdBaseJitType, simdSize); - // We want to build what is essentially the following managed code: - // var op1Lower = op1.GetLower(); - // op1Lower = Ssse3.Shuffle(op1Lower, Vector128.Create(...)); - // - // var op1Upper = op1.GetUpper(); - // op1Upper = Ssse3.Shuffle(op1Upper, Vector128.Create(...)); - // - // return Vector256.Create(op1Lower, op1Upper); + // the below are implemented with byte/sbyte + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; - simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + // shuffle with a pattern like 0 0 2 2 4 4 6 6 ... 0 0 2 2 ... (for shorts) + // (note: the 0x10 bit is ignored for Avx2.Shuffle) + simd_t shufCns = {}; + shufCns.u64[0] = 0x0606040402020000; + shufCns.u64[1] = 0x0E0E0C0C0A0A0808; + shufCns.u64[2] = 0x0606040402020000; + shufCns.u64[3] = 0x0E0E0C0C0A0A0808; - GenTree* op1Dup = fgMakeMultiUse(&op1); - GenTree* op1Lower = gtNewSimdGetLowerNode(TYP_SIMD16, op1, simdBaseJitType, simdSize); + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = shufCns; - op2 = gtNewVconNode(TYP_SIMD16); - op2->AsVecCon()->gtSimd16Val = vecCns.v128[0]; + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_AVX2_Shuffle, simdBaseJitType, simdSize); - op1Lower = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1Lower, op2, NI_SSSE3_Shuffle, simdBaseJitType, 16); + // or every second index with 1 (short) + simd_t orCns = {}; + for (size_t index = 0; index < simdSize; index++) + { + orCns.u8[index] = static_cast(index & (elementSize - 1)); + } - GenTree* op1Upper = gtNewSimdGetUpperNode(TYP_SIMD16, op1Dup, simdBaseJitType, simdSize); + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = orCns; - op2 = gtNewVconNode(TYP_SIMD16); - op2->AsVecCon()->gtSimd16Val = vecCns.v128[1]; + op2 = gtNewSimdBinOpNode(GT_OR, type, op2, cnsNode, simdBaseJitType, simdSize); - op1Upper = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1Upper, op2, NI_SSSE3_Shuffle, simdBaseJitType, 16); + // create required clones of op2 + op2Dup1 = fgMakeMultiUse(&op2); + op2Dup2 = gtCloneExpr(op2Dup1); + } - return gtNewSimdWithUpperNode(type, op1Lower, op1Upper, simdBaseJitType, simdSize); - } + else + { + // create required clones of op2 + op2Dup1 = (op2DupSafe != nullptr) ? gtCloneExpr(op2DupSafe) : fgMakeMultiUse(&op2); + op2Dup2 = gtCloneExpr(op2Dup1); + } - if (elementSize == 4) + // swap the low and high 128-bit lanes + // Vector256 swap = Avx2.Permute2x128(vector, vector, 0b00000001); + GenTree* swap; + if (!op1->IsCnsVec()) + { + GenTree* op1Dup1 = fgMakeMultiUse(&op1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); + + uint8_t control = 1; + cnsNode = gtNewIconNode(control, TYP_INT); + swap = gtNewSimdHWIntrinsicNode(type, op1Dup1, op1Dup2, cnsNode, NI_AVX2_Permute2x128, simdBaseJitType, + simdSize); + } + else + { + // if we have a constant, keep it constant + GenTree* op1Dup1 = fgMakeMultiUse(&op1); + swap = op1Dup1; + + simd_t* cnsPtr = &op1Dup1->AsVecCon()->gtSimdVal; + std::swap(cnsPtr->u64[0], cnsPtr->u64[2]); + std::swap(cnsPtr->u64[1], cnsPtr->u64[3]); + } + + // shuffle with both the normal and swapped values + // Vector256 shuf1 = Avx2.Shuffle(vector, indices); + // Vector256 shuf2 = Avx2.Shuffle(swap, indices); + GenTree* shuf1 = gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + GenTree* shuf2 = gtNewSimdHWIntrinsicNode(type, swap, op2Dup1, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + + // get the indices, and xor the cross-lane bit on the high 128-bit lane part of indices. + // V256 indicesXord = indices ^ V256.Create(V128.Create((byte)0), V128.Create((byte)0x10))); + simd_t xorCns = {}; + xorCns.u64[0] = 0; + xorCns.u64[1] = 0; + xorCns.u64[2] = 0x1010101010101010; + xorCns.u64[3] = 0x1010101010101010; + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = xorCns; + + GenTree* indicesXord = gtNewSimdBinOpNode(GT_XOR, type, op2Dup2, cnsNode, simdBaseJitType, simdSize); + + // compare our modified indices to 0x0F (highest value not swapping lane), we get 0xFF when we are swapping + // lane and 0x00 otherwise. we will also get "swapping lane" also when index is more than 32 + // (but no high bit), but this is normalised later for Shuffle, and acceptable for ShuffleNative. + // V256 selection = Avx2.CompareGreaterThan(indicesXord.AsSByte(), V256.Create((sbyte)0x0F)).AsByte(); + simd_t comparandCnd = {}; + comparandCnd.u64[0] = 0x0F0F0F0F0F0F0F0F; + comparandCnd.u64[1] = 0x0F0F0F0F0F0F0F0F; + comparandCnd.u64[2] = 0x0F0F0F0F0F0F0F0F; + comparandCnd.u64[3] = 0x0F0F0F0F0F0F0F0F; + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = comparandCnd; + GenTree* selection = gtNewSimdCmpOpNode(GT_GT, type, indicesXord, cnsNode, CORINFO_TYPE_BYTE, simdSize); + + // blend our two shuffles based on whether each element swaps lanes or not + // return Avx2.BlendVariable(shuf1, shuf2, selection); + retNode = gtNewSimdHWIntrinsicNode(type, shuf1, shuf2, selection, NI_AVX2_BlendVariable, simdBaseJitType, + simdSize); + } + else { - for (uint32_t i = 0; i < elementCount; i++) + assert(compIsaSupportedDebugOnly(InstructionSet_SSSE3)); + assert(simdSize == 16); + assert(elementSize > 1); + + // we want to convert our non-byte indices to byte indices, + // e.g., 3 2 1 0 (int) -> 12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3 (byte) + + // the below is implemented for integral types + if (varTypeIsFloating(simdBaseType)) { - vecCns.u32[i] = (uint8_t)(vecCns.u8[i * elementSize] / elementSize); + if (elementSize == 4) + { + simdBaseJitType = CORINFO_TYPE_UINT; + } + else + { + assert(elementSize == 8); + simdBaseJitType = CORINFO_TYPE_ULONG; + } } - op2 = gtNewVconNode(type); - op2->AsVecCon()->gtSimdVal = vecCns; + // shift all indices to the left by tzcnt(size) + cnsNode = gtNewIconNode(BitOperations::TrailingZeroCount(static_cast(elementSize)), TYP_INT); + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_SSE2_ShiftLeftLogical, simdBaseJitType, simdSize); - // swap the operands to match the encoding requirements - retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX2_PermuteVar8x32, simdBaseJitType, simdSize); + // the below are implemented with byte/sbyte + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + + // we need to convert the indices to byte indices + // shuffle with a pattern like 0 0 2 2 4 4 6 6 ... (for short, and similar for larger) + + simd_t shufCns = {}; + for (size_t index = 0; index < elementCount; index++) + { + for (size_t i = 0; i < elementSize; i++) + { + shufCns.u8[(index * elementSize) + i] = static_cast(index * elementSize); + } + } + + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = shufCns; + + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_SSSE3_Shuffle, simdBaseJitType, simdSize); + + // or the relevant bits + + simd_t orCns = {}; + for (size_t index = 0; index < simdSize; index++) + { + orCns.u8[index] = static_cast(index & (elementSize - 1)); + } + + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = orCns; + + op2 = gtNewSimdBinOpNode(GT_OR, type, op2, cnsNode, simdBaseJitType, simdSize); + + // apply normal byte shuffle now that we've converted it + + retNode = gtNewSimdHWIntrinsicNode(type, op1, op2, NI_SSSE3_Shuffle, simdBaseJitType, simdSize); + } + } +#elif defined(TARGET_ARM64) + NamedIntrinsic lookupIntrinsic = NI_AdvSimd_VectorTableLookup; + + if (simdSize == 16) + { + lookupIntrinsic = NI_AdvSimd_Arm64_VectorTableLookup; + } + + // fix-up indices for non-byte sized element types: + // if we have short / int / long, then we want to VectorTableLookup the least-significant byte to all bytes of that + // index element, and then shift left by the applicable amount, then or on the bits for the elements + // if it's not ShuffleNative, we also need to then fix-up the out-of-range indices (only for non-byte though) + // e.g., 3 2 1 0 (int) -> 12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3 (byte) + if (elementSize > 1) + { + // AdvSimd.ShiftLeftLogical is only valid on integral types, excluding Vector128 + if (varTypeIsFloating(simdBaseType)) + { + if (elementSize == 4) + { + simdBaseJitType = CORINFO_TYPE_INT; + } + else + { + assert(elementSize == 8); + simdBaseJitType = CORINFO_TYPE_LONG; + } + } + if ((simdSize == 16) && (simdBaseJitType == CORINFO_TYPE_INT)) + { + simdBaseJitType = CORINFO_TYPE_UINT; + } + + // shift all indices to the left by tzcnt(size) + cnsNode = gtNewIconNode(BitOperations::TrailingZeroCount(static_cast(elementSize)), TYP_INT); + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, NI_AdvSimd_ShiftLeftLogical, simdBaseJitType, simdSize); + + // VectorTableLookup is only valid on byte/sbyte + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + + simd_t shufCns = {}; + for (size_t index = 0; index < elementCount; index++) + { + for (size_t i = 0; i < elementSize; i++) + { + shufCns.u8[(index * elementSize) + i] = static_cast(index * elementSize); + } + } + + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = shufCns; + + op2 = gtNewSimdHWIntrinsicNode(type, op2, cnsNode, lookupIntrinsic, simdBaseJitType, simdSize); + + // or the relevant bits + simd_t orCns = {}; + for (size_t index = 0; index < simdSize; index++) + { + orCns.u8[index] = static_cast(index & (elementSize - 1)); + } + + cnsNode = gtNewVconNode(type); + cnsNode->AsVecCon()->gtSimdVal = orCns; + + op2 = gtNewSimdBinOpNode(GT_OR, type, op2, cnsNode, simdBaseJitType, simdSize); + } + + retNode = gtNewSimdHWIntrinsicNode(type, op1, op2, lookupIntrinsic, simdBaseJitType, simdSize); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + assert(retNode != nullptr); + +#if defined(TARGET_XARCH) + if (!isShuffleNative) +#elif defined(TARGET_ARM64) + if ((!isShuffleNative) && (elementSize > 1)) +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + { + // we need to ensure indices larger than elementCount become 0 for larger element types + + assert(op2DupSafe != nullptr); + + // get the CorInfoType used for the index comparison + CorInfoType corType = CORINFO_TYPE_UBYTE; + if (elementSize == 2) + { + corType = CORINFO_TYPE_USHORT; + } + else if (elementSize == 4) + { + corType = CORINFO_TYPE_UINT; + } + else if (elementSize == 8) + { + corType = CORINFO_TYPE_ULONG; + } + + // track whether we need to xor the high bit from the comparand + bool subComparandNode = false; + +#if defined(TARGET_XARCH) + // check if we have hardware accelerated unsigned comparison + bool hardwareAcceleratedUnsignedComparison = + (simdSize == 64) || + ((elementSize < 4) && compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512BW_VL)) || + ((elementSize >= 4) && compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512F_VL)); + + // if the hardware doesn't support direct unsigned comparison, we attempt to use signed comparison + if (!hardwareAcceleratedUnsignedComparison) + { + corType = CORINFO_TYPE_BYTE; + if (elementSize == 2) + { + corType = CORINFO_TYPE_SHORT; + } + else if (elementSize == 4) + { + corType = CORINFO_TYPE_INT; + } + else if (elementSize == 8) + { + corType = CORINFO_TYPE_LONG; + } + + // if we can't use signed comparison for free, update the comparand and op2DupSafe appropriately. + // doing this manually allows the comparand to still be a constant. + if (!canUseSignedComparisonHint) + { + subComparandNode = true; + uint64_t subtractionValue = static_cast(1) << (elementSize * 8 - 1); + GenTree* subtraction = + gtNewSimdCreateBroadcastNode(type, gtNewLconNode(subtractionValue), corType, simdSize); + + op2DupSafe = gtNewSimdBinOpNode(GT_SUB, type, op2DupSafe, subtraction, corType, simdSize); + } + } +#endif + + // create the comparand node + uint64_t comparandValue = static_cast(elementCount); + if (subComparandNode) + { + uint64_t subtraction = (uint64_t)1 << (elementSize * 8 - 1); + comparandValue -= subtraction; + } + GenTree* comparand = gtNewSimdCreateBroadcastNode(type, gtNewLconNode(comparandValue), corType, simdSize); + + assert(genTypeSize(JitType2PreciseVarType(corType)) == elementSize); + + // create the mask node (op2 < comparand), and the result node (mask & nativeResult) + GenTree* mask = gtNewSimdCmpOpNode(GT_LT, type, op2DupSafe, comparand, corType, simdSize); + retNode = gtNewSimdBinOpNode(GT_AND, type, retNode, mask, simdBaseJitType, simdSize); + } + else + { + assert(op2DupSafe == nullptr); + } + + return retNode; +} + +//------------------------------------------------------------------------ +// gtNewSimdShuffleNode: Creates a new simd shuffle node +// +// Arguments: +// type -- The type of the node +// op1 -- The values to shuffle +// op2 -- The indices to pick from +// simdBaseJitType -- The base jit type of the node +// simdSize -- The simd size of the node +// isShuffleNative -- Whether we're making a ShuffleNative node vs a Shuffle one +// +// Return Value: +// The shuffle node +// +GenTree* Compiler::gtNewSimdShuffleNode( + var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize, bool isShuffleNative) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + assert(op2 != nullptr); + assert(op2->TypeIs(type)); + + // If op2 is not constant, call into the gtNewSimdShuffleVariableNode routine + if (!op2->IsCnsVec()) + { + return gtNewSimdShuffleVariableNode(type, op1, op2, simdBaseJitType, simdSize, isShuffleNative); + } + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + size_t elementSize = genTypeSize(simdBaseType); + size_t elementCount = simdSize / elementSize; + + // For ShuffleNative, delegate to the variable implementation to get the same behaviour for + // ShuffleNative with constant vs variable indices for free. + // We want ShuffleNative to be at least as good as Shuffle (at least in non out-of-range cases), + // so if we have all values in range, then just treat it like Shuffle. + // We may as well also track whether we have the identity shuffle and all out-of-range here. + bool gotInvalidIndex = false; + bool hasIdentityShuffle = true; + bool allOutOfRange = true; + for (size_t index = 0; index < elementCount; index++) + { + uint64_t value = op2->GetIntegralVectorConstElement(index, simdBaseType); + if (value >= elementCount) + { + gotInvalidIndex = true; + } + else + { + allOutOfRange = false; + } + if (value != static_cast(index)) + { + hasIdentityShuffle = false; + } + } + if (isShuffleNative && gotInvalidIndex) + { + // Call variable implementation. + return gtNewSimdShuffleVariableNode(type, op1, op2, simdBaseJitType, simdSize, isShuffleNative); + } + if (hasIdentityShuffle) + { + // We have 0 1 2 ... for our indices, so just return op1 + return op1; + } + if (allOutOfRange) + { + // allOutOfRange represents indices that are always "out of range" which means zero should be + // selected for every element. We can special-case this down to just returning a zero node + return gtWrapWithSideEffects(gtNewZeroConNode(type), op1, GTF_ALL_EFFECT); + } + + if (op2->IsVectorZero()) + { + // TODO-XARCH-CQ: Zero represents indices that select the first element of op1 each time. We can simplify + // this down to basically a broadcast equivalent. + } + + GenTree* retNode = nullptr; + GenTreeIntConCommon* cnsNode = nullptr; + +#if defined(TARGET_XARCH) + uint8_t control = 0; + bool crossLane = false; + bool needsZero = varTypeIsSmall(simdBaseType) && (simdSize <= 16); + bool differsByLane = false; + uint64_t value = 0; + simd_t vecCns = {}; + simd_t mskCns = {}; + + for (size_t index = 0; index < elementCount; index++) + { + value = op2->GetIntegralVectorConstElement(index, simdBaseType); + + if (value < elementCount) + { + // Most of the 256-bit shuffle/permute instructions operate as if + // the inputs were 2x 128-bit values. If the selected indices cross + // the respective 128-bit "lane" we may need to specialize the codegen. + // Also, for Vector512: If we don't cross 128-bit lanes, then we can emit vpshufb + // instead of vperm* - which has lower latency & allows zeroing in 1 step. + // We also do the same for Vector256. + + crossLane |= ((((uint64_t)index ^ value) * elementSize) & ~(uint64_t)15) != 0; + + // Setting the control for byte/sbyte and short/ushort is unnecessary + // and will actually compute an incorrect control word. But it simplifies + // the overall logic needed here and will remain unused. + + control |= (value << (index * (elementCount / 2))); + + // When Ssse3 is supported, we may need vecCns to accurately select the relevant + // bytes if some index is outside the valid range. Since x86/x64 is little-endian + // we can simplify this down to a for loop that scales the value and selects count + // sequential bytes. + + for (uint32_t i = 0; i < elementSize; i++) + { + vecCns.u8[(index * elementSize) + i] = (uint8_t)((value * elementSize) + i); + + // When Ssse3 is not supported, we need to adjust the constant to be AllBitsSet + // so that we can emit a ConditionalSelect(op2, retNode, zeroNode). + + mskCns.u8[(index * elementSize) + i] = 0xFF; + } + } + else + { + needsZero = true; + + // When Ssse3 is supported, we may need vecCns to accurately select the relevant + // bytes if some index is outside the valid range. We can do this by just zeroing + // out each byte in the element. This only requires the most significant bit to be + // set, but we use 0xFF instead since that will be the equivalent of AllBitsSet + + for (uint32_t i = 0; i < elementSize; i++) + { + vecCns.u8[(index * elementSize) + i] = 0xFF; + + // When Ssse3 is not supported, we need to adjust the constant to be Zero + // so that we can emit a ConditionalSelect(op2, retNode, zeroNode). + + mskCns.u8[(index * elementSize) + i] = 0x00; + } + } + + // Check if the value differs in this lane vs any other lane (note: lane is 128 bits, or 16 bytes) + if (index * elementSize >= 16) + { + // Check if the element, masked to the lane, is the same as the element in the same position of earlier + // lanes. If it differs, differsByLane will be set to true. We just compare to the first lane, as we already + // compared it to any other in between lanes. + differsByLane |= ((vecCns.u8[index * elementSize] ^ vecCns.u8[(index * elementSize) & 15]) & 15) != 0; + } + } + + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + bool isV512Supported = false; + if ((varTypeIsByte(simdBaseType) && + (!compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512VBMI_VL))) || + (varTypeIsShort(simdBaseType) && + (!compIsEvexOpportunisticallySupported(isV512Supported, InstructionSet_AVX512BW_VL))) || + // This condition is the condition for when we'd have to emit something slower than what we can do with + // NI_AVX2_Shuffle directly: + ((!crossLane) && (needsZero || (elementSize < 4) || ((elementSize == 4) && differsByLane)))) + { + // we want to treat our type like byte here + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + + uint8_t leftWants = 0; // result left lane wants which lanes bitfield (1 - left, 2 - right) + uint8_t rightWants = 0; // result right lane wants which lanes bitfield (1 - left, 2 - right) + bool nonDefaultShuffleMask = + false; // tracks whether any element in vecCns is not the default value: 0->15, 0->15 + + simd_t selCns = {}; + for (size_t index = 0; index < simdSize; index++) + { + // get pointer to our leftWants/rightWants + uint8_t* wants = (index < 16) ? (&leftWants) : (&rightWants); + + // update our wants based on which values we use + value = vecCns.u8[index]; + if (value < 16) + { + *wants |= 1; + } + else if (value < 32) + { + *wants |= 2; + } + + // update our conditional select mask for if we need 2 shuffles + value ^= static_cast(index & 0x10); + selCns.u8[index] = ((value < 32) && (value >= 16)) ? 0xFF : 0; + + // normalise our shuffle mask, and check if it's default + if (vecCns.u8[index] < 32) + { + vecCns.u8[index] &= 0x0F; + } + if (vecCns.u8[index] != (index & 0x0F)) + { + nonDefaultShuffleMask = true; + } + } + + // we might be able to get away with only 1 shuffle, this is the case if neither leftWants nor + // rightWants are 3 (indicating only 0/1 side used) + if ((leftWants != 3) && (rightWants != 3)) + { + // set result to its initial value + retNode = op1; + + // get the permutation control + uint8_t control = 0; + if (leftWants == 2) + { + // if left wants right lane, then set that bit + control |= 1; + } + if (rightWants != 1) + { + // if right wants right lane (or neither), then set the bit for right lane + control |= 16; + } + + // create the permutation node + // if we have 16, then we don't need to actually permute, since that's what we start with + if (control != 16) + { + GenTree* retNodeDup = fgMakeMultiUse(&retNode); + + cnsNode = gtNewIconNode(control); + retNode = gtNewSimdHWIntrinsicNode(type, retNode, retNodeDup, cnsNode, NI_AVX2_Permute2x128, + simdBaseJitType, simdSize); + } + + // if we have a non-default shuffle mask, we need to do Avx2.Shuffle + if (nonDefaultShuffleMask) + { + op2 = gtNewVconNode(type); + op2->AsVecCon()->gtSimdVal = vecCns; + + retNode = gtNewSimdHWIntrinsicNode(type, retNode, op2, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + } + } + else + { + GenTree* op1Dup1 = fgMakeMultiUse(&op1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); + + // create the control for swapping + uint8_t control = 1; // 0b00000001 + cnsNode = gtNewIconNode(control); + GenTree* swap = gtNewSimdHWIntrinsicNode(type, op1Dup1, op1Dup2, cnsNode, NI_AVX2_Permute2x128, + simdBaseJitType, simdSize); + + // if we have non-default shuffle mask + if (nonDefaultShuffleMask) + { + // create the shuffle indices node + op2 = gtNewVconNode(type); + op2->AsVecCon()->gtSimdVal = vecCns; + + GenTree* op2Dup = fgMakeMultiUse(&op2); + + // shuffle both op1 and swap(op1) + op1 = gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + swap = gtNewSimdHWIntrinsicNode(type, swap, op2Dup, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + } + + // select the appropriate values + GenTree* selNode = gtNewVconNode(type); + selNode->AsVecCon()->gtSimdVal = selCns; + retNode = gtNewSimdHWIntrinsicNode(type, op1, swap, selNode, NI_AVX2_BlendVariable, simdBaseJitType, + simdSize); + } + + assert(retNode != nullptr); + return retNode; + } + + if (elementSize == 4) + { + // try to use vpshufd/vshufps instead of vpermd/vpermps. + if ((!crossLane) && (!differsByLane)) + { + assert(!needsZero); + unsigned immediate = (unsigned)0; + for (size_t i = 0; i < 4; i++) + { + value = op2->GetIntegralVectorConstElement(i, simdBaseType); + immediate |= static_cast((value & (uint64_t)3) << (i * 2)); + } + if (varTypeIsFloating(simdBaseType)) + { + op2 = gtNewIconNode(immediate); + GenTree* op1Copy = fgMakeMultiUse(&op1); + return gtNewSimdHWIntrinsicNode(type, op1, op1Copy, op2, NI_AVX_Shuffle, simdBaseJitType, simdSize); + } + else + { + op2 = gtNewIconNode(immediate); + return gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX2_Shuffle, simdBaseJitType, simdSize); + } + } + + // otherwise, use vpermd/vpermps. + else + { + for (uint32_t i = 0; i < elementCount; i++) + { + vecCns.u32[i] = (uint8_t)(vecCns.u8[i * elementSize] / elementSize); + } + + op2 = gtNewVconNode(type); + op2->AsVecCon()->gtSimdVal = vecCns; + + // swap the operands to match the encoding requirements + retNode = gtNewSimdHWIntrinsicNode(type, op2, op1, NI_AVX2_PermuteVar8x32, simdBaseJitType, simdSize); + } } else if (elementSize == 2) { + assert(crossLane); assert(canUseEvexEncodingDebugOnly()); for (uint32_t i = 0; i < elementCount; i++) { @@ -25651,6 +26414,7 @@ GenTree* Compiler::gtNewSimdShuffleNode( } else if (elementSize == 1) { + assert(crossLane); assert(IsAvx10OrIsaSupportedDebugOnly(InstructionSet_AVX512VBMI_VL)); op2 = gtNewVconNode(type); op2->AsVecCon()->gtSimdVal = vecCns; @@ -25665,14 +26429,80 @@ GenTree* Compiler::gtNewSimdShuffleNode( { assert(elementSize == 8); - cnsNode = gtNewIconNode(control); - retNode = gtNewSimdHWIntrinsicNode(type, op1, cnsNode, NI_AVX2_Permute4x64, simdBaseJitType, simdSize); + // try to use vshufpd instead of vpermpd. + if (!crossLane) + { + assert(!needsZero); + unsigned immediate = (unsigned)0; + for (size_t i = 0; i < elementCount; i++) + { + value = op2->GetIntegralVectorConstElement(i, simdBaseType); + immediate |= static_cast((value & (uint64_t)1) << i); + } + op2 = gtNewIconNode(immediate); + GenTree* op1Copy = fgMakeMultiUse(&op1); + return gtNewSimdHWIntrinsicNode(type, op1, op1Copy, op2, NI_AVX_Shuffle, CORINFO_TYPE_DOUBLE, simdSize); + } + + // otherwise, use vpermpd. + else + { + cnsNode = gtNewIconNode(control); + retNode = gtNewSimdHWIntrinsicNode(type, op1, cnsNode, NI_AVX2_Permute4x64, simdBaseJitType, simdSize); + } } } else if (simdSize == 64) { assert(IsBaselineVector512IsaSupportedDebugOnly()); - if (elementSize == 4) + if (!crossLane) + { + // if element size is 64-bit, try to use vshufpd instead of vpshufb. + if ((elementSize == 8) && (!needsZero)) + { + unsigned immediate = (unsigned)0; + for (size_t i = 0; i < elementCount; i++) + { + value = op2->GetIntegralVectorConstElement(i, simdBaseType); + immediate |= static_cast((value & (uint64_t)1) << i); + } + op2 = gtNewIconNode(immediate); + GenTree* op1Copy = fgMakeMultiUse(&op1); + return gtNewSimdHWIntrinsicNode(type, op1, op1Copy, op2, NI_AVX512F_Shuffle, CORINFO_TYPE_DOUBLE, + simdSize); + } + + // if the element size is 32-bit, try to use vpshufd/vshufps instead of vpshufb, + // if the indices (when masked to within the lane) are the same for every lane. + if ((elementSize == 4) && (!needsZero) && (!differsByLane)) + { + unsigned immediate = (unsigned)0; + for (size_t i = 0; i < 4; i++) + { + value = op2->GetIntegralVectorConstElement(i, simdBaseType); + immediate |= static_cast((value & (uint64_t)3) << (i * 2)); + } + if (varTypeIsFloating(simdBaseType)) + { + op2 = gtNewIconNode(immediate); + GenTree* op1Copy = fgMakeMultiUse(&op1); + return gtNewSimdHWIntrinsicNode(type, op1, op1Copy, op2, NI_AVX512F_Shuffle, simdBaseJitType, + simdSize); + } + else + { + op2 = gtNewIconNode(immediate); + return gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX512F_Shuffle, simdBaseJitType, simdSize); + } + } + + op2 = gtNewVconNode(type); + op2->AsVecCon()->gtSimdVal = vecCns; + + simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE; + return gtNewSimdHWIntrinsicNode(type, op1, op2, NI_AVX512BW_Shuffle, simdBaseJitType, simdSize); + } + else if (elementSize == 4) { for (uint32_t i = 0; i < elementCount; i++) { @@ -25780,7 +26610,7 @@ GenTree* Compiler::gtNewSimdShuffleNode( if (needsZero) { - assert((simdSize == 32) || !compIsaSupportedDebugOnly(InstructionSet_SSSE3)); + assert((simdSize == 32) || (!compIsaSupportedDebugOnly(InstructionSet_SSSE3))); op2 = gtNewVconNode(type); op2->AsVecCon()->gtSimdVal = mskCns; @@ -25792,18 +26622,6 @@ GenTree* Compiler::gtNewSimdShuffleNode( uint64_t value = 0; simd_t vecCns = {}; - if (simdSize == 16) - { - // Vector128.Shuffle(a, Vector128.Create(2, 3, 0, 1)) -> ExtractVector128(v.AsUInt64(), v.AsUInt64(), 1) - if ((op2->GetIntegralVectorConstElement(0, TYP_ULONG) == 0x300000002) && - (op2->GetIntegralVectorConstElement(1, TYP_ULONG) == 0x100000000)) - { - GenTree* op1Clone = fgMakeMultiUse(&op1); - return gtNewSimdHWIntrinsicNode(type, op1, op1Clone, gtNewIconNode(1), NI_AdvSimd_ExtractVector128, - CORINFO_TYPE_ULONG, simdSize); - } - } - for (size_t index = 0; index < elementCount; index++) { value = op2->GetIntegralVectorConstElement(index, simdBaseType); @@ -25824,6 +26642,17 @@ GenTree* Compiler::gtNewSimdShuffleNode( } } + if (simdSize == 16) + { + // Vector128.Shuffle(a, Vector128.Create(2, 3, 0, 1)) -> ExtractVector128(v.AsUInt64(), v.AsUInt64(), 1) + if ((vecCns.u64[0] == 0x0F0E0D0C0B0A0908) && (vecCns.u64[1] == 0x0706050403020100)) + { + GenTree* op1Clone = fgMakeMultiUse(&op1); + return gtNewSimdHWIntrinsicNode(type, op1, op1Clone, gtNewIconNode(1), NI_AdvSimd_ExtractVector128, + CORINFO_TYPE_ULONG, simdSize); + } + } + NamedIntrinsic lookupIntrinsic = NI_AdvSimd_VectorTableLookup; if (simdSize == 16) @@ -26368,18 +27197,6 @@ GenTree* Compiler::gtNewSimdToScalarNode(var_types type, GenTree* op1, CorInfoTy NamedIntrinsic intrinsic = NI_Illegal; #ifdef TARGET_XARCH -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType)) - { - // We need SSE41 to handle long, use software fallback - assert(compIsaSupportedDebugOnly(InstructionSet_SSE41)); - - // Create a GetElement node which handles decomposition - GenTree* op2 = gtNewIconNode(0); - return gtNewSimdGetElementNode(type, op1, op2, simdBaseJitType, simdSize); - } -#endif // TARGET_X86 - if (simdSize == 64) { assert(IsBaselineVector512IsaSupportedDebugOnly()); @@ -27539,7 +28356,7 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad(GenTree** pAddr) const } //------------------------------------------------------------------------ -// OperIsMemoryLoad: Does this HWI node have memory store semantics? +// OperIsMemoryStore: Does this HWI node have memory store semantics? // // Arguments: // pAddr - optional [out] parameter for the address @@ -27674,7 +28491,7 @@ bool GenTreeHWIntrinsic::OperIsMemoryStoreOrBarrier() const } //------------------------------------------------------------------------ -// OperIsEmbBroadcastCompatible: Checks if the intrinsic is a embedded broadcast compatible inintrsic. +// OperIsEmbBroadcastCompatible: Checks if the intrinsic is a embedded broadcast compatible intrinsic. // // Return Value: // true if the intrinsic node lowering instruction is embedded broadcast compatible. @@ -27740,37 +28557,6 @@ bool GenTreeHWIntrinsic::OperIsBroadcastScalar() const #endif } -//------------------------------------------------------------------------ -// OperIsCreateScalarUnsafe: Is this HWIntrinsic a CreateScalarUnsafe node. -// -// Return Value: -// Whether "this" is a CreateScalarUnsafe node. -// -bool GenTreeHWIntrinsic::OperIsCreateScalarUnsafe() const -{ - NamedIntrinsic intrinsicId = GetHWIntrinsicId(); - - switch (intrinsicId) - { -#if defined(TARGET_ARM64) - case NI_Vector64_CreateScalarUnsafe: -#endif // TARGET_ARM64 - case NI_Vector128_CreateScalarUnsafe: -#if defined(TARGET_XARCH) - case NI_Vector256_CreateScalarUnsafe: - case NI_Vector512_CreateScalarUnsafe: -#endif // TARGET_XARCH - { - return true; - } - - default: - { - return false; - } - } -} - //------------------------------------------------------------------------ // OperIsBitwiseHWIntrinsic: Is the operation a bitwise logic operation. // @@ -30173,15 +30959,24 @@ bool GenTreeHWIntrinsic::ShouldConstantProp(GenTree* operand, GenTreeVecCon* vec #endif // TARGET_XARCH case NI_Vector128_Shuffle: + case NI_Vector128_ShuffleNative: + case NI_Vector128_ShuffleNativeFallback: #if defined(TARGET_XARCH) case NI_Vector256_Shuffle: + case NI_Vector256_ShuffleNative: + case NI_Vector256_ShuffleNativeFallback: case NI_Vector512_Shuffle: + case NI_Vector512_ShuffleNative: + case NI_Vector512_ShuffleNativeFallback: #elif defined(TARGET_ARM64) case NI_Vector64_Shuffle: + case NI_Vector64_ShuffleNative: + case NI_Vector64_ShuffleNativeFallback: #endif { - // The shuffle indices need to be constant so we can preserve - // the node as a hwintrinsic instead of rewriting as a user call. + // The shuffle indices ideally are constant so we can get the best + // codegen possible. There are also some case/s where it would have + // to rewrite as a user call instead depending on available intrinsics. assert(GetOperandCount() == 2); return IsUserCall() && (operand == Op(2)); } diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 6af651b6860882..9f22ca88372380 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -6434,7 +6434,6 @@ struct GenTreeHWIntrinsic : public GenTreeJitIntrinsic bool OperIsMemoryStoreOrBarrier() const; bool OperIsEmbBroadcastCompatible() const; bool OperIsBroadcastScalar() const; - bool OperIsCreateScalarUnsafe() const; bool OperIsBitwiseHWIntrinsic() const; bool OperIsEmbRoundingEnabled() const; @@ -6788,26 +6787,25 @@ struct GenTreeVecCon : public GenTree case TYP_LONG: case TYP_ULONG: { -#if defined(TARGET_64BIT) - if (arg->IsCnsIntOrI()) + if (arg->IsIntegralConst()) { - simdVal.i64[argIdx] = static_cast(arg->AsIntCon()->gtIconVal); + simdVal.i64[argIdx] = arg->AsIntConCommon()->IntegralValue(); return true; } -#else - if (arg->OperIsLong() && arg->AsOp()->gtOp1->IsCnsIntOrI() && arg->AsOp()->gtOp2->IsCnsIntOrI()) +#if !defined(TARGET_64BIT) + else if (arg->OperIsLong() && arg->gtGetOp1()->IsCnsIntOrI() && arg->gtGetOp2()->IsCnsIntOrI()) { - // 32-bit targets will decompose GT_CNS_LNG into two GT_CNS_INT + // 32-bit targets may decompose GT_CNS_LNG into two GT_CNS_INT // We need to reconstruct the 64-bit value in order to handle this - INT64 gtLconVal = arg->AsOp()->gtOp2->AsIntCon()->gtIconVal; + INT64 gtLconVal = arg->gtGetOp2()->AsIntCon()->gtIconVal; gtLconVal <<= 32; - gtLconVal |= arg->AsOp()->gtOp1->AsIntCon()->gtIconVal; + gtLconVal |= static_cast(arg->gtGetOp1()->AsIntCon()->gtIconVal); simdVal.i64[argIdx] = gtLconVal; return true; } -#endif // TARGET_64BIT +#endif // !TARGET_64BIT else { // We expect the constant to have been already zeroed diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index d8bf386eb6009d..d936d579d8e25a 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -923,6 +923,96 @@ struct HWIntrinsicInfo return false; } + static bool IsVectorCreate(NamedIntrinsic id) + { + switch (id) + { +#if defined(TARGET_ARM64) + case NI_Vector64_Create: +#endif // TARGET_ARM64 + case NI_Vector128_Create: +#if defined(TARGET_XARCH) + case NI_Vector256_Create: + case NI_Vector512_Create: +#endif // TARGET_XARCH + return true; + default: + return false; + } + } + + static bool IsVectorCreateScalar(NamedIntrinsic id) + { + switch (id) + { +#if defined(TARGET_ARM64) + case NI_Vector64_CreateScalar: +#endif // TARGET_ARM64 + case NI_Vector128_CreateScalar: +#if defined(TARGET_XARCH) + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: +#endif // TARGET_XARCH + return true; + default: + return false; + } + } + + static bool IsVectorCreateScalarUnsafe(NamedIntrinsic id) + { + switch (id) + { +#if defined(TARGET_ARM64) + case NI_Vector64_CreateScalarUnsafe: +#endif // TARGET_ARM64 + case NI_Vector128_CreateScalarUnsafe: +#if defined(TARGET_XARCH) + case NI_Vector256_CreateScalarUnsafe: + case NI_Vector512_CreateScalarUnsafe: +#endif // TARGET_XARCH + return true; + default: + return false; + } + } + + static bool IsVectorGetElement(NamedIntrinsic id) + { + switch (id) + { +#if defined(TARGET_ARM64) + case NI_Vector64_GetElement: +#endif // TARGET_ARM64 + case NI_Vector128_GetElement: +#if defined(TARGET_XARCH) + case NI_Vector256_GetElement: + case NI_Vector512_GetElement: +#endif // TARGET_XARCH + return true; + default: + return false; + } + } + + static bool IsVectorToScalar(NamedIntrinsic id) + { + switch (id) + { +#if defined(TARGET_ARM64) + case NI_Vector64_ToScalar: +#endif // TARGET_ARM64 + case NI_Vector128_ToScalar: +#if defined(TARGET_XARCH) + case NI_Vector256_ToScalar: + case NI_Vector512_ToScalar: +#endif // TARGET_XARCH + return true; + default: + return false; + } + } + static bool HasImmediateOperand(NamedIntrinsic id) { #if defined(TARGET_ARM64) diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index be1c577d4bdfaa..a9c50c029cc22f 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -2251,38 +2251,56 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector64_Shuffle: case NI_Vector128_Shuffle: + case NI_Vector64_ShuffleNative: + case NI_Vector128_ShuffleNative: + case NI_Vector64_ShuffleNativeFallback: + case NI_Vector128_ShuffleNativeFallback: { assert((sig->numArgs == 2) || (sig->numArgs == 3)); assert((simdSize == 8) || (simdSize == 16)); + // The Native variants are non-deterministic on arm64 (for element size > 1) + bool isShuffleNative = (intrinsic != NI_Vector64_Shuffle) && (intrinsic != NI_Vector128_Shuffle); + if (isShuffleNative && (genTypeSize(simdBaseType) > 1) && BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + GenTree* indices = impStackTop(0).val; - if (!indices->IsCnsVec() || !IsValidForShuffle(indices->AsVecCon(), simdSize, simdBaseType)) + // Check if the required intrinsics to emit are available. + bool canBecomeValidForShuffle = false; + if (!IsValidForShuffle(indices, simdSize, simdBaseType, &canBecomeValidForShuffle, isShuffleNative)) + { + // All cases on arm64 are either valid or invalid, they cannot become valid later + assert(!canBecomeValidForShuffle); + break; + } + + // If the indices might become constant later, then we don't emit for now, delay until later. + if (!indices->IsCnsVec()) { assert(sig->numArgs == 2); - if (!opts.OptimizationEnabled()) + if (opts.OptimizationEnabled()) { // Only enable late stage rewriting if optimizations are enabled // as we won't otherwise encounter a constant at the later point - return nullptr; - } - - op2 = impSIMDPopStack(); - op1 = impSIMDPopStack(); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); - retNode->AsHWIntrinsic()->SetMethodHandle(this, method R2RARG(*entryPoint)); - break; + retNode->AsHWIntrinsic()->SetMethodHandle(this, method R2RARG(*entryPoint)); + break; + } } if (sig->numArgs == 2) { - op2 = impSIMDPopStack(); - op1 = impSIMDPopStack(); - - retNode = gtNewSimdShuffleNode(retType, op1, op2, simdBaseJitType, simdSize); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + retNode = gtNewSimdShuffleNode(retType, op1, op2, simdBaseJitType, simdSize, isShuffleNative); } break; } diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 4a73297d3d1e18..19792a61c4083e 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -168,6 +168,226 @@ static insOpts AddEmbMaskingMode(insOpts instOptions, regNumber maskReg, bool me return static_cast(result); } +//------------------------------------------------------------------------ +// GetImmediateMaxAndMask: Returns the max valid value and a bit mask for +// a full-range immediate of an instruction that has documented +// masking or clamping of the immediate. +// +// Arguments: +// instruction - The instruction to look up +// simdSize - The vector size for the instruction +// maskOut - A pointer to the location to return the mask +// +// Return Value: +// The max useful immediate value +// +static unsigned GetImmediateMaxAndMask(instruction ins, unsigned simdSize, unsigned* maskOut) +{ + assert(maskOut != nullptr); + assert((simdSize >= 16) && (simdSize <= 64)); + + unsigned lanes = simdSize / genTypeSize(TYP_SIMD16); + unsigned mask = 0xFF; + unsigned max = 0; + + switch (ins) + { + // These byte-wise shift instructions are documented to return a zero vector + // for shift amounts 16 or greater. + case INS_pslldq: + case INS_psrldq: + { + max = 16; + break; + } + + // palignr concatenates two 16-byte lanes and shifts the result by imm8 bytes. + // It is documented to return a zero vector for shift amounts 32 or greater. + case INS_palignr: + { + max = 32; + break; + } + + // The following groups of instructions extract/insert a scalar value from/to a + // 128-bit vector and use a documented range of bits for element index. + case INS_pextrq: + case INS_pinsrq: + { + mask = 0b00000001; + max = mask; + break; + } + + case INS_extractps: + case INS_pextrd: + case INS_pinsrd: + { + mask = 0b00000011; + max = mask; + break; + } + + case INS_pextrw: + case INS_pinsrw: + { + mask = 0b00000111; + max = mask; + break; + } + + case INS_pextrb: + case INS_pinsrb: + { + mask = 0b00001111; + max = mask; + break; + } + + // The following instructions concatenate 128- or 256-bit vectors and shift the + // result right by imm8 elements. The number of bits used depends on the + // vector size / element size. + case INS_valignd: + { + mask = (simdSize / genTypeSize(TYP_INT)) - 1; + max = mask; + break; + } + + case INS_valignq: + { + mask = (simdSize / genTypeSize(TYP_LONG)) - 1; + max = mask; + break; + } + + // The following groups of instructions operate in 128-bit lanes but use a + // different range of bits from the immediate for each lane. + case INS_blendpd: + case INS_shufpd: + case INS_vpermilpd: + { + assert(lanes <= 4); + + // two bits per lane + mask = (1 << (lanes * 2)) - 1; + max = mask; + break; + } + + case INS_blendps: + case INS_vpblendd: + { + assert(lanes <= 2); + + // four bits per lane + mask = (1 << (lanes * 4)) - 1; + max = mask; + break; + } + + case INS_mpsadbw: + { + assert(lanes <= 2); + + // three bits per lane + mask = (1 << (lanes * 3)) - 1; + max = mask; + break; + } + + // These instructions extract/insert a 128-bit vector from/to either a 256-bit or + // 512-bit vector. The number of positions is equal to the number of 128-bit lanes. + case INS_vextractf128: + case INS_vextracti128: + case INS_vextractf64x2: + case INS_vextracti64x2: + case INS_vinsertf128: + case INS_vinserti128: + case INS_vinsertf64x2: + case INS_vinserti64x2: + { + assert(lanes >= 2); + + mask = lanes - 1; + max = mask; + break; + } + + // These instructions shuffle 128-bit lanes within a larger vector. + // The number of bits used depends on the number of possible lanes. + case INS_vshuff32x4: + case INS_vshufi32x4: + case INS_vshuff64x2: + case INS_vshufi64x2: + { + assert(lanes >= 2); + + // log2(lanes) bits per lane for src selection + mask = (1 << (lanes * BitOperations::Log2(lanes))) - 1; + max = mask; + break; + } + + // These instructions extract/insert a 256-bit vector from/to a 512-bit vector + // and therefore only have two possible positions. + case INS_vextractf32x8: + case INS_vextracti32x8: + case INS_vextractf64x4: + case INS_vextracti64x4: + case INS_vinsertf32x8: + case INS_vinserti32x8: + case INS_vinsertf64x4: + case INS_vinserti64x4: + { + assert(simdSize == 64); + + mask = 0b00000001; + max = mask; + break; + } + + // The following instructions use documented ranges of bits with gaps in them. + case INS_dppd: + { + // bits [1:0] are the result broadcast mask + // bits [5:4] are the element selection mask + mask = 0b00110011; + max = mask; + break; + } + + case INS_pclmulqdq: + { + // bit 0 selects the src1 qword + // bit 4 selects the src2 qword + mask = 0b00010001; + max = mask; + break; + } + + case INS_vperm2f128: + case INS_vperm2i128: + { + // bits [1:0] select the src index for the low lane result + // bits [5:4] select the src index for the high lane result + // bits 3 and 7, if set, will zero the low or high lane, respectively + mask = 0b10111011; + max = mask; + break; + } + + default: + { + max = 255; + break; + } + } + + *maskOut = mask; + return max; +} + //------------------------------------------------------------------------ // genHWIntrinsic: Generates the code for a given hardware intrinsic node. // @@ -332,8 +552,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) }; regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, - emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, simdSize, lastOp->GetRegNum(), baseReg, + offsReg, emitSwCase); break; } case 2: @@ -344,8 +564,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) }; regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, - emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, simdSize, lastOp->GetRegNum(), baseReg, + offsReg, emitSwCase); break; } @@ -533,7 +753,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // constant value. regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, op2Reg, baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, simdSize, op2Reg, baseReg, offsReg, + emitSwCase); } } else if (node->TypeGet() == TYP_VOID) @@ -583,7 +804,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // can also occur if the consumer calls it directly and just doesn't pass a constant value. regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, op3Reg, baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, simdSize, op3Reg, baseReg, offsReg, + emitSwCase); } } else if (category == HW_Category_MemoryStore) @@ -681,7 +903,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // can also occur if the consumer calls it directly and just doesn't pass a constant value. regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, op4Reg, baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, simdSize, op4Reg, baseReg, offsReg, + emitSwCase); } } else @@ -857,7 +1080,7 @@ void CodeGen::genHWIntrinsic_R_RM( if (((instOptions & INS_OPTS_EVEX_b_MASK) != 0) && (rmOpDesc.GetKind() == OperandKind::Reg)) { - // As embedded rounding only appies in R_R case, we can skip other checks for different paths. + // As embedded rounding only applies in R_R case, we can skip other checks for different paths. regNumber op1Reg = rmOp->GetRegNum(); assert(op1Reg != REG_NA); @@ -948,7 +1171,7 @@ void CodeGen::genHWIntrinsic_R_RM( // that failed and we either didn't get marked regOptional or we did and didn't get spilled // // As such, we need to emulate the removed CreateScalarUnsafe to ensure that op1 is in a - // SIMD register so the broadcast instruction can execute succesfully. We'll just move + // SIMD register so the broadcast instruction can execute successfully. We'll just move // the value into the target register and then broadcast it out from that. emitAttr movdAttr = emitActualTypeSize(node->GetSimdBaseType()); @@ -1212,7 +1435,7 @@ void CodeGen::genHWIntrinsic_R_R_R_RM(instruction ins, if (((instOptions & INS_OPTS_EVEX_b_MASK) != 0) && (op3Desc.GetKind() == OperandKind::Reg)) { - // As embedded rounding only appies in R_R case, we can skip other checks for different paths. + // As embedded rounding only applies in R_R case, we can skip other checks for different paths. regNumber op3Reg = op3->GetRegNum(); assert(op3Reg != REG_NA); @@ -1368,6 +1591,8 @@ void CodeGen::genHWIntrinsic_R_R_R_RM_I( // // Arguments: // intrinsic - intrinsic ID +// ins - the instruction chosen for the intrinsic and base type +// attr - the emit attributes for the instruction // nonConstImmReg - the register contains non-constant imm8 argument // baseReg - a register for the start of the switch table // offsReg - a register for the offset into the switch table @@ -1382,6 +1607,8 @@ void CodeGen::genHWIntrinsic_R_R_R_RM_I( // template void CodeGen::genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsic, + instruction ins, + emitAttr attr, regNumber nonConstImmReg, regNumber baseReg, regNumber offsReg, @@ -1389,18 +1616,44 @@ void CodeGen::genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsi { assert(nonConstImmReg != REG_NA); // AVX2 Gather intrinsics use managed non-const fallback since they have discrete imm8 value range - // that does work with the current compiler generated jump-table fallback + // that does not work with the current compiler generated jump-table fallback assert(!HWIntrinsicInfo::isAVX2GatherIntrinsic(intrinsic)); emitter* emit = GetEmitter(); - const unsigned maxByte = (unsigned)HWIntrinsicInfo::lookupImmUpperBound(intrinsic) + 1; - assert(maxByte <= 256); - BasicBlock* jmpTable[256]; + unsigned maxByte = (unsigned)HWIntrinsicInfo::lookupImmUpperBound(intrinsic); + unsigned mask = 0xFF; + + // Some instructions allow full-range immediates but are documented to ignore ranges of bits + // or to clamp the value. We can implement the same masking/clamping here in order to reduce + // the size of the generated code and jump table. + + if (HWIntrinsicInfo::HasFullRangeImm(intrinsic)) + { + maxByte = GetImmediateMaxAndMask(ins, EA_SIZE(attr), &mask); + + if (mask != 0xFF) + { + emit->emitIns_R_I(INS_and, EA_4BYTE, nonConstImmReg, mask); + } + else if (maxByte < 255) + { + emit->emitIns_R_I(INS_cmp, EA_4BYTE, nonConstImmReg, maxByte); - unsigned jmpTableBase = emit->emitBBTableDataGenBeg(maxByte, true); + BasicBlock* skipLabel = genCreateTempLabel(); + inst_JMP(EJ_jbe, skipLabel); + + instGen_Set_Reg_To_Imm(EA_4BYTE, nonConstImmReg, maxByte); + + genDefineTempLabel(skipLabel); + } + } + + assert(maxByte <= 255); + BasicBlock* jmpTable[256]; + unsigned jmpTableBase = emit->emitBBTableDataGenBeg(maxByte + 1, true); // Emit the jump table - for (unsigned i = 0; i < maxByte; i++) + for (unsigned i = 0; i <= maxByte; i++) { jmpTable[i] = genCreateTempLabel(); emit->emitDataGenData(i, jmpTable[i]); @@ -1423,9 +1676,18 @@ void CodeGen::genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsi genDefineTempLabel(switchTableBeg); - for (unsigned i = 0; i < maxByte; i++) + for (unsigned i = 0; i <= maxByte; i++) { genDefineTempLabel(jmpTable[i]); + + if ((i & mask) != i) + { + // This is a jump table entry that won't be hit, because the value can't exist after + // masking. We define the labels for these values in order to pad out the jump table + // so that the valid entries fall at the correct offsets, but we don't emit any code. + continue; + } + emitSwCase((int8_t)i); emit->emitIns_J(INS_jmp, switchTableEnd); } @@ -1463,7 +1725,7 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* }; regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, attr, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1488,7 +1750,7 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* }; regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, attr, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1504,7 +1766,7 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* }; regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, attr, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1540,7 +1802,7 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* }; regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, attr, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1581,13 +1843,67 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) switch (intrinsicId) { + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: case NI_Vector512_CreateScalarUnsafe: { if (varTypeIsIntegral(baseType)) { - genHWIntrinsic_R_RM(node, ins, emitActualTypeSize(baseType), targetReg, op1, instOptions); + emitAttr baseAttr = emitActualTypeSize(baseType); + +#if defined(TARGET_X86) + if (varTypeIsLong(baseType)) + { + assert(op1->isContained()); + + if (op1->OperIsLong()) + { + node->SetSimdBaseJitType(CORINFO_TYPE_INT); + + bool canCombineLoad = false; + GenTree* loPart = op1->gtGetOp1(); + GenTree* hiPart = op1->gtGetOp2(); + + if ((loPart->isContained() && hiPart->isContained()) && + (loPart->OperIs(GT_LCL_FLD) && hiPart->OperIs(GT_LCL_FLD))) + { + GenTreeLclFld* loFld = loPart->AsLclFld(); + GenTreeLclFld* hiFld = hiPart->AsLclFld(); + + canCombineLoad = (hiFld->GetLclNum() == loFld->GetLclNum()) && + (hiFld->GetLclOffs() == (loFld->GetLclOffs() + 4)); + } + + if (!canCombineLoad) + { + if (compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + genHWIntrinsic_R_RM(node, ins, baseAttr, targetReg, loPart, instOptions); + inst_RV_RV_TT_IV(INS_pinsrd, EA_16BYTE, targetReg, targetReg, hiPart, 0x01, + !compiler->canUseVexEncoding(), instOptions); + } + else + { + regNumber tmpReg = internalRegisters.GetSingle(node); + genHWIntrinsic_R_RM(node, ins, baseAttr, targetReg, loPart, instOptions); + genHWIntrinsic_R_RM(node, ins, baseAttr, tmpReg, hiPart, instOptions); + emit->emitIns_R_R(INS_punpckldq, EA_16BYTE, targetReg, tmpReg, instOptions); + } + break; + } + + op1 = loPart; + } + + ins = INS_movq; + baseAttr = EA_8BYTE; + } +#endif // TARGET_X86 + + genHWIntrinsic_R_RM(node, ins, baseAttr, targetReg, op1, instOptions); } else { @@ -1602,6 +1918,45 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) else { assert(instOptions == INS_OPTS_NONE); + + if (HWIntrinsicInfo::IsVectorCreateScalar(intrinsicId)) + { + // If this is CreateScalar, we need to ensure the upper elements are zeroed. + // Scalar integer loads and loads from memory always zero the upper elements, + // so reg to reg copies of floating types are the only place we need to + // do anything different. + + if (baseType == TYP_FLOAT) + { + if (compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + // insertps imm8 is: + // * Bits 0-3: zmask + // * Bits 4-5: count_d + // * Bits 6-7: count_s (register form only) + // + // We want zmask 0b1110 (0xE) to zero elements 1/2/3 + // We want count_d 0b00 (0x0) to insert the value to element 0 + // We want count_s 0b00 (0x0) as we're just taking element 0 of the source + + emit->emitIns_SIMD_R_R_R_I(INS_insertps, attr, targetReg, targetReg, op1Reg, 0x0E, + instOptions); + } + else + { + assert(targetReg != op1Reg); + emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg, instOptions); + emit->emitIns_Mov(INS_movss, attr, targetReg, op1Reg, /* canSkip */ false); + } + } + else + { + // `movq xmm xmm` zeroes the upper 64 bits. + genHWIntrinsic_R_RM(node, INS_movq, attr, targetReg, op1, instOptions); + } + break; + } + // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs emit->emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); } @@ -1783,6 +2138,20 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) } genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1, instOptions); } + else if (varTypeIsIntegral(baseType)) + { + assert(!varTypeIsLong(baseType) || TargetArchitecture::Is64Bit); + assert(HWIntrinsicInfo::IsVectorToScalar(intrinsicId)); + + attr = emitActualTypeSize(baseType); + genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1, instOptions); + + if (varTypeIsSmall(baseType)) + { + emit->emitIns_Mov(ins_Move_Extend(baseType, /* srcInReg */ true), emitTypeSize(baseType), targetReg, + targetReg, /* canSkip */ false); + } + } else { assert(varTypeIsFloating(baseType)); @@ -2251,7 +2620,8 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) // can also occur if the consumer calls it directly and just doesn't pass a constant value. regNumber baseReg = internalRegisters.Extract(node); regNumber offsReg = internalRegisters.GetSingle(node); - genHWIntrinsicJumpTableFallback(intrinsicId, op2->GetRegNum(), baseReg, offsReg, emitSwCase); + genHWIntrinsicJumpTableFallback(intrinsicId, ins, EA_16BYTE, op2->GetRegNum(), baseReg, offsReg, + emitSwCase); } break; } @@ -2297,15 +2667,47 @@ void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) assert(!op2->isUsedFromReg() || (op2->GetRegNum() != targetReg) || (op1Reg == targetReg)); emit->emitIns_Mov(INS_mov, emitTypeSize(targetType), targetReg, op1Reg, /* canSkip */ true); + instruction ins = INS_crc32; +#ifdef TARGET_AMD64 + bool needsEvex = false; + if (emit->IsExtendedGPReg(targetReg)) + { + needsEvex = true; + } + else if (op2->isUsedFromReg() && emit->IsExtendedGPReg(op2->GetRegNum())) + { + needsEvex = true; + } + else if (op2->isIndir()) + { + GenTreeIndir* indir = op2->AsIndir(); + + // We don't need to check if they are actually enregistered. + if (indir->HasBase() && emit->IsExtendedGPReg(indir->Base()->GetRegNum())) + { + needsEvex = true; + } + + if (indir->HasIndex() && emit->IsExtendedGPReg(indir->Index()->GetRegNum())) + { + needsEvex = true; + } + } + + if (needsEvex) + { + ins = INS_crc32_apx; + } +#endif // TARGET_AMD64 if ((baseType == TYP_UBYTE) || (baseType == TYP_USHORT)) // baseType is the type of the second argument { assert(targetType == TYP_INT); - genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(baseType), targetReg, op2, instOptions); + genHWIntrinsic_R_RM(node, ins, emitTypeSize(baseType), targetReg, op2, instOptions); } else { assert((targetType == TYP_INT) || (targetType == TYP_LONG)); - genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(targetType), targetReg, op2, instOptions); + genHWIntrinsic_R_RM(node, ins, emitTypeSize(targetType), targetReg, op2, instOptions); } break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index efad7ee0980253..bcd837f48ec750 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -91,6 +91,8 @@ HARDWARE_INTRINSIC(Vector64, Narrow, HARDWARE_INTRINSIC(Vector64, Round, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, ShiftLeft, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector64, ShuffleNative, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector64, ShuffleNativeFallback, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -213,6 +215,8 @@ HARDWARE_INTRINSIC(Vector128, Narrow, HARDWARE_INTRINSIC(Vector128, Round, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector128, ShuffleNative, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector128, ShuffleNativeFallback, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 7d572587bbaab4..a49d4b4bdc66bf 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -62,7 +62,7 @@ HARDWARE_INTRINSIC(Vector128, ConvertToUInt32Native, HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToUInt64Native, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) @@ -109,12 +109,14 @@ HARDWARE_INTRINSIC(Vector128, Narrow, HARDWARE_INTRINSIC(Vector128, Round, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector128, ShuffleNative, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector128, ShuffleNativeFallback, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256Unsafe, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector512, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) @@ -179,7 +181,7 @@ HARDWARE_INTRINSIC(Vector256, ConvertToUInt32Native, HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ConvertToUInt64Native, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, Create, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, CreateScalar, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, CreateScalar, 32, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, CreateSequence, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) @@ -228,12 +230,14 @@ HARDWARE_INTRINSIC(Vector256, Narrow, HARDWARE_INTRINSIC(Vector256, Round, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, ShiftLeft, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector256, ShuffleNative, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector256, ShuffleNativeFallback, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ToVector512, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ToVector512Unsafe, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, Truncate, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) @@ -299,7 +303,7 @@ HARDWARE_INTRINSIC(Vector512, ConvertToUInt32Native, HARDWARE_INTRINSIC(Vector512, ConvertToUInt64, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToUInt64Native, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, Create, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, CreateScalar, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, CreateScalar, 64, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector512, CreateScalarUnsafe, 64, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector512, CreateSequence, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Dot, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) @@ -349,12 +353,14 @@ HARDWARE_INTRINSIC(Vector512, Narrow, HARDWARE_INTRINSIC(Vector512, Round, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, ShiftLeft, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector512, ShuffleNative, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(Vector512, ShuffleNativeFallback, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector512, Sqrt, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, StoreAligned, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, StoreAlignedNonTemporal, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, StoreUnsafe, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, Sum, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ToScalar, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ToScalar, 64, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, Truncate, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, WidenLower, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, WidenUpper, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index 33278184d02d29..e16951558ab85a 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -2125,16 +2125,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { if (sig->numArgs == 1) { -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !impStackTop(0).val->IsIntegralConst()) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - break; - } -#endif // TARGET_X86 - op1 = impPopStack().val; retNode = gtNewSimdCreateBroadcastNode(retType, op1, simdBaseJitType, simdSize); break; @@ -2266,16 +2256,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType)) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - break; - } -#endif // TARGET_X86 - IntrinsicNodeBuilder nodeBuilder(getAllocator(CMK_ASTNode), sig->numArgs); // TODO-CQ: We don't handle contiguous args for anything except TYP_FLOAT today @@ -2321,16 +2301,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 1); -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !impStackTop(0).val->IsIntegralConst()) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - break; - } -#endif // TARGET_X86 - op1 = impPopStack().val; retNode = gtNewSimdCreateScalarNode(retType, op1, simdBaseJitType, simdSize); break; @@ -2342,16 +2312,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 1); -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !impStackTop(0).val->IsIntegralConst()) - { - // TODO-XARCH-CQ: It may be beneficial to emit the movq - // instruction, which takes a 64-bit memory address and - // works on 32-bit x86 systems. - break; - } -#endif // TARGET_X86 - op1 = impPopStack().val; retNode = gtNewSimdCreateScalarUnsafeNode(retType, op1, simdBaseJitType, simdSize); break; @@ -2376,27 +2336,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } } - - if (varTypeIsLong(simdBaseType)) - { - if (!impStackTop(0).val->OperIsConst()) - { - // When op2 is a constant, we can skip the multiplication allowing us to always - // generate better code. However, if it isn't then we need to fallback in the - // cases where multiplication isn't supported. - - if ((simdSize != 64) && !canUseEvexEncoding()) - { - // TODO-XARCH-CQ: We should support long/ulong multiplication - break; - } - } - -#if defined(TARGET_X86) - // TODO-XARCH-CQ: We need to support 64-bit CreateBroadcast - break; -#endif // TARGET_X86 - } } impSpillSideEffect(true, stackState.esStackDepth - @@ -2462,14 +2401,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) - { - // We need SSE41 to handle long, use software fallback - break; - } -#endif // TARGET_X86 - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2765,13 +2696,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case TYP_LONG: case TYP_ULONG: { - bool useToScalar = op2->IsIntegralConst(0); - -#if defined(TARGET_X86) - useToScalar &= !varTypeIsLong(simdBaseType); -#endif // TARGET_X86 - - if (!useToScalar && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) + if (!op2->IsIntegralConst(0) && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) { // Using software fallback if simdBaseType is not supported by hardware return nullptr; @@ -3349,15 +3274,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType)) - { - // TODO-XARCH-CQ: We can't handle long here, only because one of the args might - // be scalar, and gtNewSimdCreateBroadcastNode doesn't handle long on x86. - break; - } -#endif // TARGET_X86 - CORINFO_ARG_LIST_HANDLE arg1 = sig->args; CORINFO_ARG_LIST_HANDLE arg2 = info.compCompHnd->getArgNext(arg1); var_types argType = TYP_UNKNOWN; @@ -3514,18 +3430,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); -#if defined(TARGET_X86) - if ((simdBaseType == TYP_LONG) || (simdBaseType == TYP_DOUBLE)) - { - if (!compOpportunisticallyDependsOn(InstructionSet_EVEX) && !impStackTop(0).val->IsCnsIntOrI()) - { - // If vpsraq is available, we can use that. We can also trivially emulate arithmetic shift by const - // amount. Otherwise, more work is required for long types, so we fall back to managed for now. - break; - } - } -#endif // TARGET_X86 - if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { genTreeOps op = varTypeIsUnsigned(simdBaseType) ? GT_RSZ : GT_RSH; @@ -3616,37 +3520,62 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_Shuffle: case NI_Vector256_Shuffle: case NI_Vector512_Shuffle: + case NI_Vector128_ShuffleNative: + case NI_Vector256_ShuffleNative: + case NI_Vector512_ShuffleNative: + case NI_Vector128_ShuffleNativeFallback: + case NI_Vector256_ShuffleNativeFallback: + case NI_Vector512_ShuffleNativeFallback: { assert((sig->numArgs == 2) || (sig->numArgs == 3)); + // The Native variants are non-deterministic on xarch + bool isShuffleNative = (intrinsic != NI_Vector128_Shuffle) && (intrinsic != NI_Vector256_Shuffle) && + (intrinsic != NI_Vector512_Shuffle); + if (isShuffleNative && BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + GenTree* indices = impStackTop(0).val; - if (!indices->IsCnsVec() || !IsValidForShuffle(indices->AsVecCon(), simdSize, simdBaseType)) + // Check if the required intrinsics are available to emit now (validForShuffle). If we have variable + // indices that might become possible to emit later (due to them becoming constant), this will be + // indicated in canBecomeValidForShuffle; otherwise, it's just the same as validForShuffle. + bool canBecomeValidForShuffle = false; + bool validForShuffle = + IsValidForShuffle(indices, simdSize, simdBaseType, &canBecomeValidForShuffle, isShuffleNative); + + // If it isn't valid for shuffle (and can't become valid later), then give up now. + if (!canBecomeValidForShuffle) + { + return nullptr; + } + + // If the indices might become constant later, then we don't emit for now, delay until later. + if ((!validForShuffle) || (!indices->IsCnsVec())) { assert(sig->numArgs == 2); - if (!opts.OptimizationEnabled()) + if (opts.OptimizationEnabled()) { // Only enable late stage rewriting if optimizations are enabled // as we won't otherwise encounter a constant at the later point - return nullptr; - } - - op2 = impSIMDPopStack(); - op1 = impSIMDPopStack(); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); - retNode->AsHWIntrinsic()->SetMethodHandle(this, method R2RARG(*entryPoint)); - break; + retNode->AsHWIntrinsic()->SetMethodHandle(this, method R2RARG(*entryPoint)); + break; + } } if (sig->numArgs == 2) { - op2 = impSIMDPopStack(); - op1 = impSIMDPopStack(); - - retNode = gtNewSimdShuffleNode(retType, op1, op2, simdBaseJitType, simdSize); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + retNode = gtNewSimdShuffleNode(retType, op1, op2, simdBaseJitType, simdSize, isShuffleNative); } break; } @@ -3781,14 +3710,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 1); -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) - { - // We need SSE41 to handle long, use software fallback - break; - } -#endif // TARGET_X86 - op1 = impSIMDPopStack(); retNode = gtNewSimdSumNode(retType, op1, simdBaseJitType, simdSize); break; @@ -3800,14 +3721,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 1); -#if defined(TARGET_X86) - if (varTypeIsLong(simdBaseType) && !compOpportunisticallyDependsOn(InstructionSet_SSE41)) - { - // We need SSE41 to handle long, use software fallback - break; - } -#endif // TARGET_X86 - op1 = impSIMDPopStack(); retNode = gtNewSimdToScalarNode(retType, op1, simdBaseJitType, simdSize); break; diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index c4fae10ce005ab..12b0cfb2588b50 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -3861,7 +3861,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(CORINFO_FIELD_HANDLE field, CORI int simdWidth = getSIMDTypeSizeInBytes(fieldClsHnd); if ((simdWidth > 0) && IsBaselineSimdIsaSupported()) { - assert((totalSize <= 32) && (totalSize <= MaxStructSize)); + assert((totalSize <= 64) && (totalSize <= MaxStructSize)); var_types simdType = getSIMDTypeForSize(simdWidth); bool hwAccelerated = true; @@ -4747,12 +4747,15 @@ void Compiler::impImportLeaveEHRegions(BasicBlock* block) } #endif - unsigned finallyNesting = compHndBBtab[XTnum].ebdHandlerNestingLevel; - assert(finallyNesting <= compHndBBtabCount); + // We now record the EH region ID on GT_END_LFIN instead of the finally nesting depth, + // as the later can change as we optimize the code. + // + unsigned const ehID = compHndBBtab[XTnum].ebdID; + assert(ehID <= impInlineRoot()->compEHID); - GenTree* endLFin = new (this, GT_END_LFIN) GenTreeVal(GT_END_LFIN, TYP_VOID, finallyNesting); - endLFinStmt = gtNewStmt(endLFin); - endCatches = NULL; + GenTree* const endLFin = new (this, GT_END_LFIN) GenTreeVal(GT_END_LFIN, TYP_VOID, ehID); + endLFinStmt = gtNewStmt(endLFin); + endCatches = NULL; encFinallies++; } @@ -6974,9 +6977,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_ENDFINALLY: - if (compIsForInlining()) + if (compIsForInlining() && !opts.compInlineMethodsWithEH) { - assert(!"Shouldn't have exception handlers in the inliner!"); + assert(!"Shouldn't have exception handlers in the inlinee!"); compInlineResult->NoteFatal(InlineObservation::CALLEE_HAS_ENDFINALLY); return; } @@ -6998,9 +7001,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_ENDFILTER: - if (compIsForInlining()) + if (compIsForInlining() && !opts.compInlineMethodsWithEH) { - assert(!"Shouldn't have exception handlers in the inliner!"); + assert(!"Shouldn't have exception handlers in the inlinee!"); compInlineResult->NoteFatal(InlineObservation::CALLEE_HAS_ENDFILTER); return; } @@ -7572,7 +7575,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) LEAVE: - if (compIsForInlining()) + if (compIsForInlining() && !opts.compInlineMethodsWithEH) { compInlineResult->NoteFatal(InlineObservation::CALLEE_HAS_LEAVE); return; @@ -11481,7 +11484,7 @@ inline void Compiler::impReimportMarkBlock(BasicBlock* block) void Compiler::impVerifyEHBlock(BasicBlock* block) { assert(block->hasTryIndex()); - assert(!compIsForInlining()); + assert(!compIsForInlining() || opts.compInlineMethodsWithEH); unsigned tryIndex = block->getTryIndex(); EHblkDsc* HBtab = ehGetDsc(tryIndex); @@ -12552,9 +12555,8 @@ void Compiler::impImport() // If the method had EH, we may be missing some pred edges // (notably those from BBJ_EHFINALLYRET blocks). Add them. - // Only needed for the root method, since inlinees can't have EH. // - if (!compIsForInlining() && (info.compXcptnsCount > 0)) + if (info.compXcptnsCount > 0) { impFixPredLists(); JITDUMP("\nAfter impImport() added blocks for try,catch,finally"); @@ -12962,7 +12964,7 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I // // Arguments: // fncHandle -- inline candidate method -// methInfo -- method info from VN +// methInfo -- method info from VM // forceInline -- true if method is marked with AggressiveInlining // inlineResult -- ongoing inline evaluation // @@ -12976,10 +12978,13 @@ void Compiler::impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle, // We shouldn't have made up our minds yet... assert(!inlineResult->IsDecided()); - if (methInfo->EHcount) + if (methInfo->EHcount > 0) { - inlineResult->NoteFatal(InlineObservation::CALLEE_HAS_EH); - return; + if (!opts.compInlineMethodsWithEH) + { + inlineResult->NoteFatal(InlineObservation::CALLEE_HAS_EH); + return; + } } if ((methInfo->ILCode == nullptr) || (codeSize == 0)) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 603cd256109134..4db4d09c751871 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3671,6 +3671,8 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, case NI_System_Span_get_Item: case NI_System_ReadOnlySpan_get_Item: { + optMethodFlags |= OMF_HAS_ARRAYREF; + // Have index, stack pointer-to Span s on the stack. Expand to: // // For Span @@ -7763,6 +7765,25 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, return; } + if (inlineCandidateInfo->methInfo.EHcount > 0) + { + // We cannot inline methods with EH into filter clauses, even if marked as aggressive inline + // + if (bbInFilterBBRange(compCurBB)) + { + inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_WITHIN_FILTER); + return; + } + + // Do not inline pinvoke stubs with EH. + // + if ((methAttr & CORINFO_FLG_PINVOKE) != 0) + { + inlineResult->NoteFatal(InlineObservation::CALLEE_HAS_EH); + return; + } + } + // The old value should be null OR this call should be a guarded devirtualization candidate. assert(call->IsGuardedDevirtualizationCandidate() || (call->GetSingleInlineCandidateInfo() == nullptr)); @@ -10588,7 +10609,7 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { namespaceName += 1; -#if defined(TARGET_XARCH) || defined(TARGET_ARM64) +#if defined(TARGET_XARCH) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) if (strcmp(namespaceName, "Buffers.Binary") == 0) { if (strcmp(className, "BinaryPrimitives") == 0) @@ -10638,17 +10659,16 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) if (isVectorT || (strcmp(className, "Vector") == 0)) { - if (strncmp(methodName, - "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where // possible but, they all prefix the qualified name of the interface first, so we'll // check for that and skip the prefix before trying to resolve the method. - if (strncmp(methodName + 70, ",T>.", 7) == 0) + if (strncmp(methodName + 60, ",T>.", 7) == 0) { - methodName += 77; + methodName += 67; } } diff --git a/src/coreclr/jit/inline.def b/src/coreclr/jit/inline.def index 2b045ad5d20009..44d6e83929e0ba 100644 --- a/src/coreclr/jit/inline.def +++ b/src/coreclr/jit/inline.def @@ -133,6 +133,7 @@ INLINE_OBSERVATION(CANT_CLASS_INIT, bool, "can't class init", INLINE_OBSERVATION(COMPILATION_ERROR, bool, "compilation error", FATAL, CALLSITE) INLINE_OBSERVATION(COMPILATION_FAILURE, bool, "failed to compile", FATAL, CALLSITE) INLINE_OBSERVATION(EXPLICIT_TAIL_PREFIX, bool, "explicit tail prefix", FATAL, CALLSITE) +INLINE_OBSERVATION(EH_TABLE_FULL, bool, "callee has eh, eh table is full", FATAL, CALLSITE) INLINE_OBSERVATION(GENERIC_DICTIONARY_LOOKUP, bool, "runtime dictionary lookup", FATAL, CALLSITE) INLINE_OBSERVATION(HAS_CALL_VIA_LDVIRTFTN, bool, "call via ldvirtftn", FATAL, CALLSITE) INLINE_OBSERVATION(HAS_COMPLEX_HANDLE, bool, "complex handle access", FATAL, CALLSITE) diff --git a/src/coreclr/jit/inlinepolicy.cpp b/src/coreclr/jit/inlinepolicy.cpp index d22676a62a3ea2..357cf6090b7957 100644 --- a/src/coreclr/jit/inlinepolicy.cpp +++ b/src/coreclr/jit/inlinepolicy.cpp @@ -911,21 +911,6 @@ int DefaultPolicy::DetermineCallsiteNativeSizeEstimate(CORINFO_METHOD_INFO* meth void DefaultPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) { - -#if defined(DEBUG) - - // Punt if we're inlining and we've reached the acceptance limit. - int limit = JitConfig.JitInlineLimit(); - unsigned current = m_RootCompiler->m_inlineStrategy->GetInlineCount(); - - if (!m_IsPrejitRoot && (limit >= 0) && (current >= static_cast(limit))) - { - SetFailure(InlineObservation::CALLSITE_OVER_INLINE_LIMIT); - return; - } - -#endif // defined(DEBUG) - assert(InlDecisionIsCandidate(m_Decision)); assert(m_Observation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE); @@ -1134,20 +1119,6 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) assert(InlDecisionIsCandidate(m_Decision)); assert(m_Observation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE); -#if defined(DEBUG) - - // Punt if we're inlining and we've reached the acceptance limit. - int limit = JitConfig.JitInlineLimit(); - unsigned current = m_RootCompiler->m_inlineStrategy->GetInlineCount(); - - if (!m_IsPrejitRoot && (limit >= 0) && (current >= static_cast(limit))) - { - SetFailure(InlineObservation::CALLSITE_OVER_INLINE_LIMIT); - return; - } - -#endif // defined(DEBUG) - // Budget check. const bool overBudget = this->BudgetCheck(); if (overBudget) @@ -2400,21 +2371,6 @@ bool DiscretionaryPolicy::PropagateNeverToRuntime() const void DiscretionaryPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) { - -#if defined(DEBUG) - - // Punt if we're inlining and we've reached the acceptance limit. - int limit = JitConfig.JitInlineLimit(); - unsigned current = m_RootCompiler->m_inlineStrategy->GetInlineCount(); - - if (!m_IsPrejitRoot && (limit >= 0) && (current >= static_cast(limit))) - { - SetFailure(InlineObservation::CALLSITE_OVER_INLINE_LIMIT); - return; - } - -#endif // defined(DEBUG) - // Make additional observations based on the method info MethodInfoObservations(methodInfo); diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index fe3da0a63eb904..bd614016bdb24d 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -920,6 +920,9 @@ CodeGen::OperandDesc CodeGen::genOperandDesc(GenTree* op) break; } + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: case NI_Vector512_CreateScalarUnsafe: @@ -927,7 +930,7 @@ CodeGen::OperandDesc CodeGen::genOperandDesc(GenTree* op) // The hwintrinsic should be contained and its // op1 should be either contained or spilled. This // allows us to transparently "look through" the - // CreateScalarUnsafe and treat it directly like + // CreateScalar/Unsafe and treat it directly like // a load from memory. assert(hwintrinsic->isContained()); diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index e90102caf241fe..305a8f7124d7df 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -532,7 +532,6 @@ enum insOpts : unsigned INS_OPTS_JALR, // see ::emitIns_J_R(). INS_OPTS_J, // see ::emitIns_J(). INS_OPTS_J_cond, // see ::emitIns_J_cond_la(). - INS_OPTS_I, // see ::emitLoadImmediate(). INS_OPTS_C, // see ::emitIns_Call(). INS_OPTS_RELOC, // see ::emitIns_R_AI(). }; diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index 5957b4deb9799b..8ce09fa6468934 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -228,10 +228,10 @@ INST3(movups, "movups", IUM_WR, PCKFLT(0x11), BAD_CODE, INST3(mulps, "mulps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x59), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Multiply packed singles INST3(mulss, "mulss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x59), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Multiply scalar single INST3(orps, "orps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x56), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Or packed singles -INST3(prefetchnta, "prefetchnta", IUM_RD, 0x000F0018, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG) -INST3(prefetcht0, "prefetcht0", IUM_RD, 0x000F0818, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG) -INST3(prefetcht1, "prefetcht1", IUM_RD, 0x000F1018, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG) -INST3(prefetcht2, "prefetcht2", IUM_RD, 0x000F1818, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG) +INST3(prefetchnta, "prefetchnta", IUM_RD, 0x000F0018, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG | Encoding_REX2) +INST3(prefetcht0, "prefetcht0", IUM_RD, 0x000F0818, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG | Encoding_REX2) +INST3(prefetcht1, "prefetcht1", IUM_RD, 0x000F1018, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG | Encoding_REX2) +INST3(prefetcht2, "prefetcht2", IUM_RD, 0x000F1818, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG | Encoding_REX2) INST3(rcpps, "rcpps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x53), INS_TT_NONE, REX_WIG | Encoding_VEX) // Reciprocal of packed singles INST3(rcpss, "rcpss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x53), INS_TT_NONE, REX_WIG | Encoding_VEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Reciprocal of scalar single INST3(rsqrtps, "rsqrtps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x52), INS_TT_NONE, REX_WIG | Encoding_VEX) // Reciprocal Sqrt of packed singles @@ -280,16 +280,16 @@ INST3(mfence, "mfence", IUM_RD, 0x000FF0AE, BAD_CODE, INST3(minpd, "minpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5D), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Return Minimum packed doubles INST3(minsd, "minsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x5D), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Return Minimum scalar double INST3(movapd, "movapd", IUM_WR, PCKDBL(0x29), BAD_CODE, PCKDBL(0x28), INS_TT_FULL_MEM, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) -INST3(movd, "movd", IUM_WR, PCKDBL(0x7E), BAD_CODE, PCKDBL(0x6E), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_WX | Encoding_VEX | Encoding_EVEX) // Move DWORD/QWORD between xmm regs <-> memory/r32/r64 regs -INST3(movdqa, "movdqa", IUM_WR, PCKDBL(0x7F), BAD_CODE, PCKDBL(0x6F), INS_TT_FULL_MEM, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) -INST3(movdqu, "movdqu", IUM_WR, SSEFLT(0x7F), BAD_CODE, SSEFLT(0x6F), INS_TT_FULL_MEM, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) +INST3(movd, "movd", IUM_WR, PCKDBL(0x7E), BAD_CODE, PCKDBL(0x6E), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_WX | Encoding_VEX | Encoding_EVEX | Encoding_REX2) // Move DWORD/QWORD between xmm regs <-> memory/r32/r64 regs +INST3(movdqa, "movdqa", IUM_WR, PCKDBL(0x7F), BAD_CODE, PCKDBL(0x6F), INS_TT_FULL_MEM, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | Encoding_REX2) +INST3(movdqu, "movdqu", IUM_WR, SSEFLT(0x7F), BAD_CODE, SSEFLT(0x6F), INS_TT_FULL_MEM, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | Encoding_REX2 ) INST3(movhpd, "movhpd", IUM_WR, PCKDBL(0x17), BAD_CODE, PCKDBL(0x16), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) INST3(movlpd, "movlpd", IUM_WR, PCKDBL(0x13), BAD_CODE, PCKDBL(0x12), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) INST3(movmskpd, "movmskpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x50), INS_TT_NONE, REX_WIG | Encoding_VEX) // Extract 2-bit sign mask from xmm and store in reg. The upper bits of r32 or r64 are filled with zeros. INST3(movntdq, "movntdq", IUM_WR, PCKDBL(0xE7), BAD_CODE, BAD_CODE, INS_TT_FULL_MEM, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) -INST3(movnti, "movnti", IUM_WR, PCKFLT(0xC3), BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WX) +INST3(movnti, "movnti", IUM_WR, PCKFLT(0xC3), BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WX | Encoding_REX2) INST3(movntpd, "movntpd", IUM_WR, PCKDBL(0x2B), BAD_CODE, BAD_CODE, INS_TT_FULL_MEM, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) -INST3(movq, "movq", IUM_WR, PCKDBL(0xD6), BAD_CODE, SSEFLT(0x7E), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) // Move Quadword between memory/mm <-> regs +INST3(movq, "movq", IUM_WR, PCKDBL(0xD6), BAD_CODE, SSEFLT(0x7E), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | Encoding_REX2) // Move Quadword between memory/mm <-> regs INST3(movsd_simd, "movsd", IUM_WR, SSEDBL(0x11), BAD_CODE, SSEDBL(0x10), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) INST3(movupd, "movupd", IUM_WR, PCKDBL(0x11), BAD_CODE, PCKDBL(0x10), INS_TT_FULL_MEM, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) INST3(mulpd, "mulpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x59), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Multiply packed doubles @@ -602,16 +602,14 @@ INST3(blsmsk, "blsmsk", IUM_WR, BAD_CODE, BAD_CODE, INST3(blsr, "blsr", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_Has_NF) // Reset Lowest Set Bit // BMI2 -INST3(bzhi, "bzhi", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF5), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction | Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF) // Zero High Bits Starting with Specified Bit Position -INST3(mulx, "mulx", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF6), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Unsigned Multiply Without Affecting Flags -INST3(pdep, "pdep", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF5), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Parallel Bits Deposit -INST3(pext, "pext", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF5), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Parallel Bits Extract -INST3(rorx, "rorx", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0xF0), INS_TT_NONE, REX_WX | Encoding_VEX) -#ifdef TARGET_AMD64 -INST3(sarx, "sarx", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0xF7), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift Arithmetic Right Without Affecting Flags -INST3(shlx, "shlx", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF7), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift Logical Left Without Affecting Flags -INST3(shrx, "shrx", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF2, 0xF7), INS_TT_NONE, REX_WX | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift Logical Right Without Affecting Flags -#endif +INST3(bzhi, "bzhi", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF5), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF) // Zero High Bits Starting with Specified Bit Position +INST3(mulx, "mulx", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF6), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Unsigned Multiply Without Affecting Flags +INST3(pdep, "pdep", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF5), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Parallel Bits Deposit +INST3(pext, "pext", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF5), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Parallel Bits Extract +INST3(rorx, "rorx", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0xF0), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX) +INST3(sarx, "sarx", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0xF7), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift Arithmetic Right Without Affecting Flags +INST3(shlx, "shlx", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF7), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift Logical Left Without Affecting Flags +INST3(shrx, "shrx", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF2, 0xF7), INS_TT_NONE, REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift Logical Right Without Affecting Flags INST3(LAST_BMI_INSTRUCTION, "LAST_BMI_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, BAD_CODE, INS_TT_NONE, INS_FLAGS_None) @@ -622,8 +620,8 @@ INST3(FIRST_AVX512_INSTRUCTION, "FIRST_AVX512_INSTRUCTION", IUM_WR, BAD_CODE, BA // AVX512F INST3(kandw, "kandw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x41), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND masks INST3(kandnw, "kandnw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x42), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND NOT masks -INST3(kmovw_gpr, "kmovw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovw_msk, "kmovw", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovw_gpr, "kmovw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers +INST3(kmovw_msk, "kmovw", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers INST3(knotw, "knotw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x44), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // NOT mask register INST3(korw, "korw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x45), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical OR masks INST3(kortestw, "kortestw", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x98), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags @@ -772,10 +770,10 @@ INST3(kandd, "kandd", IUM_WR, BAD_CODE, BAD_ INST3(kandq, "kandq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x41), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND masks INST3(kandnd, "kandnd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x42), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND NOT masks INST3(kandnq, "kandnq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x42), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND NOT masks -INST3(kmovd_gpr, "kmovd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovd_msk, "kmovd", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovq_gpr, "kmovq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovq_msk, "kmovq", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovd_gpr, "kmovd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers +INST3(kmovd_msk, "kmovd", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers +INST3(kmovq_gpr, "kmovq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W1 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers +INST3(kmovq_msk, "kmovq", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers INST3(knotd, "knotd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x44), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // NOT mask register INST3(knotq, "knotq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x44), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // NOT mask register INST3(kord, "kord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x45), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical OR masks @@ -838,8 +836,8 @@ INST3(kaddb, "kaddb", IUM_WR, BAD_CODE, BAD_ INST3(kaddw, "kaddw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x4A), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Add two masks INST3(kandb, "kandb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x41), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND masks INST3(kandnb, "kandnb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x42), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical AND NOT masks -INST3(kmovb_gpr, "kmovb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovb_msk, "kmovb", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovb_gpr, "kmovb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers +INST3(kmovb_msk, "kmovb", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | Encoding_EVEX | KInstruction) // Move from and to mask registers INST3(knotb, "knotb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x44), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // NOT mask register INST3(korb, "korb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x45), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction | KInstructionWithLBit) // Bitwise logical OR masks INST3(kortestb, "kortestb", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x98), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags @@ -919,7 +917,7 @@ INST3(vcvttps2ibs, "cvttps2ibs", IUM_WR, BAD_CODE, BAD_ INST3(vcvttps2iubs, "cvttps2iubs", IUM_WR, BAD_CODE, BAD_CODE, PCKDBLMAP(0x05, 0x6A), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt with truncation/saturation scalar single to unsigned DWORD/QWORD INST3(vmpsadbw, "mpsadbw", IUM_WR, BAD_CODE, BAD_CODE, AVX3A(0x42), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Compute Multiple Packed Sums of Absolute Difference -INST3(vminmaxsd, "minmaxsd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x53), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Return Minimum/Maximum scalar double +INST3(vminmaxsd, "minmaxsd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x53), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Return Minimum/Maximum scalar double INST3(vminmaxss, "minmaxss", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x53), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Return Minimum/Maximum scalar single INST3(vminmaxpd, "minmaxpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x52), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported | INS_Flags_IsDstSrcSrcAVXInstruction) // Return Maximum packed doubles INST3(vminmaxps, "minmaxps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x52), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported | INS_Flags_IsDstSrcSrcAVXInstruction) // Return Maximum packed singles @@ -969,24 +967,30 @@ INST3(LAST_APX_INSTRUCTION, "LAST_APX_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, // Scalar instructions in SSE4.2 INST3(crc32, "crc32", IUM_RW, BAD_CODE, BAD_CODE, PSSE38(0xF2, 0xF0), INS_TT_NONE, INS_FLAGS_None) +#ifdef TARGET_AMD64 +INST3(crc32_apx, "crc32", IUM_RW, BAD_CODE, BAD_CODE, 0x0000F0, INS_TT_NONE, INS_FLAGS_None) +#endif // BMI1 INST3(tzcnt, "tzcnt", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xBC), INS_TT_NONE, Undefined_OF | Undefined_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | Encoding_REX2) // Count the Number of Trailing Zero Bits +#ifdef TARGET_AMD64 +INST3(tzcnt_apx, "tzcnt", IUM_WR, BAD_CODE, BAD_CODE, 0x0000F4, INS_TT_NONE, Undefined_OF | Undefined_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_Has_NF) // Count the Number of Trailing Zero Bits +#endif // LZCNT INST3(lzcnt, "lzcnt", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xBD), INS_TT_NONE, Undefined_OF | Undefined_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | Encoding_REX2) +#ifdef TARGET_AMD64 +INST3(lzcnt_apx, "lzcnt", IUM_WR, BAD_CODE, BAD_CODE, 0x0000F5, INS_TT_NONE, Undefined_OF | Undefined_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_Has_NF) +#endif // MOVBE INST3(movbe, "movbe", IUM_WR, PCKMVB(0xF1), BAD_CODE, PCKMVB(0xF0), INS_TT_NONE, INS_FLAGS_None) // POPCNT INST3(popcnt, "popcnt", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xB8), INS_TT_NONE, Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Resets_CF | Encoding_REX2) - -#if defined(TARGET_AMD64) -INST3(tzcnt_apx, "tzcnt", IUM_WR, BAD_CODE, BAD_CODE, 0x0000F4, INS_TT_NONE, Undefined_OF | Undefined_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_Has_NF) // Count the Number of Trailing Zero Bits -INST3(lzcnt_apx, "lzcnt", IUM_WR, BAD_CODE, BAD_CODE, 0x0000F5, INS_TT_NONE, Undefined_OF | Undefined_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_Has_NF) -INST3(popcnt_apx, "popcnt", IUM_WR, BAD_CODE, BAD_CODE, 0x000088, INS_TT_NONE, Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Resets_CF | INS_Flags_Has_NF) -#endif // TARGET_AMD64 +#ifdef TARGET_AMD64 +INST3(popcnt_apx, "popcnt", IUM_WR, BAD_CODE, BAD_CODE, 0x000088, INS_TT_NONE, Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Resets_CF | INS_Flags_Has_NF) +#endif INST3(neg, "neg", IUM_RW, 0x0018F6, BAD_CODE, 0x0018F6, INS_TT_NONE, Writes_OF | Writes_SF | Writes_ZF | Writes_AF | Writes_PF | Writes_CF | INS_FLAGS_Has_Wbit | Encoding_REX2 | INS_Flags_Has_NDD | INS_Flags_Has_NF) INST3(not, "not", IUM_RW, 0x0010F6, BAD_CODE, 0x0010F6, INS_TT_NONE, INS_FLAGS_None | INS_FLAGS_Has_Wbit | Encoding_REX2 | INS_Flags_Has_NDD) diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 5fe7439d2bc658..f4fda0855d46cc 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -119,6 +119,9 @@ CONFIG_INTEGER(JitInlinePrintStats, "JitInlinePrintStats", 0) CONFIG_INTEGER(JitInlineSize, "JITInlineSize", DEFAULT_MAX_INLINE_SIZE) CONFIG_INTEGER(JitInlineDepth, "JITInlineDepth", DEFAULT_MAX_INLINE_DEPTH) CONFIG_INTEGER(JitForceInlineDepth, "JITForceInlineDepth", DEFAULT_MAX_FORCE_INLINE_DEPTH) +RELEASE_CONFIG_INTEGER(JitInlineMethodsWithEH, "JitInlineMethodsWithEH", 1) +CONFIG_STRING(JitInlineMethodsWithEHRange, "JitInlineMethodsWithEHRange") + CONFIG_INTEGER(JitLongAddress, "JitLongAddress", 0) // Force using the large pseudo instruction form for long address CONFIG_INTEGER(JitMaxUncheckedOffset, "JitMaxUncheckedOffset", 8) @@ -381,8 +384,6 @@ CONFIG_INTEGER(JitStressPromotedEvexEncoding, "JitStressPromotedEvexEncoding", 0 CONFIG_INTEGER(JitStressEvexEncoding, "JitStressEvexEncoding", 0) #endif -RELEASE_CONFIG_INTEGER(PreferredVectorBitWidth, "PreferredVectorBitWidth", 0) // The preferred decimal width, in bits, to use for any implicit vectorization emitted. A value less than 128 is treated as the system default. - // // Hardware Intrinsic ISAs; keep in sync with clrconfigvalues.h // @@ -798,9 +799,6 @@ RELEASE_CONFIG_INTEGER(JitEnablePhysicalPromotion, "JitEnablePhysicalPromotion", // Enable cross-block local assertion prop RELEASE_CONFIG_INTEGER(JitEnableCrossBlockLocalAssertionProp, "JitEnableCrossBlockLocalAssertionProp", 1) -// Do greedy RPO-based layout in Compiler::fgReorderBlocks. -RELEASE_CONFIG_INTEGER(JitDoReversePostOrderLayout, "JitDoReversePostOrderLayout", 1); - // Enable strength reduction RELEASE_CONFIG_INTEGER(JitEnableStrengthReduction, "JitEnableStrengthReduction", 1) diff --git a/src/coreclr/jit/jitee.h b/src/coreclr/jit/jitee.h index edfbafc917d470..8c6e82ec7b9dd3 100644 --- a/src/coreclr/jit/jitee.h +++ b/src/coreclr/jit/jitee.h @@ -44,10 +44,6 @@ class JitFlags JIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention #endif -#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. @@ -147,10 +143,6 @@ class JitFlags FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SOFTFP_ABI, JIT_FLAG_SOFTFP_ABI); #endif // TARGET_ARM -#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/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 3356349e61adc4..5290a29ca24a34 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -241,7 +241,7 @@ bool EHblkDsc::ebdIsSameTry(BasicBlock* ebdTryBeg, BasicBlock* ebdTryLast) void EHblkDsc::DispEntry(unsigned XTnum) { - printf(" %2u ::", XTnum); + printf(" %2u %2u ::", ebdID, XTnum); #if defined(FEATURE_EH_WINDOWS_X86) if (ebdHandlerNestingLevel == 0) @@ -1258,6 +1258,30 @@ EHblkDsc* Compiler::ehInitTryBlockRange(BasicBlock* blk, BasicBlock** tryBeg, Ba return tryTab; } +//------------------------------------------------------------------------ +// ehFindEHblkDscById: find an eh table entry by its ID +// +// Argument: +// ID to use in search +// +// Returns: +// Pointer to the entry, or nullptr +// +EHblkDsc* Compiler::ehFindEHblkDscById(unsigned short id) +{ + EHblkDsc* result = nullptr; + for (EHblkDsc* const xtab : EHClauses(this)) + { + if (xtab->ebdID == id) + { + result = xtab; + break; + } + } + + return result; +} + /***************************************************************************** * This method updates the value of ebdTryBeg */ @@ -1339,8 +1363,8 @@ void Compiler::fgFindTryRegionEnds() // Null out try end pointers to signify the given clause hasn't been visited yet. for (EHblkDsc* const HBtab : EHClauses(this)) { - // Ignore try regions inside handler regions. - if (!HBtab->ebdTryLast->hasHndIndex()) + // Ignore try regions inside funclet regions. + if (!UsesFunclets() || !HBtab->ebdTryLast->hasHndIndex()) { HBtab->ebdTryLast = nullptr; unsetTryEnds++; @@ -1728,8 +1752,9 @@ EHblkDsc* Compiler::fgTryAddEHTableEntries(unsigned XTnum, unsigned count, bool if (deferAdding) { // We can add count entries... + // (we may not have allocated a table, so return a dummy non-null entry) // - return compHndBBtab; + return (EHblkDsc*)(0x1); } if (newCount > compHndBBtabAllocCount) @@ -3208,12 +3233,6 @@ void Compiler::dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& claus void Compiler::fgVerifyHandlerTab() { - if (compIsForInlining()) - { - // We don't inline functions with EH. Don't bother verifying the EH table in the inlinee Compiler. - return; - } - if (compHndBBtabCount == 0) { return; @@ -3230,6 +3249,9 @@ void Compiler::fgVerifyHandlerTab() // block (case 3)? bool multipleLastBlockNormalizationDone = false; // Currently disabled + BitVecTraits traits(impInlineRoot()->compEHID, this); + BitVec ids(BitVecOps::MakeEmpty(&traits)); + assert(compHndBBtabCount <= compHndBBtabAllocCount); unsigned XTnum; @@ -3237,6 +3259,11 @@ void Compiler::fgVerifyHandlerTab() for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) { + // EH IDs should be unique and in range + // + assert(HBtab->ebdID < impInlineRoot()->compEHID); + assert(BitVecOps::TryAddElemD(&traits, ids, HBtab->ebdID)); + assert(HBtab->ebdTryBeg != nullptr); assert(HBtab->ebdTryLast != nullptr); assert(HBtab->ebdHndBeg != nullptr); @@ -3763,7 +3790,7 @@ void Compiler::fgDispHandlerTab() return; } - printf("\nindex "); + printf("\n id, index "); #if defined(FEATURE_EH_WINDOWS_X86) if (!UsesFunclets()) { diff --git a/src/coreclr/jit/jiteh.h b/src/coreclr/jit/jiteh.h index eb4c1bfbd5baf6..34cae18ec950cb 100644 --- a/src/coreclr/jit/jiteh.h +++ b/src/coreclr/jit/jiteh.h @@ -89,6 +89,8 @@ struct EHblkDsc unsigned ebdTyp; // Exception type (a class token), otherwise }; + unsigned short ebdID; // Unique ID for this eh descriptor (stable across add/delete/inlining) + EHHandlerType ebdHandlerType; #if defined(FEATURE_EH_WINDOWS_X86) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 6a97cfa276a49a..1e6d365b9d133f 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -4771,7 +4771,7 @@ bool Compiler::lvaIsPreSpilled(unsigned lclNum, regMaskTP preSpillMask) // void Compiler::lvaUpdateArgWithInitialReg(LclVarDsc* varDsc) { - noway_assert(varDsc->lvIsParam); + assert(varDsc->lvIsParam || varDsc->lvIsParamRegTarget); if (varDsc->lvIsRegCandidate()) { @@ -4790,20 +4790,11 @@ void Compiler::lvaUpdateArgsWithInitialReg() return; } - for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) + for (unsigned lclNum = 0; lclNum < lvaCount; lclNum++) { LclVarDsc* varDsc = lvaGetDesc(lclNum); - if (varDsc->lvPromoted) - { - for (unsigned fieldVarNum = varDsc->lvFieldLclStart; - fieldVarNum < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++fieldVarNum) - { - LclVarDsc* fieldVarDsc = lvaGetDesc(fieldVarNum); - lvaUpdateArgWithInitialReg(fieldVarDsc); - } - } - else + if (varDsc->lvIsParam || varDsc->lvIsParamRegTarget) { lvaUpdateArgWithInitialReg(varDsc); } diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index c999e1b1721c23..8e7e894dde2ce1 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -45,6 +45,22 @@ void ArrIndex::PrintBoundsCheckNodes(unsigned dim /* = -1 */) } } +//-------------------------------------------------------------------------------------------------- +// Print: debug print an SpanIndex struct in form: `V01[V02]`. +// +void SpanIndex::Print() +{ + printf("V%02d[V%02d]", lenLcl, indLcl); +} + +//-------------------------------------------------------------------------------------------------- +// PrintBoundsCheckNode: - debug print an SpanIndex struct bounds check node tree id +// +void SpanIndex::PrintBoundsCheckNode() +{ + Compiler::printTreeID(bndsChk); +} + #endif // DEBUG //-------------------------------------------------------------------------------------------------- @@ -80,6 +96,10 @@ GenTree* LC_Array::ToGenTree(Compiler* comp, BasicBlock* bb) arrAddr->gtFlags |= GTF_INX_ADDR_NONNULL; arr = comp->gtNewIndexIndir(arrAddr->AsIndexAddr()); + + // We don't really need to call morph here if we import arr[i] directly + // without gtNewArrayIndexAddr (but it's a bit of verbose). + arr = comp->fgMorphTree(arr); } // If asked for arrlen invoke arr length operator. if (oper == ArrLen) @@ -111,6 +131,20 @@ GenTree* LC_Array::ToGenTree(Compiler* comp, BasicBlock* bb) return nullptr; } +//-------------------------------------------------------------------------------------------------- +// ToGenTree: Convert a Span.Length operation into a GenTree node. +// +// Arguments: +// comp - Compiler instance to allocate trees +// +// Return Values: +// Returns the gen tree representation for Span.Length +// +GenTree* LC_Span::ToGenTree(Compiler* comp) +{ + return comp->gtNewLclvNode(spanIndex->lenLcl, comp->lvaTable[spanIndex->lenLcl].lvType); +} + //-------------------------------------------------------------------------------------------------- // ToGenTree - Convert an "identifier" into a GenTree node. // @@ -134,6 +168,8 @@ GenTree* LC_Ident::ToGenTree(Compiler* comp, BasicBlock* bb) return comp->gtNewLclvNode(lclNum, comp->lvaTable[lclNum].lvType); case ArrAccess: return arrAccess.ToGenTree(comp, bb); + case SpanAccess: + return spanAccess.ToGenTree(comp); case Null: return comp->gtNewIconNode(0, TYP_REF); case ClassHandle: @@ -861,54 +897,12 @@ BasicBlock* LoopCloneContext::CondToStmtInBlock(Compiler* // const weight_t fastLikelihood = fastPathWeightScaleFactor; - // Choose how to generate the conditions - const bool generateOneConditionPerBlock = true; - - if (generateOneConditionPerBlock) - { - // N = conds.Size() branches must all be true to execute the fast loop. - // Use the N'th root.... - // - const weight_t fastLikelihoodPerBlock = exp(log(fastLikelihood) / (weight_t)conds.Size()); - - for (unsigned i = 0; i < conds.Size(); ++i) - { - BasicBlock* newBlk = comp->fgNewBBafter(BBJ_COND, insertAfter, /*extendRegion*/ true); - newBlk->inheritWeight(insertAfter); - - JITDUMP("Adding " FMT_BB " -> " FMT_BB "\n", newBlk->bbNum, slowPreheader->bbNum); - FlowEdge* const trueEdge = comp->fgAddRefPred(slowPreheader, newBlk); - newBlk->SetTrueEdge(trueEdge); - trueEdge->setLikelihood(1 - fastLikelihoodPerBlock); - - if (insertAfter->KindIs(BBJ_COND)) - { - JITDUMP("Adding " FMT_BB " -> " FMT_BB "\n", insertAfter->bbNum, newBlk->bbNum); - FlowEdge* const falseEdge = comp->fgAddRefPred(newBlk, insertAfter); - insertAfter->SetFalseEdge(falseEdge); - falseEdge->setLikelihood(fastLikelihoodPerBlock); - } - - JITDUMP("Adding conditions %u to " FMT_BB "\n", i, newBlk->bbNum); - - GenTree* cond = conds[i].ToGenTree(comp, newBlk, /* invert */ true); - GenTree* jmpTrueTree = comp->gtNewOperNode(GT_JTRUE, TYP_VOID, cond); - Statement* stmt = comp->fgNewStmtFromTree(jmpTrueTree); - - comp->fgInsertStmtAtEnd(newBlk, stmt); - - // Remorph. - JITDUMP("Loop cloning condition tree before morphing:\n"); - DBEXEC(comp->verbose, comp->gtDispTree(jmpTrueTree)); - JITDUMP("\n"); - comp->fgMorphBlockStmt(newBlk, stmt DEBUGARG("Loop cloning condition")); - - insertAfter = newBlk; - } + // N = conds.Size() branches must all be true to execute the fast loop. + // Use the N'th root.... + // + const weight_t fastLikelihoodPerBlock = exp(log(fastLikelihood) / (weight_t)conds.Size()); - return insertAfter; - } - else + for (unsigned i = 0; i < conds.Size(); ++i) { BasicBlock* newBlk = comp->fgNewBBafter(BBJ_COND, insertAfter, /*extendRegion*/ true); newBlk->inheritWeight(insertAfter); @@ -916,43 +910,28 @@ BasicBlock* LoopCloneContext::CondToStmtInBlock(Compiler* JITDUMP("Adding " FMT_BB " -> " FMT_BB "\n", newBlk->bbNum, slowPreheader->bbNum); FlowEdge* const trueEdge = comp->fgAddRefPred(slowPreheader, newBlk); newBlk->SetTrueEdge(trueEdge); - trueEdge->setLikelihood(1.0 - fastLikelihood); + trueEdge->setLikelihood(1 - fastLikelihoodPerBlock); if (insertAfter->KindIs(BBJ_COND)) { JITDUMP("Adding " FMT_BB " -> " FMT_BB "\n", insertAfter->bbNum, newBlk->bbNum); FlowEdge* const falseEdge = comp->fgAddRefPred(newBlk, insertAfter); insertAfter->SetFalseEdge(falseEdge); - falseEdge->setLikelihood(fastLikelihood); + falseEdge->setLikelihood(fastLikelihoodPerBlock); } - JITDUMP("Adding conditions to " FMT_BB "\n", newBlk->bbNum); + JITDUMP("Adding conditions %u to " FMT_BB "\n", i, newBlk->bbNum); - // Get the first condition. - GenTree* cond = conds[0].ToGenTree(comp, newBlk, /* invert */ false); - for (unsigned i = 1; i < conds.Size(); ++i) - { - // Append all conditions using AND operator. - cond = comp->gtNewOperNode(GT_AND, TYP_INT, cond, conds[i].ToGenTree(comp, newBlk, /* invert */ false)); - } - - // Add "cond == 0" node - cond = comp->gtNewOperNode(GT_EQ, TYP_INT, cond, comp->gtNewIconNode(0)); - - // Add jmpTrue "cond == 0" + GenTree* cond = conds[i].ToGenTree(comp, newBlk, /* invert */ true); + cond->gtFlags |= (GTF_RELOP_JMP_USED | GTF_DONT_CSE); GenTree* jmpTrueTree = comp->gtNewOperNode(GT_JTRUE, TYP_VOID, cond); Statement* stmt = comp->fgNewStmtFromTree(jmpTrueTree); comp->fgInsertStmtAtEnd(newBlk, stmt); - - // Remorph. - JITDUMP("Loop cloning condition tree before morphing:\n"); - DBEXEC(comp->verbose, comp->gtDispTree(jmpTrueTree)); - JITDUMP("\n"); - comp->fgMorphBlockStmt(newBlk, stmt DEBUGARG("Loop cloning condition")); - - return newBlk; + insertAfter = newBlk; } + + return insertAfter; } //-------------------------------------------------------------------------------------------------- @@ -1133,6 +1112,10 @@ bool Compiler::optDeriveLoopCloningConditions(FlowGraphNaturalLoop* loop, LoopCl JitExpandArrayStack* optInfos = context->GetLoopOptInfo(loop->GetIndex()); assert(optInfos->Size() > 0); + // If we have spans, that means we have to be careful about the stride (see below). + // + bool hasSpans = false; + // We only need to check for iteration behavior if we have array checks. // bool checkIterationBehavior = false; @@ -1147,6 +1130,11 @@ bool Compiler::optDeriveLoopCloningConditions(FlowGraphNaturalLoop* loop, LoopCl checkIterationBehavior = true; break; + case LcOptInfo::LcSpan: + checkIterationBehavior = true; + hasSpans = true; + break; + case LcOptInfo::LcTypeTest: { LcTypeTestOptInfo* ttInfo = optInfo->AsLcTypeTestOptInfo(); @@ -1207,16 +1195,22 @@ bool Compiler::optDeriveLoopCloningConditions(FlowGraphNaturalLoop* loop, LoopCl } const bool isIncreasingLoop = iterInfo->IsIncreasingLoop(); - assert(isIncreasingLoop || iterInfo->IsDecreasingLoop()); + if (!isIncreasingLoop && !iterInfo->IsDecreasingLoop()) + { + // Normally, we reject weird-looking loops in optIsLoopClonable, but it's not the case + // when we have both GDVs and array checks inside such loops. + return false; + } // We already know that this is either increasing or decreasing loop and the // stride is (> 0) or (< 0). Here, just take the abs() value and check if it // is beyond the limit. int stride = abs(iterInfo->IterConst()); - if (stride >= 58) + static_assert_no_msg(INT32_MAX >= CORINFO_Array_MaxLength); + if (stride >= (INT32_MAX - (CORINFO_Array_MaxLength - 1) + 1)) { - // Array.MaxLength can have maximum of 0X7FFFFFC7 elements, so make sure + // Array.MaxLength can have maximum of 0x7fffffc7 elements, so make sure // the stride increment doesn't overflow or underflow the index. Hence, // the maximum stride limit is set to // (int.MaxValue - (Array.MaxLength - 1) + 1), which is @@ -1224,6 +1218,14 @@ bool Compiler::optDeriveLoopCloningConditions(FlowGraphNaturalLoop* loop, LoopCl return false; } + // We don't know exactly whether we might be dealing with a Span or not, + // but if we suspect we are, we need to be careful about the stride: + // As Span<>.Length can be INT32_MAX unlike arrays. + if (hasSpans && (stride > 1)) + { + return false; + } + LC_Ident ident; // Init conditions if (iterInfo->HasConstInit) @@ -1366,6 +1368,15 @@ bool Compiler::optDeriveLoopCloningConditions(FlowGraphNaturalLoop* loop, LoopCl context->EnsureArrayDerefs(loop->GetIndex())->Push(array); } break; + case LcOptInfo::LcSpan: + { + LcSpanOptInfo* spanInfo = optInfo->AsLcSpanOptInfo(); + LC_Span spanLen(&spanInfo->spanIndex); + LC_Ident spanLenIdent = LC_Ident::CreateSpanAccess(spanLen); + LC_Condition cond(opLimitCondition, LC_Expr(ident), LC_Expr(spanLenIdent)); + context->EnsureConditions(loop->GetIndex())->Push(cond); + } + break; case LcOptInfo::LcMdArray: { LcMdArrayOptInfo* mdArrInfo = optInfo->AsLcMdArrayOptInfo(); @@ -1508,10 +1519,6 @@ bool Compiler::optComputeDerefConditions(FlowGraphNaturalLoop* loop, LoopCloneCo JitExpandArrayStack* const arrayDeref = context->EnsureArrayDerefs(loop->GetIndex()); JitExpandArrayStack* const objDeref = context->EnsureObjDerefs(loop->GetIndex()); - // We currently expect to have at least one of these. - // - assert((arrayDeref->Size() != 0) || (objDeref->Size() != 0)); - // Generate the array dereference checks. // // For each array in the dereference list, construct a tree, @@ -1732,6 +1739,39 @@ void Compiler::optPerformStaticOptimizations(FlowGraphNaturalLoop* loop, DBEXEC(dynamicPath, optDebugLogLoopCloning(arrIndexInfo->arrIndex.useBlock, arrIndexInfo->stmt)); } break; + case LcOptInfo::LcSpan: + { + LcSpanOptInfo* spanIndexInfo = optInfo->AsLcSpanOptInfo(); + compCurBB = spanIndexInfo->spanIndex.useBlock; + GenTree* bndsChkNode = spanIndexInfo->spanIndex.bndsChk; + +#ifdef DEBUG + if (verbose) + { + printf("Remove bounds check "); + printTreeID(bndsChkNode->gtGetOp1()); + printf(" for " FMT_STMT ", ", spanIndexInfo->stmt->GetID()); + spanIndexInfo->spanIndex.Print(); + printf(", bounds check nodes: "); + spanIndexInfo->spanIndex.PrintBoundsCheckNode(); + printf("\n"); + } +#endif // DEBUG + + if (bndsChkNode->gtGetOp1()->OperIs(GT_BOUNDS_CHECK)) + { + optRemoveCommaBasedRangeCheck(bndsChkNode, spanIndexInfo->stmt); + } + else + { + JITDUMP(" Bounds check already removed\n"); + + // If the bounds check node isn't there, it better have been converted to a GT_NOP. + assert(bndsChkNode->gtGetOp1()->OperIs(GT_NOP)); + } + DBEXEC(dynamicPath, optDebugLogLoopCloning(spanIndexInfo->spanIndex.useBlock, spanIndexInfo->stmt)); + } + break; case LcOptInfo::LcMdArray: // TODO-CQ: CLONE: Implement. break; @@ -1966,7 +2006,6 @@ BasicBlock* Compiler::optInsertLoopChoiceConditions(LoopCloneContext* contex BasicBlock* insertAfter) { JITDUMP("Inserting loop " FMT_LP " loop choice conditions\n", loop->GetIndex()); - assert(context->HasBlockConditions(loop->GetIndex())); assert(slowPreheader != nullptr); if (context->HasBlockConditions(loop->GetIndex())) @@ -2140,9 +2179,6 @@ void Compiler::optCloneLoop(FlowGraphNaturalLoop* loop, LoopCloneContext* contex // ... // slowPreheader --> slowHeader // - // We should always have block conditions. - - assert(context->HasBlockConditions(loop->GetIndex())); // If any condition is false, go to slowPreheader (which branches or falls through to header of the slow loop). BasicBlock* slowHeader = nullptr; @@ -2325,6 +2361,44 @@ bool Compiler::optExtractArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsN return true; } +//--------------------------------------------------------------------------------------------------------------- +// optExtractSpanIndex: Try to extract the Span element access from "tree". +// +// Arguments: +// tree - the tree to be checked if it is the Span [] operation. +// result - the extracted information is updated in result. +// +// Return Value: +// Returns true if Span index can be extracted, else, return false. +// +// Notes: +// The way loop cloning works for Span is that we don't actually know (or care) +// if it's a Span or an array, we just extract index and length locals out +/// of the GT_BOUNDS_CHECK node. The fact that the length is a local var +/// allows us to not worry about array/span dereferencing. +// +bool Compiler::optExtractSpanIndex(GenTree* tree, SpanIndex* result) +{ + // Bounds checks are almost always wrapped in a comma node + // and are the first operand. + if (!tree->OperIs(GT_COMMA) || !tree->gtGetOp1()->OperIs(GT_BOUNDS_CHECK)) + { + return false; + } + + GenTreeBoundsChk* arrBndsChk = tree->gtGetOp1()->AsBoundsChk(); + if (!arrBndsChk->GetIndex()->OperIs(GT_LCL_VAR) || !arrBndsChk->GetArrayLength()->OperIs(GT_LCL_VAR)) + { + return false; + } + + result->lenLcl = arrBndsChk->GetArrayLength()->AsLclVarCommon()->GetLclNum(); + result->indLcl = arrBndsChk->GetIndex()->AsLclVarCommon()->GetLclNum(); + result->bndsChk = tree; + result->useBlock = compCurBB; + return true; +} + //--------------------------------------------------------------------------------------------------------------- // optReconstructArrIndexHelp: Helper function for optReconstructArrIndex. See that function for more details. // @@ -2588,6 +2662,30 @@ Compiler::fgWalkResult Compiler::optCanOptimizeByLoopCloning(GenTree* tree, Loop return WALK_SKIP_SUBTREES; } + SpanIndex spanIndex = SpanIndex(); + if (info->cloneForArrayBounds && optExtractSpanIndex(tree, &spanIndex)) + { + // Check that the span's length local variable is invariant within the loop body. + if (!optIsStackLocalInvariant(info->loop, spanIndex.lenLcl)) + { + JITDUMP("Span.Length V%02d is not loop invariant\n", spanIndex.lenLcl); + return WALK_SKIP_SUBTREES; + } + + unsigned iterVar = info->context->GetLoopIterInfo(info->loop->GetIndex())->IterVar; + if (spanIndex.indLcl == iterVar) + { + // Update the loop context. + info->context->EnsureLoopOptInfo(info->loop->GetIndex()) + ->Push(new (this, CMK_LoopOpt) LcSpanOptInfo(spanIndex, info->stmt)); + } + else + { + JITDUMP("Induction V%02d is not used as index\n", iterVar); + } + return WALK_SKIP_SUBTREES; + } + if (info->cloneForGDVTests && tree->OperIs(GT_JTRUE)) { JITDUMP("...GDV considering [%06u]\n", dspTreeID(tree)); diff --git a/src/coreclr/jit/loopcloning.h b/src/coreclr/jit/loopcloning.h index cfda1be87a8b9d..ecdda09775f87a 100644 --- a/src/coreclr/jit/loopcloning.h +++ b/src/coreclr/jit/loopcloning.h @@ -211,6 +211,28 @@ struct ArrIndex #endif }; +// SpanIndex represents a span element access and associated bounds check. +struct SpanIndex +{ + unsigned lenLcl; // The Span length local num + unsigned indLcl; // The index local num + GenTree* bndsChk; // The bounds check node + BasicBlock* useBlock; // Block where the [] occurs + + SpanIndex() + : lenLcl(BAD_VAR_NUM) + , indLcl(BAD_VAR_NUM) + , bndsChk(nullptr) + , useBlock(nullptr) + { + } + +#ifdef DEBUG + void Print(); + void PrintBoundsCheckNode(); +#endif +}; + // Forward declarations #define LC_OPT(en) struct en##OptInfo; #include "loopcloningopts.h" @@ -317,6 +339,21 @@ struct LcJaggedArrayOptInfo : public LcOptInfo } }; +// Optimization info for a Span +// +struct LcSpanOptInfo : public LcOptInfo +{ + SpanIndex spanIndex; // SpanIndex representation of the Span. + Statement* stmt; // "stmt" where the optimization opportunity occurs. + + LcSpanOptInfo(SpanIndex& spanIndex, Statement* stmt) + : LcOptInfo(LcSpan) + , spanIndex(spanIndex) + , stmt(stmt) + { + } +}; + // Optimization info for a type test // struct LcTypeTestOptInfo : public LcOptInfo @@ -481,6 +518,38 @@ struct LC_Array GenTree* ToGenTree(Compiler* comp, BasicBlock* bb); }; +// Symbolic representation of Span.Length +struct LC_Span +{ + SpanIndex* spanIndex; + +#ifdef DEBUG + void Print() + { + spanIndex->Print(); + } +#endif + + LC_Span() + : spanIndex(nullptr) + { + } + + LC_Span(SpanIndex* arrIndex) + : spanIndex(arrIndex) + { + } + + // Equality operator + bool operator==(const LC_Span& that) const + { + return (spanIndex->lenLcl == that.spanIndex->lenLcl) && (spanIndex->indLcl == that.spanIndex->indLcl); + } + + // Get a tree representation for this symbolic Span.Length + GenTree* ToGenTree(Compiler* comp); +}; + //------------------------------------------------------------------------ // LC_Ident: symbolic representation of "a value" // @@ -492,6 +561,7 @@ struct LC_Ident Const, Var, ArrAccess, + SpanAccess, Null, ClassHandle, IndirOfLocal, @@ -509,6 +579,7 @@ struct LC_Ident unsigned indirOffs; }; LC_Array arrAccess; + LC_Span spanAccess; CORINFO_CLASS_HANDLE clsHnd; struct { @@ -553,6 +624,8 @@ struct LC_Ident return (lclNum == that.lclNum) && (indirOffs == that.indirOffs); case ArrAccess: return (arrAccess == that.arrAccess); + case SpanAccess: + return (spanAccess == that.spanAccess); case Null: return true; case MethodAddr: @@ -598,6 +671,9 @@ struct LC_Ident case ArrAccess: arrAccess.Print(); break; + case SpanAccess: + spanAccess.Print(); + break; case Null: printf("null"); break; @@ -646,6 +722,13 @@ struct LC_Ident return id; } + static LC_Ident CreateSpanAccess(const LC_Span& spanLen) + { + LC_Ident id(SpanAccess); + id.spanAccess = spanLen; + return id; + } + static LC_Ident CreateNull() { return LC_Ident(Null); diff --git a/src/coreclr/jit/loopcloningopts.h b/src/coreclr/jit/loopcloningopts.h index 2fb13937e2f86a..e27a3d802e11c4 100644 --- a/src/coreclr/jit/loopcloningopts.h +++ b/src/coreclr/jit/loopcloningopts.h @@ -13,5 +13,6 @@ LC_OPT(LcMdArray) LC_OPT(LcJaggedArray) LC_OPT(LcTypeTest) LC_OPT(LcMethodAddrTest) +LC_OPT(LcSpan) #undef LC_OPT diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 760bf995e50d7b..8b1dc5d10b1e06 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -7810,10 +7810,10 @@ bool Lowering::TryFoldBinop(GenTreeOp* node) return true; } - if (node->OperIs(GT_LSH, GT_RSH, GT_RSZ, GT_ROL, GT_ROR, GT_OR, GT_XOR) && - (op1->IsIntegralConst(0) || op2->IsIntegralConst(0))) + if ((node->OperIs(GT_LSH, GT_RSH, GT_RSZ, GT_ROL, GT_ROR) && op2->IsIntegralConst(0)) || + (node->OperIs(GT_OR, GT_XOR) && (op1->IsIntegralConst(0) || op2->IsIntegralConst(0)))) { - GenTree* zeroOp = op1->IsIntegralConst(0) ? op1 : op2; + GenTree* zeroOp = op2->IsIntegralConst(0) ? op2 : op1; GenTree* otherOp = zeroOp == op1 ? op2 : op1; LIR::Use use; @@ -7968,7 +7968,7 @@ PhaseStatus Lowering::DoPhase() } #if !defined(TARGET_64BIT) - DecomposeLongs decomp(comp); // Initialize the long decomposition class. + DecomposeLongs decomp(comp, this); // Initialize the long decomposition class. if (comp->compLongUsed) { decomp.PrepareForDecomposition(); diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 611ceb09339233..d44880bd947554 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -464,61 +464,6 @@ class Lowering final : public Phase unsigned simdSize); #endif // FEATURE_HW_INTRINSICS - //---------------------------------------------------------------------------------------------- - // TryRemoveCastIfPresent: Removes op it is a cast operation and the size of its input is at - // least the size of expectedType - // - // Arguments: - // expectedType - The expected type of the cast operation input if it is to be removed - // op - The tree to remove if it is a cast op whose input is at least the size of expectedType - // - // Returns: - // op if it was not a cast node or if its input is not at least the size of expected type; - // Otherwise, it returns the underlying operation that was being casted - GenTree* TryRemoveCastIfPresent(var_types expectedType, GenTree* op) - { - if (!op->OperIs(GT_CAST) || !comp->opts.OptimizationEnabled()) - { - return op; - } - - GenTreeCast* cast = op->AsCast(); - GenTree* castOp = cast->CastOp(); - - // FP <-> INT casts should be kept - if (varTypeIsFloating(castOp) ^ varTypeIsFloating(expectedType)) - { - return op; - } - - // Keep casts which can overflow - if (cast->gtOverflow()) - { - return op; - } - - // Keep casts with operands usable from memory. - if (castOp->isContained() || castOp->IsRegOptional()) - { - return op; - } - - if (genTypeSize(cast->CastToType()) >= genTypeSize(expectedType)) - { -#ifndef TARGET_64BIT - // Don't expose TYP_LONG on 32bit - if (castOp->TypeIs(TYP_LONG)) - { - return op; - } -#endif - BlockRange().Remove(op); - return castOp; - } - - return op; - } - // Utility functions public: static bool IndirsAreEquivalent(GenTree* pTreeA, GenTree* pTreeB); @@ -568,6 +513,13 @@ class Lowering final : public Phase bool IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTree* childNode, bool* supportsRegOptional); #endif // FEATURE_HW_INTRINSICS + // Checks for memory conflicts in the instructions between childNode and parentNode, and returns true if childNode + // can be contained. + bool IsSafeToContainMem(GenTree* parentNode, GenTree* childNode) const; + + // Similar to above, but allows bypassing a "transparent" parent. + bool IsSafeToContainMem(GenTree* grandparentNode, GenTree* parentNode, GenTree* childNode) const; + static void TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, BasicBlock* block); private: @@ -599,13 +551,6 @@ class Lowering final : public Phase GenTree* endExclusive, GenTree* ignoreNode) const; - // Checks for memory conflicts in the instructions between childNode and parentNode, and returns true if childNode - // can be contained. - bool IsSafeToContainMem(GenTree* parentNode, GenTree* childNode) const; - - // Similar to above, but allows bypassing a "transparent" parent. - bool IsSafeToContainMem(GenTree* grandparentNode, GenTree* parentNode, GenTree* childNode) const; - // Check if marking an operand of a node as reg-optional is safe. bool IsSafeToMarkRegOptional(GenTree* parentNode, GenTree* node) const; diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 963d0c4d1fbb7a..8c2528de2c2e65 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -2015,11 +2015,9 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) // bool Lowering::IsValidConstForMovImm(GenTreeHWIntrinsic* node) { - assert((node->GetHWIntrinsicId() == NI_Vector64_Create) || (node->GetHWIntrinsicId() == NI_Vector128_Create) || - (node->GetHWIntrinsicId() == NI_Vector64_CreateScalar) || - (node->GetHWIntrinsicId() == NI_Vector128_CreateScalar) || - (node->GetHWIntrinsicId() == NI_Vector64_CreateScalarUnsafe) || - (node->GetHWIntrinsicId() == NI_Vector128_CreateScalarUnsafe) || + assert(HWIntrinsicInfo::IsVectorCreate(node->GetHWIntrinsicId()) || + HWIntrinsicInfo::IsVectorCreateScalar(node->GetHWIntrinsicId()) || + HWIntrinsicInfo::IsVectorCreateScalarUnsafe(node->GetHWIntrinsicId()) || (node->GetHWIntrinsicId() == NI_AdvSimd_DuplicateToVector64) || (node->GetHWIntrinsicId() == NI_AdvSimd_DuplicateToVector128) || (node->GetHWIntrinsicId() == NI_AdvSimd_Arm64_DuplicateToVector64) || @@ -2278,7 +2276,7 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) assert(simdSize != 0); bool isConstant = GenTreeVecCon::IsHWIntrinsicCreateConstant(node, simdVal); - bool isCreateScalar = (intrinsicId == NI_Vector64_CreateScalar) || (intrinsicId == NI_Vector128_CreateScalar); + bool isCreateScalar = HWIntrinsicInfo::IsVectorCreateScalar(intrinsicId); size_t argCnt = node->GetOperandCount(); // Check if we have a cast that we can remove. Note that "IsValidConstForMovImm" diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 1a7b0e708eb6c3..743218ecede33b 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -2044,26 +2044,14 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_Insert: case NI_SSE41_Insert: - case NI_SSE41_X64_Insert: { assert(node->GetOperandCount() == 3); - var_types simdBaseType = node->GetSimdBaseType(); - - // Insert takes either a 32-bit register or a memory operand. - // In either case, only SimdBaseType bits are read and so - // widening or narrowing the operand may be unnecessary and it - // can just be used directly. - - node->Op(2) = TryRemoveCastIfPresent(simdBaseType, node->Op(2)); - - if (simdBaseType != TYP_FLOAT) + if (node->GetSimdBaseType() != TYP_FLOAT) { break; } - assert(intrinsicId == NI_SSE41_Insert); // We have Sse41.Insert in which case we can specially handle // a couple of interesting scenarios involving chains of Inserts @@ -2272,19 +2260,6 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE42_Crc32: - { - assert(node->GetOperandCount() == 2); - - // Crc32 takes either a bit register or a memory operand. - // In either case, only gtType bits are read and so widening - // or narrowing the operand may be unnecessary and it can - // just be used directly. - - node->Op(2) = TryRemoveCastIfPresent(node->TypeGet(), node->Op(2)); - break; - } - case NI_SSE2_CompareGreaterThan: { if (node->GetSimdBaseType() != TYP_DOUBLE) @@ -3082,6 +3057,7 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm comp->gtNewSimdCreateBroadcastNode(simdType, broadcastOp, op1Intrinsic->GetSimdBaseJitType(), simdSize); + assert(vecCns->IsCnsVec()); BlockRange().InsertAfter(broadcastOp, vecCns); nestedOp2 = vecCns; @@ -4032,10 +4008,9 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) GenTree* tmp2 = nullptr; GenTree* tmp3 = nullptr; - bool isConstant = GenTreeVecCon::IsHWIntrinsicCreateConstant(node, simdVal); - bool isCreateScalar = (intrinsicId == NI_Vector128_CreateScalar) || (intrinsicId == NI_Vector256_CreateScalar) || - (intrinsicId == NI_Vector512_CreateScalar); - size_t argCnt = node->GetOperandCount(); + bool isConstant = GenTreeVecCon::IsHWIntrinsicCreateConstant(node, simdVal); + bool isCreateScalar = HWIntrinsicInfo::IsVectorCreateScalar(intrinsicId); + size_t argCnt = node->GetOperandCount(); if (isConstant) { @@ -4046,8 +4021,8 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) #if !defined(TARGET_64BIT) if (arg->OperIsLong()) { - BlockRange().Remove(arg->AsOp()->gtGetOp1()); - BlockRange().Remove(arg->AsOp()->gtGetOp2()); + BlockRange().Remove(arg->gtGetOp1()); + BlockRange().Remove(arg->gtGetOp2()); } #endif // !TARGET_64BIT BlockRange().Remove(arg); @@ -4075,165 +4050,61 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) { if (isCreateScalar) { - node->gtType = TYP_SIMD16; - node->SetSimdSize(16); - switch (simdBaseType) { case TYP_BYTE: case TYP_UBYTE: - { - // Types need to be explicitly zero-extended to ensure upper-bits are zero - // - // We need to explicitly use TYP_UBYTE since unsigned is ignored for small types - // Explicitly handle both BYTE and UBYTE to account for reinterpret casts and the like - // - // The from type is INT since that is the input type tracked by IR, where-as the target - // type needs to be UBYTE so it implicitly zero-extends back to TYP_INT - - tmp1 = comp->gtNewCastNode(TYP_INT, op1, /* unsigned */ true, TYP_UBYTE); - BlockRange().InsertAfter(op1, tmp1); - LowerNode(tmp1); - - node->ChangeHWIntrinsicId(NI_SSE2_ConvertScalarToVector128Int32, tmp1); - node->SetSimdBaseJitType(CORINFO_TYPE_INT); - break; - } - case TYP_SHORT: case TYP_USHORT: { - // Types need to be explicitly zero-extended to ensure upper-bits are zero + // The smallest scalar SIMD load that zeroes upper elements is 32 bits, so for CreateScalar, + // we must ensure that the upper bits of that 32-bit value are zero if the base type is small. // - // We need to explicitly use TYP_USHORT since unsigned is ignored for small types - // Explicitly handle both SHORT and USHORT to account for reinterpret casts and the like + // The most likely case is that op1 is a cast from int/long to the base type: + // * CAST int <- short <- int/long + // If the base type is signed, that cast will be sign-extending, but we need zero extension, + // so we can simply retype the cast to the unsigned type of the same size. // - // The from type is INT since that is the input type tracked by IR, where-as the target - // type needs to be USHORT so it implicitly zero-extends back to TYP_INT - - tmp1 = comp->gtNewCastNode(TYP_INT, op1, /* unsigned */ true, TYP_USHORT); - BlockRange().InsertAfter(op1, tmp1); - LowerNode(tmp1); + // It's also possible we have a memory load of the base type: + // * IND short + // We can likewise change the type of the indir to force zero extension on load. + // + // If we can't safely retype one of the above patterns and don't already have a cast to the + // correct unsigned type, we will insert our own cast. - node->ChangeHWIntrinsicId(NI_SSE2_ConvertScalarToVector128Int32, tmp1); node->SetSimdBaseJitType(CORINFO_TYPE_INT); - break; - } - - case TYP_INT: - { - node->ChangeHWIntrinsicId(NI_SSE2_ConvertScalarToVector128Int32); - break; - } - - case TYP_UINT: - { - node->ChangeHWIntrinsicId(NI_SSE2_ConvertScalarToVector128UInt32); - break; - } -#if defined(TARGET_AMD64) - case TYP_LONG: - { - node->ChangeHWIntrinsicId(NI_SSE2_X64_ConvertScalarToVector128Int64); - break; - } - - case TYP_ULONG: - { - node->ChangeHWIntrinsicId(NI_SSE2_X64_ConvertScalarToVector128UInt64); - break; - } -#endif // TARGET_AMD64 + var_types unsignedType = varTypeToUnsigned(simdBaseType); - case TYP_FLOAT: - { - tmp1 = comp->gtNewZeroConNode(simdType); - BlockRange().InsertBefore(op1, tmp1); - LowerNode(tmp1); - - if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + if (op1->OperIs(GT_CAST) && !op1->gtOverflow()) { - // Sse41.Insert has: - // * Bits 0-3: zmask - // * Bits 4-5: count_d - // * Bits 6-7: count_s (register form only) - // - // We want zmask 0b1110 (0xE) to zero elements 1/2/3 - // We want count_d 0b00 (0x0) to insert the value to element 0 - // We want count_s 0b00 (0x0) as we're just taking element 0 of the source - - idx = comp->gtNewIconNode(0x0E); - BlockRange().InsertAfter(op1, idx); - LowerNode(idx); - - node->ResetHWIntrinsicId(NI_SSE41_Insert, comp, tmp1, op1, idx); + assert(op1->TypeIs(TYP_INT) && (genTypeSize(op1->CastToType()) == genTypeSize(simdBaseType))); + op1->AsCast()->gtCastType = unsignedType; } - else + else if (op1->OperIs(GT_IND, GT_LCL_FLD)) { - node->ResetHWIntrinsicId(NI_SSE_MoveScalar, comp, tmp1, op1); + assert(genTypeSize(op1) == genTypeSize(simdBaseType)); + op1->gtType = unsignedType; + } + else if (!op1->OperIs(GT_CAST) || (op1->AsCast()->CastToType() != unsignedType)) + { + tmp1 = comp->gtNewCastNode(TYP_INT, op1, /* fromUnsigned */ false, unsignedType); + node->Op(1) = tmp1; + BlockRange().InsertAfter(op1, tmp1); + LowerNode(tmp1); } - break; - } - - case TYP_DOUBLE: - { - tmp1 = comp->gtNewZeroConNode(simdType); - BlockRange().InsertBefore(op1, tmp1); - LowerNode(tmp1); - node->ResetHWIntrinsicId(NI_SSE2_MoveScalar, comp, tmp1, op1); break; } default: { - unreached(); - } - } - - if (simdSize > 16) - { - assert((simdSize == 32) || (simdSize == 64)); - - // We're creating a Vector256/512 scalar so we need to treat the original op as Vector128, - // we need to unsafely extend up to Vector256/512 (which is actually safe since the 128-bit - // op will zero extend up to 256/512-bits), and then we need to replace the original use - // with the new TYP_SIMD32/64 node. - - node->ChangeType(TYP_SIMD16); - node->SetSimdSize(16); - LowerNode(node); - - LIR::Use use; - bool foundUse = BlockRange().TryGetUse(node, &use); - - tmp2 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD32, node, NI_Vector128_ToVector256Unsafe, simdBaseJitType, - 16); - BlockRange().InsertAfter(node, tmp2); - - if (simdSize == 64) - { - tmp3 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD64, tmp2, NI_Vector256_ToVector512Unsafe, - simdBaseJitType, 32); - BlockRange().InsertAfter(tmp2, tmp3); - tmp2 = tmp3; - } - - if (foundUse) - { - use.ReplaceWith(tmp2); - } - else - { - node->ClearUnusedValue(); - tmp2->SetUnusedValue(); + break; } - - node = tmp2->AsHWIntrinsic(); } - return LowerNode(node); + ContainCheckHWIntrinsic(node); + return node->gtNext; } // We have the following (where simd is simd16, simd32 or simd64): @@ -4509,40 +4380,6 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) break; } -#if defined(TARGET_AMD64) - case TYP_LONG: - case TYP_ULONG: - { - // We will be constructing the following parts: - // ... - // /--* tmp1 simd16 - // * STORE_LCL_VAR simd16 - // tmp1 = LCL_VAR simd16 - // tmp2 = LCL_VAR simd16 - // /--* tmp1 simd16 - // +--* tmp2 simd16 - // node = * HWINTRINSIC simd16 ulong UnpackLow - - // This is roughly the following managed code: - // ... - // var tmp2 = tmp1; - // return Sse2.UnpackLow(tmp1, tmp2); - - assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); - - node->Op(1) = tmp1; - LIR::Use tmp1Use(BlockRange(), &node->Op(1), node); - ReplaceWithLclVar(tmp1Use); - tmp1 = node->Op(1); - - tmp2 = comp->gtClone(tmp1); - BlockRange().InsertAfter(tmp1, tmp2); - - node->ResetHWIntrinsicId(NI_SSE2_UnpackLow, tmp1, tmp2); - break; - } -#endif // TARGET_AMD64 - case TYP_FLOAT: { if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX)) @@ -4599,9 +4436,12 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) break; } + case TYP_LONG: + case TYP_ULONG: case TYP_DOUBLE: { - if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE3)) + if ((IsContainableMemoryOp(op1) || simdBaseType == TYP_DOUBLE) && + comp->compOpportunisticallyDependsOn(InstructionSet_SSE3)) { // We will be constructing the following parts: // ... @@ -4613,6 +4453,7 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) // return Sse3.MoveAndDuplicate(tmp1); node->ChangeHWIntrinsicId(NI_SSE3_MoveAndDuplicate, tmp1); + node->SetSimdBaseJitType(CORINFO_TYPE_DOUBLE); break; } @@ -4626,12 +4467,12 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) // tmp2 = LCL_VAR simd16 // /--* tmp1 simd16 // +--* tmp2 simd16 - // node = * HWINTRINSIC simd16 float MoveLowToHigh + // node = * HWINTRINSIC simd16 T UnpackLow // This is roughly the following managed code: // ... // var tmp2 = tmp1; - // return Sse.MoveLowToHigh(tmp1, tmp2); + // return Sse2.UnpackLow(tmp1, tmp2); node->Op(1) = tmp1; LIR::Use tmp1Use(BlockRange(), &node->Op(1), node); @@ -4641,8 +4482,7 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) tmp2 = comp->gtClone(tmp1); BlockRange().InsertAfter(tmp1, tmp2); - node->ResetHWIntrinsicId(NI_SSE_MoveLowToHigh, tmp1, tmp2); - node->SetSimdBaseJitType(CORINFO_TYPE_FLOAT); + node->ResetHWIntrinsicId(NI_SSE2_UnpackLow, tmp1, tmp2); break; } @@ -4655,19 +4495,16 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) return LowerNode(node); } - GenTree* op2 = node->Op(2); - - // TODO-XArch-AVX512 : Merge the NI_Vector512_Create and NI_Vector256_Create paths below. - // We have the following (where simd is simd16 or simd32): - // /--* op1 T - // +--* ... T - // +--* opN T - // node = * HWINTRINSIC simd T Create - if (intrinsicId == NI_Vector512_Create) + if (intrinsicId == NI_Vector512_Create || intrinsicId == NI_Vector256_Create) { - assert(comp->IsBaselineVector512IsaSupportedDebugOnly()); + assert(argCnt >= (simdSize / genTypeSize(TYP_LONG))); + assert(((simdSize == 64) && comp->IsBaselineVector512IsaSupportedDebugOnly()) || + ((simdSize == 32) && comp->IsBaselineVector256IsaSupportedDebugOnly())); - // We will be constructing the following parts: + // The larger vector implementation is simplified by splitting the + // job in half and delegating to the next smaller vector size. + // + // For example, for Vector512, we construct the following: // /--* op1 T // +--* ... T // lo = * HWINTRINSIC simd32 T Create @@ -4697,86 +4534,35 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) // lo = Vector256.Create(op1, ..., op16); // hi = Vector256.Create(op17, ..., op32); + var_types halfType = comp->getSIMDTypeForSize(simdSize / 2); + NamedIntrinsic halfCreate = (simdSize == 64) ? NI_Vector256_Create : NI_Vector128_Create; + NamedIntrinsic withUpper = (simdSize == 64) ? NI_Vector512_WithUpper : NI_Vector256_WithUpper; + size_t halfArgCnt = argCnt / 2; assert((halfArgCnt * 2) == argCnt); GenTree* loInsertionPoint = LIR::LastNode(node->GetOperandArray(), halfArgCnt); - - GenTree* lo = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD32, node->GetOperandArray(), halfArgCnt, - NI_Vector256_Create, simdBaseJitType, 32); - BlockRange().InsertAfter(loInsertionPoint, lo); - GenTree* hiInsertionPoint = LIR::LastNode(node->GetOperandArray(halfArgCnt), halfArgCnt); - GenTree* hi = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD32, node->GetOperandArray(halfArgCnt), halfArgCnt, - NI_Vector256_Create, simdBaseJitType, 32); - BlockRange().InsertAfter(hiInsertionPoint, hi); - - assert(argCnt >= 7); - node->ResetHWIntrinsicId(NI_Vector512_WithUpper, comp, lo, hi); - - LowerNode(lo); - LowerNode(hi); - - return LowerNode(node); - } - else if (intrinsicId == NI_Vector256_Create) - { - assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); - // We will be constructing the following parts: - // /--* op1 T - // +--* ... T - // lo = * HWINTRINSIC simd16 T Create - // /--* ... T - // +--* opN T - // hi = * HWINTRINSIC simd16 T Create - // /--* lo simd32 - // +--* hi simd16 - // node = * HWINTRINSIC simd32 T WithUpper - - // This is roughly the following managed code: - // ... - // var lo = Vector128.Create(op1, ...); - // var hi = Vector128.Create(..., opN); - // return lo.WithUpper(hi); - - // Each Vector128.Create call gets half the operands. That is: - // lo = Vector128.Create(op1, op2); - // hi = Vector128.Create(op3, op4); - // -or- - // lo = Vector128.Create(op1, ..., op4); - // hi = Vector128.Create(op5, ..., op8); - // -or- - // lo = Vector128.Create(op1, ..., op8); - // hi = Vector128.Create(op9, ..., op16); - // -or- - // lo = Vector128.Create(op1, ..., op16); - // hi = Vector128.Create(op17, ..., op32); + GenTree* lo = comp->gtNewSimdHWIntrinsicNode(halfType, node->GetOperandArray(), halfArgCnt, halfCreate, + simdBaseJitType, simdSize / 2); - size_t halfArgCnt = argCnt / 2; - assert((halfArgCnt * 2) == argCnt); + GenTree* hi = comp->gtNewSimdHWIntrinsicNode(halfType, node->GetOperandArray(halfArgCnt), halfArgCnt, + halfCreate, simdBaseJitType, simdSize / 2); - GenTree* loInsertionPoint = LIR::LastNode(node->GetOperandArray(), halfArgCnt); + node->ResetHWIntrinsicId(withUpper, comp, lo, hi); - GenTree* lo = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, node->GetOperandArray(), halfArgCnt, - NI_Vector128_Create, simdBaseJitType, 16); BlockRange().InsertAfter(loInsertionPoint, lo); - - GenTree* hiInsertionPoint = LIR::LastNode(node->GetOperandArray(halfArgCnt), halfArgCnt); - - GenTree* hi = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, node->GetOperandArray(halfArgCnt), halfArgCnt, - NI_Vector128_Create, simdBaseJitType, 16); BlockRange().InsertAfter(hiInsertionPoint, hi); - assert(argCnt >= 3); - node->ResetHWIntrinsicId(NI_Vector256_WithUpper, comp, lo, hi); - LowerNode(lo); LowerNode(hi); return LowerNode(node); } + assert(intrinsicId == NI_Vector128_Create); + // We will be constructing the following parts: // /--* op1 T // tmp1 = * HWINTRINSIC simd16 T CreateScalarUnsafe @@ -4975,54 +4761,6 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) break; } -#if defined(TARGET_AMD64) - case TYP_LONG: - case TYP_ULONG: - { - if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41_X64)) - { - // We will be constructing the following parts: - // ... - // idx = CNS_INT int 1 - // /--* tmp1 simd16 - // +--* op2 T - // +--* idx int - // node = * HWINTRINSIC simd16 T Insert - - // This is roughly the following managed code: - // ... - // return Sse41.X64.Insert(tmp1, op2, 0x01); - - idx = comp->gtNewIconNode(0x01, TYP_INT); - BlockRange().InsertBefore(node, idx); - - node->ResetHWIntrinsicId(NI_SSE41_X64_Insert, comp, tmp1, op2, idx); - break; - } - - // We will be constructing the following parts: - // ... - // /--* op2 T - // tmp2 = * HWINTRINSIC simd16 T CreateScalarUnsafe - // /--* tmp1 simd16 - // +--* tmp2 simd16 - // node = * HWINTRINSIC simd16 T UnpackLow - - // This is roughly the following managed code: - // ... - // var tmp2 = Vector128.CreateScalarUnsafe(op2); - // return Sse2.UnpackLow(tmp1, tmp2); - - assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); - - tmp2 = InsertNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op2, simdBaseJitType, 16); - LowerNode(tmp2); - - node->ResetHWIntrinsicId(NI_SSE2_UnpackLow, tmp1, tmp2); - break; - } -#endif // TARGET_AMD64 - case TYP_FLOAT: { unsigned N = 0; @@ -5162,28 +4900,52 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) break; } + case TYP_LONG: + case TYP_ULONG: case TYP_DOUBLE: { + GenTree* op2 = node->Op(2); + + if (varTypeIsLong(simdBaseType) && comp->compOpportunisticallyDependsOn(InstructionSet_SSE41_X64)) + { + // We will be constructing the following parts: + // ... + // idx = CNS_INT int 1 + // /--* tmp1 simd16 + // +--* op2 T + // +--* idx int + // node = * HWINTRINSIC simd16 T Insert + + // This is roughly the following managed code: + // ... + // return Sse41.X64.Insert(tmp1, op2, 0x01); + + idx = comp->gtNewIconNode(0x01, TYP_INT); + BlockRange().InsertBefore(node, idx); + + node->ResetHWIntrinsicId(NI_SSE41_X64_Insert, comp, tmp1, op2, idx); + break; + } + // We will be constructing the following parts: // ... // /--* op2 T // tmp2 = * HWINTRINSIC simd16 T CreateScalarUnsafe // /--* tmp1 simd16 // +--* tmp2 simd16 - // node = * HWINTRINSIC simd16 T MoveLowToHigh + // node = * HWINTRINSIC simd16 T UnpackLow // This is roughly the following managed code: // ... // var tmp2 = Vector128.CreateScalarUnsafe(op2); - // return Sse.MoveLowToHigh(tmp1, tmp2); + // return Sse.UnpackLow(tmp1, tmp2); assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); tmp2 = InsertNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op2, simdBaseJitType, 16); LowerNode(tmp2); - node->ResetHWIntrinsicId(NI_SSE_MoveLowToHigh, tmp1, tmp2); - node->SetSimdBaseJitType(CORINFO_TYPE_FLOAT); + node->ResetHWIntrinsicId(NI_SSE2_UnpackLow, tmp1, tmp2); break; } @@ -5210,9 +4972,7 @@ GenTree* Lowering::LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node) var_types simdBaseType = node->GetSimdBaseType(); unsigned simdSize = node->GetSimdSize(); - assert((intrinsicId == NI_Vector128_GetElement) || (intrinsicId == NI_Vector256_GetElement) || - (intrinsicId == NI_Vector512_GetElement)); - + assert(HWIntrinsicInfo::IsVectorGetElement(intrinsicId)); assert(!varTypeIsSIMD(simdType)); assert(varTypeIsArithmetic(simdBaseType)); assert(simdSize != 0); @@ -6835,24 +6595,25 @@ GenTree* Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node) unsigned simdSize = node->GetSimdSize(); var_types simdType = Compiler::getSIMDTypeForSize(simdSize); - assert((intrinsicId == NI_Vector128_ToScalar) || (intrinsicId == NI_Vector256_ToScalar) || - (intrinsicId == NI_Vector512_ToScalar)); - + assert(HWIntrinsicInfo::IsVectorToScalar(intrinsicId)); assert(varTypeIsSIMD(simdType)); assert(varTypeIsArithmetic(simdBaseType)); assert(simdSize != 0); GenTree* op1 = node->Op(1); - if (IsContainableMemoryOp(op1)) + if (IsContainableMemoryOp(op1) && (!varTypeIsLong(simdBaseType) || TargetArchitecture::Is64Bit)) { - // We will specially handle ToScalar when op1 is already in memory + // If op1 is already in memory, we'd like the consumer of ToScalar to be able to look + // through to the memory directly. Early folding is preferable, as it unlocks additional + // containment opportunities for the consuming nodes. If we can't fold away ToScalar, + // we will still contain op1 if possible, and let codegen try to peek through to it. + // + // However, we specifically need to avoid doing this for long on 32-bit because we are + // already past DecomposeLongs, and codegen wouldn't be able to handle it. if (op1->OperIs(GT_IND)) { - // We want to optimize ToScalar down to an Indir where possible as - // this unlocks additional containment opportunities for various nodes - GenTreeIndir* indir = op1->AsIndir(); GenTreeIndir* newIndir = @@ -6879,9 +6640,6 @@ GenTree* Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node) { uint32_t elemSize = genTypeSize(simdBaseType); - // We want to optimize ToScalar down to a LclFld where possible as - // this unlocks additional containment opportunities for various nodes - GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon(); uint32_t lclOffs = lclVar->GetLclOffs() + (0 * elemSize); LclVarDsc* lclDsc = comp->lvaGetDesc(lclVar); @@ -6908,92 +6666,10 @@ GenTree* Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node) return LowerNode(lclFld); } } - - if (IsSafeToContainMem(node, op1)) - { - // Handle other cases in codegen - ContainCheckHWIntrinsic(node); - return node->gtNext; - } } - switch (simdBaseType) - { - case TYP_BYTE: - case TYP_SHORT: - case TYP_INT: - { - node->gtType = TYP_INT; - node->SetSimdBaseJitType(CORINFO_TYPE_INT); - node->ChangeHWIntrinsicId(NI_SSE2_ConvertToInt32); - break; - } - - case TYP_UBYTE: - case TYP_USHORT: - case TYP_UINT: - { - node->gtType = TYP_INT; - node->SetSimdBaseJitType(CORINFO_TYPE_UINT); - node->ChangeHWIntrinsicId(NI_SSE2_ConvertToUInt32); - break; - } - -#if defined(TARGET_AMD64) - case TYP_LONG: - { - node->ChangeHWIntrinsicId(NI_SSE2_X64_ConvertToInt64); - break; - } - - case TYP_ULONG: - { - node->ChangeHWIntrinsicId(NI_SSE2_X64_ConvertToUInt64); - break; - } -#endif // TARGET_AMD64 - - case TYP_FLOAT: - case TYP_DOUBLE: - { - ContainCheckHWIntrinsic(node); - return node->gtNext; - } - - default: - { - unreached(); - } - } - - GenTree* next = LowerNode(node); - - if (genTypeSize(simdBaseType) < 4) - { - // The move intrinsics do not touch the upper bits, so we need an explicit - // cast to ensure the result is properly sign extended - - LIR::Use use; - - bool foundUse = BlockRange().TryGetUse(node, &use); - bool fromUnsigned = varTypeIsUnsigned(simdBaseType); - - GenTreeCast* cast = comp->gtNewCastNode(TYP_INT, node, fromUnsigned, simdBaseType); - BlockRange().InsertAfter(node, cast); - - if (foundUse) - { - use.ReplaceWith(cast); - } - else - { - node->ClearUnusedValue(); - cast->SetUnusedValue(); - } - next = LowerNode(cast); - } - - return next; + ContainCheckHWIntrinsic(node); + return node->gtNext; } //---------------------------------------------------------------------------------------------- @@ -8016,20 +7692,38 @@ void Lowering::ContainCheckStoreIndir(GenTreeStoreInd* node) case NI_Vector256_ToScalar: case NI_Vector512_ToScalar: { - if (varTypeIsFloating(simdBaseType)) + // These intrinsics are "ins reg/mem, xmm" or "ins xmm, reg/mem" + // + // In the case we are coming from and going to memory, we want to + // preserve the original containment as we'll end up emitting a pair + // of scalar moves. e.g. for float: + // movss xmm0, [addr1] ; Size: 4, Latency: 4-7, TP: 0.5 + // movss [addr2], xmm0 ; Size: 4, Latency: 4-10, TP: 1 + // + // However, we want to prefer containing the store over allowing the + // input to be regOptional, so track and clear containment if required. + + clearContainedNode = hwintrinsic->Op(1); + isContainable = !clearContainedNode->isContained(); + + if (isContainable && varTypeIsIntegral(simdBaseType)) { - // These intrinsics are "ins reg/mem, xmm" or "ins xmm, reg/mem" - // - // In the case we are coming from and going to memory, we want to - // preserve the original containment as we'll end up emitting: - // movss xmm0, [addr1] ; Size: 4, Latency: 4-7, TP: 0.5 - // movss [addr2], xmm0 ; Size: 4, Latency: 4-10, TP: 1 - // - // However, we want to prefer containing the store over allowing the - // input to be regOptional, so track and clear containment if required. + isContainable = (genTypeSize(simdBaseType) == genTypeSize(node)) && + (!varTypeIsSmall(simdBaseType) || + comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)); + + if (isContainable && varTypeIsSmall(simdBaseType)) + { + CorInfoType baseJitType = varTypeIsByte(node) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_USHORT; + intrinsicId = varTypeIsByte(node) ? NI_SSE41_Extract : NI_SSE2_Extract; + + GenTree* zero = comp->gtNewZeroConNode(TYP_INT); + BlockRange().InsertBefore(hwintrinsic, zero); - clearContainedNode = hwintrinsic->Op(1); - isContainable = !clearContainedNode->isContained(); + hwintrinsic->SetSimdBaseJitType(baseJitType); + hwintrinsic->ResetHWIntrinsicId(intrinsicId, hwintrinsic->Op(1), zero); + zero->SetContained(); + } } break; } @@ -8453,21 +8147,40 @@ void Lowering::ContainCheckDivOrMod(GenTreeOp* node) void Lowering::ContainCheckShiftRotate(GenTreeOp* node) { assert(node->OperIsShiftOrRotate()); + + GenTree* source = node->gtOp1; + GenTree* shiftBy = node->gtOp2; + #ifdef TARGET_X86 - GenTree* source = node->gtOp1; if (node->OperIsShiftLong()) { - assert(source->OperGet() == GT_LONG); + assert(source->OperIs(GT_LONG)); MakeSrcContained(node, source); } -#endif +#endif // TARGET_X86 - GenTree* shiftBy = node->gtOp2; if (IsContainableImmed(node, shiftBy) && (shiftBy->AsIntConCommon()->IconValue() <= 255) && (shiftBy->AsIntConCommon()->IconValue() >= 0)) { MakeSrcContained(node, shiftBy); } + + bool canContainSource = !source->isContained() && (genTypeSize(source) >= genTypeSize(node)); + + // BMI2 rotate and shift instructions take memory operands but do not set flags. + // rorx takes imm8 for the rotate amount; shlx/shrx/sarx take r32/64 for shift amount. + if (canContainSource && !node->gtSetFlags() && (shiftBy->isContained() != node->OperIsShift()) && + comp->compOpportunisticallyDependsOn(InstructionSet_BMI2)) + { + if (IsContainableMemoryOp(source) && IsSafeToContainMem(node, source)) + { + MakeSrcContained(node, source); + } + else if (IsSafeToMarkRegOptional(node, source)) + { + MakeSrcRegOptional(node, source); + } + } } //------------------------------------------------------------------------ @@ -9152,6 +8865,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre case NI_AVX10v1_ShiftRightArithmetic: { assert((tupleType & INS_TT_MEM128) != 0); + tupleType = static_cast(tupleType & ~INS_TT_MEM128); // Shift amount (op2) can be either imm8 or vector. If vector, it will always be xmm/m128. // @@ -9163,12 +8877,8 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre expectedSize = genTypeSize(TYP_SIMD16); break; } - else if ((expectedSize < genTypeSize(TYP_SIMD64)) && (ins != INS_vpsraq)) + else if (!comp->canUseEvexEncoding()) { - // TODO-XArch-CQ: This should really only be checking EVEX capability, however - // emitter::TakesEvexPrefix doesn't currently handle requiring EVEX based on presence - // of an immediate operand. For now we disable containment of op1 unless EVEX is - // required for some other reason. supportsMemoryOp = false; break; } @@ -9214,7 +8924,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre default: SIZE_FROM_TUPLE_TYPE: { - tupleType = static_cast(tupleType & ~INS_TT_MEM128); switch (tupleType) { case INS_TT_NONE: @@ -9295,6 +9004,9 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre switch (parentIntrinsicId) { + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: case NI_Vector512_CreateScalarUnsafe: @@ -9399,6 +9111,9 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre switch (intrinsicId) { + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: case NI_Vector512_CreateScalarUnsafe: @@ -9494,7 +9209,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre { GenTreeHWIntrinsic* hwintrinsicOperand = broadcastOperand->AsHWIntrinsic(); - if (hwintrinsicOperand->OperIsCreateScalarUnsafe()) + if (HWIntrinsicInfo::IsVectorCreateScalarUnsafe(hwintrinsicOperand->GetHWIntrinsicId())) { // CreateScalarUnsafe can contain non-memory operands such as enregistered // locals, so we want to check if its operand is containable instead. This @@ -9841,9 +9556,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) if ((simdSize == 8) || (simdSize == 12)) { // We want to handle GetElement/ToScalar still for Vector2/3 - if ((intrinsicId != NI_Vector128_GetElement) && (intrinsicId != NI_Vector128_ToScalar) && - (intrinsicId != NI_Vector256_GetElement) && (intrinsicId != NI_Vector256_ToScalar) && - (intrinsicId != NI_Vector512_GetElement) && (intrinsicId != NI_Vector512_ToScalar)) + if (!HWIntrinsicInfo::IsVectorToScalar(intrinsicId) && !HWIntrinsicInfo::IsVectorGetElement(intrinsicId)) { // TODO-XArch-CQ: Ideally we would key this off of the size the containing node // expects vs the size node actually is or would be if spilled to the stack @@ -9952,7 +9665,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { GenTreeHWIntrinsic* childNode = op1->AsHWIntrinsic(); - if (childNode->OperIsCreateScalarUnsafe()) + if (HWIntrinsicInfo::IsVectorCreateScalarUnsafe(childNode->GetHWIntrinsicId())) { // We have a very special case of BroadcastScalarToVector(CreateScalarUnsafe(op1)) // @@ -9964,6 +9677,12 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) // op1 directly, we'll then special case the codegen to materialize the value into a // SIMD register in the case it is marked optional and doesn't get spilled. + if (childNode->Op(1)->OperIsLong()) + { + // Decomposed longs require special codegen + return; + } + node->Op(1) = childNode->Op(1); BlockRange().Remove(op1); @@ -10068,6 +9787,50 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) return; } +#ifdef TARGET_X86 + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: + case NI_Vector128_CreateScalarUnsafe: + case NI_Vector256_CreateScalarUnsafe: + case NI_Vector512_CreateScalarUnsafe: + { + if (op1->OperIsLong()) + { + // Contain decomposed longs and handle them in codegen + assert(varTypeIsLong(simdBaseType)); + + for (GenTree* longOp : op1->Operands()) + { + if (IsContainableMemoryOp(longOp) && IsSafeToContainMem(node, longOp)) + { + MakeSrcContained(node, longOp); + } + else if (IsSafeToMarkRegOptional(node, longOp)) + { + MakeSrcRegOptional(node, longOp); + } + } + + MakeSrcContained(node, op1); + return; + } + break; + } + + case NI_Vector128_ToScalar: + case NI_Vector256_ToScalar: + case NI_Vector512_ToScalar: + { + // These will be contained by a STOREIND + if (varTypeIsLong(simdBaseType)) + { + return; + } + break; + } +#endif + default: { break; diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index fe29ad9fd77d9b..1aa99206749e23 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -3856,9 +3856,36 @@ void LinearScan::processKills(RefPosition* killRefPosition) RefPosition* nextKill = killRefPosition->nextRefPosition; regMaskTP killedRegs = killRefPosition->getKilledRegisters(); - while (killedRegs.IsNonEmpty()) + + freeKilledRegs(killRefPosition, killedRegs.getLow(), nextKill, REG_LOW_BASE); + +#ifdef HAS_MORE_THAN_64_REGISTERS + freeKilledRegs(killRefPosition, killedRegs.getHigh(), nextKill, REG_HIGH_BASE); +#endif + + regsBusyUntilKill &= ~killRefPosition->getKilledRegisters(); + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, nullptr, NONE, + killRefPosition->getKilledRegisters())); +} + +//------------------------------------------------------------------------ +// freeKilledRegs: Handle registers that are being killed. +// +// Arguments: +// killRefPosition - The RefPosition for the kill +// killedRegs - Registers to kill +// nextKill - The RefPosition for next kill +// regBase - `0` or `64` based on the `killedRegs` being processed +// +void LinearScan::freeKilledRegs(RefPosition* killRefPosition, + SingleTypeRegSet killedRegs, + RefPosition* nextKill, + int regBase) +{ + + while (killedRegs != RBM_NONE) { - regNumber killedReg = genFirstRegNumFromMaskAndToggle(killedRegs); + regNumber killedReg = (regNumber)(genFirstRegNumFromMaskAndToggle(killedRegs) + regBase); RegRecord* regRecord = getRegisterRecord(killedReg); Interval* assignedInterval = regRecord->assignedInterval; if (assignedInterval != nullptr) @@ -3874,10 +3901,6 @@ void LinearScan::processKills(RefPosition* killRefPosition) : regRecord->recentRefPosition->nextRefPosition; updateNextFixedRef(regRecord, regNextRefPos, nextKill); } - - regsBusyUntilKill &= ~killRefPosition->getKilledRegisters(); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, nullptr, NONE, - killRefPosition->getKilledRegisters())); } //------------------------------------------------------------------------ @@ -4555,14 +4578,34 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock) } } #else + regMaskTP deadCandidates = ~liveRegs; // Only focus on actual registers present deadCandidates &= actualRegistersMask; + handleDeadCandidates(deadCandidates.getLow(), REG_LOW_BASE, inVarToRegMap); +#ifdef HAS_MORE_THAN_64_REGISTERS + handleDeadCandidates(deadCandidates.getHigh(), REG_HIGH_BASE, inVarToRegMap); +#endif // HAS_MORE_THAN_64_REGISTERS +#endif // TARGET_ARM +} - while (deadCandidates.IsNonEmpty()) +//------------------------------------------------------------------------ +// handleDeadCandidates: Handle registers that are assigned to local variables. +// +// Arguments: +// deadCandidates - mask of registers. +// regBase - base register number. +// inVarToRegMap - variable to register map. +// +// Return Value: +// None +// +void LinearScan::handleDeadCandidates(SingleTypeRegSet deadCandidates, int regBase, VarToRegMap inVarToRegMap) +{ + while (deadCandidates != RBM_NONE) { - regNumber reg = genFirstRegNumFromMaskAndToggle(deadCandidates); + regNumber reg = (regNumber)(genFirstRegNumFromMaskAndToggle(deadCandidates) + regBase); RegRecord* physRegRecord = getRegisterRecord(reg); makeRegAvailable(reg, physRegRecord->registerType); @@ -4592,7 +4635,6 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock) } } } -#endif // TARGET_ARM } //------------------------------------------------------------------------ @@ -4741,6 +4783,22 @@ void LinearScan::freeRegister(RegRecord* physRegRecord) } } +//------------------------------------------------------------------------ +// LinearScan::freeRegisters: Free the registers in 'regsToFree' +// +// Arguments: +// regsToFree - the mask of registers to free, separated into low and high parts. +// regBase - `0` or `64` depending on if the registers to be freed are in the lower or higher bank. +// +void LinearScan::freeRegistersSingleType(SingleTypeRegSet regsToFree, int regBase) +{ + while (regsToFree != RBM_NONE) + { + regNumber nextReg = (regNumber)(genFirstRegNumFromMaskAndToggle(regsToFree) + regBase); + RegRecord* regRecord = getRegisterRecord(nextReg); + freeRegister(regRecord); + } +} //------------------------------------------------------------------------ // LinearScan::freeRegisters: Free the registers in 'regsToFree' // @@ -4756,20 +4814,26 @@ void LinearScan::freeRegisters(regMaskTP regsToFree) INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FREE_REGS)); makeRegsAvailable(regsToFree); +#ifdef TARGET_ARM while (regsToFree.IsNonEmpty()) { regNumber nextReg = genFirstRegNumFromMaskAndToggle(regsToFree); RegRecord* regRecord = getRegisterRecord(nextReg); -#ifdef TARGET_ARM if (regRecord->assignedInterval != nullptr && (regRecord->assignedInterval->registerType == TYP_DOUBLE)) { assert(genIsValidDoubleReg(nextReg)); regsToFree.RemoveRegNumFromMask(regNumber(nextReg + 1)); } -#endif freeRegister(regRecord); } +#else + freeRegistersSingleType(regsToFree.getLow(), REG_LOW_BASE); +#ifdef HAS_MORE_THAN_64_REGISTERS + freeRegistersSingleType(regsToFree.getHigh(), REG_HIGH_BASE); +#endif + +#endif } //------------------------------------------------------------------------ @@ -8218,7 +8282,7 @@ void LinearScan::resolveRegisters() // Determine initial position for parameters - if (varDsc->lvIsParam) + if (varDsc->lvIsParam || varDsc->lvIsParamRegTarget) { SingleTypeRegSet initialRegMask = interval->firstRefPosition->registerAssignment; regNumber initialReg = (initialRegMask == RBM_NONE || interval->firstRefPosition->spillAfter) diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index a00338006e865d..4b76b336be504c 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -1005,8 +1005,10 @@ class LinearScan : public LinearScanInterface // Record variable locations at start/end of block void processBlockStartLocations(BasicBlock* current); - void processBlockEndLocations(BasicBlock* current); - void resetAllRegistersState(); + + FORCEINLINE void handleDeadCandidates(SingleTypeRegSet deadCandidates, int regBase, VarToRegMap inVarToRegMap); + void processBlockEndLocations(BasicBlock* current); + void resetAllRegistersState(); #ifdef TARGET_ARM bool isSecondHalfReg(RegRecord* regRec, Interval* interval); @@ -1079,9 +1081,10 @@ class LinearScan : public LinearScanInterface SingleTypeRegSet lowSIMDRegs(); SingleTypeRegSet internalFloatRegCandidates(); - void makeRegisterInactive(RegRecord* physRegRecord); - void freeRegister(RegRecord* physRegRecord); - void freeRegisters(regMaskTP regsToFree); + void makeRegisterInactive(RegRecord* physRegRecord); + void freeRegister(RegRecord* physRegRecord); + void freeRegisters(regMaskTP regsToFree); + FORCEINLINE void freeRegistersSingleType(SingleTypeRegSet regsToFree, int regBase); // Get the type that this tree defines. var_types getDefType(GenTree* tree) @@ -1192,8 +1195,12 @@ class LinearScan : public LinearScanInterface void setIntervalAsSplit(Interval* interval); void spillInterval(Interval* interval, RefPosition* fromRefPosition DEBUGARG(RefPosition* toRefPosition)); - void processKills(RefPosition* killRefPosition); - void spillGCRefs(RefPosition* killRefPosition); + void processKills(RefPosition* killRefPosition); + FORCEINLINE void freeKilledRegs(RefPosition* killRefPosition, + SingleTypeRegSet killedRegs, + RefPosition* nextKill, + int regBase); + void spillGCRefs(RefPosition* killRefPosition); /***************************************************************************** * Register selection diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 93d78e26d2d6bf..3ef6952fb8aec5 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1105,19 +1105,17 @@ int LinearScan::BuildShiftRotate(GenTree* tree) } #endif } -#if defined(TARGET_64BIT) - else if (tree->OperIsShift() && !tree->isContained() && + else if (!tree->isContained() && (tree->OperIsShift() || source->isContained()) && compiler->compOpportunisticallyDependsOn(InstructionSet_BMI2)) { - // shlx (as opposed to mov+shl) instructions handles all register forms, but it does not handle contained form - // for memory operand. Likewise for sarx and shrx. + // We don'thave any specific register requirements here, so skip the logic that + // reserves RCX or preferences the source reg. // ToDo-APX : Remove when extended EVEX support is available srcCount += BuildOperandUses(source, BuildApxIncompatibleGPRMask(source, srcCandidates)); srcCount += BuildOperandUses(shiftBy, BuildApxIncompatibleGPRMask(shiftBy, dstCandidates)); BuildDef(tree, BuildApxIncompatibleGPRMask(tree, dstCandidates, true)); return srcCount; } -#endif else { // This ends up being BMI @@ -1141,9 +1139,9 @@ int LinearScan::BuildShiftRotate(GenTree* tree) #ifdef TARGET_X86 // The first operand of a GT_LSH_HI and GT_RSH_LO oper is a GT_LONG so that // we can have a three operand form. - if (tree->OperGet() == GT_LSH_HI || tree->OperGet() == GT_RSH_LO) + if (tree->OperIs(GT_LSH_HI) || tree->OperIs(GT_RSH_LO)) { - assert((source->OperGet() == GT_LONG) && source->isContained()); + assert(source->OperIs(GT_LONG) && source->isContained()); GenTree* sourceLo = source->gtGetOp1(); GenTree* sourceHi = source->gtGetOp2(); @@ -1153,7 +1151,7 @@ int LinearScan::BuildShiftRotate(GenTree* tree) if (!tree->isContained()) { - if (tree->OperGet() == GT_LSH_HI) + if (tree->OperIs(GT_LSH_HI)) { setDelayFree(sourceLoUse); } @@ -1174,6 +1172,7 @@ int LinearScan::BuildShiftRotate(GenTree* tree) { srcCount += BuildOperandUses(source, srcCandidates); } + if (!tree->isContained()) { if (!shiftBy->isContained()) @@ -2046,39 +2045,47 @@ int LinearScan::BuildIntrinsic(GenTree* tree) #ifdef FEATURE_HW_INTRINSICS //------------------------------------------------------------------------ -// SkipContainedCreateScalarUnsafe: Skips a contained CreateScalarUnsafe node +// SkipContainedUnaryOp: Skips a contained non-memory or const node // and gets the underlying op1 instead // // Arguments: // node - The node to handle // // Return Value: -// If node is a contained CreateScalarUnsafe, it's op1 is returned; +// If node is a contained non-memory or const unary op, its op1 is returned; // otherwise node is returned unchanged. -static GenTree* SkipContainedCreateScalarUnsafe(GenTree* node) +static GenTree* SkipContainedUnaryOp(GenTree* node) { - if (!node->OperIsHWIntrinsic() || !node->isContained()) + if (!node->isContained()) { return node; } - GenTreeHWIntrinsic* hwintrinsic = node->AsHWIntrinsic(); - NamedIntrinsic intrinsicId = hwintrinsic->GetHWIntrinsicId(); - - switch (intrinsicId) + if (node->OperIsHWIntrinsic()) { - case NI_Vector128_CreateScalarUnsafe: - case NI_Vector256_CreateScalarUnsafe: - case NI_Vector512_CreateScalarUnsafe: - { - return hwintrinsic->Op(1); - } + GenTreeHWIntrinsic* hwintrinsic = node->AsHWIntrinsic(); + NamedIntrinsic intrinsicId = hwintrinsic->GetHWIntrinsicId(); - default: + switch (intrinsicId) { - return node; + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: + case NI_Vector128_CreateScalarUnsafe: + case NI_Vector256_CreateScalarUnsafe: + case NI_Vector512_CreateScalarUnsafe: + { + return hwintrinsic->Op(1); + } + + default: + { + break; + } } } + + return node; } //------------------------------------------------------------------------ @@ -2135,8 +2142,8 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou } else { - // A contained CreateScalarUnsafe is special in that we're not containing it to load from - // memory and it isn't a constant. Instead, its essentially a "transparent" node we're ignoring + // In a few cases, we contain an operand that isn't a load from memory or a constant. Instead, + // it is essentially a "transparent" node we're ignoring or handling specially in codegen // to simplify the overall IR handling. As such, we need to "skip" such nodes when present and // get the underlying op1 so that delayFreeUse and other preferencing remains correct. @@ -2145,37 +2152,37 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou GenTree* op3 = nullptr; GenTree* op4 = nullptr; GenTree* op5 = nullptr; - GenTree* lastOp = SkipContainedCreateScalarUnsafe(intrinsicTree->Op(numArgs)); + GenTree* lastOp = SkipContainedUnaryOp(intrinsicTree->Op(numArgs)); switch (numArgs) { case 5: { - op5 = SkipContainedCreateScalarUnsafe(intrinsicTree->Op(5)); + op5 = SkipContainedUnaryOp(intrinsicTree->Op(5)); FALLTHROUGH; } case 4: { - op4 = SkipContainedCreateScalarUnsafe(intrinsicTree->Op(4)); + op4 = SkipContainedUnaryOp(intrinsicTree->Op(4)); FALLTHROUGH; } case 3: { - op3 = SkipContainedCreateScalarUnsafe(intrinsicTree->Op(3)); + op3 = SkipContainedUnaryOp(intrinsicTree->Op(3)); FALLTHROUGH; } case 2: { - op2 = SkipContainedCreateScalarUnsafe(intrinsicTree->Op(2)); + op2 = SkipContainedUnaryOp(intrinsicTree->Op(2)); FALLTHROUGH; } case 1: { - op1 = SkipContainedCreateScalarUnsafe(intrinsicTree->Op(1)); + op1 = SkipContainedUnaryOp(intrinsicTree->Op(1)); break; } @@ -2224,11 +2231,14 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou // must be handled within the case. switch (intrinsicId) { + case NI_Vector128_CreateScalar: + case NI_Vector256_CreateScalar: + case NI_Vector512_CreateScalar: case NI_Vector128_CreateScalarUnsafe: - case NI_Vector128_ToScalar: case NI_Vector256_CreateScalarUnsafe: - case NI_Vector256_ToScalar: case NI_Vector512_CreateScalarUnsafe: + case NI_Vector128_ToScalar: + case NI_Vector256_ToScalar: case NI_Vector512_ToScalar: { assert(numArgs == 1); @@ -2242,17 +2252,38 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou } else { - // We will either be in memory and need to be moved - // into a register of the appropriate size or we - // are already in an XMM/YMM/ZMM register and can stay - // where we are. + // CreateScalarUnsafe and ToScalar are essentially no-ops for floating point types and can reuse + // the op1 register. CreateScalar needs to clear the upper elements, so if we have a float and + // can't use insertps to zero the upper elements in-place, we'll need a different target reg. - tgtPrefUse = BuildUse(op1); + RefPosition* op1Use = BuildUse(op1); srcCount += 1; + + if ((baseType == TYP_FLOAT) && HWIntrinsicInfo::IsVectorCreateScalar(intrinsicId) && + !compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + setDelayFree(op1Use); + } + else + { + tgtPrefUse = op1Use; + } } buildUses = false; } +#if TARGET_X86 + else if (varTypeIsByte(baseType) && HWIntrinsicInfo::IsVectorToScalar(intrinsicId)) + { + dstCandidates = allByteRegs(); + } + else if (varTypeIsLong(baseType) && !compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + // For SSE2 fallbacks, we will need a temp register to insert the upper half of a long + buildInternalFloatRegisterDefForNode(intrinsicTree); + setInternalRegsDelayFree = true; + } +#endif // TARGET_X86 break; } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 43390fd874418a..53b9bc8166d44b 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -2287,6 +2287,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) #else *use = fieldList->SoleFieldOrThis(); #endif + *use = fgMorphTree(*use); } else { @@ -2335,7 +2336,8 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) // Try to see if we can use the promoted fields to pass this argument. // - if (varDsc->lvPromoted && (varDsc->lvFieldCnt == arg->AbiInfo.CountRegsAndStackSlots())) + if (varDsc->lvPromoted && !varDsc->lvDoNotEnregister && + (varDsc->lvFieldCnt == arg->AbiInfo.CountRegsAndStackSlots())) { bool fieldsMatch = true; @@ -2366,6 +2368,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) if (fieldsMatch) { newArg = fgMorphLclToFieldList(lclNode)->SoleFieldOrThis(); + newArg = fgMorphTree(newArg); } } } @@ -2511,7 +2514,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) lvaSetVarDoNotEnregister(lclVar->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField)); } } - result->SetMorphed(this); + result = fgMorphTree(result); return result; } else @@ -2532,7 +2535,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) } GenTree* indir = gtNewIndir(type, addr); - indir->SetMorphed(this, /* doChildren*/ true); + indir->SetMorphed(this, /* doChildren */ true); return indir; } }; @@ -2593,16 +2596,15 @@ GenTreeFieldList* Compiler::fgMorphLclToFieldList(GenTreeLclVar* lcl) unsigned fieldLclNum = varDsc->lvFieldLclStart; GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList(); - fieldList->SetMorphed(this); for (unsigned i = 0; i < fieldCount; i++) { LclVarDsc* fieldVarDsc = lvaGetDesc(fieldLclNum); GenTree* lclVar = gtNewLclvNode(fieldLclNum, fieldVarDsc->TypeGet()); - lclVar->SetMorphed(this); fieldList->AddField(this, lclVar, fieldVarDsc->lvFldOffset, fieldVarDsc->TypeGet()); fieldLclNum++; } + return fieldList; } @@ -4684,8 +4686,13 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call) // fgMorphRecursiveFastTailCallIntoLoop() is not handling update of generic context while transforming // a recursive call into a loop. Another option is to modify gtIsRecursiveCall() to check that the // generic type parameters of both caller and callee generic method are the same. - if (opts.compTailCallLoopOpt && canFastTailCall && gtIsRecursiveCall(call) && !lvaReportParamTypeArg() && - !lvaKeepAliveAndReportThis() && !call->IsVirtual() && !hasStructParam && !varTypeIsStruct(call->TypeGet())) + // + // For OSR, we prefer to tailcall for call counting + potential transition + // into the actual tier1 version. + // + if (opts.compTailCallLoopOpt && canFastTailCall && !opts.IsOSR() && gtIsRecursiveCall(call) && + !lvaReportParamTypeArg() && !lvaKeepAliveAndReportThis() && !call->IsVirtual() && !hasStructParam && + !varTypeIsStruct(call->TypeGet())) { fastTailCallToLoop = true; } @@ -6159,23 +6166,12 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa // Remove the call fgRemoveStmt(block, lastStmt); + assert(!opts.IsOSR()); // Set the loop edge. - BasicBlock* entryBB; - if (opts.IsOSR()) - { - // Todo: this may not look like a viable loop header. - // Might need the moral equivalent of an init BB. - entryBB = fgEntryBB; - } - else - { - assert(doesMethodHaveRecursiveTailcall()); - - // TODO-Cleanup: We should really be expanding tailcalls into loops - // much earlier than this, at a place where we do not need to have - // hacky workarounds to figure out what the actual IL entry block is. - entryBB = fgGetFirstILBlock(); - } + // TODO-Cleanup: We should really be expanding tailcalls into loops much + // earlier than this, at a place where we can just use the init BB here. + BasicBlock* entryBB = fgGetFirstILBlock(); + assert(doesMethodHaveRecursiveTailcall()); FlowEdge* const newEdge = fgAddRefPred(entryBB, block); block->SetKindAndTargetEdge(BBJ_ALWAYS, newEdge); @@ -8366,7 +8362,10 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA GenTree*& retVal = tree->AsOp()->ReturnValueRef(); if ((retVal != nullptr) && ((genReturnBB == nullptr) || (compCurBB == genReturnBB))) { - fgTryReplaceStructLocalWithFields(&retVal); + if (fgTryReplaceStructLocalWithFields(&retVal)) + { + retVal = fgMorphTree(retVal); + } } break; } @@ -8424,19 +8423,22 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // Notes: // Currently only called when the tree parent is a GT_RETURN/GT_SWIFT_ERROR_RET. // -void Compiler::fgTryReplaceStructLocalWithFields(GenTree** use) +bool Compiler::fgTryReplaceStructLocalWithFields(GenTree** use) { if (!(*use)->OperIs(GT_LCL_VAR)) { - return; + return false; } LclVarDsc* varDsc = lvaGetDesc((*use)->AsLclVar()); - if (!varDsc->lvDoNotEnregister && varDsc->lvPromoted) + if (varDsc->lvDoNotEnregister || !varDsc->lvPromoted) { - *use = fgMorphLclToFieldList((*use)->AsLclVar()); + return false; } + + *use = fgMorphLclToFieldList((*use)->AsLclVar()); + return true; } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp index 751b11fc8898ee..af5e1b8d0f31c3 100644 --- a/src/coreclr/jit/objectalloc.cpp +++ b/src/coreclr/jit/objectalloc.cpp @@ -18,6 +18,175 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "gentree.h" #include "jitstd/algorithm.h" +//------------------------------------------------------------------------ +// ObjectAllocator: construct the object allocator object +// +// Arguments: +// comp - compiler instance +// +// Notes: +// Runs only if Compiler::optMethodFlags has flag OMF_HAS_NEWOBJ set. +// +// Builds a connection graph where nodes mostly represent local vars, +// showing how locals can assign values to one another. +// +// The graph also includes a few absract node types: a node representing +// an unknow source of values, and (pseudo local) nodes representing +// assignments that only happen under particular conditions. +// +ObjectAllocator::ObjectAllocator(Compiler* comp) + : Phase(comp, PHASE_ALLOCATE_OBJECTS) + , m_IsObjectStackAllocationEnabled(false) + , m_AnalysisDone(false) + , m_bvCount(0) + , m_bitVecTraits(BitVecTraits(comp->lvaCount, comp)) + , m_HeapLocalToStackLocalMap(comp->getAllocator(CMK_ObjectAllocator)) + , m_EnumeratorLocalToPseudoLocalMap(comp->getAllocator(CMK_ObjectAllocator)) + , m_CloneMap(comp->getAllocator(CMK_ObjectAllocator)) + , m_nextLocalIndex(0) + , m_firstPseudoLocalNum(BAD_VAR_NUM) + , m_firstPseudoLocalIndex(BAD_VAR_NUM) + , m_numPseudoLocals(0) + , m_maxPseudoLocals(0) + , m_regionsToClone(0) +{ + m_EscapingPointers = BitVecOps::UninitVal(); + m_PossiblyStackPointingPointers = BitVecOps::UninitVal(); + m_DefinitelyStackPointingPointers = BitVecOps::UninitVal(); + m_ConnGraphAdjacencyMatrix = nullptr; + m_StackAllocMaxSize = (unsigned)JitConfig.JitObjectStackAllocationSize(); +} + +//------------------------------------------------------------------------ +// IsTrackedType: see if this type is being tracked by escape analysis +// +// Arguments: +// type - type of interest +// +// Returns: +// true if so +// +bool ObjectAllocator::IsTrackedType(var_types type) +{ + const bool isTrackableScalar = (type == TYP_REF) || (genActualType(type) == TYP_I_IMPL) || (type == TYP_BYREF); + return isTrackableScalar; +} + +//------------------------------------------------------------------------ +// IsTrackedLocal: see if this local is being tracked by escape analysis +// +// Arguments: +// lclNum - local of interest +// +// Returns: +// true if so +// +bool ObjectAllocator::IsTrackedLocal(unsigned lclNum) +{ + assert(lclNum < comp->lvaCount); + LclVarDsc* const varDsc = comp->lvaGetDesc(lclNum); + return varDsc->lvTracked; +} + +//------------------------------------------------------------------------ +// HasIndex: see if a given local has a tracking index +// +// Arguments: +// lclNum -- local to query +// +// Returns: +// true if so +// +bool ObjectAllocator::HasIndex(unsigned lclNum) +{ + if (lclNum < comp->lvaCount) + { + LclVarDsc* const varDsc = comp->lvaGetDesc(lclNum); + return varDsc->lvTracked; + } + + if ((lclNum >= m_firstPseudoLocalNum) && (lclNum < m_bvCount)) + { + return true; + } + + return false; +} + +//------------------------------------------------------------------------ +// LocalToIndex: get the bit vector index for a local or pseudo-local +// +// Arguments: +// lclNum -- local var num or pseudo local var num +// +// Returns: +// bvIndex to use +// +unsigned ObjectAllocator::LocalToIndex(unsigned lclNum) +{ + unsigned result = BAD_VAR_NUM; + + if (lclNum < comp->lvaCount) + { + assert(IsTrackedLocal(lclNum)); + LclVarDsc* const varDsc = comp->lvaGetDesc(lclNum); + result = varDsc->lvVarIndex; + } + else + { + result = m_firstPseudoLocalIndex + (lclNum - m_firstPseudoLocalNum); + } + + assert(result < m_bvCount); + + return result; +} + +//------------------------------------------------------------------------ +// IndexToLocal: get the local num for a bv index +// +// Arguments: +// bvIndex -- bit vector index +// +// Returns: +// local num +// +unsigned ObjectAllocator::IndexToLocal(unsigned bvIndex) +{ + assert(bvIndex < m_bvCount); + unsigned result = BAD_VAR_NUM; + + if (bvIndex < m_firstPseudoLocalIndex) + { + result = comp->lvaTrackedToVarNum[bvIndex]; + assert(IsTrackedLocal(result)); + } + else + { + result = m_firstPseudoLocalNum + (bvIndex - m_firstPseudoLocalIndex); + } + + return result; +} + +#ifdef DEBUG +//------------------------------------------------------------------------------ +// DumpIndex: write a description of a given bv index +// +// Arguments: +// bvIndex - index to describe +// +// Notes: +// includes leading space +// +void ObjectAllocator::DumpIndex(unsigned bvIndex) +{ + const unsigned lclNum = IndexToLocal(bvIndex); + const bool isLocalVar = (lclNum < m_firstPseudoLocalNum); + printf(" %c%02u", isLocalVar ? 'V' : 'P', lclNum); +} +#endif + //------------------------------------------------------------------------ // DoPhase: Run analysis (if object stack allocation is enabled) and then // morph each GT_ALLOCOBJ node either into an allocation helper @@ -101,7 +270,8 @@ PhaseStatus ObjectAllocator::DoPhase() void ObjectAllocator::MarkLclVarAsEscaping(unsigned int lclNum) { - BitVecOps::AddElemD(&m_bitVecTraits, m_EscapingPointers, lclNum); + const unsigned bvIndex = LocalToIndex(lclNum); + BitVecOps::AddElemD(&m_bitVecTraits, m_EscapingPointers, bvIndex); } //------------------------------------------------------------------------------ @@ -114,7 +284,8 @@ void ObjectAllocator::MarkLclVarAsEscaping(unsigned int lclNum) void ObjectAllocator::MarkLclVarAsPossiblyStackPointing(unsigned int lclNum) { - BitVecOps::AddElemD(&m_bitVecTraits, m_PossiblyStackPointingPointers, lclNum); + const unsigned bvIndex = LocalToIndex(lclNum); + BitVecOps::AddElemD(&m_bitVecTraits, m_PossiblyStackPointingPointers, bvIndex); } //------------------------------------------------------------------------------ @@ -127,7 +298,9 @@ void ObjectAllocator::MarkLclVarAsPossiblyStackPointing(unsigned int lclNum) void ObjectAllocator::MarkLclVarAsDefinitelyStackPointing(unsigned int lclNum) { - BitVecOps::AddElemD(&m_bitVecTraits, m_DefinitelyStackPointingPointers, lclNum); + const unsigned bvIndex = LocalToIndex(lclNum); + JITDUMP("Marking V%02u (0x%02x) as definitely stack-pointing\n", lclNum, bvIndex); + BitVecOps::AddElemD(&m_bitVecTraits, m_DefinitelyStackPointingPointers, bvIndex); } //------------------------------------------------------------------------------ @@ -140,23 +313,188 @@ void ObjectAllocator::MarkLclVarAsDefinitelyStackPointing(unsigned int lclNum) void ObjectAllocator::AddConnGraphEdge(unsigned int sourceLclNum, unsigned int targetLclNum) { - BitVecOps::AddElemD(&m_bitVecTraits, m_ConnGraphAdjacencyMatrix[sourceLclNum], targetLclNum); + const unsigned sourceBvIndex = LocalToIndex(sourceLclNum); + const unsigned targetBvIndex = LocalToIndex(targetLclNum); + BitVecOps::AddElemD(&m_bitVecTraits, m_ConnGraphAdjacencyMatrix[sourceBvIndex], targetBvIndex); +} + +//------------------------------------------------------------------------ +// PrepareAnalysis: determine how to model the escape analysis problem +// with bit vectors. +// +void ObjectAllocator::PrepareAnalysis() +{ + // Determine how locals map to indicies in the bit vectors / connection graph. + // + // In "lcl num" space + // + // We reserve the range [0...L-1] for the initial set of locals. + // Here L is the initial lvaCount. + // + // If conditional escape analysis is enabled, we reserve the range [L...L+M-1] + // for locals allocated during the conditional escape analysis expansions, + // where M is the maximum number of pseudo-vars. + // + // We reserve the range [L+M ... L+2M-1] for pseudo locals themselves. + // + // In "bv" space + // + // We reserve the range [0...N-1] for the initial set of tracked locals. + // Here N <= L is the number of tracked locals, determined below, an each + // tracked local has an index assigned in this range. + // + // If conditional escape analysis is enabled, we reserve the range [N...N+M-1] + // for locals allocated during the conditional escape analysis expansions, + // where N is the maximum number of pseudo-vars. + // + // We reserve the range [N+M ... N+2M-1] for pseudo locals themselves. + // + // LocalToIndex translates from "lcl num" space to "bv" space + // IndexToLocal translates from "bv" space space to "lcl num" space + // + const unsigned localCount = comp->lvaCount; + unsigned bvNext = 0; + + // Enumerate which locals are going to appear in our connection + // graph, and assign them BV indicies. + // + for (unsigned lclNum = 0; lclNum < localCount; lclNum++) + { + LclVarDsc* const varDsc = comp->lvaGetDesc(lclNum); + + if (IsTrackedType(varDsc->TypeGet())) + { + varDsc->lvTracked = 1; + varDsc->lvVarIndex = (unsigned short)bvNext; + bvNext++; + } + else + { + varDsc->lvTracked = 0; + varDsc->lvVarIndex = 0; + } + } + + m_nextLocalIndex = bvNext; + + // If we are going to do any conditional escape analysis, determine + // how much extra BV space we'll need. + // + bool const hasEnumeratorLocals = comp->hasImpEnumeratorGdvLocalMap(); + + if (hasEnumeratorLocals) + { + unsigned const enumeratorLocalCount = comp->getImpEnumeratorGdvLocalMap()->GetCount(); + assert(enumeratorLocalCount > 0); + + // For now, disable conditional escape analysis with OSR + // since the dominance picture is muddled at this point. + // + // The conditionally escaping allocation sites will likely be in loops anyways. + // + bool const enableConditionalEscape = JitConfig.JitObjectStackAllocationConditionalEscape() > 0; + bool const isOSR = comp->opts.IsOSR(); + + if (enableConditionalEscape && !isOSR) + { + +#ifdef DEBUG + static ConfigMethodRange JitObjectStackAllocationConditionalEscapeRange; + JitObjectStackAllocationConditionalEscapeRange.EnsureInit( + JitConfig.JitObjectStackAllocationConditionalEscapeRange()); + const unsigned hash = comp->info.compMethodHash(); + const bool inRange = JitObjectStackAllocationConditionalEscapeRange.Contains(hash); +#else + const bool inRange = true; +#endif + + if (inRange) + { + JITDUMP("Enabling conditional escape analysis [%u pseudo-vars]\n", enumeratorLocalCount); + m_maxPseudoLocals = enumeratorLocalCount; + } + else + { + JITDUMP("Not enabling conditional escape analysis (disabled by range config)\n"); + } + } + else + { + JITDUMP("Not enabling conditional escape analysis [%u pseudo-vars]: %s\n", enumeratorLocalCount, + enableConditionalEscape ? "OSR" : "disabled by config"); + } + } + + // When we clone to prevent conditional escape, we'll also create a new local + // var that we will track. So we need to leave room for these vars. There can + // be as many of these as there are pseudo locals. + // + m_firstPseudoLocalNum = localCount + m_maxPseudoLocals; // L + M, per above + m_firstPseudoLocalIndex = bvNext + m_maxPseudoLocals; // N, per above + bvNext += 2 * m_maxPseudoLocals; + + // Now set up the BV traits. + // + m_bvCount = bvNext; + m_bitVecTraits = BitVecTraits(m_bvCount, comp); + + // Create the reverse mapping from bvIndex to local var index + // (leave room for locals we may allocate) + // + if (comp->lvaTrackedToVarNumSize < m_firstPseudoLocalNum) + { + comp->lvaTrackedToVarNumSize = m_firstPseudoLocalNum; + comp->lvaTrackedToVarNum = new (comp->getAllocator(CMK_LvaTable)) unsigned[comp->lvaTrackedToVarNumSize]; + } + + for (unsigned lclNum = 0; lclNum < localCount; lclNum++) + { + LclVarDsc* const varDsc = comp->lvaGetDesc(lclNum); + + if (varDsc->lvTracked) + { + comp->lvaTrackedToVarNum[varDsc->lvVarIndex] = lclNum; + } + } + + JITDUMP("%u locals, %u tracked by escape analysis\n", localCount, m_nextLocalIndex); + + if (m_nextLocalIndex > 0) + { + JITDUMP("\nLocal var range [%02u...%02u]\n", 0, localCount); + if (m_maxPseudoLocals > 0) + { + JITDUMP("Enumerator var range [%02u...%02u]\n", localCount, localCount + m_maxPseudoLocals - 1); + JITDUMP("Pseudo var range [%02u...%02u]\n", m_firstPseudoLocalNum, + m_firstPseudoLocalNum + m_maxPseudoLocals - 1); + } + + JITDUMP("\nLocal var bv range [%02u...%02u]\n", 0, m_nextLocalIndex - 1); + if (m_maxPseudoLocals > 0) + { + JITDUMP("Enumerator var bv range [%02u...%02u]\n", m_nextLocalIndex, + m_nextLocalIndex + m_maxPseudoLocals - 1); + JITDUMP("Pseudo var bv range [%02u...%02u]\n", m_nextLocalIndex + m_maxPseudoLocals, + m_nextLocalIndex + 2 * m_maxPseudoLocals - 1); + } + } } //------------------------------------------------------------------------ // DoAnalysis: Walk over basic blocks of the method and detect all local // variables that can be allocated on the stack. - +// void ObjectAllocator::DoAnalysis() { assert(m_IsObjectStackAllocationEnabled); assert(!m_AnalysisDone); - if (comp->lvaCount > 0) + PrepareAnalysis(); + + if (m_bvCount > 0) { - m_EscapingPointers = BitVecOps::MakeEmpty(&m_bitVecTraits); - m_ConnGraphAdjacencyMatrix = - new (comp->getAllocator(CMK_ObjectAllocator)) BitSetShortLongRep[comp->lvaCount + m_maxPseudoLocals + 1]; + m_EscapingPointers = BitVecOps::MakeEmpty(&m_bitVecTraits); + m_ConnGraphAdjacencyMatrix = new (comp->getAllocator(CMK_ObjectAllocator)) BitSetShortLongRep[m_bvCount]; // If we are doing conditional escape analysis, we also need to compute dominance. // @@ -263,28 +601,24 @@ void ObjectAllocator::MarkEscapingVarsAndBuildConnGraph() for (unsigned int lclNum = 0; lclNum < comp->lvaCount; ++lclNum) { - var_types type = comp->lvaTable[lclNum].TypeGet(); - - if (type == TYP_REF || genActualType(type) == TYP_I_IMPL || type == TYP_BYREF) + if (!IsTrackedLocal(lclNum)) { - m_ConnGraphAdjacencyMatrix[lclNum] = BitVecOps::MakeEmpty(&m_bitVecTraits); - - if (comp->lvaTable[lclNum].IsAddressExposed()) - { - JITDUMP(" V%02u is address exposed\n", lclNum); - MarkLclVarAsEscaping(lclNum); - } + continue; } - else + + const unsigned bvIndex = LocalToIndex(lclNum); + m_ConnGraphAdjacencyMatrix[bvIndex] = BitVecOps::MakeEmpty(&m_bitVecTraits); + + if (comp->lvaTable[lclNum].IsAddressExposed()) { - // Variable that may not point to objects will not participate in our analysis. - m_ConnGraphAdjacencyMatrix[lclNum] = BitVecOps::UninitVal(); + JITDUMP(" V%02u is address exposed\n", lclNum); + MarkLclVarAsEscaping(lclNum); } } for (unsigned int p = 0; p < m_maxPseudoLocals; p++) { - m_ConnGraphAdjacencyMatrix[p + comp->lvaCount] = BitVecOps::MakeEmpty(&m_bitVecTraits); + m_ConnGraphAdjacencyMatrix[p + m_firstPseudoLocalIndex] = BitVecOps::MakeEmpty(&m_bitVecTraits); } // We should have computed the DFS tree already. @@ -321,29 +655,29 @@ void ObjectAllocator::ComputeEscapingNodes(BitVecTraits* bitVecTraits, BitVec& e JITDUMP("\nComputing escape closure\n\n"); bool doOneMoreIteration = true; BitSetShortLongRep newEscapingNodes = BitVecOps::UninitVal(); - unsigned int lclNum; + unsigned int lclIndex; while (doOneMoreIteration) { BitVecOps::Iter iterator(bitVecTraits, escapingNodesToProcess); doOneMoreIteration = false; - while (iterator.NextElem(&lclNum)) + while (iterator.NextElem(&lclIndex)) { - if (m_ConnGraphAdjacencyMatrix[lclNum] != nullptr) + if (m_ConnGraphAdjacencyMatrix[lclIndex] != nullptr) { doOneMoreIteration = true; // newEscapingNodes = adjacentNodes[lclNum] - BitVecOps::Assign(bitVecTraits, newEscapingNodes, m_ConnGraphAdjacencyMatrix[lclNum]); + BitVecOps::Assign(bitVecTraits, newEscapingNodes, m_ConnGraphAdjacencyMatrix[lclIndex]); // newEscapingNodes = newEscapingNodes \ escapingNodes BitVecOps::DiffD(bitVecTraits, newEscapingNodes, escapingNodes); // escapingNodesToProcess = escapingNodesToProcess U newEscapingNodes BitVecOps::UnionD(bitVecTraits, escapingNodesToProcess, newEscapingNodes); // escapingNodes = escapingNodes U newEscapingNodes BitVecOps::UnionD(bitVecTraits, escapingNodes, newEscapingNodes); - // escapingNodesToProcess = escapingNodesToProcess \ { lclNum } - BitVecOps::RemoveElemD(bitVecTraits, escapingNodesToProcess, lclNum); + // escapingNodesToProcess = escapingNodesToProcess \ { lclIndex } + BitVecOps::RemoveElemD(bitVecTraits, escapingNodesToProcess, lclIndex); #ifdef DEBUG // Print the first witness to new escapes. @@ -351,12 +685,13 @@ void ObjectAllocator::ComputeEscapingNodes(BitVecTraits* bitVecTraits, BitVec& e if (!BitVecOps::IsEmpty(bitVecTraits, newEscapingNodes)) { BitVecOps::Iter iterator(bitVecTraits, newEscapingNodes); - unsigned int newLclNum; - while (iterator.NextElem(&newLclNum)) + unsigned int newLclIndex; + while (iterator.NextElem(&newLclIndex)) { - // Note P's never are sources of assignments... - JITDUMP("%c%02u causes V%02u to escape\n", lclNum >= comp->lvaCount ? 'P' : 'V', lclNum, - newLclNum); + JITDUMPEXEC(DumpIndex(lclIndex)); + JITDUMP(" causes "); + JITDUMPEXEC(DumpIndex(newLclIndex)); + JITDUMP(" to escape\n"); } } #endif @@ -395,70 +730,203 @@ void ObjectAllocator::ComputeStackObjectPointers(BitVecTraits* bitVecTraits) changed = false; for (unsigned int lclNum = 0; lclNum < comp->lvaCount; ++lclNum) { - LclVarDsc* lclVarDsc = comp->lvaGetDesc(lclNum); - var_types type = lclVarDsc->TypeGet(); + if (!IsTrackedLocal(lclNum)) + { + continue; + } + + const unsigned lclIndex = LocalToIndex(lclNum); - if (type == TYP_REF || type == TYP_I_IMPL || type == TYP_BYREF) + if (!MayLclVarPointToStack(lclNum) && + !BitVecOps::IsEmptyIntersection(bitVecTraits, m_PossiblyStackPointingPointers, + m_ConnGraphAdjacencyMatrix[lclIndex])) { - if (!MayLclVarPointToStack(lclNum) && - !BitVecOps::IsEmptyIntersection(bitVecTraits, m_PossiblyStackPointingPointers, - m_ConnGraphAdjacencyMatrix[lclNum])) - { - // We discovered a new pointer that may point to the stack. - MarkLclVarAsPossiblyStackPointing(lclNum); + // We discovered a new pointer that may point to the stack. + MarkLclVarAsPossiblyStackPointing(lclNum); - // Check if this pointer always points to the stack. - // For OSR the reference may be pointing at the heap-allocated Tier0 version. - // - if ((lclVarDsc->lvSingleDef == 1) && !comp->opts.IsOSR()) + // Check if this pointer always points to the stack. + // For OSR the reference may be pointing at the heap-allocated Tier0 version. + // + LclVarDsc* lclVarDsc = comp->lvaGetDesc(lclNum); + + if ((lclVarDsc->lvSingleDef == 1) && !comp->opts.IsOSR()) + { + // Check if we know what is assigned to this pointer. + unsigned bitCount = BitVecOps::Count(bitVecTraits, m_ConnGraphAdjacencyMatrix[lclIndex]); + assert(bitCount <= 1); + if (bitCount == 1) { - // Check if we know what is assigned to this pointer. - unsigned bitCount = BitVecOps::Count(bitVecTraits, m_ConnGraphAdjacencyMatrix[lclNum]); - assert(bitCount <= 1); - if (bitCount == 1) + BitVecOps::Iter iter(bitVecTraits, m_ConnGraphAdjacencyMatrix[lclIndex]); + unsigned rhsLclIndex = 0; + iter.NextElem(&rhsLclIndex); + unsigned rhsLclNum = IndexToLocal(rhsLclIndex); + if (DoesLclVarPointToStack(rhsLclNum)) { - BitVecOps::Iter iter(bitVecTraits, m_ConnGraphAdjacencyMatrix[lclNum]); - unsigned rhsLclNum = 0; - iter.NextElem(&rhsLclNum); - - if (DoesLclVarPointToStack(rhsLclNum)) - { - // The only store to lclNum local is the definitely-stack-pointing - // rhsLclNum local so lclNum local is also definitely-stack-pointing. - MarkLclVarAsDefinitelyStackPointing(lclNum); - } + // The only store to lclNum local is the definitely-stack-pointing + // rhsLclNum local so lclNum local is also definitely-stack-pointing. + MarkLclVarAsDefinitelyStackPointing(lclNum); } } - changed = true; } + changed = true; } } } - JITDUMP("Definitely stack-pointing locals:"); +#ifdef DEBUG + if (comp->verbose) { - BitVecOps::Iter iter(bitVecTraits, m_DefinitelyStackPointingPointers); - unsigned lclNum = 0; - while (iter.NextElem(&lclNum)) + printf("Definitely stack-pointing locals:"); + { + BitVecOps::Iter iter(bitVecTraits, m_DefinitelyStackPointingPointers); + unsigned lclIndex = 0; + while (iter.NextElem(&lclIndex)) + { + DumpIndex(lclIndex); + } + printf("\n"); + } + + printf("Possibly stack-pointing locals:"); { - JITDUMP(" V%02u", lclNum); + BitVecOps::Iter iter(bitVecTraits, m_PossiblyStackPointingPointers); + unsigned lclIndex = 0; + while (iter.NextElem(&lclIndex)) + { + if (!BitVecOps::IsMember(bitVecTraits, m_DefinitelyStackPointingPointers, lclIndex)) + { + DumpIndex(lclIndex); + } + } + printf("\n"); } - JITDUMP("\n"); } +#endif +} + +//------------------------------------------------------------------------ +// CanAllocateLclVarOnStack: Returns true iff local variable can be +// allocated on the stack. +// +// Arguments: +// lclNum - Local variable number +// clsHnd - Class/struct handle of the variable class +// allocType - Type of allocation (newobj or newarr) +// length - Length of the array (for newarr) +// blockSize - [out, optional] exact size of the object +// reason - [out, required] if result is false, reason why +// preliminaryCheck - if true, allow checking before analysis is done +// (for things that inherently disqualify the local) +// +// Return Value: +// Returns true iff local variable can be allocated on the stack. +// +bool ObjectAllocator::CanAllocateLclVarOnStack(unsigned int lclNum, + CORINFO_CLASS_HANDLE clsHnd, + ObjectAllocationType allocType, + ssize_t length, + unsigned int* blockSize, + const char** reason, + bool preliminaryCheck) +{ + assert(preliminaryCheck || m_AnalysisDone); + + bool enableBoxedValueClasses = true; + bool enableRefClasses = true; + bool enableArrays = true; + *reason = "[ok]"; - JITDUMP("Possibly stack-pointing locals:"); +#ifdef DEBUG + enableBoxedValueClasses = (JitConfig.JitObjectStackAllocationBoxedValueClass() != 0); + enableRefClasses = (JitConfig.JitObjectStackAllocationRefClass() != 0); + enableArrays = (JitConfig.JitObjectStackAllocationArray() != 0); +#endif + + unsigned classSize = 0; + + if (allocType == OAT_NEWARR) { - BitVecOps::Iter iter(bitVecTraits, m_PossiblyStackPointingPointers); - unsigned lclNum = 0; - while (iter.NextElem(&lclNum)) + if (!enableArrays) + { + *reason = "[disabled by config]"; + return false; + } + + if ((length < 0) || (length > CORINFO_Array_MaxLength)) + { + *reason = "[invalid array length]"; + return false; + } + + ClassLayout* const layout = comp->typGetArrayLayout(clsHnd, (unsigned)length); + classSize = layout->GetSize(); + } + else if (allocType == OAT_NEWOBJ) + { + if (comp->info.compCompHnd->isValueClass(clsHnd)) + { + if (!enableBoxedValueClasses) + { + *reason = "[disabled by config]"; + return false; + } + + if (comp->info.compCompHnd->getTypeForBoxOnStack(clsHnd) == NO_CLASS_HANDLE) + { + *reason = "[no boxed type available]"; + return false; + } + + classSize = comp->info.compCompHnd->getClassSize(clsHnd); + } + else { - if (!BitVecOps::IsMember(bitVecTraits, m_DefinitelyStackPointingPointers, lclNum)) + if (!enableRefClasses) { - JITDUMP(" V%02u", lclNum); + *reason = "[disabled by config]"; + return false; } + + if (!comp->info.compCompHnd->canAllocateOnStack(clsHnd)) + { + *reason = "[runtime disallows]"; + return false; + } + + classSize = comp->info.compCompHnd->getHeapClassSize(clsHnd); } - JITDUMP("\n"); } + else + { + assert(!"Unexpected allocation type"); + return false; + } + + if (classSize > m_StackAllocMaxSize) + { + *reason = "[too large]"; + return false; + } + + if (preliminaryCheck) + { + return true; + } + + const bool escapes = CanLclVarEscape(lclNum); + + if (escapes) + { + *reason = "[escapes]"; + return false; + } + + if (blockSize != nullptr) + { + *blockSize = classSize; + } + + return true; } //------------------------------------------------------------------------ @@ -1351,8 +1819,7 @@ void ObjectAllocator::RewriteUses() unsigned int newLclNum = BAD_VAR_NUM; LclVarDsc* lclVarDsc = m_compiler->lvaGetDesc(lclNum); - if ((lclNum < BitVecTraits::GetSize(&m_allocator->m_bitVecTraits)) && - m_allocator->MayLclVarPointToStack(lclNum)) + if (m_allocator->MayLclVarPointToStack(lclNum)) { // Analysis does not handle indirect access to pointer locals. assert(tree->OperIsScalarLocal()); @@ -1539,7 +2006,7 @@ bool ObjectAllocator::AnalyzeIfCloningCanPreventEscape(BitVecTraits* bitVecTrait for (unsigned p = 0; p < m_numPseudoLocals; p++) { - unsigned const pseudoLocal = p + comp->lvaCount; + unsigned const pseudoLocal = p + m_firstPseudoLocalNum; bool canClone = true; CloneInfo* info = nullptr; @@ -1553,8 +2020,9 @@ bool ObjectAllocator::AnalyzeIfCloningCanPreventEscape(BitVecTraits* bitVecTrait break; } - unsigned lclNum = BAD_VAR_NUM; - BitVec pseudoLocalAdjacencies = m_ConnGraphAdjacencyMatrix[pseudoLocal]; + // See what locals were "assigned" to the pseudo local. + // + BitVec pseudoLocalAdjacencies = m_ConnGraphAdjacencyMatrix[LocalToIndex(pseudoLocal)]; // If we found an allocation but didn't find any conditionally escaping uses, then cloning is of no use // @@ -1568,14 +2036,15 @@ bool ObjectAllocator::AnalyzeIfCloningCanPreventEscape(BitVecTraits* bitVecTrait // Check if each conditionally escaping local escapes on its own; if so cloning is of no use // BitVecOps::Iter iterator(bitVecTraits, pseudoLocalAdjacencies); - while (canClone && iterator.NextElem(&lclNum)) + unsigned lclNumIndex = BAD_VAR_NUM; + while (canClone && iterator.NextElem(&lclNumIndex)) { - if (BitVecOps::IsMember(bitVecTraits, escapingNodes, lclNum)) + if (BitVecOps::IsMember(bitVecTraits, escapingNodes, lclNumIndex)) { // The enumerator var or a related var had escaping uses somewhere in the method, // not under a failing GDV or any GDV. // - JITDUMP(" V%02u escapes independently of P%02u\n", lclNum, pseudoLocal); + JITDUMP(" V%02u escapes independently of P%02u\n", IndexToLocal(lclNumIndex), pseudoLocal); canClone = false; break; } @@ -1583,11 +2052,11 @@ bool ObjectAllocator::AnalyzeIfCloningCanPreventEscape(BitVecTraits* bitVecTrait // Also check the alloc temps // - if (info->m_allocTemps != nullptr) + if (canClone && (info->m_allocTemps != nullptr)) { for (unsigned v : *(info->m_allocTemps)) { - if (BitVecOps::IsMember(bitVecTraits, escapingNodes, v)) + if (BitVecOps::IsMember(bitVecTraits, escapingNodes, LocalToIndex(v))) { JITDUMP(" alloc temp V%02u escapes independently of P%02u\n", v, pseudoLocal) canClone = false; @@ -1601,7 +2070,7 @@ bool ObjectAllocator::AnalyzeIfCloningCanPreventEscape(BitVecTraits* bitVecTrait // We may be able to clone and specialize the enumerator uses to ensure // that the allocated enumerator does not escape. // - JITDUMP(" P%02u is guarding the escape of V%02u\n", pseudoLocal, lclNum); + JITDUMP(" P%02u is guarding the escape of V%02u\n", pseudoLocal, info->m_local); if (info->m_allocTemps != nullptr) { JITDUMP(" along with "); @@ -1650,7 +2119,7 @@ bool ObjectAllocator::AnalyzeIfCloningCanPreventEscape(BitVecTraits* bitVecTrait { JITDUMP(" not optimizing, so will mark P%02u as escaping\n", pseudoLocal); MarkLclVarAsEscaping(pseudoLocal); - BitVecOps::AddElemD(bitVecTraits, escapingNodesToProcess, pseudoLocal); + BitVecOps::AddElemD(bitVecTraits, escapingNodesToProcess, LocalToIndex(pseudoLocal)); newEscapes = true; } } @@ -1669,7 +2138,7 @@ unsigned ObjectAllocator::NewPseudoLocal() unsigned result = BAD_VAR_NUM; if (m_numPseudoLocals < m_maxPseudoLocals) { - result = comp->lvaCount + m_numPseudoLocals; + result = m_firstPseudoLocalNum + m_numPseudoLocals; m_numPseudoLocals++; } return result; @@ -2937,10 +3406,22 @@ void ObjectAllocator::CloneAndSpecialize(CloneInfo* info) // Type for now as TYP_REF; this will get rewritten later during RewriteUses // - comp->lvaTable[newEnumeratorLocal].lvType = TYP_REF; - comp->lvaTable[newEnumeratorLocal].lvSingleDef = 1; + LclVarDsc* const newEnumeratorDsc = comp->lvaGetDesc(newEnumeratorLocal); + + newEnumeratorDsc->lvType = TYP_REF; + newEnumeratorDsc->lvSingleDef = 1; comp->lvaSetClass(newEnumeratorLocal, info->m_type, /* isExact */ true); + newEnumeratorDsc->lvTracked = 1; + newEnumeratorDsc->lvVarIndex = (unsigned short)m_nextLocalIndex; // grr + assert(newEnumeratorDsc->lvVarIndex < comp->lvaTrackedToVarNumSize); + comp->lvaTrackedToVarNum[newEnumeratorDsc->lvVarIndex] = newEnumeratorLocal; + m_nextLocalIndex++; + assert(m_maxPseudoLocals > 0); + assert(newEnumeratorDsc->lvVarIndex < m_firstPseudoLocalIndex); + + JITDUMP("Tracking V%02u via 0x%02x\n", newEnumeratorLocal, newEnumeratorDsc->lvVarIndex); + class ReplaceVisitor final : public GenTreeVisitor { CloneInfo* m_info; diff --git a/src/coreclr/jit/objectalloc.h b/src/coreclr/jit/objectalloc.h index 99dd8965924669..d7a59bb33a85d7 100644 --- a/src/coreclr/jit/objectalloc.h +++ b/src/coreclr/jit/objectalloc.h @@ -125,6 +125,7 @@ class ObjectAllocator final : public Phase // Data members bool m_IsObjectStackAllocationEnabled; bool m_AnalysisDone; + unsigned m_bvCount; BitVecTraits m_bitVecTraits; BitVec m_EscapingPointers; // We keep the set of possibly-stack-pointing pointers as a superset of the set of @@ -138,8 +139,11 @@ class ObjectAllocator final : public Phase // Info for conditionally-escaping locals LocalToLocalMap m_EnumeratorLocalToPseudoLocalMap; CloneMap m_CloneMap; - unsigned m_maxPseudoLocals; + unsigned m_nextLocalIndex; + unsigned m_firstPseudoLocalNum; + unsigned m_firstPseudoLocalIndex; unsigned m_numPseudoLocals; + unsigned m_maxPseudoLocals; unsigned m_regionsToClone; //=============================================================================== @@ -160,11 +164,17 @@ class ObjectAllocator final : public Phase virtual PhaseStatus DoPhase() override; private: + bool IsTrackedType(var_types type); + bool IsTrackedLocal(unsigned lclNum); + bool HasIndex(unsigned lclNum); + unsigned LocalToIndex(unsigned lclNum); + unsigned IndexToLocal(unsigned bvIndex); bool CanLclVarEscape(unsigned int lclNum); void MarkLclVarAsPossiblyStackPointing(unsigned int lclNum); void MarkLclVarAsDefinitelyStackPointing(unsigned int lclNum); bool MayLclVarPointToStack(unsigned int lclNum); bool DoesLclVarPointToStack(unsigned int lclNum); + void PrepareAnalysis(); void DoAnalysis(); void MarkLclVarAsEscaping(unsigned int lclNum); void MarkEscapingVarsAndBuildConnGraph(); @@ -212,79 +222,11 @@ class ObjectAllocator final : public Phase void CloneAndSpecialize(); static const unsigned int s_StackAllocMaxSize = 0x2000U; -}; - -//=============================================================================== - -inline ObjectAllocator::ObjectAllocator(Compiler* comp) - : Phase(comp, PHASE_ALLOCATE_OBJECTS) - , m_IsObjectStackAllocationEnabled(false) - , m_AnalysisDone(false) - , m_bitVecTraits(BitVecTraits(comp->lvaCount, comp)) - , m_HeapLocalToStackLocalMap(comp->getAllocator(CMK_ObjectAllocator)) - , m_EnumeratorLocalToPseudoLocalMap(comp->getAllocator(CMK_ObjectAllocator)) - , m_CloneMap(comp->getAllocator(CMK_ObjectAllocator)) - , m_maxPseudoLocals(0) - , m_numPseudoLocals(0) - , m_regionsToClone(0) - -{ - // If we are going to do any conditional escape analysis, allocate - // extra BV space for the "pseudo" locals we'll need. - // - // For now, disable conditional escape analysis with OSR - // since the dominance picture is muddled at this point. - // - // The conditionally escaping allocation sites will likely be in loops anyways. - // - bool const hasEnumeratorLocals = comp->hasImpEnumeratorGdvLocalMap(); - - if (hasEnumeratorLocals) - { - unsigned const enumeratorLocalCount = comp->getImpEnumeratorGdvLocalMap()->GetCount(); - assert(enumeratorLocalCount > 0); - - bool const enableConditionalEscape = JitConfig.JitObjectStackAllocationConditionalEscape() > 0; - bool const isOSR = comp->opts.IsOSR(); - - if (enableConditionalEscape && !isOSR) - { #ifdef DEBUG - static ConfigMethodRange JitObjectStackAllocationConditionalEscapeRange; - JitObjectStackAllocationConditionalEscapeRange.EnsureInit( - JitConfig.JitObjectStackAllocationConditionalEscapeRange()); - const unsigned hash = comp->info.compMethodHash(); - const bool inRange = JitObjectStackAllocationConditionalEscapeRange.Contains(hash); -#else - const bool inRange = true; + void DumpIndex(unsigned bvIndex); #endif - - if (inRange) - { - m_maxPseudoLocals = enumeratorLocalCount; - m_bitVecTraits = BitVecTraits(comp->lvaCount + enumeratorLocalCount + 1, comp); - JITDUMP("Enabling conditional escape analysis [%u pseudo-vars]\n", enumeratorLocalCount); - } - else - { - JITDUMP("Not enabling conditional escape analysis (disabled by range config)\n"); - } - } - else - { - JITDUMP("Not enabling conditional escape analysis [%u pseudo-vars]: %s\n", enumeratorLocalCount, - enableConditionalEscape ? "OSR" : "disabled by config"); - } - } - - m_EscapingPointers = BitVecOps::UninitVal(); - m_PossiblyStackPointingPointers = BitVecOps::UninitVal(); - m_DefinitelyStackPointingPointers = BitVecOps::UninitVal(); - m_ConnGraphAdjacencyMatrix = nullptr; - - m_StackAllocMaxSize = (unsigned)JitConfig.JitObjectStackAllocationSize(); -} +}; //------------------------------------------------------------------------ // IsObjectStackAllocationEnabled: Returns true iff object stack allocation is enabled @@ -305,131 +247,6 @@ inline void ObjectAllocator::EnableObjectStackAllocation() m_IsObjectStackAllocationEnabled = true; } -//------------------------------------------------------------------------ -// CanAllocateLclVarOnStack: Returns true iff local variable can be -// allocated on the stack. -// -// Arguments: -// lclNum - Local variable number -// clsHnd - Class/struct handle of the variable class -// allocType - Type of allocation (newobj or newarr) -// length - Length of the array (for newarr) -// blockSize - [out, optional] exact size of the object -// reason - [out, required] if result is false, reason why -// preliminaryCheck - if true, allow checking before analysis is done -// (for things that inherently disqualify the local) -// -// Return Value: -// Returns true iff local variable can be allocated on the stack. -// -inline bool ObjectAllocator::CanAllocateLclVarOnStack(unsigned int lclNum, - CORINFO_CLASS_HANDLE clsHnd, - ObjectAllocationType allocType, - ssize_t length, - unsigned int* blockSize, - const char** reason, - bool preliminaryCheck) -{ - assert(preliminaryCheck || m_AnalysisDone); - - bool enableBoxedValueClasses = true; - bool enableRefClasses = true; - bool enableArrays = true; - *reason = "[ok]"; - -#ifdef DEBUG - enableBoxedValueClasses = (JitConfig.JitObjectStackAllocationBoxedValueClass() != 0); - enableRefClasses = (JitConfig.JitObjectStackAllocationRefClass() != 0); - enableArrays = (JitConfig.JitObjectStackAllocationArray() != 0); -#endif - - unsigned classSize = 0; - - if (allocType == OAT_NEWARR) - { - if (!enableArrays) - { - *reason = "[disabled by config]"; - return false; - } - - if ((length < 0) || (length > CORINFO_Array_MaxLength)) - { - *reason = "[invalid array length]"; - return false; - } - - ClassLayout* const layout = comp->typGetArrayLayout(clsHnd, (unsigned)length); - classSize = layout->GetSize(); - } - else if (allocType == OAT_NEWOBJ) - { - if (comp->info.compCompHnd->isValueClass(clsHnd)) - { - if (!enableBoxedValueClasses) - { - *reason = "[disabled by config]"; - return false; - } - - if (comp->info.compCompHnd->getTypeForBoxOnStack(clsHnd) == NO_CLASS_HANDLE) - { - *reason = "[no boxed type available]"; - return false; - } - - classSize = comp->info.compCompHnd->getClassSize(clsHnd); - } - else - { - if (!enableRefClasses) - { - *reason = "[disabled by config]"; - return false; - } - - if (!comp->info.compCompHnd->canAllocateOnStack(clsHnd)) - { - *reason = "[runtime disallows]"; - return false; - } - - classSize = comp->info.compCompHnd->getHeapClassSize(clsHnd); - } - } - else - { - assert(!"Unexpected allocation type"); - return false; - } - - if (classSize > m_StackAllocMaxSize) - { - *reason = "[too large]"; - return false; - } - - if (preliminaryCheck) - { - return true; - } - - const bool escapes = CanLclVarEscape(lclNum); - - if (escapes) - { - *reason = "[escapes]"; - return false; - } - - if (blockSize != nullptr) - { - *blockSize = classSize; - } - - return true; -} - //------------------------------------------------------------------------ // CanLclVarEscape: Returns true iff local variable can // potentially escape from the method @@ -442,7 +259,13 @@ inline bool ObjectAllocator::CanAllocateLclVarOnStack(unsigned int lclNu inline bool ObjectAllocator::CanLclVarEscape(unsigned int lclNum) { - return BitVecOps::IsMember(&m_bitVecTraits, m_EscapingPointers, lclNum); + if (!HasIndex(lclNum)) + { + return true; + } + + const unsigned bvIndex = LocalToIndex(lclNum); + return BitVecOps::IsMember(&m_bitVecTraits, m_EscapingPointers, bvIndex); } //------------------------------------------------------------------------ @@ -458,7 +281,14 @@ inline bool ObjectAllocator::CanLclVarEscape(unsigned int lclNum) inline bool ObjectAllocator::MayLclVarPointToStack(unsigned int lclNum) { assert(m_AnalysisDone); - return BitVecOps::IsMember(&m_bitVecTraits, m_PossiblyStackPointingPointers, lclNum); + + if (!HasIndex(lclNum)) + { + return false; + } + + const unsigned bvIndex = LocalToIndex(lclNum); + return BitVecOps::IsMember(&m_bitVecTraits, m_PossiblyStackPointingPointers, bvIndex); } //------------------------------------------------------------------------ @@ -475,7 +305,14 @@ inline bool ObjectAllocator::MayLclVarPointToStack(unsigned int lclNum) inline bool ObjectAllocator::DoesLclVarPointToStack(unsigned int lclNum) { assert(m_AnalysisDone); - return BitVecOps::IsMember(&m_bitVecTraits, m_DefinitelyStackPointingPointers, lclNum); + + if (!HasIndex(lclNum)) + { + return false; + } + + const unsigned bvIndex = LocalToIndex(lclNum); + return BitVecOps::IsMember(&m_bitVecTraits, m_DefinitelyStackPointingPointers, bvIndex); } //=============================================================================== diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 164f53dda6b2f4..10abc319b6184f 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -2368,30 +2368,38 @@ PhaseStatus Compiler::optInvertLoops() } //----------------------------------------------------------------------------- -// optOptimizeFlow: simplify flow graph +// optOptimizeFlow: Simplify flowgraph, and run a few flow optimizations // // Returns: // suitable phase status // -// Notes: -// Does not do profile-based reordering to try and ensure that -// that we recognize and represent as many loops as possible. -// PhaseStatus Compiler::optOptimizeFlow() { noway_assert(opts.OptimizationEnabled()); - fgUpdateFlowGraph(/* doTailDuplication */ true); - fgReorderBlocks(/* useProfile */ false); + bool modified = fgUpdateFlowGraph(/* doTailDuplication */ true); - // fgReorderBlocks can cause IR changes even if it does not modify - // the flow graph. It calls gtPrepareCost which can cause operand swapping. - // Work around this for now. - // - // Note phase status only impacts dumping and checking done post-phase, - // it has no impact on a release build. - // - return PhaseStatus::MODIFIED_EVERYTHING; + // Skipping fgExpandRarelyRunBlocks when we have PGO data incurs diffs if the profile is inconsistent, + // as it will propagate missing profile weights throughout the flowgraph. + // Running profile synthesis beforehand should get rid of these diffs. + // TODO: Always rely on profile synthesis to identify cold blocks. + modified |= fgExpandRarelyRunBlocks(); + + // Run branch optimizations for non-handler blocks. + assert(!fgFuncletsCreated); + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->Next()) + { + if (block->hasHndIndex()) + { + assert(bbIsHandlerBeg(block)); + block = ehGetDsc(block->getHndIndex())->ebdHndLast; + continue; + } + + modified |= fgOptimizeBranch(block); + } + + return modified ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } //----------------------------------------------------------------------------- @@ -2412,6 +2420,18 @@ PhaseStatus Compiler::optOptimizePreLayout() modified |= fgExpandRarelyRunBlocks(); } + // Run a late pass of unconditional-to-conditional branch optimization, skipping handler blocks. + for (BasicBlock* block = fgFirstBB; block != fgFirstFuncletBB; block = block->Next()) + { + if (!UsesFunclets() && block->hasHndIndex()) + { + block = ehGetDsc(block->getHndIndex())->ebdHndLast; + continue; + } + + modified |= fgOptimizeBranch(block); + } + return modified ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index bbd14401bc53eb..b1e3af0f917896 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -1307,6 +1307,13 @@ class LocalsUseVisitor : public GenTreeVisitor rep.LclNum = m_compiler->lvaGrabTemp(false DEBUGARG(rep.Description)); LclVarDsc* dsc = m_compiler->lvaGetDesc(rep.LclNum); dsc->lvType = rep.AccessType; + + // Are we promoting Span<>._length field? + if ((rep.Offset == OFFSETOF__CORINFO_Span__length) && (rep.AccessType == TYP_INT) && + m_compiler->lvaGetDesc(agg->LclNum)->IsSpan()) + { + dsc->SetIsNeverNegative(true); + } } #ifdef DEBUG diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index da035fd952559e..7d7e20fde9daff 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -637,7 +637,7 @@ void RangeCheck::MergeEdgeAssertions(GenTreeLclVarCommon* lcl, ASSERT_VALARG_TP // bool RangeCheck::TryGetRangeFromAssertions(Compiler* comp, ValueNum num, ASSERT_VALARG_TP assertions, Range* pRange) { - MergeEdgeAssertions(comp, num, num, assertions, pRange); + MergeEdgeAssertions(comp, num, ValueNumStore::NoVN, assertions, pRange, false); return !pRange->LowerLimit().IsUnknown() || !pRange->UpperLimit().IsUnknown(); } @@ -645,14 +645,19 @@ bool RangeCheck::TryGetRangeFromAssertions(Compiler* comp, ValueNum num, ASSERT_ // MergeEdgeAssertions: Merge assertions on the edge flowing into the block about a variable // // Arguments: -// comp - the compiler instance -// normalLclVN - the value number to look for assertions for -// preferredBoundVN - when this VN is set, it will be given preference over constant limits -// assertions - the assertions to use -// pRange - the range to tighten with assertions +// comp - the compiler instance +// normalLclVN - the value number to look for assertions for +// preferredBoundVN - when this VN is set, it will be given preference over constant limits +// assertions - the assertions to use +// pRange - the range to tighten with assertions +// canUseCheckedBounds - true if we can use checked bounds assertions (cache) // -void RangeCheck::MergeEdgeAssertions( - Compiler* comp, ValueNum normalLclVN, ValueNum preferredBoundVN, ASSERT_VALARG_TP assertions, Range* pRange) +void RangeCheck::MergeEdgeAssertions(Compiler* comp, + ValueNum normalLclVN, + ValueNum preferredBoundVN, + ASSERT_VALARG_TP assertions, + Range* pRange, + bool canUseCheckedBounds) { Range assertedRange = Range(Limit(Limit::keUnknown)); if (BitVecOps::IsEmpty(comp->apTraits, assertions)) @@ -680,7 +685,7 @@ void RangeCheck::MergeEdgeAssertions( bool isUnsigned = false; // Current assertion is of the form (i < len - cns) != 0 - if (curAssertion->IsCheckedBoundArithBound()) + if (canUseCheckedBounds && curAssertion->IsCheckedBoundArithBound()) { ValueNumStore::CompareCheckedBoundArithInfo info; @@ -709,7 +714,7 @@ void RangeCheck::MergeEdgeAssertions( cmpOper = (genTreeOps)info.cmpOper; } // Current assertion is of the form (i < len) != 0 - else if (curAssertion->IsCheckedBoundBound()) + else if (canUseCheckedBounds && curAssertion->IsCheckedBoundBound()) { ValueNumStore::CompareCheckedBoundArithInfo info; @@ -767,7 +772,7 @@ void RangeCheck::MergeEdgeAssertions( int cnstLimit = (int)curAssertion->op2.u1.iconVal; assert(cnstLimit == comp->vnStore->CoercedConstantValue(curAssertion->op2.vn)); - if ((cnstLimit == 0) && (curAssertion->assertionKind == Compiler::OAK_NOT_EQUAL) && + if ((cnstLimit == 0) && (curAssertion->assertionKind == Compiler::OAK_NOT_EQUAL) && canUseCheckedBounds && comp->vnStore->IsVNCheckedBound(curAssertion->op1.vn)) { // we have arr.Len != 0, so the length must be atleast one diff --git a/src/coreclr/jit/rangecheck.h b/src/coreclr/jit/rangecheck.h index 884687ce35ff9c..d90257a990bc2e 100644 --- a/src/coreclr/jit/rangecheck.h +++ b/src/coreclr/jit/rangecheck.h @@ -728,8 +728,12 @@ class RangeCheck void MergeEdgeAssertions(GenTreeLclVarCommon* lcl, ASSERT_VALARG_TP assertions, Range* pRange); // Inspect the assertions about the current ValueNum to refine pRange - static void MergeEdgeAssertions( - Compiler* comp, ValueNum num, ValueNum preferredBoundVN, ASSERT_VALARG_TP assertions, Range* pRange); + static void MergeEdgeAssertions(Compiler* comp, + ValueNum num, + ValueNum preferredBoundVN, + ASSERT_VALARG_TP assertions, + Range* pRange, + bool canUseCheckedBounds = true); // The maximum possible value of the given "limit". If such a value could not be determined // return "false". For example: CORINFO_Array_MaxLength for array length. diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index de23305c145b7f..9c7a8c6a112c28 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -341,11 +341,19 @@ void Rationalizer::RewriteHWIntrinsicAsUserCall(GenTree** use, ArrayStackgtFlags & GTF_REVERSE_OPS) == 0); // gtNewSimdShuffleNode with reverse ops is not supported GenTree* op1 = operands[0]; GenTree* op2 = operands[1]; - if (op2->IsCnsVec() && comp->IsValidForShuffle(op2->AsVecCon(), simdSize, simdBaseType)) + bool isShuffleNative = intrinsicId != NI_Vector128_Shuffle; +#if defined(TARGET_XARCH) + isShuffleNative = + isShuffleNative && (intrinsicId != NI_Vector256_Shuffle) && (intrinsicId != NI_Vector512_Shuffle); +#elif defined(TARGET_ARM64) + isShuffleNative = isShuffleNative && (intrinsicId != NI_Vector64_Shuffle); +#endif + + // Check if the required intrinsics to emit are available. + if (!comp->IsValidForShuffle(op2, simdSize, simdBaseType, nullptr, isShuffleNative)) { - result = comp->gtNewSimdShuffleNode(retType, op1, op2, simdBaseJitType, simdSize); + break; } + + result = comp->gtNewSimdShuffleNode(retType, op1, op2, simdBaseJitType, simdSize, isShuffleNative); break; } @@ -790,6 +810,13 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge } break; + case GT_BSWAP16: + if (node->gtGetOp1()->OperIs(GT_CAST)) + { + comp->fgSimpleLowerBswap16(BlockRange(), node); + } + break; + default: // Check that we don't have nodes not allowed in HIR here. assert((node->DebugOperKind() & DBK_NOTHIR) == 0); diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index cb4957a6b5f107..b8baab7d1825e9 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -239,6 +239,10 @@ typedef uint64_t regMaskSmall; #define HAS_MORE_THAN_64_REGISTERS 1 #endif // TARGET_ARM64 +#define REG_LOW_BASE 0 +#ifdef HAS_MORE_THAN_64_REGISTERS +#define REG_HIGH_BASE 64 +#endif // TODO: Rename regMaskSmall as RegSet64 (at least for 64-bit) typedef regMaskSmall SingleTypeRegSet; inline SingleTypeRegSet genSingleTypeRegMask(regNumber reg); diff --git a/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp b/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp index a0ca5a4c0081cc..9e6a65bc7d9a3f 100644 --- a/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp +++ b/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp @@ -6,7 +6,6 @@ #include "rhassert.h" #include "RedhawkWarnings.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp index 051b9b0d8f7a88..9db38fc25eb855 100644 --- a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp +++ b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp @@ -7,7 +7,6 @@ #include "gcinterface.dac.h" #include "rhassert.h" #include "TargetPtrs.h" -#include "varint.h" #include "PalRedhawkCommon.h" #include "PalRedhawk.h" #include "holder.h" diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp index a3643e32f5eaf7..f7a91492de8c6f 100644 --- a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp @@ -13,7 +13,6 @@ #include "GcEnum.h" #include "shash.h" #include "TypeManager.h" -#include "varint.h" #include "PalRedhawkCommon.h" #include "PalRedhawk.h" #include "holder.h" diff --git a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp index 91fd2db9260622..7ef489ddd33389 100644 --- a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp @@ -17,7 +17,6 @@ #include "PalRedhawkCommon.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "interoplibinterface.h" diff --git a/src/coreclr/nativeaot/Runtime/GcStressControl.cpp b/src/coreclr/nativeaot/Runtime/GcStressControl.cpp index 3d01748557580e..3f9853a3ea3b1e 100644 --- a/src/coreclr/nativeaot/Runtime/GcStressControl.cpp +++ b/src/coreclr/nativeaot/Runtime/GcStressControl.cpp @@ -15,7 +15,6 @@ #include "Crst.h" #include "RhConfig.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "forward_declarations.h" #include "StackFrameIterator.h" diff --git a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp index cd5f37e5199928..17bb554fa307d5 100644 --- a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp @@ -18,7 +18,6 @@ #include "rhbinder.h" #include "RuntimeInstance.h" #include "regdisplay.h" -#include "varint.h" #include "StackFrameIterator.h" #include "thread.h" #include "event.h" diff --git a/src/coreclr/nativeaot/Runtime/NativePrimitiveDecoder.h b/src/coreclr/nativeaot/Runtime/NativePrimitiveDecoder.h new file mode 100644 index 00000000000000..bbfd20b1ac4ad8 --- /dev/null +++ b/src/coreclr/nativeaot/Runtime/NativePrimitiveDecoder.h @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// C/C++ clone of NativePrimitiveDecoder.cs subset + +class NativePrimitiveDecoder +{ +public: + static uint32_t ReadUnsigned(uint8_t* & p) + { + uint32_t value = 0; + + uint32_t val = *p; + if ((val & 1) == 0) + { + value = (val >> 1); + p += 1; + } + else if ((val & 2) == 0) + { + value = (val >> 2) | + (*(p + 1) << 6); + p += 2; + } + else if ((val & 4) == 0) + { + value = (val >> 3) | + (*(p + 1) << 5) | + (*(p + 2) << 13); + p += 3; + } + else if ((val & 8) == 0) + { + value = (val >> 4) | + (*(p + 1) << 4) | + (*(p + 2) << 12) | + (*(p + 3) << 20); + p += 4; + } + else + { + value = *(p+1) | (*(p+2) << 8) | (*(p+3) << 16) | (*(p+4) << 24); + p += 5; + } + + return value; + } + + static int32_t ReadInt32(uint8_t* & p) + { + int32_t value = *p | (*(p+1) << 8) | (*(p+2) << 16) | (*(p+3) << 24); + p += 4; + return value; + } + + static uint32_t ReadUInt32(uint8_t* & p) + { + uint32_t value = *p | (*(p+1) << 8) | (*(p+2) << 16) | (*(p+3) << 24); + p += 4; + return value; + } +}; diff --git a/src/coreclr/nativeaot/Runtime/RestrictedCallouts.cpp b/src/coreclr/nativeaot/Runtime/RestrictedCallouts.cpp index 56e673217967fa..cf2cbf5df66934 100644 --- a/src/coreclr/nativeaot/Runtime/RestrictedCallouts.cpp +++ b/src/coreclr/nativeaot/Runtime/RestrictedCallouts.cpp @@ -22,7 +22,6 @@ #include "MethodTable.h" #include "ObjectLayout.h" #include "event.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp index ce16c44a514c23..cbb72fd1aead03 100644 --- a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp +++ b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp @@ -21,7 +21,6 @@ #include "shash.h" #include "TypeManager.h" #include "MethodTable.h" -#include "varint.h" #include "CommonMacros.inl" #include "slist.inl" diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 78a39612f907c0..f9a730cd872d74 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -14,7 +14,6 @@ #include "RedhawkWarnings.h" #include "rhassert.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/TypeManager.cpp b/src/coreclr/nativeaot/Runtime/TypeManager.cpp index 96dc357136d90a..cb993dfd74ffa3 100644 --- a/src/coreclr/nativeaot/Runtime/TypeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/TypeManager.cpp @@ -10,7 +10,6 @@ #include "rhassert.h" #include "slist.h" #include "shash.h" -#include "varint.h" #include "rhbinder.h" #include "regdisplay.h" #include "StackFrameIterator.h" diff --git a/src/coreclr/nativeaot/Runtime/event.cpp b/src/coreclr/nativeaot/Runtime/event.cpp index 05a511510e385c..e53875d16318e1 100644 --- a/src/coreclr/nativeaot/Runtime/event.cpp +++ b/src/coreclr/nativeaot/Runtime/event.cpp @@ -9,7 +9,6 @@ #include "PalRedhawk.h" #include "rhassert.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/eventtrace_gcheap.cpp b/src/coreclr/nativeaot/Runtime/eventtrace_gcheap.cpp index 2acf81392c2b00..d2cdf011ba2a99 100644 --- a/src/coreclr/nativeaot/Runtime/eventtrace_gcheap.cpp +++ b/src/coreclr/nativeaot/Runtime/eventtrace_gcheap.cpp @@ -13,7 +13,6 @@ #include "daccess.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/inc/varint.h b/src/coreclr/nativeaot/Runtime/inc/varint.h deleted file mode 100644 index e5d0853bf48ffa..00000000000000 --- a/src/coreclr/nativeaot/Runtime/inc/varint.h +++ /dev/null @@ -1,82 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -class VarInt -{ -public: - static uint32_t ReadUnsigned(PTR_uint8_t & pbEncoding) - { - uintptr_t lengthBits = *pbEncoding & 0x0F; - size_t negLength = s_negLengthTab[lengthBits]; - uintptr_t shift = s_shiftTab[lengthBits]; - uint32_t result = *(PTR_uint32_t)(pbEncoding - negLength - 4); - - result >>= shift; - pbEncoding -= negLength; - - return result; - } - -private: - static int8_t s_negLengthTab[16]; - static uint8_t s_shiftTab[16]; -}; - -#ifndef __GNUC__ -__declspec(selectany) -#endif -int8_t -#ifdef __GNUC__ -__attribute__((weak)) -#endif -VarInt::s_negLengthTab[16] = -{ - -1, // 0 - -2, // 1 - -1, // 2 - -3, // 3 - - -1, // 4 - -2, // 5 - -1, // 6 - -4, // 7 - - -1, // 8 - -2, // 9 - -1, // 10 - -3, // 11 - - -1, // 12 - -2, // 13 - -1, // 14 - -5, // 15 -}; - -#ifndef __GNUC__ -__declspec(selectany) -#endif -uint8_t -#ifdef __GNUC__ -__attribute__((weak)) -#endif -VarInt::s_shiftTab[16] = -{ - 32-7*1, // 0 - 32-7*2, // 1 - 32-7*1, // 2 - 32-7*3, // 3 - - 32-7*1, // 4 - 32-7*2, // 5 - 32-7*1, // 6 - 32-7*4, // 7 - - 32-7*1, // 8 - 32-7*2, // 9 - 32-7*1, // 10 - 32-7*3, // 11 - - 32-7*1, // 12 - 32-7*2, // 13 - 32-7*1, // 14 - 0, // 15 -}; diff --git a/src/coreclr/nativeaot/Runtime/interoplibinterface_objc.cpp b/src/coreclr/nativeaot/Runtime/interoplibinterface_objc.cpp index 5a1dfe10f96b20..e3f1ca24cee3fa 100644 --- a/src/coreclr/nativeaot/Runtime/interoplibinterface_objc.cpp +++ b/src/coreclr/nativeaot/Runtime/interoplibinterface_objc.cpp @@ -18,7 +18,6 @@ #include "MethodTable.h" #include "ObjectLayout.h" #include "event.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/portable.cpp b/src/coreclr/nativeaot/Runtime/portable.cpp index f11a678e9027ee..ec992bc0ac4708 100644 --- a/src/coreclr/nativeaot/Runtime/portable.cpp +++ b/src/coreclr/nativeaot/Runtime/portable.cpp @@ -13,7 +13,6 @@ #include "slist.h" #include "shash.h" -#include "varint.h" #include "holder.h" #include "rhbinder.h" #include "Crst.h" diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index dffebe8bbde3c9..7bf6745066de45 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -11,7 +11,6 @@ #include "PalRedhawk.h" #include "rhassert.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/stressLog.cpp b/src/coreclr/nativeaot/Runtime/stressLog.cpp index 97c0a2615f9501..c1461cd284de88 100644 --- a/src/coreclr/nativeaot/Runtime/stressLog.cpp +++ b/src/coreclr/nativeaot/Runtime/stressLog.cpp @@ -21,7 +21,6 @@ #include "Crst.h" #include "rhassert.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/thread.cpp b/src/coreclr/nativeaot/Runtime/thread.cpp index a1a774a63ec691..0f269f23cbd58f 100644 --- a/src/coreclr/nativeaot/Runtime/thread.cpp +++ b/src/coreclr/nativeaot/Runtime/thread.cpp @@ -15,7 +15,6 @@ #include "PalRedhawk.h" #include "rhassert.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/threadstore.cpp b/src/coreclr/nativeaot/Runtime/threadstore.cpp index dbd321ffcff4e6..ddc5ef2eee0285 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.cpp +++ b/src/coreclr/nativeaot/Runtime/threadstore.cpp @@ -10,7 +10,6 @@ #include "PalRedhawk.h" #include "rhassert.h" #include "slist.h" -#include "varint.h" #include "regdisplay.h" #include "StackFrameIterator.h" #include "thread.h" diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp index 231be716316475..79e0548199c2d9 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp @@ -9,7 +9,7 @@ #include "regdisplay.h" #include "ICodeManager.h" #include "UnixNativeCodeManager.h" -#include "varint.h" +#include "NativePrimitiveDecoder.h" #include "holder.h" #include "CommonMacros.inl" @@ -1421,7 +1421,7 @@ bool UnixNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet pEnumState->pMethodStartAddress = dac_cast(pNativeMethodInfo->pMethodStartAddress); pEnumState->pEHInfo = dac_cast(p + *dac_cast(p)); pEnumState->uClause = 0; - pEnumState->nClauses = VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEnumState->nClauses = NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); return true; } @@ -1439,9 +1439,9 @@ bool UnixNativeCodeManager::EHEnumNext(EHEnumState * pEHEnumState, EHClause * pE pEnumState->uClause++; - pEHClauseOut->m_tryStartOffset = VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_tryStartOffset = NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); - uint32_t tryEndDeltaAndClauseKind = VarInt::ReadUnsigned(pEnumState->pEHInfo); + uint32_t tryEndDeltaAndClauseKind = NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); pEHClauseOut->m_clauseKind = (EHClauseKind)(tryEndDeltaAndClauseKind & 0x3); pEHClauseOut->m_tryEndOffset = pEHClauseOut->m_tryStartOffset + (tryEndDeltaAndClauseKind >> 2); @@ -1457,23 +1457,23 @@ bool UnixNativeCodeManager::EHEnumNext(EHEnumState * pEHEnumState, EHClause * pE switch (pEHClauseOut->m_clauseKind) { case EH_CLAUSE_TYPED: - pEHClauseOut->m_handlerAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_handlerAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); // Read target type { // @TODO: Compress EHInfo using type table index scheme // https://github.com/dotnet/corert/issues/972 - int32_t typeRelAddr = *((PTR_int32_t&)pEnumState->pEHInfo); - pEHClauseOut->m_pTargetType = dac_cast(pEnumState->pEHInfo + typeRelAddr); - pEnumState->pEHInfo += 4; + uint8_t* pBase = pEnumState->pEHInfo; + int32_t typeRelAddr = NativePrimitiveDecoder::ReadInt32(pEnumState->pEHInfo); + pEHClauseOut->m_pTargetType = dac_cast(pBase + typeRelAddr); } break; case EH_CLAUSE_FAULT: - pEHClauseOut->m_handlerAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_handlerAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); break; case EH_CLAUSE_FILTER: - pEHClauseOut->m_handlerAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + VarInt::ReadUnsigned(pEnumState->pEHInfo); - pEHClauseOut->m_filterAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_handlerAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_filterAddress = dac_cast(PINSTRToPCODE(dac_cast(pEnumState->pMethodStartAddress))) + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); break; default: UNREACHABLE_MSG("unexpected EHClauseKind"); diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index af1a7185866120..6a9435d58c0b83 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -175,7 +175,7 @@ struct Registers_REGDISPLAY : REGDISPLAY inline bool validFloatRegister(int) { return false; } inline bool validVectorRegister(int) { return false; } - inline static int lastDwarfRegNum() { return 16; } + static constexpr int lastDwarfRegNum() { return 16; } inline bool validRegister(int regNum) const { @@ -297,7 +297,7 @@ struct Registers_REGDISPLAY : REGDISPLAY inline bool validFloatRegister(int) { return false; } inline bool validVectorRegister(int) { return false; } - inline static int lastDwarfRegNum() { return 16; } + static constexpr int lastDwarfRegNum() { return 16; } inline bool validRegister(int regNum) const { @@ -336,7 +336,7 @@ struct Registers_REGDISPLAY : REGDISPLAY struct Registers_REGDISPLAY : REGDISPLAY { inline static int getArch() { return libunwind::REGISTERS_ARM; } - inline static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } + static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } bool validRegister(int num) const; bool validFloatRegister(int num) const; @@ -533,7 +533,7 @@ void Registers_REGDISPLAY::setFloatRegister(int num, double value) struct Registers_REGDISPLAY : REGDISPLAY { inline static int getArch() { return libunwind::REGISTERS_ARM64; } - inline static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } + static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } bool validRegister(int num) const; bool validFloatRegister(int num) { return false; }; @@ -816,7 +816,7 @@ void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) struct Registers_REGDISPLAY : REGDISPLAY { inline static int getArch() { return libunwind::REGISTERS_LOONGARCH; } - inline static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH; } + static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH; } bool validRegister(int num) const; bool validFloatRegister(int num) { return false; }; @@ -1096,7 +1096,7 @@ void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) struct Registers_REGDISPLAY : REGDISPLAY { inline static int getArch() { return libunwind::REGISTERS_RISCV; } - inline static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } + static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } bool validRegister(int num) const; bool validFloatRegister(int num) { return false; }; diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index a6437b56ac7b80..1b95e27caad563 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -11,7 +11,7 @@ #include "regdisplay.h" #include "ICodeManager.h" #include "CoffNativeCodeManager.h" -#include "varint.h" +#include "NativePrimitiveDecoder.h" #include "holder.h" #include "CommonMacros.inl" @@ -1044,7 +1044,7 @@ bool CoffNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet pEnumState->pMethodStartAddress = dac_cast(*pMethodStartAddress); pEnumState->pEHInfo = dac_cast(m_moduleBase + *dac_cast(p)); pEnumState->uClause = 0; - pEnumState->nClauses = VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEnumState->nClauses = NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); return true; } @@ -1059,9 +1059,9 @@ bool CoffNativeCodeManager::EHEnumNext(EHEnumState * pEHEnumState, EHClause * pE return false; pEnumState->uClause++; - pEHClauseOut->m_tryStartOffset = VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_tryStartOffset = NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); - uint32_t tryEndDeltaAndClauseKind = VarInt::ReadUnsigned(pEnumState->pEHInfo); + uint32_t tryEndDeltaAndClauseKind = NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); pEHClauseOut->m_clauseKind = (EHClauseKind)(tryEndDeltaAndClauseKind & 0x3); pEHClauseOut->m_tryEndOffset = pEHClauseOut->m_tryStartOffset + (tryEndDeltaAndClauseKind >> 2); @@ -1077,22 +1077,22 @@ bool CoffNativeCodeManager::EHEnumNext(EHEnumState * pEHEnumState, EHClause * pE switch (pEHClauseOut->m_clauseKind) { case EH_CLAUSE_TYPED: - pEHClauseOut->m_handlerAddress = pEnumState->pMethodStartAddress + VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_handlerAddress = pEnumState->pMethodStartAddress + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); // Read target type { // @TODO: Compress EHInfo using type table index scheme // https://github.com/dotnet/corert/issues/972 - uint32_t typeRVA = *((PTR_uint32_t&)pEnumState->pEHInfo)++; + uint32_t typeRVA = NativePrimitiveDecoder::ReadUInt32(pEnumState->pEHInfo); pEHClauseOut->m_pTargetType = dac_cast(m_moduleBase + typeRVA); } break; case EH_CLAUSE_FAULT: - pEHClauseOut->m_handlerAddress = pEnumState->pMethodStartAddress + VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_handlerAddress = pEnumState->pMethodStartAddress + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); break; case EH_CLAUSE_FILTER: - pEHClauseOut->m_handlerAddress = pEnumState->pMethodStartAddress + VarInt::ReadUnsigned(pEnumState->pEHInfo); - pEHClauseOut->m_filterAddress = pEnumState->pMethodStartAddress + VarInt::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_handlerAddress = pEnumState->pMethodStartAddress + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); + pEHClauseOut->m_filterAddress = pEnumState->pMethodStartAddress + NativePrimitiveDecoder::ReadUnsigned(pEnumState->pEHInfo); break; default: UNREACHABLE_MSG("unexpected EHClauseKind"); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 0abedd830a6b14..2de459555d114d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -697,10 +697,6 @@ CP0001 T:Internal.Runtime.Augments.TypeLoaderCallbacks - - CP0001 - T:Internal.Runtime.CanonTypeKind - CP0001 T:Internal.Runtime.CompilerServices.FunctionPointerOps @@ -717,18 +713,6 @@ CP0001 T:Internal.Runtime.CompilerServices.OpenMethodResolver - - CP0001 - T:Internal.Runtime.CompilerServices.RuntimeFieldHandleInfo - - - CP0001 - T:Internal.Runtime.CompilerServices.RuntimeMethodHandleInfo - - - CP0001 - T:Internal.Runtime.CompilerServices.RuntimeSignature - CP0001 T:Internal.Runtime.TypeManagerHandle @@ -753,6 +737,14 @@ CP0001 T:System.MDArray + + CP0001 + T:System.FieldHandleInfo + + + CP0001 + T:System.MethodHandleInfo + CP0001 T:System.Reflection.BinderBundle diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs index 6202cd45be89d5..33ebf9886745f0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs @@ -103,21 +103,6 @@ public static Assembly Load(AssemblyName assemblyRef, bool throwOnFileNotFound) return RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(assemblyRef.ToRuntimeAssemblyName()); } - public static Assembly Load(ReadOnlySpan rawAssembly, ReadOnlySpan pdbSymbolStore) - { - if (rawAssembly.IsEmpty) - throw new ArgumentNullException(nameof(rawAssembly)); - - return RuntimeAssemblyInfo.GetRuntimeAssemblyFromByteArray(rawAssembly, pdbSymbolStore); - } - - public static Assembly Load(string assemblyPath) - { - ArgumentNullException.ThrowIfNull(assemblyPath); - - return RuntimeAssemblyInfo.GetRuntimeAssemblyFromPath(assemblyPath); - } - // // This overload of GetMethodForHandle only accepts handles for methods declared on non-generic types (the method, however, // can be an instance of a generic method.) To resolve handles for methods declared on generic types, you must pass diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs index a59701eb8c85bf..cee8abb23ab324 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs @@ -19,7 +19,6 @@ public partial struct AssemblyBindResult { public MetadataReader Reader; public ScopeDefinitionHandle ScopeDefinitionHandle; - public IEnumerable OverflowScopes; } // @@ -33,10 +32,6 @@ public abstract class AssemblyBinder { public abstract bool Bind(RuntimeAssemblyName refName, bool cacheMissedLookups, out AssemblyBindResult result, out Exception exception); - public abstract bool Bind(ReadOnlySpan rawAssembly, ReadOnlySpan rawSymbolStore, out AssemblyBindResult result, out Exception exception); - - public abstract bool Bind(string assemblyPath, out AssemblyBindResult bindResult, out Exception exception); - public abstract IList GetLoadedAssemblies(); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index d592f7506f7aec..a473c80470f6fc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -483,7 +483,7 @@ public static IntPtr NewInterfaceDispatchCell(RuntimeTypeHandle interfaceTypeHan } [Intrinsic] - public static RuntimeTypeHandle GetCanonType(CanonTypeKind kind) + public static RuntimeTypeHandle GetCanonType() { // Compiler needs to expand this. This is not expressible in IL. throw new NotSupportedException(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs index 7dc7641435e5e9..c7b5203ffebd4f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs @@ -19,13 +19,10 @@ public abstract class TypeLoaderCallbacks public abstract bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr GetThreadStaticGCDescForDynamicType(TypeManagerHandle handle, int index); public abstract IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntPtr signature, out IntPtr auxResult); - public abstract bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs); - public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs); - public abstract bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2); + public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs); public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeMethodHandle declMethod); - public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName); - public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName); + public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle); public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle, out RuntimeTypeHandle pointerTypeHandle); public abstract bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, bool isMdArray, int rank, out RuntimeTypeHandle arrayTypeHandle); /// diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/MethodNameAndSignature.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/MethodNameAndSignature.cs new file mode 100644 index 00000000000000..04884e5ac54506 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/MethodNameAndSignature.cs @@ -0,0 +1,57 @@ +// 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.Diagnostics; + +using Internal.Metadata.NativeFormat; + +namespace Internal.Runtime.CompilerServices +{ + [CLSCompliant(false)] + public class MethodNameAndSignature + { + public MetadataReader Reader { get; } + public MethodHandle Handle { get; } + + public MethodNameAndSignature(MetadataReader reader, MethodHandle handle) + { + Reader = reader; + Handle = handle; + } + + public string GetName() + { + Method method = Reader.GetMethod(Handle); + return Reader.GetString(method.Name); + } + + public override bool Equals(object? compare) + { + if (compare == null) + return false; + + MethodNameAndSignature? other = compare as MethodNameAndSignature; + if (other == null) + return false; + + // Comparing handles is enough if there's only one metadata blob + // (Same assumption in GetHashCode below!) + Debug.Assert(Reader == other.Reader); + + Method thisMethod = Reader.GetMethod(Handle); + Method otherMethod = other.Reader.GetMethod(other.Handle); + + return thisMethod.Signature.Equals(otherMethod.Signature) + && thisMethod.Name.Equals(otherMethod.Name); + } + + public override int GetHashCode() + { + Method method = Reader.GetMethod(Handle); + + // Assumes we only have one metadata blob + return method.Signature.GetHashCode() ^ method.Name.GetHashCode(); + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs deleted file mode 100644 index 53f4d7e9ac2585..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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.InteropServices; - -namespace Internal.Runtime.CompilerServices -{ - [StructLayout(LayoutKind.Sequential)] - [CLSCompliant(false)] - public unsafe struct RuntimeFieldHandleInfo - { - public IntPtr NativeLayoutInfoSignature; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs deleted file mode 100644 index 41aa17cdcbfdae..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs +++ /dev/null @@ -1,53 +0,0 @@ -// 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.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; - -using Internal.Runtime.Augments; - -namespace Internal.Runtime.CompilerServices -{ - public class MethodNameAndSignature - { - public string Name { get; } - public RuntimeSignature Signature { get; } - - public MethodNameAndSignature(string name, RuntimeSignature signature) - { - Name = name; - Signature = signature; - } - - public override bool Equals(object? compare) - { - if (compare == null) - return false; - - MethodNameAndSignature? other = compare as MethodNameAndSignature; - if (other == null) - return false; - - if (Name != other.Name) - return false; - - return Signature.Equals(other.Signature); - } - - public override int GetHashCode() - { - int hash = Name.GetHashCode(); - - return hash; - } - } - - [StructLayout(LayoutKind.Sequential)] - [CLSCompliant(false)] - public unsafe struct RuntimeMethodHandleInfo - { - public IntPtr NativeLayoutInfoSignature; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs deleted file mode 100644 index 28fc165de7df99..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs +++ /dev/null @@ -1,127 +0,0 @@ -// 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.Diagnostics; -using System.Runtime; - -using Internal.Runtime.Augments; - -namespace Internal.Runtime.CompilerServices -{ - public struct RuntimeSignature - { - private IntPtr _moduleHandle; - private int _tokenOrOffset; - private bool _isNativeLayoutSignature; - - [CLSCompliant(false)] - public static RuntimeSignature CreateFromNativeLayoutSignature(TypeManagerHandle moduleHandle, uint nativeLayoutOffset) - { - return new RuntimeSignature - { - _moduleHandle = moduleHandle.GetIntPtrUNSAFE(), - _tokenOrOffset = (int)nativeLayoutOffset, - _isNativeLayoutSignature = true, - }; - } - - [CLSCompliant(false)] - public static RuntimeSignature CreateFromNativeLayoutSignature(RuntimeSignature oldSignature, uint newNativeLayoutOffset) - { - return new RuntimeSignature - { - _moduleHandle = oldSignature._moduleHandle, - _tokenOrOffset = (int)newNativeLayoutOffset, - _isNativeLayoutSignature = true, - }; - } - - public static RuntimeSignature CreateFromMethodHandle(TypeManagerHandle moduleHandle, int token) - { - return new RuntimeSignature - { - _moduleHandle = moduleHandle.GetIntPtrUNSAFE(), - _tokenOrOffset = token, - _isNativeLayoutSignature = false, - }; - } - - public bool IsNativeLayoutSignature - { - get - { - return _isNativeLayoutSignature; - } - } - - public int Token - { - get - { - if (_isNativeLayoutSignature) - { - Debug.Assert(false); - return -1; - } - return _tokenOrOffset; - } - } - - [CLSCompliant(false)] - public uint NativeLayoutOffset - { - get - { - if (!_isNativeLayoutSignature) - { - Debug.Assert(false); - return unchecked((uint)-1); - } - return (uint)_tokenOrOffset; - } - } - - public IntPtr ModuleHandle - { - get - { - return _moduleHandle; - } - } - - public bool Equals(RuntimeSignature other) - { - if (IsNativeLayoutSignature && other.IsNativeLayoutSignature) - { - if ((ModuleHandle == other.ModuleHandle) && (NativeLayoutOffset == other.NativeLayoutOffset)) - return true; - } - else if (!IsNativeLayoutSignature && !other.IsNativeLayoutSignature) - { - if ((ModuleHandle == other.ModuleHandle) && (Token == other.Token)) - return true; - } - - // Walk both signatures to check for equality the slow way - return RuntimeAugments.TypeLoaderCallbacks.CompareMethodSignatures(this, other); - } - - /// - /// Fast equality check - /// - public bool StructuralEquals(RuntimeSignature other) - { - if (_moduleHandle != other._moduleHandle) - return false; - - if (_tokenOrOffset != other._tokenOrOffset) - return false; - - if (_isNativeLayoutSignature != other._isNativeLayoutSignature) - return false; - - return true; - } - } -} 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 71646b278f0f3c..72df9073427635 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 @@ -119,9 +119,7 @@ - - - + @@ -355,9 +353,6 @@ Internal\LowLevelLinq\LowLevelEnumerable.ToArray.cs - - Internal\Runtime\CanonTypeKind.cs - System\Runtime\RhFailFastReason.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs index a6a183fa73cd84..20dbd1206ef754 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs @@ -72,36 +72,33 @@ private LowLevelDictionary CreateCaseInsensitiveTypeDictionary( LowLevelDictionary dict = new LowLevelDictionary(); - foreach (QScopeDefinition scope in AllScopes) + MetadataReader reader = Scope.Reader; + ScopeDefinition scopeDefinition = Scope.ScopeDefinition; + IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; + IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); + foreach (NamespaceDefinitionHandle namespaceHandle in allNamespaceHandles) { - MetadataReader reader = scope.Reader; - ScopeDefinition scopeDefinition = scope.ScopeDefinition; - IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; - IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); - foreach (NamespaceDefinitionHandle namespaceHandle in allNamespaceHandles) - { - string ns = namespaceHandle.ToNamespaceName(reader); - if (ns.Length != 0) - ns += "."; - ns = ns.ToLowerInvariant(); + string ns = namespaceHandle.ToNamespaceName(reader); + if (ns.Length != 0) + ns += "."; + ns = ns.ToLowerInvariant(); - NamespaceDefinition namespaceDefinition = namespaceHandle.GetNamespaceDefinition(reader); - foreach (TypeDefinitionHandle typeDefinitionHandle in namespaceDefinition.TypeDefinitions) + NamespaceDefinition namespaceDefinition = namespaceHandle.GetNamespaceDefinition(reader); + foreach (TypeDefinitionHandle typeDefinitionHandle in namespaceDefinition.TypeDefinitions) + { + string fullName = ns + typeDefinitionHandle.GetTypeDefinition(reader).Name.GetString(reader).ToLowerInvariant(); + if (!dict.TryGetValue(fullName, out _)) { - string fullName = ns + typeDefinitionHandle.GetTypeDefinition(reader).Name.GetString(reader).ToLowerInvariant(); - if (!dict.TryGetValue(fullName, out _)) - { - dict.Add(fullName, new QHandle(reader, typeDefinitionHandle)); - } + dict.Add(fullName, new QHandle(reader, typeDefinitionHandle)); } + } - foreach (TypeForwarderHandle typeForwarderHandle in namespaceDefinition.TypeForwarders) + foreach (TypeForwarderHandle typeForwarderHandle in namespaceDefinition.TypeForwarders) + { + string fullName = ns + typeForwarderHandle.GetTypeForwarder(reader).Name.GetString(reader).ToLowerInvariant(); + if (!dict.TryGetValue(fullName, out _)) { - string fullName = ns + typeForwarderHandle.GetTypeForwarder(reader).Name.GetString(reader).ToLowerInvariant(); - if (!dict.TryGetValue(fullName, out _)) - { - dict.Add(fullName, new QHandle(reader, typeForwarderHandle)); - } + dict.Add(fullName, new QHandle(reader, typeForwarderHandle)); } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs index 34a045281fd52f..e52605d1d45cee 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs @@ -21,15 +21,12 @@ internal sealed override RuntimeTypeInfo UncachedGetTypeCoreCaseSensitive(string namespaceParts[numNamespaceParts - i - 1] = parts[i]; string name = parts[numNamespaceParts]; - foreach (QScopeDefinition scopeDefinition in AllScopes) - { - MetadataReader reader = scopeDefinition.Reader; - ScopeDefinitionHandle scopeDefinitionHandle = scopeDefinition.Handle; - - NamespaceDefinition namespaceDefinition; - if (!TryResolveNamespaceDefinitionCaseSensitive(reader, namespaceParts, scopeDefinitionHandle, out namespaceDefinition)) - continue; + MetadataReader reader = Scope.Reader; + ScopeDefinitionHandle scopeDefinitionHandle = Scope.Handle; + NamespaceDefinition namespaceDefinition; + if (TryResolveNamespaceDefinitionCaseSensitive(reader, namespaceParts, scopeDefinitionHandle, out namespaceDefinition)) + { // We've successfully drilled down the namespace chain. Now look for a top-level type matching the type name. TypeDefinitionHandleCollection candidateTypes = namespaceDefinition.TypeDefinitions; foreach (TypeDefinitionHandle candidateType in candidateTypes) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs index 3e26daa4672511..2ca7967bcffc5b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs @@ -20,21 +20,17 @@ namespace System.Reflection.Runtime.Assemblies.NativeFormat { internal sealed partial class NativeFormatRuntimeAssembly : RuntimeAssemblyInfo { - private NativeFormatRuntimeAssembly(MetadataReader reader, ScopeDefinitionHandle scope, IEnumerable overflowScopes) + private NativeFormatRuntimeAssembly(MetadataReader reader, ScopeDefinitionHandle scope) { Scope = new QScopeDefinition(reader, scope); - OverflowScopes = overflowScopes; } public sealed override IEnumerable CustomAttributes { get { - foreach (QScopeDefinition scope in AllScopes) - { - foreach (CustomAttributeData cad in RuntimeCustomAttributeData.GetCustomAttributes(scope.Reader, scope.ScopeDefinition.CustomAttributes)) - yield return cad; - } + foreach (CustomAttributeData cad in RuntimeCustomAttributeData.GetCustomAttributes(Scope.Reader, Scope.ScopeDefinition.CustomAttributes)) + yield return cad; } } @@ -43,17 +39,14 @@ public sealed override IEnumerable DefinedTypes [RequiresUnreferencedCode("Types might be removed")] get { - foreach (QScopeDefinition scope in AllScopes) - { - MetadataReader reader = scope.Reader; - ScopeDefinition scopeDefinition = scope.ScopeDefinition; - IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; - IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); - IEnumerable allTopLevelTypes = reader.GetTopLevelTypes(allNamespaceHandles); - IEnumerable allTypes = reader.GetTransitiveTypes(allTopLevelTypes, publicOnly: false); - foreach (TypeDefinitionHandle typeDefinitionHandle in allTypes) - yield return (TypeInfo)typeDefinitionHandle.GetNamedType(reader).ToType(); - } + MetadataReader reader = Scope.Reader; + ScopeDefinition scopeDefinition = Scope.ScopeDefinition; + IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; + IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); + IEnumerable allTopLevelTypes = reader.GetTopLevelTypes(allNamespaceHandles); + IEnumerable allTypes = reader.GetTransitiveTypes(allTopLevelTypes, publicOnly: false); + foreach (TypeDefinitionHandle typeDefinitionHandle in allTypes) + yield return (TypeInfo)typeDefinitionHandle.GetNamedType(reader).ToType(); } } @@ -62,17 +55,14 @@ public sealed override IEnumerable ExportedTypes [RequiresUnreferencedCode("Types might be removed")] get { - foreach (QScopeDefinition scope in AllScopes) - { - MetadataReader reader = scope.Reader; - ScopeDefinition scopeDefinition = scope.ScopeDefinition; - IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; - IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); - IEnumerable allTopLevelTypes = reader.GetTopLevelTypes(allNamespaceHandles); - IEnumerable allTypes = reader.GetTransitiveTypes(allTopLevelTypes, publicOnly: true); - foreach (TypeDefinitionHandle typeDefinitionHandle in allTypes) - yield return typeDefinitionHandle.ResolveTypeDefinition(reader).ToType(); - } + MetadataReader reader = Scope.Reader; + ScopeDefinition scopeDefinition = Scope.ScopeDefinition; + IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; + IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); + IEnumerable allTopLevelTypes = reader.GetTopLevelTypes(allNamespaceHandles); + IEnumerable allTypes = reader.GetTransitiveTypes(allTopLevelTypes, publicOnly: true); + foreach (TypeDefinitionHandle typeDefinitionHandle in allTypes) + yield return typeDefinitionHandle.ResolveTypeDefinition(reader).ToType(); } } @@ -80,22 +70,16 @@ public sealed override MethodInfo EntryPoint { get { - // The scope that defines metadata for the owning type of the entrypoint will be the one - // to carry the entrypoint token information. Find it by iterating over all scopes. + MetadataReader reader = Scope.Reader; - foreach (QScopeDefinition scope in AllScopes) + QualifiedMethodHandle entrypointHandle = Scope.ScopeDefinition.EntryPoint; + if (!entrypointHandle.IsNil) { - MetadataReader reader = scope.Reader; - - QualifiedMethodHandle entrypointHandle = scope.ScopeDefinition.EntryPoint; - if (!entrypointHandle.IsNil) - { - QualifiedMethod entrypointMethod = entrypointHandle.GetQualifiedMethod(reader); - TypeDefinitionHandle declaringTypeHandle = entrypointMethod.EnclosingType; - MethodHandle methodHandle = entrypointMethod.Method; - NativeFormatRuntimeNamedTypeInfo containingType = NativeFormatRuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(reader, declaringTypeHandle, default(RuntimeTypeHandle)); - return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(new NativeFormatMethodCommon(methodHandle, containingType, containingType), containingType); - } + QualifiedMethod entrypointMethod = entrypointHandle.GetQualifiedMethod(reader); + TypeDefinitionHandle declaringTypeHandle = entrypointMethod.EnclosingType; + MethodHandle methodHandle = entrypointMethod.Method; + NativeFormatRuntimeNamedTypeInfo containingType = NativeFormatRuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(reader, declaringTypeHandle, default(RuntimeTypeHandle)); + return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(new NativeFormatMethodCommon(methodHandle, containingType, containingType), containingType); } return null; @@ -106,25 +90,22 @@ protected sealed override IEnumerable TypeForwardInfos { get { - foreach (QScopeDefinition scope in AllScopes) + MetadataReader reader = Scope.Reader; + ScopeDefinition scopeDefinition = Scope.ScopeDefinition; + IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; + IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); + foreach (NamespaceDefinitionHandle namespaceHandle in allNamespaceHandles) { - MetadataReader reader = scope.Reader; - ScopeDefinition scopeDefinition = scope.ScopeDefinition; - IEnumerable topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition }; - IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); - foreach (NamespaceDefinitionHandle namespaceHandle in allNamespaceHandles) + string? namespaceName = null; + foreach (TypeForwarderHandle typeForwarderHandle in namespaceHandle.GetNamespaceDefinition(reader).TypeForwarders) { - string? namespaceName = null; - foreach (TypeForwarderHandle typeForwarderHandle in namespaceHandle.GetNamespaceDefinition(reader).TypeForwarders) - { - namespaceName ??= namespaceHandle.ToNamespaceName(reader); + namespaceName ??= namespaceHandle.ToNamespaceName(reader); - TypeForwarder typeForwarder = typeForwarderHandle.GetTypeForwarder(reader); - string typeName = typeForwarder.Name.GetString(reader); - RuntimeAssemblyName redirectedAssemblyName = typeForwarder.Scope.ToRuntimeAssemblyName(reader); + TypeForwarder typeForwarder = typeForwarderHandle.GetTypeForwarder(reader); + string typeName = typeForwarder.Name.GetString(reader); + RuntimeAssemblyName redirectedAssemblyName = typeForwarder.Scope.ToRuntimeAssemblyName(reader); - yield return new TypeForwardInfo(redirectedAssemblyName, namespaceName, typeName); - } + yield return new TypeForwardInfo(redirectedAssemblyName, namespaceName, typeName); } } } @@ -194,20 +175,5 @@ public sealed override int GetHashCode() } internal QScopeDefinition Scope { get; } - - internal IEnumerable OverflowScopes { get; } - - internal IEnumerable AllScopes - { - get - { - yield return Scope; - - foreach (QScopeDefinition overflowScope in OverflowScopes) - { - yield return overflowScope; - } - } - } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs index 1674cc9b18cfe0..fde55471130bb6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs @@ -130,7 +130,7 @@ public sealed override RuntimeFieldHandle FieldHandle { return RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleForComponents( DeclaringType.TypeHandle, - Name); + _fieldHandle); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs index 84e1c1c547d6be..7c2486b4d88e29 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs @@ -34,7 +34,7 @@ internal partial class RuntimeAssemblyInfo static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly? runtimeAssembly) { if (bindResult.Reader != null) - runtimeAssembly = NativeFormatRuntimeAssembly.GetRuntimeAssembly(bindResult.Reader, bindResult.ScopeDefinitionHandle, bindResult.OverflowScopes); + runtimeAssembly = NativeFormatRuntimeAssembly.GetRuntimeAssembly(bindResult.Reader, bindResult.ScopeDefinitionHandle); } } } @@ -43,9 +43,9 @@ namespace System.Reflection.Runtime.Assemblies.NativeFormat { internal sealed partial class NativeFormatRuntimeAssembly { - internal static RuntimeAssembly GetRuntimeAssembly(MetadataReader reader, ScopeDefinitionHandle scope, IEnumerable overflowScopes) + internal static RuntimeAssembly GetRuntimeAssembly(MetadataReader reader, ScopeDefinitionHandle scope) { - return s_scopeToAssemblyDispenser.GetOrAdd(new RuntimeAssemblyKey(reader, scope, overflowScopes)); + return s_scopeToAssemblyDispenser.GetOrAdd(new RuntimeAssemblyKey(reader, scope)); } private static readonly Dispenser s_scopeToAssemblyDispenser = @@ -53,26 +53,23 @@ internal static RuntimeAssembly GetRuntimeAssembly(MetadataReader reader, ScopeD DispenserScenario.Scope_Assembly, delegate (RuntimeAssemblyKey qScopeDefinition) { - return (RuntimeAssembly)new NativeFormat.NativeFormatRuntimeAssembly(qScopeDefinition.Reader, qScopeDefinition.Handle, qScopeDefinition.Overflows); + return (RuntimeAssembly)new NativeFormat.NativeFormatRuntimeAssembly(qScopeDefinition.Reader, qScopeDefinition.Handle); } ); //----------------------------------------------------------------------------------------------------------- - // Captures a qualified scope (a reader plus a handle) representing the canonical definition of an assembly, - // plus a set of "overflow" scopes representing additional pieces of the assembly. + // Captures a qualified scope (a reader plus a handle) representing the canonical definition of an assembly //----------------------------------------------------------------------------------------------------------- private struct RuntimeAssemblyKey : IEquatable { - public RuntimeAssemblyKey(MetadataReader reader, ScopeDefinitionHandle handle, IEnumerable overflows) + public RuntimeAssemblyKey(MetadataReader reader, ScopeDefinitionHandle handle) { _reader = reader; _handle = handle; - _overflows = overflows; } public MetadataReader Reader { get { return _reader; } } public ScopeDefinitionHandle Handle { get { return _handle; } } - public IEnumerable Overflows { get { return _overflows; } } public override bool Equals(object obj) { @@ -84,8 +81,6 @@ public override bool Equals(object obj) public bool Equals(RuntimeAssemblyKey other) { - // Equality depends only on the canonical definition of an assembly, not - // the overflows. if (!(_reader == other._reader)) return false; if (!(_handle.Equals(other._handle))) @@ -100,7 +95,6 @@ public override int GetHashCode() private readonly MetadataReader _reader; private readonly ScopeDefinitionHandle _handle; - private readonly IEnumerable _overflows; } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs index 060a59536ca8ae..bca23c27f7216d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs @@ -38,42 +38,6 @@ internal static RuntimeAssembly GetRuntimeAssembly(RuntimeAssemblyName assemblyR return result; } - /// - /// Returns non-null or throws. - /// - internal static RuntimeAssembly GetRuntimeAssemblyFromByteArray(ReadOnlySpan rawAssembly, ReadOnlySpan pdbSymbolStore) - { - AssemblyBinder binder = ReflectionCoreExecution.ExecutionEnvironment.AssemblyBinder; - if (!binder.Bind(rawAssembly, pdbSymbolStore, out AssemblyBindResult bindResult, out Exception exception)) - { - if (exception != null) - throw exception; - else - throw new BadImageFormatException(); - } - - RuntimeAssembly result = GetRuntimeAssembly(bindResult); - return result; - } - - /// - /// Returns non-null or throws. - /// - internal static RuntimeAssembly GetRuntimeAssemblyFromPath(string assemblyPath) - { - AssemblyBinder binder = ReflectionCoreExecution.ExecutionEnvironment.AssemblyBinder; - if (!binder.Bind(assemblyPath, out AssemblyBindResult bindResult, out Exception exception)) - { - if (exception != null) - throw exception; - else - throw new BadImageFormatException(); - } - - RuntimeAssembly result = GetRuntimeAssembly(bindResult, assemblyPath); - return result; - } - /// /// Returns null if no assembly matches the assemblyRefName. Throws for other error cases. /// diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs index e07f23d3fcc205..ad37847fc02cea 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs @@ -201,12 +201,9 @@ public RuntimeMethodHandle GetRuntimeMethodHandle(Type[] genericArgs) genericArgHandles = null; } - TypeManagerHandle typeManager = RuntimeAugments.TypeLoaderCallbacks.GetModuleForMetadataReader(Reader); - return RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleForComponents( DeclaringType.TypeHandle, - Name, - RuntimeSignature.CreateFromMethodHandle(typeManager, MethodHandle.AsInt()), + _methodHandle, genericArgHandles); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs index 38105ec0984fdb..6257b9cad006ef 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.NativeAot.cs @@ -506,17 +506,31 @@ static NativeObjectWrapper() ComAwareWeakReference.InitializeCallbacks(&ComWeakRefToObject, &PossiblyComObject, &ObjectToComWeakRef); } - public static NativeObjectWrapper Create(IntPtr externalComObject, IntPtr inner, ComWrappers comWrappers, object comProxy, CreateObjectFlags flags) + public static NativeObjectWrapper Create( + IntPtr externalComObject, + IntPtr inner, + ComWrappers comWrappers, + object comProxy, + CreateObjectFlags flags, + ref IntPtr referenceTrackerMaybe) { - if (flags.HasFlag(CreateObjectFlags.TrackerObject) && - Marshal.QueryInterface(externalComObject, IID_IReferenceTracker, out IntPtr trackerObject) == HResults.S_OK) - { - return new ReferenceTrackerNativeObjectWrapper(externalComObject, inner, comWrappers, comProxy, flags, trackerObject); - } - else + if (flags.HasFlag(CreateObjectFlags.TrackerObject)) { - return new NativeObjectWrapper(externalComObject, inner, comWrappers, comProxy, flags); + IntPtr trackerObject = referenceTrackerMaybe; + + // We're taking ownership of this reference tracker object, so reset the reference + referenceTrackerMaybe = IntPtr.Zero; + + // If we already have a reference tracker (that will be the case in aggregation scenarios), then reuse it. + // Otherwise, do the 'QueryInterface' call for it here. This allows us to only ever query for this IID once. + if (trackerObject != IntPtr.Zero || + Marshal.QueryInterface(externalComObject, IID_IReferenceTracker, out trackerObject) == HResults.S_OK) + { + return new ReferenceTrackerNativeObjectWrapper(externalComObject, inner, comWrappers, comProxy, flags, trackerObject); + } } + + return new NativeObjectWrapper(externalComObject, inner, comWrappers, comProxy, flags); } protected NativeObjectWrapper(IntPtr externalComObject, IntPtr inner, ComWrappers comWrappers, object comProxy, CreateObjectFlags flags) @@ -881,7 +895,8 @@ private static void DetermineIdentityAndInner( IntPtr innerMaybe, CreateObjectFlags flags, out IntPtr identity, - out IntPtr inner) + out IntPtr inner, + out IntPtr referenceTrackerMaybe) { inner = innerMaybe; @@ -902,13 +917,15 @@ private static void DetermineIdentityAndInner( // to get identity from an inner is through a non-IUnknown // interface QI. Once we have the IReferenceTracker // instance we can be sure the QI for IUnknown will really - // be the true identity. - using ComHolder referenceTracker = new ComHolder(referenceTrackerPtr); + // be the true identity. This allows us to keep the reference tracker + // reference alive, so we can reuse it later. checkForIdentity = referenceTrackerPtr; + referenceTrackerMaybe = referenceTrackerPtr; Marshal.ThrowExceptionForHR(Marshal.QueryInterface(checkForIdentity, IID_IUnknown, out identity)); } else { + referenceTrackerMaybe = IntPtr.Zero; Marshal.ThrowExceptionForHR(Marshal.QueryInterface(externalComObject, IID_IUnknown, out identity)); } @@ -949,72 +966,90 @@ private unsafe bool TryGetOrCreateObjectForComInstanceInternal( innerMaybe, flags, out IntPtr identity, - out IntPtr inner); + out IntPtr inner, + out IntPtr referenceTrackerMaybe); - using ComHolder releaseIdentity = new ComHolder(identity); - - // If the user has requested a unique instance, - // we will immediately create the object, register it, - // and return. - if (flags.HasFlag(CreateObjectFlags.UniqueInstance)) + try { - retValue = CreateAndRegisterObjectForComInstance(identity, inner, flags); - return retValue is not null; - } + // If the user has requested a unique instance, + // we will immediately create the object, register it, + // and return. + if (flags.HasFlag(CreateObjectFlags.UniqueInstance)) + { + retValue = CreateAndRegisterObjectForComInstance(identity, inner, flags, ref referenceTrackerMaybe); + return retValue is not null; + } - // If we have a live cached wrapper currently, - // return that. - if (_rcwCache.FindProxyForComInstance(identity) is object liveCachedWrapper) - { - retValue = liveCachedWrapper; - return true; - } + // If we have a live cached wrapper currently, + // return that. + if (_rcwCache.FindProxyForComInstance(identity) is object liveCachedWrapper) + { + retValue = liveCachedWrapper; + return true; + } - // If the user tried to provide a pre-created managed wrapper, try to register - // that object as the wrapper. - if (wrapperMaybe is not null) - { - retValue = RegisterObjectForComInstance(identity, inner, wrapperMaybe, flags); - return retValue is not null; - } + // If the user tried to provide a pre-created managed wrapper, try to register + // that object as the wrapper. + if (wrapperMaybe is not null) + { + retValue = RegisterObjectForComInstance(identity, inner, wrapperMaybe, flags, ref referenceTrackerMaybe); + return retValue is not null; + } - // Check if the provided COM instance is actually a managed object wrapper from this - // ComWrappers instance, and use it if it is. - if (flags.HasFlag(CreateObjectFlags.Unwrap)) - { - ComInterfaceDispatch* comInterfaceDispatch = TryGetComInterfaceDispatch(identity); - if (comInterfaceDispatch != null) + // Check if the provided COM instance is actually a managed object wrapper from this + // ComWrappers instance, and use it if it is. + if (flags.HasFlag(CreateObjectFlags.Unwrap)) { - // If we found a managed object wrapper in this ComWrappers instance - // and it has the same identity pointer as the one we're creating a NativeObjectWrapper for, - // unwrap it. We don't AddRef the wrapper as we don't take a reference to it. - // - // A managed object can have multiple managed object wrappers, with a max of one per context. - // Let's say we have a managed object A and ComWrappers instances C1 and C2. Let B1 and B2 be the - // managed object wrappers for A created with C1 and C2 respectively. - // If we are asked to create an EOC for B1 with the unwrap flag on the C2 ComWrappers instance, - // we will create a new wrapper. In this scenario, we'll only unwrap B2. - object unwrapped = ComInterfaceDispatch.GetInstance(comInterfaceDispatch); - if (_managedObjectWrapperTable.TryGetValue(unwrapped, out ManagedObjectWrapperHolder? unwrappedWrapperInThisContext)) + ComInterfaceDispatch* comInterfaceDispatch = TryGetComInterfaceDispatch(identity); + if (comInterfaceDispatch != null) { - // The unwrapped object has a CCW in this context. Compare with identity - // so we can see if it's the CCW for the unwrapped object in this context. - if (unwrappedWrapperInThisContext.ComIp == identity) + // If we found a managed object wrapper in this ComWrappers instance + // and it has the same identity pointer as the one we're creating a NativeObjectWrapper for, + // unwrap it. We don't AddRef the wrapper as we don't take a reference to it. + // + // A managed object can have multiple managed object wrappers, with a max of one per context. + // Let's say we have a managed object A and ComWrappers instances C1 and C2. Let B1 and B2 be the + // managed object wrappers for A created with C1 and C2 respectively. + // If we are asked to create an EOC for B1 with the unwrap flag on the C2 ComWrappers instance, + // we will create a new wrapper. In this scenario, we'll only unwrap B2. + object unwrapped = ComInterfaceDispatch.GetInstance(comInterfaceDispatch); + if (_managedObjectWrapperTable.TryGetValue(unwrapped, out ManagedObjectWrapperHolder? unwrappedWrapperInThisContext)) { - retValue = unwrapped; - return true; + // The unwrapped object has a CCW in this context. Compare with identity + // so we can see if it's the CCW for the unwrapped object in this context. + if (unwrappedWrapperInThisContext.ComIp == identity) + { + retValue = unwrapped; + return true; + } } } } + + // If the user didn't provide a wrapper and couldn't unwrap a managed object wrapper, + // create a new wrapper. + retValue = CreateAndRegisterObjectForComInstance(identity, inner, flags, ref referenceTrackerMaybe); + return retValue is not null; } + finally + { + // Releasing a native object can never throw (it's a native call, so exceptions can't + // go through the ABI, it'd just crash the whole process). So we can use a single + // 'finally' block to release both native pointers we're holding in this scope. + Marshal.Release(identity); - // If the user didn't provide a wrapper and couldn't unwrap a managed object wrapper, - // create a new wrapper. - retValue = CreateAndRegisterObjectForComInstance(identity, inner, flags); - return retValue is not null; + if (referenceTrackerMaybe != IntPtr.Zero) + { + Marshal.Release(referenceTrackerMaybe); + } + } } - private object? CreateAndRegisterObjectForComInstance(IntPtr identity, IntPtr inner, CreateObjectFlags flags) + private object? CreateAndRegisterObjectForComInstance( + IntPtr identity, + IntPtr inner, + CreateObjectFlags flags, + ref IntPtr referenceTrackerMaybe) { object? retValue = CreateObject(identity, flags); if (retValue is null) @@ -1023,17 +1058,23 @@ private unsafe bool TryGetOrCreateObjectForComInstanceInternal( return null; } - return RegisterObjectForComInstance(identity, inner, retValue, flags); + return RegisterObjectForComInstance(identity, inner, retValue, flags, ref referenceTrackerMaybe); } - private object RegisterObjectForComInstance(IntPtr identity, IntPtr inner, object comProxy, CreateObjectFlags flags) + private object RegisterObjectForComInstance( + IntPtr identity, + IntPtr inner, + object comProxy, + CreateObjectFlags flags, + ref IntPtr referenceTrackerMaybe) { NativeObjectWrapper nativeObjectWrapper = NativeObjectWrapper.Create( identity, inner, this, comProxy, - flags); + flags, + ref referenceTrackerMaybe); object actualProxy = comProxy; NativeObjectWrapper actualWrapper = nativeObjectWrapper; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs index ff98d77ee098ce..f354e92fcd9aca 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs @@ -20,7 +20,7 @@ internal static int SizeOfHelper(RuntimeType t, bool throwIfNotMarshalable) { Debug.Assert(throwIfNotMarshalable); - if (t.IsPointer /* or IsFunctionPointer */) + if (t.IsPointer || t.IsFunctionPointer) return IntPtr.Size; if (t.IsByRef || t.IsArray || t.ContainsGenericParameters) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.NativeAot.cs index bd40eed1212bdb..9c2206e87a860c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.NativeAot.cs @@ -43,18 +43,21 @@ public void StartProfileOptimization(string profile) private static Assembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) { - // TODO: This is not passing down the AssemblyLoadContext, - // so it won't actually work properly when multiple assemblies with the same identity get loaded. - return ReflectionAugments.Load(assemblyPath); + ArgumentNullException.ThrowIfNull(assemblyPath); + + throw new PlatformNotSupportedException(); } #pragma warning restore IDE0060 -#pragma warning disable CA1822 - internal Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySpan arrSymbols) +#pragma warning disable CA1822, IDE0060 + internal Assembly InternalLoad(ReadOnlySpan rawAssembly, ReadOnlySpan rawSymbols) { - return ReflectionAugments.Load(arrAssembly, arrSymbols); + if (rawAssembly.IsEmpty) + throw new ArgumentNullException(nameof(rawAssembly)); + + throw new PlatformNotSupportedException(); } -#pragma warning restore CA1822 +#pragma warning restore CA1822, IDE0060 private void ReferenceUnreferencedEvents() { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs index 01624ba5469dde..766d7b4bf7949c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs @@ -2,9 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; +using Internal.Metadata.NativeFormat; using Internal.Runtime.Augments; namespace System @@ -29,7 +31,7 @@ public override bool Equals(object? obj) return Equals((RuntimeFieldHandle)obj); } - public bool Equals(RuntimeFieldHandle handle) + public unsafe bool Equals(RuntimeFieldHandle handle) { if (_value == handle._value) return true; @@ -37,26 +39,21 @@ public bool Equals(RuntimeFieldHandle handle) if (_value == IntPtr.Zero || handle._value == IntPtr.Zero) return false; - string fieldName1, fieldName2; - RuntimeTypeHandle declaringType1, declaringType2; + FieldHandleInfo* thisInfo = ToFieldHandleInfo(); + FieldHandleInfo* thatInfo = handle.ToFieldHandleInfo(); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType1, out fieldName1); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(handle, out declaringType2, out fieldName2); - - return declaringType1.Equals(declaringType2) && fieldName1 == fieldName2; + return thisInfo->DeclaringType.Equals(thatInfo->DeclaringType) && thisInfo->Handle.Equals(thatInfo->Handle); } - public override int GetHashCode() + public override unsafe int GetHashCode() { if (_value == IntPtr.Zero) return 0; - string fieldName; - RuntimeTypeHandle declaringType; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType, out fieldName); + FieldHandleInfo* info = ToFieldHandleInfo(); - int hashcode = declaringType.GetHashCode(); - return (hashcode + int.RotateLeft(hashcode, 13)) ^ fieldName.GetHashCode(); + int hashcode = info->DeclaringType.GetHashCode(); + return (hashcode + int.RotateLeft(hashcode, 13)) ^ info->Handle.GetHashCode(); } public static RuntimeFieldHandle FromIntPtr(IntPtr value) => new RuntimeFieldHandle(value); @@ -79,5 +76,19 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) { throw new PlatformNotSupportedException(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal readonly unsafe FieldHandleInfo* ToFieldHandleInfo() + { + return (FieldHandleInfo*)_value; + } + } + + [CLSCompliant(false)] + [StructLayout(LayoutKind.Sequential)] + public struct FieldHandleInfo + { + public RuntimeTypeHandle DeclaringType; + public FieldHandle Handle; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs index 3de517db8f37c1..13b10d64e93cc5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs @@ -2,10 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; +using Internal.Metadata.NativeFormat; using Internal.Reflection.Augments; +using Internal.Runtime; using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; @@ -31,7 +34,7 @@ public override bool Equals(object? obj) return Equals((RuntimeMethodHandle)obj); } - public bool Equals(RuntimeMethodHandle handle) + public unsafe bool Equals(RuntimeMethodHandle handle) { if (_value == handle._value) return true; @@ -39,52 +42,40 @@ public bool Equals(RuntimeMethodHandle handle) if (_value == IntPtr.Zero || handle._value == IntPtr.Zero) return false; - RuntimeTypeHandle declaringType1, declaringType2; - MethodNameAndSignature nameAndSignature1, nameAndSignature2; - RuntimeTypeHandle[] genericArgs1, genericArgs2; + MethodHandleInfo* thisInfo = ToMethodHandleInfo(); + MethodHandleInfo* thatInfo = handle.ToMethodHandleInfo(); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType1, out nameAndSignature1, out genericArgs1); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(handle, out declaringType2, out nameAndSignature2, out genericArgs2); - - if (!declaringType1.Equals(declaringType2)) + if (!thisInfo->DeclaringType.Equals(thatInfo->DeclaringType)) return false; - if (!nameAndSignature1.Equals(nameAndSignature2)) + if (!thisInfo->Handle.Equals(thatInfo->Handle)) return false; - if ((genericArgs1 == null && genericArgs2 != null) || (genericArgs1 != null && genericArgs2 == null)) + if (thisInfo->NumGenericArgs != thatInfo->NumGenericArgs) return false; - if (genericArgs1 != null) + + RuntimeTypeHandle* thisFirstArg = &thisInfo->FirstArgument; + RuntimeTypeHandle* thatFirstArg = &thatInfo->FirstArgument; + for (int i = 0; i < thisInfo->NumGenericArgs; i++) { - if (genericArgs1.Length != genericArgs2!.Length) + if (!thisFirstArg[i].Equals(thatFirstArg[i])) return false; - for (int i = 0; i < genericArgs1.Length; i++) - { - if (!genericArgs1[i].Equals(genericArgs2![i])) - return false; - } } return true; } - public override int GetHashCode() + public override unsafe int GetHashCode() { if (_value == IntPtr.Zero) return 0; - RuntimeTypeHandle declaringType; - MethodNameAndSignature nameAndSignature; - RuntimeTypeHandle[] genericArgs; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType, out nameAndSignature, out genericArgs); + MethodHandleInfo* info = ToMethodHandleInfo(); - int hashcode = declaringType.GetHashCode(); - hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ nameAndSignature.Name.GetHashCode(); - if (genericArgs != null) + int hashcode = info->DeclaringType.GetHashCode(); + hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ info->Handle.GetHashCode(); + for (int i = 0; i < info->NumGenericArgs; i++) { - for (int i = 0; i < genericArgs.Length; i++) - { - int argumentHashCode = genericArgs[i].GetHashCode(); - hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ argumentHashCode; - } + int argumentHashCode = (&info->FirstArgument)[i].GetHashCode(); + hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ argumentHashCode; } return hashcode; @@ -104,12 +95,12 @@ public override int GetHashCode() return !left.Equals(right); } - public IntPtr GetFunctionPointer() + public unsafe IntPtr GetFunctionPointer() { - RuntimeTypeHandle declaringType; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType, out _, out _); + if (_value == IntPtr.Zero) + throw new ArgumentNullException(null, SR.Arg_InvalidHandle); - return ReflectionAugments.GetFunctionPointer(this, declaringType); + return ReflectionAugments.GetFunctionPointer(this, ToMethodHandleInfo()->DeclaringType); } [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] @@ -118,5 +109,21 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) { throw new PlatformNotSupportedException(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal readonly unsafe MethodHandleInfo* ToMethodHandleInfo() + { + return (MethodHandleInfo*)_value; + } + } + + [CLSCompliant(false)] + [StructLayout(LayoutKind.Sequential)] + public struct MethodHandleInfo + { + public RuntimeTypeHandle DeclaringType; + public MethodHandle Handle; + public int NumGenericArgs; + public RuntimeTypeHandle FirstArgument; } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 10c1ac5bb45da7..0c3f90f286bb2a 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -227,30 +227,8 @@ public sealed override MethodBaseInvoker TryGetMethodInvokerNoConstraintCheck(Ru { MethodBase methodInfo = ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles); - MethodSignatureComparer methodSignatureComparer = new MethodSignatureComparer(methodHandle); - - MethodInvokeInfo methodInvokeInfo; -#if GENERICS_FORCE_USG - // Stress mode to force the usage of universal canonical method targets for reflection invokes. - // It is recommended to use "/SharedGenericsMode GenerateAllUniversalGenerics" NUTC command line argument when - // compiling the application in order to effectively use the GENERICS_FORCE_USG mode. - - // If we are just trying to invoke a non-generic method on a non-generic type, we won't force the universal lookup - if (!RuntimeAugments.IsGenericType(declaringTypeHandle) && (genericMethodTypeArgumentHandles == null || genericMethodTypeArgumentHandles.Length == 0)) - methodInvokeInfo = TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - methodInfo, ref methodSignatureComparer, CanonicalFormKind.Specific); - else - methodInvokeInfo = TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - methodInfo, ref methodSignatureComparer, CanonicalFormKind.Universal); -#else - methodInvokeInfo = TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - methodInfo, ref methodSignatureComparer, CanonicalFormKind.Specific); - - // If we failed to get a MethodInvokeInfo for an exact method, or a canonically equivalent method, check if there is a universal canonically - // equivalent entry that could be used (it will be much slower, and require a calling convention converter) - methodInvokeInfo ??= TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - methodInfo, ref methodSignatureComparer, CanonicalFormKind.Universal); -#endif + MethodInvokeInfo methodInvokeInfo = TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, + methodInfo); if (methodInvokeInfo == null) return null; @@ -280,12 +258,10 @@ private static RuntimeTypeHandle[] GetTypeSequence(ref ExternalReferencesTable e return result; } - private static IntPtr TryGetVirtualResolveData(NativeFormatModuleInfo module, - RuntimeTypeHandle methodHandleDeclaringType, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericArgs, - ref MethodSignatureComparer methodSignatureComparer) + private static IntPtr TryGetVirtualResolveData(RuntimeTypeHandle methodHandleDeclaringType, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericArgs) { TypeLoaderEnvironment.VirtualResolveDataResult lookupResult; - bool success = TypeLoaderEnvironment.TryGetVirtualResolveData(module, methodHandleDeclaringType, genericArgs, ref methodSignatureComparer, out lookupResult); + bool success = TypeLoaderEnvironment.TryGetVirtualResolveData(methodHandleDeclaringType, methodHandle, genericArgs, out lookupResult); if (!success) return IntPtr.Zero; else @@ -311,16 +287,12 @@ private static IntPtr TryGetVirtualResolveData(NativeFormatModuleInfo module, /// Handle of method to look up /// Runtime handles of generic method arguments /// MethodInfo of method to look up - /// Helper structure used for comparing signatures - /// Requested canon form /// Constructed method invoke info, null on failure private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles, - MethodBase methodInfo, - ref MethodSignatureComparer methodSignatureComparer, - CanonicalFormKind canonFormKind) + MethodBase methodInfo) { MethodInvokeMetadata methodInvokeMetadata; @@ -328,8 +300,6 @@ private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - ref methodSignatureComparer, - canonFormKind, out methodInvokeMetadata)) { // Method invoke info not found @@ -351,9 +321,7 @@ private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( IntPtr resolver = IntPtr.Zero; if ((methodInvokeMetadata.InvokeTableFlags & InvokeTableFlags.HasVirtualInvoke) != 0) { - resolver = TryGetVirtualResolveData(ModuleList.Instance.GetModuleInfoForMetadataReader(methodHandle.NativeFormatReader), - declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - ref methodSignatureComparer); + resolver = TryGetVirtualResolveData(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles); // Unable to find virtual resolution information, cannot return valid MethodInvokeInfo if (resolver == IntPtr.Zero) @@ -713,36 +681,13 @@ private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFor declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle); } - if ((entryFlags & InvokeTableFlags.HasMetadataHandle) != 0) - { - RuntimeTypeHandle declaringTypeHandleDefinition = GetTypeDefinition(declaringTypeHandle); - QTypeDefinition qTypeDefinition = GetMetadataForNamedType(declaringTypeHandleDefinition); - - MethodHandle nativeFormatMethodHandle = - (((int)HandleType.Method << 25) | (int)entryMethodHandleOrNameAndSigRaw).AsMethodHandle(); + RuntimeTypeHandle declaringTypeHandleDefinition = GetTypeDefinition(declaringTypeHandle); + QTypeDefinition qTypeDefinition = GetMetadataForNamedType(declaringTypeHandleDefinition); - methodHandle = new QMethodDefinition(qTypeDefinition.NativeFormatReader, nativeFormatMethodHandle); - } - else - { -#if FEATURE_SHARED_LIBRARY - uint nameAndSigOffset = entryMethodHandleOrNameAndSigRaw; - MethodNameAndSignature nameAndSig; - if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(mappingTableModule.Handle, nameAndSigOffset, out nameAndSig)) - { - Debug.Assert(false); - return false; - } + MethodHandle nativeFormatMethodHandle = + (((int)HandleType.Method << 25) | (int)entryMethodHandleOrNameAndSigRaw).AsMethodHandle(); - if (!TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSig, out methodHandle)) - { - Debug.Assert(false); - return false; - } -#else - throw NotImplemented.ByDesign; -#endif - } + methodHandle = new QMethodDefinition(qTypeDefinition.NativeFormatReader, nativeFormatMethodHandle); return true; } @@ -772,8 +717,7 @@ public sealed override FieldAccessor TryGetFieldAccessor( { FieldAccessMetadata fieldAccessMetadata; - if (!TypeLoaderEnvironment.TryGetFieldAccessMetadata( - metadataReader, + if (!TypeLoaderEnvironment.TryGetFieldAccessMetadataFromFieldAccessMap( declaringTypeHandle, fieldHandle, out fieldAccessMetadata)) @@ -820,8 +764,6 @@ public sealed override FieldAccessor TryGetFieldAccessor( } else { - Debug.Assert((fieldAccessMetadata.Flags & FieldTableFlags.IsUniversalCanonicalEntry) == 0); - if (fieldBase != FieldTableFlags.NonGCStatic) { fieldOffset = fieldAccessMetadata.Offset; @@ -854,12 +796,7 @@ public sealed override FieldAccessor TryGetFieldAccessor( // public sealed override unsafe bool TryGetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { - MethodNameAndSignature nameAndSignature; - methodHandle = default(QMethodDefinition); - if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodTypeArgumentHandles)) - return false; - - return TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSignature, out methodHandle); + return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles); } // @@ -875,32 +812,7 @@ public sealed override bool TryGetMethodFromHandleAndType(RuntimeMethodHandle ru // public sealed override unsafe bool TryGetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle) { - fieldHandle = default(FieldHandle); - - string fieldName; - if (!TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName)) - return false; - - RuntimeTypeHandle metadataLookupTypeHandle = GetTypeDefinition(declaringTypeHandle); - - QTypeDefinition qTypeDefinition = GetMetadataForNamedType(metadataLookupTypeHandle); - - // TODO! Handle ecma style types - MetadataReader reader = qTypeDefinition.NativeFormatReader; - TypeDefinitionHandle typeDefinitionHandle = qTypeDefinition.NativeFormatHandle; - - TypeDefinition typeDefinition = typeDefinitionHandle.GetTypeDefinition(reader); - foreach (FieldHandle fh in typeDefinition.Fields) - { - Field field = fh.GetField(reader); - if (field.Name.StringEquals(fieldName, reader)) - { - fieldHandle = fh; - return true; - } - } - - return false; + return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldHandle); } // diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs index f3e07c4f049fde..9a96d8205d451e 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs @@ -38,7 +38,7 @@ public sealed override void GetInterfaceMap(Type instanceType, [DynamicallyAcces goto notFound; } - MethodBase methodBase = ReflectionExecution.GetMethodBaseFromStartAddressIfAvailable(classRtMethodHandle); + MethodBase methodBase = ReflectionExecution.GetMethodBaseFromOriginalLdftnResult(classRtMethodHandle, instanceType.TypeHandle); if (methodBase == null) { goto notFound; @@ -90,12 +90,6 @@ public sealed override void GetEnumInfo(RuntimeTypeHandle typeHandle, out string out isFlags); return; } -#if ECMA_METADATA_SUPPORT - if (qTypeDefinition.IsEcmaFormatMetadataBased) - { - return EcmaFormatEnumInfo.Create(typeHandle, qTypeDefinition.EcmaFormatReader, qTypeDefinition.EcmaFormatHandle); - } -#endif names = Array.Empty(); values = Array.Empty(); isFlags = false; diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs index 6bff16c340a92d..ae02c0b4612f30 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs @@ -42,17 +42,6 @@ internal static MethodBaseInvoker CreateMethodInvoker(RuntimeTypeHandle declarin if (0 != (methodAttributes & MethodAttributes.Static)) isStatic = true; } -#if ECMA_METADATA_SUPPORT - if (methodHandle.IsEcmaFormatMetadataBased) - { - var reader = methodHandle.EcmaFormatReader; - var method = reader.GetMethodDefinition(methodHandle.EcmaFormatHandle); - var blobReader = reader.GetBlobReader(method.Signature); - byte sigByte = blobReader.ReadByte(); - if ((sigByte & (byte)System.Reflection.Metadata.SignatureAttributes.Instance) == 0) - isStatic = true; - } -#endif if (isStatic) return new StaticMethodInvoker(methodInvokeInfo); diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs index 749948d3403690..736c09a8a095fd 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs @@ -94,6 +94,17 @@ public static MethodBase GetMethodBaseFromStartAddressIfAvailable(IntPtr methodS return ExecutionDomain.GetMethod(declaringTypeHandle, qMethodDefinition, genericMethodTypeArgumentHandles: null); } + public static MethodBase GetMethodBaseFromOriginalLdftnResult(IntPtr methodStartAddress, RuntimeTypeHandle declaringTypeHandle) + { + if (!ExecutionEnvironment.TryGetMethodForOriginalLdFtnResult(methodStartAddress, + ref declaringTypeHandle, out QMethodDefinition qMethodDefinition, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)) + { + return null; + } + + return ExecutionDomain.GetMethod(declaringTypeHandle, qMethodDefinition, genericMethodTypeArgumentHandles); + } + internal static ExecutionEnvironmentImplementation ExecutionEnvironment { get; private set; } } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs index 5669203a6f39d1..9bb61c5cfb9073 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs @@ -47,7 +47,7 @@ public static MethodInfo GetDelegateMethodInfo(Delegate del) callTryGetMethod = false; methodHandle = QMethodDefinition.FromObjectAndInt(resolver->Reader, resolver->Handle); - if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(resolver->GVMMethodHandle, out _, out _, out genericMethodTypeArgumentHandles)) + if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(resolver->GVMMethodHandle, out _, out QMethodDefinition dummy, out genericMethodTypeArgumentHandles)) throw new NotSupportedException(SR.DelegateGetMethodInfo_NoInstantiation); } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs index 5700f56e812d0f..fba014a2415992 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs @@ -25,48 +25,23 @@ public sealed partial class AssemblyBinderImplementation : AssemblyBinder { private AssemblyBinderImplementation() { - _scopeGroups = Array.Empty>(); - + ArrayBuilder> scopes = default; foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules()) - RegisterModule(module); - } - - public static AssemblyBinderImplementation Instance { get; } = new AssemblyBinderImplementation(); - - partial void BindEcmaFilePath(string assemblyPath, ref AssemblyBindResult bindResult, ref Exception exception, ref bool? result); - partial void BindEcmaBytes(ReadOnlySpan rawAssembly, ReadOnlySpan rawSymbolStore, ref AssemblyBindResult bindResult, ref Exception exception, ref bool? result); - partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, bool cacheMissedLookups, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool resultBoolean); - partial void InsertEcmaLoadedAssemblies(List loadedAssemblies); - - public sealed override bool Bind(string assemblyPath, out AssemblyBindResult bindResult, out Exception exception) - { - bool? result = null; - exception = null; - bindResult = default(AssemblyBindResult); - - BindEcmaFilePath(assemblyPath, ref bindResult, ref exception, ref result); + { + MetadataReader reader = module.MetadataReader; + foreach (ScopeDefinitionHandle scopeDefinitionHandle in reader.ScopeDefinitions) + { + scopes.Add(new KeyValuePair( + scopeDefinitionHandle.ToRuntimeAssemblyName(reader), + new QScopeDefinition(reader, scopeDefinitionHandle) + )); + } + } - // If the Ecma assembly binder isn't linked in, simply throw PlatformNotSupportedException - if (!result.HasValue) - throw new PlatformNotSupportedException(); - else - return result.Value; + ScopeGroups = scopes.ToArray(); } - public sealed override bool Bind(ReadOnlySpan rawAssembly, ReadOnlySpan rawSymbolStore, out AssemblyBindResult bindResult, out Exception exception) - { - bool? result = null; - exception = null; - bindResult = default(AssemblyBindResult); - - BindEcmaBytes(rawAssembly, rawSymbolStore, ref bindResult, ref exception, ref result); - - // If the Ecma assembly binder isn't linked in, simply throw PlatformNotSupportedException - if (!result.HasValue) - throw new PlatformNotSupportedException(); - else - return result.Value; - } + public static AssemblyBinderImplementation Instance { get; } = new AssemblyBinderImplementation(); public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLookups, out AssemblyBindResult result, out Exception exception) { @@ -76,7 +51,7 @@ public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLo Exception preferredException = null; - foreach (KeyValuePair group in ScopeGroups) + foreach (KeyValuePair group in ScopeGroups) { if (AssemblyNameMatches(refName, group.Key, ref preferredException)) { @@ -87,18 +62,13 @@ public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLo } foundMatch = true; - ScopeDefinitionGroup scopeDefinitionGroup = group.Value; + QScopeDefinition scopeDefinitionGroup = group.Value; - result.Reader = scopeDefinitionGroup.CanonicalScope.Reader; - result.ScopeDefinitionHandle = scopeDefinitionGroup.CanonicalScope.Handle; - result.OverflowScopes = scopeDefinitionGroup.OverflowScopes; + result.Reader = scopeDefinitionGroup.Reader; + result.ScopeDefinitionHandle = scopeDefinitionGroup.Handle; } } - BindEcmaAssemblyName(refName, cacheMissedLookups, ref result, ref exception, ref preferredException, ref foundMatch); - if (exception != null) - return false; - if (!foundMatch) { exception = preferredException ?? new FileNotFoundException(SR.Format(SR.FileNotFound_AssemblyNotFound, refName.FullName)); @@ -111,19 +81,16 @@ public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLo public sealed override IList GetLoadedAssemblies() { List loadedAssemblies = new List(ScopeGroups.Length); - foreach (KeyValuePair group in ScopeGroups) + foreach (KeyValuePair group in ScopeGroups) { - ScopeDefinitionGroup scopeDefinitionGroup = group.Value; + QScopeDefinition scopeDefinitionGroup = group.Value; AssemblyBindResult result = default(AssemblyBindResult); - result.Reader = scopeDefinitionGroup.CanonicalScope.Reader; - result.ScopeDefinitionHandle = scopeDefinitionGroup.CanonicalScope.Handle; - result.OverflowScopes = scopeDefinitionGroup.OverflowScopes; + result.Reader = scopeDefinitionGroup.Reader; + result.ScopeDefinitionHandle = scopeDefinitionGroup.Handle; loadedAssemblies.Add(result); } - InsertEcmaLoadedAssemblies(loadedAssemblies); - return loadedAssemblies; } @@ -188,86 +155,6 @@ private static bool AssemblyVersionMatches(Version refVersion, Version defVersio return true; } - /// - /// This callback gets called whenever a module gets registered. It adds the metadata reader - /// for the new module to the available scopes. The lock in ExecutionEnvironmentImplementation ensures - /// that this function may never be called concurrently so that we can assume that two threads - /// never update the reader and scope list at the same time. - /// - /// Module to register - private void RegisterModule(NativeFormatModuleInfo nativeFormatModuleInfo) - { - LowLevelDictionaryWithIEnumerable scopeGroups = new LowLevelDictionaryWithIEnumerable(); - foreach (KeyValuePair oldGroup in _scopeGroups) - { - scopeGroups.Add(oldGroup.Key, oldGroup.Value); - } - AddScopesFromReaderToGroups(scopeGroups, nativeFormatModuleInfo.MetadataReader); - - // Update reader and scope list - KeyValuePair[] scopeGroupsArray = new KeyValuePair[scopeGroups.Count]; - int i = 0; - foreach (KeyValuePair data in scopeGroups) - { - scopeGroupsArray[i] = data; - i++; - } - - _scopeGroups = scopeGroupsArray; - } - - private KeyValuePair[] ScopeGroups - { - get - { - return _scopeGroups; - } - } - - private static void AddScopesFromReaderToGroups(LowLevelDictionaryWithIEnumerable groups, MetadataReader reader) - { - foreach (ScopeDefinitionHandle scopeDefinitionHandle in reader.ScopeDefinitions) - { - RuntimeAssemblyName defName = scopeDefinitionHandle.ToRuntimeAssemblyName(reader); - ScopeDefinitionGroup scopeDefinitionGroup; - if (groups.TryGetValue(defName, out scopeDefinitionGroup)) - { - scopeDefinitionGroup.AddOverflowScope(new QScopeDefinition(reader, scopeDefinitionHandle)); - } - else - { - scopeDefinitionGroup = new ScopeDefinitionGroup(new QScopeDefinition(reader, scopeDefinitionHandle)); - groups.Add(defName, scopeDefinitionGroup); - } - } - } - - private volatile KeyValuePair[] _scopeGroups; - - private class ScopeDefinitionGroup - { - public ScopeDefinitionGroup(QScopeDefinition canonicalScope) - { - _canonicalScope = canonicalScope; - } - - public QScopeDefinition CanonicalScope { get { return _canonicalScope; } } - - public IEnumerable OverflowScopes - { - get - { - return _overflowScopes.ToArray(); - } - } - - public void AddOverflowScope(QScopeDefinition overflowScope) - { - _overflowScopes.Add(overflowScope); - } - - private readonly QScopeDefinition _canonicalScope; - private ArrayBuilder _overflowScopes; - } + private KeyValuePair[] ScopeGroups { get; } } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CanonicallyEquivalentEntryLocator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CanonicallyEquivalentEntryLocator.cs index 1b1082f3132fc9..7efdc51725fb69 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CanonicallyEquivalentEntryLocator.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CanonicallyEquivalentEntryLocator.cs @@ -17,9 +17,8 @@ public struct CanonicallyEquivalentEntryLocator private RuntimeTypeHandle _genericDefinition; private RuntimeTypeHandle[] _genericArgs; private DefType _defType; - private CanonicalFormKind _canonKind; - public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind, CanonicalFormKind kind) + public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind) { if (RuntimeAugments.IsGenericType(typeToFind)) { @@ -32,16 +31,14 @@ public CanonicallyEquivalentEntryLocator(RuntimeTypeHandle typeToFind, Canonical } _typeToFind = typeToFind; - _canonKind = kind; _defType = null; } - internal CanonicallyEquivalentEntryLocator(DefType typeToFind, CanonicalFormKind kind) + internal CanonicallyEquivalentEntryLocator(DefType typeToFind) { _genericArgs = null; _genericDefinition = default(RuntimeTypeHandle); _typeToFind = default(RuntimeTypeHandle); - _canonKind = kind; _defType = typeToFind; } @@ -50,10 +47,10 @@ public int LookupHashCode get { if (_defType != null) - return _defType.ConvertToCanonForm(_canonKind).GetHashCode(); + return _defType.ConvertToCanonForm(CanonicalFormKind.Specific).GetHashCode(); if (!_genericDefinition.IsNull()) - return TypeLoaderEnvironment.Instance.GetCanonicalHashCode(_typeToFind, _canonKind); + return TypeLoaderEnvironment.Instance.GetCanonicalHashCode(_typeToFind, CanonicalFormKind.Specific); else return _typeToFind.GetHashCode(); } @@ -63,9 +60,9 @@ public bool IsCanonicallyEquivalent(RuntimeTypeHandle other) { if (_defType != null) { - TypeDesc typeToFindAsCanon = _defType.ConvertToCanonForm(_canonKind); + TypeDesc typeToFindAsCanon = _defType.ConvertToCanonForm(CanonicalFormKind.Specific); TypeDesc otherTypeAsTypeDesc = _defType.Context.ResolveRuntimeTypeHandle(other); - TypeDesc otherTypeAsCanon = otherTypeAsTypeDesc.ConvertToCanonForm(_canonKind); + TypeDesc otherTypeAsCanon = otherTypeAsTypeDesc.ConvertToCanonForm(CanonicalFormKind.Specific); return typeToFindAsCanon == otherTypeAsCanon; } @@ -77,7 +74,7 @@ public bool IsCanonicallyEquivalent(RuntimeTypeHandle other) RuntimeTypeHandle[] otherGenericArgs; otherGenericDefinition = RuntimeAugments.GetGenericInstantiation(other, out otherGenericArgs); - return _genericDefinition.Equals(otherGenericDefinition) && TypeLoaderEnvironment.Instance.CanInstantiationsShareCode(_genericArgs, otherGenericArgs, _canonKind); + return _genericDefinition.Equals(otherGenericDefinition) && TypeLoaderEnvironment.Instance.CanInstantiationsShareCode(_genericArgs, otherGenericArgs, CanonicalFormKind.Specific); } else return false; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs index b49eec372a1ff0..9a5995e17fb9ef 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs @@ -216,8 +216,6 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo if (state.ThreadDataSize != 0) dynamicTypeFlags |= DynamicTypeFlags.HasThreadStatics; - // Note: The number of vtable slots on the MethodTable to create is not necessary equal to the number of - // vtable slots on the template type for universal generics (see ComputeVTableLayout) ushort numVtableSlots = state.NumVTableSlots; // Compute the MethodTable size and allocate it diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs index 215a0f51325215..eb911d4037afde 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs @@ -242,9 +242,6 @@ internal override unsafe void Prepare(TypeBuilder builder) internal override IntPtr Create(TypeBuilder builder) { - // TODO (USG): What if this method's instantiation is a non-shareable one (from a normal canonical - // perspective) and there's an exact method pointer for the method in question, do we still - // construct a method dictionary to be used with the universal canonical method implementation? Debug.Assert(GenericMethod.RuntimeMethodDictionary != IntPtr.Zero); return GenericMethod.RuntimeMethodDictionary; } @@ -253,7 +250,7 @@ internal override IntPtr Create(TypeBuilder builder) private class FieldLdTokenCell : GenericDictionaryCell { internal TypeDesc ContainingType; - internal IntPtr FieldName; + internal int FieldHandle; internal override unsafe void Prepare(TypeBuilder builder) { @@ -267,7 +264,7 @@ internal override unsafe IntPtr Create(TypeBuilder builder) { RuntimeFieldHandle handle = TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents( builder.GetRuntimeTypeHandle(ContainingType), - FieldName); + FieldHandle); return *(IntPtr*)&handle; } @@ -276,8 +273,6 @@ internal override unsafe IntPtr Create(TypeBuilder builder) private class MethodLdTokenCell : GenericDictionaryCell { internal MethodDesc Method; - internal IntPtr MethodName; - internal RuntimeSignature MethodSignature; internal override unsafe void Prepare(TypeBuilder builder) { @@ -301,8 +296,7 @@ internal override unsafe IntPtr Create(TypeBuilder builder) RuntimeMethodHandle handle = TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents( builder.GetRuntimeTypeHandle(Method.OwningType), - MethodName, - MethodSignature, + Method.NameAndSignature.Handle, genericArgHandles); return *(IntPtr*)&handle; @@ -467,30 +461,22 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.FieldLdToken: { - NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); - - var type = nativeLayoutInfoLoadContext.GetType(ref ldtokenSigParser); - IntPtr fieldNameSig = ldtokenSigParser.Reader.OffsetToAddress(ldtokenSigParser.Offset); - TypeLoaderLogger.WriteLine("LdToken on: " + type.ToString() + "." + ldtokenSigParser.GetString()); + var type = nativeLayoutInfoLoadContext.GetType(ref parser); + int handle = (int)parser.GetUnsigned(); + TypeLoaderLogger.WriteLine("LdToken on: " + type.ToString() + "." + handle.LowLevelToString()); - cell = new FieldLdTokenCell() { FieldName = fieldNameSig, ContainingType = type }; + cell = new FieldLdTokenCell() { FieldHandle = handle, ContainingType = type }; } break; case FixupSignatureKind.MethodLdToken: { - NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); - - RuntimeSignature methodNameSig; - RuntimeSignature methodSig; - var method = nativeLayoutInfoLoadContext.GetMethod(ref ldtokenSigParser, out methodNameSig, out methodSig); - TypeLoaderLogger.WriteLine("LdToken on: " + method.OwningType.ToString() + "::" + method.NameAndSignature.Name); + var method = nativeLayoutInfoLoadContext.GetMethod(ref parser); + TypeLoaderLogger.WriteLine("LdToken on: " + method.OwningType.ToString() + "::" + method.NameAndSignature.GetName()); cell = new MethodLdTokenCell { Method = method, - MethodName = methodNameSig.NativeLayoutSignature(), - MethodSignature = methodSig }; } break; @@ -515,7 +501,7 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.Method: { - var method = nativeLayoutInfoLoadContext.GetMethod(ref parser, out _, out _); + var method = nativeLayoutInfoLoadContext.GetMethod(ref parser); TypeLoaderLogger.WriteLine("Method: " + method.ToString()); cell = new MethodCell @@ -544,9 +530,7 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.GenericStaticConstrainedMethod: { TypeDesc constraintType = nativeLayoutInfoLoadContext.GetType(ref parser); - - NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); - MethodDesc constrainedMethod = nativeLayoutInfoLoadContext.GetMethod(ref ldtokenSigParser); + MethodDesc constrainedMethod = nativeLayoutInfoLoadContext.GetMethod(ref parser); TypeLoaderLogger.WriteLine("GenericStaticConstrainedMethod: " + constraintType.ToString() + " Method " + constrainedMethod.ToString()); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs index c484eb6e5afded..f4353f9db8f54b 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs @@ -395,22 +395,4 @@ public static NativeFormatModuleInfoEnumerable EnumerateModules(TypeManagerHandl return new NativeFormatModuleInfoEnumerable(Instance._loadedModuleMap, preferredModule); } } - - public static partial class RuntimeSignatureHelper - { - public static ModuleInfo GetModuleInfo(this Internal.Runtime.CompilerServices.RuntimeSignature methodSignature) - { - if (methodSignature.IsNativeLayoutSignature) - { - return ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(methodSignature.ModuleHandle)); - } - else - { - ModuleInfo moduleInfo; - bool success = ModuleList.Instance.TryGetModuleInfoByHandle(new TypeManagerHandle(methodSignature.ModuleHandle), out moduleInfo); - Debug.Assert(success); - return moduleInfo; - } - } - } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs index 90a2c9857c6dc1..e7e798a7e6728f 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using System.Reflection.Runtime.General; using Internal.NativeFormat; using Internal.Runtime; @@ -175,7 +176,7 @@ internal TypeDesc GetType(ref NativeParser parser) } } - internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature methodNameSig, out RuntimeSignature methodSig) + internal MethodDesc GetMethod(ref NativeParser parser) { MethodFlags flags = (MethodFlags)parser.GetUnsigned(); @@ -184,7 +185,8 @@ internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature meth functionPointer = GetExternalReferencePointer(parser.GetUnsigned()); DefType containingType = (DefType)GetType(ref parser); - MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.GetMethodNameAndSignature(ref parser, _module.Handle, out methodNameSig, out methodSig); + int token = (int)parser.GetUnsigned(); + MethodNameAndSignature nameAndSignature = new MethodNameAndSignature(_module.MetadataReader, token.AsHandle().ToMethodHandle(_module.MetadataReader)); bool unboxingStub = (flags & MethodFlags.IsUnboxingStub) != 0; @@ -208,11 +210,6 @@ internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature meth return retVal; } - internal MethodDesc GetMethod(ref NativeParser parser) - { - return GetMethod(ref parser, out _, out _); - } - internal TypeDesc[] GetTypeSequence(ref NativeParser parser) { uint count = parser.GetSequenceCount(); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TemplateLocator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TemplateLocator.cs index d3fd2dd8b24a18..07c322552dc825 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TemplateLocator.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TemplateLocator.cs @@ -56,10 +56,6 @@ private static TypeDesc TryGetTypeTemplate_Internal(TypeDesc concreteType, Canon continue; } - Debug.Assert( - (kind != CanonicalFormKind.Universal) || - (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.ConvertToCanonForm(kind))); - nativeLayoutInfoModule = moduleInfo; return candidateTemplate; } @@ -126,10 +122,6 @@ private static InstantiatedMethod TryGetGenericMethodTemplate_Internal(Instantia continue; } - Debug.Assert( - (kind != CanonicalFormKind.Universal) || - (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind))); - return candidateTemplate; } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index 5d817bff72eda9..48bb6c91b6169d 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -322,10 +322,6 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method) } } - // Ensure that if this method is non-shareable from a normal canonical perspective, then - // its template MUST be a universal canonical template method - Debug.Assert(!method.IsNonSharableMethod || (method.IsNonSharableMethod && templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal))); - NativeReader nativeLayoutInfoReader = TypeLoaderEnvironment.GetNativeLayoutInfoReader(nativeLayoutModule.Handle); var methodInfoParser = new NativeParser(nativeLayoutInfoReader, nativeLayoutInfoToken); @@ -348,7 +344,7 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method) break; default: - Debug.Fail("Unexpected BagElementKind for generic method with name " + method.NameAndSignature.Name + "! Only BagElementKind.DictionaryLayout should appear."); + Debug.Fail("Unexpected BagElementKind for generic method with name " + method.NameAndSignature.GetName() + "! Only BagElementKind.DictionaryLayout should appear."); throw new BadImageFormatException(); } } @@ -361,12 +357,6 @@ internal void ParseNativeLayoutInfo(TypeBuilderState state, TypeDesc type) { TypeLoaderLogger.WriteLine("Parsing NativeLayoutInfo for type " + type.ToString() + " ..."); - bool isTemplateUniversalCanon = false; - if (state.TemplateType != null) - { - isTemplateUniversalCanon = state.TemplateType.IsCanonicalSubtype(CanonicalFormKind.Universal); - } - if (state.TemplateType == null) { throw new MissingTemplateException(); @@ -427,15 +417,8 @@ internal void ParseNativeLayoutInfo(TypeBuilderState state, TypeDesc type) state.ThreadStaticDesc = context.GetGCStaticInfo(typeInfoParser.GetUnsigned()); break; - case BagElementKind.FieldLayout: - TypeLoaderLogger.WriteLine("Found BagElementKind.FieldLayout"); - typeInfoParser.SkipInteger(); // Handled in type layout algorithm - break; - case BagElementKind.DictionaryLayout: TypeLoaderLogger.WriteLine("Found BagElementKind.DictionaryLayout"); - Debug.Assert(!isTemplateUniversalCanon, "Universal template nativelayout do not have DictionaryLayout"); - Debug.Assert(state.Dictionary == null); if (!state.TemplateType.RetrieveRuntimeTypeHandleIfPossible()) { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs index b184395c2a5195..39915c06576a15 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs @@ -85,7 +85,7 @@ public TypeDesc TemplateType _templateTypeLoaderNativeLayout = true; _templateComputed = true; - if ((_templateType != null) && !_templateType.IsCanonicalSubtype(CanonicalFormKind.Universal)) + if (_templateType != null) _nativeLayoutTokenComputed = true; } @@ -267,7 +267,6 @@ private ushort ComputeNumVTableSlots() } else { - // This should only happen for non-universal templates Debug.Assert(TypeBeingBuilt.IsTemplateCanonical()); TypeDesc templateType = TypeBeingBuilt.ComputeTemplate(false); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs index 634770228e4da2..4330ad08aea7e9 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; +using System.Reflection.Runtime.General; using System.Threading; using Internal.NativeFormat; @@ -27,7 +28,7 @@ public override int GetHashCode() { if (!_hashCode.HasValue) { - _hashCode = _declaringTypeHandle.GetHashCode() ^ TypeHashingAlgorithms.ComputeGenericInstanceHashCode(TypeHashingAlgorithms.ComputeNameHashCode(_methodNameAndSignature.Name), _genericMethodArgumentHandles); + _hashCode = _declaringTypeHandle.GetHashCode() ^ TypeHashingAlgorithms.ComputeGenericInstanceHashCode(TypeHashingAlgorithms.ComputeNameHashCode(_methodNameAndSignature.GetName()), _genericMethodArgumentHandles); } return _hashCode.Value; } @@ -147,7 +148,7 @@ internal override bool MatchParsedEntry(ref NativeParser entryParser, ref Extern RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); // Hash table names / sigs are indirected through to the native layout info - MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.Instance.GetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned()); + MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.GetMethodNameAndSignatureFromToken(moduleHandle, entryParser.GetUnsigned()); RuntimeTypeHandle[] parsedArgsHandles = GetTypeSequence(ref externalReferencesLookup, ref entryParser); @@ -186,10 +187,8 @@ public bool TryGetGenericMethodComponents(IntPtr methodDictionary, out RuntimeTy { if (!TryGetDynamicGenericMethodComponents(methodDictionary, out declaringType, out nameAndSignature, out genericMethodArgumentHandles)) { - if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out TypeManagerHandle typeManager, out uint nameAndSigOffset, out genericMethodArgumentHandles)) + if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out nameAndSignature, out genericMethodArgumentHandles)) return false; - - nameAndSignature = TypeLoaderEnvironment.Instance.GetMethodNameAndSignatureFromNativeLayoutOffset(typeManager, nameAndSigOffset); } return true; @@ -199,7 +198,7 @@ public static bool TryGetGenericMethodComponents(IntPtr methodDictionary, out Ru { TypeLoaderEnvironment instance = TypeLoaderEnvironment.InstanceOrNull; if (instance == null || !instance.TryGetDynamicGenericMethodComponents(methodDictionary, out declaringType, out _, out genericMethodArgumentHandles)) - if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out _, out _, out genericMethodArgumentHandles)) + if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out _, out genericMethodArgumentHandles)) return false; return true; @@ -248,8 +247,6 @@ public bool TryGetGenericVirtualMethodPointer(InstantiatedMethod method, out Int { if (!method.CanShareNormalGenericCode()) { - // First see if we can find an exact method implementation for the GVM (avoid using USG implementations if we can, - // because USG code is much slower). if (TryLookupExactMethodPointer(method, out methodPointer)) { Debug.Assert(methodPointer != IntPtr.Zero); @@ -370,7 +367,7 @@ private bool TryGetDynamicGenericMethodComponents(IntPtr methodDictionary, out R return true; } } - private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDictionary, out RuntimeTypeHandle declaringType, out TypeManagerHandle typeManager, out uint nameAndSigOffset, out RuntimeTypeHandle[] genericMethodArgumentHandles) + private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDictionary, out RuntimeTypeHandle declaringType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgumentHandles) { // Generic method dictionaries have a header that has the hash code in it. Locate the header IntPtr dictionaryHeader = IntPtr.Subtract(methodDictionary, IntPtr.Size); @@ -398,8 +395,8 @@ private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDict // We have a match - fill in the results declaringType = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); - typeManager = module.Handle; - nameAndSigOffset = entryParser.GetUnsigned(); + int token = (int)entryParser.GetUnsigned(); + nameAndSignature = new MethodNameAndSignature(module.MetadataReader, token.AsHandle().ToMethodHandle(module.MetadataReader)); uint arity = entryParser.GetSequenceCount(); genericMethodArgumentHandles = new RuntimeTypeHandle[arity]; @@ -414,8 +411,7 @@ private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDict } declaringType = default(RuntimeTypeHandle); - typeManager = default; - nameAndSigOffset = 0; + nameAndSignature = null; genericMethodArgumentHandles = null; return false; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs index efe5e92830c6c1..06573d1beb03e9 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs @@ -41,58 +41,21 @@ public struct FieldAccessMetadata public sealed partial class TypeLoaderEnvironment { - /// - /// Try to look up field access info for given canon in metadata blobs for all available modules. - /// - /// Metadata reader for the declaring type - /// Declaring type for the method - /// Field handle - /// Output - metadata information for field accessor construction - /// true when found, false otherwise - public static bool TryGetFieldAccessMetadata( - MetadataReader metadataReader, - RuntimeTypeHandle runtimeTypeHandle, - FieldHandle fieldHandle, - out FieldAccessMetadata fieldAccessMetadata) - { - fieldAccessMetadata = default(FieldAccessMetadata); - - if (TryGetFieldAccessMetadataFromFieldAccessMap( - runtimeTypeHandle, - fieldHandle, - CanonicalFormKind.Specific, - ref fieldAccessMetadata)) - { - return true; - } - - if (TryGetFieldAccessMetadataFromFieldAccessMap( - runtimeTypeHandle, - fieldHandle, - CanonicalFormKind.Universal, - ref fieldAccessMetadata)) - { - return true; - } - - return false; - } - /// /// Try to look up field access info for given canon in metadata blobs for all available modules. /// /// Declaring type for the method /// Field handle - /// Canonical form to use /// Output - metadata information for field accessor construction /// true when found, false otherwise - private static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap( + public static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap( RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle, - CanonicalFormKind canonFormKind, - ref FieldAccessMetadata fieldAccessMetadata) + out FieldAccessMetadata fieldAccessMetadata) { - CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind); + fieldAccessMetadata = default; + + CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle); foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle))) { @@ -119,29 +82,18 @@ private static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap( FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned(); - if ((canonFormKind == CanonicalFormKind.Universal) != ((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) != 0)) - continue; - RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) && !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle)) continue; - if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0) - { - Handle entryFieldHandle = (((int)HandleType.Field << 25) | (int)entryParser.GetUnsigned()).AsHandle(); - if (!fieldHandle.Equals(entryFieldHandle)) - continue; - } - else - { - Debug.Fail("Multifile path"); - } + Handle entryFieldHandle = (((int)HandleType.Field << 25) | (int)entryParser.GetUnsigned()).AsHandle(); + if (!fieldHandle.Equals(entryFieldHandle)) + continue; int fieldOffset; IntPtr fieldAddressCookie = IntPtr.Zero; - Debug.Assert(canonFormKind != CanonicalFormKind.Universal); if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) { fieldOffset = (int)entryParser.GetUnsigned(); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs index c73df4af62b5d7..568a8a444c3975 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Reflection.Runtime.General; using System.Runtime; using System.Runtime.InteropServices; using System.Threading; @@ -105,7 +106,7 @@ internal static InstantiatedMethod GVMLookupForSlotWorker(DefType targetType, In sb.AppendLine(); sb.AppendLine("Declaring type: " + GetTypeNameDebug(slotMethod.OwningType)); sb.AppendLine("Target type: " + GetTypeNameDebug(targetType)); - sb.AppendLine("Method name: " + slotMethod.NameAndSignature.Name); + sb.AppendLine("Method name: " + slotMethod.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < slotMethod.Instantiation.Length; i++) { @@ -133,7 +134,7 @@ internal unsafe IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle type, sb.AppendLine("Failed to create generic virtual method implementation"); sb.AppendLine(); sb.AppendLine("Declaring type: " + GetTypeNameDebug(result.OwningType)); - sb.AppendLine("Method name: " + result.NameAndSignature.Name); + sb.AppendLine("Method name: " + result.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < result.Instantiation.Length; i++) { @@ -146,19 +147,9 @@ internal unsafe IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle type, return FunctionPointerOps.GetGenericMethodFunctionPointer(methodPointer, dictionaryPointer); } - private static MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, TypeManagerHandle moduleHandle, uint nativeLayoutOffset) + public static MethodNameAndSignature GetMethodNameAndSignatureFromToken(TypeManagerHandle moduleHandle, uint token) { - NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset); - - string methodName = parser.GetString(); - - // Signatures are indirected to through a relative offset so that we don't have to parse them - // when not comparing signatures (parsing them requires resolving types and is tremendously - // expensive). - NativeParser sigParser = parser.GetParserFromRelativeOffset(); - RuntimeSignature methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, sigParser.Offset); - - return new MethodNameAndSignature(methodName, methodSig); + return new MethodNameAndSignature(ModuleList.Instance.GetMetadataReaderForModule(moduleHandle), token.AsHandle().ToMethodHandle(null)); } private static RuntimeTypeHandle GetTypeDefinition(RuntimeTypeHandle typeHandle) @@ -191,7 +182,7 @@ private static InstantiatedMethod FindMatchingInterfaceSlot(NativeFormatModuleIn if (nameAndSigToken != SpecialGVMInterfaceEntry.Diamond && nameAndSigToken != SpecialGVMInterfaceEntry.Reabstraction) { - targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); + targetMethodNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, nameAndSigToken); targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); isDefaultInterfaceMethodImplementation = RuntimeAugments.IsInterface(targetTypeHandle); #if GVM_RESOLUTION_TRACE @@ -263,12 +254,23 @@ private static InstantiatedMethod FindMatchingInterfaceSlot(NativeFormatModuleIn DefType interfaceImplType; // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller - if (!RuntimeAugments.IsInterface(targetTypeHandle) || !RuntimeAugments.IsGenericTypeDefinition(targetTypeHandle)) + if (!RuntimeAugments.IsGenericTypeDefinition(targetTypeHandle)) { - // Not a default interface method or default interface method on a non-generic type. - // We have a usable type handle. + // No genericness involved, we can use the type as-is. interfaceImplType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle); } + else if (!isDefaultInterfaceMethodImplementation) + { + // Target type is in open form. We know the concrete form is somewhere in the inheritance hierarchy of targetType. + // This covers cases like: + // interface IFoo { void Frob(); } + // class Base { public void Frob() { } } + // class Derived : Base>, IFoo { } + // In the above case, targetTypeHandle is Base, targetType is Derived and we want Base>. + interfaceImplType = targetType; + while (!interfaceImplType.GetTypeDefinition().RuntimeTypeHandle.Equals(targetTypeHandle)) + interfaceImplType = (DefType)interfaceImplType.BaseType; + } else if (currentIfaceType.HasInstantiation && currentIfaceType.GetTypeDefinition().RuntimeTypeHandle.Equals(targetTypeHandle)) { // Default interface method implemented on the same type that declared the slot. @@ -357,7 +359,7 @@ private static InstantiatedMethod ResolveInterfaceGenericVirtualMethodSlot(DefTy continue; uint nameAndSigToken = entryParser.GetUnsigned(); - MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); + MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, nameAndSigToken); if (!interfaceMethodNameAndSignature.Equals(slotMethod.NameAndSignature)) continue; @@ -489,13 +491,13 @@ private static InstantiatedMethod ResolveGenericVirtualMethodTarget(DefType targ continue; uint parsedCallingNameAndSigToken = entryParser.GetUnsigned(); - MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedCallingNameAndSigToken); + MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(slotMethod.NameAndSignature)) continue; uint parsedTargetMethodNameAndSigToken = entryParser.GetUnsigned(); - MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedTargetMethodNameAndSigToken); + MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index dd2bc75e3d61d4..f28b55e5b0d6dc 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -11,6 +11,7 @@ using System.Text; using System.Threading; +using Internal.Metadata.NativeFormat; using Internal.NativeFormat; using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; @@ -22,79 +23,16 @@ namespace Internal.Runtime.TypeLoader { public sealed partial class TypeLoaderEnvironment { - [StructLayout(LayoutKind.Sequential)] - private struct DynamicFieldHandleInfo - { - public IntPtr DeclaringType; - public IntPtr FieldName; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct DynamicMethodHandleInfo - { - public IntPtr DeclaringType; - public IntPtr MethodName; - public RuntimeSignature MethodSignature; - public int NumGenericArgs; - public IntPtr GenericArgsArray; - } - - - #region String conversions - private static unsafe string GetStringFromMemoryInNativeFormat(IntPtr pointerToDataStream) - { - byte* dataStream = (byte*)pointerToDataStream; - uint stringLen = NativePrimitiveDecoder.DecodeUnsigned(ref dataStream); - return Encoding.UTF8.GetString(dataStream, checked((int)stringLen)); - } - - /// - /// From a string, get a pointer to an allocated memory location that holds a NativeFormat encoded string. - /// This is used for the creation of RuntimeFieldHandles from metadata. - /// - /// - /// - public unsafe IntPtr GetNativeFormatStringForString(string str) - { - using (_typeLoaderLock.EnterScope()) - { - IntPtr result; - if (_nativeFormatStrings.TryGetValue(str, out result)) - return result; - - NativePrimitiveEncoder stringEncoder = default; - stringEncoder.Init(); - byte[] utf8Bytes = Encoding.UTF8.GetBytes(str); - stringEncoder.WriteUnsigned(checked((uint)utf8Bytes.Length)); - foreach (byte b in utf8Bytes) - stringEncoder.WriteByte(b); - - void* allocatedNativeFormatString = MemoryHelpers.AllocateMemory(stringEncoder.Size); - unsafe - { - stringEncoder.Save((byte*)allocatedNativeFormatString, stringEncoder.Size); - } - _nativeFormatStrings.Add(str, (IntPtr)allocatedNativeFormatString); - return (IntPtr)allocatedNativeFormatString; - } - } - - private LowLevelDictionary _nativeFormatStrings = new LowLevelDictionary(); - #endregion - - #region Ldtoken Hashtables private struct RuntimeFieldHandleKey : IEquatable { private RuntimeTypeHandle _declaringType; - private string _fieldName; - private int _hashcode; + private FieldHandle _handle; - public RuntimeFieldHandleKey(RuntimeTypeHandle declaringType, string fieldName) + public RuntimeFieldHandleKey(RuntimeTypeHandle declaringType, FieldHandle fieldHandle) { _declaringType = declaringType; - _fieldName = fieldName; - _hashcode = declaringType.GetHashCode() ^ fieldName.GetHashCode(); + _handle = fieldHandle; } public override bool Equals(object obj) @@ -108,37 +46,27 @@ public override bool Equals(object obj) public bool Equals(RuntimeFieldHandleKey other) { - return other._declaringType.Equals(_declaringType) && other._fieldName == _fieldName; + return other._declaringType.Equals(_declaringType) && other._handle.Equals(_handle); } - public override int GetHashCode() { return _hashcode; } + public override int GetHashCode() => _declaringType.GetHashCode() ^ _handle.GetHashCode(); } private struct RuntimeMethodHandleKey : IEquatable { private RuntimeTypeHandle _declaringType; - private string _methodName; - private RuntimeSignature _signature; + private MethodHandle _handle; private RuntimeTypeHandle[] _genericArgs; - private int _hashcode; - public RuntimeMethodHandleKey(RuntimeTypeHandle declaringType, string methodName, RuntimeSignature signature, RuntimeTypeHandle[] genericArgs) + public RuntimeMethodHandleKey(RuntimeTypeHandle declaringType, MethodHandle handle, RuntimeTypeHandle[] genericArgs) { // genericArgs will be null if this is a (typical or not) method definition // genericArgs are non-null only for instantiated generic methods. Debug.Assert(genericArgs == null || genericArgs.Length > 0); _declaringType = declaringType; - _methodName = methodName; - _signature = signature; + _handle = handle; _genericArgs = genericArgs; - int methodNameHashCode = methodName == null ? 0 : methodName.GetHashCode(); - _hashcode = methodNameHashCode ^ signature.GetHashCode(); - - if (genericArgs != null) - _hashcode ^= TypeHashingAlgorithms.ComputeGenericInstanceHashCode(declaringType.GetHashCode(), genericArgs); - else - _hashcode ^= declaringType.GetHashCode(); } public override bool Equals(object obj) @@ -152,7 +80,7 @@ public override bool Equals(object obj) public bool Equals(RuntimeMethodHandleKey other) { - if (!_declaringType.Equals(other._declaringType) || _methodName != other._methodName || !_signature.Equals(other._signature)) + if (!_declaringType.Equals(other._declaringType) || !_handle.Equals(other._handle)) return false; if ((_genericArgs == null) != (other._genericArgs == null)) @@ -171,7 +99,10 @@ public bool Equals(RuntimeMethodHandleKey other) return true; } - public override int GetHashCode() { return _hashcode; } + public override int GetHashCode() + => _handle.GetHashCode() ^ (_genericArgs == null + ? _declaringType.GetHashCode() + : TypeHashingAlgorithms.ComputeGenericInstanceHashCode(_declaringType.GetHashCode(), _genericArgs)); } private LowLevelDictionary _runtimeFieldHandles = new LowLevelDictionary(); @@ -180,30 +111,23 @@ public bool Equals(RuntimeMethodHandleKey other) #region Field Ldtoken Functions - public RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName) + public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, int handle) { - IntPtr nameAsIntPtr = GetNativeFormatStringForString(fieldName); - return GetRuntimeFieldHandleForComponents(declaringTypeHandle, nameAsIntPtr); + return GetRuntimeFieldHandleForComponents(declaringTypeHandle, handle.AsHandle().ToFieldHandle(null)); } - public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, IntPtr fieldName) + public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle) { - string fieldNameStr = GetStringFromMemoryInNativeFormat(fieldName); - - RuntimeFieldHandleKey key = new RuntimeFieldHandleKey(declaringTypeHandle, fieldNameStr); - RuntimeFieldHandle runtimeFieldHandle = default(RuntimeFieldHandle); + RuntimeFieldHandleKey key = new RuntimeFieldHandleKey(declaringTypeHandle, handle); lock (_runtimeFieldHandles) { - if (!_runtimeFieldHandles.TryGetValue(key, out runtimeFieldHandle)) + if (!_runtimeFieldHandles.TryGetValue(key, out RuntimeFieldHandle runtimeFieldHandle)) { - DynamicFieldHandleInfo* fieldData = (DynamicFieldHandleInfo*)MemoryHelpers.AllocateMemory(sizeof(DynamicFieldHandleInfo)); - fieldData->DeclaringType = *(IntPtr*)&declaringTypeHandle; - fieldData->FieldName = fieldName; - - // Special flag (lowest bit set) in the handle value to indicate it was dynamically allocated - IntPtr runtimeFieldHandleValue = (IntPtr)fieldData + 1; - runtimeFieldHandle = *(RuntimeFieldHandle*)&runtimeFieldHandleValue; + FieldHandleInfo* fieldData = (FieldHandleInfo*)MemoryHelpers.AllocateMemory(sizeof(FieldHandleInfo)); + fieldData->DeclaringType = declaringTypeHandle; + fieldData->Handle = handle; + runtimeFieldHandle = RuntimeFieldHandle.FromIntPtr((nint)fieldData); _runtimeFieldHandles.Add(key, runtimeFieldHandle); } @@ -212,102 +136,50 @@ public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeH } } - public bool TryGetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) + public unsafe bool TryGetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle) { - return runtimeFieldHandle.IsDynamic() ? - TryGetDynamicRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName) : - TryGetStaticRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName); - } - - private unsafe bool TryGetDynamicRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) - { - IntPtr runtimeFieldHandleValue = *(IntPtr*)&runtimeFieldHandle; - - // Special flag in the handle value to indicate it was dynamically allocated - Debug.Assert((runtimeFieldHandleValue & 0x1) == 0x1); - - DynamicFieldHandleInfo* fieldData = (DynamicFieldHandleInfo*)(runtimeFieldHandleValue - 1); - declaringTypeHandle = *(RuntimeTypeHandle*)&(fieldData->DeclaringType); - - // FieldName points to the field name in NativeLayout format, so we parse it using a NativeParser - IntPtr fieldNamePtr = fieldData->FieldName; - fieldName = GetStringFromMemoryInNativeFormat(fieldNamePtr); - - return true; - } - - private unsafe bool TryGetStaticRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) - { - fieldName = null; - declaringTypeHandle = default(RuntimeTypeHandle); - - // Make sure it's not a dynamically allocated RuntimeFieldHandle before we attempt to use it to parse native layout data - Debug.Assert(((*(IntPtr*)&runtimeFieldHandle).ToInt64() & 0x1) == 0); - - RuntimeFieldHandleInfo* fieldData = *(RuntimeFieldHandleInfo**)&runtimeFieldHandle; - RuntimeSignature signature; - - // The native layout info signature is a pair. - // The first is a pointer that points to the TypeManager indirection cell. - // The second is the offset into the native layout info blob in that TypeManager, where the native signature is encoded. - IntPtr* nativeLayoutInfoSignatureData = (IntPtr*)fieldData->NativeLayoutInfoSignature; - - signature = RuntimeSignature.CreateFromNativeLayoutSignature( - new TypeManagerHandle(*(IntPtr*)nativeLayoutInfoSignatureData[0]), - (uint)nativeLayoutInfoSignatureData[1].ToInt32()); - - RuntimeSignature remainingSignature; - if (!GetTypeFromSignatureAndContext(signature, null, null, out declaringTypeHandle, out remainingSignature)) - return false; - - // GetTypeFromSignatureAndContext parses the type from the signature and returns a pointer to the next - // part of the native layout signature to read which we get the field name from - var reader = GetNativeLayoutInfoReader(remainingSignature); - var parser = new NativeParser(reader, remainingSignature.NativeLayoutOffset); - fieldName = parser.GetString(); - + FieldHandleInfo* fieldData = (FieldHandleInfo*)runtimeFieldHandle.Value; + declaringTypeHandle = fieldData->DeclaringType; + fieldHandle = fieldData->Handle; return true; } #endregion #region Method Ldtoken Functions + public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, int handle, RuntimeTypeHandle[] genericMethodArgs) + => GetRuntimeMethodHandleForComponents(declaringTypeHandle, handle.AsHandle().ToMethodHandle(null), genericMethodArgs); + /// /// Create a runtime method handle from name, signature and generic arguments. If the methodSignature /// is constructed from a metadata token, the methodName should be IntPtr.Zero, as it already encodes the method /// name. /// - public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, IntPtr methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) + public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs) { - string methodNameStr = methodName == IntPtr.Zero ? null : GetStringFromMemoryInNativeFormat(methodName); - - RuntimeMethodHandleKey key = new RuntimeMethodHandleKey(declaringTypeHandle, methodNameStr, methodSignature, genericMethodArgs); - RuntimeMethodHandle runtimeMethodHandle = default(RuntimeMethodHandle); + RuntimeMethodHandleKey key = new RuntimeMethodHandleKey(declaringTypeHandle, handle, genericMethodArgs); lock (_runtimeMethodHandles) { - if (!_runtimeMethodHandles.TryGetValue(key, out runtimeMethodHandle)) + if (!_runtimeMethodHandles.TryGetValue(key, out RuntimeMethodHandle runtimeMethodHandle)) { - int sizeToAllocate = sizeof(DynamicMethodHandleInfo); + int sizeToAllocate = sizeof(MethodHandleInfo); int numGenericMethodArgs = genericMethodArgs == null ? 0 : genericMethodArgs.Length; // Use checked arithmetics to ensure there aren't any overflows/truncations sizeToAllocate = checked(sizeToAllocate + (numGenericMethodArgs > 0 ? sizeof(IntPtr) * (numGenericMethodArgs - 1) : 0)); - DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)MemoryHelpers.AllocateMemory(sizeToAllocate); - methodData->DeclaringType = *(IntPtr*)&declaringTypeHandle; - methodData->MethodName = methodName; - methodData->MethodSignature = methodSignature; + MethodHandleInfo* methodData = (MethodHandleInfo*)MemoryHelpers.AllocateMemory(sizeToAllocate); + methodData->DeclaringType = declaringTypeHandle; + methodData->Handle = handle; methodData->NumGenericArgs = numGenericMethodArgs; - IntPtr* genericArgPtr = &(methodData->GenericArgsArray); + RuntimeTypeHandle* genericArgPtr = &methodData->FirstArgument; for (int i = 0; i < numGenericMethodArgs; i++) { RuntimeTypeHandle currentArg = genericMethodArgs[i]; - genericArgPtr[i] = *(IntPtr*)¤tArg; + genericArgPtr[i] = currentArg; } - // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob - IntPtr runtimeMethodHandleValue = (IntPtr)methodData + 1; - runtimeMethodHandle = *(RuntimeMethodHandle*)&runtimeMethodHandleValue; + runtimeMethodHandle = RuntimeMethodHandle.FromIntPtr((nint)methodData); _runtimeMethodHandles.Add(key, runtimeMethodHandle); } @@ -315,74 +187,16 @@ public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTyp return runtimeMethodHandle; } } - public RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) - { - IntPtr nameAsIntPtr = GetNativeFormatStringForString(methodName); - return GetRuntimeMethodHandleForComponents(declaringTypeHandle, nameAsIntPtr, methodSignature, genericMethodArgs); - } public MethodDesc GetMethodDescForRuntimeMethodHandle(TypeSystemContext context, RuntimeMethodHandle runtimeMethodHandle) { - return runtimeMethodHandle.IsDynamic() ? - GetMethodDescForDynamicRuntimeMethodHandle(context, runtimeMethodHandle) : - GetMethodDescForStaticRuntimeMethodHandle(context, runtimeMethodHandle); - } - - public bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) - { - return runtimeMethodHandle.IsDynamic() ? - TryGetDynamicRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs) : - TryGetStaticRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs); - } - - private unsafe bool TryGetDynamicRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) - { - IntPtr runtimeMethodHandleValue = *(IntPtr*)&runtimeMethodHandle; - - // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob - Debug.Assert((runtimeMethodHandleValue & 0x1) == 0x1); - - DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)(runtimeMethodHandleValue - 1); - - declaringTypeHandle = *(RuntimeTypeHandle*)&(methodData->DeclaringType); - genericMethodArgs = null; - - if (methodData->NumGenericArgs > 0) - { - IntPtr* genericArgPtr = &(methodData->GenericArgsArray); - genericMethodArgs = new RuntimeTypeHandle[methodData->NumGenericArgs]; - for (int i = 0; i < methodData->NumGenericArgs; i++) - { - genericMethodArgs[i] = *(RuntimeTypeHandle*)&(genericArgPtr[i]); - } - } - - if (methodData->MethodSignature.IsNativeLayoutSignature) - { - // MethodName points to the method name in NativeLayout format, so we parse it using a NativeParser - IntPtr methodNamePtr = methodData->MethodName; - string name = GetStringFromMemoryInNativeFormat(methodNamePtr); - - nameAndSignature = new MethodNameAndSignature(name, methodData->MethodSignature); - } - else - { - ModuleInfo moduleInfo = methodData->MethodSignature.GetModuleInfo(); - var metadataReader = ((NativeFormatModuleInfo)moduleInfo).MetadataReader; - var methodHandle = methodData->MethodSignature.Token.AsHandle().ToMethodHandle(metadataReader); - var method = methodHandle.GetMethod(metadataReader); - var name = metadataReader.GetConstantStringValue(method.Name).Value; - nameAndSignature = new MethodNameAndSignature(name, methodData->MethodSignature); - } - - return true; - } - public MethodDesc GetMethodDescForDynamicRuntimeMethodHandle(TypeSystemContext context, RuntimeMethodHandle runtimeMethodHandle) - { - bool success = TryGetDynamicRuntimeMethodHandleComponents(runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, - out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs); + bool success = TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, + out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs); Debug.Assert(success); + MetadataReader reader = ModuleList.Instance.GetMetadataReaderForModule(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)); + MethodNameAndSignature nameAndSignature = new MethodNameAndSignature(reader, handle); + DefType type = (DefType)context.ResolveRuntimeTypeHandle(declaringTypeHandle); if (genericMethodArgs != null) @@ -394,57 +208,40 @@ public MethodDesc GetMethodDescForDynamicRuntimeMethodHandle(TypeSystemContext c return context.ResolveRuntimeMethod(unboxingStub: false, type, nameAndSignature); } - private unsafe bool TryGetStaticRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) + public unsafe bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition handle, out RuntimeTypeHandle[] genericMethodArgs) { - declaringTypeHandle = default(RuntimeTypeHandle); - nameAndSignature = null; - genericMethodArgs = null; - - TypeSystemContext context = TypeSystemContextFactory.Create(); + if (TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out MethodHandle methodHandle, out genericMethodArgs)) + { + MetadataReader reader = ModuleList.Instance.GetMetadataReaderForModule(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)); + handle = new QMethodDefinition(reader, methodHandle); + return true; + } + handle = default; + return false; + } - MethodDesc parsedMethod = GetMethodDescForStaticRuntimeMethodHandle(context, runtimeMethodHandle); + public unsafe bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs) + { + MethodHandleInfo* methodData = (MethodHandleInfo*)runtimeMethodHandle.Value; - if (!EnsureTypeHandleForType(parsedMethod.OwningType)) - return false; + declaringTypeHandle = methodData->DeclaringType; + handle = methodData->Handle; - declaringTypeHandle = parsedMethod.OwningType.RuntimeTypeHandle; - nameAndSignature = parsedMethod.NameAndSignature; - if (!parsedMethod.IsMethodDefinition && parsedMethod.Instantiation.Length > 0) + if (methodData->NumGenericArgs > 0) { - genericMethodArgs = new RuntimeTypeHandle[parsedMethod.Instantiation.Length]; - for (int i = 0; i < parsedMethod.Instantiation.Length; ++i) + RuntimeTypeHandle* genericArgPtr = (RuntimeTypeHandle*)&methodData->FirstArgument; + genericMethodArgs = new RuntimeTypeHandle[methodData->NumGenericArgs]; + for (int i = 0; i < methodData->NumGenericArgs; i++) { - if (!EnsureTypeHandleForType(parsedMethod.Instantiation[i])) - return false; - - genericMethodArgs[i] = parsedMethod.Instantiation[i].RuntimeTypeHandle; + genericMethodArgs[i] = genericArgPtr[i]; } } - - TypeSystemContextFactory.Recycle(context); + else + { + genericMethodArgs = null; + } return true; } - - public unsafe MethodDesc GetMethodDescForStaticRuntimeMethodHandle(TypeSystemContext context, RuntimeMethodHandle runtimeMethodHandle) - { - // Make sure it's not a dynamically allocated RuntimeMethodHandle before we attempt to use it to parse native layout data - Debug.Assert(((*(IntPtr*)&runtimeMethodHandle).ToInt64() & 0x1) == 0); - - RuntimeMethodHandleInfo* methodData = *(RuntimeMethodHandleInfo**)&runtimeMethodHandle; - RuntimeSignature signature; - - // The native layout info signature is a pair. - // The first is a pointer that points to the TypeManager indirection cell. - // The second is the offset into the native layout info blob in that TypeManager, where the native signature is encoded. - IntPtr* nativeLayoutInfoSignatureData = (IntPtr*)methodData->NativeLayoutInfoSignature; - - signature = RuntimeSignature.CreateFromNativeLayoutSignature( - new TypeManagerHandle(*(IntPtr*)nativeLayoutInfoSignatureData[0]), - (uint)nativeLayoutInfoSignatureData[1].ToInt32()); - - RuntimeSignature remainingSignature; - return GetMethodFromSignatureAndContext(context, signature, null, null, out remainingSignature); - } #endregion } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index 6c94d937a87382..0545b31ada272c 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -414,7 +414,7 @@ internal static IntPtr TryGetDefaultConstructorForType(TypeDesc type) { if (type is DefType defType) { - CanonicallyEquivalentEntryLocator canonHelperSpecific = new CanonicallyEquivalentEntryLocator(defType, CanonicalFormKind.Specific); + CanonicallyEquivalentEntryLocator canonHelperSpecific = new CanonicallyEquivalentEntryLocator(defType); foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules()) { @@ -436,7 +436,7 @@ internal static IntPtr TryGetDefaultConstructorForType(TypeDesc type) /// Function pointer representing the constructor, IntPtr.Zero when not found public IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle) { - CanonicallyEquivalentEntryLocator canonHelperSpecific = new CanonicallyEquivalentEntryLocator(runtimeTypeHandle, CanonicalFormKind.Specific); + CanonicallyEquivalentEntryLocator canonHelperSpecific = new CanonicallyEquivalentEntryLocator(runtimeTypeHandle); foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(runtimeTypeHandle))) { @@ -495,11 +495,12 @@ public struct VirtualResolveDataResult public bool IsGVM; } - public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, - RuntimeTypeHandle methodHandleDeclaringType, RuntimeTypeHandle[] genericArgs, - ref MethodSignatureComparer methodSignatureComparer, + public static bool TryGetVirtualResolveData( + RuntimeTypeHandle methodHandleDeclaringType, QMethodDefinition method, RuntimeTypeHandle[] genericArgs, out VirtualResolveDataResult lookupResult) { + NativeFormatModuleInfo module = ModuleList.Instance.GetModuleInfoForMetadataReader(method.NativeFormatReader); + lookupResult = default(VirtualResolveDataResult); NativeReader invokeMapReader = GetNativeReaderForBlob(module, ReflectionMapBlob.VirtualInvokeMap); NativeParser invokeMapParser = new NativeParser(invokeMapReader, 0); @@ -520,9 +521,7 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, // of the method's containing type instead of the open type definition. // - CanonicallyEquivalentEntryLocator canonHelper = new CanonicallyEquivalentEntryLocator( - methodHandleDeclaringType, - CanonicalFormKind.Specific); + CanonicallyEquivalentEntryLocator canonHelper = new CanonicallyEquivalentEntryLocator(methodHandleDeclaringType); var lookup = invokeHashtable.Lookup(canonHelper.LookupHashCode); @@ -531,19 +530,18 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, { // Grammar of an entry in the hash table: // Virtual Method uses a normal slot - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1) + slot + // TypeKey + Handle + (NumberOfStepsUpParentHierarchyToType << 1) + slot // OR // Generic Virtual Method - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1 + 1) + // TypeKey + Handle + (NumberOfStepsUpParentHierarchyToType << 1 + 1) RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!canonHelper.IsCanonicallyEquivalent(entryType)) continue; - uint nameAndSigPointerToken = entryParser.GetUnsigned(); + int token = (int)entryParser.GetUnsigned(); - MethodNameAndSignature nameAndSig = TypeLoaderEnvironment.Instance.GetMethodNameAndSignatureFromNativeLayoutOffset(module.Handle, nameAndSigPointerToken); - if (!methodSignatureComparer.IsMatchingNativeLayoutMethodNameAndSignature(nameAndSig.Name, nameAndSig.Signature)) + if (!token.AsHandle().ToMethodHandle(module.MetadataReader).Equals(method.NativeFormatHandle)) { continue; } @@ -567,16 +565,7 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, if (isGenericVirtualMethod) { - RuntimeSignature methodName; - RuntimeSignature methodSignature; - - if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignaturePointersFromNativeLayoutSignature(module.Handle, nameAndSigPointerToken, out methodName, out methodSignature)) - { - Debug.Assert(false); - return false; - } - - RuntimeMethodHandle gvmSlot = TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeOfVirtualInvoke, methodName.NativeLayoutSignature(), methodSignature, genericArgs); + RuntimeMethodHandle gvmSlot = TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeOfVirtualInvoke, token, genericArgs); lookupResult = new VirtualResolveDataResult { @@ -610,16 +599,12 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, /// Declaring type for the method /// Method handle /// Handles of generic argument types - /// Helper class used to compare method signatures - /// Canonical form to use /// Output - metadata information for method invoker construction /// true when found, false otherwise public static bool TryGetMethodInvokeMetadata( RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles, - ref MethodSignatureComparer methodSignatureComparer, - CanonicalFormKind canonFormKind, out MethodInvokeMetadata methodInvokeMetadata) { if (methodHandle.IsNativeFormatMetadataBased) @@ -629,8 +614,6 @@ public static bool TryGetMethodInvokeMetadata( declaringTypeHandle, methodHandle.NativeFormatHandle, genericMethodTypeArgumentHandles, - ref methodSignatureComparer, - canonFormKind, out methodInvokeMetadata)) { return true; @@ -648,8 +631,6 @@ public static bool TryGetMethodInvokeMetadata( /// Declaring type for the method /// Method handle /// Handles of generic argument types - /// Helper class used to compare method signatures - /// Canonical form to use /// Output - metadata information for method invoker construction /// true when found, false otherwise private static bool TryGetMethodInvokeMetadataFromInvokeMap( @@ -657,11 +638,9 @@ private static bool TryGetMethodInvokeMetadataFromInvokeMap( RuntimeTypeHandle declaringTypeHandle, MethodHandle methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles, - ref MethodSignatureComparer methodSignatureComparer, - CanonicalFormKind canonFormKind, out MethodInvokeMetadata methodInvokeMetadata) { - CanonicallyEquivalentEntryLocator canonHelper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind); + CanonicallyEquivalentEntryLocator canonHelper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle); TypeManagerHandle methodHandleModule = ModuleList.Instance.GetModuleForMetadataReader(metadataReader); foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle))) @@ -681,7 +660,6 @@ private static bool TryGetMethodInvokeMetadataFromInvokeMap( var lookup = invokeHashtable.Lookup(canonHelper.LookupHashCode); var entryData = new InvokeMapEntryDataEnumerator( new PreloadedTypeComparator(declaringTypeHandle, genericMethodTypeArgumentHandles), - canonFormKind, module.Handle, methodHandle, methodHandleModule); @@ -689,7 +667,7 @@ private static bool TryGetMethodInvokeMetadataFromInvokeMap( NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { - entryData.GetNext(ref entryParser, ref externalReferences, ref methodSignatureComparer, canonHelper); + entryData.GetNext(ref entryParser, ref externalReferences, canonHelper); if (!entryData.IsMatchingOrCompatibleEntry()) continue; @@ -778,7 +756,6 @@ private struct InvokeMapEntryDataEnumerator - /// Metadata reader corresponding to the method declaring type - /// - private readonly MetadataReader _metadataReader; - - /// - /// Method handle - /// - private readonly MethodHandle _methodHandle; - - /// - /// Method instance obtained from the method handle - /// - private readonly Method _method; - - /// - /// Method signature - /// - private readonly MethodSignature _methodSignature; - - /// - /// true = this is a static method - /// - private readonly bool _isStatic; - - /// - /// true = this is a generic method - /// - private readonly bool _isGeneric; - - public MethodSignatureComparer( - QMethodDefinition methodHandle) - { - if (methodHandle.IsNativeFormatMetadataBased) - { - _metadataReader = methodHandle.NativeFormatReader; - _methodHandle = methodHandle.NativeFormatHandle; - - _method = _methodHandle.GetMethod(_metadataReader); - - _methodSignature = _method.Signature.GetMethodSignature(_metadataReader); - _isGeneric = (_methodSignature.GenericParameterCount != 0); - - // Precalculate initial method attributes used in signature queries - _isStatic = (_method.Flags & MethodAttributes.Static) != 0; - } - else - { - _metadataReader = null; - _methodHandle = default(MethodHandle); - _method = default(Method); - _methodSignature = default(MethodSignature); - _isGeneric = false; - _isStatic = false; - } - } - - /// - /// Construct a comparer between NativeFormat metadata methods and native layouts - /// - /// Metadata reader for the method declaring type - /// Handle of method to compare - public MethodSignatureComparer( - MetadataReader metadataReader, - MethodHandle methodHandle) - { - _metadataReader = metadataReader; - _methodHandle = methodHandle; - - _method = methodHandle.GetMethod(metadataReader); - - _methodSignature = _method.Signature.GetMethodSignature(_metadataReader); - _isGeneric = (_methodSignature.GenericParameterCount != 0); - - // Precalculate initial method attributes used in signature queries - _isStatic = (_method.Flags & MethodAttributes.Static) != 0; - } - - public bool IsMatchingNativeLayoutMethodNameAndSignature(string name, RuntimeSignature signature) - { - return _method.Name.StringEquals(name, _metadataReader) && - IsMatchingNativeLayoutMethodSignature(signature); - } - - public bool IsMatchingNativeLayoutMethodSignature(RuntimeSignature signature) - { - NativeParser parser = GetNativeParserForSignature(signature); - - if (!CompareCallingConventions((MethodCallingConvention)parser.GetUnsigned())) - return false; - - if (_isGeneric) - { - uint genericParamCount1 = parser.GetUnsigned(); - int genericParamCount2 = _methodSignature.GenericParameterCount; - - if (genericParamCount1 != genericParamCount2) - return false; - } - - uint parameterCount = parser.GetUnsigned(); - - if (!CompareTypeSigWithType(ref parser, new TypeManagerHandle(signature.ModuleHandle), _methodSignature.ReturnType)) - { - return false; - } - - uint parameterIndexToMatch = 0; - foreach (Handle parameterSignature in _methodSignature.Parameters) - { - if (parameterIndexToMatch >= parameterCount) - { - // The metadata-defined _method has more parameters than the native layout - return false; - } - if (!CompareTypeSigWithType(ref parser, new TypeManagerHandle(signature.ModuleHandle), parameterSignature)) - return false; - parameterIndexToMatch++; - } - - // Make sure that all native layout parameters have been matched - return parameterIndexToMatch == parameterCount; - } - - /// - /// Look up module containing given nativesignature and return the appropriate native parser. - /// - /// Signature to look up - /// Native parser for the signature - internal static NativeParser GetNativeParserForSignature(RuntimeSignature signature) - { - Debug.Assert(signature.IsNativeLayoutSignature); - NativeFormatModuleInfo module = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature.ModuleHandle)); - - NativeReader reader = TypeLoaderEnvironment.GetNativeReaderForBlob(module, ReflectionMapBlob.NativeLayoutInfo); - return new NativeParser(reader, signature.NativeLayoutOffset); - } - - private bool CompareTypeSigWithType(ref NativeParser parser, TypeManagerHandle moduleHandle, Handle typeHandle) - { - while (typeHandle.HandleType == HandleType.TypeSpecification - || typeHandle.HandleType == HandleType.ModifiedType) - { - if (typeHandle.HandleType == HandleType.TypeSpecification) - { - typeHandle = typeHandle - .ToTypeSpecificationHandle(_metadataReader) - .GetTypeSpecification(_metadataReader) - .Signature; - } - else - { - typeHandle = typeHandle - .ToModifiedTypeHandle(_metadataReader) - .GetModifiedType(_metadataReader) - .Type; - } - } - - // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader - // expects to read it in. - uint startOffset = parser.Offset; - - uint data; - var typeSignatureKind = parser.GetTypeSignatureKind(out data); - - switch (typeSignatureKind) - { - case TypeSignatureKind.Lookback: - { - NativeParser lookbackParser = parser.GetLookbackParser(data); - return CompareTypeSigWithType(ref lookbackParser, moduleHandle, typeHandle); - } - - case TypeSignatureKind.Modifier: - { - // Ensure the modifier kind (vector, pointer, byref) is the same - TypeModifierKind modifierKind = (TypeModifierKind)data; - switch (modifierKind) - { - case TypeModifierKind.Array: - if (typeHandle.HandleType == HandleType.SZArraySignature) - { - return CompareTypeSigWithType(ref parser, moduleHandle, typeHandle - .ToSZArraySignatureHandle(_metadataReader) - .GetSZArraySignature(_metadataReader) - .ElementType); - } - return false; - - case TypeModifierKind.ByRef: - if (typeHandle.HandleType == HandleType.ByReferenceSignature) - { - return CompareTypeSigWithType(ref parser, moduleHandle, typeHandle - .ToByReferenceSignatureHandle(_metadataReader) - .GetByReferenceSignature(_metadataReader) - .Type); - } - return false; - - case TypeModifierKind.Pointer: - if (typeHandle.HandleType == HandleType.PointerSignature) - { - return CompareTypeSigWithType(ref parser, moduleHandle, typeHandle - .ToPointerSignatureHandle(_metadataReader) - .GetPointerSignature(_metadataReader) - .Type); - } - return false; - - default: - Debug.Assert(null == "invalid type modifier kind"); - return false; - } - } - - case TypeSignatureKind.Variable: - { - bool isMethodVar = (data & 0x1) == 1; - uint index = data >> 1; - - if (isMethodVar) - { - if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature) - { - return index == typeHandle - .ToMethodTypeVariableSignatureHandle(_metadataReader) - .GetMethodTypeVariableSignature(_metadataReader) - .Number; - } - } - else - { - if (typeHandle.HandleType == HandleType.TypeVariableSignature) - { - return index == typeHandle - .ToTypeVariableSignatureHandle(_metadataReader) - .GetTypeVariableSignature(_metadataReader) - .Number; - } - } - - return false; - } - - case TypeSignatureKind.MultiDimArray: - { - if (typeHandle.HandleType != HandleType.ArraySignature) - { - return false; - } - - ArraySignature sig = typeHandle - .ToArraySignatureHandle(_metadataReader) - .GetArraySignature(_metadataReader); - - if (data != sig.Rank) - return false; - - if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.ElementType)) - return false; - - uint boundCount1 = parser.GetUnsigned(); - for (uint i = 0; i < boundCount1; i++) - { - parser.GetUnsigned(); - } - - uint lowerBoundCount1 = parser.GetUnsigned(); - - for (uint i = 0; i < lowerBoundCount1; i++) - { - parser.GetUnsigned(); - } - break; - } - - case TypeSignatureKind.FunctionPointer: - { - // callingConvention is in data - uint argCount1 = parser.GetUnsigned(); - - for (uint i = 0; i < argCount1; i++) - { - if (!CompareTypeSigWithType(ref parser, moduleHandle, typeHandle)) - return false; - } - return false; - } - - case TypeSignatureKind.Instantiation: - { - if (typeHandle.HandleType != HandleType.TypeInstantiationSignature) - { - return false; - } - - TypeInstantiationSignature sig = typeHandle - .ToTypeInstantiationSignatureHandle(_metadataReader) - .GetTypeInstantiationSignature(_metadataReader); - - if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.GenericType)) - { - return false; - } - - uint genericArgIndex = 0; - foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments) - { - if (genericArgIndex >= data) - { - // The metadata generic has more parameters than the native layour - return false; - } - if (!CompareTypeSigWithType(ref parser, moduleHandle, genericArgumentTypeHandle)) - { - return false; - } - genericArgIndex++; - } - // Make sure all generic parameters have been matched - return genericArgIndex == data; - } - - case TypeSignatureKind.BuiltIn: - case TypeSignatureKind.External: - { - RuntimeTypeHandle type2; - switch (typeHandle.HandleType) - { - case HandleType.TypeDefinition: - if (!TypeLoaderEnvironment.TryGetNamedTypeForMetadata( - new QTypeDefinition(_metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader)), out type2)) - { - return false; - } - break; - - default: - return false; - } - - RuntimeTypeHandle type1; - if (typeSignatureKind == TypeSignatureKind.External) - { - type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, moduleHandle, startOffset); - } - else - { - type1 = ((Internal.TypeSystem.WellKnownType)data).GetRuntimeTypeHandle(); - } - - return type1.Equals(type2); - } - - default: - return false; - } - return true; - } - - private bool CompareCallingConventions(MethodCallingConvention callingConvention) - { - return (callingConvention.HasFlag(MethodCallingConvention.Static) == _isStatic) && - (callingConvention.HasFlag(MethodCallingConvention.Generic) == _isGeneric); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs index bc9c208f472f10..eef4c2e793f8cf 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs @@ -22,340 +22,18 @@ namespace Internal.Runtime.TypeLoader { public sealed partial class TypeLoaderEnvironment { - public bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2) - { - if (signature1.IsNativeLayoutSignature && signature2.IsNativeLayoutSignature) - { - if (signature1.StructuralEquals(signature2)) - return true; - - NativeFormatModuleInfo module1 = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature1.ModuleHandle)); - NativeReader reader1 = GetNativeLayoutInfoReader(signature1); - NativeParser parser1 = new NativeParser(reader1, signature1.NativeLayoutOffset); - - NativeFormatModuleInfo module2 = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature2.ModuleHandle)); - NativeReader reader2 = GetNativeLayoutInfoReader(signature2); - NativeParser parser2 = new NativeParser(reader2, signature2.NativeLayoutOffset); - - return CompareMethodSigs(parser1, module1, parser2, module2); - } - else if (signature1.IsNativeLayoutSignature) - { - int token = signature2.Token; - MetadataReader metadataReader = ModuleList.Instance.GetMetadataReaderForModule(new TypeManagerHandle(signature2.ModuleHandle)); - - MethodSignatureComparer comparer = new MethodSignatureComparer(metadataReader, token.AsHandle().ToMethodHandle(metadataReader)); - return comparer.IsMatchingNativeLayoutMethodSignature(signature1); - } - else if (signature2.IsNativeLayoutSignature) - { - int token = signature1.Token; - MetadataReader metadataReader = ModuleList.Instance.GetMetadataReaderForModule(new TypeManagerHandle(signature1.ModuleHandle)); - - MethodSignatureComparer comparer = new MethodSignatureComparer(metadataReader, token.AsHandle().ToMethodHandle(metadataReader)); - return comparer.IsMatchingNativeLayoutMethodSignature(signature2); - } - else - { - // For now, RuntimeSignatures are only used to compare for method signature equality (along with their Name) - // So we can implement this with the simple equals check - if (signature1.Token != signature2.Token) - return false; - - if (signature1.ModuleHandle != signature2.ModuleHandle) - return false; - - return true; - } - } - public static bool IsStaticMethodSignature(MethodNameAndSignature signature) { - Debug.Assert(signature.Signature.IsNativeLayoutSignature); - NativeReader reader = GetNativeLayoutInfoReader(signature.Signature); - NativeParser parser = new NativeParser(reader, signature.Signature.NativeLayoutOffset); - - MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); - return (callingConvention & MethodCallingConvention.Static) != 0; + var method = signature.Handle.GetMethod(signature.Reader); + return (method.Flags & MethodAttributes.Static) != 0; } public uint GetGenericArgumentCountFromMethodNameAndSignature(MethodNameAndSignature signature) { - if (signature.Signature.IsNativeLayoutSignature) - { - NativeReader reader = GetNativeLayoutInfoReader(signature.Signature); - NativeParser parser = new NativeParser(reader, signature.Signature.NativeLayoutOffset); - - return GetGenericArgCountFromSig(parser); - } - else - { - ModuleInfo module = signature.Signature.GetModuleInfo(); - NativeFormatModuleInfo nativeFormatModule = (NativeFormatModuleInfo)module; - var metadataReader = nativeFormatModule.MetadataReader; - var methodHandle = signature.Signature.Token.AsHandle().ToMethodHandle(metadataReader); - - var method = methodHandle.GetMethod(metadataReader); - var methodSignature = method.Signature.GetMethodSignature(metadataReader); - return checked((uint)methodSignature.GenericParameterCount); - } - } - - public bool TryGetMethodNameAndSignaturePointersFromNativeLayoutSignature(TypeManagerHandle module, uint methodNameAndSigToken, out RuntimeSignature methodNameSig, out RuntimeSignature methodSig) - { - methodNameSig = default(RuntimeSignature); - methodSig = default(RuntimeSignature); - - NativeReader reader = GetNativeLayoutInfoReader(module); - NativeParser parser = new NativeParser(reader, methodNameAndSigToken); - if (parser.IsNull) - return false; - - methodNameSig = RuntimeSignature.CreateFromNativeLayoutSignature(module, parser.Offset); - parser.SkipString(); // methodName - - // Signatures are indirected to through a relative offset so that we don't have to parse them - // when not comparing signatures (parsing them requires resolving types and is tremendously - // expensive). - NativeParser sigParser = parser.GetParserFromRelativeOffset(); - methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(module, sigParser.Offset); - - return true; - } - - public MethodNameAndSignature GetMethodNameAndSignatureFromNativeLayoutOffset(TypeManagerHandle moduleHandle, uint nativeLayoutOffset) - { - NativeReader reader = GetNativeLayoutInfoReader(moduleHandle); - NativeParser parser = new NativeParser(reader, nativeLayoutOffset); - return GetMethodNameAndSignature(ref parser, moduleHandle, out _, out _); - } - - internal static MethodNameAndSignature GetMethodNameAndSignature(ref NativeParser parser, TypeManagerHandle moduleHandle, out RuntimeSignature methodNameSig, out RuntimeSignature methodSig) - { - methodNameSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, parser.Offset); - string methodName = parser.GetString(); - - // Signatures are indirected to through a relative offset so that we don't have to parse them - // when not comparing signatures (parsing them requires resolving types and is tremendously - // expensive). - NativeParser sigParser = parser.GetParserFromRelativeOffset(); - methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, sigParser.Offset); - - return new MethodNameAndSignature(methodName, methodSig); - } - - #region Private Helpers - - private static RuntimeTypeHandle GetExternalTypeHandle(NativeFormatModuleInfo moduleHandle, uint typeIndex) - { - Debug.Assert(moduleHandle != null); - - RuntimeTypeHandle result; - - TypeSystemContext context = TypeSystemContextFactory.Create(); - { - NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); - nativeLayoutContext._module = moduleHandle; - nativeLayoutContext._typeSystemContext = context; - - TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex); - result = type.RuntimeTypeHandle; - } - TypeSystemContextFactory.Recycle(context); - - Debug.Assert(!result.IsNull()); - return result; - } - - private static uint GetGenericArgCountFromSig(NativeParser parser) - { - MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); - - if ((callingConvention & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) - { - return parser.GetUnsigned(); - } - else - { - return 0; - } - } - - private static bool CompareMethodSigs(NativeParser parser1, NativeFormatModuleInfo moduleHandle1, NativeParser parser2, NativeFormatModuleInfo moduleHandle2) - { - MethodCallingConvention callingConvention1 = (MethodCallingConvention)parser1.GetUnsigned(); - MethodCallingConvention callingConvention2 = (MethodCallingConvention)parser2.GetUnsigned(); - - if (callingConvention1 != callingConvention2) - return false; - - if ((callingConvention1 & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) - { - if (parser1.GetUnsigned() != parser2.GetUnsigned()) - return false; - } - - uint parameterCount1 = parser1.GetUnsigned(); - uint parameterCount2 = parser2.GetUnsigned(); - if (parameterCount1 != parameterCount2) - return false; - - // Compare one extra parameter to account for the return type - for (uint i = 0; i <= parameterCount1; i++) - { - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - } - - return true; - } - - private static bool CompareTypeSigs(ref NativeParser parser1, NativeFormatModuleInfo moduleHandle1, ref NativeParser parser2, NativeFormatModuleInfo moduleHandle2) - { - // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader - // expects to read it in. - uint data1; - uint startOffset1 = parser1.Offset; - var typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1); - - // If the parser is at a lookback type, get a new parser for it and recurse. - // Since we haven't read the element type of parser2 yet, we just pass it in unchanged - if (typeSignatureKind1 == TypeSignatureKind.Lookback) - { - NativeParser lookbackParser1 = parser1.GetLookbackParser(data1); - return CompareTypeSigs(ref lookbackParser1, moduleHandle1, ref parser2, moduleHandle2); - } - - uint data2; - var typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2); - - // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1 - // before recursing. - if (typeSignatureKind2 == TypeSignatureKind.Lookback) - { - NativeParser lookbackParser2 = parser2.GetLookbackParser(data2); - parser1 = new NativeParser(parser1.Reader, startOffset1); - return CompareTypeSigs(ref parser1, moduleHandle1, ref lookbackParser2, moduleHandle2); - } - - if (typeSignatureKind1 != typeSignatureKind2) - return false; - - switch (typeSignatureKind1) - { - case TypeSignatureKind.Lookback: - { - // Recursion above better have removed all lookbacks - Debug.Fail("Unexpected lookback type"); - return false; - } - - case TypeSignatureKind.Modifier: - { - // Ensure the modifier kind (vector, pointer, byref) is the same - if (data1 != data2) - return false; - return CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2); - } - - case TypeSignatureKind.Variable: - { - // variable index is in data - if (data1 != data2) - return false; - break; - } - - case TypeSignatureKind.MultiDimArray: - { - // rank is in data - if (data1 != data2) - return false; - - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - - uint boundCount1 = parser1.GetUnsigned(); - uint boundCount2 = parser2.GetUnsigned(); - if (boundCount1 != boundCount2) - return false; - - for (uint i = 0; i < boundCount1; i++) - { - if (parser1.GetUnsigned() != parser2.GetUnsigned()) - return false; - } - - uint lowerBoundCount1 = parser1.GetUnsigned(); - uint lowerBoundCount2 = parser2.GetUnsigned(); - if (lowerBoundCount1 != lowerBoundCount2) - return false; - - for (uint i = 0; i < lowerBoundCount1; i++) - { - if (parser1.GetUnsigned() != parser2.GetUnsigned()) - return false; - } - break; - } - - case TypeSignatureKind.FunctionPointer: - { - // callingConvention is in data - if (data1 != data2) - return false; - uint argCount1 = parser1.GetUnsigned(); - uint argCount2 = parser2.GetUnsigned(); - if (argCount1 != argCount2) - return false; - for (uint i = 0; i < argCount1; i++) - { - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - } - break; - } - - case TypeSignatureKind.Instantiation: - { - // Type parameter count is in data - if (data1 != data2) - return false; - - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - - for (uint i = 0; i < data1; i++) - { - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - } - break; - } - - case TypeSignatureKind.BuiltIn: - RuntimeTypeHandle typeHandle3 = ((WellKnownType)data1).GetRuntimeTypeHandle(); - RuntimeTypeHandle typeHandle4 = ((WellKnownType)data2).GetRuntimeTypeHandle(); - if (!typeHandle3.Equals(typeHandle4)) - return false; - - break; - - case TypeSignatureKind.External: - { - RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(moduleHandle1, data1); - RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(moduleHandle2, data2); - if (!typeHandle1.Equals(typeHandle2)) - return false; - - break; - } - - default: - return false; - } - return true; + var metadataReader = signature.Reader; + var method = signature.Handle.GetMethod(metadataReader); + var methodSignature = method.Signature.GetMethodSignature(metadataReader); + return checked((uint)methodSignature.GenericParameterCount); } - #endregion } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index 22c07b2e837bc6..cb1b6462ab3fe6 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -48,19 +48,9 @@ public override IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntP return TypeLoaderEnvironment.Instance.GenericLookupFromContextAndSignature(context, signature, out auxResult); } - public override bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) + public override RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs) { - return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs); - } - - public override RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) - { - return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeHandle, methodName, methodSignature, genericMethodArgs); - } - - public override bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2) - { - return TypeLoaderEnvironment.Instance.CompareMethodSignatures(signature1, signature2); + return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeHandle, handle, genericMethodArgs); } public override IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle) @@ -73,14 +63,9 @@ public override IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targe return TypeLoaderEnvironment.Instance.ResolveGenericVirtualMethodTarget(targetTypeHandle, declMethod); } - public override bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) - { - return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName); - } - - public override RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName) + public override RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle) { - return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents(declaringTypeHandle, fieldName); + return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents(declaringTypeHandle, handle); } public override IntPtr ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(IntPtr unboxingFunctionPointer, RuntimeTypeHandle declaringType) @@ -99,18 +84,6 @@ public override bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementType } } - public static class RuntimeSignatureExtensions - { - public static IntPtr NativeLayoutSignature(this RuntimeSignature signature) - { - if (!signature.IsNativeLayoutSignature) - Environment.FailFast("Not a valid native layout signature"); - - NativeReader reader = TypeLoaderEnvironment.GetNativeLayoutInfoReader(signature); - return reader.OffsetToAddress(signature.NativeLayoutOffset); - } - } - public sealed partial class TypeLoaderEnvironment { [ThreadStatic] @@ -210,67 +183,6 @@ private bool EnsureTypeHandleForType(TypeDesc type) return !type.RuntimeTypeHandle.IsNull(); } - // - // Parse a native layout signature pointed to by "signature" in the executable image, optionally using - // "typeArgs" and "methodArgs" for generic type parameter substitution. The first field in "signature" - // must be an encoded type but any data beyond that is user-defined and returned in "remainingSignature" - // - internal bool GetTypeFromSignatureAndContext(RuntimeSignature signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out RuntimeSignature remainingSignature) - { - NativeReader reader = GetNativeLayoutInfoReader(signature); - NativeParser parser = new NativeParser(reader, signature.NativeLayoutOffset); - - bool result = GetTypeFromSignatureAndContext(ref parser, new TypeManagerHandle(signature.ModuleHandle), typeArgs, methodArgs, out createdType); - - remainingSignature = RuntimeSignature.CreateFromNativeLayoutSignature(signature, parser.Offset); - - return result; - } - - internal bool GetTypeFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType) - { - createdType = default(RuntimeTypeHandle); - TypeSystemContext context = TypeSystemContextFactory.Create(); - - TypeDesc parsedType = TryParseNativeSignatureWorker(context, moduleHandle, ref parser, typeArgs, methodArgs, false) as TypeDesc; - if (parsedType == null) - return false; - - if (!EnsureTypeHandleForType(parsedType)) - return false; - - createdType = parsedType.RuntimeTypeHandle; - - TypeSystemContextFactory.Recycle(context); - return true; - } - - // - // Parse a native layout signature pointed to by "signature" in the executable image, optionally using - // "typeArgs" and "methodArgs" for generic type parameter substitution. The first field in "signature" - // must be an encoded method but any data beyond that is user-defined and returned in "remainingSignature" - // - public MethodDesc GetMethodFromSignatureAndContext(TypeSystemContext context, RuntimeSignature signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeSignature remainingSignature) - { - NativeReader reader = GetNativeLayoutInfoReader(signature); - NativeParser parser = new NativeParser(reader, signature.NativeLayoutOffset); - - MethodDesc result = TryParseNativeSignatureWorker(context, new TypeManagerHandle(signature.ModuleHandle), ref parser, typeArgs, methodArgs, true) as MethodDesc; - - remainingSignature = RuntimeSignature.CreateFromNativeLayoutSignature(signature, parser.Offset); - - return result; - } - - // - // Returns the native layout info reader - // - internal static unsafe NativeReader GetNativeLayoutInfoReader(RuntimeSignature signature) - { - Debug.Assert(signature.IsNativeLayoutSignature); - return GetNativeLayoutInfoReader(new TypeManagerHandle(signature.ModuleHandle)); - } - // // Returns the native layout info reader // @@ -463,23 +375,6 @@ public int GetCanonicalHashCode(RuntimeTypeHandle typeHandle, CanonicalFormKind return hashCode; } - private static object TryParseNativeSignatureWorker(TypeSystemContext typeSystemContext, TypeManagerHandle moduleHandle, ref NativeParser parser, RuntimeTypeHandle[] typeGenericArgumentHandles, RuntimeTypeHandle[] methodGenericArgumentHandles, bool isMethodSignature) - { - Instantiation typeGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(typeGenericArgumentHandles ?? Array.Empty()); - Instantiation methodGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(methodGenericArgumentHandles ?? Array.Empty()); - - NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); - nativeLayoutContext._module = ModuleList.Instance.GetModuleInfoByHandle(moduleHandle); - nativeLayoutContext._typeSystemContext = typeSystemContext; - nativeLayoutContext._typeArgumentHandles = typeGenericArguments; - nativeLayoutContext._methodArgumentHandles = methodGenericArguments; - - if (isMethodSignature) - return nativeLayoutContext.GetMethod(ref parser); - else - return nativeLayoutContext.GetType(ref parser); - } - public bool TryGetGenericMethodDictionaryForComponents(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericMethodArgHandles, MethodNameAndSignature nameAndSignature, out IntPtr methodDictionary) { TypeSystemContext context = TypeSystemContextFactory.Create(); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/CanonTypes.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/CanonTypes.Runtime.cs index 05f4d6829bc599..b8c4d8b3e9ba81 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/CanonTypes.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/CanonTypes.Runtime.cs @@ -15,15 +15,7 @@ internal partial class CanonType { partial void Initialize() { - SetRuntimeTypeHandleUnsafe(RuntimeAugments.GetCanonType(CanonTypeKind.NormalCanon)); - } - } - - internal partial class UniversalCanonType - { - partial void Initialize() - { - SetRuntimeTypeHandleUnsafe(RuntimeAugments.GetCanonType(CanonTypeKind.UniversalCanon)); + SetRuntimeTypeHandleUnsafe(RuntimeAugments.GetCanonType()); } } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs index 042b1957e22b65..9df61f9ad7f1bc 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs @@ -93,7 +93,7 @@ public override string Name { get { - return _nameAndSignature.Name; + return NameAndSignature.GetName(); } } @@ -163,7 +163,7 @@ public override bool HasCustomAttribute(string attributeNamespace, string attrib public override string ToString() { - string result = OwningType.ToString() + ".Method(" + NameAndSignature.Name + ")"; + string result = OwningType.ToString() + ".Method(" + Name + ")"; return result; } #endif diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs index 96c8c5ea2ac201..295d5b9a48012c 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs @@ -219,22 +219,10 @@ internal static TypeDesc ComputeTemplate(TypeBuilderState state, bool templateRe return templateType; } - internal bool IsTemplateUniversal() - { - TypeDesc templateType = ComputeTemplate(false); - if (templateType == null) - return false; - else - return templateType.IsCanonicalSubtype(CanonicalFormKind.Universal); - } - internal bool IsTemplateCanonical() { TypeDesc templateType = ComputeTemplate(false); - if (templateType == null) - return false; - else - return !templateType.IsCanonicalSubtype(CanonicalFormKind.Universal); + return templateType != null; } } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs index 1e4b888552220a..6391cf78abaa65 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs @@ -188,10 +188,6 @@ public TypeDesc ResolveRuntimeTypeHandle(RuntimeTypeHandle rtth) { returnedType = CanonType; } - else if (rtth.Equals(UniversalCanonType.RuntimeTypeHandle)) - { - returnedType = UniversalCanonType; - } else if (RuntimeAugments.IsGenericTypeDefinition(rtth)) { unsafe @@ -335,7 +331,7 @@ public RuntimeMethodKey(bool unboxingStub, DefType owningType, MethodNameAndSign _owningType = owningType; _methodNameAndSignature = nameAndSignature; - _hashCode = TypeHashingAlgorithms.ComputeMethodHashCode(owningType.GetHashCode(), TypeHashingAlgorithms.ComputeNameHashCode(nameAndSignature.Name)); + _hashCode = TypeHashingAlgorithms.ComputeMethodHashCode(owningType.GetHashCode(), TypeHashingAlgorithms.ComputeNameHashCode(nameAndSignature.GetName())); } public class RuntimeMethodKeyHashtable : LockFreeReaderHashtable diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj index 09881516e2950c..4ed2c0fec251ec 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj @@ -4,8 +4,6 @@ TYPE_LOADER_IMPLEMENTATION;$(DefineConstants) TYPE_LOADER_TRACE;$(DefineConstants) GVM_RESOLUTION_TRACE;$(DefineConstants) - CCCONVERTER_TRACE;$(DefineConstants) - GENERICS_FORCE_USG;$(DefineConstants) false @@ -241,7 +239,6 @@ - diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 47f73c3214a6f7..293d9ab41b156c 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -132,12 +132,6 @@ extern bool g_arm64_atomics_present; #define DECLSPEC_NORETURN PAL_NORETURN -#ifdef __clang_analyzer__ -#define ANALYZER_NORETURN __attribute((analyzer_noreturn)) -#else -#define ANALYZER_NORETURN -#endif - #define EMPTY_BASES_DECL #if !defined(_MSC_VER) || defined(SOURCE_FORMATTING) @@ -527,20 +521,6 @@ SearchPathW( #define SearchPath SearchPathW -PALIMPORT -BOOL -PALAPI -CopyFileW( - IN LPCWSTR lpExistingFileName, - IN LPCWSTR lpNewFileName, - IN BOOL bFailIfExists); - -#ifdef UNICODE -#define CopyFile CopyFileW -#else -#define CopyFile CopyFileA -#endif - PALIMPORT DWORD PALAPI @@ -718,21 +698,6 @@ GetFullPathNameW( #define GetFullPathName GetFullPathNameA #endif -PALIMPORT -UINT -PALAPI -GetTempFileNameW( - IN LPCWSTR lpPathName, - IN LPCWSTR lpPrefixString, - IN UINT uUnique, - OUT LPWSTR lpTempFileName); - -#ifdef UNICODE -#define GetTempFileName GetTempFileNameW -#else -#define GetTempFileName GetTempFileNameA -#endif - PALIMPORT DWORD PALAPI @@ -854,6 +819,7 @@ PALAPI PAL_CreateMutexW( IN BOOL bInitialOwner, IN LPCWSTR lpName, + IN BOOL bCurrentUserOnly, IN LPSTR lpSystemCallErrors, IN DWORD dwSystemCallErrorsBufferSize); @@ -875,6 +841,7 @@ HANDLE PALAPI PAL_OpenMutexW( IN LPCWSTR lpName, + IN BOOL bCurrentUserOnly, IN LPSTR lpSystemCallErrors, IN DWORD dwSystemCallErrorsBufferSize); @@ -1550,7 +1517,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { M512 Zmm30; M512 Zmm31; }; - + struct { DWORD64 Egpr16; @@ -1570,7 +1537,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { DWORD64 Egpr30; DWORD64 Egpr31; }; - + } CONTEXT, *PCONTEXT, *LPCONTEXT; // @@ -2473,7 +2440,9 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { #define CONTEXT_CONTROL 0 #define CONTEXT_INTEGER 0 #define CONTEXT_FLOATING_POINT 0 +#define CONTEXT_DEBUG_REGISTERS 0 #define CONTEXT_FULL 0 +#define CONTEXT_ALL 0 #define CONTEXT_XSTATE 0 diff --git a/src/coreclr/pal/inc/pal_error.h b/src/coreclr/pal/inc/pal_error.h index b387e68540060a..b03f9cefa129f5 100644 --- a/src/coreclr/pal/inc/pal_error.h +++ b/src/coreclr/pal/inc/pal_error.h @@ -147,7 +147,6 @@ #define ERROR_PALINIT_TLS 65295L #define ERROR_PALINIT_ENV 65296L #define ERROR_PALINIT_DBG_CHANNELS 65297L -#define ERROR_PALINIT_SHARED_MEMORY_MANAGER 65298L #define ERROR_PALINIT_SHM 65299L #define ERROR_PALINIT_MODULE_MANAGER 65300L diff --git a/src/coreclr/pal/inc/palprivate.h b/src/coreclr/pal/inc/palprivate.h index eff68205585950..12d7ceda53f56d 100644 --- a/src/coreclr/pal/inc/palprivate.h +++ b/src/coreclr/pal/inc/palprivate.h @@ -20,15 +20,6 @@ CreateFileA( IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile); -PALIMPORT -BOOL -PALAPI -CopyFileA( - IN LPCSTR lpExistingFileName, - IN LPCSTR lpNewFileName, - IN BOOL bFailIfExists); - - PALIMPORT BOOL PALAPI @@ -78,15 +69,6 @@ GetFullPathNameA( OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart); -PALIMPORT -UINT -PALAPI -GetTempFileNameA( - IN LPCSTR lpPathName, - IN LPCSTR lpPrefixString, - IN UINT uUnique, - OUT LPSTR lpTempFileName); - PALIMPORT DWORD PALAPI diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 1122fcbe580358..9028af1aecc99c 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -904,100 +904,6 @@ CreateFileW( } -/*++ -Function: - CopyFileW - -See MSDN doc. - -Notes: - There are several (most) error paths here that do not call SetLastError(). -This is because we know that CreateFile, ReadFile, and WriteFile will do so, -and will have a much better idea of the specific error. ---*/ -BOOL -PALAPI -CopyFileW( - IN LPCWSTR lpExistingFileName, - IN LPCWSTR lpNewFileName, - IN BOOL bFailIfExists) -{ - CPalThread *pThread; - PathCharString sourcePathString; - PathCharString destPathString; - char * source; - char * dest; - int src_size, dest_size, length = 0; - BOOL bRet = FALSE; - - PERF_ENTRY(CopyFileW); - ENTRY("CopyFileW(lpExistingFileName=%p (%S), lpNewFileName=%p (%S), bFailIfExists=%d)\n", - lpExistingFileName?lpExistingFileName:W16_NULLSTRING, - lpExistingFileName?lpExistingFileName:W16_NULLSTRING, - lpNewFileName?lpNewFileName:W16_NULLSTRING, - lpNewFileName?lpNewFileName:W16_NULLSTRING, bFailIfExists); - - pThread = InternalGetCurrentThread(); - if (lpExistingFileName != NULL) - { - length = (PAL_wcslen(lpExistingFileName)+1) * MaxWCharToAcpLengthFactor; - } - - source = sourcePathString.OpenStringBuffer(length); - if (NULL == source) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - - src_size = WideCharToMultiByte( CP_ACP, 0, lpExistingFileName, -1, source, length, - NULL, NULL ); - - if( src_size == 0 ) - { - sourcePathString.CloseBuffer(0); - DWORD dwLastError = GetLastError(); - ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); - pThread->SetLastError(ERROR_INTERNAL_ERROR); - goto done; - } - - sourcePathString.CloseBuffer(src_size - 1); - length = 0; - - if (lpNewFileName != NULL) - { - length = (PAL_wcslen(lpNewFileName)+1) * MaxWCharToAcpLengthFactor; - } - - dest = destPathString.OpenStringBuffer(length); - if (NULL == dest) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - dest_size = WideCharToMultiByte( CP_ACP, 0, lpNewFileName, -1, dest, length, - NULL, NULL ); - - if( dest_size == 0 ) - { - destPathString.CloseBuffer(0); - DWORD dwLastError = GetLastError(); - ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); - pThread->SetLastError(ERROR_INTERNAL_ERROR); - goto done; - } - - destPathString.CloseBuffer(dest_size - 1); - bRet = CopyFileA(source,dest,bFailIfExists); - -done: - LOGEXIT("CopyFileW returns BOOL %d\n", bRet); - PERF_EXIT(CopyFileW); - return bRet; -} - - /*++ Function: DeleteFileA @@ -2593,335 +2499,6 @@ FlushFileBuffers( uUniqueSeed++;\ } -/*++ - Function: - GetTempFileNameA - -uUnique is always 0. - --*/ -const int MAX_PREFIX = 3; -const int MAX_SEEDSIZE = 8; /* length of "unique portion of - the string, plus extension(FFFF.TMP). */ -static USHORT uUniqueSeed = 0; -static BOOL IsInitialized = FALSE; - -UINT -PALAPI -GetTempFileNameA( - IN LPCSTR lpPathName, - IN LPCSTR lpPrefixString, - IN UINT uUnique, - OUT LPSTR lpTempFileName) -{ - CPalThread *pThread; - CHAR * full_name; - PathCharString full_namePS; - int length; - CHAR * file_template; - PathCharString file_templatePS; - CHAR chLastPathNameChar; - - HANDLE hTempFile; - UINT uRet = 0; - DWORD dwError; - USHORT uLoopCounter = 0; - - PERF_ENTRY(GetTempFileNameA); - ENTRY("GetTempFileNameA(lpPathName=%p (%s), lpPrefixString=%p (%s), uUnique=%u, " - "lpTempFileName=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", - lpPrefixString?lpPrefixString:"NULL", - lpPrefixString?lpPrefixString:"NULL", uUnique, - lpTempFileName?lpTempFileName:"NULL"); - - pThread = InternalGetCurrentThread(); - if ( !IsInitialized ) - { - uUniqueSeed = (USHORT)( time( NULL ) ); - - /* On the off chance 0 is returned. - 0 being the error return code. */ - ENSURE_UNIQUE_NOT_ZERO - IsInitialized = TRUE; - } - - if ( !lpPathName || *lpPathName == '\0' ) - { - pThread->SetLastError( ERROR_DIRECTORY ); - goto done; - } - - if ( NULL == lpTempFileName ) - { - ERROR( "lpTempFileName cannot be NULL\n" ); - pThread->SetLastError( ERROR_INVALID_PARAMETER ); - goto done; - } - - if ( strlen( lpPathName ) + MAX_SEEDSIZE + MAX_PREFIX >= MAX_LONGPATH ) - { - WARN( "File names larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH ); - pThread->SetLastError( ERROR_FILENAME_EXCED_RANGE ); - goto done; - } - - length = strlen(lpPathName) + MAX_SEEDSIZE + MAX_PREFIX + 10; - file_template = file_templatePS.OpenStringBuffer(length); - if (NULL == file_template) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - *file_template = '\0'; - strcat_s( file_template, file_templatePS.GetSizeOf(), lpPathName ); - file_templatePS.CloseBuffer(length); - - chLastPathNameChar = file_template[strlen(file_template)-1]; - if (chLastPathNameChar != '/') - { - strcat_s( file_template, file_templatePS.GetSizeOf(), "/" ); - } - - if ( lpPrefixString ) - { - strncat_s( file_template, file_templatePS.GetSizeOf(), lpPrefixString, MAX_PREFIX ); - } - strncat_s( file_template, file_templatePS.GetSizeOf(), "%.4x.TMP", MAX_SEEDSIZE ); - - /* Create the file. */ - dwError = GetLastError(); - pThread->SetLastError( NOERROR ); - - length = strlen(file_template) + MAX_SEEDSIZE + MAX_PREFIX; - full_name = full_namePS.OpenStringBuffer(length); - if (NULL == full_name) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto done; - } - sprintf_s( full_name, full_namePS.GetSizeOf(), file_template, (0 == uUnique) ? uUniqueSeed : uUnique); - full_namePS.CloseBuffer(length); - - hTempFile = CreateFileA( full_name, GENERIC_WRITE, - FILE_SHARE_READ, NULL, CREATE_NEW, 0, NULL ); - - if (uUnique == 0) - { - /* The USHORT will overflow back to 0 if we go past - 65536 files, so break the loop after 65536 iterations. - If the CreateFile call was not successful within that - number of iterations, then there are no temp file names - left for that directory. */ - while ( ERROR_PATH_NOT_FOUND != GetLastError() && - INVALID_HANDLE_VALUE == hTempFile && uLoopCounter < 0xFFFF ) - { - uUniqueSeed++; - ENSURE_UNIQUE_NOT_ZERO; - - pThread->SetLastError( NOERROR ); - sprintf_s( full_name, full_namePS.GetSizeOf(), file_template, uUniqueSeed ); - hTempFile = CreateFileA( full_name, GENERIC_WRITE, - FILE_SHARE_READ, NULL, CREATE_NEW, 0, NULL ); - uLoopCounter++; - - } - } - - /* Reset the error code.*/ - if ( NOERROR == GetLastError() ) - { - pThread->SetLastError( dwError ); - } - - /* Windows sets ERROR_FILE_EXISTS,if there - are no available temp files. */ - if ( INVALID_HANDLE_VALUE != hTempFile ) - { - if (0 == uUnique) - { - uRet = uUniqueSeed; - uUniqueSeed++; - ENSURE_UNIQUE_NOT_ZERO; - } - else - { - uRet = uUnique; - } - - if ( CloseHandle( hTempFile ) ) - { - if (strcpy_s( lpTempFileName, MAX_LONGPATH, full_name ) != SAFECRT_SUCCESS) - { - ERROR( "strcpy_s failed!\n"); - pThread->SetLastError( ERROR_FILENAME_EXCED_RANGE ); - *lpTempFileName = '\0'; - uRet = 0; - } - } - else - { - ASSERT( "Unable to close the handle %p\n", hTempFile ); - pThread->SetLastError( ERROR_INTERNAL_ERROR ); - *lpTempFileName = '\0'; - uRet = 0; - } - } - else if ( INVALID_HANDLE_VALUE == hTempFile && uLoopCounter < 0xFFFF ) - { - ERROR( "Unable to create temp file. \n" ); - uRet = 0; - - if ( ERROR_PATH_NOT_FOUND == GetLastError() ) - { - /* CreateFile failed because it could not - find the path. */ - pThread->SetLastError( ERROR_DIRECTORY ); - } /* else use the lasterror value from CreateFileA */ - } - else - { - TRACE( "65535 files already exist in the directory. " - "No temp files available for creation.\n" ); - pThread->SetLastError( ERROR_FILE_EXISTS ); - } - -done: - LOGEXIT("GetTempFileNameA returns UINT %u\n", uRet); - PERF_EXIT(GetTempFileNameA); - return uRet; - -} - -/*++ -Function: - GetTempFileNameW - -uUnique is always 0. ---*/ -UINT -PALAPI -GetTempFileNameW( - IN LPCWSTR lpPathName, - IN LPCWSTR lpPrefixString, - IN UINT uUnique, - OUT LPWSTR lpTempFileName) -{ - CPalThread *pThread; - INT path_size = 0; - INT prefix_size = 0; - CHAR * full_name; - CHAR * prefix_string; - CHAR * tempfile_name = NULL; - PathCharString full_namePS, prefix_stringPS; - INT length = 0; - UINT uRet; - - PERF_ENTRY(GetTempFileNameW); - ENTRY("GetTempFileNameW(lpPathName=%p (%S), lpPrefixString=%p (%S), uUnique=%u, " - "lpTempFileName=%p)\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING, - lpPrefixString?lpPrefixString:W16_NULLSTRING, - lpPrefixString?lpPrefixString:W16_NULLSTRING,uUnique, lpTempFileName); - - pThread = InternalGetCurrentThread(); - /* Sanity checks. */ - if ( !lpPathName || *lpPathName == '\0' ) - { - pThread->SetLastError( ERROR_DIRECTORY ); - uRet = 0; - goto done; - } - - length = (PAL_wcslen(lpPathName)+1) * MaxWCharToAcpLengthFactor; - full_name = full_namePS.OpenStringBuffer(length); - if (NULL == full_name) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - uRet = 0; - goto done; - } - path_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, full_name, - length, NULL, NULL ); - - if( path_size == 0 ) - { - full_namePS.CloseBuffer(0); - DWORD dwLastError = GetLastError(); - ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); - pThread->SetLastError(ERROR_INTERNAL_ERROR); - uRet = 0; - goto done; - } - - full_namePS.CloseBuffer(path_size - 1); - - if (lpPrefixString != NULL) - { - length = (PAL_wcslen(lpPrefixString)+1) * MaxWCharToAcpLengthFactor; - prefix_string = prefix_stringPS.OpenStringBuffer(length); - if (NULL == prefix_string) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - uRet = 0; - goto done; - } - prefix_size = WideCharToMultiByte( CP_ACP, 0, lpPrefixString, -1, - prefix_string, - MAX_LONGPATH - path_size - MAX_SEEDSIZE, - NULL, NULL ); - - if( prefix_size == 0 ) - { - prefix_stringPS.CloseBuffer(0); - DWORD dwLastError = GetLastError(); - ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); - pThread->SetLastError(ERROR_INTERNAL_ERROR); - uRet = 0; - goto done; - } - prefix_stringPS.CloseBuffer(prefix_size - 1); - } - - tempfile_name = (char*)malloc(MAX_LONGPATH); - if (tempfile_name == NULL) - { - pThread->SetLastError(ERROR_NOT_ENOUGH_MEMORY); - uRet = 0; - goto done; - } - - uRet = GetTempFileNameA(full_name, - (lpPrefixString == NULL) ? NULL : prefix_string, - 0, tempfile_name); - if (uRet) - { - path_size = MultiByteToWideChar( CP_ACP, 0, tempfile_name, -1, - lpTempFileName, MAX_LONGPATH ); - - if (!path_size) - { - DWORD dwLastError = GetLastError(); - if (dwLastError == ERROR_INSUFFICIENT_BUFFER) - { - WARN("File names larger than MAX_PATH_FNAME (%d)! \n", MAX_LONGPATH); - dwLastError = ERROR_FILENAME_EXCED_RANGE; - } - else - { - ASSERT("MultiByteToWideChar failure! error is %d", dwLastError); - dwLastError = ERROR_INTERNAL_ERROR; - } - pThread->SetLastError(dwLastError); - uRet = 0; - } - } - -done: - free(tempfile_name); - - LOGEXIT("GetTempFileNameW returns UINT %u\n", uRet); - PERF_EXIT(GetTempFileNameW); - return uRet; -} - /*++ Function: FILEGetLastErrorFromErrno @@ -3009,156 +2586,6 @@ DWORD DIRGetLastErrorFromErrno( void ) } -/*++ -Function: - CopyFileA - -See MSDN doc. - -Notes: - There are several (most) error paths here that do not call SetLastError(). -This is because we know that CreateFile, ReadFile, and WriteFile will do so, -and will have a much better idea of the specific error. ---*/ -BOOL -PALAPI -CopyFileA( - IN LPCSTR lpExistingFileName, - IN LPCSTR lpNewFileName, - IN BOOL bFailIfExists) -{ - CPalThread *pThread; - HANDLE hSource = INVALID_HANDLE_VALUE; - HANDLE hDest = INVALID_HANDLE_VALUE; - DWORD dwDestCreationMode; - BOOL bGood = FALSE; - DWORD dwSrcFileAttributes; - struct stat SrcFileStats; - - const int buffer_size = 16*1024; - char *buffer = (char*)alloca(buffer_size); - DWORD bytes_read; - DWORD bytes_written; - int permissions; - - - PERF_ENTRY(CopyFileA); - ENTRY("CopyFileA(lpExistingFileName=%p (%s), lpNewFileName=%p (%s), bFailIfExists=%d)\n", - lpExistingFileName?lpExistingFileName:"NULL", - lpExistingFileName?lpExistingFileName:"NULL", - lpNewFileName?lpNewFileName:"NULL", - lpNewFileName?lpNewFileName:"NULL", bFailIfExists); - - pThread = InternalGetCurrentThread(); - if ( bFailIfExists ) - { - dwDestCreationMode = CREATE_NEW; - } - else - { - dwDestCreationMode = CREATE_ALWAYS; - } - - hSource = CreateFileA( lpExistingFileName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - 0, - NULL ); - - if ( hSource == INVALID_HANDLE_VALUE ) - { - ERROR("CreateFileA failed for %s\n", lpExistingFileName); - goto done; - } - - /* Need to preserve the file attributes */ - dwSrcFileAttributes = GetFileAttributesA(lpExistingFileName); - if (dwSrcFileAttributes == 0xffffffff) - { - ERROR("GetFileAttributesA failed for %s\n", lpExistingFileName); - goto done; - } - - /* Need to preserve the owner/group and chmod() flags */ - if (stat (lpExistingFileName, &SrcFileStats) == -1) - { - ERROR("stat() failed for %s\n", lpExistingFileName); - pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpExistingFileName)); - goto done; - } - - hDest = CreateFileA( lpNewFileName, - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - dwDestCreationMode, - 0, - NULL ); - - if ( hDest == INVALID_HANDLE_VALUE ) - { - ERROR("CreateFileA failed for %s\n", lpNewFileName); - goto done; - } - - // We don't set file attributes in CreateFile. The only attribute - // that is reflected on disk in Unix is read-only, and we set that - // here. - permissions = (S_IRWXU | S_IRWXG | S_IRWXO); - if ((dwSrcFileAttributes & FILE_ATTRIBUTE_READONLY) != 0) - { - permissions &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - } - - /* Make sure the new file has the same chmod() flags. */ - if (chmod(lpNewFileName, SrcFileStats.st_mode & permissions) == -1) - { - WARN ("chmod() failed to set mode 0x%x on new file\n", - SrcFileStats.st_mode & permissions); - pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpNewFileName)); - goto done; - } - - while( (bGood = ReadFile( hSource, buffer, buffer_size, &bytes_read, NULL )) - && bytes_read > 0 ) - { - bGood = ( WriteFile( hDest, buffer, bytes_read, &bytes_written, NULL ) - && bytes_written == bytes_read); - if (!bGood) break; - } - - if (!bGood) - { - ERROR("Copy failed\n"); - - if ( !CloseHandle(hDest) || - !DeleteFileA(lpNewFileName) ) - { - ERROR("Unable to clean up partial copy\n"); - } - hDest = INVALID_HANDLE_VALUE; - - goto done; - } - -done: - - if ( hSource != INVALID_HANDLE_VALUE ) - { - CloseHandle( hSource ); - } - if ( hDest != INVALID_HANDLE_VALUE ) - { - CloseHandle( hDest ); - } - - LOGEXIT("CopyFileA returns BOOL %d\n", bGood); - PERF_EXIT(CopyFileA); - return bGood; -} - PAL_ERROR CorUnix::InternalCreatePipe( CPalThread *pThread, diff --git a/src/coreclr/pal/src/include/pal/mutex.hpp b/src/coreclr/pal/src/include/pal/mutex.hpp index 016668dafb1624..9ff179ca43d180 100644 --- a/src/coreclr/pal/src/include/pal/mutex.hpp +++ b/src/coreclr/pal/src/include/pal/mutex.hpp @@ -37,6 +37,7 @@ namespace CorUnix LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName, + BOOL bCurrentUserOnly, HANDLE *phMutex ); @@ -51,6 +52,7 @@ namespace CorUnix SharedMemorySystemCallErrors *errors, CPalThread *pThread, LPCSTR lpName, + BOOL bCurrentUserOnly, HANDLE *phMutex ); @@ -216,10 +218,10 @@ class NamedMutexProcessData : public SharedMemoryProcessDataBase bool m_hasRefFromLockOwnerThread; public: - static SharedMemoryProcessDataHeader *CreateOrOpen(SharedMemorySystemCallErrors *errors, LPCSTR name, bool acquireLockIfCreated, bool *createdRef); - static SharedMemoryProcessDataHeader *Open(SharedMemorySystemCallErrors *errors, LPCSTR name); + static SharedMemoryProcessDataHeader *CreateOrOpen(SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope, bool acquireLockIfCreated, bool *createdRef); + static SharedMemoryProcessDataHeader *Open(SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope); private: - static SharedMemoryProcessDataHeader *CreateOrOpen(SharedMemorySystemCallErrors *errors, LPCSTR name, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef); + static SharedMemoryProcessDataHeader *CreateOrOpen(SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef); public: NamedMutexProcessData( diff --git a/src/coreclr/pal/src/include/pal/sharedmemory.h b/src/coreclr/pal/src/include/pal/sharedmemory.h index 63e5ddd1540fa8..c1ec1b9b6ae2d3 100644 --- a/src/coreclr/pal/src/include/pal/sharedmemory.h +++ b/src/coreclr/pal/src/include/pal/sharedmemory.h @@ -27,27 +27,26 @@ #define SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT (_MAX_FNAME - 1) #define SHARED_MEMORY_MAX_NAME_CHAR_COUNT (STRING_LENGTH("Global\\") + SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT) -#define SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME ".dotnet" -#define SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME ".dotnet/shm" -#define SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME ".dotnet/lockfiles" -static_assert_no_msg(ARRAY_SIZE(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) >= ARRAY_SIZE(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME)); +#define SHARED_MEMORY_USER_UNSCOPED_RUNTIME_TEMP_DIRECTORY_NAME ".dotnet" +#define SHARED_MEMORY_USER_SCOPED_RUNTIME_TEMP_DIRECTORY_NAME_PREFIX ".dotnet-uid" +#define SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME "shm" +#define SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME "lockfiles" +static_assert_no_msg(STRING_LENGTH(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) >= STRING_LENGTH(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME)); #define SHARED_MEMORY_GLOBAL_DIRECTORY_NAME "global" #define SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX "session" -static_assert_no_msg(ARRAY_SIZE(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) >= ARRAY_SIZE(SHARED_MEMORY_GLOBAL_DIRECTORY_NAME)); -#define SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE ".coreclr.XXXXXX" - -#define SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT (10) +#define SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE ".dotnet.XXXXXX" // Note that this Max size does not include the prefix folder path size which is unknown (in the case of sandbox) until runtime #define SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT \ ( \ + STRING_LENGTH(SHARED_MEMORY_USER_SCOPED_RUNTIME_TEMP_DIRECTORY_NAME_PREFIX) + \ + 11 /* user ID, path separator */ + \ STRING_LENGTH(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) + \ 1 /* path separator */ + \ STRING_LENGTH(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) + \ - SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT + \ - 1 /* path separator */ + \ + 11 /* session ID, path separator */ + \ SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT \ ) @@ -98,12 +97,17 @@ class SharedMemorySystemCallErrors void Append(LPCSTR format, ...); }; +class SharedMemoryId; + class SharedMemoryHelpers { private: - static const mode_t PermissionsMask_CurrentUser_ReadWriteExecute; + static const mode_t PermissionsMask_OwnerUser_ReadWrite; + static const mode_t PermissionsMask_OwnerUser_ReadWriteExecute; + static const mode_t PermissionsMask_NonOwnerUsers_Write; static const mode_t PermissionsMask_AllUsers_ReadWrite; static const mode_t PermissionsMask_AllUsers_ReadWriteExecute; + static const mode_t PermissionsMask_Sticky; public: static const UINT32 InvalidProcessId; static const SIZE_T InvalidThreadId; @@ -114,17 +118,14 @@ class SharedMemoryHelpers static SIZE_T AlignUp(SIZE_T value, SIZE_T alignment); static void *Alloc(SIZE_T byteCount); - - template static void BuildSharedFilesPath(PathCharString& destination, const char (&suffix)[SuffixByteCount]); - static void BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixByteCount); static bool AppendUInt32String(PathCharString& destination, UINT32 value); - static bool EnsureDirectoryExists(SharedMemorySystemCallErrors *errors, const char *path, bool isGlobalLockAcquired, bool createIfNotExist = true, bool isSystemDirectory = false); + static bool EnsureDirectoryExists(SharedMemorySystemCallErrors *errors, const char *path, const SharedMemoryId *id, bool isGlobalLockAcquired, bool createIfNotExist = true, bool isSystemDirectory = false); private: static int Open(SharedMemorySystemCallErrors *errors, LPCSTR path, int flags, mode_t mode = static_cast(0)); public: static int OpenDirectory(SharedMemorySystemCallErrors *errors, LPCSTR path); - static int CreateOrOpenFile(SharedMemorySystemCallErrors *errors, LPCSTR path, bool createIfNotExist = true, bool *createdRef = nullptr); + static int CreateOrOpenFile(SharedMemorySystemCallErrors *errors, LPCSTR path, const SharedMemoryId *id, bool createIfNotExist = true, bool *createdRef = nullptr); static void CloseFile(int fileDescriptor); static int ChangeMode(LPCSTR path, mode_t mode); @@ -150,19 +151,24 @@ class SharedMemoryId LPCSTR m_name; SIZE_T m_nameCharCount; bool m_isSessionScope; // false indicates global scope + bool m_isUserScope; + uid_t m_userScopeUid; public: SharedMemoryId(); - SharedMemoryId(LPCSTR name, SIZE_T nameCharCount, bool isSessionScope); - SharedMemoryId(LPCSTR name); + SharedMemoryId(LPCSTR name, bool isUserScope); public: LPCSTR GetName() const; SIZE_T GetNameCharCount() const; + void ReplaceNamePtr(LPCSTR name); bool IsSessionScope() const; - bool Equals(SharedMemoryId *other) const; + bool IsUserScope() const; + uid_t GetUserScopeUid() const; + bool Equals(const SharedMemoryId *other) const; public: + bool AppendRuntimeTempDirectoryName(PathCharString& path) const; bool AppendSessionDirectoryName(PathCharString& path) const; }; @@ -222,7 +228,7 @@ class SharedMemoryProcessDataHeader SharedMemoryProcessDataHeader *m_nextInProcessDataHeaderList; public: - static SharedMemoryProcessDataHeader *CreateOrOpen(SharedMemorySystemCallErrors *errors, LPCSTR name, SharedMemorySharedDataHeader requiredSharedDataHeader, SIZE_T sharedDataByteCount, bool createIfNotExist, bool *createdRef); + static SharedMemoryProcessDataHeader *CreateOrOpen(SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope, SharedMemorySharedDataHeader requiredSharedDataHeader, SIZE_T sharedDataByteCount, bool createIfNotExist, bool *createdRef); public: static SharedMemoryProcessDataHeader *PalObject_GetProcessDataHeader(CorUnix::IPalObject *object); @@ -230,14 +236,14 @@ class SharedMemoryProcessDataHeader static void PalObject_Close(CorUnix::CPalThread *thread, CorUnix::IPalObject *object, bool isShuttingDown); private: - SharedMemoryProcessDataHeader(SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount); + SharedMemoryProcessDataHeader(const SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount); public: - static SharedMemoryProcessDataHeader *New(SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount); + static SharedMemoryProcessDataHeader *New(const SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount); ~SharedMemoryProcessDataHeader(); void Close(); public: - SharedMemoryId *GetId(); + const SharedMemoryId *GetId() const; SharedMemoryProcessDataBase *GetData() const; void SetData(SharedMemoryProcessDataBase *data); SharedMemorySharedDataHeader *GetSharedDataHeader() const; @@ -256,8 +262,24 @@ class SharedMemoryManager static CRITICAL_SECTION s_creationDeletionProcessLock; static int s_creationDeletionLockFileDescriptor; - static PathCharString* s_runtimeTempDirectoryPath; - static PathCharString* s_sharedMemoryDirectoryPath; + struct UserScopeUidAndFileDescriptor + { + uid_t userScopeUid; + int fileDescriptor; + + UserScopeUidAndFileDescriptor() : userScopeUid((uid_t)0), fileDescriptor(-1) + { + } + + UserScopeUidAndFileDescriptor(uid_t userScopeUid, int fileDescriptor) + : userScopeUid(userScopeUid), fileDescriptor(fileDescriptor) + { + } + }; + + static UserScopeUidAndFileDescriptor *s_userScopeUidToCreationDeletionLockFDs; + static int s_userScopeUidToCreationDeletionLockFDsCount; + static int s_userScopeUidToCreationDeletionLockFDsCapacity; private: static SharedMemoryProcessDataHeader *s_processDataHeaderListHead; @@ -269,17 +291,16 @@ class SharedMemoryManager #endif // _DEBUG public: - static bool StaticInitialize(); + static void StaticInitialize(); static void StaticClose(); public: static void AcquireCreationDeletionProcessLock(); static void ReleaseCreationDeletionProcessLock(); - static void AcquireCreationDeletionFileLock(SharedMemorySystemCallErrors *errors); - static void ReleaseCreationDeletionFileLock(); - -public: - static bool CopySharedMemoryBasePath(PathCharString& destination); + static void AcquireCreationDeletionFileLock(SharedMemorySystemCallErrors *errors, const SharedMemoryId *id); + static void ReleaseCreationDeletionFileLock(const SharedMemoryId *id); + static void AddUserScopeUidCreationDeletionLockFD(uid_t userScopeUid, int creationDeletionLockFD); + static int FindUserScopeCreationDeletionLockFD(uid_t userScopeUid); #ifdef _DEBUG public: @@ -290,7 +311,7 @@ class SharedMemoryManager public: static void AddProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader); static void RemoveProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader); - static SharedMemoryProcessDataHeader *FindProcessDataHeader(SharedMemoryId *id); + static SharedMemoryProcessDataHeader *FindProcessDataHeader(const SharedMemoryId *id); }; #endif // !_PAL_SHARED_MEMORY_H_ diff --git a/src/coreclr/pal/src/include/pal/sharedmemory.inl b/src/coreclr/pal/src/include/pal/sharedmemory.inl deleted file mode 100644 index 598172c2bbc72b..00000000000000 --- a/src/coreclr/pal/src/include/pal/sharedmemory.inl +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef _PAL_SHARED_MEMORY_INL_ -#define _PAL_SHARED_MEMORY_INL_ - -#include "sharedmemory.h" - -#include "dbgmsg.h" - -#include - -template -void SharedMemoryHelpers::BuildSharedFilesPath( - PathCharString& destination, - const char (&suffix)[SuffixByteCount]) -{ - BuildSharedFilesPath(destination, suffix, SuffixByteCount - 1); -} - -#endif // !_PAL_SHARED_MEMORY_INL_ diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 7a74159cae60b8..26b193280152cf 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -410,12 +410,7 @@ Initialize( // we use large numbers of threads or have many open files. } - if (!SharedMemoryManager::StaticInitialize()) - { - ERROR("Shared memory static initialization failed!\n"); - palError = ERROR_PALINIT_SHARED_MEMORY_MANAGER; - goto CLEANUP1; - } + SharedMemoryManager::StaticInitialize(); // // Initialize global process data diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index a6074852b08a59..368dbfa4950f10 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -25,8 +25,6 @@ SET_DEFAULT_DEBUG_CHANNEL(SHMEM); // some headers have code with asserts, so do using namespace CorUnix; -#include "pal/sharedmemory.inl" - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // AutoFreeBuffer @@ -127,11 +125,14 @@ void SharedMemorySystemCallErrors::Append(LPCSTR format, ...) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SharedMemoryHelpers -const mode_t SharedMemoryHelpers::PermissionsMask_CurrentUser_ReadWriteExecute = S_IRUSR | S_IWUSR | S_IXUSR; +const mode_t SharedMemoryHelpers::PermissionsMask_OwnerUser_ReadWrite = S_IRUSR | S_IWUSR; +const mode_t SharedMemoryHelpers::PermissionsMask_OwnerUser_ReadWriteExecute = S_IRUSR | S_IWUSR | S_IXUSR; +const mode_t SharedMemoryHelpers::PermissionsMask_NonOwnerUsers_Write = S_IWGRP | S_IWOTH; const mode_t SharedMemoryHelpers::PermissionsMask_AllUsers_ReadWrite = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; const mode_t SharedMemoryHelpers::PermissionsMask_AllUsers_ReadWriteExecute = PermissionsMask_AllUsers_ReadWrite | (S_IXUSR | S_IXGRP | S_IXOTH); +const mode_t SharedMemoryHelpers::PermissionsMask_Sticky = S_ISVTX; const UINT32 SharedMemoryHelpers::InvalidProcessId = static_cast(-1); const SIZE_T SharedMemoryHelpers::InvalidThreadId = static_cast(-1); const UINT64 SharedMemoryHelpers::InvalidSharedThreadId = static_cast(-1); @@ -161,15 +162,20 @@ SIZE_T SharedMemoryHelpers::AlignUp(SIZE_T value, SIZE_T alignment) bool SharedMemoryHelpers::EnsureDirectoryExists( SharedMemorySystemCallErrors *errors, const char *path, + const SharedMemoryId *id, bool isGlobalLockAcquired, bool createIfNotExist, bool isSystemDirectory) { _ASSERTE(path != nullptr); + _ASSERTE(id != nullptr); _ASSERTE(!(isSystemDirectory && createIfNotExist)); // should not create or change permissions on system directories _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); _ASSERTE(!isGlobalLockAcquired || SharedMemoryManager::IsCreationDeletionFileLockAcquired()); + mode_t permissionsMask = + id->IsUserScope() ? PermissionsMask_OwnerUser_ReadWriteExecute : PermissionsMask_AllUsers_ReadWriteExecute; + // Check if the path already exists struct stat statInfo; int statResult = stat(path, &statInfo); @@ -189,15 +195,16 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (isGlobalLockAcquired) { - int operationResult = mkdir(path, PermissionsMask_AllUsers_ReadWriteExecute); + int operationResult = mkdir(path, permissionsMask); if (operationResult != 0) { if (errors != nullptr) { int errorCode = errno; errors->Append( - "mkdir(\"%s\", AllUsers_ReadWriteExecute) == %d; errno == %s;", + "mkdir(\"%s\", %s_ReadWriteExecute) == %d; errno == %s;", path, + id->IsUserScope() ? "OwnerUser" : "AllUsers", operationResult, GetFriendlyErrorCodeString(errorCode)); } @@ -205,15 +212,16 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } - operationResult = ChangeMode(path, PermissionsMask_AllUsers_ReadWriteExecute); + operationResult = ChangeMode(path, permissionsMask); if (operationResult != 0) { if (errors != nullptr) { int errorCode = errno; errors->Append( - "chmod(\"%s\", AllUsers_ReadWriteExecute) == %d; errno == %s;", + "chmod(\"%s\", %s_ReadWriteExecute) == %d; errno == %s;", path, + id->IsUserScope() ? "OwnerUser" : "AllUsers", operationResult, GetFriendlyErrorCodeString(errorCode)); } @@ -226,7 +234,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( } PathCharString tempPath; - BuildSharedFilesPath(tempPath, SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE); + VerifyStringOperation(tempPath.Set(*gSharedFilesPath) && tempPath.Append(SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE)); if (mkdtemp(tempPath.OpenStringBuffer()) == nullptr) { @@ -242,15 +250,16 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } - int operationResult = ChangeMode(tempPath, PermissionsMask_AllUsers_ReadWriteExecute); + int operationResult = ChangeMode(tempPath, permissionsMask); if (operationResult != 0) { if (errors != nullptr) { int errorCode = errno; errors->Append( - "chmod(\"%s\", AllUsers_ReadWriteExecute) == %d; errno == %s;", + "chmod(\"%s\", %s_ReadWriteExecute) == %d; errno == %s;", (const char *)tempPath, + id->IsUserScope() ? "OwnerUser" : "AllUsers", operationResult, GetFriendlyErrorCodeString(errorCode)); } @@ -300,12 +309,21 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (isSystemDirectory) { // For system directories (such as TEMP_DIRECTORY_PATH), require sufficient permissions only for the - // current user. For instance, "docker run --mount ..." to mount /tmp to some directory on the host mounts the + // owner user. For instance, "docker run --mount ..." to mount /tmp to some directory on the host mounts the // destination directory with the same permissions as the source directory, which may not include some permissions for // other users. In the docker container, other user permissions are typically not relevant and relaxing the permissions // requirement allows for that scenario to work without having to work around it by first giving sufficient permissions // for all users. - if ((statInfo.st_mode & PermissionsMask_CurrentUser_ReadWriteExecute) == PermissionsMask_CurrentUser_ReadWriteExecute) + // + // If the directory is being used for user-scoped shared memory data, also ensure that either it has the sticky bit or + // it's owned by the current user and without write access for other users. + permissionsMask = PermissionsMask_OwnerUser_ReadWriteExecute; + if ((statInfo.st_mode & permissionsMask) == permissionsMask && + ( + !id->IsUserScope() || + statInfo.st_mode & PermissionsMask_Sticky || + (statInfo.st_uid == id->GetUserScopeUid() && !(statInfo.st_mode & PermissionsMask_NonOwnerUsers_Write)) + )) { return true; } @@ -313,38 +331,71 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (errors != nullptr) { errors->Append( - "stat(\"%s\", &info) == 0; info.st_mode == 0x%x; (info.st_mode & CurrentUser_ReadWriteExecute) != CurrentUser_ReadWriteExecute;", + "stat(\"%s\", &info) == 0; info.st_mode == 0x%x; info.st_uid == %u; info.st_mode || info.st_uid;", path, - (int)statInfo.st_mode); + (int)statInfo.st_mode, + (int)statInfo.st_uid); + } + + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + + // For non-system directories (such as gSharedFilesPath/SHARED_MEMORY_USER_UNSCOPED_RUNTIME_TEMP_DIRECTORY_NAME), + // require the sufficient permissions and try to update them if requested to create the directory, so that + // shared memory files may be shared according to its scope. + + // For user-scoped directories, verify the owner UID + if (id->IsUserScope() && statInfo.st_uid != id->GetUserScopeUid()) + { + if (errors != nullptr) + { + errors->Append( + "stat(\"%s\", &info) == 0; info.st_uid == %u; info.st_uid != %u;", + path, + (int)statInfo.st_uid, + (int)id->GetUserScopeUid()); } throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } - // For non-system directories (such as gSharedFilesPath/SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME), - // require sufficient permissions for all users and try to update them if requested to create the directory, so that - // shared memory files may be shared by all processes on the system. - if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute) == PermissionsMask_AllUsers_ReadWriteExecute) + // Verify the permissions, or try to change them if possible + if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute) == permissionsMask || + (createIfNotExist && ChangeMode(path, permissionsMask) == 0)) { return true; } - if (!createIfNotExist || ChangeMode(path, PermissionsMask_AllUsers_ReadWriteExecute) != 0) + + // We were not able to verify or set the necessary permissions. For user-scoped directories, this is treated as a failure + // since other users aren't sufficiently restricted in permissions. + if (id->IsUserScope()) { - // We were not asked to create the path or we weren't able to set the new permissions. - // As a last resort, check that at least the current user has full access. - if ((statInfo.st_mode & PermissionsMask_CurrentUser_ReadWriteExecute) != PermissionsMask_CurrentUser_ReadWriteExecute) + if (errors != nullptr) { - if (errors != nullptr) - { - errors->Append( - "stat(\"%s\", &info) == 0; info.st_mode == 0x%x; (info.st_mode & CurrentUser_ReadWriteExecute) != CurrentUser_ReadWriteExecute;", - path, - (int)statInfo.st_mode); - } + errors->Append( + "stat(\"%s\", &info) == 0; info.st_mode == 0x%x; (info.st_mode & AllUsers_ReadWriteExecute) != OwnerUser_ReadWriteExecute;", + path, + (int)statInfo.st_mode); + } - throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } + + // For user-unscoped directories, as a last resort, check that at least the owner user has full access. + permissionsMask = PermissionsMask_OwnerUser_ReadWriteExecute; + if ((statInfo.st_mode & permissionsMask) != permissionsMask) + { + if (errors != nullptr) + { + errors->Append( + "stat(\"%s\", &info) == 0; info.st_mode == 0x%x; (info.st_mode & OwnerUser_ReadWriteExecute) != OwnerUser_ReadWriteExecute;", + path, + (int)statInfo.st_mode); } + + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } + return true; } @@ -412,6 +463,7 @@ int SharedMemoryHelpers::OpenDirectory(SharedMemorySystemCallErrors *errors, LPC int SharedMemoryHelpers::CreateOrOpenFile( SharedMemorySystemCallErrors *errors, LPCSTR path, + const SharedMemoryId *id, bool createIfNotExist, bool *createdRef) { @@ -425,12 +477,64 @@ int SharedMemoryHelpers::CreateOrOpenFile( int fileDescriptor = Open(errors, path, openFlags); if (fileDescriptor != -1) { + // For user-scoped files, verify the owner UID and permissions + if (id->IsUserScope()) + { + struct stat statInfo; + int statResult = fstat(fileDescriptor, &statInfo); + if (statResult != 0) + { + if (errors != nullptr) + { + int errorCode = errno; + errors->Append( + "fstat(\"%s\", ...) == %d; errno == %s;", + path, + statResult, + GetFriendlyErrorCodeString(errorCode)); + } + + CloseFile(fileDescriptor); + throw SharedMemoryException((DWORD)SharedMemoryError::IO); + } + + if (statInfo.st_uid != id->GetUserScopeUid()) + { + if (errors != nullptr) + { + errors->Append( + "fstat(\"%s\", &info) == 0; info.st_uid == %u; info.st_uid != %u;", + path, + (int)statInfo.st_uid, + (int)id->GetUserScopeUid()); + } + + CloseFile(fileDescriptor); + throw SharedMemoryException((DWORD)SharedMemoryError::IO); + } + + if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute) != PermissionsMask_OwnerUser_ReadWrite) + { + if (errors != nullptr) + { + errors->Append( + "fstat(\"%s\", &info) == 0; info.st_mode == 0x%x; (info.st_mode & AllUsers_ReadWriteExecute) != OwnerUser_ReadWrite;", + path, + (int)statInfo.st_mode); + } + + CloseFile(fileDescriptor); + throw SharedMemoryException((DWORD)SharedMemoryError::IO); + } + } + if (createdRef != nullptr) { *createdRef = false; } return fileDescriptor; } + _ASSERTE(errno == ENOENT); if (!createIfNotExist) { @@ -443,20 +547,22 @@ int SharedMemoryHelpers::CreateOrOpenFile( // File does not exist, create the file openFlags |= O_CREAT | O_EXCL; - fileDescriptor = Open(errors, path, openFlags, PermissionsMask_AllUsers_ReadWrite); + mode_t permissionsMask = id->IsUserScope() ? PermissionsMask_OwnerUser_ReadWrite : PermissionsMask_AllUsers_ReadWrite; + fileDescriptor = Open(errors, path, openFlags, permissionsMask); _ASSERTE(fileDescriptor != -1); // The permissions mask passed to open() is filtered by the process' permissions umask, so open() may not set all of // the requested permissions. Use chmod() to set the proper permissions. - int operationResult = ChangeMode(path, PermissionsMask_AllUsers_ReadWrite); + int operationResult = ChangeMode(path, permissionsMask); if (operationResult != 0) { if (errors != nullptr) { int errorCode = errno; errors->Append( - "chmod(\"%s\", AllUsers_ReadWrite) == %d; errno == %s;", + "chmod(\"%s\", %s_ReadWrite) == %d; errno == %s;", path, + id->IsUserScope() ? "OwnerUser" : "AllUsers", operationResult, GetFriendlyErrorCodeString(errorCode)); } @@ -663,14 +769,6 @@ void SharedMemoryHelpers::ReleaseFileLock(int fileDescriptor) } while (flockResult != 0 && errno == EINTR); } -void SharedMemoryHelpers::BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixCharCount) -{ - _ASSERTE((int)strlen(suffix) == suffixCharCount); - - VerifyStringOperation(destination.Set(*gSharedFilesPath)); - VerifyStringOperation(destination.Append(suffix, suffixCharCount)); -} - bool SharedMemoryHelpers::AppendUInt32String( PathCharString& destination, UINT32 value) @@ -694,20 +792,12 @@ void SharedMemoryHelpers::VerifyStringOperation(bool success) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SharedMemoryId -SharedMemoryId::SharedMemoryId() : m_name(nullptr) -{ -} - -SharedMemoryId::SharedMemoryId(LPCSTR name, SIZE_T nameCharCount, bool isSessionScope) - : m_name(name), m_nameCharCount(nameCharCount), m_isSessionScope(isSessionScope) +SharedMemoryId::SharedMemoryId() + : m_name(nullptr), m_nameCharCount(0), m_isSessionScope(false), m_isUserScope(false), m_userScopeUid((uid_t)0) { - _ASSERTE(name != nullptr); - _ASSERTE(nameCharCount != 0); - _ASSERTE(nameCharCount <= SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT); - _ASSERTE(strlen(name) == nameCharCount); } -SharedMemoryId::SharedMemoryId(LPCSTR name) +SharedMemoryId::SharedMemoryId(LPCSTR name, bool isUserScope) { _ASSERTE(name != nullptr); @@ -746,6 +836,16 @@ SharedMemoryId::SharedMemoryId(LPCSTR name) throw SharedMemoryException(static_cast(SharedMemoryError::NameInvalid)); } } + + m_isUserScope = isUserScope; + m_userScopeUid = isUserScope ? geteuid() : (uid_t)0; + + // The uid_t is converted to UINT32 to create a directory name, verify that it's valid + static_assert_no_msg(sizeof(uid_t) <= sizeof(UINT32)); + if ((uid_t)(UINT32)m_userScopeUid != m_userScopeUid) + { + throw SharedMemoryException(static_cast(SharedMemoryError::IO)); + } } LPCSTR SharedMemoryId::GetName() const @@ -760,20 +860,56 @@ SIZE_T SharedMemoryId::GetNameCharCount() const return m_nameCharCount; } +void SharedMemoryId::ReplaceNamePtr(LPCSTR name) +{ + _ASSERTE(name != nullptr); + _ASSERTE(m_nameCharCount != 0); + _ASSERTE(strlen(name) == m_nameCharCount); + + m_name = name; +} + bool SharedMemoryId::IsSessionScope() const { _ASSERTE(m_name != nullptr); return m_isSessionScope; } -bool SharedMemoryId::Equals(SharedMemoryId *other) const +bool SharedMemoryId::IsUserScope() const +{ + _ASSERTE(m_name != nullptr); + return m_isUserScope; +} + +uid_t SharedMemoryId::GetUserScopeUid() const +{ + _ASSERTE(m_name != nullptr); + _ASSERTE(m_isUserScope); + return m_userScopeUid; +} + +bool SharedMemoryId::Equals(const SharedMemoryId *other) const { return GetNameCharCount() == other->GetNameCharCount() && IsSessionScope() == other->IsSessionScope() && + IsUserScope() == other->IsUserScope() && + (!IsUserScope() || GetUserScopeUid() == other->GetUserScopeUid()) && strcmp(GetName(), other->GetName()) == 0; } +bool SharedMemoryId::AppendRuntimeTempDirectoryName(PathCharString& path) const +{ + if (IsUserScope()) + { + return + path.Append(SHARED_MEMORY_USER_SCOPED_RUNTIME_TEMP_DIRECTORY_NAME_PREFIX) && + SharedMemoryHelpers::AppendUInt32String(path, (UINT32)GetUserScopeUid()); + } + + return path.Append(SHARED_MEMORY_USER_UNSCOPED_RUNTIME_TEMP_DIRECTORY_NAME); +} + bool SharedMemoryId::AppendSessionDirectoryName(PathCharString& path) const { if (IsSessionScope()) @@ -826,6 +962,7 @@ void *SharedMemorySharedDataHeader::GetData() SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( SharedMemorySystemCallErrors *errors, LPCSTR name, + bool isUserScope, SharedMemorySharedDataHeader requiredSharedDataHeader, SIZE_T sharedDataByteCount, bool createIfNotExist, @@ -843,11 +980,11 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( } PathCharString filePath; - SharedMemoryId id(name); + SharedMemoryId id(name, isUserScope); struct AutoCleanup { - bool m_acquiredCreationDeletionFileLock; + const SharedMemoryId *m_acquiredCreationDeletionFileLockForId; PathCharString *m_filePath; SIZE_T m_sessionDirectoryPathCharCount; bool m_createdFile; @@ -858,7 +995,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( bool m_cancel; AutoCleanup() - : m_acquiredCreationDeletionFileLock(false), + : m_acquiredCreationDeletionFileLockForId(nullptr), m_filePath(nullptr), m_sessionDirectoryPathCharCount(0), m_createdFile(false), @@ -907,9 +1044,9 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( rmdir(*m_filePath); } - if (m_acquiredCreationDeletionFileLock) + if (m_acquiredCreationDeletionFileLockForId != nullptr) { - SharedMemoryManager::ReleaseCreationDeletionFileLock(); + SharedMemoryManager::ReleaseCreationDeletionFileLock(m_acquiredCreationDeletionFileLockForId); } } } autoCleanup; @@ -924,14 +1061,16 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( return processDataHeader; } - SharedMemoryManager::AcquireCreationDeletionFileLock(errors); - autoCleanup.m_acquiredCreationDeletionFileLock = true; + SharedMemoryManager::AcquireCreationDeletionFileLock(errors, &id); + autoCleanup.m_acquiredCreationDeletionFileLockForId = &id; // Create the session directory - SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(filePath)); - SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/')); - SharedMemoryHelpers::VerifyStringOperation(id.AppendSessionDirectoryName(filePath)); - if (!SharedMemoryHelpers::EnsureDirectoryExists(errors, filePath, true /* isGlobalLockAcquired */, createIfNotExist)) + SharedMemoryHelpers::VerifyStringOperation( + filePath.Set(*gSharedFilesPath) && + id.AppendRuntimeTempDirectoryName(filePath) && + filePath.Append('/') && filePath.Append(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME) && + filePath.Append('/') && id.AppendSessionDirectoryName(filePath)); + if (!SharedMemoryHelpers::EnsureDirectoryExists(errors, filePath, &id, true /* isGlobalLockAcquired */, createIfNotExist)) { _ASSERTE(!createIfNotExist); return nullptr; @@ -940,11 +1079,9 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( autoCleanup.m_sessionDirectoryPathCharCount = filePath.GetCount(); // Create or open the shared memory file - SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/')); - SharedMemoryHelpers::VerifyStringOperation(filePath.Append(id.GetName(), id.GetNameCharCount())); - + SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/') && filePath.Append(id.GetName(), id.GetNameCharCount())); bool createdFile; - int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(errors, filePath, createIfNotExist, &createdFile); + int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(errors, filePath, &id, createIfNotExist, &createdFile); if (fileDescriptor == -1) { _ASSERTE(!createIfNotExist); @@ -1039,8 +1176,8 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( // the shared data. The caller must release the file lock afterwards. if (!createdFile) { - autoCleanup.m_acquiredCreationDeletionFileLock = false; - SharedMemoryManager::ReleaseCreationDeletionFileLock(); + autoCleanup.m_acquiredCreationDeletionFileLockForId = nullptr; + SharedMemoryManager::ReleaseCreationDeletionFileLock(&id); } processDataHeader = SharedMemoryProcessDataHeader::New(&id, fileDescriptor, sharedDataHeader, sharedDataTotalByteCount); @@ -1108,12 +1245,13 @@ void SharedMemoryProcessDataHeader::PalObject_Close( } SharedMemoryProcessDataHeader::SharedMemoryProcessDataHeader( - SharedMemoryId *id, + const SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount) : m_refCount(1), + m_id(*id), m_data(nullptr), m_fileDescriptor(fileDescriptor), m_sharedDataHeader(sharedDataHeader), @@ -1131,13 +1269,13 @@ SharedMemoryProcessDataHeader::SharedMemoryProcessDataHeader( char *nameCopy = reinterpret_cast(this + 1); SIZE_T nameByteCount = id->GetNameCharCount() + 1; memcpy_s(nameCopy, nameByteCount, id->GetName(), nameByteCount); - m_id = SharedMemoryId(nameCopy, id->GetNameCharCount(), id->IsSessionScope()); + m_id.ReplaceNamePtr(nameCopy); SharedMemoryManager::AddProcessDataHeader(this); } SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::New( - SharedMemoryId *id, + const SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount) @@ -1177,17 +1315,17 @@ void SharedMemoryProcessDataHeader::Close() struct AutoReleaseCreationDeletionFileLock { - bool m_acquired; + const SharedMemoryId *m_acquiredForId; - AutoReleaseCreationDeletionFileLock() : m_acquired(false) + AutoReleaseCreationDeletionFileLock() : m_acquiredForId(nullptr) { } ~AutoReleaseCreationDeletionFileLock() { - if (m_acquired) + if (m_acquiredForId != nullptr) { - SharedMemoryManager::ReleaseCreationDeletionFileLock(); + SharedMemoryManager::ReleaseCreationDeletionFileLock(m_acquiredForId); } } } autoReleaseCreationDeletionFileLock; @@ -1201,8 +1339,8 @@ void SharedMemoryProcessDataHeader::Close() bool releaseSharedData = false; try { - SharedMemoryManager::AcquireCreationDeletionFileLock(nullptr); - autoReleaseCreationDeletionFileLock.m_acquired = true; + SharedMemoryManager::AcquireCreationDeletionFileLock(nullptr, GetId()); + autoReleaseCreationDeletionFileLock.m_acquiredForId = GetId(); SharedMemoryHelpers::ReleaseFileLock(m_fileDescriptor); if (SharedMemoryHelpers::TryAcquireFileLock(nullptr, m_fileDescriptor, LOCK_EX | LOCK_NB)) @@ -1246,11 +1384,12 @@ void SharedMemoryProcessDataHeader::Close() { // Delete the shared memory file, and the session directory if it's not empty PathCharString path; - SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(path)); - SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); - SharedMemoryHelpers::VerifyStringOperation(m_id.AppendSessionDirectoryName(path)); - SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); - + SharedMemoryHelpers::VerifyStringOperation( + path.Set(*gSharedFilesPath) && + m_id.AppendRuntimeTempDirectoryName(path) && + path.Append('/') && path.Append(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME) && + path.Append('/') && m_id.AppendSessionDirectoryName(path) && + path.Append('/')); SIZE_T sessionDirectoryPathCharCount = path.GetCount(); SharedMemoryHelpers::VerifyStringOperation(path.Append(m_id.GetName(), m_id.GetNameCharCount())); unlink(path); @@ -1263,7 +1402,7 @@ void SharedMemoryProcessDataHeader::Close() } } -SharedMemoryId *SharedMemoryProcessDataHeader::GetId() +const SharedMemoryId *SharedMemoryProcessDataHeader::GetId() const { return &m_id; } @@ -1345,37 +1484,20 @@ void SharedMemoryProcessDataHeader::DecRefCount() CRITICAL_SECTION SharedMemoryManager::s_creationDeletionProcessLock; int SharedMemoryManager::s_creationDeletionLockFileDescriptor = -1; +SharedMemoryManager::UserScopeUidAndFileDescriptor *SharedMemoryManager::s_userScopeUidToCreationDeletionLockFDs; +int SharedMemoryManager::s_userScopeUidToCreationDeletionLockFDsCount; +int SharedMemoryManager::s_userScopeUidToCreationDeletionLockFDsCapacity; + SharedMemoryProcessDataHeader *SharedMemoryManager::s_processDataHeaderListHead = nullptr; -PathCharString* SharedMemoryManager::s_runtimeTempDirectoryPath; -PathCharString* SharedMemoryManager::s_sharedMemoryDirectoryPath; #ifdef _DEBUG SIZE_T SharedMemoryManager::s_creationDeletionProcessLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; SIZE_T SharedMemoryManager::s_creationDeletionFileLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; #endif // _DEBUG -bool SharedMemoryManager::StaticInitialize() +void SharedMemoryManager::StaticInitialize() { InitializeCriticalSection(&s_creationDeletionProcessLock); - - s_runtimeTempDirectoryPath = new(std::nothrow) PathCharString(); - s_sharedMemoryDirectoryPath = new(std::nothrow) PathCharString(); - - if (s_runtimeTempDirectoryPath && s_sharedMemoryDirectoryPath) - { - try - { - SharedMemoryHelpers::BuildSharedFilesPath(*s_runtimeTempDirectoryPath, SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME); - SharedMemoryHelpers::BuildSharedFilesPath(*s_sharedMemoryDirectoryPath, SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME); - - return true; - } - catch (SharedMemoryException) - { - // Ignore and let function fail - } - } - return false; } void SharedMemoryManager::StaticClose() @@ -1417,16 +1539,23 @@ void SharedMemoryManager::ReleaseCreationDeletionProcessLock() LeaveCriticalSection(&s_creationDeletionProcessLock); } -void SharedMemoryManager::AcquireCreationDeletionFileLock(SharedMemorySystemCallErrors *errors) +void SharedMemoryManager::AcquireCreationDeletionFileLock(SharedMemorySystemCallErrors *errors, const SharedMemoryId *id) { + _ASSERTE(id != nullptr); _ASSERTE(IsCreationDeletionProcessLockAcquired()); _ASSERTE(!IsCreationDeletionFileLockAcquired()); - if (s_creationDeletionLockFileDescriptor == -1) + int creationDeletionLockFD = + id->IsUserScope() ? FindUserScopeCreationDeletionLockFD(id->GetUserScopeUid()) : s_creationDeletionLockFileDescriptor; + if (creationDeletionLockFD == -1) { + // Create the shared files directory + PathCharString dirPath; + SharedMemoryHelpers::VerifyStringOperation(dirPath.Set(*gSharedFilesPath)); if (!SharedMemoryHelpers::EnsureDirectoryExists( errors, - *gSharedFilesPath, + dirPath, + id, false /* isGlobalLockAcquired */, false /* createIfNotExist */, true /* isSystemDirectory */)) @@ -1440,49 +1569,117 @@ void SharedMemoryManager::AcquireCreationDeletionFileLock(SharedMemorySystemCall throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } - SharedMemoryHelpers::EnsureDirectoryExists( - errors, - *s_runtimeTempDirectoryPath, - false /* isGlobalLockAcquired */); + // Create the runtime temp directory + SharedMemoryHelpers::VerifyStringOperation(id->AppendRuntimeTempDirectoryName(dirPath)); + SharedMemoryHelpers::EnsureDirectoryExists(errors, dirPath, id, false /* isGlobalLockAcquired */); - SharedMemoryHelpers::EnsureDirectoryExists( - errors, - *s_sharedMemoryDirectoryPath, - false /* isGlobalLockAcquired */); + // Create the shared memory directory + SharedMemoryHelpers::VerifyStringOperation( + dirPath.Append('/') && dirPath.Append(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME)); + SharedMemoryHelpers::EnsureDirectoryExists(errors, dirPath, id, false /* isGlobalLockAcquired */); - s_creationDeletionLockFileDescriptor = SharedMemoryHelpers::OpenDirectory(errors, *s_sharedMemoryDirectoryPath); - if (s_creationDeletionLockFileDescriptor == -1) + // Open the shared memory directory + creationDeletionLockFD = SharedMemoryHelpers::OpenDirectory(errors, dirPath); + if (creationDeletionLockFD == -1) { if (errors != nullptr) { int errorCode = errno; errors->Append( "open(\"%s\", O_RDONLY | O_CLOEXEC, 0) == -1; errno == %s;", - (const char *)*s_sharedMemoryDirectoryPath, + (const char *)dirPath, GetFriendlyErrorCodeString(errorCode)); } throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } + + if (id->IsUserScope()) + { + AddUserScopeUidCreationDeletionLockFD(id->GetUserScopeUid(), creationDeletionLockFD); + } + else + { + s_creationDeletionLockFileDescriptor = creationDeletionLockFD; + } } - bool acquiredFileLock = SharedMemoryHelpers::TryAcquireFileLock(errors, s_creationDeletionLockFileDescriptor, LOCK_EX); + bool acquiredFileLock = SharedMemoryHelpers::TryAcquireFileLock(errors, creationDeletionLockFD, LOCK_EX); _ASSERTE(acquiredFileLock); #ifdef _DEBUG s_creationDeletionFileLockOwnerThreadId = THREADSilentGetCurrentThreadId(); #endif // _DEBUG } -void SharedMemoryManager::ReleaseCreationDeletionFileLock() +void SharedMemoryManager::ReleaseCreationDeletionFileLock(const SharedMemoryId *id) { + _ASSERTE(id != nullptr); _ASSERTE(IsCreationDeletionProcessLockAcquired()); _ASSERTE(IsCreationDeletionFileLockAcquired()); - _ASSERTE(s_creationDeletionLockFileDescriptor != -1); + + int creationDeletionLockFD = + id->IsUserScope() ? FindUserScopeCreationDeletionLockFD(id->GetUserScopeUid()) : s_creationDeletionLockFileDescriptor; + _ASSERTE(creationDeletionLockFD != -1); #ifdef _DEBUG s_creationDeletionFileLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; #endif // _DEBUG - SharedMemoryHelpers::ReleaseFileLock(s_creationDeletionLockFileDescriptor); + SharedMemoryHelpers::ReleaseFileLock(creationDeletionLockFD); +} + +void SharedMemoryManager::AddUserScopeUidCreationDeletionLockFD(uid_t userScopeUid, int creationDeletionLockFD) +{ + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + _ASSERTE(creationDeletionLockFD != -1); + _ASSERTE(FindUserScopeCreationDeletionLockFD(userScopeUid) == -1); + + int count = s_userScopeUidToCreationDeletionLockFDsCount; + int capacity = s_userScopeUidToCreationDeletionLockFDsCapacity; + if (count >= capacity) + { + int newCapacity = capacity == 0 ? 1 : capacity * 2; + if (newCapacity <= capacity || + newCapacity * sizeof(UserScopeUidAndFileDescriptor) / sizeof(UserScopeUidAndFileDescriptor) != (SIZE_T)newCapacity) + { + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } + + UserScopeUidAndFileDescriptor *newArray = new(std::nothrow) UserScopeUidAndFileDescriptor[newCapacity]; + if (newArray == nullptr) + { + throw SharedMemoryException(static_cast(SharedMemoryError::OutOfMemory)); + } + + if (count != 0) + { + UserScopeUidAndFileDescriptor *oldArray = s_userScopeUidToCreationDeletionLockFDs; + CopyMemory(newArray, oldArray, count * sizeof(newArray[0])); + delete[] oldArray; + } + + s_userScopeUidToCreationDeletionLockFDs = newArray; + s_userScopeUidToCreationDeletionLockFDsCapacity = newCapacity; + } + + s_userScopeUidToCreationDeletionLockFDs[count] = UserScopeUidAndFileDescriptor(userScopeUid, creationDeletionLockFD); + s_userScopeUidToCreationDeletionLockFDsCount = count + 1; +} + +int SharedMemoryManager::FindUserScopeCreationDeletionLockFD(uid_t userScopeUid) +{ + _ASSERTE(IsCreationDeletionProcessLockAcquired()); + + UserScopeUidAndFileDescriptor *arr = s_userScopeUidToCreationDeletionLockFDs; + for (int i = 0; i < s_userScopeUidToCreationDeletionLockFDsCount; i++) + { + _ASSERTE(arr[i].fileDescriptor != -1); + if (arr[i].userScopeUid == userScopeUid) + { + return arr[i].fileDescriptor; + } + } + + return -1; } #ifdef _DEBUG @@ -1535,7 +1732,7 @@ void SharedMemoryManager::RemoveProcessDataHeader(SharedMemoryProcessDataHeader _ASSERTE(false); } -SharedMemoryProcessDataHeader *SharedMemoryManager::FindProcessDataHeader(SharedMemoryId *id) +SharedMemoryProcessDataHeader *SharedMemoryManager::FindProcessDataHeader(const SharedMemoryId *id) { _ASSERTE(IsCreationDeletionProcessLockAcquired()); @@ -1551,8 +1748,3 @@ SharedMemoryProcessDataHeader *SharedMemoryManager::FindProcessDataHeader(Shared } return nullptr; } - -bool SharedMemoryManager::CopySharedMemoryBasePath(PathCharString& destination) -{ - return destination.Set(*s_sharedMemoryDirectoryPath) != FALSE; -} diff --git a/src/coreclr/pal/src/synchobj/mutex.cpp b/src/coreclr/pal/src/synchobj/mutex.cpp index f720fbcfb5fe44..a259f76e0192c6 100644 --- a/src/coreclr/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/pal/src/synchobj/mutex.cpp @@ -34,8 +34,6 @@ SET_DEFAULT_DEBUG_CHANNEL(SYNC); // some headers have code with asserts, so do t #include #include -#include "pal/sharedmemory.inl" - using namespace CorUnix; /* ------------------- Definitions ------------------------------*/ @@ -89,7 +87,7 @@ CreateMutexW( IN BOOL bInitialOwner, IN LPCWSTR lpName) { - return PAL_CreateMutexW(bInitialOwner, lpName, nullptr, 0); + return PAL_CreateMutexW(bInitialOwner, lpName, false /* bCurrentUserOnly */, nullptr, 0); } /*++ @@ -113,6 +111,7 @@ PALAPI PAL_CreateMutexW( IN BOOL bInitialOwner, IN LPCWSTR lpName, + IN BOOL bCurrentUserOnly, IN LPSTR lpSystemCallErrors, IN DWORD dwSystemCallErrorsBufferSize) { @@ -171,6 +170,7 @@ PAL_CreateMutexW( nullptr, bInitialOwner, lpName == nullptr ? nullptr : utf8Name, + bCurrentUserOnly, &hMutex ); } @@ -238,6 +238,7 @@ CorUnix::InternalCreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName, + BOOL bCurrentUserOnly, HANDLE *phMutex ) { @@ -317,7 +318,8 @@ CorUnix::InternalCreateMutex( SharedMemoryProcessDataHeader *processDataHeader; try { - processDataHeader = NamedMutexProcessData::CreateOrOpen(errors, lpName, !!bInitialOwner, &createdNamedMutex); + processDataHeader = + NamedMutexProcessData::CreateOrOpen(errors, lpName, !!bCurrentUserOnly, !!bInitialOwner, &createdNamedMutex); } catch (SharedMemoryException ex) { @@ -543,7 +545,7 @@ OpenMutexA ( goto OpenMutexAExit; } - palError = InternalOpenMutex(nullptr, pthr, lpName, &hMutex); + palError = InternalOpenMutex(nullptr, pthr, lpName, false /* bCurrentUserOnly */, &hMutex); OpenMutexAExit: if (NO_ERROR != palError) @@ -571,7 +573,7 @@ OpenMutexW( IN BOOL bInheritHandle, IN LPCWSTR lpName) { - return PAL_OpenMutexW(lpName, nullptr, 0); + return PAL_OpenMutexW(lpName, false /* bCurrentUserOnly */, nullptr, 0); } /*++ @@ -593,6 +595,7 @@ HANDLE PALAPI PAL_OpenMutexW( IN LPCWSTR lpName, + IN BOOL bCurrentUserOnly, IN LPSTR lpSystemCallErrors, IN DWORD dwSystemCallErrorsBufferSize) { @@ -612,10 +615,11 @@ PAL_OpenMutexW( /* validate parameters */ if (lpName == nullptr || + lpName[0] == W('\0') || (int)dwSystemCallErrorsBufferSize < 0 || (lpSystemCallErrors == nullptr) != (dwSystemCallErrorsBufferSize == 0)) { - ERROR("name is NULL or other parameters are invalid\n"); + ERROR("One or more parameters are invalid\n"); palError = ERROR_INVALID_PARAMETER; goto OpenMutexWExit; } @@ -643,7 +647,7 @@ PAL_OpenMutexW( } SharedMemorySystemCallErrors errors(lpSystemCallErrors, (int)dwSystemCallErrorsBufferSize); - palError = InternalOpenMutex(&errors, pthr, lpName == nullptr ? nullptr : utf8Name, &hMutex); + palError = InternalOpenMutex(&errors, pthr, lpName == nullptr ? nullptr : utf8Name, bCurrentUserOnly, &hMutex); } OpenMutexWExit: @@ -675,6 +679,7 @@ CorUnix::InternalOpenMutex( SharedMemorySystemCallErrors *errors, CPalThread *pthr, LPCSTR lpName, + BOOL bCurrentUserOnly, HANDLE *phMutex ) { @@ -711,7 +716,7 @@ CorUnix::InternalOpenMutex( SharedMemoryProcessDataHeader *processDataHeader; try { - processDataHeader = NamedMutexProcessData::Open(errors, lpName); + processDataHeader = NamedMutexProcessData::Open(errors, lpName, bCurrentUserOnly); } catch (SharedMemoryException ex) { @@ -1074,20 +1079,29 @@ const DWORD NamedMutexProcessData::PollLoopMaximumSleepMilliseconds = 100; SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( SharedMemorySystemCallErrors *errors, LPCSTR name, + bool isUserScope, bool acquireLockIfCreated, bool *createdRef) { - return CreateOrOpen(errors, name, true /* createIfNotExist */, acquireLockIfCreated, createdRef); + return CreateOrOpen(errors, name, isUserScope, true /* createIfNotExist */, acquireLockIfCreated, createdRef); } -SharedMemoryProcessDataHeader *NamedMutexProcessData::Open(SharedMemorySystemCallErrors *errors, LPCSTR name) +SharedMemoryProcessDataHeader *NamedMutexProcessData::Open(SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope) { - return CreateOrOpen(errors, name, false /* createIfNotExist */, false /* acquireLockIfCreated */, nullptr /* createdRef */); + return + CreateOrOpen( + errors, + name, + isUserScope, + false /* createIfNotExist */, + false /* acquireLockIfCreated */, + nullptr /* createdRef */); } SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( SharedMemorySystemCallErrors *errors, LPCSTR name, + bool isUserScope, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef) @@ -1153,7 +1167,8 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( if (m_acquiredCreationDeletionFileLock) { - SharedMemoryManager::ReleaseCreationDeletionFileLock(); + _ASSERTE(m_processDataHeader != nullptr); + SharedMemoryManager::ReleaseCreationDeletionFileLock(m_processDataHeader->GetId()); } if (!m_cancel && m_processDataHeader != nullptr) @@ -1178,6 +1193,7 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( SharedMemoryProcessDataHeader::CreateOrOpen( errors, name, + isUserScope, SharedMemorySharedDataHeader(SharedMemoryType::Mutex, SyncSystemVersion), sizeof(NamedMutexSharedData), createIfNotExist, @@ -1186,6 +1202,12 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( { *createdRef = created; } + if (processDataHeader == nullptr) + { + _ASSERTE(!created); + _ASSERTE(!createIfNotExist); + return nullptr; + } if (created) { // If the shared memory file was created, the creation/deletion file lock would have been acquired so that we can @@ -1193,11 +1215,6 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( _ASSERTE(SharedMemoryManager::IsCreationDeletionFileLockAcquired()); autoCleanup.m_acquiredCreationDeletionFileLock = true; } - if (processDataHeader == nullptr) - { - _ASSERTE(!createIfNotExist); - return nullptr; - } autoCleanup.m_processDataHeader = processDataHeader; if (created) @@ -1210,27 +1227,29 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( { #if !NAMED_MUTEX_USE_PTHREAD_MUTEX // Create the lock files directory - SharedMemoryHelpers::BuildSharedFilesPath(lockFilePath, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME); + const SharedMemoryId *id = processDataHeader->GetId(); + SharedMemoryHelpers::VerifyStringOperation( + lockFilePath.Set(*gSharedFilesPath) && + id->AppendRuntimeTempDirectoryName(lockFilePath) && + lockFilePath.Append('/') && lockFilePath.Append(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME)); if (created) { - SharedMemoryHelpers::EnsureDirectoryExists(errors, lockFilePath, true /* isGlobalLockAcquired */); + SharedMemoryHelpers::EnsureDirectoryExists(errors, lockFilePath, id, true /* isGlobalLockAcquired */); } // Create the session directory - SharedMemoryId *id = processDataHeader->GetId(); - SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/')); - SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(lockFilePath)); + SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/') && id->AppendSessionDirectoryName(lockFilePath)); if (created) { - SharedMemoryHelpers::EnsureDirectoryExists(errors, lockFilePath, true /* isGlobalLockAcquired */); + SharedMemoryHelpers::EnsureDirectoryExists(errors, lockFilePath, id, true /* isGlobalLockAcquired */); autoCleanup.m_lockFilePath = &lockFilePath; autoCleanup.m_sessionDirectoryPathCharCount = lockFilePath.GetCount(); } // Create or open the lock file - SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/')); - SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append(id->GetName(), id->GetNameCharCount())); - int lockFileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(errors, lockFilePath, created); + SharedMemoryHelpers::VerifyStringOperation( + lockFilePath.Append('/') && lockFilePath.Append(id->GetName(), id->GetNameCharCount())); + int lockFileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(errors, lockFilePath, id, created); if (lockFileDescriptor == -1) { _ASSERTE(!created); @@ -1394,11 +1413,13 @@ void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData) { // Delete the lock file, and the session directory if it's not empty PathCharString path; - SharedMemoryHelpers::BuildSharedFilesPath(path, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME); - SharedMemoryId *id = m_processDataHeader->GetId(); - SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); - SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(path)); - SharedMemoryHelpers::VerifyStringOperation(path.Append('/')); + const SharedMemoryId *id = m_processDataHeader->GetId(); + SharedMemoryHelpers::VerifyStringOperation( + path.Set(*gSharedFilesPath) && + id->AppendRuntimeTempDirectoryName(path) && + path.Append('/') && path.Append(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) && + path.Append('/') && id->AppendSessionDirectoryName(path) && + path.Append('/')); SIZE_T sessionDirectoryPathCharCount = path.GetCount(); SharedMemoryHelpers::VerifyStringOperation(path.Append(id->GetName(), id->GetNameCharCount())); unlink(path); diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 1688d3b16779bf..e9596e2ea9aba7 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2452,6 +2452,16 @@ PAL_GenerateCoreDump( (no return value) --*/ +#ifdef HOST_ANDROID +#include +VOID +PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize) +{ + // TODO: Dump all managed threads callstacks into logcat and/or file? + // TODO: Dump stress log into logcat and/or file when enabled? + minipal_log_write_fatal("Aborting process.\n"); +} +#else VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize) { @@ -2520,6 +2530,7 @@ PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize) free(signalAddressArg); } } +#endif /*++ Function: diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt index f651fde4e634aa..93b9c0070ba18b 100644 --- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt @@ -257,13 +257,6 @@ add_executable_clr(paltests filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp - file_io/CopyFileA/test1/CopyFileA.cpp - file_io/CopyFileA/test2/test2.cpp - file_io/CopyFileA/test3/test3.cpp - file_io/CopyFileA/test4/test4.cpp - file_io/CopyFileW/test1/CopyFileW.cpp - file_io/CopyFileW/test2/test2.cpp - file_io/CopyFileW/test3/test3.cpp file_io/CreateFileA/test1/CreateFileA.cpp file_io/CreateFileW/test1/CreateFileW.cpp file_io/errorpathnotfound/test1/test1.cpp @@ -289,12 +282,6 @@ add_executable_clr(paltests file_io/GetStdHandle/test2/GetStdHandle.cpp file_io/GetSystemTime/test1/test.cpp file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp - file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp - file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp - file_io/GetTempFileNameA/test3/gettempfilenamea.cpp - file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp - file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp - file_io/GetTempFileNameW/test3/gettempfilenamew.cpp file_io/gettemppatha/test1/gettemppatha.cpp file_io/GetTempPathW/test1/GetTempPathW.cpp file_io/ReadFile/test1/ReadFile.cpp @@ -402,7 +389,6 @@ add_executable_clr(paltests miscellaneous/SetEnvironmentVariableW/test3/test3.cpp miscellaneous/SetEnvironmentVariableW/test4/test4.cpp miscellaneous/SetLastError/test1/test.cpp -# pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp # pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp diff --git a/src/coreclr/pal/tests/palsuite/DisabledTests.txt b/src/coreclr/pal/tests/palsuite/DisabledTests.txt index 0f7094c4a8e882..83b9bcc843cabf 100644 --- a/src/coreclr/pal/tests/palsuite/DisabledTests.txt +++ b/src/coreclr/pal/tests/palsuite/DisabledTests.txt @@ -15,21 +15,6 @@ The above testcases were disabled in the palsuite, because they depend heavily o WaitForDebugEvent,DebugActiveProcess and ContinueDebugEvent, where these api's have been removed from the PAL. - -file_io/gettempfilenamea/test2 : -======================================= -This test takes longer than 60 seconds to run. The test creates -about 65000 files and then deletes them. The test that takes longer -than 60 seconds will be flagged as an error and so in such a case -the test will have to be run manually. - -file_io/gettempfilenamew/test2 : -======================================= -This test takes longer than 60 seconds to run. The test creates -about 65000 files and then deletes them. The test that takes longer -than 60 seconds will be flagged as an error and so in such a case -the test will have to be run manually. - locale_info/getcpinfo/test2: ======================================= This test will be useful in future versions for testing various diff --git a/src/coreclr/pal/tests/palsuite/README.txt b/src/coreclr/pal/tests/palsuite/README.txt index 84a297538f7aff..02562f186d5886 100644 --- a/src/coreclr/pal/tests/palsuite/README.txt +++ b/src/coreclr/pal/tests/palsuite/README.txt @@ -9,14 +9,10 @@ 2. RUNNING THE SUITES 3. ENVIRONMENT VARIABLES AND AUTOMATED TESTING SPECIFICS -3.1 PAL_DISABLE_MESSAGEBOX -3.2 Other Notes 4. ADDITIONAL NOTES ON TESTING/SPECIFIC TEST CASE ISSUES File_IO: getfilesize/test1, setfilepointer/test(5,6,7) - File_IO: gettempfilename(a,w)/test2 File_IO: setfileattributesa/test(1,4), setfileattributesw/test(1,4) - Miscellaneous: messageboxw/test(1,2) Pal_specific:: pal_get_stdin/test1, pal_get_stdout/test1, pal_get_stderr/test1 Threading: setconsolectrlhandler/test(3,4) @@ -45,7 +41,6 @@ The results are logged to %ROTOR_DIR%\tests\pvtResults.log. See notes in section 4 on the following test cases if running automated tests: - Miscellaneous: messageboxw/test(1,2) Threading: setconsolectrlhandler/test(3,4) @@ -59,20 +54,6 @@ ample disk space. On systems with less than 6Gb free disk space expect these test cases to fail. -File_IO: gettempfilename(a,w)/test2 - -These test cases take longer than 60 seconds to run. Currently, the Test -Harness will timeout any test case that exceeds 60 seconds. - - -Miscellaneous: messageboxw/test(1,2) - -Setting PAL_MESSAGEBOX_DISABLE=1 for these test cases prevents message box pop -ups that occur during the tests' execution on Windows. For automated testing -where user interaction is not desired/possible, setting this environment -variable will prevent a pause in the automated test run. - - ic: pal_get_stdin/test1, pal_get_stdout/test1, pal_get_stderr/test1 These test cases should be manually inspected to ensure the information being returned diff --git a/src/coreclr/pal/tests/palsuite/compilableTests.txt b/src/coreclr/pal/tests/palsuite/compilableTests.txt index eec58858f3b0dd..d9c36e4ab5d299 100644 --- a/src/coreclr/pal/tests/palsuite/compilableTests.txt +++ b/src/coreclr/pal/tests/palsuite/compilableTests.txt @@ -181,13 +181,6 @@ filemapping_memmgt/VirtualProtect/test4/paltest_virtualprotect_test4 filemapping_memmgt/VirtualProtect/test6/paltest_virtualprotect_test6 filemapping_memmgt/VirtualProtect/test7/paltest_virtualprotect_test7 filemapping_memmgt/VirtualQuery/test1/paltest_virtualquery_test1 -file_io/CopyFileA/test1/paltest_copyfilea_test1 -file_io/CopyFileA/test2/paltest_copyfilea_test2 -file_io/CopyFileA/test3/paltest_copyfilea_test3 -file_io/CopyFileA/test4/paltest_copyfilea_test4 -file_io/CopyFileW/test1/paltest_copyfilew_test1 -file_io/CopyFileW/test2/paltest_copyfilew_test2 -file_io/CopyFileW/test3/paltest_copyfilew_test3 file_io/CreateFileA/test1/paltest_createfilea_test1 file_io/CreateFileW/test1/paltest_createfilew_test1 file_io/errorpathnotfound/test1/paltest_errorpathnotfound_test1 @@ -213,12 +206,6 @@ file_io/GetStdHandle/test1/paltest_getstdhandle_test1 file_io/GetStdHandle/test2/paltest_getstdhandle_test2 file_io/GetSystemTime/test1/paltest_getsystemtime_test1 file_io/GetSystemTimeAsFileTime/test1/paltest_getsystemtimeasfiletime_test1 -file_io/GetTempFileNameA/test1/paltest_gettempfilenamea_test1 -file_io/GetTempFileNameA/test2/paltest_gettempfilenamea_test2 -file_io/GetTempFileNameA/test3/paltest_gettempfilenamea_test3 -file_io/GetTempFileNameW/test1/paltest_gettempfilenamew_test1 -file_io/GetTempFileNameW/test2/paltest_gettempfilenamew_test2 -file_io/GetTempFileNameW/test3/paltest_gettempfilenamew_test3 file_io/gettemppatha/test1/paltest_gettemppatha_test1 file_io/GetTempPathW/test1/paltest_gettemppathw_test1 file_io/ReadFile/test1/paltest_readfile_test1 @@ -313,7 +300,6 @@ miscellaneous/SetEnvironmentVariableW/test2/paltest_setenvironmentvariablew_test miscellaneous/SetEnvironmentVariableW/test3/paltest_setenvironmentvariablew_test3 miscellaneous/SetEnvironmentVariableW/test4/paltest_setenvironmentvariablew_test4 miscellaneous/SetLastError/test1/paltest_setlasterror_test1 -pal_specific/PAL_GetUserTempDirectoryW/test1/paltest_pal_getusertempdirectoryw_test1 pal_specific/PAL_Initialize_Terminate/test1/paltest_pal_initialize_terminate_test1 pal_specific/PAL_Initialize_Terminate/test2/paltest_pal_initialize_terminate_test2 pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/paltest_pal_registerlibraryw_unregisterlibraryw_test1 diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp deleted file mode 100644 index 486c4dcbd6c650..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: CopyFileA.c -** -** Purpose: Tests the PAL implementation of the CopyFileA function -** -** -**===================================================================*/ - -/* - 1. copy an existing file to existing with overwrite true - 2. copy an existing file to existing with overwrite false - 3. copy an existing file to non-existent with overwrite true - 4. copy an existing file to non-existent with overwrite false - 5. copy non-existent file to existing with overwrite true - 6. copy non-existent file to existing with overwrite false - 7. copy non-existent file to non-existent with overwrite true - 8. copy non-existent file to non-existent with overwrite false -*/ - -#include - -struct TESTS{ - char* lpSource; - char* lpDestination; - BOOL bFailIfExists; - int nResult; - }; - - -PALTEST(file_io_CopyFileA_test1_paltest_copyfilea_test1, "file_io/CopyFileA/test1/paltest_copyfilea_test1") -{ - char szSrcExisting[] = {"src_existing.tmp"}; - char szSrcNonExistent[] = {"src_non-existent.tmp"}; - char szDstExisting[] = {"dst_existing.tmp"}; - char szDstNonExistent[] = {"dst_non-existent.tmp"}; - BOOL bRc = TRUE; - BOOL bSuccess = TRUE; - FILE* tempFile = NULL; - int i; - struct TESTS testCase[] = - { - {szSrcExisting, szDstExisting, FALSE, 1}, - {szSrcExisting, szDstExisting, TRUE, 0}, - {szSrcExisting, szDstNonExistent, FALSE, 1}, - {szSrcExisting, szDstNonExistent, TRUE, 1}, - {szSrcNonExistent, szDstExisting, FALSE, 0}, - {szSrcNonExistent, szDstExisting, TRUE, 0}, - {szSrcNonExistent, szDstNonExistent, FALSE, 0}, - {szSrcNonExistent, szDstNonExistent, TRUE, 0} - }; - - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* create the src_existing file */ - tempFile = fopen(szSrcExisting, "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "CopyFileA test file: src_existing.tmp\n"); - fclose(tempFile); - } - else - { - Fail("CopyFileA: ERROR-> Couldn't create \"src_existing.tmp\" with " - "error %ld\n", - GetLastError()); - } - - /* create the dst_existing file */ - tempFile = fopen(szDstExisting, "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "CopyFileA test file: dst_existing.tmp\n"); - fclose(tempFile); - } - else - { - Fail("CopyFileA: ERROR-> Couldn't create \"dst_existing.tmp\" with " - "error %ld\n", - GetLastError()); - } - - - - for (i = 0; i < (sizeof(testCase) / sizeof(struct TESTS)); i++) - { - bRc = CopyFileA(testCase[i].lpSource, - testCase[i].lpDestination, - testCase[i].bFailIfExists); - if (!bRc) - { - if (testCase[i].nResult == 1) - { - Trace("CopyFileA: FAILED: %s -> %s with bFailIfExists = %d " - "with error %ld\n", - testCase[i].lpSource, - testCase[i].lpDestination, - testCase[i].bFailIfExists, - GetLastError()); - bSuccess = FALSE; - } - } - else - { - if (testCase[i].nResult == 0) - { - Trace("CopyFileA: FAILED: %s -> %s with bFailIfExists = %d\n", - testCase[i].lpSource, - testCase[i].lpDestination, - testCase[i].bFailIfExists); - bSuccess = FALSE; - } - else - { - /* verify the file was moved */ - if (GetFileAttributesA(testCase[i].lpDestination) == -1) - { - Trace("CopyFileA: GetFileAttributes of destination file " - "failed with error code %ld. \n", - GetLastError()); - bSuccess = FALSE; - } - else if (GetFileAttributesA(testCase[i].lpSource) == -1) - { - Trace("CopyFileA: GetFileAttributes of source file " - "failed with error code %ld. \n", - GetLastError()); - bSuccess = FALSE; - } - else - { - /* verify attributes of destination file to source file*/ - if(GetFileAttributes(testCase[i].lpSource) != - GetFileAttributes(testCase[i].lpDestination)) - { - Trace("CopyFileA : The file attributes of the " - "destination file do not match the file " - "attributes of the source file.\n"); - bSuccess = FALSE; - } - } - } - } - /* delete file file but don't worry if it fails */ - remove(szDstNonExistent); - } - - int exitCode = bSuccess ? PASS : FAIL; - PAL_TerminateEx(exitCode); - return exitCode; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp deleted file mode 100644 index cfc5237a34d3c8..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test2.c -** -** Purpose: Tests the PAL implementation of the CopyFileA function -** to see if a file can be copied to itself -** -** -**===================================================================*/ - - -#include - -PALTEST(file_io_CopyFileA_test2_paltest_copyfilea_test2, "file_io/CopyFileA/test2/paltest_copyfilea_test2") -{ - - BOOL bRc = TRUE; - char* szSrcExisting = "src_existing.tmp"; - FILE* tempFile = NULL; - DWORD temp; - int retCode; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* create the src_existing file */ - tempFile = fopen(szSrcExisting, "w"); - if (tempFile != NULL) - { - retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile); - if(retCode < 0) - { - Fail("CopyFileA: ERROR-> Couldn't write to %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - retCode = fclose(tempFile); - if(retCode != 0) - { - Fail("CopyFileA: ERROR-> Couldn't close file: %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - - } - else - { - Fail("CopyFileA: ERROR-> Couldn't create %s with " - "error %ld\n",szSrcExisting,GetLastError()); - } - - /* Get file attributes of source */ - temp = GetFileAttributes(szSrcExisting); - if (temp == -1) - { - Fail("CopyFileA: GetFileAttributes of source file " - "failed with error code %ld. \n", - GetLastError()); - } - - /* make sure a file can't copy to itself - first testing with IfFileExists flag set to true */ - bRc = CopyFileA(szSrcExisting,szSrcExisting,TRUE); - if(bRc) - { - Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); - } - - /* try to get file attributes of destination */ - if (GetFileAttributesA(szSrcExisting) == -1) - { - Fail("CopyFileA: GetFileAttributes of destination file " - "failed with error code %ld. \n", - GetLastError()); - } - else - { - /* verify attributes of destination file to source file*/ - - if(temp != GetFileAttributes(szSrcExisting)) - { - Fail("CopyFileA : The file attributes of the " - "destination file do not match the file " - "attributes of the source file.\n"); - } - } - - /* testing with IfFileExists flags set to false - should fail in Windows and pass in UNIX */ - bRc = CopyFileA(szSrcExisting,szSrcExisting,FALSE); - if(bRc && (GetLastError() != ERROR_ALREADY_EXISTS)) - { - Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); - } - - if (GetFileAttributesA(szSrcExisting) == -1) - { - Fail("CopyFileA: GetFileAttributes of destination file " - "failed with error code %ld. \n", - GetLastError()); - } - else - { - /* verify attributes of destination file to source file*/ - - if(temp != GetFileAttributes(szSrcExisting)) - { - Fail("CopyFileA : The file attributes of the " - "destination file do not match the file " - "attributes of the source file.\n"); - } - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp deleted file mode 100644 index 33d3c541c5e986..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test3.c -** -** Purpose: Tests the PAL implementation of the CopyFileA function -** to see if a file can be copied to itself -** -** -**===================================================================*/ - -#include - -PALTEST(file_io_CopyFileA_test3_paltest_copyfilea_test3, "file_io/CopyFileA/test3/paltest_copyfilea_test3") -{ - - BOOL bRc = TRUE; - char* szSrcExisting = "src_existing.tmp"; - char* szDest = "src_dest.tmp"; - FILE* tempFile = NULL; - int retCode; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* create the src_existing file */ - tempFile = fopen(szSrcExisting, "w"); - if (tempFile != NULL) - { - retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile); - if(retCode < 0) - { - retCode = fclose(tempFile); - if(retCode != 0) - { - Trace("CopyFileA: ERROR-> Couldn't close file: %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - - Fail("CopyFileA: ERROR-> Couldn't write to %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - retCode = fclose(tempFile); - if(retCode != 0) - { - Fail("CopyFileA: ERROR-> Couldn't close file: %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - - } - else - { - Fail("CopyFileA: ERROR-> Couldn't create %s with " - "error %ld\n",szSrcExisting,GetLastError()); - } - - /* set the file attributes of the source file to readonly */ - bRc = SetFileAttributesA(szSrcExisting, FILE_ATTRIBUTE_READONLY); - if(!bRc) - { - Fail("CopyFileA: ERROR-> Couldn't set file attributes for " - "file %s with error %u\n", szSrcExisting, GetLastError()); - } - - // Check the file attributes to make sure SetFileAttributes() above actually succeeded - DWORD fileAttributes = GetFileAttributesA(szSrcExisting); - if (fileAttributes == INVALID_FILE_ATTRIBUTES) - { - Fail("CopyFileA: Failed to get file attributes for source file, %u\n", GetLastError()); - } - if ((fileAttributes & FILE_ATTRIBUTE_READONLY) == 0) - { - Fail("CopyFileA: SetFileAttributes(read-only) on source file returned success but did not make it read-only.\n"); - } - - /* copy the file */ - bRc = CopyFileA(szSrcExisting,szDest,TRUE); - if(!bRc) - { - Fail("CopyFileA: Cannot copy a file with error, %u",GetLastError()); - } - - - /* try to get file attributes of destination file */ - fileAttributes = GetFileAttributesA(szDest); - if (fileAttributes == INVALID_FILE_ATTRIBUTES) - { - Fail("CopyFileA: GetFileAttributes of destination file " - "failed with error code %ld. \n", - GetLastError()); - } - - /* verify attributes of destination file to source file*/ - if((fileAttributes & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) - { - Fail("CopyFileA : The file attributes of the " - "destination file do not match the file " - "attributes of the source file.\n"); - } - - /* set the attributes of the destination file to normal again */ - bRc = SetFileAttributesA(szDest, FILE_ATTRIBUTE_NORMAL); - if(!bRc) - { - Fail("CopyFileA: ERROR-> Couldn't set file attributes for " - "file %s with error %u\n", szDest, GetLastError()); - } - - /* delete the newly copied file */ - int st = remove(szDest); - if(st != 0) - { - Fail("CopyFileA: remove failed to delete the" - "file correctly with error,%u.\n",errno); - } - - /* set the attributes of the source file to normal again */ - bRc = SetFileAttributesA(szSrcExisting, FILE_ATTRIBUTE_NORMAL); - if(!bRc) - { - Fail("CopyFileA: ERROR-> Couldn't set file attributes for " - "file %s with error %u\n", szSrcExisting, GetLastError()); - } - - /* delete the original file */ - st = remove(szSrcExisting); - if(st != 0) - { - Fail("CopyFileA: remove failed to delete the" - "file correctly with error,%u.\n",errno); - } - - PAL_Terminate(); - return PASS; - -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp deleted file mode 100644 index 9eaecf2702c0bd..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test4.c -** -** Purpose: Tests the PAL implementation of the CopyFileA function -** to see if a file can through different users belonging to -** different groups. -** - -=====================================================================*/ - -/* USECASE - Copy a file from a different user, belonging to a different group to - the current user, who is a member of the current group. Then check - to see that the current user has the basic access rights to the copied - file. - - Thie original file used is the passwd file in the etc directory of a - BSD machine. This file should exist on all machines. -*/ - -#include - -PALTEST(file_io_CopyFileA_test4_paltest_copyfilea_test4, "file_io/CopyFileA/test4/paltest_copyfilea_test4") -{ - -#if WIN32 - return PASS; - -#else - - BOOL bRc = TRUE; - char* szSrcExisting = "/etc/passwd"; - char* szDest = "temp.tmp"; - char* szStringTest = "Marry had a little lamb"; - char szStringRead[30]; /* large enough for string szStringTest */ - - HANDLE hFile = NULL; - DWORD dwBytesWritten=0; - DWORD dwBytesRead=0; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* copy the file */ - bRc = CopyFileA(szSrcExisting,szDest,TRUE); - if(!bRc) - { - Fail("CopyFileA: Cannot copy a file with error, %u",GetLastError()); - } - - /* try to get file attributes of destination file */ - if (GetFileAttributesA(szDest) == -1) - { - Fail("CopyFileA: GetFileAttributes of destination file " - "failed with error code %u. \n", - GetLastError()); - } - - /* set the attributes of the destination file to normal again */ - bRc = SetFileAttributesA(szDest, FILE_ATTRIBUTE_NORMAL); - if(!bRc) - { - Fail("CopyFileA: ERROR-> Couldn't set file attributes for " - "file %s with error %u\n", szDest, GetLastError()); - } - - /* open the file for write purposes */ - hFile = CreateFile(szDest, - GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if(hFile == INVALID_HANDLE_VALUE) - { - Fail("CopyFileA: ERROR -> Unable to create file \"%s\".\n", - szDest); - } - - /* Attempt to write to the file */ - bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL); - if (!bRc) - { - Trace("CopyFileA: ERROR -> Unable to write to copied file with error " - "%u.\n", GetLastError()); - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with " - "error %u.\n",szDest, GetLastError()); - } - Fail(""); - - } - - /* Close the file handle */ - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with error %u " - ".\n",szDest,GetLastError()); - } - - - /* open the file for read purposes */ - hFile = CreateFile(szDest, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if(hFile == INVALID_HANDLE_VALUE) - { - Fail("CopyFileA: ERROR -> Unable to create file \"%s\".\n", - szDest); - } - - /* Attempt to read from the file */ - bRc = ReadFile(hFile, szStringRead, strlen(szStringTest), &dwBytesRead, NULL); - if (!bRc) - { - Trace("CopyFileA: ERROR -> Unable to read from copied file with " - "error %u.\n",GetLastError()); - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with " - "error %u.\n",szDest, GetLastError()); - } - Fail(""); - - } - - if(strncmp(szStringTest,szStringRead, strlen(szStringTest)) != 0) - { - Trace("CopyFileA: ERROR -> The string which was written '%s' does not " - "match the string '%s' which was read from the copied file.\n", - szStringTest,szStringRead); - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with " - "error %u.\n",szDest, GetLastError()); - } - Fail(""); - } - - /* Close the file handle */ - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with error %u " - ".\n",szDest,GetLastError()); - } - - /* Remove the temporary file */ - int st = remove(szDest); - if(st != 0) - { - Fail("CopyFileA: Could not remove copied file with error %u\n", - errno); - } - - PAL_Terminate(); - return PASS; - -#endif - -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp deleted file mode 100644 index 27dc32921368e2..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: CopyFileW.c -** -** Purpose: Tests the PAL implementation of the CopyFileW function -** -** -**===================================================================*/ - -/* -1. copy an existing file to non-existent with overwrite true -2. copy an existing file to non-existent with overwrite false -3. copy an existing file to existing with overwrite true -4. copy an existing file to existing with overwrite false -5. copy non-existent file to non-existent with overwrite true -6. copy non-existent file to non-existent with overwrite false -7. copy non-existent file to existing with overwrite true -8. copy non-existent file to existing with overwrite false -*/ - -#include - -PALTEST(file_io_CopyFileW_test1_paltest_copyfilew_test1, "file_io/CopyFileW/test1/paltest_copyfilew_test1") -{ - LPSTR lpSource[2] = {"src_existing.tmp", "src_non-existent.tmp"}; - LPSTR lpDestination[2] = {"dst_existing.tmp", "dst_non-existent.tmp"}; - WCHAR* wcSource; - WCHAR* wcDest; - BOOL bFailIfExists[3] = {FALSE, TRUE}; - BOOL bRc = TRUE; - BOOL bSuccess = TRUE; - char results[20]; - FILE* resultsFile = NULL; - FILE* tempFile = NULL; - int nCounter = 0; - int i, j, k; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* load the expected results */ - resultsFile = fopen("expectedresults.txt", "r"); - memset (results, 0, 20); - fgets(results, 20, resultsFile); - fclose(resultsFile); - - nCounter = 0; - - /* create the src_existing file */ - tempFile = fopen(lpSource[0], "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "CopyFileW test file: src_existing.tmp\n"); - fclose(tempFile); - } - else - { - Fail("CopyFileW: ERROR-> Couldn't create \"src_existing.tmp\"\n"); - } - - /* create the dst_existing file */ - tempFile = fopen(lpDestination[0], "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "CopyFileW test file: dst_existing.tmp\n"); - fclose(tempFile); - } - else - { - Fail("CopyFileW: ERROR-> Couldn't create \"dst_existing.tmp\"\n"); - } - - - /* lpSource loop */ - for (i = 0; i < 2; i++) - { - /* lpDestination loop */ - for (j = 0; j < 2; j++) - { - /* bFailIfExists loop */ - for (k = 0; k < 2; k++) - { - wcSource = convert(lpSource[i]); - wcDest = convert(lpDestination[j]); - bRc = CopyFileW(wcSource, - wcDest, - bFailIfExists[k]); - free(wcSource); - free(wcDest); - if (!bRc) - { - if (results[nCounter] == '1') - { - Trace("CopyFileW: FAILED: test[%d][%d][%d]\n", i, j, k); - bSuccess = FALSE; - } - } - else - { - if (results[nCounter] == '0') - { - Trace("CopyFileW: FAILED: test[%d][%d][%d]\n", i, j, k); - bSuccess = FALSE; - } - else - { - /* verify the file was moved */ - if (GetFileAttributesA(lpDestination[j]) == -1) - { - Trace("CopyFileW: GetFileAttributes of destination" - "file failed on test[%d][%d][%d] with error " - "code %ld. \n",i,j,k,GetLastError()); - bSuccess = FALSE; - } - else if (GetFileAttributesA(lpSource[i]) == -1) - { - Trace("CopyFileW: GetFileAttributes of source file " - "file failed on test[%d][%d][%d] with error " - "code %ld. \n",i,j,k,GetLastError()); - bSuccess = FALSE; - } - else - { - /* verify attributes of destination file to - source file*/ - if(GetFileAttributes(lpSource[i]) != - GetFileAttributes(lpDestination[j])) - { - Trace("CopyFileW : The file attributes of the " - "destination file do not match the file " - "attributes of the source file on test " - "[%d][%d][%d].\n",i,j,k); - bSuccess = FALSE; - } - } - } - - } - nCounter++; - /* delete file file but don't worry if it fails */ - DeleteFileA(lpDestination[1]); - } - } - } - - int exitCode = bSuccess ? PASS : FAIL; - PAL_TerminateEx(exitCode); - return exitCode; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt b/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt deleted file mode 100644 index 535a89fe507469..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt +++ /dev/null @@ -1 +0,0 @@ -10110000 \ No newline at end of file diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp deleted file mode 100644 index 96877d95fcb69b..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test2.c -** -** Purpose: Tests the PAL implementation of the CopyFileW function -** Attempt to copy a file to itself -** -** -**===================================================================*/ - -#include - -PALTEST(file_io_CopyFileW_test2_paltest_copyfilew_test2, "file_io/CopyFileW/test2/paltest_copyfilew_test2") -{ - LPSTR szSrcExisting = "src_existing.tmp"; - WCHAR* wcSource; - BOOL bRc = TRUE; - FILE* tempFile = NULL; - DWORD temp; - int retCode; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* create the src_existing file */ - tempFile = fopen(szSrcExisting, "w"); - if (tempFile != NULL) - { - retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile); - if(retCode < 0) - { - Fail("CopyFileW: ERROR-> Couldn't write to %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - retCode = fclose(tempFile); - if(retCode != 0) - { - Fail("CopyFileW: ERROR-> Couldn't close file: %s with error " - "%u.\n", szSrcExisting, GetLastError()); - } - } - else - { - Fail("CopyFileW: ERROR-> Couldn't create %s.\n", szSrcExisting); - } - - /* convert source string to wide character */ - wcSource = convert(szSrcExisting); - - /* Get file attributes of source */ - temp = GetFileAttributes(szSrcExisting); - if (temp == -1) - { - free(wcSource); - Fail("CopyFileW: GetFileAttributes of source file " - "failed with error code %ld. \n", - GetLastError()); - } - - /* make sure a file can't copy to itself - first testing with IfFileExists flag set to true */ - bRc = CopyFileW(wcSource,wcSource,TRUE); - if(bRc) - { - free(wcSource); - Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); - } - - /* try to get file attributes of destination */ - if (GetFileAttributesA(szSrcExisting) == -1) - { - free(wcSource); - Fail("CopyFileW: GetFileAttributes of destination file " - "failed with error code %ld. \n", - GetLastError()); - } - else - { - /* verify attributes of destination file to source file*/ - if(temp != GetFileAttributes(szSrcExisting)) - { - free(wcSource); - Fail("CopyFileW : The file attributes of the " - "destination file do not match the file " - "attributes of the source file.\n"); - } - } - - /* testing with IfFileExists flags set to false - should fail in Windows and pass in UNIX */ - bRc = CopyFileW(wcSource,wcSource,FALSE); - free(wcSource); - if(bRc && (GetLastError() != ERROR_ALREADY_EXISTS)) - { - Fail("ERROR: Cannot copy a file to itself, %u",GetLastError()); - } - - if (GetFileAttributesA(szSrcExisting) == -1) - { - Fail("CopyFileW: GetFileAttributes of destination file " - "failed with error code %ld. \n", - GetLastError()); - } - else - { - /* verify attributes of destination file to source file*/ - - if(temp != GetFileAttributes(szSrcExisting)) - { - Fail("CopyFileW : The file attributes of the " - "destination file do not match the file " - "attributes of the source file.\n"); - } - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp b/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp deleted file mode 100644 index 733e7a95ae2b42..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test4.c -** -** Purpose: Tests the PAL implementation of the CopyFileW function -** to see if a file can through different users belonging to -** different groups. -** - -=====================================================================*/ - -/* USECASE - Copy a file from a different user, belonging to a different group to - the current user, who is a member of the current group. Then check - to see that the current user has the basic access rights to the copied - file. - - Thie original file used is the passwd file in the etc directory of a - BSD machine. This file should exist on all machines. -*/ - -#include - -PALTEST(file_io_CopyFileW_test3_paltest_copyfilew_test3, "file_io/CopyFileW/test3/paltest_copyfilew_test3") -{ - -#if WIN32 - return PASS; - -#else - - BOOL bRc = TRUE; - WCHAR szSrcExisting[] = {'/','e','t','c','/','p','a','s','s','w','d','\0'}; - WCHAR szDest[] = {'t','e','m','p','.','t','m','p','\0'}; - WCHAR szStringTest[] = {'M','a','r','r','y',' ','h','a','d',' ','a',' ', - 'l','i','t','t','l','e',' ','l','a','m','b','\0'}; - WCHAR szStringRead[30]; /* large enough for string szStringTest */ - - HANDLE hFile = NULL; - DWORD dwBytesWritten=0; - DWORD dwBytesRead=0; - int size=0; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* copy the file */ - bRc = CopyFileW(szSrcExisting,szDest,TRUE); - if(!bRc) - { - Fail("CopyFileW: Cannot copy a file with error, %u",GetLastError()); - } - - /* try to get file attributes of destination file */ - if (GetFileAttributesW(szDest) == -1) - { - Fail("CopyFileW: GetFileAttributes of destination file " - "failed with error code %u. \n", - GetLastError()); - } - - /* set the attributes of the destination file to normal again */ - bRc = SetFileAttributesW(szDest, FILE_ATTRIBUTE_NORMAL); - if(!bRc) - { - Fail("CopyFileW: ERROR-> Couldn't set file attributes for " - "file %S with error %u\n", szDest, GetLastError()); - } - - /* open the file for write purposes */ - hFile = CreateFileW((WCHAR *)szDest, - GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if(hFile == INVALID_HANDLE_VALUE) - { - Fail("CopyFileW: ERROR -> Unable to create file \"%S\".\n", - szDest); - } - - /* To account for the size of a WCHAR is twice that of a char */ - size = wcslen(szStringTest); - size = size*sizeof(WCHAR); - - /* Attempt to write to the file */ - bRc = WriteFile(hFile, - szStringTest, - size, - &dwBytesWritten, - NULL); - - if (!bRc) - { - Trace("CopyFileW: ERROR -> Unable to write to copied file with error " - "%u.\n", GetLastError()); - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with " - "error %u.\n",szDest, GetLastError()); - } - Fail(""); - - } - - /* Close the file handle */ - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with error %u " - ".\n",szDest,GetLastError()); - } - - - /* open the file for read purposes */ - hFile = CreateFileW((WCHAR *)szDest, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if(hFile == INVALID_HANDLE_VALUE) - { - Fail("CopyFileW: ERROR -> Unable to create file \"%S\".\n", - szDest); - } - - /* Attempt to read from the file */ - bRc = ReadFile(hFile, - szStringRead, - size, - &dwBytesRead, - NULL); - - if (!bRc) - { - Trace("CopyFileW: ERROR -> Unable to read from copied file with " - "error %u.\n",GetLastError()); - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with " - "error %u.\n",szDest, GetLastError()); - } - Fail(""); - - } - - if(wcsncmp(szStringTest,szStringRead, wcslen(szStringTest)) != 0) - { - Trace("CopyFileW: ERROR -> The string which was written '%S' does not " - "match the string '%S' which was read from the copied file.\n", - szStringTest,szStringRead); - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with " - "error %u.\n",szDest, GetLastError()); - } - Fail(""); - } - - /* Close the file handle */ - bRc = CloseHandle(hFile); - if (!bRc) - { - Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with error %u " - ".\n",szDest,GetLastError()); - } - - /* Remove the temporary file */ - bRc = DeleteFileW(szDest); - if(!bRc) - { - Fail("CopyFileW: Could not remove copied file with error %u.\n", - GetLastError()); - } - - PAL_Terminate(); - return PASS; - -#endif - -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp deleted file mode 100644 index 96d45cd90ccfab..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: GetTempFileNameA.c (test 1) -** -** Purpose: Tests the PAL implementation of the GetTempFileNameA function. -** -** Depends on: -** GetFileAttributesA -** DeleteFileA -** -** -**===================================================================*/ - -#include - - - -PALTEST(file_io_GetTempFileNameA_test1_paltest_gettempfilenamea_test1, "file_io/GetTempFileNameA/test1/paltest_gettempfilenamea_test1") -{ - UINT uiError = 0; - const UINT uUnique = 0; - const char* szDot = {"."}; - const char* szValidPrefix = {"cfr"}; - const char* szLongValidPrefix = {"cfrwxyz"}; - char szReturnedName[256]; - char szTempString[256]; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - /* valid path with null prefix */ - uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " - "with the error code: %ld\n", GetLastError()); - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" - "the created temp file with error code: %ld.\n", GetLastError()); - } - } - - - /* valid path with valid prefix */ - uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " - "prefix with the error code: %ld\n", GetLastError()); - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" - "the created temp \"%s\" file with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - } - - /* valid path with long prefix */ - uiError = GetTempFileNameA(szDot, szLongValidPrefix, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " - "prefix with the error code: %ld\n", GetLastError()); - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - - /* now verify that it only used the first 3 characters of the prefix */ - sprintf_s(szTempString, ARRAY_SIZE(szTempString), "%s\\%s", szDot, szLongValidPrefix); - if (strncmp(szTempString, szReturnedName, 6) == 0) - { - Fail("GetTempFileNameA: ERROR -> It appears that an improper prefix " - "was used.\n"); - } - - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" - "the created temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp deleted file mode 100644 index 9edaf483985a50..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: GetTempFileNameA.c (test 2) -** -** Purpose: Tests the number of files GetTempFileNameA can create. -** -** Depends on: -** GetFileAttributesA -** oodles of free disk space (>4.07GB) -** -** -**===================================================================*/ - -#include - - - -PALTEST(file_io_GetTempFileNameA_test2_paltest_gettempfilenamea_test2, "file_io/GetTempFileNameA/test2/paltest_gettempfilenamea_test2") -{ - UINT uiError = 0; - DWORD dwError = 0; - const UINT uUnique = 0; - const char* szDot = {"."}; - const char* szValidPrefix = {"cfr"}; - char szReturnedName[256]; - DWORD i; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - /* test the number of temp files that can be created */ - for (i = 0; i < 0x10005; i++) - { - uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName); - if (uiError == 0) - { - dwError = GetLastError(); - if (dwError == ERROR_FILE_EXISTS) - { - /* file already existes so break out of the loop */ - i--; /* decrement the count because it wasn't successful */ - break; - } - else - { - /* it was something other than the file already existing? */ - Fail("GetTempFileNameA: ERROR -> Call failed with a valid " - "path and prefix with the error code: %ld\n", GetLastError()); - } - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed " - "on the returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - } - } - - /* did it create more than 0xffff files */ - if (i > 0xffff) - { - Fail("GetTempFileNameA: ERROR -> Was able to create more than 0xffff" - " temp files.\n"); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp deleted file mode 100644 index fa9112c49f1ca8..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: GetTempFileNameA.c (test 3) -** -** Purpose: Tests the PAL implementation of the GetTempFileNameA function. -** Checks the file attributes and ensures that getting a file name, -** deleting the file and getting another doesn't produce the same -** as the just deleted file. Also checks the file size is 0. -** -** Depends on: -** GetFileAttributesA -** CloseHandle -** DeleteFileA -** CreateFileA -** GetFileSize -** -** -**===================================================================*/ - -#include - - - -PALTEST(file_io_GetTempFileNameA_test3_paltest_gettempfilenamea_test3, "file_io/GetTempFileNameA/test3/paltest_gettempfilenamea_test3") -{ - const UINT uUnique = 0; - UINT uiError; - const char* szDot = {"."}; - char szReturnedName[MAX_LONGPATH]; - char szReturnedName_02[MAX_LONGPATH]; - DWORD dwFileSize = 0; - HANDLE hFile; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - /* valid path with null prefix */ - uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " - "with the error code: %u.\n", - GetLastError()); - } - - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %u.\n", - szReturnedName, - GetLastError()); - } - - /* - ** verify that the file size is 0 bytes - */ - - hFile = CreateFileA(szReturnedName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - Trace("GetTempFileNameA: ERROR -> CreateFileA failed to open" - " the created temp file with error code: %u.\n", - GetLastError()); - if (!DeleteFileA(szReturnedName)) - { - Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - Fail(""); - } - - if ((dwFileSize = GetFileSize(hFile, NULL)) != (DWORD)0) - { - Trace("GetTempFileNameA: ERROR -> GetFileSize returned %u whereas" - "it should have returned 0.\n", - dwFileSize); - if (!CloseHandle(hFile)) - { - Trace("GetTempFileNameA: ERROR -> CloseHandle failed. " - "GetLastError returned: %u.\n", - GetLastError()); - } - if (!DeleteFileA(szReturnedName)) - { - Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - Fail(""); - } - - - if (!CloseHandle(hFile)) - { - Fail("GetTempFileNameA: ERROR -> CloseHandle failed. " - "GetLastError returned: %u.\n", - GetLastError()); - } - - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - - /* get another and make sure it's not the same as the last */ - uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName_02); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " - "with the error code: %u.\n", - GetLastError()); - } - - /* did we get different names? */ - if (strcmp(szReturnedName, szReturnedName_02) == 0) - { - Trace("GetTempFileNameA: ERROR -> The first call returned \"%s\". " - "The second call returned \"%s\" and the two should not be" - " the same.\n", - szReturnedName, - szReturnedName_02); - if (!DeleteFileA(szReturnedName_02)) - { - Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - Fail(""); - } - - /* clean up */ - if (!DeleteFileA(szReturnedName_02)) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileA failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp deleted file mode 100644 index 02a01a4fe7534c..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: GetTempFileNameW.c (test 1) -** -** Purpose: Tests the PAL implementation of the GetTempFileNameW function. -** -** -**===================================================================*/ - -#include - - - -PALTEST(file_io_GetTempFileNameW_test1_paltest_gettempfilenamew_test1, "file_io/GetTempFileNameW/test1/paltest_gettempfilenamew_test1") -{ - UINT uiError = 0; - const UINT uUnique = 0; - WCHAR* wPrefix = NULL; - WCHAR* wPath = NULL; - WCHAR wReturnedName[256]; - WCHAR wTempString[256]; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - - // valid path with null ext - wPath = convert("."); - uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); - free (wPath); - if (uiError == 0) - { - Fail("GetTempFileNameW: ERROR -> Call failed with a valid path " - "with the error code: %ld\n", GetLastError()); - } - else - { - // verify temp file was created - if (GetFileAttributesW(wReturnedName) == -1) - { - Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " - "returned temp file with error code: %ld.\n", GetLastError()); - } - if (DeleteFileW(wReturnedName) != TRUE) - { - Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - "the created temp file with error code: %lld.\n", GetLastError()); - } - } - - - // valid path with valid prefix - wPath = convert("."); - wPrefix = convert("cfr"); - uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); - free (wPath); - free (wPrefix); - if (uiError == 0) - { - Fail("GetTempFileNameW: ERROR -> Call failed with a valid path and " - "prefix with the error code: %ld\n", GetLastError()); - } - else - { - // verify temp file was created - if (GetFileAttributesW(wReturnedName) == -1) - { - Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " - "returned temp file with error code: %ld.\n", GetLastError()); - } - if (DeleteFileW(wReturnedName) != TRUE) - { - Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - "the created temp file with error code: %lld.\n", GetLastError()); - } - } - - // valid path with long prefix - wPath = convert("."); - wPrefix = convert("cfrwxyz"); - uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); - if (uiError == 0) - { - free (wPath); - free (wPrefix); - Fail("GetTempFileNameW: ERROR -> Call failed with a valid path and " - "prefix with the error code: %ld\n", GetLastError()); - } - else - { - // verify temp file was created - if (GetFileAttributesW(wReturnedName) == -1) - { - free (wPath); - free (wPrefix); - Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " - "returned temp file with error code: %ld.\n", GetLastError()); - } - - // now verify that it only used the first 3 characters of the prefix - WCHAR* wCurr = wTempString; - memcpy(wCurr, wPath, wcslen(wPath) * sizeof(WCHAR)); - wCurr += wcslen(wPath); - wcscat(wCurr, W("/")); - wCurr += wcslen(W("/")); - wcscat(wCurr, wPrefix); - if (memcmp(wTempString, wReturnedName, wcslen(wTempString)*sizeof(WCHAR)) == 0) - { - free (wPath); - free (wPrefix); - Fail("GetTempFileNameW: ERROR -> It appears that an improper prefix " - "was used.\n"); - } - - if (DeleteFileW(wReturnedName) != TRUE) - { - free (wPath); - free (wPrefix); - Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - "the created temp file with error code: %lld.\n", GetLastError()); - } - } - - free (wPath); - free (wPrefix); - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp deleted file mode 100644 index d79e4cad67fbc8..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: GetTempFileNameW.c (test 2) -** -** Purpose: Tests the PAL implementation of the GetTempFileNameW function. -** -** -**===================================================================*/ - -#include - - - -PALTEST(file_io_GetTempFileNameW_test2_paltest_gettempfilenamew_test2, "file_io/GetTempFileNameW/test2/paltest_gettempfilenamew_test2") -{ - UINT uiError = 0; - DWORD dwError = 0; - const UINT uUnique = 0; - WCHAR* wPrefix = NULL; - WCHAR* wPath = NULL; - WCHAR wReturnedName[256]; - DWORD i; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - - // test the number of temp files that can be created - wPrefix = convert("cfr"); - wPath = convert("."); - for (i = 0; i < 0x10005; i++) - { - uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName); - if (uiError == 0) - { - dwError = GetLastError(); - if (dwError == ERROR_FILE_EXISTS) - { - // file already existes so break out of the loop - i--; // decrement the count because it wasn't successful - break; - } - else - { - // it was something other than the file already existing? - free (wPath); - free (wPrefix); - Fail("GetTempFileNameW: ERROR -> Call failed with a valid " - "path and prefix with the error code: %ld\n", GetLastError()); - } - } - else - { - // verify temp file was created - if (GetFileAttributesW(wReturnedName) == -1) - { - free (wPath); - free (wPrefix); - Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed " - "on the returned temp file with error code: %ld.\n", - GetLastError()); - } - } - } - - free (wPath); - free (wPrefix); - - // did it create more than 0xffff files - if (i > 0xffff) - { - Fail("GetTempFileNameW: ERROR -> Was able to create more than 0xffff" - " temp files.\n"); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp deleted file mode 100644 index 312138b08e4983..00000000000000 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: GetTempFileNameW.c (test 3) -** -** Purpose: Tests the PAL implementation of the GetTempFileNameW function. -** Checks the file attributes and ensures that getting a file name, -** deleting the file and getting another doesn't produce the same -** as the just deleted file. Also checks the file size is 0. -** -** Depends on: -** GetFileAttributesW -** DeleteFileW -** CreateFileW -** GetFileSize -** CloseHandle -** -** -**===================================================================*/ - -#include - - - -PALTEST(file_io_GetTempFileNameW_test3_paltest_gettempfilenamew_test3, "file_io/GetTempFileNameW/test3/paltest_gettempfilenamew_test3") -{ - const UINT uUnique = 0; - UINT uiError; - WCHAR szwReturnedName[MAX_LONGPATH]; - WCHAR szwReturnedName_02[MAX_LONGPATH]; - DWORD dwFileSize = 0; - HANDLE hFile; - const WCHAR szwDot[] = {'.','\0'}; - const WCHAR szwPre[] = {'c','\0'}; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - /* valid path with null prefix */ - uiError = GetTempFileNameW(szwDot, szwPre, uUnique, szwReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameW: ERROR -> Call failed with a valid path " - "with the error code: %u.\n", - GetLastError()); - } - - /* verify temp file was created */ - if (GetFileAttributesW(szwReturnedName) == -1) - { - Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%S\" with error code: %u.\n", - szwReturnedName, - GetLastError()); - } - - /* - ** verify that the file size is 0 bytes - */ - - hFile = CreateFileW(szwReturnedName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - Trace("GetTempFileNameW: ERROR -> CreateFileW failed to open" - " the created temp file with error code: %u.\n", - GetLastError()); - if (!DeleteFileW(szwReturnedName)) - { - Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - Fail(""); - } - - if ((dwFileSize = GetFileSize(hFile, NULL)) != (DWORD)0) - { - Trace("GetTempFileNameW: ERROR -> GetFileSize returned %u whereas" - "it should have returned 0.\n", - dwFileSize); - if (!CloseHandle(hFile)) - { - Trace("GetTempFileNameW: ERROR -> CloseHandle was unable to close the " - "opened file. GetLastError returned %u.\n", - GetLastError()); - } - if (!DeleteFileW(szwReturnedName)) - { - Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - Fail(""); - } - - if (!CloseHandle(hFile)) - { - Fail("GetTempFileNameW: ERROR -> CloseHandle was unable to close the " - "opened file. GetLastError returned %u.\n", - GetLastError()); - } - - - /* delete the file to see if we get the same name next time around */ - if (DeleteFileW(szwReturnedName) != TRUE) - { - Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - - /* get another and make sure it's not the same as the last */ - uiError = GetTempFileNameW(szwDot, szwPre, uUnique, szwReturnedName_02); - if (uiError == 0) - { - Fail("GetTempFileNameW: ERROR -> Call failed with a valid path " - "with the error code: %u.\n", - GetLastError()); - } - - /* did we get different names? */ - if (wcsncmp(szwReturnedName, szwReturnedName_02, wcslen(szwReturnedName)) == 0) - { - Fail("GetTempFileNameW: ERROR -> The first call returned \"%S\". " - "The second call returned \"%S\" and the two should not be" - " the same.\n", - szwReturnedName, - szwReturnedName_02); - if (!DeleteFileW(szwReturnedName_02)) - { - Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - Fail(""); - } - - /* clean up */ - if (!DeleteFileW(szwReturnedName_02)) - { - Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete" - " the created temp file with error code: %u.\n", - GetLastError()); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp index 1b805708ee75c4..d3551a773a5ae8 100644 --- a/src/coreclr/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp +++ b/src/coreclr/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp @@ -17,7 +17,7 @@ ** Functions covered by this test are: -** CopyFileA, CopyFileW, CreateFileA,CreateFileW, +** CreateFileA,CreateFileW, ** DeleteFileA and DeleteFileW. @@ -84,162 +84,6 @@ PALTEST(file_io_errorpathnotfound_test1_paltest_errorpathnotfound_test1, "file_i - /*...................Test CopyFileW.............................*/ - - - - /* test with an invalid path */ - - bRc = CopyFileW(wBadFilePath,wDest,TRUE); - - if(!bRc) - - { - - if(GetLastError()!= ERROR_PATH_NOT_FOUND) - - { - - Trace("CopyFileW: calling GetLastError() after copying a file" - - " with wrong path returned [%u] while it should return [%u]\n" - - ,GetLastError(), ERROR_PATH_NOT_FOUND); - - testPass = FALSE; - - } - - } - - else - - { - - testPass = FALSE; - - } - - - - /* test with invalid file name */ - - bRc = CopyFileW(wBadFileName,wDest,TRUE); - - if(!bRc) - - { - - if(GetLastError()!= ERROR_FILE_NOT_FOUND) - - { - - Trace("CopyFileW: calling GetLastError() after copying a file" - - " with wrong name returned [%u] while it should return [%u]\n" - - ,GetLastError(), ERROR_FILE_NOT_FOUND); - - testPass = FALSE; - - } - - - - } - - else - - { - - Trace("CopyFileW: managed to copy a file with wrong name\n"); - - testPass = FALSE; - - } - - - - - - - - /*..................CopyFileA...................................*/ - - - - /* test with an invalid path */ - - bRc = CopyFileA(sBadFilePath,sDest,TRUE); - - if(! bRc) - - { - - if(GetLastError()!= ERROR_PATH_NOT_FOUND) - - { - - Trace("CopyFileA: calling GetLastError() after copying a file" - - " with wrong path returned [%u] while it should return [%u]\n" - - ,GetLastError(), ERROR_PATH_NOT_FOUND); - - testPass = FALSE; - - } - - } - - else - - { - - Trace("CopyFileA: managed to copy a file with wrong path\n"); - - testPass = FALSE; - - } - - - - /* test with an invalid file name */ - - bRc = CopyFileA(sBadFileName,sDest,TRUE); - - if(! bRc) - - { - - if(GetLastError()!= ERROR_FILE_NOT_FOUND) - - { - - Trace("CopyFileA: calling GetLastError() after copying a file" - - " with wrong name returned [%u] while it should return [%u]\n" - - ,GetLastError(), ERROR_FILE_NOT_FOUND); - - testPass = FALSE; - - } - - } - - else - - { - - Trace("CopyFileA: managed to copy a file with wrong name\n"); - - testPass = FALSE; - - } - - - diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp index e718387a84a6bb..f6b5989ee6d27d 100644 --- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp +++ b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp @@ -35,7 +35,7 @@ PALTEST(filemapping_memmgt_MapViewOfFile_test1_paltest_mapviewoffile_test1, "fil HANDLE hFile = INVALID_HANDLE_VALUE; LPSTR buf = NULL; CHAR ch[MAPPINGSIZE]; - CHAR lpFilePath[MAX_PATH]; + CHAR* lpFilePath = TEMP_DIRECTORY_PATH"tst"; DWORD dwBytesWritten = 0; DWORD dwInitialSize = 0; DWORD dwFinalSize = 0; @@ -51,8 +51,6 @@ PALTEST(filemapping_memmgt_MapViewOfFile_test1_paltest_mapviewoffile_test1, "fil return FAIL; } - GetTempFileName(TEMP_DIRECTORY_PATH, "tst", 0, lpFilePath); - /* Create a file handle with CreateFile. */ hFile = CreateFile( lpFilePath, diff --git a/src/coreclr/pal/tests/palsuite/manual-inspect.dat b/src/coreclr/pal/tests/palsuite/manual-inspect.dat index 22f9ebc1f8ff45..fc01f1d05ec3d8 100644 --- a/src/coreclr/pal/tests/palsuite/manual-inspect.dat +++ b/src/coreclr/pal/tests/palsuite/manual-inspect.dat @@ -1,11 +1,6 @@ # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. -# Automatable to detect gross errors; also manually inspect for proper behaviour -miscellaneous/messageboxw/test1,1 -# Automatable to detect gross errors; also manually inspect for proper behaviour -# Env var PAL_DISABLE_MESSAGEBOX=1 disables msg boxes for automation on Windows -miscellaneous/messageboxw/test2,1 # Automatable to detect gross errors; also manually inspect for proper behaviour pal_specific/pal_get_stderr/test1,1 pal_specific/pal_get_stdout/test1,1 diff --git a/src/coreclr/pal/tests/palsuite/manual-unautomatable.dat b/src/coreclr/pal/tests/palsuite/manual-unautomatable.dat index 78e1831fbc6a42..24575263b2e9e5 100644 --- a/src/coreclr/pal/tests/palsuite/manual-unautomatable.dat +++ b/src/coreclr/pal/tests/palsuite/manual-unautomatable.dat @@ -13,9 +13,6 @@ debug_api/outputdebugstringa/test1,1 pal_specific/pal_get_stdin/test1,1 threading/setconsolectrlhandler/test1,1 threading/setconsolectrlhandler/test4,1 -# These tests take several minutes to run and time out when run with the harness -file_io/gettempfilenamea/test2,1 -file_io/gettempfilenamew/test2,1 # getstdhandle fails under Windows if the output is redirected so # it must be run from the command line file_io/getstdhandle/test1,1 diff --git a/src/coreclr/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp b/src/coreclr/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp deleted file mode 100644 index b09d3f6263197f..00000000000000 --- a/src/coreclr/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================= -** -** Source: pal_getusertempdirectoryw.c -** -** Purpose: Positive test the PAL_GetUserTempDirectoryW API. -** Call PAL_GetUserTempDirectoryW to retrieve the user -** temp directory. -** -** -**============================================================*/ -#define UNICODE -#include - -#define DIRECTORYLENGTH 1024 - -PALTEST(pal_specific_PAL_GetUserTempDirectoryW_test1_paltest_pal_getusertempdirectoryw_test1, "pal_specific/PAL_GetUserTempDirectoryW/test1/paltest_pal_getusertempdirectoryw_test1") -{ - int err; - DWORD dwFileAttribute; - DWORD cch = DIRECTORYLENGTH; - WCHAR wDirectoryName[DIRECTORYLENGTH]; - - //Initialize the PAL environment - err = PAL_Initialize(argc, argv); - if(0 != err) - { - ExitProcess(FAIL); - } - - //retrieve the user temp directory - err = PAL_GetUserTempDirectory(ddtInstallationDependentDirectory, wDirectoryName, &cch); - - if(0 == err || 0 == strlen(convertC(wDirectoryName))) - { - Fail("Failed to call PAL_GetUserTempDirectoryW API!\n"); - } - - - //retrieve the attributes of a file or directory - dwFileAttribute = GetFileAttributesW(wDirectoryName); - - - //check if the retrieved attribute indicates a directory - if( FILE_ATTRIBUTE_DIRECTORY != (FILE_ATTRIBUTE_DIRECTORY & dwFileAttribute)) - { - Fail("PAL_GetUserTempDirectoryW API returned a non-directory name!\n"); - } - - printf ("PAL_GetUserTempDirectoryW returns %S\n", wDirectoryName); - - PAL_Terminate(); - return PASS; - -} diff --git a/src/coreclr/pal/tests/palsuite/paltestlist.txt b/src/coreclr/pal/tests/palsuite/paltestlist.txt index d8fd3a875739c0..c5d87fb07b4eec 100644 --- a/src/coreclr/pal/tests/palsuite/paltestlist.txt +++ b/src/coreclr/pal/tests/palsuite/paltestlist.txt @@ -152,12 +152,6 @@ filemapping_memmgt/VirtualProtect/test4/paltest_virtualprotect_test4 filemapping_memmgt/VirtualProtect/test6/paltest_virtualprotect_test6 filemapping_memmgt/VirtualProtect/test7/paltest_virtualprotect_test7 filemapping_memmgt/VirtualQuery/test1/paltest_virtualquery_test1 -file_io/CopyFileA/test1/paltest_copyfilea_test1 -file_io/CopyFileA/test2/paltest_copyfilea_test2 -file_io/CopyFileA/test3/paltest_copyfilea_test3 -file_io/CopyFileA/test4/paltest_copyfilea_test4 -file_io/CopyFileW/test2/paltest_copyfilew_test2 -file_io/CopyFileW/test3/paltest_copyfilew_test3 file_io/errorpathnotfound/test2/paltest_errorpathnotfound_test2 file_io/FILECanonicalizePath/paltest_filecanonicalizepath_test1 file_io/FlushFileBuffers/test1/paltest_flushfilebuffers_test1 @@ -176,10 +170,6 @@ file_io/GetFullPathNameW/test4/paltest_getfullpathnamew_test4 file_io/GetStdHandle/test2/paltest_getstdhandle_test2 file_io/GetSystemTime/test1/paltest_getsystemtime_test1 file_io/GetSystemTimeAsFileTime/test1/paltest_getsystemtimeasfiletime_test1 -file_io/GetTempFileNameA/test1/paltest_gettempfilenamea_test1 -file_io/GetTempFileNameA/test2/paltest_gettempfilenamea_test2 -file_io/GetTempFileNameA/test3/paltest_gettempfilenamea_test3 -file_io/GetTempFileNameW/test3/paltest_gettempfilenamew_test3 file_io/gettemppatha/test1/paltest_gettemppatha_test1 file_io/GetTempPathW/test1/paltest_gettemppathw_test1 file_io/ReadFile/test2/paltest_readfile_test2 diff --git a/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt b/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt index 964540f7dc90db..0ee8cb4df9a337 100644 --- a/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt +++ b/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt @@ -51,7 +51,6 @@ filemapping_memmgt/GetProcAddress/test2/paltest_getprocaddress_test2 filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/paltest_readprocessmemory_readprocessmemory_neg1 filemapping_memmgt/ReadProcessMemory/test1/paltest_readprocessmemory_test1 filemapping_memmgt/ReadProcessMemory/test2/paltest_readprocessmemory_test2 -file_io/CopyFileW/test1/paltest_copyfilew_test1 file_io/CreateFileA/test1/paltest_createfilea_test1 file_io/CreateFileW/test1/paltest_createfilew_test1 file_io/errorpathnotfound/test1/paltest_errorpathnotfound_test1 @@ -59,8 +58,6 @@ file_io/GetFileAttributesExW/test1/paltest_getfileattributesexw_test1 file_io/GetFullPathNameA/test2/paltest_getfullpathnamea_test2 file_io/GetFullPathNameW/test2/paltest_getfullpathnamew_test2 file_io/GetStdHandle/test1/paltest_getstdhandle_test1 -file_io/GetTempFileNameW/test1/paltest_gettempfilenamew_test1 -file_io/GetTempFileNameW/test2/paltest_gettempfilenamew_test2 file_io/gettemppatha/test1/paltest_gettemppatha_test1 file_io/GetTempPathW/test1/paltest_gettemppathw_test1 file_io/ReadFile/test1/paltest_readfile_test1 @@ -88,7 +85,6 @@ miscellaneous/IsBadWritePtr/test2/paltest_isbadwriteptr_test2 miscellaneous/IsBadWritePtr/test3/paltest_isbadwriteptr_test3 miscellaneous/wsprintfW/test2/paltest_wsprintfw_test2 miscellaneous/wsprintfW/test7/paltest_wsprintfw_test7 -pal_specific/PAL_GetUserTempDirectoryW/test1/paltest_pal_getusertempdirectoryw_test1 pal_specific/PAL_get_stderr/test1/paltest_pal_get_stderr_test1 pal_specific/PAL_get_stdin/test1/paltest_pal_get_stdin_test1 pal_specific/PAL_get_stdout/test1/paltest_pal_get_stdout_test1 diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp index 6c62b7edf7354c..bfc1018f8db5fa 100644 --- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp @@ -7,20 +7,19 @@ #include -const char *const SessionPrefix = "Local\\"; -const char *const GlobalPrefix = "Global\\"; - -const char *const NamePrefix = "paltest_namedmutex_test1_"; -const char *const TempNamePrefix = "paltest_namedmutex_test1_temp_"; -const char *const InvalidNamePrefix0 = "paltest\\namedmutex_"; -const char *const InvalidNamePrefix1 = "paltest/namedmutex_"; -const char *const ParentEventNamePrefix0 = "paltest_namedmutex_test1_pe0_"; -const char *const ParentEventNamePrefix1 = "paltest_namedmutex_test1_pe1_"; -const char *const ChildEventNamePrefix0 = "paltest_namedmutex_test1_ce0_"; -const char *const ChildEventNamePrefix1 = "paltest_namedmutex_test1_ce1_"; -const char *const ChildRunningEventNamePrefix = "paltest_namedmutex_test1_cr_"; - -const char *const GlobalShmFilePathPrefix = "/tmp/.dotnet/shm/global/"; +const char CurrentSessionOnlyPrefix[] = "Local\\"; +const char AllSessionsPrefix[] = "Global\\"; + +const char NamePrefix[] = "paltest_namedmutex_test1_"; +const char TempNamePrefix[] = "paltest_namedmutex_test1_temp_"; +const char HeaderMismatchTestsNamePrefix[] = "paltest_namedmutex_test1_headermismatchtests_"; +const char InvalidNamePrefix0[] = "paltest\\namedmutex_"; +const char InvalidNamePrefix1[] = "paltest/namedmutex_"; +const char ParentEventNamePrefix0[] = "paltest_namedmutex_test1_pe0_"; +const char ParentEventNamePrefix1[] = "paltest_namedmutex_test1_pe1_"; +const char ChildEventNamePrefix0[] = "paltest_namedmutex_test1_ce0_"; +const char ChildEventNamePrefix1[] = "paltest_namedmutex_test1_ce1_"; +const char ChildRunningEventNamePrefix[] = "paltest_namedmutex_test1_cr_"; #define MaxPathSize 200 const DWORD PollLoopSleepMilliseconds = 100; @@ -28,6 +27,8 @@ const DWORD FailTimeoutMilliseconds = 30000; DWORD g_expectedTimeoutMilliseconds = 500; bool g_isParent = true; +bool g_currentUserOnly = true; +bool g_currentSessionOnly = true; bool g_isStress = false; #define MaxProcessPathSize 4096 char g_processPath[MaxProcessPathSize], g_processCommandLinePath[MaxProcessPathSize]; @@ -41,13 +42,15 @@ extern int (*test_sscanf)(const char *str, const char *format, ...); extern int(*test_close)(int fd); extern int (*test_unlink)(const char *pathname); extern unsigned int test_getpid(); +extern unsigned int test_getsid(); +extern unsigned int test_geteuid(); extern int test_kill(unsigned int pid); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Test helpers extern bool TestFileExists(const char *path); -extern bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int *fdRef); +extern bool WriteHeaderInfo(const char *path, bool currentUserOnly, char sharedMemoryType, char version, int *fdRef); #define TestAssert(expression) \ do \ @@ -56,56 +59,76 @@ extern bool WriteHeaderInfo(const char *path, char sharedMemoryType, char versio { \ if (!g_isParent) \ { \ - Trace("'paltest_namedmutex_test1' child process failed at line %u. Expression: " #expression "\n", __LINE__); \ + Trace( \ + "'paltest_namedmutex_test1' child process failed at line %u. CurrentUserOnly: %d, CurrentSessionOnly: %d. Expression: " #expression "\n", \ + __LINE__, \ + (int)g_currentUserOnly, \ + (int)g_currentSessionOnly); \ } \ else \ { \ - Trace("'paltest_namedmutex_test1' failed at line %u. Expression: " #expression "\n", __LINE__); \ + Trace( \ + "'paltest_namedmutex_test1' failed at line %u. CurrentUserOnly: %d, CurrentSessionOnly: %d. Expression: " #expression "\n", \ + __LINE__, \ + (int)g_currentUserOnly, \ + (int)g_currentSessionOnly); \ } \ fflush(stdout); \ return false; \ } \ } while(false) -char *BuildName(const char *testName, char *buffer, const char *prefix0, const char *prefix1 = nullptr) +char *BuildName(const char *testName, char *buffer, const char *namePrefix = nullptr) { size_t nameLength = 0; - const char *prefixes[] = {prefix0, prefix1}; - for (int i = 0; i < 2; ++i) + if (!g_currentSessionOnly) { - const char *prefix = prefixes[i]; - if (prefix == nullptr) - { - break; - } - test_strcpy(&buffer[nameLength], prefix); - nameLength += test_strlen(prefix); + test_strcpy(&buffer[nameLength], AllSessionsPrefix); + nameLength += STRING_LENGTH(AllSessionsPrefix); + } + + if (namePrefix != nullptr) + { + nameLength += test_snprintf(&buffer[nameLength], MaxPathSize - nameLength, "%s", namePrefix); } if (g_isStress) { // Append the test name so that tests can run in parallel - nameLength += test_snprintf(&buffer[nameLength], MaxPathSize - nameLength, "%s", testName); - buffer[nameLength++] = '_'; + nameLength += test_snprintf(&buffer[nameLength], MaxPathSize - nameLength, "%s_", testName); } nameLength += test_snprintf(&buffer[nameLength], MaxPathSize - nameLength, "%u", g_parentPid); return buffer; } -char *BuildGlobalShmFilePath(const char *testName, char *buffer, const char *namePrefix) +char *BuildShmFilePath(const char *testName, char *buffer, const char *namePrefix) { size_t pathLength = 0; - test_strcpy(&buffer[pathLength], GlobalShmFilePathPrefix); - pathLength += test_strlen(GlobalShmFilePathPrefix); - test_strcpy(&buffer[pathLength], namePrefix); - pathLength += test_strlen(namePrefix); + if (g_currentUserOnly) + { + pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "/tmp/.dotnet-uid%u/shm/", test_geteuid()); + } + else + { + pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "%s", "/tmp/.dotnet/shm/"); + } + + if (g_currentSessionOnly) + { + pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "session%u/", test_getsid()); + } + else + { + pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "%s", "global/"); + } + + pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "%s", namePrefix); if (g_isStress) { // Append the test name so that tests can run in parallel - pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "%s", testName); - buffer[pathLength++] = '_'; + pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "%s_", testName); } pathLength += test_snprintf(&buffer[pathLength], MaxPathSize - pathLength, "%u", g_parentPid); @@ -175,37 +198,33 @@ void TestCreateMutex(AutoCloseMutexHandle &m, const char *name, bool initiallyOw { m.Close(); LPWSTR nameW = convert(name); - m = CreateMutex(nullptr, initiallyOwned, nameW); + m = PAL_CreateMutexW(initiallyOwned, nameW, g_currentUserOnly, nullptr, 0); free(nameW); } HANDLE TestOpenMutex(const char *name) { - return OpenMutexA(SYNCHRONIZE, false, name); + LPWSTR nameW = convert(name); + HANDLE h = PAL_OpenMutexW(nameW, g_currentUserOnly, nullptr, 0); + free(nameW); + return h; } bool StartProcess(const char *funcName) { - // Command line format: [stress] - - size_t processCommandLinePathLength = 0; - g_processCommandLinePath[processCommandLinePathLength++] = '\"'; - test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], g_processPath); - processCommandLinePathLength += test_strlen(g_processPath); - g_processCommandLinePath[processCommandLinePathLength++] = '\"'; - g_processCommandLinePath[processCommandLinePathLength++] = ' '; - const char* testname = "threading/NamedMutex/test1/paltest_namedmutex_test1"; - processCommandLinePathLength += test_snprintf(&g_processCommandLinePath[processCommandLinePathLength], MaxProcessPathSize - processCommandLinePathLength, "%s ", testname); - processCommandLinePathLength += test_snprintf(&g_processCommandLinePath[processCommandLinePathLength], MaxProcessPathSize - processCommandLinePathLength, "%u", g_parentPid); - g_processCommandLinePath[processCommandLinePathLength++] = ' '; - test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], funcName); - processCommandLinePathLength += test_strlen(funcName); - - if (g_isStress) - { - test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], " stress"); - processCommandLinePathLength += STRING_LENGTH("stress"); - } + // Command line format: + // <0|1> /* currentUserOnly */ <0|1> /* currentSessionOnly */ [stress] + test_snprintf( + g_processCommandLinePath, + MaxProcessPathSize, + "\"%s\" %s %u %s %u %u%s", + g_processPath, + "threading/NamedMutex/test1/paltest_namedmutex_test1", + g_parentPid, + funcName, + g_currentUserOnly ? 1 : 0, + g_currentSessionOnly ? 1 : 0, + g_isStress ? " stress" : ""); STARTUPINFO si; memset(&si, 0, sizeof(si)); @@ -247,7 +266,7 @@ bool StartThread(LPTHREAD_START_ROUTINE func, void *arg = nullptr, HANDLE *threa bool WaitForMutexToBeCreated(const char *testName, AutoCloseMutexHandle &m, const char *eventNamePrefix) { char eventName[MaxPathSize]; - BuildName(testName, eventName, GlobalPrefix, eventNamePrefix); + BuildName(testName, eventName, eventNamePrefix); DWORD startTime = GetTickCount(); while (true) { @@ -276,7 +295,7 @@ bool WaitForMutexToBeCreated(const char *testName, AutoCloseMutexHandle &m, cons bool AcquireChildRunningEvent(const char *testName, AutoCloseMutexHandle &childRunningEvent) { char name[MaxPathSize]; - TestCreateMutex(childRunningEvent, BuildName(testName, name, GlobalPrefix, ChildRunningEventNamePrefix)); + TestCreateMutex(childRunningEvent, BuildName(testName, name, ChildRunningEventNamePrefix)); TestAssert(WaitForSingleObject(childRunningEvent, FailTimeoutMilliseconds) == WAIT_OBJECT_0); return true; } @@ -289,7 +308,7 @@ bool InitializeParent(const char *testName, AutoCloseMutexHandle parentEvents[2] { TestCreateMutex( parentEvents[i], - BuildName(testName, name, GlobalPrefix, i == 0 ? ParentEventNamePrefix0 : ParentEventNamePrefix1), + BuildName(testName, name, i == 0 ? ParentEventNamePrefix0 : ParentEventNamePrefix1), true); TestAssert(parentEvents[i] != nullptr); TestAssert(GetLastError() != ERROR_ALREADY_EXISTS); @@ -332,7 +351,7 @@ bool InitializeChild( { TestCreateMutex( childEvents[i], - BuildName(testName, name, GlobalPrefix, i == 0 ? ChildEventNamePrefix0 : ChildEventNamePrefix1), + BuildName(testName, name, i == 0 ? ChildEventNamePrefix0 : ChildEventNamePrefix1), true); TestAssert(childEvents[i] != nullptr); TestAssert(GetLastError() != ERROR_ALREADY_EXISTS); @@ -400,17 +419,24 @@ bool NameTests() TestAssert(m != nullptr); // Normal name - TestCreateMutex(m, BuildName(testName, name, NamePrefix)); + BuildName(testName, name, NamePrefix); + TestCreateMutex(m, name); TestAssert(m != nullptr); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, NamePrefix))) != nullptr); - TestCreateMutex(m, BuildName(testName, name, SessionPrefix, NamePrefix)); - TestAssert(m != nullptr); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, SessionPrefix, NamePrefix))) != nullptr); - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); - TestAssert(m != nullptr); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) != nullptr); + if (g_currentSessionOnly) + { + // When creating or opening a mutex scoped to the current session, the prefix ("Local\") is optional + char nameWithExplicitPrefix[MaxPathSize]; + test_strcpy(nameWithExplicitPrefix, CurrentSessionOnlyPrefix); + BuildName(testName, &nameWithExplicitPrefix[STRING_LENGTH(CurrentSessionOnlyPrefix)], NamePrefix); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(nameWithExplicitPrefix)) != nullptr); + TestCreateMutex(m, nameWithExplicitPrefix); + TestAssert(m != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) != nullptr); + } - // Name too long. The maximum allowed length depends on the file system, so we're not checking for that. + // Name too long. The maximum allowed path length depends on the file system, so we're not checking for that. + if(g_currentSessionOnly) { char name[257]; memset(name, 'a', STRING_LENGTH(name)); @@ -420,36 +446,49 @@ bool NameTests() TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE); TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) == nullptr); TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE); + + name[STRING_LENGTH(name) - 1] = '\0'; + TestCreateMutex(m, name); + TestAssert(m != nullptr); + } + else + { + char name[STRING_LENGTH(AllSessionsPrefix) + 257]; + test_strcpy(name, AllSessionsPrefix); + memset(&name[STRING_LENGTH(AllSessionsPrefix)], 'a', STRING_LENGTH(name) - STRING_LENGTH(AllSessionsPrefix)); + name[STRING_LENGTH(name)] = '\0'; + TestCreateMutex(m, name); + TestAssert(m == nullptr); + TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) == nullptr); + TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE); + + name[STRING_LENGTH(name) - 1] = '\0'; + TestCreateMutex(m, name); + TestAssert(m != nullptr); } // Invalid characters in name - TestCreateMutex(m, BuildName(testName, name, InvalidNamePrefix0)); - TestAssert(m == nullptr); - TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, InvalidNamePrefix0))) == nullptr); - TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestCreateMutex(m, BuildName(testName, name, InvalidNamePrefix1)); - TestAssert(m == nullptr); - TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, InvalidNamePrefix1))) == nullptr); - TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestCreateMutex(m, BuildName(testName, name, SessionPrefix, InvalidNamePrefix0)); + BuildName(testName, name, InvalidNamePrefix0); + TestCreateMutex(m, name); TestAssert(m == nullptr); TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, SessionPrefix, InvalidNamePrefix0))) == nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) == nullptr); TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, InvalidNamePrefix1)); + BuildName(testName, name, InvalidNamePrefix1); + TestCreateMutex(m, name); TestAssert(m == nullptr); TestAssert(GetLastError() == ERROR_INVALID_NAME); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, InvalidNamePrefix1))) == nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) == nullptr); TestAssert(GetLastError() == ERROR_INVALID_NAME); // Creating a second reference to the same named mutex yields an error indicating that it was opened, not created { - TestCreateMutex(m, BuildName(testName, name, NamePrefix)); + BuildName(testName, name, NamePrefix); + TestCreateMutex(m, name); TestAssert(m != nullptr); AutoCloseMutexHandle m2; - TestCreateMutex(m2, BuildName(testName, name, NamePrefix)); + TestCreateMutex(m2, name); TestAssert(m2 != nullptr); TestAssert(GetLastError() == ERROR_ALREADY_EXISTS); } @@ -462,28 +501,32 @@ bool HeaderMismatchTests() const char *testName = "HeaderMismatchTests"; AutoCloseMutexHandle m, m2; - char name[MaxPathSize]; + char name[MaxPathSize], path[MaxPathSize]; int fd; // Create and hold onto a mutex during this test to create the shared memory directory - TestCreateMutex(m2, BuildName(testName, name, GlobalPrefix, TempNamePrefix)); + TestCreateMutex(m2, BuildName(testName, name, TempNamePrefix)); TestAssert(m2 != nullptr); + // Init name and path for the remaining tests + BuildName(testName, name, HeaderMismatchTestsNamePrefix); + BuildShmFilePath(testName, path, HeaderMismatchTestsNamePrefix); + // Unknown shared memory type - TestAssert(WriteHeaderInfo(BuildGlobalShmFilePath(testName, name, NamePrefix), -1, 1, &fd)); - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(WriteHeaderInfo(path, g_currentUserOnly, -1, 1, &fd)); + TestCreateMutex(m, name); TestAssert(m == nullptr); TestAssert(GetLastError() == ERROR_INVALID_HANDLE); TestAssert(test_close(fd) == 0); - TestAssert(test_unlink(BuildGlobalShmFilePath(testName, name, NamePrefix)) == 0); + TestAssert(test_unlink(path) == 0); // Mismatched version - TestAssert(WriteHeaderInfo(BuildGlobalShmFilePath(testName, name, NamePrefix), 0, -1, &fd)); - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(WriteHeaderInfo(path, g_currentUserOnly, 0, -1, &fd)); + TestCreateMutex(m, name); TestAssert(m == nullptr); TestAssert(GetLastError() == ERROR_INVALID_HANDLE); TestAssert(test_close(fd) == 0); - TestAssert(test_unlink(BuildGlobalShmFilePath(testName, name, NamePrefix)) == 0); + TestAssert(test_unlink(path) == 0); return true; } @@ -498,7 +541,7 @@ bool MutualExclusionTests_Parent() char name[MaxPathSize]; AutoCloseMutexHandle m; - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); // Recursive locking with various timeouts @@ -539,7 +582,7 @@ DWORD PALAPI MutualExclusionTests_Child(void *arg = nullptr) char name[MaxPathSize]; AutoCloseMutexHandle m; - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); // lock the mutex YieldToParent(parentEvents, childEvents, ei); // parent attempts to lock/release, and fails @@ -611,23 +654,23 @@ bool LifetimeTests_Parent() char name[MaxPathSize]; AutoCloseMutexHandle m; - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create first reference to mutex + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); // create first reference to mutex TestAssert(m != nullptr); - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child creates second reference to mutex using CreateMutex m.Close(); // close first reference - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference - TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(!TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create first reference to mutex + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); // create first reference to mutex TestAssert(m != nullptr); - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child creates second reference to mutex using OpenMutex m.Close(); // close first reference - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference - TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(!TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(UninitializeParent(testName, parentEvents)); return true; @@ -646,13 +689,13 @@ DWORD PALAPI LifetimeTests_Child(void *arg = nullptr) AutoCloseMutexHandle m; // ... parent creates first reference to mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create second reference to mutex using CreateMutex + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); // create second reference to mutex using CreateMutex TestAssert(m != nullptr); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent closes first reference m.Close(); // close second reference TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies, and creates first reference to mutex again - m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); // create second reference to mutex using OpenMutex + m = TestOpenMutex(BuildName(testName, name, NamePrefix)); // create second reference to mutex using OpenMutex TestAssert(m != nullptr); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent closes first reference m.Close(); // close second reference @@ -673,11 +716,11 @@ bool LifetimeTests() char name[MaxPathSize]; // Shm file should be created and deleted - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); m.Close(); - TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(!TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); } // Shm file should not be deleted until last reference is released @@ -702,7 +745,7 @@ bool AbandonTests_Parent() TestAssert(InitializeParent(testName, parentEvents, childEvents)); int ei = 0; - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex TestAssert(parentEvents[0].Release()); @@ -746,13 +789,13 @@ bool AbandonTests_Parent() while (true) { m.Close(); - if (!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))) + if (!TestFileExists(BuildShmFilePath(testName, name, NamePrefix))) { break; } TestAssert(GetTickCount() - startTime < FailTimeoutMilliseconds); - m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); + m = TestOpenMutex(BuildName(testName, name, NamePrefix)); } return true; @@ -771,7 +814,7 @@ DWORD PALAPI AbandonTests_Child_GracefulExit_Close(void *arg = nullptr) AutoCloseMutexHandle m; // ... parent waits for child to lock mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex @@ -800,7 +843,7 @@ DWORD AbandonTests_Child_GracefulExit_NoClose(void *arg = nullptr) AutoCloseMutexHandle m; // ... parent waits for child to lock mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex @@ -829,7 +872,7 @@ DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr) AutoCloseMutexHandle m; // ... parent waits for child to lock mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex @@ -859,7 +902,7 @@ DWORD AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit(void *arg = nul AutoCloseMutexHandle m; // ... root parent waits for child to lock mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); @@ -893,7 +936,7 @@ DWORD AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit(void *arg = null AutoCloseMutexHandle m; // ... immediate parent expects child to wait on mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex TestAssert(YieldToParent(parentEvents, childEvents, ei)); // root parent waits on mutex @@ -918,7 +961,7 @@ DWORD PALAPI AbandonTests_Child_TryLock(void *arg) AutoCloseMutexHandle m; // ... parent waits for child to lock mutex - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // try to lock the mutex while the parent holds the lock TestAssert(WaitForSingleObject(m, g_expectedTimeoutMilliseconds) == WAIT_TIMEOUT); @@ -960,7 +1003,7 @@ bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnSameThread() char name[MaxPathSize]; AutoCloseMutexHandle m; - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex and closes second reference to mutex on lock-owner thread @@ -971,9 +1014,9 @@ bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnSameThread() TestAssert(m.Release()); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child exits - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); m.Close(); - TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(!TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(UninitializeParent(testName, parentEvents)); return true; @@ -991,10 +1034,10 @@ DWORD PALAPI LockAndCloseWithoutThreadExitTests_Child_CloseOnSameThread(void *ar char name[MaxPathSize]; // ... parent waits for child to lock and close second reference to mutex - AutoCloseMutexHandle m(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))); + AutoCloseMutexHandle m(TestOpenMutex(BuildName(testName, name, NamePrefix))); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, NamePrefix))) != nullptr); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits for child to close last reference to mutex m.Close(); // close mutex on lock-owner thread without releasing lock @@ -1016,7 +1059,7 @@ bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnDifferentThread() char name[MaxPathSize]; AutoCloseMutexHandle m; - TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestCreateMutex(m, BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex and closes second reference to mutex on lock-owner thread @@ -1025,7 +1068,7 @@ bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnDifferentThread() TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes last reference to mutex on non-lock-owner thread TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // attempt to lock and fail m.Close(); - m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); + m = TestOpenMutex(BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); // child has implicit reference to mutex TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes new reference to mutex on lock-owner thread @@ -1033,9 +1076,9 @@ bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnDifferentThread() TestAssert(m.Release()); TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child exits - TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); m.Close(); - TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + TestAssert(!TestFileExists(BuildShmFilePath(testName, name, NamePrefix))); TestAssert(UninitializeParent(testName, parentEvents)); return true; @@ -1053,10 +1096,10 @@ DWORD PALAPI LockAndCloseWithoutThreadExitTests_Child_CloseOnDifferentThread(voi char name[MaxPathSize]; // ... parent waits for child to lock and close second reference to mutex - AutoCloseMutexHandle m(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))); + AutoCloseMutexHandle m(TestOpenMutex(BuildName(testName, name, NamePrefix))); TestAssert(m != nullptr); TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); - TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, NamePrefix))) != nullptr); TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits for child to close last reference to mutex // Close the mutex on a thread that is not the lock-owner thread, without releasing the lock @@ -1068,7 +1111,7 @@ DWORD PALAPI LockAndCloseWithoutThreadExitTests_Child_CloseOnDifferentThread(voi m.Abandon(); // mutex is already closed, don't close it again TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies while this lock-owner thread is still active - m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); + m = TestOpenMutex(BuildName(testName, name, NamePrefix)); TestAssert(m != nullptr); m.Close(); // close mutex on lock-owner thread without releasing lock TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies while this thread is still active @@ -1110,14 +1153,24 @@ bool (*const TestList[])() = bool RunTests() { + const bool Bools[] = {false, true}; bool allPassed = true; - for (SIZE_T i = 0; i < ARRAY_SIZE(TestList); ++i) + for (int i = 0; i < ARRAY_SIZE(TestList); i++) { - if (!TestList[i]()) + for (int j = 0; j < ARRAY_SIZE(Bools); j++) { - allPassed = false; + g_currentUserOnly = Bools[j]; + for (int k = 0; k < ARRAY_SIZE(Bools); k++) + { + g_currentSessionOnly = Bools[k]; + if (!TestList[i]()) + { + allPassed = false; + } + } } } + return allPassed; } @@ -1189,7 +1242,7 @@ bool StressTests(DWORD durationMinutes) PALTEST(threading_NamedMutex_test1_paltest_namedmutex_test1, "threading/NamedMutex/test1/paltest_namedmutex_test1") { - if (argc < 1 || argc > 4) + if (argc < 1 || argc > 6) { return FAIL; } @@ -1228,10 +1281,17 @@ PALTEST(threading_NamedMutex_test1_paltest_namedmutex_test1, "threading/NamedMut return result; } - // Child test process arguments: [stress] + // Child test process arguments: + // <0|1> /* currentUserOnly */ <0|1> /* currentSessionOnly */ [stress] g_isParent = false; + if (argc < 5) + { + ExitProcess(FAIL); + return FAIL; + } + // Get parent process' ID from argument if (test_sscanf(argv[1], "%u", &g_parentPid) != 1) { @@ -1239,7 +1299,19 @@ PALTEST(threading_NamedMutex_test1_paltest_namedmutex_test1, "threading/NamedMut return FAIL; } - if (argc >= 4 && test_strcmp(argv[3], "stress") == 0) + // Get the current-user-only and current-session-only args + if ((argv[3][0] != '0' && argv[3][0] != '1') || + argv[3][1] != '\0' || + (argv[4][0] != '0' && argv[4][0] != '1') || + argv[4][1] != '\0') + { + ExitProcess(FAIL); + return FAIL; + } + g_currentUserOnly = argv[3][0] != '0'; + g_currentSessionOnly = argv[4][0] != '0'; + + if (argc >= 6 && test_strcmp(argv[5], "stress") == 0) { g_isStress = true; } diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp index 77665fe69c406d..435f53108b9300 100644 --- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,16 @@ unsigned int test_getpid() return getpid(); } +unsigned int test_getsid() +{ + return getsid(0); +} + +unsigned int test_geteuid() +{ + return geteuid(); +} + int test_kill(unsigned int pid) { return kill(pid, SIGKILL); @@ -41,11 +52,24 @@ bool TestFileExists(const char *path) return true; } -bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int *fdRef) +bool WriteHeaderInfo(const char *path, bool currentUserOnly, char sharedMemoryType, char version, int *fdRef) { int fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (fd == -1) return false; + + if (currentUserOnly) + { + int chmodResult; + do + { + chmodResult = chmod(path, S_IRUSR | S_IWUSR); + } while (chmodResult != 0 && errno == EINTR); + + if (chmodResult != 0) + return false; + } + *fdRef = fd; if (ftruncate(fd, getpagesize()) != 0) return false; diff --git a/src/coreclr/pal/tests/palsuite/wasm/index.html b/src/coreclr/pal/tests/palsuite/wasm/index.html index 18b6931a4879a8..9ca90c2d7c976e 100644 --- a/src/coreclr/pal/tests/palsuite/wasm/index.html +++ b/src/coreclr/pal/tests/palsuite/wasm/index.html @@ -12,7 +12,6 @@

PAL Tests WASM

"exception_handling/RaiseException", // 3 tests, we don't have stack unwinding available from C native code "file_io/GetFileAttributesEx", // blocks main thread "file_io/GetSystemTime", // blocks main thread - "file_io/GetTempFileName./test2/paltest_gettempfilename._test2", // infinite loop "file_io/WriteFile/test5/paltest_writefile_test5", // infinite loop "file_io/SetFilePointer/test7/paltest_setfilepointer_test7", // tries to allocate 4GB of memory in MEMFS when run with chromedriver "filemapping_memmgt/MapViewOfFile/test1/paltest_mapviewoffile_test1", // infinite loop and then chrome crashes diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index 7b440d5689c469..1a887cbb41e9c3 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -4,11 +4,13 @@ <_BuildNativeTargetOS>$(TargetOS) <_BuildNativeTargetOS Condition="'$(TargetsLinuxBionic)' == 'true'">linux-bionic true + <_IcuDir Condition="'$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)' != '' and '$(TargetsBrowser)' == 'true'">$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)/runtimes/$(TargetOS)-$(TargetArchitecture)$(_RuntimeVariant)/native + @@ -48,6 +50,7 @@ <_CoreClrBuildArg Condition="'$(BuildSubdirectory)' != ''" Include="-subdir $(BuildSubdirectory)" /> <_CoreClrBuildArg Include="-cmakeargs "-DCLR_DOTNET_HOST_PATH=$(DOTNET_HOST_PATH)"" /> <_CoreClrBuildArg Condition="'$(HasCdacBuildTool)' == 'true'" Include="-cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=$(RuntimeBinDir)cdac-build-tool\cdac-build-tool.dll"" /> + <_CoreClrBuildArg Condition="'$(_IcuDir)' != ''" Include="-cmakeargs "-DCLR_CMAKE_ICU_DIR=$(_IcuDir)"" /> diff --git a/src/coreclr/scripts/superpmi-replay.proj b/src/coreclr/scripts/superpmi-replay.proj index bd4d99c660e72b..398dec78ecc221 100644 --- a/src/coreclr/scripts/superpmi-replay.proj +++ b/src/coreclr/scripts/superpmi-replay.proj @@ -50,30 +50,72 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs index 480a604d6f7b86..de972aced7c565 100644 --- a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs +++ b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs @@ -11,12 +11,6 @@ namespace ILCompiler { - [Flags] - public enum InstructionSetSupportFlags - { - Vector512Throttling = 0x1, - } - public class InstructionSetSupport { private readonly TargetArchitecture _targetArchitecture; @@ -24,21 +18,19 @@ public class InstructionSetSupport private readonly InstructionSetFlags _supportedInstructionSets; private readonly InstructionSetFlags _unsupportedInstructionSets; private readonly InstructionSetFlags _nonSpecifiableInstructionSets; - private readonly InstructionSetSupportFlags _flags; public InstructionSetSupport(InstructionSetFlags supportedInstructionSets, InstructionSetFlags unsupportedInstructionSets, TargetArchitecture architecture) : this(supportedInstructionSets, unsupportedInstructionSets, supportedInstructionSets, default(InstructionSetFlags), architecture) { } - public InstructionSetSupport(InstructionSetFlags supportedInstructionSets, InstructionSetFlags unsupportedInstructionSets, InstructionSetFlags optimisticInstructionSets, InstructionSetFlags nonSpecifiableInstructionSets, TargetArchitecture architecture, InstructionSetSupportFlags flags = 0) + public InstructionSetSupport(InstructionSetFlags supportedInstructionSets, InstructionSetFlags unsupportedInstructionSets, InstructionSetFlags optimisticInstructionSets, InstructionSetFlags nonSpecifiableInstructionSets, TargetArchitecture architecture) { _supportedInstructionSets = supportedInstructionSets; _unsupportedInstructionSets = unsupportedInstructionSets; _optimisticInstructionSets = optimisticInstructionSets; _targetArchitecture = architecture; _nonSpecifiableInstructionSets = nonSpecifiableInstructionSets; - _flags = flags; } public bool IsInstructionSetSupported(InstructionSet instructionSet) @@ -63,8 +55,6 @@ public bool IsInstructionSetExplicitlyUnsupported(InstructionSet instructionSet) public TargetArchitecture Architecture => _targetArchitecture; - public InstructionSetSupportFlags Flags => _flags; - public static string GetHardwareIntrinsicId(TargetArchitecture architecture, TypeDesc potentialTypeDesc) { if (!potentialTypeDesc.IsIntrinsic || !(potentialTypeDesc is MetadataType potentialType)) @@ -121,10 +111,13 @@ public SimdVectorLength GetVectorTSimdVector() Debug.Assert(InstructionSet.X64_VectorT256 == InstructionSet.X86_VectorT256); Debug.Assert(InstructionSet.X64_VectorT512 == InstructionSet.X86_VectorT512); - // TODO-XArch: Add support for 512-bit Vector - Debug.Assert(!IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT512)); - - if (IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT256)) + if (IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT512)) + { + Debug.Assert(!IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT128)); + Debug.Assert(!IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT256)); + return SimdVectorLength.Vector512Bit; + } + else if (IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT256)) { Debug.Assert(!IsInstructionSetOptimisticallySupported(InstructionSet.X64_VectorT128)); return SimdVectorLength.Vector256Bit; @@ -437,15 +430,15 @@ public bool ComputeInstructionSetFlags(int maxVectorTBitWidth, Debug.Assert((maxVectorTBitWidth == 0) || (maxVectorTBitWidth >= 128)); supportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT128); - if (supportedInstructionSets.HasInstructionSet(InstructionSet.X86_AVX2)) + if (supportedInstructionSets.HasInstructionSet(InstructionSet.X86_AVX512F) && (maxVectorTBitWidth >= 512)) { - if ((maxVectorTBitWidth == 0) || (maxVectorTBitWidth >= 256)) - { - supportedInstructionSets.RemoveInstructionSet(InstructionSet.X86_VectorT128); - supportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT256); - } - - // TODO-XArch: Add support for 512-bit Vector + supportedInstructionSets.RemoveInstructionSet(InstructionSet.X86_VectorT128); + supportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT512); + } + else if (supportedInstructionSets.HasInstructionSet(InstructionSet.X86_AVX2) && (maxVectorTBitWidth is 0 or >= 256)) + { + supportedInstructionSets.RemoveInstructionSet(InstructionSet.X86_VectorT128); + supportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT256); } break; } diff --git a/src/coreclr/tools/Common/Compiler/TypeExtensions.cs b/src/coreclr/tools/Common/Compiler/TypeExtensions.cs index f16b643e0cbb41..ac69f6872a6b75 100644 --- a/src/coreclr/tools/Common/Compiler/TypeExtensions.cs +++ b/src/coreclr/tools/Common/Compiler/TypeExtensions.cs @@ -104,32 +104,6 @@ public static bool IsCanonicalDefinitionType(this TypeDesc type, CanonicalFormKi return type.Context.IsCanonicalDefinitionType(type, kind); } - /// - /// Gets the value of the field ordinal. Ordinals are computed by also including static fields, but excluding - /// literal fields and fields with RVAs. - /// - public static int GetFieldOrdinal(this FieldDesc inputField) - { - // Make sure we are asking the question for a valid instance or static field - Debug.Assert(!inputField.HasRva && !inputField.IsLiteral); - - int fieldOrdinal = 0; - foreach (FieldDesc field in inputField.OwningType.GetFields()) - { - // If this field does not contribute to layout, skip - if (field.HasRva || field.IsLiteral) - continue; - - if (field == inputField) - return fieldOrdinal; - - fieldOrdinal++; - } - - Debug.Assert(false); - return -1; - } - /// /// Determine if a type has a generic depth greater than a given value /// diff --git a/src/coreclr/tools/Common/InstructionSetHelpers.cs b/src/coreclr/tools/Common/InstructionSetHelpers.cs index 14940fc74db9e5..f9e9361fb462c4 100644 --- a/src/coreclr/tools/Common/InstructionSetHelpers.cs +++ b/src/coreclr/tools/Common/InstructionSetHelpers.cs @@ -20,7 +20,6 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru string mustNotBeMessage, string invalidImplicationMessage, Logger logger, bool optimizingForSize = false) { InstructionSetSupportBuilder instructionSetSupportBuilder = new(targetArchitecture); - InstructionSetSupportFlags flags = 0; // Ready to run images are built with certain instruction set baselines if ((targetArchitecture == TargetArchitecture.X86) || (targetArchitecture == TargetArchitecture.X64)) @@ -45,6 +44,8 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru // compile both branches of IsSupported checks. bool allowOptimistic = !optimizingForSize; + bool throttleAvx512 = false; + if (instructionSet == "native") { // We're compiling for a specific chip @@ -92,7 +93,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru // * Cascade Lake // * Cooper Lake - flags |= InstructionSetSupportFlags.Vector512Throttling; + throttleAvx512 = true; } } else if (extendedModel == 0x06) @@ -101,13 +102,13 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru { // * Cannon Lake - flags |= InstructionSetSupportFlags.Vector512Throttling; + throttleAvx512 = true; } } } } - if ((flags & InstructionSetSupportFlags.Vector512Throttling) != 0 && logger.IsVerbose) + if (throttleAvx512 && logger.IsVerbose) logger.LogMessage("Vector512 is throttled"); } @@ -180,7 +181,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(instructionSetSupportBuilder); // Optimistically assume some instruction sets are present. - if (allowOptimistic && (targetArchitecture == TargetArchitecture.X86 || targetArchitecture == TargetArchitecture.X64)) + if (allowOptimistic && targetArchitecture is TargetArchitecture.X86 or TargetArchitecture.X64) { // We set these hardware features as opportunistically enabled as most of hardware in the wild supports them. // Note that we do not indicate support for AVX, or any other instruction set which uses the VEX encodings as @@ -235,7 +236,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("gfni_v512"); } } - else if (targetArchitecture == TargetArchitecture.ARM64) + else if (allowOptimistic && targetArchitecture is TargetArchitecture.ARM64) { optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("crc"); @@ -252,12 +253,42 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru optimisticInstructionSet.Remove(unsupportedInstructionSet); optimisticInstructionSet.Add(supportedInstructionSet); + if (throttleAvx512) + { + Debug.Assert(InstructionSet.X86_AVX512F == InstructionSet.X64_AVX512F); + if (supportedInstructionSet.HasInstructionSet(InstructionSet.X86_AVX512F)) + { + Debug.Assert(InstructionSet.X86_Vector256 == InstructionSet.X64_Vector256); + Debug.Assert(InstructionSet.X86_VectorT256 == InstructionSet.X64_VectorT256); + Debug.Assert(InstructionSet.X86_VectorT512 == InstructionSet.X64_VectorT512); + + // AVX-512 is supported, but we are compiling specifically for hardware that has a performance penalty for + // using 512-bit ops. We want to tell JIT not to consider Vector512 to be hardware accelerated, which we do + // by passing a PreferredVectorBitWidth value, in the form of a virtual vector ISA of the appropriate size. + // + // If we are downgrading the max accelerated vector size, we also need to downgrade Vector size. + + supportedInstructionSet.AddInstructionSet(InstructionSet.X86_Vector256); + + if (supportedInstructionSet.HasInstructionSet(InstructionSet.X86_VectorT512)) + { + supportedInstructionSet.RemoveInstructionSet(InstructionSet.X86_VectorT512); + supportedInstructionSet.AddInstructionSet(InstructionSet.X86_VectorT256); + } + + if (optimisticInstructionSet.HasInstructionSet(InstructionSet.X86_VectorT512)) + { + optimisticInstructionSet.RemoveInstructionSet(InstructionSet.X86_VectorT512); + optimisticInstructionSet.AddInstructionSet(InstructionSet.X86_VectorT256); + } + } + } + return new InstructionSetSupport(supportedInstructionSet, unsupportedInstructionSet, optimisticInstructionSet, InstructionSetSupportBuilder.GetNonSpecifiableInstructionSetsForArch(targetArchitecture), - targetArchitecture, - flags); + targetArchitecture); } } } diff --git a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormat.cs b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormat.cs index 19a75854b9bbb2..dbe629602172b5 100644 --- a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormat.cs +++ b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormat.cs @@ -50,7 +50,7 @@ enum BagElementKind : uint ThreadStaticDesc = 0x48, ThreadStaticIndex = 0x49, ThreadStaticOffset = 0x4a, - FieldLayout = 0x4b, + // unused = 0x4b, // unused = 0x4c, // unused = 0x4d, ClassConstructorPointer = 0x4e, @@ -167,18 +167,6 @@ enum GenericContextKind : uint NeedsUSGContext = 0x08, }; -#if NATIVEFORMAT_PUBLICWRITER - public -#else - internal -#endif - enum CallingConventionConverterKind : uint - { - NoInstantiatingParam = 0x00, // The calling convention interpreter can assume that the calling convention of the target method has no instantiating parameter - HasInstantiatingParam = 0x01, // The calling convention interpreter can assume that the calling convention of the target method has an instantiating parameter - MaybeInstantiatingParam = 0x02, // The calling convention interpreter can assume that the calling convention of the target method may be a fat function pointer - } - [Flags] #if NATIVEFORMAT_PUBLICWRITER public @@ -190,7 +178,6 @@ enum MethodFlags : uint HasInstantiation = 0x1, IsUnboxingStub = 0x2, HasFunctionPointer = 0x4, - FunctionPointerIsUSG = 0x8, }; [Flags] @@ -205,17 +192,4 @@ enum MethodCallingConvention : uint Static = 0x2, Unmanaged = 0x4, }; - -#if NATIVEFORMAT_PUBLICWRITER - public -#else - internal -#endif - enum FieldStorage : uint - { - Instance = 0x0, - NonGCStatic = 0x1, - GCStatic = 0x2, - TLSStatic = 0x3, - } } diff --git a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs index 0a347d7ab3c567..f2f0f33a8c6f25 100644 --- a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs +++ b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs @@ -428,14 +428,6 @@ public Vertex GetTuple(Vertex item1, Vertex item2, Vertex item3) return Unify(vertex); } - public Vertex GetMethodNameAndSigSignature(string name, Vertex signature) - { - MethodNameAndSigSignature sig = new MethodNameAndSigSignature( - GetStringConstant(name), - GetRelativeOffsetSignature(signature)); - return Unify(sig); - } - public Vertex GetStringConstant(string value) { StringConstant vertex = new StringConstant(value); @@ -460,15 +452,9 @@ public Vertex GetExternalTypeSignature(uint externalTypeId) return Unify(sig); } - public Vertex GetMethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, Vertex methodNameAndSig, Vertex[] args) + public Vertex GetMethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, int token, Vertex[] args) { - MethodSignature sig = new MethodSignature(flags, fptrReferenceId, containingType, methodNameAndSig, args); - return Unify(sig); - } - - public Vertex GetFieldSignature(Vertex containingType, string name) - { - FieldSignature sig = new FieldSignature(containingType, name); + MethodSignature sig = new MethodSignature(flags, fptrReferenceId, containingType, token, args); return Unify(sig); } @@ -765,43 +751,6 @@ public override int GetHashCode() } } -#if NATIVEFORMAT_PUBLICWRITER - public -#else - internal -#endif - class MethodNameAndSigSignature : Vertex - { - private Vertex _methodName; - private Vertex _signature; - - public MethodNameAndSigSignature(Vertex methodName, Vertex signature) - { - _methodName = methodName; - _signature = signature; - } - - internal override void Save(NativeWriter writer) - { - _methodName.Save(writer); - _signature.Save(writer); - } - - public override int GetHashCode() - { - return 509 * 197 + _methodName.GetHashCode() + 647 * _signature.GetHashCode(); - } - - public override bool Equals(object obj) - { - MethodNameAndSigSignature other = obj as MethodNameAndSigSignature; - if (other == null) - return false; - - return Equals(_methodName, other._methodName) && Equals(_signature, other._signature); - } - } - #if NATIVEFORMAT_PUBLICWRITER public #else @@ -958,15 +907,15 @@ class MethodSignature : Vertex private uint _flags; private uint _fptrReferenceId; private Vertex _containingType; - private Vertex _methodNameAndSig; + private int _token; private Vertex[] _args; - public MethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, Vertex methodNameAndSig, Vertex[] args) + public MethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, int token, Vertex[] args) { _flags = flags; _fptrReferenceId = fptrReferenceId; _containingType = containingType; - _methodNameAndSig = methodNameAndSig; + _token = token; _args = args; if ((flags & (uint)MethodFlags.HasInstantiation) != 0) @@ -981,7 +930,7 @@ internal override void Save(NativeWriter writer) if ((_flags & (uint)MethodFlags.HasFunctionPointer) != 0) writer.WriteUnsigned(_fptrReferenceId); _containingType.Save(writer); - _methodNameAndSig.Save(writer); + writer.WriteUnsigned((uint)_token); if ((_flags & (uint)MethodFlags.HasInstantiation) != 0) { writer.WriteUnsigned((uint)_args.Length); @@ -998,7 +947,7 @@ public override int GetHashCode() hash += (hash << 5) + _containingType.GetHashCode(); for (uint iArg = 0; _args != null && iArg < _args.Length; iArg++) hash += (hash << 5) + _args[iArg].GetHashCode(); - hash += (hash << 5) + _methodNameAndSig.GetHashCode(); + hash += (hash << 5) + _token.GetHashCode(); return hash; } @@ -1011,8 +960,8 @@ public override bool Equals(object obj) if (!( _flags == other._flags && _fptrReferenceId == other._fptrReferenceId && - Equals(_containingType, other._containingType) && - Equals(_methodNameAndSig, other._methodNameAndSig))) + _token == other._token && + Equals(_containingType, other._containingType))) { return false; } @@ -1032,53 +981,6 @@ public override bool Equals(object obj) } } -#if NATIVEFORMAT_PUBLICWRITER - public -#else - internal -#endif - class FieldSignature : Vertex - { - private Vertex _containingType; - private string _name; - - public FieldSignature(Vertex containingType, string name) - { - _containingType = containingType; - _name = name; - } - - internal override void Save(NativeWriter writer) - { - _containingType.Save(writer); - writer.WriteString(_name); - } - - public override int GetHashCode() - { - int hash = 113 + 97 * _containingType.GetHashCode(); - foreach (char c in _name) - hash += (hash << 5) + c * 19; - - return hash; - } - - public override bool Equals(object obj) - { - var other = obj as FieldSignature; - if (other == null) - return false; - - if (!Equals(other._containingType, _containingType)) - return false; - - if (!Equals(other._name, _name)) - return false; - - return true; - } - } - #if NATIVEFORMAT_PUBLICWRITER public #else diff --git a/src/coreclr/tools/Common/Internal/Runtime/CanonTypeKind.cs b/src/coreclr/tools/Common/Internal/Runtime/CanonTypeKind.cs deleted file mode 100644 index 661725af693987..00000000000000 --- a/src/coreclr/tools/Common/Internal/Runtime/CanonTypeKind.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Internal.Runtime -{ - public enum CanonTypeKind - { - NormalCanon, - UniversalCanon, - } -} diff --git a/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs b/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs index 189be63698bcd1..b85d3c48d0cd78 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs @@ -22,11 +22,11 @@ public enum InvokeTableFlags : uint { HasVirtualInvoke = 0x00000001, IsGenericMethod = 0x00000002, - HasMetadataHandle = 0x00000004, + // = 0x00000004, IsDefaultConstructor = 0x00000008, RequiresInstArg = 0x00000010, HasEntrypoint = 0x00000020, - IsUniversalCanonicalEntry = 0x00000040, + // = 0x00000040, NeedsParameterInterpretation = 0x00000080, CallingConventionDefault = 0x00000000, Cdecl = 0x00001000, @@ -47,8 +47,8 @@ public enum FieldTableFlags : uint StorageClass = 0x03, - IsUniversalCanonicalEntry = 0x04, - HasMetadataHandle = 0x08, + // = 0x04, + // = 0x08, FieldOffsetEncodedDirectly = 0x20, IsAnyCanonicalEntry = 0x40, IsInitOnly = 0x80 diff --git a/src/coreclr/tools/Common/Internal/Runtime/UniversalGenericParameterLayout.cs b/src/coreclr/tools/Common/Internal/Runtime/UniversalGenericParameterLayout.cs deleted file mode 100644 index 47d9234f1fbf66..00000000000000 --- a/src/coreclr/tools/Common/Internal/Runtime/UniversalGenericParameterLayout.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Internal.TypeSystem; - -namespace Internal.Runtime -{ - internal static class UniversalGenericParameterLayout - { - private enum HasVarsInvestigationLevel - { - Parameter, - NotParameter - } - - /// - /// IF THESE SEMANTICS EVER CHANGE UPDATE THE LOGIC WHICH DEFINES THIS BEHAVIOR IN - /// THE DYNAMIC TYPE LOADER AS WELL AS THE COMPILER. - /// (There is a version of this in TypeLoaderEnvironment.SignatureParsing.cs that must be kept in sync with this.) - /// - /// Parameter's are considered to have type layout dependent on their generic instantiation - /// if the type of the parameter in its signature is a type variable, or if the type is a generic - /// structure which meets 2 characteristics: - /// 1. Structure size/layout is affected by the size/layout of one or more of its generic parameters - /// 2. One or more of the generic parameters is a type variable, or a generic structure which also recursively - /// would satisfy constraint 2. (Note, that in the recursion case, whether or not the structure is affected - /// by the size/layout of its generic parameters is not investigated.) - /// - /// Examples parameter types, and behavior. - /// - /// T = true - /// List[T] = false - /// StructNotDependentOnArgsForSize[T] = false - /// GenStructDependencyOnArgsForSize[T] = true - /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[T]] = true - /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[List[T]]]] = false - /// - /// Example non-parameter type behavior - /// T = true - /// List[T] = false - /// StructNotDependentOnArgsForSize[T] = *true* - /// GenStructDependencyOnArgsForSize[T] = true - /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[T]] = true - /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[List[T]]]] = false - /// - public static bool IsLayoutDependentOnGenericInstantiation(TypeDesc type) - { - return IsLayoutDependentOnGenericInstantiation(type, HasVarsInvestigationLevel.Parameter); - } - - private static bool IsLayoutDependentOnGenericInstantiation(TypeDesc type, HasVarsInvestigationLevel investigationLevel) - { - if (type.IsSignatureVariable) - { - return true; - } - else if (type.HasInstantiation && type.IsValueType) - { - foreach (TypeDesc valueTypeInstantiationParam in type.Instantiation) - { - if (IsLayoutDependentOnGenericInstantiation(valueTypeInstantiationParam, HasVarsInvestigationLevel.NotParameter)) - { - if (investigationLevel == HasVarsInvestigationLevel.Parameter) - { - DefType universalCanonForm = (DefType)type.ConvertToCanonForm(CanonicalFormKind.Universal); - return universalCanonForm.InstanceFieldSize.IsIndeterminate; - } - else - { - return true; - } - } - } - return false; - } - else - { - // All other forms of type do not change their shape dependent on signature variables. - return false; - } - } - - public static bool MethodSignatureHasVarsNeedingCallingConventionConverter(TypeSystem.MethodSignature methodSignature) - { - if (IsLayoutDependentOnGenericInstantiation(methodSignature.ReturnType, HasVarsInvestigationLevel.Parameter)) - return true; - - for (int i = 0; i < methodSignature.Length; i++) - { - if (IsLayoutDependentOnGenericInstantiation(methodSignature[i], HasVarsInvestigationLevel.Parameter)) - return true; - } - - return false; - } - - public static bool VTableMethodRequiresCallingConventionConverter(MethodDesc method) - { - if (!MethodSignatureHasVarsNeedingCallingConventionConverter(method.GetTypicalMethodDefinition().Signature)) - return false; - - MethodDesc slotDecl = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method).GetCanonMethodTarget(CanonicalFormKind.Specific); - return slotDecl.IsCanonicalMethod(CanonicalFormKind.Universal); - } - } -} diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 70dde2b702ea3b..b27b0c5e81b746 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -4216,9 +4216,6 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes) case TargetArchitecture.X86: Debug.Assert(InstructionSet.X86_SSE2 == InstructionSet.X64_SSE2); Debug.Assert(_compilation.InstructionSetSupport.IsInstructionSetSupported(InstructionSet.X86_SSE2)); - - if ((_compilation.InstructionSetSupport.Flags & InstructionSetSupportFlags.Vector512Throttling) != 0) - flags.Set(CorJitFlag.CORJIT_FLAG_VECTOR512_THROTTLING); break; case TargetArchitecture.ARM64: @@ -4421,29 +4418,38 @@ private bool notifyInstructionSetUsage(InstructionSet instructionSet, bool suppo } else { + // We want explicitly implemented ISimdVector APIs to still be expanded where possible + // but, they all prefix the qualified name of the interface first, so we'll check for that and + // skip the prefix before trying to resolve the method. ReadOnlySpan methodName = MethodBeingCompiled.Name.AsSpan(); - if (methodName.StartsWith("System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible - // but, they all prefix the qualified name of the interface first, so we'll check for that and - // skip the prefix before trying to resolve the method. - - ReadOnlySpan partialMethodName = methodName.Slice(70); + ReadOnlySpan partialMethodName = methodName.Slice(45); - if (partialMethodName.StartsWith(",T>.")) - { - methodName = partialMethodName.Slice(7); - } - else if (partialMethodName.StartsWith("64,T>.")) + if (partialMethodName.StartsWith("Numerics.Vector")) { - methodName = partialMethodName.Slice(9); + partialMethodName = partialMethodName.Slice(15); + + if (partialMethodName.StartsWith(",T>.")) + { + methodName = partialMethodName.Slice(7); + } } - else if (partialMethodName.StartsWith("128,T>.") || - partialMethodName.StartsWith("256,T>.") || - partialMethodName.StartsWith("512,T>.")) + if (partialMethodName.StartsWith("Runtime.Intrinsics.Vector")) { - methodName = partialMethodName.Slice(10); + partialMethodName = partialMethodName.Slice(25); + + if (partialMethodName.StartsWith("64,T>.")) + { + methodName = partialMethodName.Slice(9); + } + else if (partialMethodName.StartsWith("128,T>.") || + partialMethodName.StartsWith("256,T>.") || + partialMethodName.StartsWith("512,T>.")) + { + methodName = partialMethodName.Slice(10); + } } } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 08d7df78c946d8..d2bdca093e95c7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -1403,9 +1403,6 @@ public enum CorJitFlag : uint // 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/TypeSystem/IL/Stubs/GetCanonTypeIntrinsic.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/GetCanonTypeIntrinsic.cs index 9c44adad0d5fe1..92f6b53684ff1c 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/GetCanonTypeIntrinsic.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/GetCanonTypeIntrinsic.cs @@ -15,7 +15,7 @@ public static class GetCanonTypeIntrinsic { public static MethodIL EmitIL(MethodDesc target) { - Debug.Assert(target.Signature.Length == 1); + Debug.Assert(target.Signature.Length == 0); ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); @@ -24,35 +24,7 @@ public static MethodIL EmitIL(MethodDesc target) TypeDesc runtimeTypeHandleType = context.GetWellKnownType(WellKnownType.RuntimeTypeHandle); Debug.Assert(target.Signature.ReturnType == runtimeTypeHandleType); - if (context.SupportsCanon) - { - ILCodeLabel lNotCanon = emitter.NewCodeLabel(); - codeStream.Emit(ILOpcode.ldarg_0); - codeStream.EmitLdc((int)CanonTypeKind.NormalCanon); - codeStream.Emit(ILOpcode.bne_un, lNotCanon); - codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(context.CanonType)); - codeStream.Emit(ILOpcode.ret); - codeStream.EmitLabel(lNotCanon); - - // We're not conditioning this on SupportsUniversalCanon because the runtime type loader - // does a lot of comparisons against UniversalCanon and not having a RuntimeTypeHandle - // for it makes these checks awkward. - // Would be nice if we didn't have to emit the MethodTable if universal canonical code wasn't enabled - // at the time of compilation. - ILCodeLabel lNotUniversalCanon = emitter.NewCodeLabel(); - codeStream.Emit(ILOpcode.ldarg_0); - codeStream.EmitLdc((int)CanonTypeKind.UniversalCanon); - codeStream.Emit(ILOpcode.bne_un, lNotUniversalCanon); - codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(context.UniversalCanonType)); - codeStream.Emit(ILOpcode.ret); - codeStream.EmitLabel(lNotUniversalCanon); - } - - ILLocalVariable vNullTypeHandle = emitter.NewLocal(runtimeTypeHandleType); - codeStream.EmitLdLoca(vNullTypeHandle); - codeStream.Emit(ILOpcode.initobj, emitter.NewToken(runtimeTypeHandleType)); - codeStream.EmitLdLoc(vNullTypeHandle); - + codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(context.CanonType)); codeStream.Emit(ILOpcode.ret); return emitter.Link(target); diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs index 29abb9313ea305..b5e9d32dff01ce 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs @@ -19,10 +19,9 @@ public static bool IsStructMarshallingRequired(TypeDesc typeDesc) typeDesc = typeDesc.UnderlyingType; - // TODO: There are primitive types which require marshalling, such as bool, char. if (typeDesc.IsPrimitive) { - return false; + return typeDesc.Category is TypeFlags.Boolean or TypeFlags.Char; } MetadataType type = typeDesc as MetadataType; diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs index 0dff54cd75a190..f1fc3547a09a8a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs @@ -680,11 +680,9 @@ protected override void TransformNativeToManaged(ILCodeStream codeStream) LoadManagedValue(codeStream); codeStream.Emit(ILOpcode.brtrue, lNonNull); - MethodDesc ctor = ManagedType.GetParameterlessConstructor(); - if (ctor == null) - throw new InvalidProgramException(); - - codeStream.Emit(ILOpcode.newobj, emitter.NewToken(ctor)); + codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(ManagedType)); + codeStream.Emit(ILOpcode.call, emitter.NewToken(InteropTypes.GetType(Context).GetMethod("GetTypeFromHandle", null))); + codeStream.Emit(ILOpcode.call, emitter.NewToken(InteropTypes.GetRuntimeHelpers(Context).GetKnownMethod("GetUninitializedObject", null))); StoreManagedValue(codeStream); codeStream.EmitLabel(lNonNull); @@ -736,12 +734,9 @@ protected override void AllocManagedToNative(ILCodeStream codeStream) protected override void AllocNativeToManaged(ILCodeStream codeStream) { ILEmitter emitter = _ilCodeStreams.Emitter; - - MethodDesc ctor = ManagedType.GetParameterlessConstructor(); - if (ctor == null) - throw new InvalidProgramException(); - - codeStream.Emit(ILOpcode.newobj, emitter.NewToken(ctor)); + codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(ManagedType)); + codeStream.Emit(ILOpcode.call, emitter.NewToken(InteropTypes.GetType(Context).GetMethod("GetTypeFromHandle", null))); + codeStream.Emit(ILOpcode.call, emitter.NewToken(InteropTypes.GetRuntimeHelpers(Context).GetKnownMethod("GetUninitializedObject", null))); StoreManagedValue(codeStream); } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs index 7fdd0f06596209..247e09e7f77e13 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs @@ -12,6 +12,11 @@ public static MetadataType GetGC(TypeSystemContext context) return context.SystemModule.GetKnownType("System", "GC"); } + public static MetadataType GetType(TypeSystemContext context) + { + return context.SystemModule.GetKnownType("System", "Type"); + } + public static MetadataType GetSafeHandle(TypeSystemContext context) { return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "SafeHandle"); @@ -32,6 +37,11 @@ public static MetadataType GetPInvokeMarshal(TypeSystemContext context) return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "PInvokeMarshal"); } + public static MetadataType GetRuntimeHelpers(TypeSystemContext context) + { + return context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RuntimeHelpers"); + } + public static MetadataType GetMarshal(TypeSystemContext context) { return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "Marshal"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs index 854f958b69f916..0e5a953736a5ac 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs @@ -14,6 +14,7 @@ using CustomAttributeHandle = System.Reflection.Metadata.CustomAttributeHandle; using ExportedTypeHandle = System.Reflection.Metadata.ExportedTypeHandle; using FlowAnnotations = ILLink.Shared.TrimAnalysis.FlowAnnotations; +using ParameterHandle = System.Reflection.Metadata.ParameterHandle; namespace ILCompiler { @@ -29,6 +30,7 @@ public sealed class AnalysisBasedMetadataManager : MetadataManager, ICompilation private readonly Dictionary _reflectableMethods = new Dictionary(); private readonly Dictionary _reflectableFields = new Dictionary(); private readonly HashSet _reflectableAttributes = new HashSet(); + private readonly HashSet _reflectableParameters = new HashSet(); public AnalysisBasedMetadataManager(CompilerTypeSystemContext typeSystemContext) : this(typeSystemContext, new FullyBlockedMetadataBlockingPolicy(), @@ -36,6 +38,7 @@ public AnalysisBasedMetadataManager(CompilerTypeSystemContext typeSystemContext) new NoDynamicInvokeThunkGenerationPolicy(), null, Array.Empty(), Array.Empty(), Array.Empty>(), Array.Empty>(), Array.Empty>(), Array.Empty(), + Array.Empty(), default) { } @@ -54,6 +57,7 @@ public AnalysisBasedMetadataManager( IEnumerable> reflectableMethods, IEnumerable> reflectableFields, IEnumerable reflectableAttributes, + IEnumerable reflectableParameters, MetadataManagerOptions options) : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy, options, flowAnnotations) { @@ -92,6 +96,11 @@ public AnalysisBasedMetadataManager( _reflectableAttributes.Add(refAttribute); } + foreach (var refParameter in reflectableParameters) + { + _reflectableParameters.Add(refParameter); + } + #if DEBUG HashSet moduleHash = new HashSet(_modulesWithMetadata); foreach (var refType in reflectableTypes) @@ -135,14 +144,18 @@ protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping) { ComputeMetadata(new Policy(_blockingPolicy, this), factory, out metadataBlob, out typeMappings, out methodMappings, + out methodMetadataMappings, out fieldMappings, + out fieldMetadataMappings, out stackTraceMapping); } @@ -239,6 +252,11 @@ public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle) return _parent._reflectableAttributes.Contains(new ReflectableCustomAttribute(module, caHandle)); } + public bool GeneratesMetadata(EcmaModule module, ParameterHandle paramHandle) + { + return _parent._reflectableParameters.Contains(new ReflectableParameter(module, paramHandle)); + } + public bool GeneratesMetadata(EcmaModule module, ExportedTypeHandle exportedTypeHandle) { // We'll possibly need to do something else here if we ever use this MetadataManager @@ -299,4 +317,19 @@ public override bool Equals(object obj) => obj is ReflectableCustomAttribute other && Equals(other); public override int GetHashCode() => Module.GetHashCode() ^ CustomAttributeHandle.GetHashCode(); } + + public struct ReflectableParameter : IEquatable + { + public readonly EcmaModule Module; + public readonly ParameterHandle ParameterHandle; + + public ReflectableParameter(EcmaModule module, ParameterHandle paramHandle) + => (Module, ParameterHandle) = (module, paramHandle); + + public bool Equals(ReflectableParameter other) + => other.Module == Module && other.ParameterHandle == ParameterHandle; + public override bool Equals(object obj) + => obj is ReflectableParameter other && Equals(other); + public override int GetHashCode() => Module.GetHashCode() ^ ParameterHandle.GetHashCode(); + } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index da836366290959..ecd3df3a3915c8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -374,9 +374,7 @@ public GenericDictionaryLookup ComputeGenericLookup(MethodDesc contextMethod, Re if (lookupKind == ReadyToRunHelperId.TypeHandleForCasting) { var type = (TypeDesc)targetOfLookup; - if (!type.IsRuntimeDeterminedType || - (!((RuntimeDeterminedType)type).CanonicalType.IsCanonicalDefinitionType(CanonicalFormKind.Universal) && - !((RuntimeDeterminedType)type).CanonicalType.IsNullable)) + if (!type.IsRuntimeDeterminedType || !((RuntimeDeterminedType)type).CanonicalType.IsNullable) { if (type.IsNullable) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.Aot.cs index 8d7f861958dc26..699d8d16577e51 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.Aot.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.Aot.cs @@ -70,9 +70,7 @@ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForNo public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type) { - if (type == UniversalCanonType) - return UniversalCanonLayoutAlgorithm.Instance; - else if (type.IsRuntimeDeterminedType) + if (type.IsRuntimeDeterminedType) return _runtimeDeterminedFieldLayoutAlgorithm; else if (VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(type)) return _vectorOfTFieldLayoutAlgorithm; @@ -224,34 +222,12 @@ public void LogWarnings(Logger logger) public class SharedGenericsConfiguration { - // - // Universal Shared Generics heuristics magic values determined empirically - // - public long UniversalCanonGVMReflectionRootHeuristic_InstantiationCount { get; } - public long UniversalCanonGVMDepthHeuristic_NonCanonDepth { get; } - public long UniversalCanonGVMDepthHeuristic_CanonDepth { get; } - - // Controls how many different instantiations of a generic method, or method on generic type - // should be allowed before trying to fall back to only supplying USG in the reflection - // method table. - public long UniversalCanonReflectionMethodRootHeuristic_InstantiationCount { get; } - // To avoid infinite generic recursion issues during debug type record generation, attempt to // use canonical form for types with high generic complexity. public long MaxGenericDepthOfDebugRecord { get; } public SharedGenericsConfiguration() { - UniversalCanonGVMReflectionRootHeuristic_InstantiationCount = 4; - UniversalCanonGVMDepthHeuristic_NonCanonDepth = 2; - UniversalCanonGVMDepthHeuristic_CanonDepth = 1; - - // Unlike the GVM heuristics which are intended to kick in aggressively - // this heuristic exists to make it so that a fair amount of generic - // expansion is allowed. Numbers are chosen to allow a fairly large - // amount of generic expansion before trimming. - UniversalCanonReflectionMethodRootHeuristic_InstantiationCount = 1024; - MaxGenericDepthOfDebugRecord = 15; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs index 7a85ad1fd7f31e..4336a5bd88b720 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs @@ -45,15 +45,10 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencyList.Add(factory.VTable(closestDefType), "VTable"); - if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal)) - dependencyList.Add(factory.NativeLayout.TemplateTypeLayout(_type), "Universal generic types always have template layout"); - // Track generic virtual methods that will get added to the GVM tables if ((_virtualMethodAnalysisFlags & VirtualMethodAnalysisFlags.NeedsGvmEntries) != 0) { dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type.GetTypeDefinition()), "Type with generic virtual methods")); - - AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList); } return dependencyList; @@ -75,22 +70,12 @@ protected override int GCDescSize { get { - // No GCDescs for universal canonical types - if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal)) - return 0; - - Debug.Assert(_type.IsCanonicalSubtype(CanonicalFormKind.Specific)); return GCDescEncoder.GetGCDescSize(_type); } } protected override void OutputGCDesc(ref ObjectDataBuilder builder) { - // No GCDescs for universal canonical types - if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal)) - return; - - Debug.Assert(_type.IsCanonicalSubtype(CanonicalFormKind.Specific)); GCDescEncoder.EncodeGCDesc(ref builder, _type); } @@ -107,26 +92,6 @@ protected override void OutputInterfaceMap(NodeFactory factory, ref ObjectDataBu } } - protected override int BaseSize - { - get - { - if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal) && _type.IsDefType) - { - LayoutInt instanceByteCount = ((DefType)_type).InstanceByteCount; - - if (instanceByteCount.IsIndeterminate) - { - // For USG types, they may be of indeterminate size, and the size of the type may be meaningless. - // In that case emit a fixed constant. - return MinimumObjectSize; - } - } - - return base.BaseSize; - } - } - public override int ClassCode => -1798018602; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index 1905d09e64ef0a..162d2b9c5a1dc1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -53,22 +53,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencyList.Add(factory.VTable(closestDefType), "VTable"); - if (factory.TypeSystemContext.SupportsUniversalCanon) - { - foreach (var instantiationType in _type.Instantiation) - { - if (instantiationType.IsValueType) - { - // All valuetype generic parameters of a constructed type may be effectively constructed. This is generally not that - // critical, but in the presence of universal generics the compiler may generate a Box followed by calls to ToString, - // GetHashcode or Equals in ways that cannot otherwise be detected by dependency analysis. Thus force all struct type - // generic parameters to be considered constructed when walking dependencies of a constructed generic - dependencyList.Add(factory.ConstructedTypeSymbol(instantiationType.ConvertToCanonForm(CanonicalFormKind.Specific)), - "Struct generic parameters in constructed types may be assumed to be used as constructed in constructed generic types"); - } - } - } - // Ask the metadata manager if we have any dependencies due to the presence of the EEType. factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index a37fb8d8d85c86..2c807330567229 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -263,10 +263,6 @@ private bool CanonFormTypeMayExist if (_type.IsCanonicalSubtype(CanonicalFormKind.Any)) return false; - // If we reach here, a universal canon variant can exist (if universal canon is supported) - if (_type.Context.SupportsUniversalCanon) - return true; - // Attempt to convert to canon. If the type changes, then the CanonForm exists return (_type.ConvertToCanonForm(CanonicalFormKind.Specific) != _type); } @@ -337,9 +333,6 @@ public override IEnumerable GetConditionalStaticDep if (CanonFormTypeMayExist) { result.Add(new CombinedDependencyListEntry(maximallyConstructableType, factory.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Trigger full type generation if canonical form exists")); - - if (_type.Context.SupportsUniversalCanon) - result.Add(new CombinedDependencyListEntry(maximallyConstructableType, factory.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Universal)), "Trigger full type generation if universal canonical form exists")); } return result; } @@ -636,8 +629,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact { dependencies.Add(new DependencyListEntry(factory.TypeGVMEntries(_type.GetTypeDefinition()), "Type with generic virtual methods")); - AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencies); - TypeDesc canonicalType = _type.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonicalType != _type) dependencies.Add(factory.ConstructedTypeSymbol(canonicalType), "Type with generic virtual methods"); @@ -805,16 +796,9 @@ private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData, boo if (_type.IsArray) { TypeDesc elementType = ((ArrayType)_type).ElementType; - if (elementType == elementType.Context.UniversalCanonType) - { - // elementSize == 0 - } - else - { - int elementSize = elementType.GetElementSize().AsInt; - // We validated that this will fit the short when the node was constructed. No need for nice messages. - flags |= (uint)checked((ushort)elementSize); - } + int elementSize = elementType.GetElementSize().AsInt; + // We validated that this will fit the short when the node was constructed. No need for nice messages. + flags |= (uint)checked((ushort)elementSize); } else if (_type.IsString) { @@ -943,9 +927,7 @@ private void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objDa declType.ConvertToCanonForm(CanonicalFormKind.Specific) == declType; // Note: Canonical type instantiations always have a generic dictionary vtable slot, but it's empty - // Note: If the current EETypeNode represents a universal canonical type, any dictionary slot must be empty if (declType.IsCanonicalSubtype(CanonicalFormKind.Any) - || implType.IsCanonicalSubtype(CanonicalFormKind.Universal) || factory.LazyGenericsPolicy.UsesLazyGenerics(declType) || isInterfaceWithAnEmptySlot) { @@ -1232,32 +1214,6 @@ protected override void OnMarked(NodeFactory context) Debug.Assert(_type.IsTypeDefinition || !_type.HasSameTypeDefinition(context.ArrayOfTClass), "Asking for Array MethodTable"); } - protected static void AddDependenciesForUniversalGVMSupport(NodeFactory factory, TypeDesc type, ref DependencyList dependencies) - { - if (factory.TypeSystemContext.SupportsUniversalCanon) - { - foreach (MethodDesc method in type.GetVirtualMethods()) - { - if (!method.HasInstantiation) - continue; - - if (method.IsAbstract) - continue; - - TypeDesc[] universalCanonArray = new TypeDesc[method.Instantiation.Length]; - for (int i = 0; i < universalCanonArray.Length; i++) - universalCanonArray[i] = factory.TypeSystemContext.UniversalCanonType; - - InstantiatedMethod universalCanonMethodNonCanonicalized = method.MakeInstantiatedMethod(new Instantiation(universalCanonArray)); - MethodDesc universalCanonGVMMethod = universalCanonMethodNonCanonicalized.GetCanonMethodTarget(CanonicalFormKind.Universal); - - dependencies ??= new DependencyList(); - - dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(universalCanonGVMMethod), "USG GVM Method")); - } - } - } - public override int ClassCode => 1521789141; public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs index 9e1a274e30bc4e..9740188e3dc32d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs @@ -73,17 +73,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode))); } - // Get the name and sig of the method. - // Note: the method name and signature are stored in the NativeLayoutInfo blob, not in the hashtable we build here. - - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - Debug.Assert(placedNameAndSig.SavedVertex != null); - Vertex placedNameAndSigOffsetSig = nativeWriter.GetOffsetSignature(placedNameAndSig.SavedVertex); + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, method.GetTypicalMethodDefinition()); // Get the vertex for the completed method signature - Vertex methodSignature = nativeWriter.GetTuple(declaringType, placedNameAndSigOffsetSig, arguments); + Vertex methodSignature = nativeWriter.GetTuple(declaringType, nativeWriter.GetUnsignedConstant((uint)token), arguments); // Make the generic method entry vertex @@ -118,9 +112,7 @@ public static void GetExactMethodInstantiationDependenciesForMethod(ref Dependen foreach (var arg in method.Instantiation) dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(arg), "Exact method instantiation entry")); - // Get native layout dependencies for the method signature. - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(nameAndSig), "Exact method instantiation entry")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, method.GetTypicalMethodDefinition()); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs index 694f0e2d9c90c5..98d3896311dae3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs @@ -467,18 +467,11 @@ public override NativeLayoutVertexNode TemplateDictionaryNode(NodeFactory factor { MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific); - // - // For universal canonical methods, we don't need the unboxing stub really, because - // the calling convention translation thunk will handle the unboxing (and we can avoid having a double thunk here) - // We just need the flag in the native layout info signature indicating that we needed an unboxing stub - // - bool getUnboxingStubNode = _isUnboxingThunk && !canonMethod.IsCanonicalMethod(CanonicalFormKind.Universal); - // TODO-SIZE: this is address taken only in the delegate target case return factory.NativeLayout.MethodEntrypointDictionarySlot( _method, _isUnboxingThunk, - factory.AddressTakenMethodEntrypoint(canonMethod, getUnboxingStubNode)); + factory.AddressTakenMethodEntrypoint(canonMethod, _isUnboxingThunk)); } protected override int CompareToImpl(GenericLookupResult other, TypeSystemComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs index 04d62dbad5541d..67da861f048d76 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs @@ -67,12 +67,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode))); } - // Method name and signature - NativeLayoutVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutSavedVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - Vertex placedNameAndSigVertexOffset = nativeWriter.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset); + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, method.GetTypicalMethodDefinition()); - fullMethodSignature = nativeWriter.GetTuple(containingType, placedNameAndSigVertexOffset, arguments); + fullMethodSignature = nativeWriter.GetTuple(containingType, nativeWriter.GetUnsignedConstant((uint)token), arguments); } // Method's dictionary pointer @@ -108,10 +105,7 @@ public static void GetGenericMethodsHashtableDependenciesForMethod(ref Dependenc dependencies.Add(new DependencyListEntry(argNode, "GenericMethodsHashtable entry instantiation argument")); } - // Method name and signature - NativeLayoutVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutSavedVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - dependencies.Add(new DependencyListEntry(placedNameAndSig, "GenericMethodsHashtable entry signature")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, method.GetTypicalMethodDefinition()); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs index d0e03824097534..857106fa3d4fed 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs @@ -101,12 +101,6 @@ private static bool IsEligibleToBeATemplate(MethodDesc method) Debug.Assert(method == method.GetCanonMethodTarget(CanonicalFormKind.Specific)); return true; } - else if (method.IsCanonicalMethod(CanonicalFormKind.Universal)) - { - // Must be fully canonical - if (method == method.GetCanonMethodTarget(CanonicalFormKind.Universal)) - return true; - } return false; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs index 1fb8ab0a4cc20c..6912c9358a18dc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs @@ -15,7 +15,6 @@ namespace ILCompiler.DependencyAnalysis /// public class GenericVirtualMethodImplNode : DependencyNodeCore { - private const int UniversalCanonGVMDepthHeuristic_CanonDepth = 2; private readonly MethodDesc _method; public GenericVirtualMethodImplNode(MethodDesc method) @@ -49,12 +48,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (validInstantiation) { - if (factory.TypeSystemContext.SupportsUniversalCanon && _method.IsGenericDepthGreaterThan(UniversalCanonGVMDepthHeuristic_CanonDepth)) - { - // fall back to using the universal generic variant of the generic method - return dependencies; - } - bool getUnboxingStub = _method.OwningType.IsValueType && !_method.Signature.IsStatic; dependencies ??= new DependencyList(); dependencies.Add(factory.MethodEntrypoint(_method, getUnboxingStub), "GVM Dependency - Canon method"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs index 210293d9435834..6a3affe4b74d8c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -53,11 +53,8 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); - var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); - var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); - - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "gvm table calling method signature")); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "gvm table implementation method signature")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod); } private void AddGenericVirtualMethodImplementation(MethodDesc callingMethod, MethodDesc implementationMethod) @@ -116,11 +113,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) uint targetTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(targetTypeId)); - var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); - vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + int callingMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, callingMethod); + vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)callingMethodToken)); - nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); - vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + int implementationMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, implementationMethod); + vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)implementationMethodToken)); int hashCode = callingMethod.OwningType.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ implementationType.GetHashCode(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs index 8815fea96e9b56..e1f432af8ff3c6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -55,16 +55,15 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); TypeDesc openImplementationType = implementationType.GetTypeDefinition(); - var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "interface gvm table calling method signature")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod); // Implementation could be null if this is a default interface method reabstraction or diamond. We need to record those. if (implementationMethod != null) { MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(openImplementationMethod.OwningType), "interface gvm table implementation method owning type")); - var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "interface gvm table implementation method signature")); + + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod); } if (!openImplementationType.IsInterface) @@ -153,10 +152,10 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // Emit the method signature and containing type of the current interface method uint typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType)); - var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); + int callingMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, callingMethod); Vertex vertex = nativeFormatWriter.GetTuple( nativeFormatWriter.GetUnsignedConstant(typeId), - nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + nativeFormatWriter.GetUnsignedConstant((uint)callingMethodToken)); // Emit the method name / sig and containing type of each GVM target method for the current interface method entry vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)gvmEntry.Value.Count)); @@ -164,11 +163,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (impl is MethodDesc implementationMethod) { - nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); + int implementationMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, implementationMethod); typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationMethod.OwningType)); vertex = nativeFormatWriter.GetTuple( vertex, - nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset), + nativeFormatWriter.GetUnsignedConstant((uint)implementationMethodToken), nativeFormatWriter.GetUnsignedConstant(typeId)); } else diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs index 7f44064c450894..8eaade82cc95f3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs @@ -25,12 +25,14 @@ namespace ILCompiler.DependencyAnalysis /// internal sealed class MethodMetadataNode : DependencyNodeCore { - private readonly MethodDesc _method; + private readonly EcmaMethod _method; + private readonly bool _isMinimal; - public MethodMetadataNode(MethodDesc method) + public MethodMetadataNode(MethodDesc method, bool isMinimal) { Debug.Assert(method.IsTypicalMethodDefinition); - _method = method; + _method = (EcmaMethod)method; + _isMinimal = isMinimal; } public MethodDesc Method => _method; @@ -40,7 +42,15 @@ public override IEnumerable GetStaticDependencies(NodeFacto DependencyList dependencies = new DependencyList(); dependencies.Add(factory.TypeMetadata((MetadataType)_method.OwningType), "Owning type metadata"); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaMethod)_method)); + if (!_isMinimal) + { + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _method); + + foreach (var parameterHandle in _method.MetadataReader.GetMethodDefinition(_method.Handle).GetParameters()) + { + dependencies.Add(factory.MethodParameterMetadata(new ReflectableParameter(_method.Module, parameterHandle)), "Parameter is visible"); + } + } MethodSignature sig = _method.Signature; const string reason = "Method signature metadata"; @@ -57,9 +67,9 @@ public override IEnumerable GetStaticDependencies(NodeFacto TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, sigData.type, "Modifier in a method signature"); } - if (_method is EcmaMethod ecmaMethod) + if (!_isMinimal) { - DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaMethod); + DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, _method); // On a reflectable method, perform generic data flow for the return type and all the parameter types // This is a compensation for the DI issue described in https://github.com/dotnet/runtime/issues/81358 diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs new file mode 100644 index 00000000000000..ff0278c3f1d83b --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs @@ -0,0 +1,41 @@ +// 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 ILCompiler.DependencyAnalysisFramework; + +namespace ILCompiler.DependencyAnalysis +{ + /// + /// Represents a parameter that has metadata generated in the current compilation. + /// + /// + /// Only expected to be used during ILScanning when scanning for reflection. + /// + internal sealed class MethodParameterMetadataNode : DependencyNodeCore + { + private readonly ReflectableParameter _parameter; + + public MethodParameterMetadataNode(ReflectableParameter parameter) + { + _parameter = parameter; + } + + public ReflectableParameter Parameter => _parameter; + + public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + + protected override string GetName(NodeFactory factory) + { + return $"Reflectable parameter {_parameter.ParameterHandle} in {_parameter.Module}"; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasDynamicDependencies => false; + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => true; + public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; + public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs index 8e5b9c4734f4ba..3e2b17b3617ecb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs @@ -22,7 +22,6 @@ public sealed class NativeLayoutInfoNode : ObjectNode, ISymbolDefinitionNode, IN private byte[] _writerSavedBytes; private Section _signaturesSection; - private Section _ldTokenInfoSection; private Section _templatesSection; private List _vertexNodesToWrite; @@ -34,7 +33,6 @@ public NativeLayoutInfoNode(ExternalReferencesTableNode externalReferences, Exte _writer = new NativeWriter(); _signaturesSection = _writer.NewSection(); - _ldTokenInfoSection = _writer.NewSection(); _templatesSection = _writer.NewSection(); _vertexNodesToWrite = new List(); @@ -51,7 +49,6 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => true; protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - public Section LdTokenInfoSection => _ldTokenInfoSection; public Section SignaturesSection => _signaturesSection; public Section TemplatesSection => _templatesSection; public ExternalReferencesTableNode ExternalReferences => _externalReferences; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs deleted file mode 100644 index fe00421b74e60c..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs +++ /dev/null @@ -1,128 +0,0 @@ -// 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.Diagnostics; - -using Internal.Text; -using Internal.TypeSystem; - -namespace ILCompiler.DependencyAnalysis -{ - /// - /// Represents a native layout signature. A signature is a pair where the first item is a pointer - /// to the TypeManager that contains the native layout info blob of interest, and the second item - /// is an offset into that native layout info blob - /// - public class NativeLayoutSignatureNode : DehydratableObjectNode, ISymbolDefinitionNode - { - private TypeSystemEntity _identity; - private Utf8String _identityPrefix; - private NativeLayoutSavedVertexNode _nativeSignature; - - public TypeSystemEntity Identity => _identity; - - public NativeLayoutSignatureNode(NativeLayoutSavedVertexNode nativeSignature, TypeSystemEntity identity, Utf8String identityPrefix) - { - _nativeSignature = nativeSignature; - _identity = identity; - _identityPrefix = identityPrefix; - } - - public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - { - Utf8String identityString; - if (_identity is MethodDesc) - { - identityString = nameMangler.GetMangledMethodName((MethodDesc)_identity); - } - else if (_identity is TypeDesc) - { - identityString = nameMangler.GetMangledTypeName((TypeDesc)_identity); - } - else if (_identity is FieldDesc) - { - identityString = nameMangler.GetMangledFieldName((FieldDesc)_identity); - } - else - { - Debug.Assert(false); - identityString = new Utf8String("unknown"); - } - - sb.Append(nameMangler.CompilationUnitPrefix).Append(_identityPrefix).Append(identityString); - } - - public int Offset => 0; - protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) - { - if (factory.Target.IsWindows) - return ObjectNodeSection.ReadOnlyDataSection; - else - return ObjectNodeSection.DataSection; - } - public override bool IsShareable => false; - public override bool StaticDependenciesAreComputed => true; - - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) - { - DependencyList dependencies = new DependencyList(); - dependencies.Add(new DependencyListEntry(_nativeSignature, "NativeLayoutSignatureNode target vertex")); - return dependencies; - } - - protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) - { - // This node does not trigger generation of other nodes. - if (relocsOnly) - return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); - - // Ensure native layout is saved to get valid Vertex offsets - factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); - - ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); - - objData.RequireInitialPointerAlignment(); - objData.AddSymbol(this); - - objData.EmitPointerReloc(factory.TypeManagerIndirection); - objData.EmitNaturalInt(_nativeSignature.SavedVertex.VertexOffset); - - return objData.ToObjectData(); - } - - public override int ClassCode => 1887049331; - - public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) - { - NativeLayoutSignatureNode otherSignature = (NativeLayoutSignatureNode)other; - if (_identity is MethodDesc) - { - if (otherSignature._identity is TypeDesc || otherSignature._identity is FieldDesc) - return -1; - return comparer.Compare((MethodDesc)_identity, (MethodDesc)((NativeLayoutSignatureNode)other)._identity); - } - else if (_identity is TypeDesc) - { - if (otherSignature._identity is MethodDesc) - return 1; - - if (otherSignature._identity is FieldDesc) - return -1; - - return comparer.Compare((TypeDesc)_identity, (TypeDesc)((NativeLayoutSignatureNode)other)._identity); - } - else if (_identity is FieldDesc) - { - if (otherSignature._identity is MethodDesc || otherSignature._identity is TypeDesc) - return 1; - return comparer.Compare((FieldDesc)_identity, (FieldDesc)((NativeLayoutSignatureNode)other)._identity); - } - else - { - throw new NotSupportedException("New type system entity needs a comparison"); - } - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs index f807b6b8e6c037..60b9a82dd0f930 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -90,7 +90,7 @@ protected Vertex SetSavedVertex(Vertex value) } } - internal abstract class NativeLayoutMethodEntryVertexNode : NativeLayoutSavedVertexNode + internal class NativeLayoutMethodEntryVertexNode : NativeLayoutSavedVertexNode { [Flags] public enum MethodEntryFlags @@ -102,18 +102,18 @@ public enum MethodEntryFlags protected readonly MethodDesc _method; private MethodEntryFlags _flags; private NativeLayoutTypeSignatureVertexNode _containingTypeSig; - private NativeLayoutMethodSignatureVertexNode _methodSig; private NativeLayoutTypeSignatureVertexNode[] _instantiationArgsSig; public MethodDesc Method => _method; public virtual bool IsUnboxingStub => _method.OwningType.IsValueType && !_method.Signature.IsStatic; + protected override string GetName(NodeFactory factory) => "MethodEntryVertex_" + factory.NameMangler.GetMangledMethodName(_method); + public NativeLayoutMethodEntryVertexNode(NodeFactory factory, MethodDesc method, MethodEntryFlags flags) { _method = method; _flags = flags; - _methodSig = factory.NativeLayout.MethodSignatureVertex(method.GetTypicalMethodDefinition().Signature); if ((_flags & MethodEntryFlags.CreateInstantiatedSignature) == 0) { @@ -131,7 +131,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto { DependencyList dependencies = new DependencyList(); - dependencies.Add(new DependencyListEntry(_methodSig, "NativeLayoutMethodEntryVertexNode method signature")); if ((_flags & MethodEntryFlags.CreateInstantiatedSignature) != 0) { dependencies.Add(new DependencyListEntry(context.NecessaryTypeSymbol(_method.OwningType), "NativeLayoutMethodEntryVertexNode containing type")); @@ -154,6 +153,8 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(new DependencyListEntry(methodEntryPointNode, "NativeLayoutMethodEntryVertexNode entrypoint")); } + context.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, context, _method.GetTypicalMethodDefinition()); + return dependencies; } @@ -162,8 +163,6 @@ public override Vertex WriteVertex(NodeFactory factory) Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); Vertex containingType = GetContainingTypeVertex(factory); - Vertex methodSig = _methodSig.WriteVertex(factory); - Vertex methodNameAndSig = GetNativeWriter(factory).GetMethodNameAndSigSignature(_method.Name, methodSig); Vertex[] args = null; MethodFlags flags = 0; @@ -199,12 +198,10 @@ public override Vertex WriteVertex(NodeFactory factory) IMethodNode methodEntryPointNode = GetMethodEntrypointNode(factory); fptrReferenceId = factory.MetadataManager.NativeLayoutInfo.ExternalReferences.GetIndex(methodEntryPointNode); - - if (methodEntryPointNode.Method.IsCanonicalMethod(CanonicalFormKind.Universal)) - flags |= MethodFlags.FunctionPointerIsUSG; } - return GetNativeWriter(factory).GetMethodSignature((uint)flags, fptrReferenceId, containingType, methodNameAndSig, args); + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, _method.GetTypicalMethodDefinition()); + return GetNativeWriter(factory).GetMethodSignature((uint)flags, fptrReferenceId, containingType, token, args); } private Vertex GetContainingTypeVertex(NodeFactory factory) @@ -228,85 +225,6 @@ protected virtual IMethodNode GetMethodEntrypointNode(NodeFactory factory) } } - internal sealed class NativeLayoutMethodLdTokenVertexNode : NativeLayoutMethodEntryVertexNode - { - protected override string GetName(NodeFactory factory) => "NativeLayoutMethodLdTokenVertexNode_" + factory.NameMangler.GetMangledMethodName(_method); - - public NativeLayoutMethodLdTokenVertexNode(NodeFactory factory, MethodDesc method) - : base(factory, method, method.IsRuntimeDeterminedExactMethod || method.IsGenericMethodDefinition ? 0 : MethodEntryFlags.CreateInstantiatedSignature) - { - } - - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - if (_method.IsVirtual && _method.HasInstantiation && !_method.IsGenericMethodDefinition) - { - return GetGenericVirtualMethodDependencies(context); - } - else - { - return base.GetStaticDependencies(context); - } - } - - private DependencyList GetGenericVirtualMethodDependencies(NodeFactory factory) - { - var dependencies = (DependencyList)base.GetStaticDependencies(factory); - - MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific); - - dependencies.Add(factory.GVMDependencies(canonMethod), "Potential generic virtual method call"); - - foreach (TypeDesc instArg in canonMethod.Instantiation) - { - dependencies.Add(factory.MaximallyConstructableType(instArg), "Type we need to look up for GVM dispatch"); - } - - return dependencies; - } - - public override Vertex WriteVertex(NodeFactory factory) - { - Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); - - Vertex methodEntryVertex = base.WriteVertex(factory); - return SetSavedVertex(factory.MetadataManager.NativeLayoutInfo.LdTokenInfoSection.Place(methodEntryVertex)); - } - } - - internal sealed class NativeLayoutFieldLdTokenVertexNode : NativeLayoutSavedVertexNode - { - private readonly FieldDesc _field; - private readonly NativeLayoutTypeSignatureVertexNode _containingTypeSig; - - public NativeLayoutFieldLdTokenVertexNode(NodeFactory factory, FieldDesc field) - { - _field = field; - _containingTypeSig = factory.NativeLayout.TypeSignatureVertex(field.OwningType); - } - - protected override string GetName(NodeFactory factory) => "NativeLayoutFieldLdTokenVertexNode_" + factory.NameMangler.GetMangledFieldName(_field); - - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - return new DependencyListEntry[] - { - new DependencyListEntry(_containingTypeSig, "NativeLayoutFieldLdTokenVertexNode containing type signature"), - }; - } - - public override Vertex WriteVertex(NodeFactory factory) - { - Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); - - Vertex containingType = _containingTypeSig.WriteVertex(factory); - - Vertex unplacedVertex = GetNativeWriter(factory).GetFieldSignature(containingType, _field.Name); - - return SetSavedVertex(factory.MetadataManager.NativeLayoutInfo.LdTokenInfoSection.Place(unplacedVertex)); - } - } - internal sealed class NativeLayoutMethodSignatureVertexNode : NativeLayoutVertexNode { private Internal.TypeSystem.MethodSignature _signature; @@ -360,31 +278,6 @@ public override Vertex WriteVertex(NodeFactory factory) } } - internal sealed class NativeLayoutMethodNameAndSignatureVertexNode : NativeLayoutVertexNode - { - private MethodDesc _method; - private NativeLayoutMethodSignatureVertexNode _methodSig; - - protected override string GetName(NodeFactory factory) => "NativeLayoutMethodNameAndSignatureVertexNode" + factory.NameMangler.GetMangledMethodName(_method); - - public NativeLayoutMethodNameAndSignatureVertexNode(NodeFactory factory, MethodDesc method) - { - _method = method; - _methodSig = factory.NativeLayout.MethodSignatureVertex(method.Signature); - } - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - return new DependencyListEntry[] { new DependencyListEntry(_methodSig, "NativeLayoutMethodNameAndSignatureVertexNode signature vertex") }; - } - public override Vertex WriteVertex(NodeFactory factory) - { - Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); - - Vertex methodSig = _methodSig.WriteVertex(factory); - return GetNativeWriter(factory).GetMethodNameAndSigSignature(_method.Name, methodSig); - } - } - internal abstract class NativeLayoutTypeSignatureVertexNode : NativeLayoutVertexNode { protected readonly TypeDesc _type; @@ -787,14 +680,14 @@ public NativeLayoutDictionarySignatureNode(NodeFactory nodeFactory, TypeSystemEn { if (owningMethodOrType is MethodDesc owningMethod) { - Debug.Assert(owningMethod.IsCanonicalMethod(CanonicalFormKind.Universal) || nodeFactory.LazyGenericsPolicy.UsesLazyGenerics(owningMethod)); + Debug.Assert(nodeFactory.LazyGenericsPolicy.UsesLazyGenerics(owningMethod)); Debug.Assert(owningMethod.IsCanonicalMethod(CanonicalFormKind.Any)); Debug.Assert(owningMethod.HasInstantiation); } else { TypeDesc owningType = (TypeDesc)owningMethodOrType; - Debug.Assert(owningType.IsCanonicalSubtype(CanonicalFormKind.Universal) || nodeFactory.LazyGenericsPolicy.UsesLazyGenerics(owningType)); + Debug.Assert(nodeFactory.LazyGenericsPolicy.UsesLazyGenerics(owningType)); Debug.Assert(owningType.IsCanonicalSubtype(CanonicalFormKind.Any)); } @@ -934,7 +827,7 @@ public override Vertex WriteVertex(NodeFactory factory) DictionaryLayoutNode associatedLayout = factory.GenericDictionaryLayout(_method); ICollection templateLayout = associatedLayout.GetTemplateEntries(factory); - if (!(_method.IsCanonicalMethod(CanonicalFormKind.Universal) || (factory.LazyGenericsPolicy.UsesLazyGenerics(_method))) && (templateLayout.Count > 0)) + if (!factory.LazyGenericsPolicy.UsesLazyGenerics(_method) && templateLayout.Count > 0) { List dictionaryVertices = new List(); @@ -957,7 +850,6 @@ public override Vertex WriteVertex(NodeFactory factory) public sealed class NativeLayoutTemplateTypeLayoutVertexNode : NativeLayoutSavedVertexNode { private TypeDesc _type; - private bool _isUniversalCanon; public TypeDesc CanonType => _type.ConvertToCanonForm(CanonicalFormKind.Specific); @@ -967,7 +859,6 @@ public NativeLayoutTemplateTypeLayoutVertexNode(NodeFactory factory, TypeDesc ty { Debug.Assert(type.IsCanonicalSubtype(CanonicalFormKind.Any)); Debug.Assert(type.ConvertToCanonForm(CanonicalFormKind.Specific) == type, "Assert that the canonical type passed in is in standard canonical form"); - _isUniversalCanon = type.IsCanonicalSubtype(CanonicalFormKind.Universal); _type = GetActualTemplateTypeForType(factory, type); } @@ -1045,20 +936,15 @@ public override IEnumerable GetStaticDependencies(NodeFacto } } - if (!_isUniversalCanon) + DefType closestCanonDefType = (DefType)_type.GetClosestDefType().ConvertToCanonForm(CanonicalFormKind.Specific); + if (closestCanonDefType.GCStaticFieldSize.AsInt > 0) { - DefType closestCanonDefType = (DefType)_type.GetClosestDefType().ConvertToCanonForm(CanonicalFormKind.Specific); - if (closestCanonDefType.GCStaticFieldSize.AsInt > 0) - { - BagElementKind ignored; - yield return new DependencyListEntry(GetStaticsNode(context, out ignored), "type gc static info"); - } + yield return new DependencyListEntry(GetStaticsNode(context, out _), "type gc static info"); + } - if (closestCanonDefType.ThreadGcStaticFieldSize.AsInt > 0) - { - BagElementKind ignored; - yield return new DependencyListEntry(GetThreadStaticsNode(context, out ignored), "type thread static info"); - } + if (closestCanonDefType.ThreadGcStaticFieldSize.AsInt > 0) + { + yield return new DependencyListEntry(GetThreadStaticsNode(context, out _), "type thread static info"); } if (_type.BaseType != null && !_type.BaseType.IsRuntimeDeterminedSubtype) @@ -1080,126 +966,16 @@ public override IEnumerable GetStaticDependencies(NodeFacto yield return new DependencyListEntry(dependency, "base type must be template loadable"); } } - else if (_type.IsDelegate && _isUniversalCanon) - { - // For USG delegate, we need to write the signature of the Invoke method to the native layout. - // This signature is used by the calling convention converter to marshal parameters during delegate calls. - yield return new DependencyListEntry(context.NativeLayout.MethodSignatureVertex(_type.GetMethod("Invoke", null).GetTypicalMethodDefinition().Signature), "invoke method signature"); - } - - if (_isUniversalCanon) - { - // For universal canonical template types, we need to write out field layout information so that we - // can correctly compute the type sizes for dynamically created types at runtime, and construct - // their GCDesc info - foreach (FieldDesc field in _type.GetFields()) - { - // If this field does not contribute to layout, skip - if (field.HasRva || field.IsLiteral) - { - continue; - } - - DependencyListEntry typeForFieldLayout; - - if (field.FieldType.IsGCPointer) - { - typeForFieldLayout = new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(field.Context.GetWellKnownType(WellKnownType.Object))), "universal field layout type object sized"); - } - else if (field.FieldType.IsPointer || field.FieldType.IsFunctionPointer) - { - typeForFieldLayout = new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(field.Context.GetWellKnownType(WellKnownType.IntPtr))), "universal field layout type IntPtr sized"); - } - else - { - typeForFieldLayout = new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(field.FieldType)), "universal field layout type"); - - // And ensure the type can be properly laid out - foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(field.FieldType)) - { - yield return new DependencyListEntry(dependency, "template construction dependency"); - } - } - - yield return typeForFieldLayout; - } - - // We also need to write out the signatures of interesting methods in the type's vtable, which - // will be needed by the calling convention translation logic at runtime, when the type's methods - // get invoked. This logic gathers nodes for entries *unconditionally* present. (entries may be conditionally - // present if a type has a vtable which has a size computed by usage not by IL contents) - List vtableSignatureNodeEntries = null; - int currentVTableIndexUnused = 0; - ProcessVTableEntriesForCallingConventionSignatureGeneration(context, VTableEntriesToProcess.AllOnTypesThatShouldProduceFullVTables, ref currentVTableIndexUnused, - (int vtableIndex, bool isSealedVTableSlot, MethodDesc declMethod, MethodDesc implMethod) => - { - if (implMethod.IsAbstract) - return; - - if (UniversalGenericParameterLayout.VTableMethodRequiresCallingConventionConverter(implMethod)) - { - vtableSignatureNodeEntries ??= new List(); - - vtableSignatureNodeEntries.Add(context.NativeLayout.MethodSignatureVertex(declMethod.GetTypicalMethodDefinition().Signature)); - } - }, _type, _type, _type); - - if (vtableSignatureNodeEntries != null) - { - foreach (NativeLayoutVertexNode node in vtableSignatureNodeEntries) - yield return new DependencyListEntry(node, "vtable cctor sig"); - } - } } - public override bool HasConditionalStaticDependencies => _isUniversalCanon; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) - { - List conditionalDependencies = null; - - if (_isUniversalCanon) - { - // We also need to write out the signatures of interesting methods in the type's vtable, which - // will be needed by the calling convention translation logic at runtime, when the type's methods - // get invoked. This logic gathers nodes for entries *conditionally* present. (entries may be conditionally - // present if a type has a vtable which has a size computed by usage not by IL contents) - - int currentVTableIndexUnused = 0; - ProcessVTableEntriesForCallingConventionSignatureGeneration(context, VTableEntriesToProcess.AllOnTypesThatProducePartialVTables, ref currentVTableIndexUnused, - (int vtableIndex, bool isSealedVTableSlot, MethodDesc declMethod, MethodDesc implMethod) => - { - if (implMethod.IsAbstract) - return; - - if (UniversalGenericParameterLayout.VTableMethodRequiresCallingConventionConverter(implMethod)) - { - conditionalDependencies ??= new List(); - - conditionalDependencies.Add( - new CombinedDependencyListEntry(context.NativeLayout.MethodSignatureVertex(declMethod.GetTypicalMethodDefinition().Signature), - context.VirtualMethodUse(declMethod), - "conditional vtable cctor sig")); - } - }, _type, _type, _type); - } - - if (conditionalDependencies != null) - return conditionalDependencies; - else - return Array.Empty(); - } + public override bool HasConditionalStaticDependencies => false; + public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; private static int CompareDictionaryEntries(KeyValuePair left, KeyValuePair right) { return left.Key - right.Key; } - private bool HasInstantiationDeterminedSize() - { - Debug.Assert(_isUniversalCanon); - return _type.GetClosestDefType().InstanceFieldSize.IsIndeterminate; - } - public override Vertex WriteVertex(NodeFactory factory) { Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); @@ -1209,8 +985,6 @@ public override Vertex WriteVertex(NodeFactory factory) DictionaryLayoutNode associatedLayout = factory.GenericDictionaryLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific).GetClosestDefType()); ICollection templateLayout = associatedLayout.GetTemplateEntries(factory); - NativeWriter writer = GetNativeWriter(factory); - // Interfaces if (_type.RuntimeInterfaces.Length > 0) { @@ -1225,7 +999,7 @@ public override Vertex WriteVertex(NodeFactory factory) layoutInfo.Append(BagElementKind.ImplementedInterfaces, implementedInterfaces.WriteVertex(factory)); } - if (!(_isUniversalCanon || (factory.LazyGenericsPolicy.UsesLazyGenerics(_type)) )&& (templateLayout.Count > 0)) + if (!factory.LazyGenericsPolicy.UsesLazyGenerics(_type) && templateLayout.Count > 0) { List dictionaryVertices = new List(); @@ -1248,91 +1022,33 @@ public override Vertex WriteVertex(NodeFactory factory) layoutInfo.AppendUnsigned(BagElementKind.ClassConstructorPointer, cctorStaticsIndex); } - if (!_isUniversalCanon) + DefType closestCanonDefType = (DefType)_type.GetClosestDefType().ConvertToCanonForm(CanonicalFormKind.Specific); + if (closestCanonDefType.NonGCStaticFieldSize.AsInt != 0) { - DefType closestCanonDefType = (DefType)_type.GetClosestDefType().ConvertToCanonForm(CanonicalFormKind.Specific); - if (closestCanonDefType.NonGCStaticFieldSize.AsInt != 0) - { - layoutInfo.AppendUnsigned(BagElementKind.NonGcStaticDataSize, checked((uint)closestCanonDefType.NonGCStaticFieldSize.AsInt)); - } - - if (closestCanonDefType.GCStaticFieldSize.AsInt != 0) - { - layoutInfo.AppendUnsigned(BagElementKind.GcStaticDataSize, checked((uint)closestCanonDefType.GCStaticFieldSize.AsInt)); - BagElementKind staticDescBagType; - ISymbolNode staticsDescSymbol = GetStaticsNode(factory, out staticDescBagType); - uint gcStaticsSymbolIndex = factory.MetadataManager.NativeLayoutInfo.StaticsReferences.GetIndex(staticsDescSymbol); - layoutInfo.AppendUnsigned(staticDescBagType, gcStaticsSymbolIndex); - } - - if (closestCanonDefType.ThreadGcStaticFieldSize.AsInt != 0) - { - layoutInfo.AppendUnsigned(BagElementKind.ThreadStaticDataSize, checked((uint)closestCanonDefType.ThreadGcStaticFieldSize.AsInt)); - BagElementKind threadStaticDescBagType; - ISymbolNode threadStaticsDescSymbol = GetThreadStaticsNode(factory, out threadStaticDescBagType); - uint threadStaticsSymbolIndex = factory.MetadataManager.NativeLayoutInfo.StaticsReferences.GetIndex(threadStaticsDescSymbol); - layoutInfo.AppendUnsigned(threadStaticDescBagType, threadStaticsSymbolIndex); - } + layoutInfo.AppendUnsigned(BagElementKind.NonGcStaticDataSize, checked((uint)closestCanonDefType.NonGCStaticFieldSize.AsInt)); } - if (_type.BaseType != null && _type.BaseType.IsRuntimeDeterminedSubtype) + if (closestCanonDefType.GCStaticFieldSize.AsInt != 0) { - layoutInfo.Append(BagElementKind.BaseType, factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(_type.BaseType)).WriteVertex(factory)); + layoutInfo.AppendUnsigned(BagElementKind.GcStaticDataSize, checked((uint)closestCanonDefType.GCStaticFieldSize.AsInt)); + BagElementKind staticDescBagType; + ISymbolNode staticsDescSymbol = GetStaticsNode(factory, out staticDescBagType); + uint gcStaticsSymbolIndex = factory.MetadataManager.NativeLayoutInfo.StaticsReferences.GetIndex(staticsDescSymbol); + layoutInfo.AppendUnsigned(staticDescBagType, gcStaticsSymbolIndex); } - if (_isUniversalCanon) + if (closestCanonDefType.ThreadGcStaticFieldSize.AsInt != 0) { - // For universal canonical template types, we need to write out field layout information so that we - // can correctly compute the type sizes for dynamically created types at runtime, and construct - // their GCDesc info - VertexSequence fieldsSequence = null; - - foreach (FieldDesc field in _type.GetFields()) - { - // If this field does contribute to layout, skip - if (field.HasRva || field.IsLiteral) - continue; - - // NOTE: The order and contents of the signature vertices emitted here is what we consider a field ordinal for the - // purpose of NativeLayoutFieldOffsetGenericDictionarySlotNode. - - FieldStorage fieldStorage = FieldStorage.Instance; - if (field.IsStatic) - { - if (field.IsThreadStatic) - fieldStorage = FieldStorage.TLSStatic; - else if (field.HasGCStaticBase) - fieldStorage = FieldStorage.GCStatic; - else - fieldStorage = FieldStorage.NonGCStatic; - } - - - NativeLayoutPlacedSignatureVertexNode fieldTypeSignature; - if (field.FieldType.IsGCPointer) - { - fieldTypeSignature = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(field.Context.GetWellKnownType(WellKnownType.Object))); - } - else if (field.FieldType.IsPointer || field.FieldType.IsFunctionPointer) - { - fieldTypeSignature = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(field.Context.GetWellKnownType(WellKnownType.IntPtr))); - } - else - { - fieldTypeSignature = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(field.FieldType)); - } - - Vertex staticFieldVertexData = writer.GetTuple(fieldTypeSignature.WriteVertex(factory), writer.GetUnsignedConstant((uint)fieldStorage)); - - fieldsSequence ??= new VertexSequence(); - fieldsSequence.Append(staticFieldVertexData); - } + layoutInfo.AppendUnsigned(BagElementKind.ThreadStaticDataSize, checked((uint)closestCanonDefType.ThreadGcStaticFieldSize.AsInt)); + BagElementKind threadStaticDescBagType; + ISymbolNode threadStaticsDescSymbol = GetThreadStaticsNode(factory, out threadStaticDescBagType); + uint threadStaticsSymbolIndex = factory.MetadataManager.NativeLayoutInfo.StaticsReferences.GetIndex(threadStaticsDescSymbol); + layoutInfo.AppendUnsigned(threadStaticDescBagType, threadStaticsSymbolIndex); + } - if (fieldsSequence != null) - { - Vertex placedFieldsLayout = factory.MetadataManager.NativeLayoutInfo.SignaturesSection.Place(fieldsSequence); - layoutInfo.Append(BagElementKind.FieldLayout, placedFieldsLayout); - } + if (_type.BaseType != null && _type.BaseType.IsRuntimeDeterminedSubtype) + { + layoutInfo.Append(BagElementKind.BaseType, factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(_type.BaseType)).WriteVertex(factory)); } factory.MetadataManager.NativeLayoutInfo.TemplatesSection.Place(layoutInfo); @@ -1340,13 +1056,6 @@ public override Vertex WriteVertex(NodeFactory factory) return SetSavedVertex(layoutInfo); } - private enum VTableEntriesToProcess - { - AllInVTable, - AllOnTypesThatShouldProduceFullVTables, - AllOnTypesThatProducePartialVTables - } - private static IEnumerable EnumVirtualSlotsDeclaredOnType(TypeDesc declType) { // VirtualMethodUse of Foo.Method will bring in VirtualMethodUse @@ -1370,101 +1079,6 @@ private static IEnumerable EnumVirtualSlotsDeclaredOnType(TypeDesc d yield return method; } } - - /// - /// Process the vtable entries of a type by calling operation with the vtable index, declaring method, and implementing method - /// Process them in order from 0th entry to last. - /// Skip generic virtual methods, as they are not present in the vtable itself - /// Do not adjust vtable index for generic dictionary slot - /// The vtable index is only actually valid if whichEntries is set to VTableEntriesToProcess.AllInVTable - /// - private static void ProcessVTableEntriesForCallingConventionSignatureGeneration(NodeFactory factory, VTableEntriesToProcess whichEntries, ref int currentVTableIndex, Action operation, TypeDesc implType, TypeDesc declType, TypeDesc templateType) - { - if (implType.IsInterface) - return; - - declType = declType.GetClosestDefType(); - templateType = templateType.ConvertToCanonForm(CanonicalFormKind.Specific); - - bool canShareNormalCanonicalCode = declType != declType.ConvertToCanonForm(CanonicalFormKind.Specific); - - var baseType = declType.BaseType; - if (baseType != null) - { - Debug.Assert(templateType.BaseType != null); - ProcessVTableEntriesForCallingConventionSignatureGeneration(factory, whichEntries, ref currentVTableIndex, operation, implType, baseType, templateType.BaseType); - } - - IEnumerable vtableEntriesToProcess; - - if (ConstructedEETypeNode.CreationAllowed(declType)) - { - switch (whichEntries) - { - case VTableEntriesToProcess.AllInVTable: - vtableEntriesToProcess = factory.VTable(declType).Slots; - break; - - case VTableEntriesToProcess.AllOnTypesThatShouldProduceFullVTables: - if (factory.VTable(declType).HasKnownVirtualMethodUse) - { - vtableEntriesToProcess = factory.VTable(declType).Slots; - } - else - { - vtableEntriesToProcess = Array.Empty(); - } - break; - - case VTableEntriesToProcess.AllOnTypesThatProducePartialVTables: - if (factory.VTable(declType).HasKnownVirtualMethodUse) - { - vtableEntriesToProcess = Array.Empty(); - } - else - { - vtableEntriesToProcess = EnumVirtualSlotsDeclaredOnType(declType); - } - break; - - default: - throw new Exception(); - } - } - else - { - // If allocating an object of the MethodTable isn't permitted, don't process any vtable entries. - vtableEntriesToProcess = Array.Empty(); - } - - // Dictionary slot - if (declType.HasGenericDictionarySlot() || templateType.HasGenericDictionarySlot()) - currentVTableIndex++; - - int sealedVTableSlot = 0; - DefType closestDefType = implType.GetClosestDefType(); - - // Actual vtable slots follow - foreach (MethodDesc declMethod in vtableEntriesToProcess) - { - // No generic virtual methods can appear in the vtable! - Debug.Assert(!declMethod.HasInstantiation); - - MethodDesc implMethod = closestDefType.FindVirtualFunctionTargetMethodOnObjectType(declMethod); - - if (implMethod.CanMethodBeInSealedVTable(factory) && !implType.IsArrayTypeWithoutGenericInterfaces()) - { - // Sealed vtable entries on other types in the hierarchy should not be reported (types read entries - // from their own sealed vtables, and not from the sealed vtables of base types). - if (implMethod.OwningType == closestDefType) - operation(sealedVTableSlot++, true, declMethod, implMethod); - } - else - { - operation(currentVTableIndex++, false, declMethod, implMethod); - } - } - } } public abstract class NativeLayoutGenericDictionarySlotNode : NativeLayoutVertexNode @@ -1666,29 +1280,11 @@ protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeF public sealed class NativeLayoutMethodDictionaryGenericDictionarySlotNode : NativeLayoutGenericDictionarySlotNode { private MethodDesc _method; - private WrappedMethodDictionaryVertexNode _wrappedNode; - - private sealed class WrappedMethodDictionaryVertexNode : NativeLayoutMethodEntryVertexNode - { - public WrappedMethodDictionaryVertexNode(NodeFactory factory, MethodDesc method) : - base(factory, method, default(MethodEntryFlags)) - { - } - - protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory) - { - throw new NotSupportedException(); - } - - protected sealed override string GetName(NodeFactory factory) => "WrappedMethodEntryVertexNodeForDictionarySlot_" + factory.NameMangler.GetMangledMethodName(_method); - } - public NativeLayoutMethodDictionaryGenericDictionarySlotNode(NodeFactory factory, MethodDesc method) { Debug.Assert(method.HasInstantiation); _method = method; - _wrappedNode = new WrappedMethodDictionaryVertexNode(factory, method); } protected sealed override string GetName(NodeFactory factory) => "NativeLayoutMethodDictionaryGenericDictionarySlotNode_" + factory.NameMangler.GetMangledMethodName(_method); @@ -1710,14 +1306,14 @@ public sealed override IEnumerable GetStaticDependencies(No GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); - dependencies.Add(_wrappedNode, "wrappednode"); + dependencies.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); return dependencies; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) { - return _wrappedNode.WriteVertex(factory); + return factory.NativeLayout.MethodEntry(_method).WriteVertex(factory); } } @@ -1739,7 +1335,7 @@ public sealed override IEnumerable GetStaticDependencies(No { var result = new DependencyList { - { factory.NativeLayout.FieldLdTokenVertex(_field), "Field Signature" } + { factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Owning type of field" } }; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType)) @@ -1756,8 +1352,11 @@ public sealed override IEnumerable GetStaticDependencies(No protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) { - Vertex ldToken = factory.NativeLayout.FieldLdTokenVertex(_field).WriteVertex(factory); - return GetNativeWriter(factory).GetRelativeOffsetSignature(ldToken); + Vertex owningType = factory.NativeLayout.TypeSignatureVertex(_field.OwningType).WriteVertex(factory); + Vertex fieldMetadataHandle = writer.GetUnsignedConstant( + (uint)factory.MetadataManager.GetMetadataHandleForField(factory, _field.GetTypicalFieldDefinition())); + + return writer.GetTuple(owningType, fieldMetadataHandle); } } @@ -1765,7 +1364,7 @@ public sealed class NativeLayoutMethodLdTokenGenericDictionarySlotNode : NativeL { private MethodDesc _method; - public NativeLayoutMethodLdTokenGenericDictionarySlotNode(MethodDesc method) + public NativeLayoutMethodLdTokenGenericDictionarySlotNode(NodeFactory factory, MethodDesc method) { _method = method; } @@ -1776,10 +1375,7 @@ public NativeLayoutMethodLdTokenGenericDictionarySlotNode(MethodDesc method) public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) { - var result = new DependencyList - { - { factory.NativeLayout.MethodLdTokenVertex(_method), "Method Signature" } - }; + var result = new DependencyList(); foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { @@ -1794,13 +1390,14 @@ public sealed override IEnumerable GetStaticDependencies(No factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + result.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); + return result; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) { - Vertex ldToken = factory.NativeLayout.MethodLdTokenVertex(_method).WriteVertex(factory); - return GetNativeWriter(factory).GetRelativeOffsetSignature(ldToken); + return factory.NativeLayout.MethodEntry(_method).WriteVertex(factory); } } @@ -1843,7 +1440,7 @@ public sealed override IEnumerable GetStaticDependencies(No DependencyNodeCore constrainedMethodDescriptorNode; if (_constrainedMethod.HasInstantiation) { - constrainedMethodDescriptorNode = factory.NativeLayout.MethodLdTokenVertex(_constrainedMethod); + constrainedMethodDescriptorNode = factory.NativeLayout.MethodEntry(_constrainedMethod); } else { @@ -1867,6 +1464,12 @@ public sealed override IEnumerable GetStaticDependencies(No foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constraintType)) yield return new DependencyListEntry(dependency, "template construction dependency constraintType"); + + if (_constrainedMethod.IsVirtual && _constrainedMethod.HasInstantiation) + { + MethodDesc canonMethod = _constrainedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); + yield return new DependencyListEntry(factory.GVMDependencies(canonMethod), "Generic virtual method call"); + } } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1875,9 +1478,8 @@ protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeF if (_constrainedMethod.HasInstantiation) { Debug.Assert(SignatureKind is FixupSignatureKind.GenericStaticConstrainedMethod); - Vertex constrainedMethodVertex = factory.NativeLayout.MethodLdTokenVertex(_constrainedMethod).WriteVertex(factory); - Vertex relativeOffsetVertex = GetNativeWriter(factory).GetRelativeOffsetSignature(constrainedMethodVertex); - return writer.GetTuple(constraintType, relativeOffsetVertex); + Vertex constrainedMethodVertex = factory.NativeLayout.MethodEntry(_constrainedMethod).WriteVertex(factory); + return writer.GetTuple(constraintType, constrainedMethodVertex); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs index 7fecac2a1b5723..8bed90a325e214 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs @@ -99,12 +99,9 @@ public GenericLookupResult Type(TypeDesc type) public GenericLookupResult UnwrapNullableType(TypeDesc type) { - // An actual unwrap nullable lookup is only required if the type is exactly a runtime - // determined type associated with System.__UniversalCanon itself, or if it's + // An actual unwrap nullable lookup is only required if the type is exactly // a runtime determined instance of Nullable. - if (type.IsRuntimeDeterminedType && ( - ((RuntimeDeterminedType)type).CanonicalType.IsCanonicalDefinitionType(CanonicalFormKind.Universal) || - ((RuntimeDeterminedType)type).CanonicalType.IsNullable)) + if (type.IsRuntimeDeterminedType && ((RuntimeDeterminedType)type).CanonicalType.IsNullable) return _unwrapNullableSymbols.GetOrAdd(type); else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs index e3eb154d8d0c3b..5918b71a451b34 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs @@ -37,11 +37,6 @@ private void CreateNodeCaches() return new NativeLayoutMethodSignatureVertexNode(_factory, signature); }); - _methodNameAndSignatures = new NodeCache(method => - { - return new NativeLayoutMethodNameAndSignatureVertexNode(_factory, method); - }); - _placedSignatures = new NodeCache(vertexNode => { return new NativeLayoutPlacedSignatureVertexNode(vertexNode); @@ -57,19 +52,9 @@ private void CreateNodeCaches() return new NativeLayoutPlacedVertexSequenceOfUIntVertexNode(uints); }, new UIntSequenceComparer()); - _methodLdTokenSignatures = new NodeCache(method => - { - return new NativeLayoutMethodLdTokenVertexNode(_factory, method); - }); - - _fieldLdTokenSignatures = new NodeCache(field => - { - return new NativeLayoutFieldLdTokenVertexNode(_factory, field); - }); - - _nativeLayoutSignatureNodes = new NodeCache(key => + _methodEntries = new NodeCache(method => { - return new NativeLayoutSignatureNode(key.SignatureVertex, key.Identity, key.IdentityPrefix); + return new NativeLayoutMethodEntryVertexNode(_factory, method, default); }); _templateMethodEntries = new NodeCache(method => @@ -144,7 +129,7 @@ private void CreateNodeCaches() _methodLdToken_GenericDictionarySlots = new NodeCache(method => { - return new NativeLayoutMethodLdTokenGenericDictionarySlotNode(method); + return new NativeLayoutMethodLdTokenGenericDictionarySlotNode(_factory, method); }); _dictionarySignatures = new NodeCache(owningMethodOrType => @@ -215,33 +200,6 @@ public IEnumerable TemplateConstructableTypes(TypeDesc type) } } - // Produce a set of dependencies that is necessary such that if this type - // needs to be used referenced from a NativeLayout template and any Universal Shared - // instantiation is all that is needed, that the template - // will be properly constructable. (This is done by ensuring that all - // canonical types in the deconstruction of the type are ConstructedEEType instead - // of just necessary, and that the USG variant of the template is created - // (Which is what the actual templates signatures will ensure) - public IEnumerable UniversalTemplateConstructableTypes(TypeDesc type) - { - while (type.IsParameterizedType) - { - type = ((ParameterizedType)type).ParameterType; - } - - if (type.IsSignatureVariable) - yield break; - - TypeDesc canonicalType = type.ConvertToCanonForm(CanonicalFormKind.Universal); - yield return _factory.MaximallyConstructableType(canonicalType); - - foreach (TypeDesc instantiationType in type.Instantiation) - { - foreach (var dependency in UniversalTemplateConstructableTypes(instantiationType)) - yield return dependency; - } - } - private NodeCache _typeSignatures; internal NativeLayoutTypeSignatureVertexNode TypeSignatureVertex(TypeDesc type) { @@ -260,12 +218,6 @@ internal NativeLayoutMethodSignatureVertexNode MethodSignatureVertex(MethodSigna return _methodSignatures.GetOrAdd(signature); } - private NodeCache _methodNameAndSignatures; - internal NativeLayoutMethodNameAndSignatureVertexNode MethodNameAndSignatureVertex(MethodDesc method) - { - return _methodNameAndSignatures.GetOrAdd(method); - } - private NodeCache _placedSignatures; internal NativeLayoutPlacedSignatureVertexNode PlacedSignatureVertex(NativeLayoutVertexNode vertexNode) { @@ -355,63 +307,10 @@ internal NativeLayoutPlacedVertexSequenceOfUIntVertexNode PlacedUIntVertexSequen return _placedUIntVertexSequence.GetOrAdd(uints); } - private NodeCache _methodLdTokenSignatures; - internal NativeLayoutMethodLdTokenVertexNode MethodLdTokenVertex(MethodDesc method) - { - return _methodLdTokenSignatures.GetOrAdd(method); - } - - private NodeCache _fieldLdTokenSignatures; - internal NativeLayoutFieldLdTokenVertexNode FieldLdTokenVertex(FieldDesc field) - { - return _fieldLdTokenSignatures.GetOrAdd(field); - } - - private struct NativeLayoutSignatureKey : IEquatable - { - public NativeLayoutSignatureKey(NativeLayoutSavedVertexNode signatureVertex, Utf8String identityPrefix, TypeSystemEntity identity) - { - SignatureVertex = signatureVertex; - IdentityPrefix = identityPrefix; - Identity = identity; - } - - public NativeLayoutSavedVertexNode SignatureVertex { get; } - public Utf8String IdentityPrefix { get; } - public TypeSystemEntity Identity { get; } - - public override bool Equals(object obj) - { - if (!(obj is NativeLayoutSignatureKey)) - return false; - - return Equals((NativeLayoutSignatureKey)obj); - } - - public override int GetHashCode() - { - return SignatureVertex.GetHashCode(); - } - - public bool Equals(NativeLayoutSignatureKey other) - { - if (SignatureVertex != other.SignatureVertex) - return false; - - if (!IdentityPrefix.Equals(other.IdentityPrefix)) - return false; - - if (Identity != other.Identity) - return false; - - return true; - } - } - - private NodeCache _nativeLayoutSignatureNodes; - public NativeLayoutSignatureNode NativeLayoutSignature(NativeLayoutSavedVertexNode signature, Utf8String identityPrefix, TypeSystemEntity identity) + private NodeCache _methodEntries; + internal NativeLayoutMethodEntryVertexNode MethodEntry(MethodDesc method) { - return _nativeLayoutSignatureNodes.GetOrAdd(new NativeLayoutSignatureKey(signature, identityPrefix, identity)); + return _methodEntries.GetOrAdd(method); } private NodeCache _templateMethodEntries; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index f7ef925ea3f6f9..9b73ea95894a3a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -541,7 +541,12 @@ private void CreateNodeCaches() _methodsWithMetadata = new NodeCache(method => { - return new MethodMetadataNode(method); + return new MethodMetadataNode(method, isMinimal: false); + }); + + _methodsWithLimitedMetadata = new NodeCache(method => + { + return new MethodMetadataNode(method, isMinimal: true); }); _fieldsWithMetadata = new NodeCache(field => @@ -564,6 +569,11 @@ private void CreateNodeCaches() return new CustomAttributeMetadataNode(ca); }); + _parametersWithMetadata = new NodeCache(p => + { + return new MethodParameterMetadataNode(p); + }); + _genericDictionaryLayouts = new NodeCache(_dictionaryLayoutProvider.GetLayout); _stringAllocators = new NodeCache(constructor => @@ -1331,6 +1341,16 @@ internal MethodMetadataNode MethodMetadata(MethodDesc method) return _methodsWithMetadata.GetOrAdd(method); } + private NodeCache _methodsWithLimitedMetadata; + + internal MethodMetadataNode LimitedMethodMetadata(MethodDesc method) + { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); + return _methodsWithLimitedMetadata.GetOrAdd(method); + } + private NodeCache _fieldsWithMetadata; internal FieldMetadataNode FieldMetadata(FieldDesc field) @@ -1367,6 +1387,16 @@ internal CustomAttributeMetadataNode CustomAttributeMetadata(ReflectableCustomAt return _customAttributesWithMetadata.GetOrAdd(ca); } + private NodeCache _parametersWithMetadata; + + internal MethodParameterMetadataNode MethodParameterMetadata(ReflectableParameter ca) + { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); + return _parametersWithMetadata.GetOrAdd(ca); + } + private NodeCache _frozenStringNodes; public FrozenStringNode SerializedStringObject(string data) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs index 09835d6ba6077f..d8001f0f248250 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs @@ -77,15 +77,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) flags = FieldTableFlags.Instance | FieldTableFlags.FieldOffsetEncodedDirectly; } - if (fieldMapping.MetadataHandle != 0) - flags |= FieldTableFlags.HasMetadataHandle; - if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) flags |= FieldTableFlags.IsAnyCanonicalEntry; - if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Universal)) - flags |= FieldTableFlags.IsUniversalCanonicalEntry; - if (field.IsInitOnly) flags |= FieldTableFlags.IsInitOnly; @@ -98,78 +92,62 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(declaringTypeId)); - if ((flags & FieldTableFlags.HasMetadataHandle) != 0) - { - // Only store the offset portion of the metadata handle to get better integer compression - vertex = writer.GetTuple(vertex, - writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask))); - } - else - { - // No metadata handle means we need to store name - vertex = writer.GetTuple(vertex, - writer.GetStringConstant(field.Name)); - } + // Only store the offset portion of the metadata handle to get better integer compression + vertex = writer.GetTuple(vertex, + writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask))); - if ((flags & FieldTableFlags.IsUniversalCanonicalEntry) != 0) - { - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(checked((uint)field.GetFieldOrdinal()))); - } - else + switch (flags & FieldTableFlags.StorageClass) { - switch (flags & FieldTableFlags.StorageClass) - { - case FieldTableFlags.ThreadStatic: - case FieldTableFlags.GCStatic: - case FieldTableFlags.NonGCStatic: + case FieldTableFlags.ThreadStatic: + case FieldTableFlags.GCStatic: + case FieldTableFlags.NonGCStatic: + { + uint fieldOffset = (uint)field.Offset.AsInt; + if (field.IsThreadStatic && field.OwningType is MetadataType mt) + { + fieldOffset += factory.ThreadStaticBaseOffset(mt); + } + + if (field.OwningType.HasInstantiation) + { + vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(fieldOffset)); + } + else { - uint fieldOffset = (uint)field.Offset.AsInt; - if (field.IsThreadStatic && field.OwningType is MetadataType mt) + MetadataType metadataType = (MetadataType)field.OwningType; + + ISymbolNode staticsNode; + if (field.IsThreadStatic) + { + staticsNode = factory.TypeThreadStaticIndex(metadataType); + } + else if (field.HasGCStaticBase) + { + staticsNode = factory.TypeGCStaticsSymbol(metadataType); + } + else { - fieldOffset += factory.ThreadStaticBaseOffset(mt); + staticsNode = factory.TypeNonGCStaticsSymbol(metadataType); } - if (field.OwningType.HasInstantiation) + if (!field.IsThreadStatic && !field.HasGCStaticBase) { - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(fieldOffset)); + uint index = _externalReferences.GetIndex(staticsNode, (int)fieldOffset); + vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index)); } else { - MetadataType metadataType = (MetadataType)field.OwningType; - - ISymbolNode staticsNode; - if (field.IsThreadStatic) - { - staticsNode = factory.TypeThreadStaticIndex(metadataType); - } - else if (field.HasGCStaticBase) - { - staticsNode = factory.TypeGCStaticsSymbol(metadataType); - } - else - { - staticsNode = factory.TypeNonGCStaticsSymbol(metadataType); - } - - if (!field.IsThreadStatic && !field.HasGCStaticBase) - { - uint index = _externalReferences.GetIndex(staticsNode, (int)fieldOffset); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index)); - } - else - { - uint index = _externalReferences.GetIndex(staticsNode); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index)); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(fieldOffset)); - } + uint index = _externalReferences.GetIndex(staticsNode); + vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index)); + vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(fieldOffset)); } } - break; + } + break; - case FieldTableFlags.Instance: - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)field.Offset.AsInt)); - break; - } + case FieldTableFlags.Instance: + vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)field.Offset.AsInt)); + break; } int hashCode = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific).GetHashCode(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs index f0786d96ac9f71..82a7aef31d87e7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -68,28 +68,11 @@ public static void AddDependenciesDueToReflectability(ref DependencyList depende dependencies.Add(factory.AddressTakenMethodEntrypoint(method), "Body of a reflectable method"); } - // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference - // Use a name/sig reference instead. - if (!factory.MetadataManager.WillUseMetadataTokenToReferenceMethod(method)) - { - dependencies.Add(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())), - "Non metadata-local method reference"); - } - if (method.HasInstantiation) { - if (method.IsCanonicalMethod(CanonicalFormKind.Any)) - { - dependencies.Add(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())), - "Signature of canonical method"); - } - - if (!method.IsCanonicalMethod(CanonicalFormKind.Universal)) + foreach (var instArg in method.Instantiation) { - foreach (var instArg in method.Instantiation) - { - dependencies.Add(factory.NecessaryTypeSymbol(instArg), "Reflectable generic method inst arg"); - } + dependencies.Add(factory.NecessaryTypeSymbol(instArg), "Reflectable generic method inst arg"); } } @@ -180,15 +163,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (!method.IsAbstract) flags |= InvokeTableFlags.HasEntrypoint; - if (mappingEntry.MetadataHandle != 0) - flags |= InvokeTableFlags.HasMetadataHandle; - if (!factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method)) flags |= InvokeTableFlags.NeedsParameterInterpretation; - if (method.IsCanonicalMethod(CanonicalFormKind.Universal)) - flags |= InvokeTableFlags.IsUniversalCanonicalEntry; - // TODO: native signature for P/Invokes and UnmanagedCallersOnly methods if (method.IsRawPInvoke() || method.IsUnmanagedCallersOnly) continue; @@ -198,17 +175,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) Vertex vertex = writer.GetUnsignedConstant((uint)flags); - if ((flags & InvokeTableFlags.HasMetadataHandle) != 0) - { - // Only store the offset portion of the metadata handle to get better integer compression - vertex = writer.GetTuple(vertex, - writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask))); - } - else - { - var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); - } + // Only store the offset portion of the metadata handle to get better integer compression + vertex = writer.GetTuple(vertex, + writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask))); // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted. IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType); @@ -232,22 +201,13 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if ((flags & InvokeTableFlags.IsGenericMethod) != 0) { - if ((flags & InvokeTableFlags.RequiresInstArg) != 0) - { - var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSigGenericMethod.SavedVertex.VertexOffset)); - } - - if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) == 0) + VertexSequence args = new VertexSequence(); + for (int i = 0; i < method.Instantiation.Length; i++) { - VertexSequence args = new VertexSequence(); - for (int i = 0; i < method.Instantiation.Length; i++) - { - uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i])); - args.Append(writer.GetUnsignedConstant(argId)); - } - vertex = writer.GetTuple(vertex, args); + uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i])); + args.Append(writer.GetUnsignedConstant(argId)); } + vertex = writer.GetTuple(vertex, args); } int hashCode = method.OwningType.GetHashCode(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs index fa6bd51940aacc..cdce445f8264fd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs @@ -88,10 +88,6 @@ public static void GetVirtualInvokeMapDependencies(ref DependencyList dependenci factory.NecessaryTypeSymbol(method.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific)), "Reflection virtual invoke owning type"); - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - dependencies.Add(placedNameAndSig, "Reflection virtual invoke method signature"); - if (!method.HasInstantiation) { MethodDesc slotDefiningMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method); @@ -162,24 +158,22 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // Grammar of an entry in the hash table: // Virtual Method uses a normal slot - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1) + slot + // TypeKey + MethodHandle + (NumberOfStepsUpParentHierarchyToType << 1) + slot // OR // Generic Virtual Method - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1 + 1) + // TypeKey + MethodHandle + (NumberOfStepsUpParentHierarchyToType << 1 + 1) int parentHierarchyDistance; MethodDesc declaringMethodForSlot = GetDeclaringVirtualMethodAndHierarchyDistance(method, out parentHierarchyDistance); ISymbolNode containingTypeKeyNode = factory.NecessaryTypeSymbol(containingTypeKey); - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, method.GetTypicalMethodDefinition()); Vertex vertex; if (method.HasInstantiation) { vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeKeyNode)), - writer.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset), + writer.GetUnsignedConstant((uint)token), writer.GetUnsignedConstant(((uint)parentHierarchyDistance << 1) + VirtualInvokeTableEntry.GenericVirtualMethod)); } else @@ -190,7 +184,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeKeyNode)), - writer.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset)); + writer.GetUnsignedConstant((uint)token)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)parentHierarchyDistance << 1), diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs index ddb94c51c9df48..150d4d6a0e9a32 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs @@ -38,8 +38,6 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) return ObjectNodeSection.DataSection; } - private static readonly Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RFHSignature_"); - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { DependencyList result = null; @@ -54,8 +52,10 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); - NativeLayoutFieldLdTokenVertexNode ldtokenSigNode = factory.NativeLayout.FieldLdTokenVertex(_targetField); - objData.EmitPointerReloc(factory.NativeLayout.NativeLayoutSignature(ldtokenSigNode, s_NativeLayoutSignaturePrefix, _targetField)); + int handle = relocsOnly ? 0 : factory.MetadataManager.GetMetadataHandleForField(factory, _targetField.GetTypicalFieldDefinition()); + + objData.EmitPointerReloc(factory.MaximallyConstructableType(_targetField.OwningType)); + objData.EmitInt(handle); return objData.ToObjectData(); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs index 6e20a964a64fcb..7f5f3035ccbc70 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -66,8 +66,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact return dependencies; } - private static readonly Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RMHSignature_"); - protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); @@ -75,8 +73,21 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); - NativeLayoutMethodLdTokenVertexNode ldtokenSigNode = factory.NativeLayout.MethodLdTokenVertex(_targetMethod); - objData.EmitPointerReloc(factory.NativeLayout.NativeLayoutSignature(ldtokenSigNode, s_NativeLayoutSignaturePrefix, _targetMethod)); + int handle = relocsOnly ? 0 : factory.MetadataManager.GetMetadataHandleForMethod(factory, _targetMethod.GetTypicalMethodDefinition()); + + objData.EmitPointerReloc(factory.MaximallyConstructableType(_targetMethod.OwningType)); + objData.EmitInt(handle); + + if (_targetMethod != _targetMethod.GetMethodDefinition()) + { + objData.EmitInt(_targetMethod.Instantiation.Length); + foreach (TypeDesc instParam in _targetMethod.Instantiation) + objData.EmitPointerReloc(factory.NecessaryTypeSymbol(instParam)); + } + else + { + objData.EmitInt(0); + } return objData.ToObjectData(); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs index b5bb5760b5e29f..e3a0b4d38ab17e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs @@ -70,8 +70,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto foreach (var entry in ScanForInterfaceGenericVirtualMethodEntries()) InterfaceGenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref _staticDependencies, context, entry.CallingMethod, entry.ImplementationType, entry.ImplementationMethod); - - Debug.Assert(_staticDependencies.Count > 0); } return _staticDependencies; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs index 9050cf8c097fe9..d1a4a0dc9b73bb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs @@ -242,12 +242,6 @@ public override IEnumerable GetConditionalStaticDep factory.VirtualMethodUse(method), factory.VirtualMethodUse(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Canonically equivalent virtual method use"); - - if (defType.Context.SupportsUniversalCanon) - yield return new CombinedDependencyListEntry( - factory.VirtualMethodUse(method), - factory.VirtualMethodUse(method.GetCanonMethodTarget(CanonicalFormKind.Universal)), - "Universal Canonically equivalent virtual method use"); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs index ca716e795ccb14..6cf9cde5167067 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs @@ -50,7 +50,7 @@ protected override void OnMarked(NodeFactory factory) lazyVTableSlice?.AddEntry(_decl); } - public override bool HasConditionalStaticDependencies => _decl.Context.SupportsUniversalCanon && _decl.OwningType.HasInstantiation && !_decl.OwningType.IsInterface; + public override bool HasConditionalStaticDependencies => false; public override bool HasDynamicDependencies => false; public override bool InterestingForDynamicDependencyAnalysis => false; @@ -76,32 +76,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto return dependencies; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) - { - Debug.Assert(_decl.OwningType.HasInstantiation); - Debug.Assert(!_decl.OwningType.IsInterface); - Debug.Assert(factory.TypeSystemContext.SupportsUniversalCanon); - - DefType universalCanonicalOwningType = (DefType)_decl.OwningType.ConvertToCanonForm(CanonicalFormKind.Universal); - Debug.Assert(universalCanonicalOwningType.IsCanonicalSubtype(CanonicalFormKind.Universal)); - - if (!factory.VTable(universalCanonicalOwningType).HasKnownVirtualMethodUse) - { - // This code ensures that in cases where we don't structurally force all universal canonical instantiations - // to have full vtables, that we ensure that all vtables are equivalently shaped between universal and non-universal types - return new CombinedDependencyListEntry[] { - new CombinedDependencyListEntry( - factory.VirtualMethodUse(_decl.GetCanonMethodTarget(CanonicalFormKind.Universal)), - factory.NativeLayout.TemplateTypeLayout(universalCanonicalOwningType), - "If universal canon instantiation of method exists, ensure that the universal canonical type has the right set of dependencies") - }; - } - else - { - return Array.Empty(); - } - } - + public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs index d0773ba4806468..efad0516f5a354 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs @@ -636,8 +636,7 @@ private static bool CanAssumeWholeProgramViewOnTypeUse(NodeFactory factory, Type } if (baseType.IsCanonicalSubtype(CanonicalFormKind.Any) - || baseType.ConvertToCanonForm(CanonicalFormKind.Specific) != baseType - || baseType.Context.SupportsUniversalCanon) + || baseType.ConvertToCanonForm(CanonicalFormKind.Specific) != baseType) { // If the interface has a canonical form, we might not have a full view of all implementers. // E.g. if we have: diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 53a722cdb663f0..1476d46cbd10e0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -48,7 +48,9 @@ public abstract class MetadataManager : ICompilationRootProvider private byte[] _metadataBlob; private List> _typeMappings; private List> _fieldMappings; + private Dictionary _fieldHandleMap; private List> _methodMappings; + private Dictionary _methodHandleMap; private List _stackTraceMappings; protected readonly string _metadataLogFile; protected readonly StackTraceEmissionPolicy _stackTraceEmissionPolicy; @@ -442,16 +444,6 @@ public bool ShouldMethodBeInInvokeMap(MethodDesc method) public void GetDependenciesDueToGenericDictionary(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { - MetadataCategory category = GetMetadataCategory(method.GetCanonMethodTarget(CanonicalFormKind.Specific)); - - if ((category & MetadataCategory.RuntimeMapping) != 0) - { - // If the method is visible from reflection, we need to keep track of this statically generated - // dictionary to make sure MakeGenericMethod works even without a type loader template - dependencies ??= new DependencyList(); - dependencies.Add(factory.GenericMethodsHashtableEntry(method), "Reflection visible dictionary"); - } - if (method.Signature.IsStatic && method.IsSynchronized) { dependencies ??= new DependencyList(); @@ -536,6 +528,11 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency // and property setters) } + public virtual void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + { + // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata + } + protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) { // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata @@ -691,7 +688,7 @@ protected void EnsureMetadataGenerated(NodeFactory factory) if (_metadataBlob != null) return; - ComputeMetadata(factory, out _metadataBlob, out _typeMappings, out _methodMappings, out _fieldMappings, out _stackTraceMappings); + ComputeMetadata(factory, out _metadataBlob, out _typeMappings, out _methodMappings, out _methodHandleMap, out _fieldMappings, out _fieldHandleMap, out _stackTraceMappings); } void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) @@ -704,7 +701,9 @@ protected abstract void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping); protected void ComputeMetadata( @@ -713,7 +712,9 @@ protected void ComputeMetadata( out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping) where TPolicy : struct, IMetadataPolicy { var transformed = MetadataTransform.Run(policy, GetCompilationModulesWithMetadata()); @@ -785,7 +786,9 @@ protected void ComputeMetadata( typeMappings = new List>(); methodMappings = new List>(); + methodMetadataMappings = new Dictionary(); fieldMappings = new List>(); + fieldMetadataMappings = new Dictionary(); stackTraceMapping = new List(); // Generate type definition mappings @@ -805,8 +808,15 @@ record ??= transformed.GetTransformedTypeReference(definition); typeMappings.Add(new MetadataMapping(definition, writer.GetRecordHandle(record))); } + foreach (var methodMapping in transformed.GetTransformedMethodDefinitions()) + methodMetadataMappings[methodMapping.Key] = writer.GetRecordHandle(methodMapping.Value); + foreach (var method in GetReflectableMethods()) { + MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); + if (record == null) + continue; + if (method.IsGenericMethodDefinition || method.OwningType.IsGenericDefinition) { // Generic definitions don't have runtime artifacts we would need to map to. @@ -825,15 +835,18 @@ record ??= transformed.GetTransformedTypeReference(definition); if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0) continue; - MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); - - if (record != null) - methodMappings.Add(new MetadataMapping(method, writer.GetRecordHandle(record))); + methodMappings.Add(new MetadataMapping(method, writer.GetRecordHandle(record))); } HashSet canonicalFields = new HashSet(); foreach (var field in GetFieldsWithRuntimeMapping()) { + Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); + if (record == null) + continue; + + fieldMetadataMappings[field.GetTypicalFieldDefinition()] = writer.GetRecordHandle(record); + FieldDesc fieldToAdd = field; TypeDesc canonOwningType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonOwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) @@ -847,9 +860,7 @@ record ??= transformed.GetTransformedTypeReference(definition); fieldToAdd = canonField; } - Field record = transformed.GetTransformedFieldDefinition(fieldToAdd.GetTypicalFieldDefinition()); - if (record != null) - fieldMappings.Add(new MetadataMapping(fieldToAdd, writer.GetRecordHandle(record))); + fieldMappings.Add(new MetadataMapping(fieldToAdd, writer.GetRecordHandle(record))); } // Generate stack trace metadata mapping @@ -949,12 +960,40 @@ public IEnumerable> GetMethodMapping(NodeFactory fac return _methodMappings; } + public int GetMetadataHandleForMethod(NodeFactory factory, MethodDesc method) + { + if (!CanGenerateMetadata(method)) + { + // We can end up here with reflection disabled or multifile compilation. + // If we ever productize either, we'll need to do something different. + // Scenarios that currently need this won't work in these modes. + return 0; + } + + EnsureMetadataGenerated(factory); + return _methodHandleMap[method]; + } + public IEnumerable> GetFieldMapping(NodeFactory factory) { EnsureMetadataGenerated(factory); return _fieldMappings; } + public int GetMetadataHandleForField(NodeFactory factory, FieldDesc field) + { + if (!CanGenerateMetadata(field)) + { + // We can end up here with reflection disabled or multifile compilation. + // If we ever productize either, we'll need to do something different. + // Scenarios that currently need this won't work in these modes. + return 0; + } + + EnsureMetadataGenerated(factory); + return _fieldHandleMap[field]; + } + public IEnumerable GetStackTraceMapping(NodeFactory factory) { EnsureMetadataGenerated(factory); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UniversalGenericsRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UniversalGenericsRootProvider.cs deleted file mode 100644 index 19494506f7be30..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UniversalGenericsRootProvider.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Internal.TypeSystem; - -namespace ILCompiler -{ - /// - /// Compilation roots necessary to enable universal shared generics thats - /// are not encompassed in other root providers - /// - public class UniversalGenericsRootProvider : ICompilationRootProvider - { - private TypeSystemContext _context; - - public UniversalGenericsRootProvider(TypeSystemContext context) - { - _context = context; - } - - public void AddCompilationRoots(IRootingServiceProvider rootProvider) - { - if (_context.SupportsUniversalCanon) - rootProvider.AddCompilationRoot(_context.UniversalCanonType.MakeArrayType(), "Universal generic array support"); - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index fd0c4e025d65e1..799792ea28abf0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -56,6 +56,7 @@ private static (string AttributeName, DiagnosticId Id)[] _requiresAttributeMisma private readonly List _typesWithMetadata = new List(); private readonly List _fieldsWithRuntimeMapping = new List(); private readonly List _customAttributesWithMetadata = new List(); + private readonly List _parametersWithMetadata = new List(); internal IReadOnlyDictionary FeatureSwitches { get; } @@ -147,6 +148,12 @@ protected override void Graph_NewMarkedNode(DependencyNodeCore obj) _customAttributesWithMetadata.Add(customAttributeMetadataNode.CustomAttribute); } + var parameterMetadataNode = obj as MethodParameterMetadataNode; + if (parameterMetadataNode != null) + { + _parametersWithMetadata.Add(parameterMetadataNode.Parameter); + } + var reflectedFieldNode = obj as ReflectedFieldNode; if (reflectedFieldNode != null) { @@ -221,11 +228,13 @@ protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping) { ComputeMetadata(new GeneratedTypesAndCodeMetadataPolicy(_blockingPolicy, factory), - factory, out metadataBlob, out typeMappings, out methodMappings, out fieldMappings, out stackTraceMapping); + factory, out metadataBlob, out typeMappings, out methodMappings, out methodMetadataMappings, out fieldMappings, out fieldMetadataMappings, out stackTraceMapping); } protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) @@ -234,6 +243,21 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method"); } + public override void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + { + if (CanGenerateMetadata(method)) + { + dependencies ??= new DependencyList(); + dependencies.Add(factory.LimitedMethodMetadata(method.GetTypicalMethodDefinition()), "Method referenced from native layout"); + } + else + { + // We can end up here with reflection disabled or multifile compilation. + // If we ever productize either, we'll need to do something different. + // Scenarios that currently need this won't work in these modes. + } + } + protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) { dependencies ??= new DependencyList(); @@ -918,7 +942,7 @@ public MetadataManager ToAnalysisBasedMetadataManager() return new AnalysisBasedMetadataManager( _typeSystemContext, _blockingPolicy, _resourceBlockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, _dynamicInvokeThunkGenerationPolicy, FlowAnnotations, _modulesWithMetadata, _typesWithForcedEEType, reflectableTypes.ToEnumerable(), reflectableMethods.ToEnumerable(), - reflectableFields.ToEnumerable(), _customAttributesWithMetadata, _options); + reflectableFields.ToEnumerable(), _customAttributesWithMetadata, _parametersWithMetadata, _options); } private void AddDataflowDependency(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, string reason) @@ -1018,7 +1042,7 @@ public bool GeneratesMetadata(FieldDesc fieldDef) public bool GeneratesMetadata(MethodDesc methodDef) { - return _factory.MethodMetadata(methodDef).Marked; + return _factory.MethodMetadata(methodDef).Marked || _factory.LimitedMethodMetadata(methodDef).Marked; } public bool GeneratesMetadata(MetadataType typeDef) @@ -1031,6 +1055,11 @@ public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle) return _factory.CustomAttributeMetadata(new ReflectableCustomAttribute(module, caHandle)).Marked; } + public bool GeneratesMetadata(EcmaModule module, ParameterHandle paramHandle) + { + return _factory.MethodParameterMetadata(new ReflectableParameter(module, paramHandle)).Marked; + } + public bool GeneratesMetadata(EcmaModule module, ExportedTypeHandle exportedTypeHandle) { // Generate the forwarder only if we generated the target type. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 954ae4124058ac..62e2c202d89a64 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -215,9 +215,6 @@ Common\StackTraceData.cs - - Common\UniversalGenericParameterLayout.cs - Common\Utf8String.cs @@ -426,6 +423,7 @@ + @@ -502,7 +500,6 @@ - @@ -655,7 +652,6 @@ - @@ -688,9 +684,6 @@ Common\ArrayBuilder.cs - - Common\CanonTypeKind.cs - Common\MethodTable.Constants.cs diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs index 02d48c7a810cfd..492bcb1f82db2c 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs @@ -15,6 +15,8 @@ public IReadOnlyCollection Records get { return _map.Values; } } + public IEnumerable> Entries => _map; + public EntityMap(IEqualityComparer comparer) { _map = new Dictionary(comparer); diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs index 408a3be6ded51f..c79bc3fe477aec 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs @@ -43,6 +43,12 @@ public interface IMetadataPolicy /// bool GeneratesMetadata(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandle customAttribute); + /// + /// Returns true if the parameter should generate metadata. + /// If false, the parameter is not generated. + /// + bool GeneratesMetadata(Cts.Ecma.EcmaModule module, Ecma.ParameterHandle parameter); + /// /// Returns true if an exported type entry should generate metadata. /// diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs index d64c6fd67dadb3..04e95b91beab91 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs @@ -97,6 +97,13 @@ public Method GetTransformedMethodDefinition(Cts.MethodDesc method) return rec as Method; } + public IEnumerable> GetTransformedMethodDefinitions() + { + foreach (KeyValuePair entry in _transform._methods.Entries) + if (entry.Value is Method m) + yield return new KeyValuePair(entry.Key, m); + } + /// /// Attempts to retrieve a record corresponding to the specified /// . Returns null if not found. diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs index 02c35466167aad..98845f5b6b2d43 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs @@ -84,6 +84,9 @@ private void InitializeMethodDefinition(Cts.MethodDesc entity, Method record) record.Parameters.Capacity = paramHandles.Count; foreach (var paramHandle in paramHandles) { + if (!_policy.GeneratesMetadata(ecmaEntity.Module, paramHandle)) + continue; + Ecma.Parameter param = reader.GetParameter(paramHandle); Parameter paramRecord = new Parameter { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 0621f2bcd1eb23..8de9294e68f2c6 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -1240,11 +1240,6 @@ const char* CorJitFlagToString(CORJIT_FLAGS::CorJitFlag flag) 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 ""; } diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp index 4bc2fb0784aa88..0b02e4b8afe9e5 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp @@ -61,7 +61,7 @@ JitInstance* JitInstance::InitJit(char* nameOfJit, if (st1 != nullptr) st1->Start(); - HRESULT hr = jit->StartUp(nameOfJit, false, breakOnAssert, firstContext); + HRESULT hr = jit->StartUp(nameOfJit, breakOnAssert, firstContext); if (st1 != nullptr) st1->Stop(); if (hr != S_OK) @@ -75,7 +75,7 @@ JitInstance* JitInstance::InitJit(char* nameOfJit, return jit; } -HRESULT JitInstance::StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBreakorAV, MethodContext* firstContext) +HRESULT JitInstance::StartUp(char* PathToJit, bool breakOnDebugBreakorAV, MethodContext* firstContext) { // startup jit DWORD dwRetVal = 0; @@ -85,8 +85,6 @@ HRESULT JitInstance::StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBre SetBreakOnDebugBreakOrAV(breakOnDebugBreakorAV); char pFullPathName[MAX_PATH]; - char lpTempPathBuffer[MAX_PATH]; - char szTempFileName[MAX_PATH]; // find the full jit path dwRetVal = ::GetFullPathNameA(PathToJit, MAX_PATH, pFullPathName, nullptr); @@ -96,67 +94,15 @@ HRESULT JitInstance::StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBre return E_FAIL; } - // Store the full path to the jit - PathToOriginalJit = (char*)malloc(MAX_PATH); - if (PathToOriginalJit == nullptr) - { - LogError("1st HeapAlloc failed (0x%08x)", ::GetLastError()); - return E_FAIL; - } - ::strcpy_s(PathToOriginalJit, MAX_PATH, pFullPathName); - - if (copyJit) - { - // Get a temp file location - dwRetVal = ::GetTempPathA(MAX_PATH, lpTempPathBuffer); - if (dwRetVal == 0) - { - LogError("GetTempPath failed (0x%08x)", ::GetLastError()); - return E_FAIL; - } - if (dwRetVal > MAX_PATH) - { - LogError("GetTempPath returned a path that was larger than MAX_PATH"); - return E_FAIL; - } - // Get a temp filename - uRetVal = ::GetTempFileNameA(lpTempPathBuffer, "Jit", 0, szTempFileName); - if (uRetVal == 0) - { - LogError("GetTempFileName failed (0x%08x)", ::GetLastError()); - return E_FAIL; - } - dwRetVal = (DWORD)::strlen(szTempFileName); - - // Store the full path to the temp jit - PathToTempJit = (char*)malloc(MAX_PATH); - if (PathToTempJit == nullptr) - { - LogError("2nd HeapAlloc failed 0x%08x)", ::GetLastError()); - return E_FAIL; - } - ::strcpy_s(PathToTempJit, MAX_PATH, szTempFileName); - - // Copy Temp File - bRetVal = ::CopyFileA(PathToOriginalJit, PathToTempJit, FALSE); - if (bRetVal == FALSE) - { - LogError("CopyFile failed (0x%08x)", ::GetLastError()); - return E_FAIL; - } - } - else - PathToTempJit = PathToOriginalJit; - #ifndef TARGET_UNIX // No file version APIs in the PAL // Do a quick version check DWORD dwHandle = 0; - DWORD fviSize = GetFileVersionInfoSizeA(PathToTempJit, &dwHandle); + DWORD fviSize = GetFileVersionInfoSizeA(pFullPathName, &dwHandle); if ((fviSize != 0) && (dwHandle == 0)) { unsigned char* fviData = new unsigned char[fviSize]; - if (GetFileVersionInfoA(PathToTempJit, dwHandle, fviSize, fviData)) + if (GetFileVersionInfoA(pFullPathName, dwHandle, fviSize, fviData)) { UINT size = 0; VS_FIXEDFILEINFO* verInfo = nullptr; @@ -165,7 +111,7 @@ HRESULT JitInstance::StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBre if (size) { if (verInfo->dwSignature == 0xfeef04bd) - LogDebug("'%s' is version %u.%u.%u.%u", PathToTempJit, (verInfo->dwFileVersionMS) >> 16, + LogDebug("'%s' is version %u.%u.%u.%u", pFullPathName, (verInfo->dwFileVersionMS) >> 16, (verInfo->dwFileVersionMS) & 0xFFFF, (verInfo->dwFileVersionLS) >> 16, (verInfo->dwFileVersionLS) & 0xFFFF); } @@ -176,7 +122,7 @@ HRESULT JitInstance::StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBre #endif // !TARGET_UNIX // Load Library - hLib = ::LoadLibraryExA(PathToTempJit, NULL, 0); + hLib = ::LoadLibraryExA(pFullPathName, NULL, 0); if (hLib == 0) { LogError("LoadLibrary failed (0x%08x)", ::GetLastError()); @@ -240,51 +186,6 @@ HRESULT JitInstance::StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBre return S_OK; } -bool JitInstance::reLoad(MethodContext* firstContext) -{ - FreeLibrary(hLib); - - // Load Library - hLib = ::LoadLibraryExA(PathToTempJit, NULL, 0); - if (hLib == 0) - { - LogError("LoadLibrary failed (0x%08x)", ::GetLastError()); - return false; - } - - // get entry points - pngetJit = (PgetJit)::GetProcAddress(hLib, "getJit"); - if (pngetJit == 0) - { - LogError("GetProcAddress 'getJit' failed (0x%08x)", ::GetLastError()); - return false; - } - pnjitStartup = (PjitStartup)::GetProcAddress(hLib, "jitStartup"); - - // Setup ICorJitHost and call jitStartup if necessary - if (pnjitStartup != nullptr) - { - mc = firstContext; - jitHost = new JitHost(*this); - if (!callJitStartup(jitHost)) - { - LogError("jitStartup failed"); - return false; - } - } - - pJitInstance = pngetJit(); - if (pJitInstance == nullptr) - { - LogError("pngetJit gave us null"); - return false; - } - - icji = InitICorJitInfo(this); - - return true; -} - #undef DLLEXPORT #ifdef _MSC_VER #define DLLEXPORT __declspec(dllexport) diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.h b/src/coreclr/tools/superpmi/superpmi/jitinstance.h index 492c29bf8e4dbd..164147a100c0d6 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.h +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.h @@ -27,8 +27,6 @@ struct ReplayResults class JitInstance { private: - char* PathToOriginalJit; - char* PathToTempJit; HMODULE hLib; PgetJit pngetJit; PjitStartup pnjitStartup; @@ -62,8 +60,7 @@ class JitInstance LightWeightMap* forceOptions, LightWeightMap* options); - HRESULT StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBreakorAV, MethodContext* firstContext); - bool reLoad(MethodContext* firstContext); + HRESULT StartUp(char* PathToJit, bool breakOnDebugBreakorAV, MethodContext* firstContext); bool callJitStartup(ICorJitHost* newHost); diff --git a/src/coreclr/utilcode/CMakeLists.txt b/src/coreclr/utilcode/CMakeLists.txt index 06282d39189e56..78ae6b2b365632 100644 --- a/src/coreclr/utilcode/CMakeLists.txt +++ b/src/coreclr/utilcode/CMakeLists.txt @@ -84,7 +84,9 @@ convert_to_absolute_path(UTILCODE_SOURCES ${UTILCODE_SOURCES}) convert_to_absolute_path(UTILCODE_DAC_SOURCES ${UTILCODE_DAC_SOURCES}) convert_to_absolute_path(UTILCODE_STATICNOHOST_SOURCES ${UTILCODE_STATICNOHOST_SOURCES}) +if(NOT CLR_CMAKE_TARGET_ARCH_WASM) add_library_clr(utilcode_dac STATIC ${UTILCODE_DAC_SOURCES}) +endif() add_library_clr(utilcode OBJECT ${UTILCODE_SOURCES}) add_library_clr(utilcodestaticnohost STATIC ${UTILCODE_STATICNOHOST_SOURCES}) @@ -92,9 +94,11 @@ target_link_libraries(utilcodestaticnohost PUBLIC coreclrminipal) if(CLR_CMAKE_HOST_UNIX) target_link_libraries(utilcodestaticnohost PUBLIC nativeresourcestring) - target_link_libraries(utilcode_dac PUBLIC nativeresourcestring) + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + target_link_libraries(utilcode_dac PUBLIC nativeresourcestring) + add_dependencies(utilcode_dac coreclrpal) + endif() target_link_libraries(utilcode INTERFACE nativeresourcestring) - add_dependencies(utilcode_dac coreclrpal) add_dependencies(utilcode coreclrpal) endif(CLR_CMAKE_HOST_UNIX) @@ -107,12 +111,14 @@ if(CLR_CMAKE_HOST_WIN32) link_natvis_sources_for_target(utilcode INTERFACE utilcode.natvis) endif(CLR_CMAKE_HOST_WIN32) -set_target_properties(utilcode_dac PROPERTIES DAC_COMPONENT TRUE) -target_compile_definitions(utilcode_dac PRIVATE SELF_NO_HOST) +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + set_target_properties(utilcode_dac PROPERTIES DAC_COMPONENT TRUE) + target_compile_definitions(utilcode_dac PRIVATE SELF_NO_HOST) + add_dependencies(utilcode_dac ${UTILCODE_DEPENDENCIES}) + target_precompile_headers(utilcode_dac PRIVATE [["stdafx.h"]]) + endif() target_compile_definitions(utilcodestaticnohost PRIVATE SELF_NO_HOST) -add_dependencies(utilcode_dac ${UTILCODE_DEPENDENCIES}) add_dependencies(utilcode ${UTILCODE_DEPENDENCIES}) add_dependencies(utilcodestaticnohost ${UTILCODE_DEPENDENCIES}) -target_precompile_headers(utilcode_dac PRIVATE [["stdafx.h"]]) target_precompile_headers(utilcode PRIVATE [["stdafx.h"]]) target_precompile_headers(utilcodestaticnohost PRIVATE [["stdafx.h"]]) diff --git a/src/coreclr/utilcode/log.cpp b/src/coreclr/utilcode/log.cpp index 56ddf6aef9c20e..b95523fc33a218 100644 --- a/src/coreclr/utilcode/log.cpp +++ b/src/coreclr/utilcode/log.cpp @@ -372,10 +372,9 @@ VOID LogSpewAlwaysValist(const char *fmt, va_list args) if (LogFlags & LOG_ENABLE_CONSOLE_LOGGING) { - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pBuffer, buflen, &written, 0); - //@TODO ...Unnecessary to flush console? + minipal_log_write_info(pBuffer); if (LogFlags & LOG_ENABLE_FLUSH_FILE) - FlushFileBuffers( GetStdHandle(STD_OUTPUT_HANDLE) ); + minipal_log_sync_info(); } if (LogFlags & LOG_ENABLE_DEBUGGER_LOGGING) @@ -415,6 +414,5 @@ VOID LogSpewAlways (const char *fmt, ... ) LogSpewValist (LF_ALWAYS, LL_ALWAYS, fmt, args); va_end(args); } - #endif // LOGGING diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 61a210eb37ef36..157edb931583a0 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -639,6 +639,7 @@ if(CLR_CMAKE_TARGET_ARCH_AMD64) ${ARCH_SOURCES_DIR}/ExternalMethodFixupThunk.asm ${ARCH_SOURCES_DIR}/UMThunkStub.asm ${ARCH_SOURCES_DIR}/VirtualCallStubAMD64.asm + ${ARCH_SOURCES_DIR}/StubPrecodeDynamicHelpers.asm ) set(VM_HEADERS_WKS_ARCH_ASM @@ -666,7 +667,8 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM64) ${RUNTIME_DIR}/${ARCH_SOURCES_DIR}/StubDispatch.asm ${ARCH_SOURCES_DIR}/thunktemplates.asm ${ARCH_SOURCES_DIR}/CachedInterfaceDispatchCoreCLR.asm - ) + ${ARCH_SOURCES_DIR}/StubPrecodeDynamicHelpers.asm + ) set(VM_HEADERS_WKS_ARCH_ASM ${ARCH_SOURCES_DIR}/asmconstants.h @@ -697,6 +699,7 @@ else(CLR_CMAKE_TARGET_WIN32) ${ARCH_SOURCES_DIR}/unixasmhelpers.S ${ARCH_SOURCES_DIR}/umthunkstub.S ${ARCH_SOURCES_DIR}/virtualcallstubamd64.S + ${ARCH_SOURCES_DIR}/StubPrecodeDynamicHelpers.S ) elseif(CLR_CMAKE_TARGET_ARCH_I386) set(VM_SOURCES_WKS_ARCH_ASM @@ -725,6 +728,7 @@ else(CLR_CMAKE_TARGET_WIN32) ${ARCH_SOURCES_DIR}/pinvokestubs.S ${RUNTIME_DIR}/${ARCH_SOURCES_DIR}/StubDispatch.S ${ARCH_SOURCES_DIR}/thunktemplates.S + ${ARCH_SOURCES_DIR}/StubPrecodeDynamicHelpers.S ) elseif(CLR_CMAKE_TARGET_ARCH_LOONGARCH64) set(VM_SOURCES_WKS_ARCH_ASM @@ -955,10 +959,12 @@ convert_to_absolute_path(VM_SOURCES_WKS_ARCH_ASM ${VM_SOURCES_WKS_ARCH_ASM}) convert_to_absolute_path(VM_SOURCES_DAC ${VM_SOURCES_DAC}) convert_to_absolute_path(VM_SOURCES_WKS_SPECIAL ${VM_SOURCES_WKS_SPECIAL}) -add_library_clr(cee_dac ${VM_SOURCES_DAC}) -add_dependencies(cee_dac eventing_headers) -set_target_properties(cee_dac PROPERTIES DAC_COMPONENT TRUE) -target_precompile_headers(cee_dac PRIVATE [["common.h"]]) +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_library_clr(cee_dac ${VM_SOURCES_DAC}) + add_dependencies(cee_dac eventing_headers) + set_target_properties(cee_dac PROPERTIES DAC_COMPONENT TRUE) + target_precompile_headers(cee_dac PRIVATE [["common.h"]]) +endif() add_subdirectory(wks) diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index 55251c3ec70f99..b0d1b7b4093312 100644 --- a/src/coreclr/vm/amd64/AsmHelpers.asm +++ b/src/coreclr/vm/amd64/AsmHelpers.asm @@ -497,4 +497,14 @@ NESTED_ENTRY InterpreterStub, _TEXT NESTED_END InterpreterStub, _TEXT endif ; FEATURE_INTERPRETER +; rcx -This pointer +; rdx -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + mov METHODDESC_REGISTER, [METHODDESC_REGISTER + ThisPtrRetBufPrecodeData__Target] + mov r11, rcx + mov rcx, rdx + mov rdx, r11 + jmp METHODDESC_REGISTER +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT + end \ No newline at end of file diff --git a/src/coreclr/vm/amd64/StubPrecodeDynamicHelpers.S b/src/coreclr/vm/amd64/StubPrecodeDynamicHelpers.S new file mode 100644 index 00000000000000..b0d92303ffb4ed --- /dev/null +++ b/src/coreclr/vm/amd64/StubPrecodeDynamicHelpers.S @@ -0,0 +1,264 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + +#define SecretArg_Reg r10 +#define FirstArg_Reg rdi +#define SecondArg_Reg rsi +#define SecondArg_DwordReg esi +#define ThirdArg_Reg rdx +#define ThirdArg_DwordReg edx +#define FourthArg_Reg rcx + +#define DATA_SLOT(field) r10 + OFFSETOF__DynamicHelperStubArgs__ ## field +#define GENERIC_DICT_DATA_SLOT(field) r10 + OFFSETOF__GenericDictionaryDynamicHelperStubData__ ## field + +LEAF_ENTRY DynamicHelper_CallHelper_1Arg, _TEXT + mov FirstArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + jmp QWORD PTR [DATA_SLOT(Helper)] +LEAF_END DynamicHelper_CallHelper_1Arg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_AddSecondArg, _TEXT + mov SecondArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + jmp QWORD PTR [DATA_SLOT(Helper)] +LEAF_END DynamicHelper_CallHelper_AddSecondArg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_2Arg, _TEXT + mov FirstArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov SecondArg_Reg, QWORD PTR [DATA_SLOT(Constant2)] + jmp QWORD PTR [DATA_SLOT(Helper)] +LEAF_END DynamicHelper_CallHelper_2Arg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_ArgMove, _TEXT + mov SecondArg_Reg, FirstArg_Reg + mov FirstArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + jmp QWORD PTR [DATA_SLOT(Helper)] +LEAF_END DynamicHelper_CallHelper_ArgMove, _TEXT + +LEAF_ENTRY DynamicHelper_Return, _TEXT + ret +LEAF_END DynamicHelper_Return, _TEXT + +LEAF_ENTRY DynamicHelper_ReturnConst, _TEXT + mov rax, SecretArg_Reg + ret +LEAF_END DynamicHelper_ReturnConst, _TEXT + +LEAF_ENTRY DynamicHelper_ReturnIndirConst, _TEXT + mov rax, QWORD PTR [SecretArg_Reg] + ret +LEAF_END DynamicHelper_ReturnIndirConst, _TEXT + +LEAF_ENTRY DynamicHelper_ReturnIndirConstWithOffset, _TEXT + mov rax, QWORD PTR [DATA_SLOT(Constant1)] + mov rax, QWORD PTR [rax] + add rax, QWORD PTR [DATA_SLOT(Constant2)] + ret +LEAF_END DynamicHelper_ReturnIndirConstWithOffset, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_AddThirdArg, _TEXT + mov ThirdArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + jmp QWORD PTR [DATA_SLOT(Helper)] +LEAF_END DynamicHelper_CallHelper_AddThirdArg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_AddThirdAndFourthArg, _TEXT + mov ThirdArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov FourthArg_Reg, QWORD PTR [DATA_SLOT(Constant2)] + jmp QWORD PTR [DATA_SLOT(Helper)] +LEAF_END DynamicHelper_CallHelper_AddThirdAndFourthArg, _TEXT + +// Generic dictionaries can have 2 or 3 indirections (5 indirs of 32bit size, and 2 8 byte quantities) = 40 bytes +// If it has 2 its for a Method, and the first indirection is always offsetof(InstantiatiedMethodDesc, m_pPerInstInfo) +// If it has 3 its for a Class, and the first indirection is always MethodTable::GetOffsetOfPerInstInfo +// It can also have 0, 0, to just return the class type +// Test For Null Or Not (If not present, cannot have a size check) +// SizeCheck or not (Only needed if size > Some number) +// +// Also special case where we just return the TypeHandle or MethodDesc itself +// Should probably have special case for 1, 2, 3 generic arg of MethodDesc/MethodTable + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SecondIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // SizeCheck + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SizeOffset)] + mov ThirdArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SlotOffset)] + cmp qword ptr[rax + SecondArg_Reg], ThirdArg_Reg + jle LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall) + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // Null test + test rax, rax + je LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall) + ret +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall): + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + PREPARE_EXTERNAL_VAR g_pClassWithSlotAndModule, rax + jmp [rax] +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_TestForNull, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SecondIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // Null test + test rax, rax + je LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall) + ret +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall): + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + PREPARE_EXTERNAL_VAR g_pClassWithSlotAndModule, rax + jmp [rax] +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SecondIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // SizeCheck + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SizeOffset)] + mov ThirdArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SlotOffset)] + cmp qword ptr[rax + SecondArg_Reg], ThirdArg_Reg + jle LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall) + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // Null test + test rax, rax + je LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall) + ret +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall): + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + PREPARE_EXTERNAL_VAR g_pMethodWithSlotAndModule, rax + jmp [rax] +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_TestForNull, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + // Null test + test rax, rax + je LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall) + ret +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall): + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + PREPARE_EXTERNAL_VAR g_pMethodWithSlotAndModule, rax + jmp [rax] +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_0, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax] + // Standard Indirection + mov rax, QWORD PTR [rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_0, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_1, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax] + // Standard Indirection + mov rax, QWORD PTR [rax + 0x8] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_1, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_2, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax] + // Standard Indirection + mov rax, QWORD PTR [rax + 0x10] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_2, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_3, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax] + // Standard Indirection + mov rax, QWORD PTR [rax + 0x18] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_3, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_0, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_0, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_1, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax + 0x8] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_1, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_2, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax + 0x10] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_2, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_3, _TEXT + // First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + mov rax, QWORD PTR [rax + 0x18] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_3, _TEXT + +#endif //// FEATURE_STUBPRECODE_DYNAMIC_HELPERS diff --git a/src/coreclr/vm/amd64/StubPrecodeDynamicHelpers.asm b/src/coreclr/vm/amd64/StubPrecodeDynamicHelpers.asm new file mode 100644 index 00000000000000..b30da071542941 --- /dev/null +++ b/src/coreclr/vm/amd64/StubPrecodeDynamicHelpers.asm @@ -0,0 +1,278 @@ +; Licensed to the .NET Foundation under one or more agreements. +; The .NET Foundation licenses this file to you under the MIT license. + +include +include AsmConstants.inc + +ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + +SecretArg_Reg equ r10 +FirstArg_Reg equ rcx +SecondArg_Reg equ rdx +SecondArg_DwordReg equ edx +ThirdArg_Reg equ r8 +ThirdArg_DwordReg equ r8d +FourthArg_Reg equ r9 + +DATA_SLOT macro field + exitm @CatStr(r10, < + OFFSETOF__DynamicHelperStubArgs__>, field) +endm + +GENERIC_DICT_DATA_SLOT macro field + exitm @CatStr(r10, < + OFFSETOF__GenericDictionaryDynamicHelperStubData__>, field) +endm + +extern g_pClassWithSlotAndModule:QWORD +extern g_pMethodWithSlotAndModule:QWORD + +LEAF_ENTRY DynamicHelper_CallHelper_1Arg, _TEXT + mov FirstArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov rax, QWORD PTR [DATA_SLOT(Helper)] + TAILJMP_RAX +LEAF_END DynamicHelper_CallHelper_1Arg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_AddSecondArg, _TEXT + mov SecondArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov rax, QWORD PTR [DATA_SLOT(Helper)] + TAILJMP_RAX +LEAF_END DynamicHelper_CallHelper_AddSecondArg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_2Arg, _TEXT + mov FirstArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov SecondArg_Reg, QWORD PTR [DATA_SLOT(Constant2)] + mov rax, QWORD PTR [DATA_SLOT(Helper)] + TAILJMP_RAX +LEAF_END DynamicHelper_CallHelper_2Arg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_ArgMove, _TEXT + mov SecondArg_Reg, FirstArg_Reg + mov FirstArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov rax, QWORD PTR [DATA_SLOT(Helper)] + TAILJMP_RAX +LEAF_END DynamicHelper_CallHelper_ArgMove, _TEXT + +LEAF_ENTRY DynamicHelper_Return, _TEXT + ret +LEAF_END DynamicHelper_Return, _TEXT + +LEAF_ENTRY DynamicHelper_ReturnConst, _TEXT + mov rax, SecretArg_Reg + ret +LEAF_END DynamicHelper_ReturnConst, _TEXT + +LEAF_ENTRY DynamicHelper_ReturnIndirConst, _TEXT + mov rax, QWORD PTR [SecretArg_Reg] + ret +LEAF_END DynamicHelper_ReturnIndirConst, _TEXT + +LEAF_ENTRY DynamicHelper_ReturnIndirConstWithOffset, _TEXT + mov rax, QWORD PTR [DATA_SLOT(Constant1)] + mov rax, QWORD PTR [rax] + add rax, QWORD PTR [DATA_SLOT(Constant2)] + ret +LEAF_END DynamicHelper_ReturnIndirConstWithOffset, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_AddThirdArg, _TEXT + mov ThirdArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov rax, QWORD PTR [DATA_SLOT(Helper)] + TAILJMP_RAX +LEAF_END DynamicHelper_CallHelper_AddThirdArg, _TEXT + +LEAF_ENTRY DynamicHelper_CallHelper_AddThirdAndFourthArg, _TEXT + mov ThirdArg_Reg, QWORD PTR [DATA_SLOT(Constant1)] + mov FourthArg_Reg, QWORD PTR [DATA_SLOT(Constant2)] + mov rax, QWORD PTR [DATA_SLOT(Helper)] + TAILJMP_RAX +LEAF_END DynamicHelper_CallHelper_AddThirdAndFourthArg, _TEXT + +; Generic dictionaries can have 2 or 3 indirections (5 indirs of 32bit size, and 2 8 byte quantities) = 40 bytes +; If it has 2 its for a Method, and the first indirection is always offsetof(InstantiatiedMethodDesc, m_pPerInstInfo) +; If it has 3 its for a Class, and the first indirection is always MethodTable::GetOffsetOfPerInstInfo +; It can also have 0, 0, to just return the class type +; Test For Null Or Not (If not present, cannot have a size check) +; SizeCheck or not (Only needed if size > Some number) +; +; Also special case where we just return the TypeHandle or MethodDesc itself +; Should probably have special case for 1, 2, 3 generic arg of MethodDesc/MethodTable + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SecondIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; SizeCheck + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SizeOffset)] + mov ThirdArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SlotOffset)] + cmp qword ptr[rax + SecondArg_Reg], ThirdArg_Reg + jle DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; Null test + test rax, rax + je DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall + ret +DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall: + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + mov rax, QWORD PTR [g_pClassWithSlotAndModule] + TAILJMP_RAX +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_TestForNull, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SecondIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; Null test + test rax, rax + je DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall + ret +DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall: + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + mov rax, QWORD PTR [g_pClassWithSlotAndModule] + TAILJMP_RAX +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SecondIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; SizeCheck + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SizeOffset)] + mov ThirdArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(SlotOffset)] + cmp qword ptr[rax + SecondArg_Reg], ThirdArg_Reg + jle DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; Null test + test rax, rax + je DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall + ret +DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall: + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + mov rax, QWORD PTR [g_pMethodWithSlotAndModule] + TAILJMP_RAX +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_TestForNull, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ; Null test + test rax, rax + je DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall + ret +DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall: + mov SecondArg_Reg, QWORD PTR [GENERIC_DICT_DATA_SLOT(HandleArgs)] + mov rax, QWORD PTR [g_pMethodWithSlotAndModule] + TAILJMP_RAX +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_TestForNull, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + mov SecondArg_DwordReg, DWORD PTR [GENERIC_DICT_DATA_SLOT(LastIndir)] + mov rax, QWORD PTR [SecondArg_Reg+rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_0, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax] + ; Standard Indirection + mov rax, QWORD PTR [rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_0, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_1, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax] + ; Standard Indirection + mov rax, QWORD PTR [rax + 8h] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_1, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_2, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax] + ; Standard Indirection + mov rax, QWORD PTR [rax + 10h] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_2, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_3, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax] + ; Standard Indirection + mov rax, QWORD PTR [rax + 18h] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_3, _TEXT + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_0, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_0, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_1, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax + 08h] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_1, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_2, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax + 10h] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_2, _TEXT + + +LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_3, _TEXT + ; First indirection + mov rax, QWORD PTR [FirstArg_Reg+OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + mov rax, QWORD PTR [rax + 18h] + ret +LEAF_END DynamicHelper_GenericDictionaryLookup_Method_3, _TEXT + +endif ;; FEATURE_STUBPRECODE_DYNAMIC_HELPERS + end \ No newline at end of file diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h index 07e3199ff67f85..9f4e3543dfaad6 100644 --- a/src/coreclr/vm/amd64/asmconstants.h +++ b/src/coreclr/vm/amd64/asmconstants.h @@ -34,6 +34,9 @@ #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 +#define ThisPtrRetBufPrecodeData__Target 0x00 +ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target)); + #define ASMCONSTANT_OFFSETOF_ASSERT(struct, member) \ ASMCONSTANTS_C_ASSERT(OFFSETOF__##struct##__##member == offsetof(struct, member)); @@ -123,7 +126,42 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__ThreadExceptionState__m_pCurrentTracker == offsetof(ThreadExceptionState, m_pCurrentTracker)); +#define OFFSETOF__DynamicHelperStubArgs__Constant1 0x0 +ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicHelperStubArgs__Constant1 + == offsetof(DynamicHelperStubArgs, Constant1)); + +#define OFFSETOF__DynamicHelperStubArgs__Constant2 0x8 +ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicHelperStubArgs__Constant2 + == offsetof(DynamicHelperStubArgs, Constant2)); + +#define OFFSETOF__DynamicHelperStubArgs__Helper 0x10 +ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicHelperStubArgs__Helper + == offsetof(DynamicHelperStubArgs, Helper)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__SecondIndir 0x0 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__SecondIndir + == offsetof(GenericDictionaryDynamicHelperStubData, SecondIndir)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__LastIndir 0x4 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__LastIndir + == offsetof(GenericDictionaryDynamicHelperStubData, LastIndir)); +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__SizeOffset 0x8 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__SizeOffset + == offsetof(GenericDictionaryDynamicHelperStubData, SizeOffset)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__SlotOffset 0xc +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__SlotOffset + == offsetof(GenericDictionaryDynamicHelperStubData, SlotOffset)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__HandleArgs 0x10 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__HandleArgs + == offsetof(GenericDictionaryDynamicHelperStubData, HandleArgs)); + +#define OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo DBG_FRE(0x40, 0x18) +ASMCONSTANTS_C_ASSERT(OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo + == offsetof(InstantiatedMethodDesc, m_pPerInstInfo)); + #define OFFSETOF__MethodTable__m_dwFlags 0x00 ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodTable__m_dwFlags @@ -152,6 +190,10 @@ ASMCONSTANTS_C_ASSERT(METHODTABLE_OFFSET_VTABLE == sizeof(MethodTable)); ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodTable__m_ElementType == offsetof(MethodTable, m_ElementTypeHnd)); +#define OFFSETOF__MethodTable__m_pPerInstInfo DBG_FRE(0x38, 0x30) +ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodTable__m_pPerInstInfo + == offsetof(MethodTable, m_pPerInstInfo)); + #define OFFSETOF__MethodTable__m_pInterfaceMap DBG_FRE(0x40, 0x38) ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodTable__m_pInterfaceMap == offsetof(MethodTable, m_pInterfaceMap)); diff --git a/src/coreclr/vm/amd64/asmhelpers.S b/src/coreclr/vm/amd64/asmhelpers.S index 6d2efe5d7c7dd9..73646ad2aa2a02 100644 --- a/src/coreclr/vm/amd64/asmhelpers.S +++ b/src/coreclr/vm/amd64/asmhelpers.S @@ -352,3 +352,13 @@ NESTED_ENTRY InterpreterStub, _TEXT, NoHandler NESTED_END InterpreterStub, _TEXT #endif // FEATURE_INTERPRETER + +//rdi -This pointer +//rsi -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + mov METHODDESC_REGISTER, [METHODDESC_REGISTER + ThisPtrRetBufPrecodeData__Target] + mov r11, rsi + mov rsi, rdi + mov rdi, r11 + jmp METHODDESC_REGISTER +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index f2c42529ac22dd..e89900341ec7db 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -690,6 +690,7 @@ DWORD GetOffsetAtEndOfFunction(ULONGLONG uImageBase, // // Allocation of dynamic helpers // +#ifndef FEATURE_STUBPRECODE_DYNAMIC_HELPERS #define DYNAMIC_HELPER_ALIGNMENT sizeof(TADDR) @@ -1053,6 +1054,7 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, END_DYNAMIC_HELPER_EMIT(); } } +#endif // !FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif // FEATURE_READYTORUN diff --git a/src/coreclr/vm/appdomainnative.cpp b/src/coreclr/vm/appdomainnative.cpp index ada5e6c7b689a0..f8cae6a32ea273 100644 --- a/src/coreclr/vm/appdomainnative.cpp +++ b/src/coreclr/vm/appdomainnative.cpp @@ -129,6 +129,22 @@ extern "C" void QCALLTYPE String_IsInterned(QCall::StringHandleOnStack str) END_QCALL; } +extern "C" STRINGREF* QCALLTYPE String_StrCns(UINT32 rid, CORINFO_MODULE_HANDLE scopeHnd) +{ + QCALL_CONTRACT; + + STRINGREF* hndStr = NULL; + + BEGIN_QCALL; + + // Retrieve the handle to the CLR string object. + hndStr = ConstructStringLiteral(scopeHnd, RidToToken(rid, mdtString)); + + END_QCALL; + + return hndStr; +} + extern "C" void QCALLTYPE String_Intern(QCall::StringHandleOnStack str) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/appdomainnative.hpp b/src/coreclr/vm/appdomainnative.hpp index 7fb86136bf196b..921af74fa9d909 100644 --- a/src/coreclr/vm/appdomainnative.hpp +++ b/src/coreclr/vm/appdomainnative.hpp @@ -16,6 +16,7 @@ #include "qcall.h" +extern "C" STRINGREF* QCALLTYPE String_StrCns(UINT32 rid, CORINFO_MODULE_HANDLE scopeHnd); extern "C" void QCALLTYPE String_Intern(QCall::StringHandleOnStack str); extern "C" void QCALLTYPE String_IsInterned(QCall::StringHandleOnStack str); diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index 52bca1f038cca3..369241a0d85023 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -36,6 +36,9 @@ ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::Inline #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 +#define ThisPtrRetBufPrecodeData__Target 0x00 +ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target)); + #define REDIRECTSTUB_SP_OFFSET_CONTEXT 0 diff --git a/src/coreclr/vm/arm/asmhelpers.S b/src/coreclr/vm/arm/asmhelpers.S index 5017a582f3ab8c..e577b1828ae8a3 100644 --- a/src/coreclr/vm/arm/asmhelpers.S +++ b/src/coreclr/vm/arm/asmhelpers.S @@ -561,6 +561,9 @@ LOCAL_LABEL(stackProbe_loop): __\name\()__g_ephemeral_low_offset = 0xffff __\name\()__g_ephemeral_high_offset = 0xffff __\name\()__g_card_table_offset = 0xffff +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + __\name\()__g_sw_ww_table_offset = 0xffff +#endif .endm .macro LOAD_GC_GLOBAL name, regName, globalName @@ -603,6 +606,28 @@ LOCAL_LABEL(stackProbe_loop): 0: .endm +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + .macro UPDATE_WRITE_WATCH_TABLE name, ptrReg, mp, tmpReg + + LOAD_GC_GLOBAL \name, __wbScratch, g_sw_ww_table + cbz __wbScratch, 2f + add __wbScratch, __wbScratch, \ptrReg, lsr #0xc // SoftwareWriteWatch::AddressToTableByteIndexShift + + .if(\mp) + ldrb \tmpReg, [__wbScratch] + cmp \tmpReg, #0xff + itt ne + movne \tmpReg, 0xff + strbne \tmpReg, [__wbScratch] + .else + mov \tmpReg, #0xff + strb \tmpReg, [__wbScratch] + .endif + +2: + .endm +#endif + .macro CHECK_GC_HEAP_RANGE name, ptrReg, label LOAD_GC_GLOBAL \name, __wbScratch, g_lowest_address cmp \ptrReg, __wbScratch @@ -621,6 +646,9 @@ LOCAL_LABEL(stackProbe_loop): str r1, [r0] UPDATE_GC_SHADOW \name, r0, r1 +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + UPDATE_WRITE_WATCH_TABLE \name, r0, \mp, r12 +#endif UPDATE_CARD_TABLE \name, r0, r1, \mp, \post, r0 bx lr LEAF_END_MARKED \name, _TEXT @@ -632,6 +660,9 @@ LOCAL_LABEL(stackProbe_loop): str r1, [r0] CHECK_GC_HEAP_RANGE \name, r0, 1f UPDATE_GC_SHADOW \name, r0, r1 +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + UPDATE_WRITE_WATCH_TABLE \name, r0, 0, r12 +#endif UPDATE_CARD_TABLE \name, r0, r1, 0, \post, r0 1: bx lr @@ -645,6 +676,9 @@ LOCAL_LABEL(stackProbe_loop): str r1, [r0] CHECK_GC_HEAP_RANGE \name, r0, 1f UPDATE_GC_SHADOW \name, r0, r1 +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + UPDATE_WRITE_WATCH_TABLE \name, r0, 1, r12 +#endif UPDATE_CARD_TABLE \name, r0, r1, 1, \post, r0 bx lr 1: @@ -664,6 +698,9 @@ LOCAL_LABEL(stackProbe_loop): str r2, [r0] CHECK_GC_HEAP_RANGE \name, r0, 1f UPDATE_GC_SHADOW \name, r0, r2 +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + UPDATE_WRITE_WATCH_TABLE \name, r0, \mp, r12 +#endif UPDATE_CARD_TABLE \name, r0, r2, \mp, \post, r2 1: add r0, #4 @@ -681,6 +718,9 @@ LOCAL_LABEL(stackProbe_loop): .word __\name\()__g_ephemeral_low_offset .word __\name\()__g_ephemeral_high_offset .word __\name\()__g_card_table_offset +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + .word __\name\()__g_sw_ww_table_offset +#endif .endm // There 4 versions of each write barriers. A 2x2 combination of multi-proc/single-proc and pre/post grow version @@ -937,3 +977,15 @@ LOCAL_LABEL(JIT_PollGCRarePath): ldr r2, [r2] EPILOG_BRANCH_REG r2 LEAF_END JIT_PollGC, _TEXT + + +//x0 -This pointer +//x1 -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + ldr r12, [r12, #ThisPtrRetBufPrecodeData__Target] + // Use XOR swap technique to set avoid the need to spill to the stack + eor r0, r0, r1 + eor r1, r0, r1 + eor r0, r0, r1 + EPILOG_BRANCH_REG r12 +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h index 9d205824fc1808..110669e5df45d9 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -962,63 +962,6 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool // Create alias for optimized implementations of helpers provided on this platform // -//------------------------------------------------------------------------ -// -// Precode definitions -// -//------------------------------------------------------------------------ -// -// Note: If you introduce new precode implementation below, then please -// update PrecodeStubManager::CheckIsStub_Internal to account for it. - -// Precode to shuffle this and retbuf for closed delegates over static methods with return buffer -struct ThisPtrRetBufPrecode { - - static const int Type = 0x01; - - // mov r12, r0 - // mov r0, r1 - // mov r1, r12 - // ldr pc, [pc, #0] ; =m_pTarget - // dcd pTarget - // dcd pMethodDesc - WORD m_rgCode[6]; - TADDR m_pTarget; - TADDR m_pMethodDesc; - - void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); - - TADDR GetMethodDesc() - { - LIMITED_METHOD_DAC_CONTRACT; - - return m_pMethodDesc; - } - - PCODE GetTarget() - { - LIMITED_METHOD_DAC_CONTRACT; - return m_pTarget; - } - -#ifndef DACCESS_COMPILE - BOOL SetTargetInterlocked(TADDR target, TADDR expected) - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - } - CONTRACTL_END; - - ExecutableWriterHolder precodeWriterHolder(this, sizeof(ThisPtrRetBufPrecode)); - return InterlockedCompareExchange((LONG*)&precodeWriterHolder.GetRW()->m_pTarget, (LONG)target, (LONG)expected) == (LONG)expected; - } -#endif // !DACCESS_COMPILE -}; -typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; - - //********************************************************************** // Miscellaneous //********************************************************************** diff --git a/src/coreclr/vm/arm/patchedcode.S b/src/coreclr/vm/arm/patchedcode.S index 95d53ae96a613a..94a6b44d285490 100644 --- a/src/coreclr/vm/arm/patchedcode.S +++ b/src/coreclr/vm/arm/patchedcode.S @@ -26,17 +26,17 @@ // See ValidateWriteBarriers on how the sizes of these should be calculated .align 4 LEAF_ENTRY JIT_WriteBarrier, _TEXT - .space (0x84) + .space (0xA8) LEAF_END_MARKED JIT_WriteBarrier, _TEXT .align 4 LEAF_ENTRY JIT_CheckedWriteBarrier, _TEXT - .space (0x9C) + .space (0xC0) LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT .align 4 LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT - .space (0xA0) + .space (0xC4) LEAF_END_MARKED JIT_ByRefWriteBarrier , _TEXT LEAF_ENTRY JIT_PatchedWriteBarrierLast, _TEXT diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 8a896ce0cdc41e..0becb0440bac5c 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -287,6 +287,9 @@ struct WriteBarrierDescriptor DWORD m_dw_g_ephemeral_low_offset; // Offset of the instruction reading g_ephemeral_low DWORD m_dw_g_ephemeral_high_offset; // Offset of the instruction reading g_ephemeral_high DWORD m_dw_g_card_table_offset; // Offset of the instruction reading g_card_table +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + DWORD m_dw_g_sw_ww_table_offset; // Offset of the instruction reading g_sw_ww_table +#endif }; // Infrastructure used for mapping of the source and destination of current WB patching @@ -455,6 +458,9 @@ void UpdateGCWriteBarriers(bool postGrow = false) GWB_PATCH_OFFSET(g_ephemeral_low); GWB_PATCH_OFFSET(g_ephemeral_high); GWB_PATCH_OFFSET(g_card_table); +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + GWB_PATCH_OFFSET(g_sw_ww_table); +#endif } pDesc++; @@ -494,6 +500,24 @@ int StompWriteBarrierEphemeral(bool isRuntimeSuspended) return SWB_ICACHE_FLUSH; } +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +int SwitchToWriteWatchBarrier(bool isRuntimeSuspended) +{ + UNREFERENCED_PARAMETER(isRuntimeSuspended); + _ASSERTE(isRuntimeSuspended); + UpdateGCWriteBarriers(); + return SWB_ICACHE_FLUSH; +} + +int SwitchToNonWriteWatchBarrier(bool isRuntimeSuspended) +{ + UNREFERENCED_PARAMETER(isRuntimeSuspended); + _ASSERTE(isRuntimeSuspended); + UpdateGCWriteBarriers(); + return SWB_ICACHE_FLUSH; +} +#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + void FlushWriteBarrierInstructionCache() { // We've changed code so we must flush the instruction cache. @@ -709,26 +733,6 @@ void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool update #ifndef DACCESS_COMPILE -void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) -{ - WRAPPER_NO_CONTRACT; - - int n = 0; - - m_rgCode[n++] = 0x4684; // mov r12, r0 - m_rgCode[n++] = 0x4608; // mov r0, r1 - m_rgCode[n++] = 0xea4f; // mov r1, r12 - m_rgCode[n++] = 0x010c; - m_rgCode[n++] = 0xf8df; // ldr pc, [pc, #0] - m_rgCode[n++] = 0xf000; - - _ASSERTE(n == ARRAY_SIZE(m_rgCode)); - - m_pTarget = GetPreStubEntryPoint(); - m_pMethodDesc = (TADDR)pMD; -} - - /* Rough pseudo-code of interface dispatching: diff --git a/src/coreclr/vm/arm64/StubPrecodeDynamicHelpers.S b/src/coreclr/vm/arm64/StubPrecodeDynamicHelpers.S new file mode 100644 index 00000000000000..82c9ec3ecc9b18 --- /dev/null +++ b/src/coreclr/vm/arm64/StubPrecodeDynamicHelpers.S @@ -0,0 +1,284 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "asmconstants.h" +#include "unixasmmacros.inc" + +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + +#define SecretArg_Reg x12 +#define FirstArg_Reg x0 +#define SecondArg_Reg x1 +#define SecondArg_DwordReg w1 +#define ThirdArg_Reg x2 +#define ThirdArg_DwordReg w2 +#define FourthArg_Reg x3 + +#define DATA_SLOT(field) [x12, #OFFSETOF__DynamicHelperStubArgs__ ## field] +#define GENERIC_DICT_DATA_SLOT(field) [x12, #OFFSETOF__GenericDictionaryDynamicHelperStubData__ ## field] + + LEAF_ENTRY DynamicHelper_CallHelper_1Arg, _TEXT + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END DynamicHelper_CallHelper_1Arg, _TEXT + + LEAF_ENTRY DynamicHelper_CallHelper_AddSecondArg, _TEXT + ldr SecondArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END DynamicHelper_CallHelper_AddSecondArg, _TEXT + + LEAF_ENTRY DynamicHelper_CallHelper_2Arg, _TEXT + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr SecondArg_Reg, DATA_SLOT(Constant2) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END DynamicHelper_CallHelper_2Arg, _TEXT + + LEAF_ENTRY DynamicHelper_CallHelper_ArgMove, _TEXT + mov SecondArg_Reg, FirstArg_Reg + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END DynamicHelper_CallHelper_ArgMove, _TEXT + + LEAF_ENTRY DynamicHelper_Return, _TEXT + ret lr + LEAF_END DynamicHelper_Return, _TEXT + + LEAF_ENTRY DynamicHelper_ReturnConst, _TEXT + mov FirstArg_Reg, SecretArg_Reg + ret lr + LEAF_END DynamicHelper_ReturnConst, _TEXT + + LEAF_ENTRY DynamicHelper_ReturnIndirConst, _TEXT + ldr FirstArg_Reg, [SecretArg_Reg, #0] + ret lr + LEAF_END DynamicHelper_ReturnIndirConst, _TEXT + + LEAF_ENTRY DynamicHelper_ReturnIndirConstWithOffset, _TEXT + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr FirstArg_Reg, [FirstArg_Reg] + ldr SecondArg_Reg, DATA_SLOT(Constant2) + add FirstArg_Reg, FirstArg_Reg, SecondArg_Reg + ret lr + LEAF_END DynamicHelper_ReturnIndirConstWithOffset, _TEXT + + LEAF_ENTRY DynamicHelper_CallHelper_AddThirdArg, _TEXT + ldr ThirdArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END DynamicHelper_CallHelper_AddThirdArg, _TEXT + + LEAF_ENTRY DynamicHelper_CallHelper_AddThirdAndFourthArg, _TEXT + ldr ThirdArg_Reg, DATA_SLOT(Constant1) + ldr FourthArg_Reg, DATA_SLOT(Constant2) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END DynamicHelper_CallHelper_AddThirdAndFourthArg, _TEXT + + // Generic dictionaries can have 2 or 3 indirections (5 indirs of 32bit size, and 2 8 byte quantities) = 40 bytes + // If it has 2 its for a Method, and the first indirection is always offsetof(InstantiatiedMethodDesc, m_pPerInstInfo) + // If it has 3 its for a Class, and the first indirection is always MethodTable::GetOffsetOfPerInstInfo + // It can also have 0, 0, to just return the class type + // Test For Null Or Not (If not present, cannot have a size check) + // SizeCheck or not (Only needed if size > Some number) + // + // Also special case where we just return the TypeHandle or MethodDesc itself + // Should probably have special case for 1, 2, 3 generic arg of MethodDesc/MethodTable + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull, _TEXT + // Save Generic Context + mov x4, FirstArg_Reg + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SecondIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // SizeCheck + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SizeOffset) + ldr ThirdArg_DwordReg, GENERIC_DICT_DATA_SLOT(SlotOffset) + ldr FourthArg_Reg, [FirstArg_Reg, SecondArg_Reg] + cmp FourthArg_Reg, ThirdArg_Reg + b.ls LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall) + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // Null test + cbz FirstArg_Reg, LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall) + ret lr +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall): + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + PREPARE_EXTERNAL_VAR g_pClassWithSlotAndModule, x3 + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_TestForNull, _TEXT + // Save Generic Context + mov x4, FirstArg_Reg + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SecondIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // Null test + cbz FirstArg_Reg, LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall) + ret lr +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall): + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + PREPARE_EXTERNAL_VAR g_pClassWithSlotAndModule, x3 + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END DynamicHelper_GenericDictionaryLookup_Class_TestForNull, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SecondIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Class, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull, _TEXT + // Save Generic Context + mov x4, FirstArg_Reg + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // SizeCheck + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SizeOffset) + ldr ThirdArg_DwordReg, GENERIC_DICT_DATA_SLOT(SlotOffset) + ldr FourthArg_Reg, [FirstArg_Reg, SecondArg_Reg] + cmp FourthArg_Reg, ThirdArg_Reg + b.ls LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall) + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // Null test + cbz FirstArg_Reg, LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall) + ret lr +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall): + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + PREPARE_EXTERNAL_VAR g_pMethodWithSlotAndModule, x3 + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_TestForNull, _TEXT + // Save Generic Context + mov x4, FirstArg_Reg + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + // Null test + cbz FirstArg_Reg, LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall) + ret lr +LOCAL_LABEL(DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall): + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + PREPARE_EXTERNAL_VAR g_pMethodWithSlotAndModule, x3 + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END DynamicHelper_GenericDictionaryLookup_Method_TestForNull, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Method, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_0, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_0, _TEXT + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_1, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x8] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_1, _TEXT + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_2, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x10] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_2, _TEXT + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_3, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x18] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Class_0_3, _TEXT + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_0, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Method_0, _TEXT + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_1, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x8] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Method_1, _TEXT + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_2, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x10] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Method_2, _TEXT + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_3, _TEXT + // First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + // Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x18] + ret lr + LEAF_END DynamicHelper_GenericDictionaryLookup_Method_3, _TEXT + +#endif //// FEATURE_STUBPRECODE_DYNAMIC_HELPERS diff --git a/src/coreclr/vm/arm64/StubPrecodeDynamicHelpers.asm b/src/coreclr/vm/arm64/StubPrecodeDynamicHelpers.asm new file mode 100644 index 00000000000000..32e494f96fc09f --- /dev/null +++ b/src/coreclr/vm/arm64/StubPrecodeDynamicHelpers.asm @@ -0,0 +1,293 @@ +; Licensed to the .NET Foundation under one or more agreements. +; The .NET Foundation licenses this file to you under the MIT license. + +#include "ksarm64.h" +#include "asmconstants.h" +#include "asmmacros.h" + +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + +TEXTAREA + + IMPORT g_pClassWithSlotAndModule + IMPORT g_pMethodWithSlotAndModule + +#define SecretArg_Reg x12 +#define FirstArg_Reg x0 +#define SecondArg_Reg x1 +#define SecondArg_DwordReg w1 +#define ThirdArg_Reg x2 +#define ThirdArg_DwordReg w2 +#define FourthArg_Reg x3 + +#define HASH_SYMBOL # +#define DATA_SLOT(field) [x12, HASH_SYMBOL OFFSETOF__DynamicHelperStubArgs__##field] +#define GENERIC_DICT_DATA_SLOT(field) [x12, HASH_SYMBOL OFFSETOF__GenericDictionaryDynamicHelperStubData__ ## field] + + LEAF_ENTRY DynamicHelper_CallHelper_1Arg + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END + + LEAF_ENTRY DynamicHelper_CallHelper_AddSecondArg + ldr SecondArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END + + LEAF_ENTRY DynamicHelper_CallHelper_2Arg + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr SecondArg_Reg, DATA_SLOT(Constant2) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END + + LEAF_ENTRY DynamicHelper_CallHelper_ArgMove + mov SecondArg_Reg, FirstArg_Reg + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END + + LEAF_ENTRY DynamicHelper_Return + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_ReturnConst + mov FirstArg_Reg, SecretArg_Reg + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_ReturnIndirConst + ldr FirstArg_Reg, [SecretArg_Reg, #0] + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_ReturnIndirConstWithOffset + ldr FirstArg_Reg, DATA_SLOT(Constant1) + ldr FirstArg_Reg, [FirstArg_Reg] + ldr SecondArg_Reg, DATA_SLOT(Constant2) + add FirstArg_Reg, FirstArg_Reg, SecondArg_Reg + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_CallHelper_AddThirdArg + ldr ThirdArg_Reg, DATA_SLOT(Constant1) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END + + LEAF_ENTRY DynamicHelper_CallHelper_AddThirdAndFourthArg + ldr ThirdArg_Reg, DATA_SLOT(Constant1) + ldr FourthArg_Reg, DATA_SLOT(Constant2) + ldr x12, DATA_SLOT(Helper) + EPILOG_BRANCH_REG x12 + LEAF_END + + ; Generic dictionaries can have 2 or 3 indirections (5 indirs of 32bit size, and 2 8 byte quantities) = 40 bytes + ; If it has 2 its for a Method, and the first indirection is always offsetof(InstantiatiedMethodDesc, m_pPerInstInfo) + ; If it has 3 its for a Class, and the first indirection is always MethodTable::GetOffsetOfPerInstInfo + ; It can also have 0, 0, to just return the class type + ; Test For Null Or Not (If not present, cannot have a size check) + ; SizeCheck or not (Only needed if size > Some number) + ; + ; Also special case where we just return the TypeHandle or MethodDesc itself + ; Should probably have special case for 1, 2, 3 generic arg of MethodDesc/MethodTable + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull + ; Save Generic Context + mov x4, FirstArg_Reg + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SecondIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; SizeCheck + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SizeOffset) + ldr ThirdArg_DwordReg, GENERIC_DICT_DATA_SLOT(SlotOffset) + ldr FourthArg_Reg, [FirstArg_Reg, SecondArg_Reg] + cmp FourthArg_Reg, ThirdArg_Reg + b.ls DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; Null test + cbz FirstArg_Reg, DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall + ret lr +DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull_HelperCall + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + ldr x3, =g_pClassWithSlotAndModule + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_TestForNull + ; Save Generic Context + mov x4, FirstArg_Reg + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SecondIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; Null test + cbz FirstArg_Reg, DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall + ret lr +DynamicHelper_GenericDictionaryLookup_Class_TestForNull_HelperCall + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + ldr x3, =g_pClassWithSlotAndModule + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SecondIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull + ; Save Generic Context + mov x4, FirstArg_Reg + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; SizeCheck + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(SizeOffset) + ldr ThirdArg_DwordReg, GENERIC_DICT_DATA_SLOT(SlotOffset) + ldr FourthArg_Reg, [FirstArg_Reg, SecondArg_Reg] + cmp FourthArg_Reg, ThirdArg_Reg + b.ls DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; Null test + cbz FirstArg_Reg, DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall + ret lr +DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull_HelperCall + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + ldr x3, =g_pMethodWithSlotAndModule + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_TestForNull + ; Save Generic Context + mov x4, FirstArg_Reg + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ; Null test + cbz FirstArg_Reg, DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall + ret lr +DynamicHelper_GenericDictionaryLookup_Method_TestForNull_HelperCall + mov FirstArg_Reg, x4 + ldr SecondArg_Reg, GENERIC_DICT_DATA_SLOT(HandleArgs) + ldr x3, =g_pMethodWithSlotAndModule + ldr x3, [x3] + EPILOG_BRANCH_REG x3 + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + ldr SecondArg_DwordReg, GENERIC_DICT_DATA_SLOT(LastIndir) + ldr FirstArg_Reg, [SecondArg_Reg, FirstArg_Reg] + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_0 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ret lr + LEAF_END + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_1 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x8] + ret lr + LEAF_END + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_2 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x10] + ret lr + LEAF_END + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Class_0_3 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__MethodTable__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x18] + ret lr + LEAF_END + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_0 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg] + ret lr + LEAF_END + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_1 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x8] + ret lr + LEAF_END + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_2 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x10] + ret lr + LEAF_END + + + LEAF_ENTRY DynamicHelper_GenericDictionaryLookup_Method_3 + ; First indirection + ldr FirstArg_Reg, [FirstArg_Reg, #OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo] + ; Standard Indirection + ldr FirstArg_Reg, [FirstArg_Reg, #0x18] + ret lr + LEAF_END + +#endif ;; FEATURE_STUBPRECODE_DYNAMIC_HELPERS + + END diff --git a/src/coreclr/vm/arm64/asmconstants.h b/src/coreclr/vm/arm64/asmconstants.h index 476bd6f7f0b3c9..ade900bbf84e3d 100644 --- a/src/coreclr/vm/arm64/asmconstants.h +++ b/src/coreclr/vm/arm64/asmconstants.h @@ -36,6 +36,9 @@ ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::Inline #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 +#define ThisPtrRetBufPrecodeData__Target 0x00 +ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target)); + #define Thread__m_fPreemptiveGCDisabled 0x04 #define Thread__m_pFrame 0x08 @@ -113,6 +116,41 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__Frame == sizeof(Frame)); #endif ASMCONSTANTS_C_ASSERT(SIZEOF__CONTEXT == sizeof(T_CONTEXT)); +#define OFFSETOF__DynamicHelperStubArgs__Constant1 0x0 +ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicHelperStubArgs__Constant1 + == offsetof(DynamicHelperStubArgs, Constant1)); + +#define OFFSETOF__DynamicHelperStubArgs__Constant2 0x8 +ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicHelperStubArgs__Constant2 + == offsetof(DynamicHelperStubArgs, Constant2)); + +#define OFFSETOF__DynamicHelperStubArgs__Helper 0x10 +ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicHelperStubArgs__Helper + == offsetof(DynamicHelperStubArgs, Helper)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__SecondIndir 0x0 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__SecondIndir + == offsetof(GenericDictionaryDynamicHelperStubData, SecondIndir)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__LastIndir 0x4 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__LastIndir + == offsetof(GenericDictionaryDynamicHelperStubData, LastIndir)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__SizeOffset 0x8 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__SizeOffset + == offsetof(GenericDictionaryDynamicHelperStubData, SizeOffset)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__SlotOffset 0xc +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__SlotOffset + == offsetof(GenericDictionaryDynamicHelperStubData, SlotOffset)); + +#define OFFSETOF__GenericDictionaryDynamicHelperStubData__HandleArgs 0x10 +ASMCONSTANTS_C_ASSERT(OFFSETOF__GenericDictionaryDynamicHelperStubData__HandleArgs + == offsetof(GenericDictionaryDynamicHelperStubData, HandleArgs)); + +#define OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo DBG_FRE(0x40, 0x18) +ASMCONSTANTS_C_ASSERT(OFFSETOF__InstantiatedMethodDesc__m_pPerInstInfo + == offsetof(InstantiatedMethodDesc, m_pPerInstInfo)); //========================================= #define MethodTable__m_dwFlags 0x0 @@ -121,6 +159,10 @@ ASMCONSTANTS_C_ASSERT(MethodTable__m_dwFlags == offsetof(MethodTable, m_dwFlags) #define MethodTable__m_BaseSize 0x04 ASMCONSTANTS_C_ASSERT(MethodTable__m_BaseSize == offsetof(MethodTable, m_BaseSize)); +#define OFFSETOF__MethodTable__m_pPerInstInfo DBG_FRE(0x38, 0x30) +ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodTable__m_pPerInstInfo + == offsetof(MethodTable, m_pPerInstInfo)); + #define MethodTable__m_ElementType DBG_FRE(0x38, 0x30) ASMCONSTANTS_C_ASSERT(MethodTable__m_ElementType == offsetof(MethodTable, m_ElementTypeHnd)); diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index d1336d71eaba65..5fac7fae7aa838 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -851,3 +851,13 @@ NESTED_ENTRY InterpreterStub, _TEXT, NoHandler NESTED_END InterpreterStub, _TEXT #endif // FEATURE_INTERPRETER + +//x0 -This pointer +//x1 -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + ldr x12, [METHODDESC_REGISTER, #ThisPtrRetBufPrecodeData__Target] + mov x11, x0 // Move first arg pointer to temp register + mov x0, x1 // Move ret buf arg pointer from location in ABI for return buffer for instance method to location in ABI for return buffer for static method + mov x1, x11 // Move temp register to first arg register for static method with return buffer + EPILOG_BRANCH_REG x12 +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index f0cb2a27f1da39..3dd6edcb34ab2b 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -1235,5 +1235,15 @@ JIT_PollGCRarePath NESTED_END #endif // FEATURE_INTERPRETER +;x0 -This pointer +;x1 -ReturnBuffer + LEAF_ENTRY ThisPtrRetBufPrecodeWorker + ldr x12, [METHODDESC_REGISTER, #ThisPtrRetBufPrecodeData__Target] + mov x11, x0 ; Move first arg pointer to temp register + mov x0, x1 ; Move ret buf arg pointer from location in ABI for return buffer for instance method to location in ABI for return buffer for static method + mov x1, x11 ; Move temp register to first arg register for static method with return buffer + EPILOG_BRANCH_REG x12 + LEAF_END + ; Must be at very end of file END diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index 6e875ebe6c439d..c016515df827ce 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -544,46 +544,4 @@ struct HijackArgs }; }; -// Precode to shuffle this and retbuf for closed delegates over static methods with return buffer -struct ThisPtrRetBufPrecode { - - static const int Type = 0x10; - - UINT32 m_rgCode[6]; - TADDR m_pTarget; - TADDR m_pMethodDesc; - - void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); - - TADDR GetMethodDesc() - { - LIMITED_METHOD_DAC_CONTRACT; - - return m_pMethodDesc; - } - - PCODE GetTarget() - { - LIMITED_METHOD_DAC_CONTRACT; - return m_pTarget; - } - -#ifndef DACCESS_COMPILE - BOOL SetTargetInterlocked(TADDR target, TADDR expected) - { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - } - CONTRACTL_END; - - ExecutableWriterHolder precodeWriterHolder(this, sizeof(ThisPtrRetBufPrecode)); - return (TADDR)InterlockedCompareExchange64( - (LONGLONG*)&precodeWriterHolder.GetRW()->m_pTarget, (TADDR)target, (TADDR)expected) == expected; - } -#endif // !DACCESS_COMPILE -}; -typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; - #endif // __cgencpu_h__ diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index d9a97484359644..4e6a79dfa3b83f 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -537,31 +537,6 @@ void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool update ClearRegDisplayArgumentAndScratchRegisters(pRD); } -#ifndef DACCESS_COMPILE -void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) -{ - WRAPPER_NO_CONTRACT; - - int n = 0; - //Initially - //x0 -This ptr - //x1 -ReturnBuffer - m_rgCode[n++] = 0x91000010; // mov x16, x0 - m_rgCode[n++] = 0x91000020; // mov x0, x1 - m_rgCode[n++] = 0x91000201; // mov x1, x16 - m_rgCode[n++] = 0x58000070; // ldr x16, [pc, #12] - _ASSERTE((UINT32*)&m_pTarget == &m_rgCode[n + 2]); - m_rgCode[n++] = 0xd61f0200; // br x16 - n++; // empty 4 bytes for data alignment below - _ASSERTE(n == ARRAY_SIZE(m_rgCode)); - - - m_pTarget = GetPreStubEntryPoint(); - m_pMethodDesc = (TADDR)pMD; -} - -#endif // !DACCESS_COMPILE - void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * pCalleeSaved) { LIMITED_METHOD_CONTRACT; @@ -1468,6 +1443,7 @@ void StubLinkerCPU::EmitCallManagedMethod(MethodDesc *pMD, BOOL fTailCall) // // Allocation of dynamic helpers // +#ifndef FEATURE_STUBPRECODE_DYNAMIC_HELPERS #define DYNAMIC_HELPER_ALIGNMENT sizeof(TADDR) @@ -1939,6 +1915,7 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, END_DYNAMIC_HELPER_EMIT(); } } +#endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif // FEATURE_READYTORUN diff --git a/src/coreclr/vm/callcounting.h b/src/coreclr/vm/callcounting.h index 34bbf526225fc0..8073e860f5e88c 100644 --- a/src/coreclr/vm/callcounting.h +++ b/src/coreclr/vm/callcounting.h @@ -101,6 +101,8 @@ class CallCountingStub static const SIZE_T CodeSize = 40; #elif defined(TARGET_RISCV64) static const SIZE_T CodeSize = 40; +#elif defined(TARGET_WASM) + static const SIZE_T CodeSize = 0; #endif private: diff --git a/src/coreclr/vm/callingconvention.h b/src/coreclr/vm/callingconvention.h index 63a92f9b1fbcf5..5b167300ec856d 100644 --- a/src/coreclr/vm/callingconvention.h +++ b/src/coreclr/vm/callingconvention.h @@ -186,6 +186,16 @@ struct TransitionBlock }; TADDR padding; // Keep size of TransitionBlock as multiple of 16-byte. Simplifies code in PROLOG_WITH_TRANSITION_BLOCK ArgumentRegisters m_argumentRegisters; +#elif defined(TARGET_WASM) + // No transition block on WASM yet + union { + CalleeSavedRegisters m_calleeSavedRegisters; + // alias saved link register as m_ReturnAddress + struct { + TADDR m_ReturnAddress; + }; + }; + ArgumentRegisters m_argumentRegisters; #else PORTABILITY_ASSERT("TransitionBlock"); #endif @@ -924,6 +934,16 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE } #endif // TARGET_LOONGARCH64 || TARGET_RISCV64 + +#ifdef TARGET_WASM + + // Get layout information for the argument that the ArgIterator is currently visiting. + void GetArgLoc(int argOffset, ArgLocDesc *pLoc) + { + _ASSERTE(!"GetArgLoc not implemented for WASM"); + } +#endif // TARGET_WASM + protected: DWORD m_dwFlags; // Cached flags int m_nSizeOfArgStack; // Cached value of SizeOfArgStack diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index ffdd7dd2246cfa..567c5b03d91fb7 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -2191,21 +2191,18 @@ void ModuleBase::InitializeStringData(DWORD token, EEStringData *pstrData, CQuic } -OBJECTHANDLE ModuleBase::ResolveStringRef(DWORD token, void** ppPinnedString) +STRINGREF* ModuleBase::ResolveStringRef(DWORD token, void** ppPinnedString) { CONTRACTL { INSTANCE_CHECK; - THROWS; - GC_TRIGGERS; - MODE_ANY; + STANDARD_VM_CHECK; INJECT_FAULT(COMPlusThrowOM()); PRECONDITION(TypeFromToken(token) == mdtString); } CONTRACTL_END; EEStringData strData; - OBJECTHANDLE string = NULL; #if !BIGENDIAN InitializeStringData(token, &strData, NULL); @@ -2215,14 +2212,8 @@ OBJECTHANDLE ModuleBase::ResolveStringRef(DWORD token, void** ppPinnedString) #endif // !!BIGENDIAN GCX_COOP(); - - LoaderAllocator *pLoaderAllocator; - - pLoaderAllocator = this->GetLoaderAllocator(); - - string = (OBJECTHANDLE)pLoaderAllocator->GetStringObjRefPtrFromUnicodeString(&strData, ppPinnedString); - - return string; + LoaderAllocator* pLoaderAllocator = this->GetLoaderAllocator(); + return pLoaderAllocator->GetStringObjRefPtrFromUnicodeString(&strData, ppPinnedString); } mdToken Module::GetEntryPointToken() diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 9f6c87e5d787e5..fa11dd2ce20e36 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -578,7 +578,7 @@ class ModuleBase } // Resolving - OBJECTHANDLE ResolveStringRef(DWORD Token, void** ppPinnedString = nullptr); + STRINGREF* ResolveStringRef(DWORD Token, void** ppPinnedString = nullptr); private: // string helper void InitializeStringData(DWORD token, EEStringData *pstrData, CQuickBytes *pqb); diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 12b02c90a39ba4..0a26fe9076ff83 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1551,17 +1551,7 @@ void EEJitManager::SetCpuInfo() #if defined(TARGET_X86) || defined(TARGET_AMD64) - // Clean up mutually exclusive ISAs - if (CPUCompileFlags.IsSet(InstructionSet_VectorT512)) - { - CPUCompileFlags.Clear(InstructionSet_VectorT256); - CPUCompileFlags.Clear(InstructionSet_VectorT128); - } - else if (CPUCompileFlags.IsSet(InstructionSet_VectorT256)) - { - CPUCompileFlags.Clear(InstructionSet_VectorT128); - } - + bool throttleVector512 = false; int cpuidInfo[4]; const int CPUID_EAX = 0; @@ -1614,7 +1604,7 @@ void EEJitManager::SetCpuInfo() // * Cascade Lake // * Cooper Lake - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_VECTOR512_THROTTLING); + throttleVector512 = true; } } else if (xarchCpuInfo.ExtendedModelId == 0x06) @@ -1623,11 +1613,54 @@ void EEJitManager::SetCpuInfo() { // * Cannon Lake - CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_VECTOR512_THROTTLING); + throttleVector512 = true; } } } } + + // If we have a PreferredVectorBitWidth, we will pass that to JIT in the form of a virtual vector ISA of the + // appropriate size. We will also clamp the max Vector size to be no larger than PreferredVectorBitWidth, + // because JIT maps Vector to the fixed-width vector of matching size for the purposes of intrinsic + // resolution. We want to avoid a situation where e.g. Vector.IsHardwareAccelerated returns false + // because Vector512.IsHardwareAccelerated returns false due to config or automatic throttling. + + uint32_t preferredVectorBitWidth = (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PreferredVectorBitWidth) / 128) * 128; + + if ((preferredVectorBitWidth == 0) && throttleVector512) + { + preferredVectorBitWidth = 256; + } + + if (preferredVectorBitWidth >= 512) + { + CPUCompileFlags.Set(InstructionSet_Vector512); + } + else if (preferredVectorBitWidth >= 256) + { + CPUCompileFlags.Set(InstructionSet_Vector256); + CPUCompileFlags.Clear(InstructionSet_VectorT512); + } + else if (preferredVectorBitWidth != 0) + { + CPUCompileFlags.Set(InstructionSet_Vector128); + CPUCompileFlags.Clear(InstructionSet_VectorT512); + CPUCompileFlags.Clear(InstructionSet_VectorT256); + } + + // Only one VectorT ISA can be set, and we have validated that anything left in the flags is supported + // by both the hardware and the config. Remove everything less than the largest supported. + + if (CPUCompileFlags.IsSet(InstructionSet_VectorT512)) + { + CPUCompileFlags.Clear(InstructionSet_VectorT256); + CPUCompileFlags.Clear(InstructionSet_VectorT128); + } + else if (CPUCompileFlags.IsSet(InstructionSet_VectorT256)) + { + CPUCompileFlags.Clear(InstructionSet_VectorT128); + } + #endif // TARGET_X86 || TARGET_AMD64 m_CPUCompileFlags = CPUCompileFlags; diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index 9ff3492a399b9c..35c149355fae27 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -92,7 +92,7 @@ enum StubCodeBlockKind : int { STUB_CODE_BLOCK_UNKNOWN = 0, STUB_CODE_BLOCK_JUMPSTUB = 1, - STUB_CODE_BLOCK_PRECODE = 2, + UNUSED = 2, STUB_CODE_BLOCK_DYNAMICHELPER = 3, STUB_CODE_BLOCK_STUBPRECODE = 4, STUB_CODE_BLOCK_FIXUPPRECODE = 5, @@ -105,11 +105,11 @@ enum StubCodeBlockKind : int // Last valid value. Note that the definition is duplicated in debug\daccess\fntableaccess.cpp STUB_CODE_BLOCK_LAST = 0xF, // Placeholders returned by code:GetStubCodeBlockKind - STUB_CODE_BLOCK_NOCODE, - STUB_CODE_BLOCK_MANAGED, - STUB_CODE_BLOCK_STUBLINK, + STUB_CODE_BLOCK_NOCODE = 0x10, + STUB_CODE_BLOCK_MANAGED = 0x11, + STUB_CODE_BLOCK_STUBLINK = 0x12, // Placeholdes used by ReadyToRun images - STUB_CODE_BLOCK_METHOD_CALL_THUNK, + STUB_CODE_BLOCK_METHOD_CALL_THUNK = 0x13, }; //----------------------------------------------------------------------------- @@ -2565,6 +2565,10 @@ class EECodeInfo } #endif // TARGET_X86 +#if defined(TARGET_WASM) +ULONG GetFixedStackSize(); +#endif + #if defined(TARGET_AMD64) BOOL HasFrameRegister(); ULONG GetFixedStackSize(); diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index b2e9dd295d02ee..7234839e886b86 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -73,7 +73,7 @@ #include -#ifdef HOST_AMD64 +#if defined(HOST_AMD64) || defined(HOST_X86) #include #endif diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index e483a08eb1d670..a5d9eb2037b536 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -835,6 +835,7 @@ DEFINE_METHOD(STRING, CTORF_SBYTEPTR_START_LEN_ENCODING, Ctor, DEFINE_METHOD(STRING, INTERNAL_COPY, InternalCopy, SM_Str_IntPtr_Int_RetVoid) DEFINE_METHOD(STRING, WCSLEN, wcslen, SM_PtrChar_RetInt) DEFINE_METHOD(STRING, STRLEN, strlen, SM_PtrByte_RetInt) +DEFINE_METHOD(STRING, STRCNS, StrCns, SM_UInt_IntPtr_RetStr) DEFINE_PROPERTY(STRING, LENGTH, Length, Int) DEFINE_CLASS(STRING_BUILDER, Text, StringBuilder) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index fe435ce8d569dc..b3f4a568a6696f 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -48,7 +48,7 @@ void SafeExitProcess(UINT exitCode, ShutdownCompleteAction sca = SCA_ExitProcess { _ASSERTE(!"Bad Exit value"); FAULT_NOT_FATAL(); // if we OOM we can simply give up - fprintf(stderr, "Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); + minipal_log_print_error("Error 0x%08x.\n\nBreakOnBadExit: returning bad exit code.", exitCode); DebugBreak(); } } @@ -233,8 +233,9 @@ class CallStackLogger MethodDesc* pMD = m_frames[index]; TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature); + str.Append(W("\n")); + PrintToStdErrW(str.GetUnicode()); - PrintToStdErrA("\n"); } public: @@ -265,6 +266,7 @@ class CallStackLogger repeatStr.AppendPrintf("Repeated %d times:\n", m_largestCommonStartRepeat); PrintToStdErrW(repeatStr.GetUnicode()); + PrintToStdErrA("--------------------------------\n"); for (int i = 0; i < m_largestCommonStartLength; i++) { @@ -373,11 +375,11 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS { if (exitCode == (UINT)COR_E_FAILFAST) { - PrintToStdErrA("Process terminated. "); + PrintToStdErrA("Process terminated.\n"); } else { - PrintToStdErrA("Fatal error. "); + PrintToStdErrA("Fatal error.\n"); } if (errorSource != NULL) @@ -393,9 +395,9 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, PEXCEPTION_POINTERS else { // If no message was passed in, generate it from the exitCode - SString exitCodeMessage; + InlineSString<256> exitCodeMessage; GetHRMsg(exitCode, exitCodeMessage); - PrintToStdErrW((LPCWSTR)exitCodeMessage); + PrintToStdErrW(exitCodeMessage.GetUnicode()); } PrintToStdErrA("\n"); diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index fb6c0c3feeda09..2be358789efc59 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -11,6 +11,7 @@ #include "ep-rt-coreclr.h" #include #include +#include #include #include #include @@ -404,10 +405,10 @@ ds_rt_server_log_pause_message (void) uint32_t port_suspended = ds_rt_config_value_get_default_port_suspend(); - printf("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); - printf("DOTNET_%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports); - printf("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended); - fflush(stdout); + minipal_log_print_info("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); + minipal_log_print_info("DOTNET_%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports); + minipal_log_print_info("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended); + minipal_log_flush_info(); } #endif /* ENABLE_PERFTRACING */ diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 7bd720baf28676..2bef68c8814e95 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4756,8 +4756,6 @@ LONG __stdcall COMUnhandledExceptionFilter( // EXCEPTION_CONTINUE_SEARCH or #pragma code_seg(pop, uef) #endif // !TARGET_UNIX -void PrintStackTraceToStdout(); - static SString GetExceptionMessageWrapper(Thread* pThread, OBJECTREF throwable) { STATIC_CONTRACT_THROWS; @@ -4788,17 +4786,17 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, wcsncpy_s(buf, buf_size, SZ_UNHANDLED_EXCEPTION, SZ_UNHANDLED_EXCEPTION_CHARLEN); } - PrintToStdErrW(buf); - PrintToStdErrA(" "); - - SString message = GetExceptionMessageWrapper(pThread, throwable); + SString message(buf); + SString exceptionMessage = GetExceptionMessageWrapper(pThread, throwable); - if (!message.IsEmpty()) + message.Append(W(" ")); + if (!exceptionMessage.IsEmpty()) { - PrintToStdErrW(message); + message.Append(exceptionMessage); } + message.Append(W("\n")); - PrintToStdErrA("\n"); + PrintToStdErrW(message.GetUnicode()); #if defined(FEATURE_EVENT_TRACE) && !defined(TARGET_UNIX) // Send the log to Windows Event Log @@ -5005,10 +5003,13 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, EX_CATCH { LOG((LF_EH, LL_INFO10, "Exception occurred while processing uncaught exception\n")); - UtilLoadStringRC(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf, buf_size); - PrintToStdErrA("\n "); + + _ASSERTE(buf_size > 6); + wcscpy_s(buf, buf_size, W("\n ")); + UtilLoadStringRC(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf + 4, buf_size - 6); + wcscat_s(buf, buf_size, W("\n")); + PrintToStdErrW(buf); - PrintToStdErrA("\n"); } EX_END_CATCH(SwallowAllExceptions); } diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 36ac51dba804ae..c4786039f7b5c1 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -5909,7 +5909,7 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo } pDispatcherContext->ControlPc = (UINT_PTR) GetIP(pDispatcherContext->ContextRecord); - + #if defined(TARGET_ARM64) // Since this routine is used to fixup contexts for async exceptions, // clear the CONTEXT_UNWOUND_TO_CALL flag since, semantically, frames @@ -8040,7 +8040,7 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg END_QCALL; } -extern "C" BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterIP, REGDISPLAY* pvRegDisplay) +extern "C" CLR_BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterIP, REGDISPLAY* pvRegDisplay) { QCALL_CONTRACT; @@ -8106,7 +8106,7 @@ struct ExtendedEHClauseEnumerator : EH_CLAUSE_ENUMERATOR unsigned EHCount; }; -extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo* pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum) +extern "C" CLR_BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo* pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum) { QCALL_CONTRACT; @@ -8128,10 +8128,10 @@ extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *p return pExtendedEHEnum->EHCount != 0; } -extern "C" BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause) +extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause) { QCALL_CONTRACT; - BOOL result = FALSE; + CLR_BOOL result = FALSE; BEGIN_QCALL; Thread* pThread = GET_THREAD(); @@ -8211,10 +8211,10 @@ extern uint32_t g_exceptionCount; MethodDesc * GetUserMethodForILStub(Thread * pThread, UINT_PTR uStubSP, MethodDesc * pILStubMD, Frame ** ppFrameOut); -static BOOL CheckExceptionInterception(StackFrameIterator* pStackFrameIterator, ExInfo *pExInfo) +static CLR_BOOL CheckExceptionInterception(StackFrameIterator* pStackFrameIterator, ExInfo *pExInfo) { // check if the exception is intercepted. - BOOL isIntercepted = FALSE; + CLR_BOOL isIntercepted = FALSE; if (pExInfo->m_ExceptionFlags.DebuggerInterceptInfo()) { MethodDesc *pMD = pStackFrameIterator->m_crawl.GetFunction(); @@ -8379,11 +8379,11 @@ static void NotifyFunctionEnter(StackFrameIterator *pThis, Thread *pThread, ExIn pExInfo->m_pMDToReportFunctionLeave = pMD; } -extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, bool instructionFault, bool* pfIsExceptionIntercepted) +extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, CLR_BOOL instructionFault, CLR_BOOL* pfIsExceptionIntercepted) { QCALL_CONTRACT; - bool result = false; + CLR_BOOL result = FALSE; Thread* pThread = GET_THREAD(); ExInfo* pExInfo = (ExInfo*)pThread->GetExceptionState()->GetCurrentExceptionTracker(); @@ -8531,7 +8531,7 @@ static StackWalkAction MoveToNextNonSkippedFrame(StackFrameIterator* pStackFrame bool IsCallDescrWorkerInternalReturnAddress(PCODE pCode); -extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideClauseIdx, bool* fUnwoundReversePInvoke, bool* pfIsExceptionIntercepted) +extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR_BOOL* fUnwoundReversePInvoke, CLR_BOOL* pfIsExceptionIntercepted) { QCALL_CONTRACT; @@ -8556,7 +8556,7 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla // Check for reverse pinvoke (but eliminate the case when the caller is managed) or CallDescrWorkerInternal. if (!ExecutionManager::IsManagedCode(GetIP(pThis->m_crawl.GetRegisterSet()->pCallerContext))) { - bool invalidRevPInvoke; + CLR_BOOL invalidRevPInvoke; #ifdef USE_GC_INFO_DECODER GcInfoDecoder gcInfoDecoder(pThis->m_crawl.GetCodeInfo()->GetGCInfoToken(), DECODE_REVERSE_PINVOKE_VAR); invalidRevPInvoke = gcInfoDecoder.GetReversePInvokeFrameStackSlot() != NO_REVERSE_PINVOKE_FRAME; @@ -8592,11 +8592,11 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla { if (IsCallDescrWorkerInternalReturnAddress(GetIP(pThis->m_crawl.GetRegisterSet()->pCallerContext))) { - invalidRevPInvoke = true; + invalidRevPInvoke = TRUE; } else if (pThis->m_crawl.IsFilterFunclet()) { - invalidRevPInvoke = true; + invalidRevPInvoke = TRUE; } else { @@ -8653,7 +8653,7 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla { if (fUnwoundReversePInvoke) { - *fUnwoundReversePInvoke = false; + *fUnwoundReversePInvoke = FALSE; } } @@ -8762,10 +8762,10 @@ Exit:; *pfIsExceptionIntercepted = CheckExceptionInterception(pThis, pTopExInfo); - return true; + return TRUE; } - return false; + return FALSE; } namespace AsmOffsetsAsserts diff --git a/src/coreclr/vm/exceptionhandlingqcalls.h b/src/coreclr/vm/exceptionhandlingqcalls.h index 7054080cef3c00..fd1feccef6cb91 100644 --- a/src/coreclr/vm/exceptionhandlingqcalls.h +++ b/src/coreclr/vm/exceptionhandlingqcalls.h @@ -14,13 +14,13 @@ struct ExInfo; extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo); extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo); -extern "C" BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterP, REGDISPLAY* pvRegDisplay); +extern "C" CLR_BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterP, REGDISPLAY* pvRegDisplay); extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay); extern "C" void QCALLTYPE AppendExceptionStackFrame(QCall::ObjectHandleOnStack exceptionObj, SIZE_T ip, SIZE_T sp, int flags, ExInfo *pExInfo); -extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo *pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum); -extern "C" BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause); -extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, bool instructionFault, bool* pIsExceptionIntercepted); -extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, unsigned int* uExCollideClauseIdx, bool* fUnwoundReversePInvoke, bool* pIsExceptionIntercepted); +extern "C" CLR_BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo *pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum); +extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause); +extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, CLR_BOOL instructionFault, CLR_BOOL* pIsExceptionIntercepted); +extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, unsigned int* uExCollideClauseIdx, CLR_BOOL* fUnwoundReversePInvoke, CLR_BOOL* pIsExceptionIntercepted); #endif // DACCESS_COMPILE #endif // FEATURE_EH_FUNCLETS diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index be519af3b9b239..a8423816bc48d9 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -729,6 +729,9 @@ class ResumableFrame : public Frame #elif defined(TARGET_RISCV64) Object** firstIntReg = (Object**)&this->GetContext()->Gp; Object** lastIntReg = (Object**)&this->GetContext()->T6; +#elif defined(TARGET_WASM) + Object** firstIntReg = nullptr; + Object** lastIntReg = nullptr; #else _ASSERTE(!"nyi for platform"); #endif @@ -742,6 +745,14 @@ class ResumableFrame : public Frame protected: PTR_CONTEXT m_Regs; + + friend struct cdac_data; +}; + +template<> +struct cdac_data +{ + static constexpr size_t TargetContextPtr = offsetof(ResumableFrame, m_Regs); }; @@ -1011,6 +1022,16 @@ class FaultingExceptionFrame : public Frame } void UpdateRegDisplay_Impl(const PREGDISPLAY, bool updateFloats = false); + + friend struct ::cdac_data; +}; + +template<> +struct cdac_data +{ +#ifdef FEATURE_EH_FUNCLETS + static constexpr size_t TargetContext = offsetof(FaultingExceptionFrame, m_ctx); +#endif // FEATURE_EH_FUNCLETS }; #ifdef FEATURE_EH_FUNCLETS @@ -1152,6 +1173,14 @@ class FuncEvalFrame : public Frame return m_showFrame; } + + friend struct cdac_data; +}; + +template<> +struct cdac_data +{ + static constexpr size_t DebuggerEvalPtr = offsetof(FuncEvalFrame, m_pDebuggerEval); }; typedef DPTR(FuncEvalFrame) PTR_FuncEvalFrame; @@ -1669,8 +1698,15 @@ class FramedMethodFrame : public TransitionFrame #endif return dac_cast(p); } + + friend struct cdac_data; }; +template<> +struct cdac_data +{ + static constexpr size_t TransitionBlockPtr = offsetof(FramedMethodFrame, m_pTransitionBlock); +}; #ifdef FEATURE_COMINTEROP @@ -1963,6 +1999,15 @@ class HijackFrame : public Frame TADDR m_ReturnAddress; PTR_Thread m_Thread; DPTR(HijackArgs) m_Args; + + friend struct ::cdac_data; +}; + +template<> +struct cdac_data +{ + static constexpr size_t ReturnAddress = offsetof(HijackFrame, m_ReturnAddress); + static constexpr size_t HijackArgsPtr = offsetof(HijackFrame, m_Args); }; #endif // FEATURE_HIJACK diff --git a/src/coreclr/vm/gccover.cpp b/src/coreclr/vm/gccover.cpp index d0789dd6b37b07..05e767c0325598 100644 --- a/src/coreclr/vm/gccover.cpp +++ b/src/coreclr/vm/gccover.cpp @@ -401,12 +401,6 @@ static MethodDesc* getTargetMethodDesc(PCODE target) } } - if (stubKind == STUB_CODE_BLOCK_PRECODE) - { - // The address looks like a value stub, try to get the method descriptor. - return MethodDesc::GetMethodDescFromStubAddr(target, TRUE); - } - if (stubKind == STUB_CODE_BLOCK_STUBPRECODE) { Precode* pPrecode = Precode::GetPrecodeFromEntryPoint(target); @@ -414,6 +408,7 @@ static MethodDesc* getTargetMethodDesc(PCODE target) { case PRECODE_STUB: case PRECODE_NDIRECT_IMPORT: + case PRECODE_THISPTR_RETBUF: return dac_cast(pPrecode->AsStubPrecode()->GetMethodDesc()); default: return nullptr; diff --git a/src/coreclr/vm/gcinfodecoder.cpp b/src/coreclr/vm/gcinfodecoder.cpp index 1b11a3e8f7ceee..bccb5313b6a0d9 100644 --- a/src/coreclr/vm/gcinfodecoder.cpp +++ b/src/coreclr/vm/gcinfodecoder.cpp @@ -72,9 +72,9 @@ } #endif // !LOG_PIPTR -bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback) +template bool TGcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback) { - GcInfoDecoder *pThis = (GcInfoDecoder*)hCallback; + TGcInfoDecoder *pThis = (TGcInfoDecoder*)hCallback; bool fStop = pThis->m_InstructionOffset >= startOffset && pThis->m_InstructionOffset < stopOffset; @@ -86,7 +86,7 @@ bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, } // returns true if we decoded all that was asked; -bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) +template bool TGcInfoDecoder::PredecodeFatHeader(int remainingFlags) { int numFlagBits = (m_Version == 1) ? GC_INFO_FLAGS_BIT_SIZE_VERSION_1 : GC_INFO_FLAGS_BIT_SIZE; m_headerFlags = (GcInfoHeaderFlags)m_Reader.Read(numFlagBits); @@ -101,7 +101,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) return true; } - m_CodeLength = (UINT32)DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(CODE_LENGTH_ENCBASE)); + m_CodeLength = GcInfoEncoding::DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::CODE_LENGTH_ENCBASE)); remainingFlags &= ~DECODE_CODE_LENGTH; if (remainingFlags == 0) { @@ -113,21 +113,21 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) { // Note that normalization as a code offset can be different than // normalization as code length - UINT32 normCodeLength = NORMALIZE_CODE_OFFSET(m_CodeLength); + UINT32 normCodeLength = GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength); // Decode prolog/epilog information - UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(NORM_PROLOG_SIZE_ENCBASE) + 1; - UINT32 normEpilogSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(NORM_EPILOG_SIZE_ENCBASE); + UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NORM_PROLOG_SIZE_ENCBASE) + 1; + UINT32 normEpilogSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NORM_EPILOG_SIZE_ENCBASE); - m_ValidRangeStart = (UINT32)DENORMALIZE_CODE_OFFSET(normPrologSize); - m_ValidRangeEnd = (UINT32)DENORMALIZE_CODE_OFFSET(normCodeLength - normEpilogSize); + m_ValidRangeStart = GcInfoEncoding::DENORMALIZE_CODE_OFFSET(normPrologSize); + m_ValidRangeEnd = GcInfoEncoding::DENORMALIZE_CODE_OFFSET(normCodeLength - normEpilogSize); _ASSERTE(m_ValidRangeStart < m_ValidRangeEnd); } else if ((m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE) { // Decode prolog information - UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(NORM_PROLOG_SIZE_ENCBASE) + 1; - m_ValidRangeStart = (UINT32)DENORMALIZE_CODE_OFFSET(normPrologSize); + UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NORM_PROLOG_SIZE_ENCBASE) + 1; + m_ValidRangeStart = GcInfoEncoding::DENORMALIZE_CODE_OFFSET(normPrologSize); // satisfy asserts that assume m_GSCookieValidRangeStart != 0 ==> m_GSCookieValidRangeStart < m_GSCookieValidRangeEnd m_ValidRangeEnd = m_ValidRangeStart + 1; } @@ -146,7 +146,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) // Decode the offset to the GS cookie. if (m_headerFlags & GC_INFO_HAS_GS_COOKIE) { - m_GSCookieStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(GS_COOKIE_STACK_SLOT_ENCBASE)); + m_GSCookieStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::GS_COOKIE_STACK_SLOT_ENCBASE)); } else { @@ -164,7 +164,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) // The PSPSym is relative to the caller SP on IA64 and the initial stack pointer before any stack allocation on X64 (InitialSP). if (m_headerFlags & GC_INFO_HAS_PSP_SYM) { - m_PSPSymStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(PSP_SYM_STACK_SLOT_ENCBASE)); + m_PSPSymStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::PSP_SYM_STACK_SLOT_ENCBASE)); } else { @@ -181,7 +181,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) // Decode the offset to the generics type context. if ((m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE) { - m_GenericsInstContextStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE)); + m_GenericsInstContextStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE)); } else { @@ -197,7 +197,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) if (m_headerFlags & GC_INFO_HAS_STACK_BASE_REGISTER) { - m_StackBaseRegister = (UINT32)DENORMALIZE_STACK_BASE_REGISTER(m_Reader.DecodeVarLengthUnsigned(STACK_BASE_REGISTER_ENCBASE)); + m_StackBaseRegister = GcInfoEncoding::DENORMALIZE_STACK_BASE_REGISTER((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_BASE_REGISTER_ENCBASE)); } else { @@ -206,9 +206,9 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) if (m_headerFlags & GC_INFO_HAS_EDIT_AND_CONTINUE_INFO) { - m_SizeOfEditAndContinuePreservedArea = (UINT32)m_Reader.DecodeVarLengthUnsigned(SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE); + m_SizeOfEditAndContinuePreservedArea = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE); #ifdef TARGET_ARM64 - m_SizeOfEditAndContinueFixedStackFrame = (UINT32)m_Reader.DecodeVarLengthUnsigned(SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE); + m_SizeOfEditAndContinueFixedStackFrame = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE); #endif } else @@ -228,7 +228,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) if (m_headerFlags & GC_INFO_REVERSE_PINVOKE_FRAME) { - m_ReversePInvokeFrameStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(REVERSE_PINVOKE_FRAME_ENCBASE)); + m_ReversePInvokeFrameStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::REVERSE_PINVOKE_FRAME_ENCBASE)); } else { @@ -243,13 +243,14 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) } #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - m_SizeOfStackOutgoingAndScratchArea = (UINT32)DENORMALIZE_SIZE_OF_STACK_AREA(m_Reader.DecodeVarLengthUnsigned(SIZE_OF_STACK_AREA_ENCBASE)); + m_SizeOfStackOutgoingAndScratchArea = GcInfoEncoding::DENORMALIZE_SIZE_OF_STACK_AREA((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::SIZE_OF_STACK_AREA_ENCBASE)); #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA return false; } -GcInfoDecoder::GcInfoDecoder( +template +TGcInfoDecoder::TGcInfoDecoder( GCInfoToken gcInfoToken, GcInfoDecoderFlags flags, UINT32 breakOffset @@ -288,7 +289,7 @@ GcInfoDecoder::GcInfoDecoder( if (m_Reader.ReadOneFast()) { m_headerFlags = GC_INFO_HAS_STACK_BASE_REGISTER; - m_StackBaseRegister = (UINT32)DENORMALIZE_STACK_BASE_REGISTER(0); + m_StackBaseRegister = GcInfoEncoding::DENORMALIZE_STACK_BASE_REGISTER(0); } else { @@ -307,7 +308,7 @@ GcInfoDecoder::GcInfoDecoder( return; } - m_CodeLength = (UINT32)DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(CODE_LENGTH_ENCBASE)); + m_CodeLength = GcInfoEncoding::DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::CODE_LENGTH_ENCBASE)); // // predecoding the rest of slim header does not require any reading. @@ -346,7 +347,7 @@ GcInfoDecoder::GcInfoDecoder( } #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - m_NumSafePoints = (UINT32) DENORMALIZE_NUM_SAFE_POINTS(m_Reader.DecodeVarLengthUnsigned(NUM_SAFE_POINTS_ENCBASE)); + m_NumSafePoints = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_SAFE_POINTS_ENCBASE); m_SafePointIndex = m_NumSafePoints; #endif @@ -356,7 +357,7 @@ GcInfoDecoder::GcInfoDecoder( } else { - m_NumInterruptibleRanges = (UINT32) DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(m_Reader.DecodeVarLengthUnsigned(NUM_INTERRUPTIBLE_RANGES_ENCBASE)); + m_NumInterruptibleRanges = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_INTERRUPTIBLE_RANGES_ENCBASE); } #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -371,7 +372,7 @@ GcInfoDecoder::GcInfoDecoder( { // Note that normalization as a code offset can be different than // normalization as code length - UINT32 normCodeLength = NORMALIZE_CODE_OFFSET(m_CodeLength); + UINT32 normCodeLength = GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength); UINT32 numBitsPerOffset = CeilOfLog2(normCodeLength); m_Reader.Skip(m_NumSafePoints * numBitsPerOffset); @@ -390,25 +391,25 @@ GcInfoDecoder::GcInfoDecoder( } } -bool GcInfoDecoder::IsInterruptible() +template bool TGcInfoDecoder::IsInterruptible() { _ASSERTE( m_Flags & DECODE_INTERRUPTIBILITY ); return m_IsInterruptible; } -bool GcInfoDecoder::HasInterruptibleRanges() +template bool TGcInfoDecoder::HasInterruptibleRanges() { _ASSERTE(m_Flags & (DECODE_INTERRUPTIBILITY | DECODE_GC_LIFETIMES)); return m_NumInterruptibleRanges > 0; } -bool GcInfoDecoder::IsSafePoint() +template bool TGcInfoDecoder::IsSafePoint() { _ASSERTE(m_Flags & (DECODE_INTERRUPTIBILITY | DECODE_GC_LIFETIMES)); return m_SafePointIndex != m_NumSafePoints; } -bool GcInfoDecoder::CouldBeSafePoint() +template bool TGcInfoDecoder::CouldBeSafePoint() { // This is used in asserts. Ideally it would return false // if current location canot possibly be a safepoint. @@ -418,13 +419,13 @@ bool GcInfoDecoder::CouldBeSafePoint() return m_NumInterruptibleRanges == 0; } -bool GcInfoDecoder::HasMethodDescGenericsInstContext() +template bool TGcInfoDecoder::HasMethodDescGenericsInstContext() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); return (m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) == GC_INFO_HAS_GENERICS_INST_CONTEXT_MD; } -bool GcInfoDecoder::HasMethodTableGenericsInstContext() +template bool TGcInfoDecoder::HasMethodTableGenericsInstContext() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); return (m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) == GC_INFO_HAS_GENERICS_INST_CONTEXT_MT; @@ -434,7 +435,7 @@ bool GcInfoDecoder::HasMethodTableGenericsInstContext() // This is used for gcinfodumper: is the given offset // a call-return offset with partially-interruptible GC info? -bool GcInfoDecoder::IsSafePoint(UINT32 codeOffset) +template bool TGcInfoDecoder::IsSafePoint(UINT32 codeOffset) { _ASSERTE(m_Flags == DECODE_EVERYTHING && m_InstructionOffset == 0); if(m_NumSafePoints == 0) @@ -454,13 +455,14 @@ bool GcInfoDecoder::IsSafePoint(UINT32 codeOffset) // the whole run will be under 64 bytes, so likely we will stay in the same cache line. #define MAX_LINEAR_SEARCH 32 +template NOINLINE -UINT32 GcInfoDecoder::NarrowSafePointSearch(size_t savedPos, UINT32 breakOffset, UINT32* searchEnd) +UINT32 TGcInfoDecoder::NarrowSafePointSearch(size_t savedPos, UINT32 breakOffset, UINT32* searchEnd) { INT32 low = 0; INT32 high = (INT32)m_NumSafePoints; - const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + const UINT32 numBitsPerOffset = CeilOfLog2(GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength)); while (high - low > MAX_LINEAR_SEARCH) { const INT32 mid = (low + high) / 2; @@ -479,14 +481,14 @@ UINT32 GcInfoDecoder::NarrowSafePointSearch(size_t savedPos, UINT32 breakOffset, return low; } -UINT32 GcInfoDecoder::FindSafePoint(UINT32 breakOffset) +template UINT32 TGcInfoDecoder::FindSafePoint(UINT32 breakOffset) { _ASSERTE(m_NumSafePoints > 0); UINT32 result = m_NumSafePoints; const size_t savedPos = m_Reader.GetCurrentPos(); - const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + const UINT32 numBitsPerOffset = CeilOfLog2(GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength)); - const UINT32 normBreakOffset = NORMALIZE_CODE_OFFSET(breakOffset); + const UINT32 normBreakOffset = GcInfoEncoding::NORMALIZE_CODE_OFFSET(breakOffset); UINT32 linearSearchStart = 0; UINT32 linearSearchEnd = m_NumSafePoints; if (linearSearchEnd - linearSearchStart > MAX_LINEAR_SEARCH) @@ -516,23 +518,23 @@ UINT32 GcInfoDecoder::FindSafePoint(UINT32 breakOffset) return result; } -void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, void * hCallback) +template void TGcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, void * hCallback) { if(m_NumSafePoints == 0) return; - const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + const UINT32 numBitsPerOffset = CeilOfLog2(GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_CodeLength)); for(UINT32 i = 0; i < m_NumSafePoints; i++) { UINT32 normOffset = (UINT32)m_Reader.Read(numBitsPerOffset); - UINT32 offset = DENORMALIZE_CODE_OFFSET(normOffset); + UINT32 offset = GcInfoEncoding::DENORMALIZE_CODE_OFFSET(normOffset); pCallback(this, offset, hCallback); } } #endif -void GcInfoDecoder::EnumerateInterruptibleRanges ( +template void TGcInfoDecoder::EnumerateInterruptibleRanges ( EnumerateInterruptibleRangesCallback *pCallback, void * hCallback) { @@ -543,14 +545,14 @@ void GcInfoDecoder::EnumerateInterruptibleRanges ( for(UINT32 i=0; i INT32 TGcInfoDecoder::GetGSCookieStackSlot() { _ASSERTE( m_Flags & DECODE_GS_COOKIE ); return m_GSCookieStackSlot; } -INT32 GcInfoDecoder::GetReversePInvokeFrameStackSlot() +template INT32 TGcInfoDecoder::GetReversePInvokeFrameStackSlot() { _ASSERTE(m_Flags & DECODE_REVERSE_PINVOKE_VAR); return m_ReversePInvokeFrameStackSlot; } -UINT32 GcInfoDecoder::GetGSCookieValidRangeStart() +template UINT32 TGcInfoDecoder::GetGSCookieValidRangeStart() { _ASSERTE( m_Flags & DECODE_GS_COOKIE ); return m_ValidRangeStart; } -UINT32 GcInfoDecoder::GetGSCookieValidRangeEnd() +template UINT32 TGcInfoDecoder::GetGSCookieValidRangeEnd() { _ASSERTE( m_Flags & DECODE_GS_COOKIE ); return m_ValidRangeEnd; } -UINT32 GcInfoDecoder::GetPrologSize() +template UINT32 TGcInfoDecoder::GetPrologSize() { _ASSERTE( m_Flags & DECODE_PROLOG_LENGTH ); return m_ValidRangeStart; } -INT32 GcInfoDecoder::GetGenericsInstContextStackSlot() +template INT32 TGcInfoDecoder::GetGenericsInstContextStackSlot() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); return m_GenericsInstContextStackSlot; } -INT32 GcInfoDecoder::GetPSPSymStackSlot() +template INT32 TGcInfoDecoder::GetPSPSymStackSlot() { _ASSERTE( m_Flags & DECODE_PSP_SYM ); return m_PSPSymStackSlot; } -bool GcInfoDecoder::GetIsVarArg() +template bool TGcInfoDecoder::GetIsVarArg() { _ASSERTE( m_Flags & DECODE_VARARG ); return m_headerFlags & GC_INFO_IS_VARARG; } #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -bool GcInfoDecoder::HasTailCalls() +template bool TGcInfoDecoder::HasTailCalls() { _ASSERTE( m_Flags & DECODE_HAS_TAILCALLS ); return ((m_headerFlags & GC_INFO_HAS_TAILCALLS) != 0); } #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 -bool GcInfoDecoder::WantsReportOnlyLeaf() +template bool TGcInfoDecoder::WantsReportOnlyLeaf() { // Only AMD64 with JIT64 can return false here. #ifdef TARGET_AMD64 @@ -626,33 +628,33 @@ bool GcInfoDecoder::WantsReportOnlyLeaf() #endif } -UINT32 GcInfoDecoder::GetCodeLength() +template UINT32 TGcInfoDecoder::GetCodeLength() { // SUPPORTS_DAC; _ASSERTE( m_Flags & DECODE_CODE_LENGTH ); return m_CodeLength; } -UINT32 GcInfoDecoder::GetStackBaseRegister() +template UINT32 TGcInfoDecoder::GetStackBaseRegister() { return m_StackBaseRegister; } -UINT32 GcInfoDecoder::GetSizeOfEditAndContinuePreservedArea() +template UINT32 TGcInfoDecoder::GetSizeOfEditAndContinuePreservedArea() { _ASSERTE( m_Flags & DECODE_EDIT_AND_CONTINUE ); return m_SizeOfEditAndContinuePreservedArea; } #ifdef TARGET_ARM64 -UINT32 GcInfoDecoder::GetSizeOfEditAndContinueFixedStackFrame() +template UINT32 TGcInfoDecoder::GetSizeOfEditAndContinueFixedStackFrame() { _ASSERTE( m_Flags & DECODE_EDIT_AND_CONTINUE ); return m_SizeOfEditAndContinueFixedStackFrame; } #endif -size_t GcInfoDecoder::GetNumBytesRead() +template size_t TGcInfoDecoder::GetNumBytesRead() { return (m_Reader.GetCurrentPos() + 7) / 8; } @@ -660,7 +662,7 @@ size_t GcInfoDecoder::GetNumBytesRead() #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA -UINT32 GcInfoDecoder::GetSizeOfStackParameterArea() +template UINT32 TGcInfoDecoder::GetSizeOfStackParameterArea() { return m_SizeOfStackOutgoingAndScratchArea; } @@ -668,7 +670,7 @@ UINT32 GcInfoDecoder::GetSizeOfStackParameterArea() #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA -bool GcInfoDecoder::EnumerateLiveSlots( +template bool TGcInfoDecoder::EnumerateLiveSlots( PREGDISPLAY pRD, bool reportScratchSlots, unsigned inputFlags, @@ -694,9 +696,9 @@ bool GcInfoDecoder::EnumerateLiveSlots( _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - GcSlotDecoder slotDecoder; + GcSlotDecoder slotDecoder; - UINT32 normBreakOffset = NORMALIZE_CODE_OFFSET(m_InstructionOffset); + UINT32 normBreakOffset = GcInfoEncoding::NORMALIZE_CODE_OFFSET(m_InstructionOffset); // Normalized break offset // Relative to interruptible ranges #if PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -717,8 +719,8 @@ bool GcInfoDecoder::EnumerateLiveSlots( // Skip interruptibility information for(UINT32 i=0; i 0) && m_Reader.ReadOneFast()) { - numBitsPerOffset = (UINT32) m_Reader.DecodeVarLengthUnsigned(POINTER_SIZE_ENCBASE) + 1; + numBitsPerOffset = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::POINTER_SIZE_ENCBASE) + 1; _ASSERTE(numBitsPerOffset != 0); } @@ -820,11 +822,11 @@ bool GcInfoDecoder::EnumerateLiveSlots( // RLE encoded bool fSkip = (m_Reader.ReadOneFast() == 0); bool fReport = true; - UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ); + UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ); fSkip = !fSkip; while (readSlots < numSlots) { - UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ) + 1; + UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ) + 1; if (fReport) { for(UINT32 slotIndex = readSlots; slotIndex < readSlots + cnt; slotIndex++) @@ -884,11 +886,11 @@ bool GcInfoDecoder::EnumerateLiveSlots( // If no info is found for the call site, we default to fully-interruptible LOG((LF_GCROOTS, LL_INFO1000000, "No GC info found for call site at offset %x. Defaulting to fully-interruptible information.\n", (int) m_InstructionOffset)); - UINT32 numChunks = (numInterruptibleLength + NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / NUM_NORM_CODE_OFFSETS_PER_CHUNK; - UINT32 breakChunk = pseudoBreakOffset / NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 numChunks = (numInterruptibleLength + GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 breakChunk = pseudoBreakOffset / GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; _ASSERTE(breakChunk < numChunks); - UINT32 numBitsPerPointer = (UINT32) m_Reader.DecodeVarLengthUnsigned(POINTER_SIZE_ENCBASE); + UINT32 numBitsPerPointer = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::POINTER_SIZE_ENCBASE); if(!numBitsPerPointer) goto ReportUntracked; @@ -922,11 +924,11 @@ bool GcInfoDecoder::EnumerateLiveSlots( // RLE encoded bool fSkip = (m_Reader.ReadOneFast() == 0); bool fReport = true; - UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ); + UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ); fSkip = !fSkip; while (readSlots < numSlots) { - UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ) + 1; + UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ) + 1; if (fReport) { numCouldBeLiveSlots += cnt; @@ -978,15 +980,15 @@ bool GcInfoDecoder::EnumerateLiveSlots( // We need to find a new run else if (fSkipFirst) { - UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_SKIP_ENCBASE ) + 1; + UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE ) + 1; slotIndex += tmp; - cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_RUN_ENCBASE ); + cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ); } else { - UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_RUN_ENCBASE ) + 1; + UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ) + 1; slotIndex += tmp; - cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_SKIP_ENCBASE ); + cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE ); } UINT32 isLive = (UINT32) finalStateReader.Read(1); @@ -994,16 +996,16 @@ bool GcInfoDecoder::EnumerateLiveSlots( if(chunk == breakChunk) { // Read transitions - UINT32 normBreakOffsetDelta = pseudoBreakOffset % NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 normBreakOffsetDelta = pseudoBreakOffset % GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; for(;;) { if(!m_Reader.ReadOneFast()) break; - UINT32 transitionOffset = (UINT32) m_Reader.Read(NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2); + UINT32 transitionOffset = (UINT32) m_Reader.Read(GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2); lifetimeTransitionsCount++; - _ASSERTE(transitionOffset && transitionOffset < NUM_NORM_CODE_OFFSETS_PER_CHUNK); + _ASSERTE(transitionOffset && transitionOffset < GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK); if(transitionOffset > normBreakOffsetDelta) { isLive ^= 1; @@ -1050,7 +1052,7 @@ bool GcInfoDecoder::EnumerateLiveSlots( return true; } -void GcInfoDecoder::EnumerateUntrackedSlots( +template void TGcInfoDecoder::EnumerateUntrackedSlots( PREGDISPLAY pRD, unsigned inputFlags, GCEnumCallback pCallBack, @@ -1062,13 +1064,13 @@ void GcInfoDecoder::EnumerateUntrackedSlots( _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - GcSlotDecoder slotDecoder; + GcSlotDecoder slotDecoder; // Skip interruptibility information for(UINT32 i=0; i void TGcInfoDecoder::ReportUntrackedSlots( + GcSlotDecoder& slotDecoder, PREGDISPLAY pRD, unsigned inputFlags, GCEnumCallback pCallBack, @@ -1104,11 +1106,11 @@ void GcInfoDecoder::ReportUntrackedSlots( } } -void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) +template void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) { if (reader.ReadOneFast()) { - m_NumRegisters = (UINT32) reader.DecodeVarLengthUnsigned(NUM_REGISTERS_ENCBASE); + m_NumRegisters = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_REGISTERS_ENCBASE); } else { @@ -1117,8 +1119,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) UINT32 numStackSlots; if (reader.ReadOneFast()) { - numStackSlots = (UINT32) reader.DecodeVarLengthUnsigned(NUM_STACK_SLOTS_ENCBASE); - m_NumUntracked = (UINT32) reader.DecodeVarLengthUnsigned(NUM_UNTRACKED_SLOTS_ENCBASE); + numStackSlots = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_STACK_SLOTS_ENCBASE); + m_NumUntracked = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_UNTRACKED_SLOTS_ENCBASE); } else { @@ -1135,8 +1137,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) _ASSERTE(i < MAX_PREDECODED_SLOTS); - UINT32 normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - UINT32 regNum = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + UINT32 regNum = normRegNum; GcSlotFlags flags = (GcSlotFlags) reader.Read(2); m_SlotArray[0].Slot.RegisterNumber = regNum; @@ -1147,15 +1149,15 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) { if(flags) { - normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - regNum = DENORMALIZE_REGISTER(normRegNum); + normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + regNum = normRegNum; flags = (GcSlotFlags) reader.Read(2); } else { - UINT32 normRegDelta = (UINT32) reader.DecodeVarLengthUnsigned(REGISTER_DELTA_ENCBASE) + 1; + UINT32 normRegDelta = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_DELTA_ENCBASE) + 1; normRegNum += normRegDelta; - regNum = DENORMALIZE_REGISTER(normRegNum); + regNum = normRegNum; } m_SlotArray[i].Slot.RegisterNumber = regNum; @@ -1168,8 +1170,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // We have stack slots left and more room to predecode GcStackSlotBase spBase = (GcStackSlotBase) reader.Read(2); - UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - INT32 spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + INT32 spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); GcSlotFlags flags = (GcSlotFlags) reader.Read(2); m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1183,15 +1185,15 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); flags = (GcSlotFlags) reader.Read(2); } else { - INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); normSpOffset += normSpOffsetDelta; - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); } m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1205,8 +1207,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // We have untracked stack slots left and more room to predecode GcStackSlotBase spBase = (GcStackSlotBase) reader.Read(2); - UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - INT32 spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + INT32 spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); GcSlotFlags flags = (GcSlotFlags) reader.Read(2); m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1220,15 +1222,15 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); flags = (GcSlotFlags) reader.Read(2); } else { - INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); normSpOffset += normSpOffsetDelta; - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); } m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1259,12 +1261,12 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) { if(flags) { - reader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); flags = (GcSlotFlags) reader.Read(2); } else { - reader.DecodeVarLengthUnsigned(REGISTER_DELTA_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_DELTA_ENCBASE); } } @@ -1275,7 +1277,7 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // Skip the first stack slot reader.Read(2); - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); i++; } @@ -1289,12 +1291,12 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); } else { - reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); } } } @@ -1306,7 +1308,7 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // Skip the first untracked slot reader.Read(2); - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); i++; } @@ -1319,19 +1321,19 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); } else { - reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); } } } } } -const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) +template const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) { _ASSERTE(slotIndex < m_NumSlots); @@ -1354,23 +1356,23 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) if(m_NumDecodedSlots == 0) { // Decode the first register - UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - m_pLastSlot->Slot.RegisterNumber = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + m_pLastSlot->Slot.RegisterNumber = normRegNum; m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else { if(m_pLastSlot->Flags) { - UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - m_pLastSlot->Slot.RegisterNumber = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + m_pLastSlot->Slot.RegisterNumber = normRegNum; m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else { - UINT32 normRegDelta = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(REGISTER_DELTA_ENCBASE) + 1; - UINT32 normRegNum = normRegDelta + NORMALIZE_REGISTER(m_pLastSlot->Slot.RegisterNumber); - m_pLastSlot->Slot.RegisterNumber = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegDelta = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_DELTA_ENCBASE) + 1; + UINT32 normRegNum = normRegDelta + m_pLastSlot->Slot.RegisterNumber; + m_pLastSlot->Slot.RegisterNumber = normRegNum; } } } @@ -1384,8 +1386,8 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) { // Decode the first stack slot or first untracked slot m_pLastSlot->Slot.Stack.Base = (GcStackSlotBase) m_SlotReader.Read(2); - UINT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - m_pLastSlot->Slot.Stack.SpOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + UINT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + m_pLastSlot->Slot.Stack.SpOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else @@ -1394,15 +1396,15 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) if(m_pLastSlot->Flags) { - INT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - m_pLastSlot->Slot.Stack.SpOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + INT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + m_pLastSlot->Slot.Stack.SpOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else { - INT32 normSpOffsetDelta = (INT32) m_SlotReader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); - INT32 normSpOffset = normSpOffsetDelta + NORMALIZE_STACK_SLOT(m_pLastSlot->Slot.Stack.SpOffset); - m_pLastSlot->Slot.Stack.SpOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + INT32 normSpOffsetDelta = (INT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); + INT32 normSpOffset = normSpOffsetDelta + GcInfoEncoding::NORMALIZE_STACK_SLOT(m_pLastSlot->Slot.Stack.SpOffset); + m_pLastSlot->Slot.Stack.SpOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); } } } @@ -1421,7 +1423,7 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) #if defined(TARGET_AMD64) -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1443,7 +1445,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( } #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1460,7 +1462,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( } #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 16); _ASSERTE(regNum != 4); // rsp @@ -1481,7 +1483,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1496,7 +1498,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P } -void GcInfoDecoder::ReportRegisterToGC( // AMD64 +template void TGcInfoDecoder::ReportRegisterToGC( // AMD64 int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1556,7 +1558,7 @@ void GcInfoDecoder::ReportRegisterToGC( // AMD64 #elif defined(TARGET_ARM) -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1598,7 +1600,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( } #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1616,7 +1618,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 14); _ASSERTE(regNum != 13); // sp @@ -1625,7 +1627,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1640,7 +1642,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P } -void GcInfoDecoder::ReportRegisterToGC( // ARM +template void TGcInfoDecoder::ReportRegisterToGC( // ARM int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1679,7 +1681,7 @@ void GcInfoDecoder::ReportRegisterToGC( // ARM #elif defined(TARGET_ARM64) -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1714,7 +1716,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( #endif } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 30); _ASSERTE(regNum != 18); @@ -1722,7 +1724,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) return regNum <= 17 || regNum >= 29; // R12 and R14/LR are both scratch registers } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1737,7 +1739,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P } -void GcInfoDecoder::ReportRegisterToGC( // ARM64 +template void TGcInfoDecoder::ReportRegisterToGC( // ARM64 int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1796,7 +1798,7 @@ void GcInfoDecoder::ReportRegisterToGC( // ARM64 } #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1825,7 +1827,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( #elif defined(TARGET_LOONGARCH64) #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1841,7 +1843,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( } #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1870,14 +1872,14 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( #endif } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 31); return (regNum <= 21 && ((regNum >= 4) || (regNum == 1))); } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1891,7 +1893,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #endif } -void GcInfoDecoder::ReportRegisterToGC( +template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1952,7 +1954,7 @@ void GcInfoDecoder::ReportRegisterToGC( #elif defined(TARGET_RISCV64) #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1968,7 +1970,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( } #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -2008,14 +2010,14 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( #endif } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 31); return (regNum >= 5 && regNum <= 7) || (regNum >= 10 and regNum <= 17) || regNum >= 28 || regNum == 1; } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -2029,7 +2031,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #endif } -void GcInfoDecoder::ReportRegisterToGC( +template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -2089,7 +2091,7 @@ void GcInfoDecoder::ReportRegisterToGC( #else // Unknown platform -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -2098,19 +2100,19 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( return NULL; } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { PORTABILITY_ASSERT("GcInfoDecoder::IsScratchRegister"); return false; } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { _ASSERTE( !"NYI" ); return false; } -void GcInfoDecoder::ReportRegisterToGC( +template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -2124,7 +2126,7 @@ void GcInfoDecoder::ReportRegisterToGC( #endif // Unknown platform -OBJECTREF* GcInfoDecoder::GetStackSlot( +template OBJECTREF* TGcInfoDecoder::GetStackSlot( INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD @@ -2164,7 +2166,7 @@ OBJECTREF* GcInfoDecoder::GetStackSlot( } #ifdef DACCESS_COMPILE -int GcInfoDecoder::GetStackReg(int spBase) +template int TGcInfoDecoder::GetStackReg(int spBase) { #if defined(TARGET_AMD64) int esp = 4; @@ -2187,7 +2189,7 @@ int GcInfoDecoder::GetStackReg(int spBase) } #endif // DACCESS_COMPILE -void GcInfoDecoder::ReportStackSlotToGC( +template void TGcInfoDecoder::ReportStackSlotToGC( INT32 spOffset, GcStackSlotBase spBase, unsigned gcFlags, @@ -2222,6 +2224,7 @@ void GcInfoDecoder::ReportStackSlotToGC( pCallBack(hCallBack, pObjRef, gcFlags DAC_ARG(DacSlotLocation(GetStackReg(spBase), spOffset, true))); } +// Instantiate the decoder so other files can use it +template class TGcInfoDecoder; #endif // USE_GC_INFO_DECODER - diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index c036ab4469704a..ee5197f5ff294f 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -46,6 +46,8 @@ ASMCONSTANTS_C_ASSERT(FRAMETYPE_TailCallFrame == (int)FrameIdentifier::TailCallF #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 +#define ThisPtrRetBufPrecodeData__Target 0x00 +ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target)); // CONTEXT from pal.h #define CONTEXT_Edi 0x9c diff --git a/src/coreclr/vm/i386/asmhelpers.S b/src/coreclr/vm/i386/asmhelpers.S index be0d5bf56e7ced..be02044fed4d07 100644 --- a/src/coreclr/vm/i386/asmhelpers.S +++ b/src/coreclr/vm/i386/asmhelpers.S @@ -1081,3 +1081,14 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler NESTED_END OnCallCountThresholdReachedStub, _TEXT #endif // FEATURE_TIERED_COMPILATION + +//edi -This pointer +//esi -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + mov eax, [eax + ThisPtrRetBufPrecodeData__Target] + // Use XOR swap technique to set avoid the need to spill to the stack + xor edi, esi + xor esi, edi + xor edi, esi + jmp eax +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 0906e40023ea68..e226383bcc7885 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -1394,4 +1394,15 @@ _OnCallCountThresholdReachedStub@0 endp endif ; FEATURE_TIERED_COMPILATION +; rcx -This pointer +; rdx -ReturnBuffer +_ThisPtrRetBufPrecodeWorker@0 proc public + mov eax, [eax + ThisPtrRetBufPrecodeData__Target] + ; Use XOR swap technique to set avoid the need to spill to the stack + xor ecx, edx + xor edx, ecx + xor ecx, edx + jmp eax +_ThisPtrRetBufPrecodeWorker@0 endp + end diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 11aed220fc92c7..4eaed789a29231 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -2705,78 +2705,3 @@ VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray) } #endif // !DACCESS_COMPILE - -#ifdef HAS_THISPTR_RETBUF_PRECODE - -// rel32 jmp target that points back to the jump (infinite loop). -// Used to mark uninitialized ThisPtrRetBufPrecode target -#define REL32_JMP_SELF (-5) - -#ifndef DACCESS_COMPILE -void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) -{ - WRAPPER_NO_CONTRACT; - - IN_TARGET_64BIT(m_nop1 = X86_INSTR_NOP;) // nop -#ifdef UNIX_AMD64_ABI - m_prefix1 = 0x48; - m_movScratchArg0 = 0xC78B; // mov rax,rdi - m_prefix2 = 0x48; - m_movArg0Arg1 = 0xFE8B; // mov rdi,rsi - m_prefix3 = 0x48; - m_movArg1Scratch = 0xF08B; // mov rsi,rax -#else - IN_TARGET_64BIT(m_prefix1 = 0x48;) - m_movScratchArg0 = 0xC889; // mov r/eax,r/ecx - IN_TARGET_64BIT(m_prefix2 = 0x48;) - m_movArg0Arg1 = 0xD189; // mov r/ecx,r/edx - IN_TARGET_64BIT(m_prefix3 = 0x48;) - m_movArg1Scratch = 0xC289; // mov r/edx,r/eax -#endif - m_nop2 = X86_INSTR_NOP; // nop - m_jmp = X86_INSTR_JMP_REL32; // jmp rel32 - m_pMethodDesc = (TADDR)pMD; - - // This precode is never patched lazily - avoid unnecessary jump stub allocation - m_rel32 = REL32_JMP_SELF; - - _ASSERTE(*((BYTE*)this + OFFSETOF_PRECODE_TYPE) == ThisPtrRetBufPrecode::Type); -} - -IN_TARGET_32BIT(static_assert_no_msg(offsetof(ThisPtrRetBufPrecode, m_movScratchArg0) == OFFSETOF_PRECODE_TYPE);) - -BOOL ThisPtrRetBufPrecode::SetTargetInterlocked(TADDR target, TADDR expected) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - } - CONTRACTL_END; - - // This precode is never patched lazily - the interlocked semantics is not required. - _ASSERTE(m_rel32 == REL32_JMP_SELF); - - // Use pMD == NULL to allocate the jump stub in non-dynamic heap that has the same lifetime as the precode itself - INT32 newRel32 = rel32UsingJumpStub(&m_rel32, target, NULL /* pMD */, ((MethodDesc *)GetMethodDesc())->GetLoaderAllocator()); - - _ASSERTE(IS_ALIGNED(&m_rel32, sizeof(INT32))); - ExecutableWriterHolder rel32WriterHolder(&m_rel32, sizeof(INT32)); - InterlockedExchange((LONG*)rel32WriterHolder.GetRW(), (LONG)newRel32); - - return TRUE; -} -#endif // !DACCESS_COMPILE - -PCODE ThisPtrRetBufPrecode::GetTarget() -{ - LIMITED_METHOD_DAC_CONTRACT; - - // This precode is never patched lazily - pretend that the uninitialized m_rel32 points to prestub - if (m_rel32 == REL32_JMP_SELF) - return GetPreStubEntryPoint(); - - return rel32Decode(PTR_HOST_MEMBER_TADDR(ThisPtrRetBufPrecode, this, m_rel32)); -} - -#endif // HAS_THISPTR_RETBUF_PRECODE diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 0978dee0976f93..f60120d6faeb07 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -339,63 +339,4 @@ inline TADDR rel32Decode(/*PTR_INT32*/ TADDR pRel32) void rel32SetInterlocked(/*PINT32*/ PVOID pRel32, /*PINT32*/ PVOID pRel32RW, TADDR target, MethodDesc* pMD); BOOL rel32SetInterlocked(/*PINT32*/ PVOID pRel32, /*PINT32*/ PVOID pRel32RW, TADDR target, TADDR expected, MethodDesc* pMD); -//------------------------------------------------------------------------ -// -// Precode definitions -// -//------------------------------------------------------------------------ - -#include - -#ifdef HAS_THISPTR_RETBUF_PRECODE - -// Precode to stuffle this and retbuf for closed delegates over static methods with return buffer -struct ThisPtrRetBufPrecode { - -#ifdef HOST_64BIT - static const int Type = 0x90; -#else - static const int Type = 0x89; -#endif // HOST_64BIT - - // mov regScratch,regArg0 - // mov regArg0,regArg1 - // mov regArg1,regScratch - // nop - // jmp EntryPoint - // dw pMethodDesc - - IN_TARGET_64BIT(BYTE m_nop1;) - IN_TARGET_64BIT(BYTE m_prefix1;) - WORD m_movScratchArg0; - IN_TARGET_64BIT(BYTE m_prefix2;) - WORD m_movArg0Arg1; - IN_TARGET_64BIT(BYTE m_prefix3;) - WORD m_movArg1Scratch; - BYTE m_nop2; - BYTE m_jmp; - INT32 m_rel32; - TADDR m_pMethodDesc; - - void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); - - TADDR GetMethodDesc() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return m_pMethodDesc; - } - - PCODE GetTarget(); - - BOOL SetTargetInterlocked(TADDR target, TADDR expected); -}; - -typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; - -#endif // HAS_THISPTR_RETBUF_PRECODE - -#include - #endif // STUBLINKERX86_H_ diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index cb02d86f39e358..58ece1e6d234c2 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "interpexec.h" +#include #ifdef FEATURE_INTERPRETER @@ -40,6 +41,9 @@ void InterpExecMethod(InterpMethodContextFrame *pFrame, InterpThreadContext *pTh ip = pFrame->startIp + sizeof(InterpMethod*) / sizeof(int32_t); stack = pFrame->pStack; + int32_t returnOffset, callArgsOffset; + +MAIN_LOOP: while (true) { switch (*ip) @@ -48,16 +52,714 @@ void InterpExecMethod(InterpMethodContextFrame *pFrame, InterpThreadContext *pTh LOCAL_VAR(ip[1], int32_t) = ip[2]; ip += 3; break; + case INTOP_LDC_I4_0: + LOCAL_VAR(ip[1], int32_t) = 0; + ip += 2; + break; + case INTOP_LDC_I8_0: + LOCAL_VAR(ip[1], int64_t) = 0; + ip += 2; + break; case INTOP_RET: // Return stack slot sized value *(int64_t*)pFrame->pRetVal = LOCAL_VAR(ip[1], int64_t); goto EXIT_FRAME; + case INTOP_RET_VT: + memmove(pFrame->pRetVal, stack + ip[1], ip[2]); + goto EXIT_FRAME; case INTOP_RET_VOID: goto EXIT_FRAME; + +#define MOV(argtype1,argtype2) \ + LOCAL_VAR(ip [1], argtype1) = LOCAL_VAR(ip [2], argtype2); \ + ip += 3; + // When loading from a local, we might need to sign / zero extend to 4 bytes + // which is our minimum "register" size in interp. They are only needed when + // the address of the local is taken and we should try to optimize them out + // because the local can't be propagated. + case INTOP_MOV_I4_I1: MOV(int32_t, int8_t); break; + case INTOP_MOV_I4_U1: MOV(int32_t, uint8_t); break; + case INTOP_MOV_I4_I2: MOV(int32_t, int16_t); break; + case INTOP_MOV_I4_U2: MOV(int32_t, uint16_t); break; + // Normal moves between vars + case INTOP_MOV_4: MOV(int32_t, int32_t); break; + case INTOP_MOV_8: MOV(int64_t, int64_t); break; + + case INTOP_MOV_VT: + memmove(stack + ip[1], stack + ip[2], ip[3]); + ip += 4; + break; + + case INTOP_CONV_R_UN_I4: + LOCAL_VAR(ip[1], double) = (double)LOCAL_VAR(ip[2], uint32_t); + ip += 3; + break; + case INTOP_CONV_R_UN_I8: + LOCAL_VAR(ip[1], double) = (double)LOCAL_VAR(ip[2], uint64_t); + ip += 3; + break; + case INTOP_CONV_I1_I4: + LOCAL_VAR(ip[1], int32_t) = (int8_t)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_CONV_I1_I8: + LOCAL_VAR(ip[1], int32_t) = (int8_t)LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_CONV_I1_R4: + LOCAL_VAR(ip[1], int32_t) = (int8_t)(int32_t)LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_CONV_I1_R8: + LOCAL_VAR(ip[1], int32_t) = (int8_t)(int32_t)LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_CONV_U1_I4: + LOCAL_VAR(ip[1], int32_t) = (uint8_t)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_CONV_U1_I8: + LOCAL_VAR(ip[1], int32_t) = (uint8_t)LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_CONV_U1_R4: + LOCAL_VAR(ip[1], int32_t) = (uint8_t)(uint32_t)LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_CONV_U1_R8: + LOCAL_VAR(ip[1], int32_t) = (uint8_t)(uint32_t)LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_CONV_I2_I4: + LOCAL_VAR(ip[1], int32_t) = (int16_t)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_CONV_I2_I8: + LOCAL_VAR(ip[1], int32_t) = (int16_t)LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_CONV_I2_R4: + LOCAL_VAR(ip[1], int32_t) = (int16_t)(int32_t)LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_CONV_I2_R8: + LOCAL_VAR(ip[1], int32_t) = (int16_t)(int32_t)LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_CONV_U2_I4: + LOCAL_VAR(ip[1], int32_t) = (uint16_t)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_CONV_U2_I8: + LOCAL_VAR(ip[1], int32_t) = (uint16_t)LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_CONV_U2_R4: + LOCAL_VAR(ip[1], int32_t) = (uint16_t)(uint32_t)LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_CONV_U2_R8: + LOCAL_VAR(ip[1], int32_t) = (uint16_t)(uint32_t)LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_CONV_I4_R4: + LOCAL_VAR(ip[1], int32_t) = (int32_t)LOCAL_VAR(ip[2], float); + ip += 3; + break;; + case INTOP_CONV_I4_R8: + LOCAL_VAR(ip[1], int32_t) = (int32_t)LOCAL_VAR(ip[2], double); + ip += 3; + break;; + + case INTOP_CONV_U4_R4: + case INTOP_CONV_U4_R8: + assert(0); + break; + + case INTOP_CONV_I8_I4: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_CONV_I8_U4: + LOCAL_VAR(ip[1], int64_t) = (uint32_t)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break;; + case INTOP_CONV_I8_R4: + LOCAL_VAR(ip[1], int64_t) = (int64_t)LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_CONV_I8_R8: + LOCAL_VAR(ip[1], int64_t) = (int64_t)LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_CONV_R4_I4: + LOCAL_VAR(ip[1], float) = (float)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break;; + case INTOP_CONV_R4_I8: + LOCAL_VAR(ip[1], float) = (float)LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_CONV_R4_R8: + LOCAL_VAR(ip[1], float) = (float)LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_CONV_R8_I4: + LOCAL_VAR(ip[1], double) = (double)LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_CONV_R8_I8: + LOCAL_VAR(ip[1], double) = (double)LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_CONV_R8_R4: + LOCAL_VAR(ip[1], double) = (double)LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_CONV_U8_R4: + case INTOP_CONV_U8_R8: + // TODO + assert(0); + break; + + case INTOP_SWITCH: + { + uint32_t val = LOCAL_VAR(ip[1], uint32_t); + uint32_t n = ip[2]; + ip += 3; + if (val < n) + { + ip += val; + ip += *ip; + } + else + { + ip += n; + } + break; + } + + case INTOP_BR: + ip += ip[1]; + break; + +#define BR_UNOP(datatype, op) \ + if (LOCAL_VAR(ip[1], datatype) op) \ + ip += ip[2]; \ + else \ + ip += 3; + + case INTOP_BRFALSE_I4: + BR_UNOP(int32_t, == 0); + break; + case INTOP_BRFALSE_I8: + BR_UNOP(int64_t, == 0); + break; + case INTOP_BRTRUE_I4: + BR_UNOP(int32_t, != 0); + break; + case INTOP_BRTRUE_I8: + BR_UNOP(int64_t, != 0); + break; + +#define BR_BINOP_COND(cond) \ + if (cond) \ + ip += ip[3]; \ + else \ + ip += 4; + +#define BR_BINOP(datatype, op) \ + BR_BINOP_COND(LOCAL_VAR(ip[1], datatype) op LOCAL_VAR(ip[2], datatype)) + + case INTOP_BEQ_I4: + BR_BINOP(int32_t, ==); + break; + case INTOP_BEQ_I8: + BR_BINOP(int64_t, ==); + break; + case INTOP_BEQ_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(!isunordered(f1, f2) && f1 == f2); + break; + } + case INTOP_BEQ_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(!isunordered(d1, d2) && d1 == d2); + break; + } + case INTOP_BGE_I4: + BR_BINOP(int32_t, >=); + break; + case INTOP_BGE_I8: + BR_BINOP(int64_t, >=); + break; + case INTOP_BGE_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(!isunordered(f1, f2) && f1 >= f2); + break; + } + case INTOP_BGE_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(!isunordered(d1, d2) && d1 >= d2); + break; + } + case INTOP_BGT_I4: + BR_BINOP(int32_t, >); + break; + case INTOP_BGT_I8: + BR_BINOP(int64_t, >); + break; + case INTOP_BGT_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(!isunordered(f1, f2) && f1 > f2); + break; + } + case INTOP_BGT_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(!isunordered(d1, d2) && d1 > d2); + break; + } + case INTOP_BLT_I4: + BR_BINOP(int32_t, <); + break; + case INTOP_BLT_I8: + BR_BINOP(int64_t, <); + break; + case INTOP_BLT_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(!isunordered(f1, f2) && f1 < f2); + break; + } + case INTOP_BLT_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(!isunordered(d1, d2) && d1 < d2); + break; + } + case INTOP_BLE_I4: + BR_BINOP(int32_t, <=); + break; + case INTOP_BLE_I8: + BR_BINOP(int64_t, <=); + break; + case INTOP_BLE_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(!isunordered(f1, f2) && f1 <= f2); + break; + } + case INTOP_BLE_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(!isunordered(d1, d2) && d1 <= d2); + break; + } + case INTOP_BNE_UN_I4: + BR_BINOP(uint32_t, !=); + break; + case INTOP_BNE_UN_I8: + BR_BINOP(uint64_t, !=); + break; + case INTOP_BNE_UN_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(isunordered(f1, f2) || f1 != f2); + break; + } + case INTOP_BNE_UN_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(isunordered(d1, d2) || d1 != d2); + break; + } + case INTOP_BGE_UN_I4: + BR_BINOP(uint32_t, >=); + break; + case INTOP_BGE_UN_I8: + BR_BINOP(uint64_t, >=); + break; + case INTOP_BGE_UN_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(isunordered(f1, f2) || f1 >= f2); + break; + } + case INTOP_BGE_UN_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(isunordered(d1, d2) || d1 >= d2); + break; + } + case INTOP_BGT_UN_I4: + BR_BINOP(uint32_t, >); + break; + case INTOP_BGT_UN_I8: + BR_BINOP(uint64_t, >); + break; + case INTOP_BGT_UN_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(isunordered(f1, f2) || f1 > f2); + break; + } + case INTOP_BGT_UN_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(isunordered(d1, d2) || d1 > d2); + break; + } + case INTOP_BLE_UN_I4: + BR_BINOP(uint32_t, <=); + break; + case INTOP_BLE_UN_I8: + BR_BINOP(uint64_t, <=); + break; + case INTOP_BLE_UN_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(isunordered(f1, f2) || f1 <= f2); + break; + } + case INTOP_BLE_UN_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(isunordered(d1, d2) || d1 <= d2); + break; + } + case INTOP_BLT_UN_I4: + BR_BINOP(uint32_t, <); + break; + case INTOP_BLT_UN_I8: + BR_BINOP(uint64_t, <); + break; + case INTOP_BLT_UN_R4: + { + float f1 = LOCAL_VAR(ip[1], float); + float f2 = LOCAL_VAR(ip[2], float); + BR_BINOP_COND(isunordered(f1, f2) || f1 < f2); + break; + } + case INTOP_BLT_UN_R8: + { + double d1 = LOCAL_VAR(ip[1], double); + double d2 = LOCAL_VAR(ip[2], double); + BR_BINOP_COND(isunordered(d1, d2) || d1 < d2); + break; + } + + case INTOP_ADD_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) + LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_ADD_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) + LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_ADD_R4: + LOCAL_VAR(ip[1], float) = LOCAL_VAR(ip[2], float) + LOCAL_VAR(ip[3], float); + ip += 4; + break; + case INTOP_ADD_R8: + LOCAL_VAR(ip[1], double) = LOCAL_VAR(ip[2], double) + LOCAL_VAR(ip[3], double); + ip += 4; + break; + + case INTOP_SUB_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) - LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_SUB_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) - LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_SUB_R4: + LOCAL_VAR(ip[1], float) = LOCAL_VAR(ip[2], float) - LOCAL_VAR(ip[3], float); + ip += 4; + break; + case INTOP_SUB_R8: + LOCAL_VAR(ip[1], double) = LOCAL_VAR(ip[2], double) - LOCAL_VAR(ip[3], double); + ip += 4; + break; + + case INTOP_MUL_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) * LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_MUL_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) * LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_MUL_R4: + LOCAL_VAR(ip[1], float) = LOCAL_VAR(ip[2], float) * LOCAL_VAR(ip[3], float); + ip += 4; + break; + case INTOP_MUL_R8: + LOCAL_VAR(ip[1], double) = LOCAL_VAR(ip[2], double) * LOCAL_VAR(ip[3], double); + ip += 4; + break; + + case INTOP_SHL_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) << LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_SHL_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) << LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_SHR_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) >> LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_SHR_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) >> LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_SHR_UN_I4: + LOCAL_VAR(ip[1], uint32_t) = LOCAL_VAR(ip[2], uint32_t) >> LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_SHR_UN_I8: + LOCAL_VAR(ip[1], uint64_t) = LOCAL_VAR(ip[2], uint64_t) >> LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + + case INTOP_NEG_I4: + LOCAL_VAR(ip[1], int32_t) = - LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_NEG_I8: + LOCAL_VAR(ip[1], int64_t) = - LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + case INTOP_NEG_R4: + LOCAL_VAR(ip[1], float) = - LOCAL_VAR(ip[2], float); + ip += 3; + break; + case INTOP_NEG_R8: + LOCAL_VAR(ip[1], double) = - LOCAL_VAR(ip[2], double); + ip += 3; + break; + case INTOP_NOT_I4: + LOCAL_VAR(ip[1], int32_t) = ~ LOCAL_VAR(ip[2], int32_t); + ip += 3; + break; + case INTOP_NOT_I8: + LOCAL_VAR(ip[1], int64_t) = ~ LOCAL_VAR(ip[2], int64_t); + ip += 3; + break; + + case INTOP_AND_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) & LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_AND_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) & LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_OR_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) | LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_OR_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) | LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_XOR_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) ^ LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_XOR_I8: + LOCAL_VAR(ip[1], int64_t) = LOCAL_VAR(ip[2], int64_t) ^ LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + +#define CMP_BINOP_FP(datatype, op, noOrderVal) \ + do { \ + datatype f1 = LOCAL_VAR(ip[2], datatype); \ + datatype f2 = LOCAL_VAR(ip[3], datatype); \ + if (isunordered(f1, f2)) \ + LOCAL_VAR(ip[1], int32_t) = noOrderVal; \ + else \ + LOCAL_VAR(ip[1], int32_t) = f1 op f2; \ + ip += 4; \ + } while (0) + + case INTOP_CEQ_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) == LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_CEQ_I8: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int64_t) == LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_CEQ_R4: + CMP_BINOP_FP(float, ==, 0); + break; + case INTOP_CEQ_R8: + CMP_BINOP_FP(double, ==, 0); + break; + + case INTOP_CGT_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) > LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_CGT_I8: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int64_t) > LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_CGT_R4: + CMP_BINOP_FP(float, >, 0); + break; + case INTOP_CGT_R8: + CMP_BINOP_FP(double, >, 0); + break; + + case INTOP_CGT_UN_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], uint32_t) > LOCAL_VAR(ip[3], uint32_t); + ip += 4; + break; + case INTOP_CGT_UN_I8: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], uint32_t) > LOCAL_VAR(ip[3], uint32_t); + ip += 4; + break; + case INTOP_CGT_UN_R4: + CMP_BINOP_FP(float, >, 1); + break; + case INTOP_CGT_UN_R8: + CMP_BINOP_FP(double, >, 1); + break; + + case INTOP_CLT_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) < LOCAL_VAR(ip[3], int32_t); + ip += 4; + break; + case INTOP_CLT_I8: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int64_t) < LOCAL_VAR(ip[3], int64_t); + ip += 4; + break; + case INTOP_CLT_R4: + CMP_BINOP_FP(float, <, 0); + break; + case INTOP_CLT_R8: + CMP_BINOP_FP(double, <, 0); + break; + + case INTOP_CLT_UN_I4: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], uint32_t) < LOCAL_VAR(ip[3], uint32_t); + ip += 4; + break; + case INTOP_CLT_UN_I8: + LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], uint64_t) < LOCAL_VAR(ip[3], uint64_t); + ip += 4; + break; + case INTOP_CLT_UN_R4: + CMP_BINOP_FP(float, <, 1); + break; + case INTOP_CLT_UN_R8: + CMP_BINOP_FP(double, <, 1); + break; + + case INTOP_CALL: + { + size_t targetMethod = (size_t)pMethod->pDataItems[ip[3]]; + returnOffset = ip[1]; + callArgsOffset = ip[2]; + const int32_t *targetIp; + + if (targetMethod & INTERP_METHOD_DESC_TAG) + { + // First execution of this call. Ensure target method is compiled and + // patch the data item slot with the actual method code. + MethodDesc *pMD = (MethodDesc*)(targetMethod & ~INTERP_METHOD_DESC_TAG); + PCODE code = pMD->GetNativeCode(); + if (!code) { + GCX_PREEMP(); + pMD->PrepareInitialCode(CallerGCMode::Coop); + code = pMD->GetNativeCode(); + } + pMethod->pDataItems[ip[3]] = (void*)code; + targetIp = (const int32_t*)code; + } + else + { + // At this stage in the implementation, we assume this is pointer to + // interpreter code. In the future, this should probably be tagged pointer + // for interpreter call or normal pointer for JIT/R2R call. + targetIp = (const int32_t*)targetMethod; + } + + // Save current execution state once we return from called method + pFrame->ip = ip + 4; + + // Allocate child frame. + { + InterpMethodContextFrame *pChildFrame = pFrame->pNext; + if (!pChildFrame) + { + pChildFrame = (InterpMethodContextFrame*)alloca(sizeof(InterpMethodContextFrame)); + pChildFrame->pNext = NULL; + pFrame->pNext = pChildFrame; + } + pChildFrame->ReInit(pFrame, targetIp, stack + returnOffset, stack + callArgsOffset); + pFrame = pChildFrame; + } + assert (((size_t)pFrame->pStack % INTERP_STACK_ALIGNMENT) == 0); + + // Set execution state for the new frame + pMethod = *(InterpMethod**)pFrame->startIp; + stack = pFrame->pStack; + ip = pFrame->startIp + sizeof(InterpMethod*) / sizeof(int32_t); + pThreadContext->pStackPointer = stack + pMethod->allocaSize; + break; + } + case INTOP_FAILFAST: + assert(0); + break; + default: + assert(0); + break; } } EXIT_FRAME: + if (pFrame->pParent && pFrame->pParent->ip) + { + // Return to the main loop after a non-recursive interpreter call + pFrame = pFrame->pParent; + ip = pFrame->ip; + stack = pFrame->pStack; + pMethod = *(InterpMethod**)pFrame->startIp; + pFrame->ip = NULL; + + pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize; + goto MAIN_LOOP; + } + pThreadContext->pStackPointer = pFrame->pStack; } diff --git a/src/coreclr/vm/interpexec.h b/src/coreclr/vm/interpexec.h index 52bc9d234834c6..19d1e12500e082 100644 --- a/src/coreclr/vm/interpexec.h +++ b/src/coreclr/vm/interpexec.h @@ -24,10 +24,20 @@ struct StackVal struct InterpMethodContextFrame { InterpMethodContextFrame *pParent; - int32_t *startIp; // from start_ip we can obtain InterpMethod and MethodDesc + const int32_t *startIp; // from startIp we can obtain InterpMethod and MethodDesc int8_t *pStack; int8_t *pRetVal; - int32_t *ip; + const int32_t *ip; // This ip is updated only when execution can leave the frame + InterpMethodContextFrame *pNext; + + void ReInit(InterpMethodContextFrame *pParent, const int32_t *startIp, int8_t *pRetVal, int8_t *pStack) + { + this->pParent = pParent; + this->startIp = startIp; + this->pRetVal = pRetVal; + this->pStack = pStack; + this->ip = NULL; + } }; struct InterpThreadContext diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 28ac102756360d..927268a4769291 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -902,39 +902,15 @@ HCIMPL1(StringObject*, FramedAllocateString, DWORD stringLength) HCIMPLEND /*********************************************************************/ -OBJECTHANDLE ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void** ppPinnedString) +STRINGREF* ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void** ppPinnedString) { - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } CONTRACTL_END; + STANDARD_VM_CONTRACT; _ASSERTE(TypeFromToken(metaTok) == mdtString); - Module* module = GetModule(scopeHnd); return module->ResolveStringRef(metaTok, ppPinnedString); } -/*********************************************************************/ -HCIMPL2(Object *, JIT_StrCns, unsigned rid, CORINFO_MODULE_HANDLE scopeHnd) -{ - FCALL_CONTRACT; - - OBJECTHANDLE hndStr = 0; - - HELPER_METHOD_FRAME_BEGIN_RET_0(); - - // Retrieve the handle to the CLR string object. - hndStr = ConstructStringLiteral(scopeHnd, RidToToken(rid, mdtString)); - HELPER_METHOD_FRAME_END(); - - // Don't use ObjectFromHandle; this isn't a real handle - return *(Object**)hndStr; -} -HCIMPLEND - - //======================================================================== // // ARRAY HELPERS @@ -3384,21 +3360,21 @@ HCIMPL3_RAW(void, JIT_ReversePInvokeEnterTrackTransitions, ReversePInvokeFrame* frame->pMD = pMD; Thread* thread = GetThreadNULLOk(); - + // If a thread instance exists and is in the // correct GC mode attempt a quick transition. if (thread != NULL && !thread->PreemptiveGCDisabled()) { frame->currentThread = thread; - + #ifdef PROFILING_SUPPORTED if (CORProfilerTrackTransitions()) { ProfilerUnmanagedToManagedTransitionMD(frame->pMD, COR_PRF_TRANSITION_CALL); } #endif - + // Manually inline the fast path in Thread::DisablePreemptiveGC(). thread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); if (g_TrapReturningThreads != 0) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 5d85d98fc4acbc..00eede9ce5685b 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11738,7 +11738,7 @@ InfoAccessType CEEJitInfo::constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd { // If ConstructStringLiteral returns a pinned reference we can return it by value (IAT_VALUE) void* ppPinnedString = nullptr; - void** ptr = (void**)ConstructStringLiteral(scopeHnd, metaTok, &ppPinnedString); + STRINGREF* ptr = ConstructStringLiteral(scopeHnd, metaTok, &ppPinnedString); if (ppPinnedString != nullptr) { @@ -12466,11 +12466,16 @@ void CEEJitInfo::getEHinfo( { GetMethod(ftn)->AsDynamicMethodDesc()->GetResolver()->GetEHInfo(EHnumber, clause); } - else + else if (ftn == CORINFO_METHOD_HANDLE(m_pMethodBeingCompiled)) { - _ASSERTE(ftn == CORINFO_METHOD_HANDLE(m_pMethodBeingCompiled)); // For now only support if the method being jitted getEHinfoHelper(ftn, EHnumber, clause, m_ILHeader); } + else + { + MethodDesc* method = GetMethod(ftn); + COR_ILMETHOD_DECODER header(method->GetILHeader(), method->GetMDImport(), NULL); + getEHinfoHelper(ftn, EHnumber, clause, &header); + } EE_TO_JIT_TRANSITION(); } diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 7f1835e458a53a..4b647b25430cdb 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -1029,7 +1029,7 @@ void DoGcStress (PT_CONTEXT regs, NativeCodeVersion nativeCodeVersion); // ppPinnedString: If the string is pinned (e.g. allocated in frozen heap), // the pointer to the pinned string is returned in *ppPinnedPointer. ppPinnedPointer == nullptr // means that the caller does not care whether the string is pinned or not. -OBJECTHANDLE ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void** ppPinnedString = nullptr); +STRINGREF* ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void** ppPinnedString = nullptr); FCDECL2(Object*, JIT_Box_MP_FastPortable, CORINFO_CLASS_HANDLE type, void* data); FCDECL2(Object*, JIT_Box, CORINFO_CLASS_HANDLE type, void* data); diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 5b40f60b674ac9..5257358d4758e5 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -18,6 +18,9 @@ UINT64 LoaderAllocator::cLoaderAllocatorsCreated = 1; LoaderAllocator::LoaderAllocator(bool collectible) : +#if defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) + m_dynamicHelpersRangeList(STUB_CODE_BLOCK_STUBPRECODE, collectible), +#endif // defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) m_stubPrecodeRangeList(STUB_CODE_BLOCK_STUBPRECODE, collectible), m_fixupPrecodeRangeList(STUB_CODE_BLOCK_FIXUPPRECODE, collectible) { @@ -28,10 +31,11 @@ LoaderAllocator::LoaderAllocator(bool collectible) : m_pLowFrequencyHeap = NULL; m_pHighFrequencyHeap = NULL; m_pStubHeap = NULL; - m_pPrecodeHeap = NULL; m_pExecutableHeap = NULL; #ifdef FEATURE_READYTORUN +#ifndef FEATURE_STUBPRECODE_DYNAMIC_HELPERS m_pDynamicHelpersHeap = NULL; +#endif // !FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif m_pFuncPtrStubs = NULL; m_hLoaderAllocatorObjectHandle = (OBJECTHANDLE)NULL; @@ -1197,8 +1201,6 @@ void LoaderAllocator::Init(BYTE *pExecutableHeapMemory) initReservedMem += dwStubHeapReserveSize; - m_pPrecodeHeap = new (&m_PrecodeHeapInstance) CodeFragmentHeap(this, STUB_CODE_BLOCK_PRECODE); - m_pNewStubPrecodeHeap = new (&m_NewStubPrecodeHeapInstance) LoaderHeap(2 * GetStubCodePageSize(), 2 * GetStubCodePageSize(), &m_stubPrecodeRangeList, @@ -1207,6 +1209,20 @@ void LoaderAllocator::Init(BYTE *pExecutableHeapMemory) StubPrecode::GenerateCodePage, StubPrecode::CodeSize); +#if defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) && defined(FEATURE_READYTORUN) + if (IsCollectible()) + { + m_pDynamicHelpersStubHeap = m_pNewStubPrecodeHeap; + } + m_pDynamicHelpersStubHeap = new (&m_DynamicHelpersHeapInstance) LoaderHeap(2 * GetStubCodePageSize(), + 2 * GetStubCodePageSize(), + &m_dynamicHelpersRangeList, + UnlockedLoaderHeap::HeapKind::Interleaved, + false /* fUnlocked */, + StubPrecode::GenerateCodePage, + StubPrecode::CodeSize); +#endif // defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) && defined(FEATURE_READYTORUN) + m_pFixupPrecodeHeap = new (&m_FixupPrecodeHeapInstance) LoaderHeap(2 * GetStubCodePageSize(), 2 * GetStubCodePageSize(), &m_fixupPrecodeRangeList, @@ -1240,6 +1256,8 @@ void LoaderAllocator::Init(BYTE *pExecutableHeapMemory) #ifdef FEATURE_READYTORUN + +#ifndef FEATURE_STUBPRECODE_DYNAMIC_HELPERS PTR_CodeFragmentHeap LoaderAllocator::GetDynamicHelpersHeap() { CONTRACTL { @@ -1255,6 +1273,7 @@ PTR_CodeFragmentHeap LoaderAllocator::GetDynamicHelpersHeap() } return m_pDynamicHelpersHeap; } +#endif // !FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif FuncPtrStubs * LoaderAllocator::GetFuncPtrStubs() @@ -1389,32 +1408,37 @@ void LoaderAllocator::Terminate() m_pStubHeap = NULL; } - if (m_pPrecodeHeap != NULL) - { - m_pPrecodeHeap->~CodeFragmentHeap(); - m_pPrecodeHeap = NULL; - } - if (m_pFixupPrecodeHeap != NULL) { m_pFixupPrecodeHeap->~LoaderHeap(); m_pFixupPrecodeHeap = NULL; } + #ifdef FEATURE_READYTORUN + #ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + if (m_pDynamicHelpersStubHeap != NULL) + { + if (m_pDynamicHelpersStubHeap != m_pNewStubPrecodeHeap) + { + m_pDynamicHelpersStubHeap->~LoaderHeap(); + } + m_pDynamicHelpersStubHeap = NULL; + } + #else + if (m_pDynamicHelpersHeap != NULL) + { + delete m_pDynamicHelpersHeap; + m_pDynamicHelpersHeap = NULL; + } + #endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS + #endif + if (m_pNewStubPrecodeHeap != NULL) { m_pNewStubPrecodeHeap->~LoaderHeap(); m_pNewStubPrecodeHeap = NULL; } -#ifdef FEATURE_READYTORUN - if (m_pDynamicHelpersHeap != NULL) - { - delete m_pDynamicHelpersHeap; - m_pDynamicHelpersHeap = NULL; - } -#endif - if (m_pFuncPtrStubs != NULL) { delete m_pFuncPtrStubs; @@ -1470,19 +1494,22 @@ void LoaderAllocator::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { m_pStubHeap->EnumMemoryRegions(flags); } - if (m_pPrecodeHeap.IsValid()) - { - m_pPrecodeHeap->EnumMemoryRegions(flags); - } if (m_pExecutableHeap.IsValid()) { m_pExecutableHeap->EnumMemoryRegions(flags); } #ifdef FEATURE_READYTORUN +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + if (m_pDynamicHelpersStubHeap.IsValid() && m_pDynamicHelpersStubHeap != m_pNewStubPrecodeHeap) + { + m_pDynamicHelpersStubHeap->EnumMemoryRegions(flags); + } +#else if (m_pDynamicHelpersHeap.IsValid()) { m_pDynamicHelpersHeap->EnumMemoryRegions(flags); } +#endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif if (m_pFixupPrecodeHeap.IsValid()) { diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index b6961ca49257d3..9880a627636720 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -301,19 +301,26 @@ class LoaderAllocator BYTE m_LowFreqHeapInstance[sizeof(LoaderHeap)]; BYTE m_HighFreqHeapInstance[sizeof(LoaderHeap)]; BYTE m_StubHeapInstance[sizeof(LoaderHeap)]; - BYTE m_PrecodeHeapInstance[sizeof(CodeFragmentHeap)]; BYTE m_FixupPrecodeHeapInstance[sizeof(LoaderHeap)]; BYTE m_NewStubPrecodeHeapInstance[sizeof(LoaderHeap)]; BYTE m_StaticsHeapInstance[sizeof(LoaderHeap)]; +#ifdef FEATURE_READYTORUN +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + BYTE m_DynamicHelpersHeapInstance[sizeof(LoaderHeap)]; +#endif // !FEATURE_STUBPRECODE_DYNAMIC_HELPERS +#endif // FEATURE_READYTORUN PTR_LoaderHeap m_pLowFrequencyHeap; PTR_LoaderHeap m_pHighFrequencyHeap; PTR_LoaderHeap m_pStaticsHeap; PTR_LoaderHeap m_pStubHeap; // stubs for PInvoke, remoting, etc - PTR_CodeFragmentHeap m_pPrecodeHeap; PTR_LoaderHeap m_pExecutableHeap; #ifdef FEATURE_READYTORUN +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + PTR_LoaderHeap m_pDynamicHelpersStubHeap; // R2R Stubs for dynamic helpers. Seperate from m_pStubHeap to avoid allowing these stubs to take up cache space once the process is fully hot. +#else PTR_CodeFragmentHeap m_pDynamicHelpersHeap; -#endif +#endif // !FEATURE_STUBPRECODE_DYNAMIC_HELPERS +#endif // FEATURE_READYTORUN PTR_LoaderHeap m_pFixupPrecodeHeap; PTR_LoaderHeap m_pNewStubPrecodeHeap; //**************************************************************************************** @@ -344,6 +351,9 @@ class LoaderAllocator // IL stub cache with fabricated MethodTable parented by a random module in this LoaderAllocator. ILStubCache m_ILStubCache; +#if defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) + CodeRangeMapRangeList m_dynamicHelpersRangeList; +#endif // defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) CodeRangeMapRangeList m_stubPrecodeRangeList; CodeRangeMapRangeList m_fixupPrecodeRangeList; @@ -603,17 +613,19 @@ class LoaderAllocator return m_pStubHeap; } - PTR_CodeFragmentHeap GetPrecodeHeap() + PTR_LoaderHeap GetNewStubPrecodeHeap() { LIMITED_METHOD_CONTRACT; - return m_pPrecodeHeap; + return m_pNewStubPrecodeHeap; } - PTR_LoaderHeap GetNewStubPrecodeHeap() +#if defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) + PTR_LoaderHeap GetDynamicHelpersStubHeap() { LIMITED_METHOD_CONTRACT; - return m_pNewStubPrecodeHeap; + return m_pDynamicHelpersStubHeap; } +#endif // defined(FEATURE_READYTORUN) && defined(FEATURE_STUBPRECODE_DYNAMIC_HELPERS) // The executable heap is intended to only be used by the global loader allocator. // It refers to executable memory that is not associated with a rangelist. diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index 8a9b830a4ef6f6..8a7ffecd191734 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -37,6 +37,9 @@ ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::Inline #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 +#define ThisPtrRetBufPrecodeData__Target 0x00 +ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target)); + #define Thread__m_fPreemptiveGCDisabled 0x04 #define Thread__m_pFrame 0x08 diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index b2abecbafb5f31..6f2a89383852c4 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -1142,3 +1142,13 @@ LOCAL_LABEL(JIT_PollGCRarePath): ld.d $t0, $t0, 0 EPILOG_BRANCH_REG $t0 LEAF_END JIT_PollGC, _TEXT + +//a0 -This pointer +//a1 -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + ld.w $METHODDESC_REGISTER, $METHODDESC_REGISTER, ThisPtrRetBufPrecodeData__Target + move $t0, $a0 // Move first arg pointer to temp register + move $a0, $a1 // Move ret buf arg pointer from location in ABI for return buffer for instance method to location in ABI for return buffer for static method + move $a1, $t0 // Move temp register to first arg register for static method with return buffer + EPILOG_BRANCH_REG $METHODDESC_REGISTER +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT diff --git a/src/coreclr/vm/loongarch64/cgencpu.h b/src/coreclr/vm/loongarch64/cgencpu.h index 1938eeb100b235..d7bfc6b12283af 100644 --- a/src/coreclr/vm/loongarch64/cgencpu.h +++ b/src/coreclr/vm/loongarch64/cgencpu.h @@ -441,46 +441,4 @@ struct HijackArgs EXTERN_C VOID STDCALL PrecodeFixupThunk(); -// Precode to shuffle this and retbuf for closed delegates over static methods with return buffer -struct ThisPtrRetBufPrecode { - - static const int Type = 2;//2, for Type encoding. - - UINT32 m_rgCode[6]; - TADDR m_pTarget; - TADDR m_pMethodDesc; - - void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); - - TADDR GetMethodDesc() - { - LIMITED_METHOD_DAC_CONTRACT; - - return m_pMethodDesc; - } - - PCODE GetTarget() - { - LIMITED_METHOD_DAC_CONTRACT; - return m_pTarget; - } - -#ifndef DACCESS_COMPILE - BOOL SetTargetInterlocked(TADDR target, TADDR expected) - { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - } - CONTRACTL_END; - - ExecutableWriterHolder precodeWriterHolder(this, sizeof(ThisPtrRetBufPrecode)); - return (TADDR)InterlockedCompareExchange64( - (LONGLONG*)&precodeWriterHolder.GetRW()->m_pTarget, (TADDR)target, (TADDR)expected) == expected; - } -#endif // !DACCESS_COMPILE -}; -typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; - #endif // __cgencpu_h__ diff --git a/src/coreclr/vm/loongarch64/stubs.cpp b/src/coreclr/vm/loongarch64/stubs.cpp index 519e4f761cadf4..b126073279136c 100644 --- a/src/coreclr/vm/loongarch64/stubs.cpp +++ b/src/coreclr/vm/loongarch64/stubs.cpp @@ -548,31 +548,6 @@ void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool update ClearRegDisplayArgumentAndScratchRegisters(pRD); } -#ifndef DACCESS_COMPILE - -void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) -{ - WRAPPER_NO_CONTRACT; - - //Initially - //a0 -This ptr - //a1 -ReturnBuffer - m_rgCode[0] = 0x18000055; //pcaddi r21,2 - m_rgCode[1] = 0x28c042b5; //ld.d r21,16(r21) - m_rgCode[2] = 0x0380008f; //ori r15,a0,0x0 - m_rgCode[3] = 0x038000a4; //ori a0,a1,0x0 - m_rgCode[4] = 0x038001e5; //ori a1,r15,0x0 - m_rgCode[5] = 0x4c0002a0; //jirl r0,r21,0 - - _ASSERTE((UINT32*)&m_pTarget == &m_rgCode[6]); - _ASSERTE(6 == ARRAY_SIZE(m_rgCode)); - - m_pTarget = GetPreStubEntryPoint(); - m_pMethodDesc = (TADDR)pMD; -} - -#endif // !DACCESS_COMPILE - void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * pCalleeSaved) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 3d279240f0cbb3..2883b95ac39afa 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -220,6 +220,7 @@ DEFINE_METASIG(SM(RetUInt, _, K)) DEFINE_METASIG(SM(RetBool, _, F)) DEFINE_METASIG(SM(IntPtr_RetStr, I, s)) DEFINE_METASIG(SM(IntPtr_RetBool, I, F)) +DEFINE_METASIG(SM(UInt_IntPtr_RetStr, K I, s)) DEFINE_METASIG_T(SM(RuntimeType_RuntimeMethodHandleInternal_RetMethodBase, C(CLASS) g(METHOD_HANDLE_INTERNAL), C(METHOD_BASE) )) DEFINE_METASIG_T(SM(RuntimeType_IRuntimeFieldInfo_RetFieldInfo, C(CLASS) C(I_RT_FIELD_INFO), C(FIELD_INFO) )) DEFINE_METASIG(SM(Char_Bool_Bool_RetByte, u F F, b)) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index bb8d2430c21f49..5a103f193ac3fe 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2278,8 +2278,6 @@ MethodDesc* NonVirtualEntry2MethodDesc(PCODE entryPoint) switch(stubCodeBlockKind) { - case STUB_CODE_BLOCK_PRECODE: - return MethodDesc::GetMethodDescFromStubAddr(entryPoint); case STUB_CODE_BLOCK_FIXUPPRECODE: return (MethodDesc*)((FixupPrecode*)PCODEToPINSTR(entryPoint))->GetMethodDesc(); case STUB_CODE_BLOCK_STUBPRECODE: diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 5bd6d77a70f807..19dddae79d2350 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -3920,12 +3920,12 @@ public : // JITed code and JIT helpers. The space used by m_pPerInstInfo is used to represent the array // element type handle for array MethodTables. + public: union { PerInstInfo_t m_pPerInstInfo; TADDR m_ElementTypeHnd; }; - public: union { PTR_InterfaceInfo m_pInterfaceMap; diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 0f3c65c12981b6..16186cb5b08f1a 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -10181,6 +10181,8 @@ void MethodTableBuilder::CheckForSystemTypes() // although applying 16 byte alignment is consistent with treatment of 128 bit SSE types // even on X86 pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128) +#elif defined(TARGET_WASM) + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(v128) #else #error Unknown architecture #endif // TARGET_64BIT diff --git a/src/coreclr/vm/precode.cpp b/src/coreclr/vm/precode.cpp index 75743dbd9e5258..f462883881a86f 100644 --- a/src/coreclr/vm/precode.cpp +++ b/src/coreclr/vm/precode.cpp @@ -34,6 +34,9 @@ BOOL Precode::IsValidType(PrecodeType t) #ifdef HAS_THISPTR_RETBUF_PRECODE case PRECODE_THISPTR_RETBUF: #endif // HAS_THISPTR_RETBUF_PRECODE +#ifdef FEATURE_INTERPRETER + case PRECODE_INTERPRETER: +#endif // FEATURE_INTERPRETER case PRECODE_UMENTRY_THUNK: return TRUE; default: @@ -70,6 +73,10 @@ SIZE_T Precode::SizeOf(PrecodeType t) case PRECODE_THISPTR_RETBUF: return sizeof(ThisPtrRetBufPrecode); #endif // HAS_THISPTR_RETBUF_PRECODE +#ifdef FEATURE_INTERPRETER + case PRECODE_INTERPRETER: + return sizeof(InterpreterPrecode); +#endif // FEATURE_INTERPRETER default: UnexpectedPrecodeType("Precode::SizeOf", t); @@ -141,6 +148,14 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) pMD = AsThisPtrRetBufPrecode()->GetMethodDesc(); break; #endif // HAS_THISPTR_RETBUF_PRECODE + case PRECODE_UMENTRY_THUNK: + return NULL; + break; +#ifdef FEATURE_INTERPRETER + case PRECODE_INTERPRETER: + return NULL; + break; +#endif // FEATURE_INTERPRETER default: break; @@ -226,26 +241,27 @@ Precode* Precode::Allocate(PrecodeType t, MethodDesc* pMD, } CONTRACTL_END; - SIZE_T size = Precode::SizeOf(t); - Precode* pPrecode; + Precode* pPrecode = NULL; if (t == PRECODE_FIXUP) { - pPrecode = (Precode*)pamTracker->Track(pLoaderAllocator->GetFixupPrecodeHeap()->AllocAlignedMem(size, 1)); + pPrecode = (Precode*)pamTracker->Track(pLoaderAllocator->GetFixupPrecodeHeap()->AllocAlignedMem(sizeof(FixupPrecode), 1)); pPrecode->Init(pPrecode, t, pMD, pLoaderAllocator); } - else if (t == PRECODE_STUB || t == PRECODE_NDIRECT_IMPORT) +#ifdef HAS_THISPTR_RETBUF_PRECODE + else if (t == PRECODE_THISPTR_RETBUF) { - pPrecode = (Precode*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocAlignedMem(size, 1)); - pPrecode->Init(pPrecode, t, pMD, pLoaderAllocator); + ThisPtrRetBufPrecode* pThisPtrRetBufPrecode = (ThisPtrRetBufPrecode*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocAlignedMem(sizeof(ThisPtrRetBufPrecode), 1)); + ThisPtrRetBufPrecodeData *pData = (ThisPtrRetBufPrecodeData*)pamTracker->Track(pLoaderAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(ThisPtrRetBufPrecodeData)))); + pThisPtrRetBufPrecode->Init(pData, pMD, pLoaderAllocator); + pPrecode = (Precode*)pThisPtrRetBufPrecode; } +#endif // HAS_THISPTR_RETBUF_PRECODE else { - pPrecode = (Precode*)pamTracker->Track(pLoaderAllocator->GetPrecodeHeap()->AllocAlignedMem(size, AlignOf(t))); - ExecutableWriterHolder precodeWriterHolder(pPrecode, size); - precodeWriterHolder.GetRW()->Init(pPrecode, t, pMD, pLoaderAllocator); - ClrFlushInstructionCache(pPrecode, size); - + _ASSERTE(t == PRECODE_STUB || t == PRECODE_NDIRECT_IMPORT); + pPrecode = (Precode*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocAlignedMem(sizeof(StubPrecode), 1)); + pPrecode->Init(pPrecode, t, pMD, pLoaderAllocator); } return pPrecode; @@ -335,7 +351,6 @@ BOOL Precode::SetTargetInterlocked(PCODE target, BOOL fOnlyRedirectFromPrestub) #ifdef HAS_THISPTR_RETBUF_PRECODE case PRECODE_THISPTR_RETBUF: ret = AsThisPtrRetBufPrecode()->SetTargetInterlocked(target, expected); - ClrFlushInstructionCache(this, sizeof(ThisPtrRetBufPrecode), /* hasCodeExecutedBefore */ true); break; #endif // HAS_THISPTR_RETBUF_PRECODE @@ -359,15 +374,25 @@ void Precode::Reset() PrecodeType t = GetType(); SIZE_T size = Precode::SizeOf(t); - if (t == PRECODE_FIXUP) + switch (t) { + case PRECODE_STUB: +#ifdef HAS_NDIRECT_IMPORT_PRECODE + case PRECODE_NDIRECT_IMPORT: +#endif // HAS_NDIRECT_IMPORT_PRECODE +#ifdef HAS_FIXUP_PRECODE + case PRECODE_FIXUP: +#endif // HAS_FIXUP_PRECODE +#ifdef HAS_THISPTR_RETBUF_PRECODE + case PRECODE_THISPTR_RETBUF: +#endif // HAS_THISPTR_RETBUF_PRECODE Init(this, t, pMD, pMD->GetLoaderAllocator()); - } - else - { - ExecutableWriterHolder precodeWriterHolder(this, size); - precodeWriterHolder.GetRW()->Init(this, t, pMD, pMD->GetLoaderAllocator()); - ClrFlushInstructionCache(this, SizeOf(), /* hasCodeExecutedBefore */ true); + break; + + default: + _ASSERTE(!"Unexpected precode type"); + JIT_FailFast(); + break; } } @@ -398,6 +423,23 @@ void FixupPrecode::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) #ifndef DACCESS_COMPILE +#ifdef HAS_THISPTR_RETBUF_PRECODE +extern "C" void ThisPtrRetBufPrecodeWorker(); +void ThisPtrRetBufPrecode::Init(ThisPtrRetBufPrecodeData* pPrecodeData, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) +{ + StubPrecode::Init(this, dac_cast(pPrecodeData), pLoaderAllocator, ThisPtrRetBufPrecode::Type, (TADDR)ThisPtrRetBufPrecodeWorker); + pPrecodeData->MethodDesc = pMD; + pPrecodeData->Target = GetPreStubEntryPoint(); +} + +void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) +{ + ThisPtrRetBufPrecodeData* pPrecodeData = GetData(); + pPrecodeData->MethodDesc = pMD; + pPrecodeData->Target = GetPreStubEntryPoint(); +} +#endif // HAS_THISPTR_RETBUF_PRECODE + void StubPrecode::Init(StubPrecode* pPrecodeRX, TADDR secretParam, LoaderAllocator *pLoaderAllocator /* = NULL */, TADDR type /* = StubPrecode::Type */, TADDR target /* = NULL */) { diff --git a/src/coreclr/vm/precode.h b/src/coreclr/vm/precode.h index c9a07e8751b217..45dce16d84f847 100644 --- a/src/coreclr/vm/precode.h +++ b/src/coreclr/vm/precode.h @@ -50,6 +50,11 @@ EXTERN_C VOID STDCALL PrecodeRemotingThunk(); #define SIZEOF_PRECODE_BASE CODE_SIZE_ALIGN #define OFFSETOF_PRECODE_TYPE 0 +#elif defined(TARGET_WASM) + +#define SIZEOF_PRECODE_BASE 0 +#define OFFSETOF_PRECODE_TYPE 0 + #endif // TARGET_AMD64 #ifndef DACCESS_COMPILE @@ -71,6 +76,9 @@ struct InvalidPrecode static const int Type = 0xff; #elif defined(TARGET_RISCV64) static const int Type = 0xff; +#elif defined(TARGET_WASM) + // unreachable instruction + static const int Type = 0; #endif }; @@ -94,6 +102,9 @@ extern "C" void InterpreterStub(); #endif class UMEntryThunk; + +struct ThisPtrRetBufPrecode; + typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk; #define PRECODE_UMENTRY_THUNK_VALUE 0x7 // Define the value here and not in UMEntryThunk to avoid circular dependency with the dllimportcallback.h header @@ -118,6 +129,9 @@ struct StubPrecode #elif defined(TARGET_RISCV64) static const int Type = 0x17; static const SIZE_T CodeSize = 24; +#elif defined(TARGET_WASM) + static const int Type = 0; + static const SIZE_T CodeSize = 0; #endif // TARGET_AMD64 BYTE m_code[CodeSize]; @@ -139,6 +153,10 @@ struct StubPrecode TADDR GetMethodDesc(); +#ifdef HAS_THISPTR_RETBUF_PRECODE + ThisPtrRetBufPrecode* AsThisPtrRetBufPrecode(); +#endif // HAS_THISPTR_RETBUF_PRECODE + #ifndef DACCESS_COMPILE void SetSecretParam(TADDR secretParam) { @@ -235,6 +253,88 @@ typedef DPTR(NDirectImportPrecode) PTR_NDirectImportPrecode; #endif // HAS_NDIRECT_IMPORT_PRECODE +#ifdef HAS_THISPTR_RETBUF_PRECODE + +struct ThisPtrRetBufPrecodeData +{ + PCODE Target; + class MethodDesc *MethodDesc; +}; + +typedef DPTR(ThisPtrRetBufPrecodeData) PTR_ThisPtrRetBufPrecodeData; + +// ThisPtrRetBufPrecode, built on the infra for the StubPrecode +// (This is fake precode. VTable slot does not point to it.) +struct ThisPtrRetBufPrecode : StubPrecode +{ + static const int Type = 0x08; + + void Init(ThisPtrRetBufPrecodeData* pPrecodeData, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); + void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); + + PTR_ThisPtrRetBufPrecodeData GetData() const + { + LIMITED_METHOD_CONTRACT; + return dac_cast(StubPrecode::GetData()->SecretParam); + } + + LPVOID GetEntrypoint() + { + LIMITED_METHOD_CONTRACT; + return (LPVOID)PINSTRToPCODE(dac_cast(this)); + } + + PCODE GetTarget() + { + LIMITED_METHOD_DAC_CONTRACT; + + return GetData()->Target; + } + + void ResetTargetInterlocked() + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + ThisPtrRetBufPrecodeData *pData = GetData(); + InterlockedExchangeT(&pData->Target, GetPreStubEntryPoint()); + } + + BOOL SetTargetInterlocked(TADDR target, TADDR expected) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + ThisPtrRetBufPrecodeData *pData = GetData(); + return InterlockedCompareExchangeT(&pData->Target, (PCODE)target, (PCODE)expected) == expected; + } + + TADDR GetMethodDesc() + { + LIMITED_METHOD_DAC_CONTRACT; + + return dac_cast(GetData()->MethodDesc); + } +}; +typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; + +inline ThisPtrRetBufPrecode* StubPrecode::AsThisPtrRetBufPrecode() +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + return dac_cast(this); +} + +#endif // HAS_THISPTR_RETBUF_PRECODE + #ifdef FEATURE_INTERPRETER struct InterpreterPrecodeData { @@ -311,6 +411,10 @@ struct FixupPrecode static const int Type = 0x97; static const SIZE_T CodeSize = 32; static const int FixupCodeOffset = 10; +#elif defined(TARGET_WASM) + static const int Type = 2; + static const SIZE_T CodeSize = 0; + static const int FixupCodeOffset = 0; #endif // TARGET_AMD64 BYTE m_code[CodeSize]; @@ -422,6 +526,9 @@ enum PrecodeType { PRECODE_THISPTR_RETBUF = ThisPtrRetBufPrecode::Type, #endif // HAS_THISPTR_RETBUF_PRECODE PRECODE_UMENTRY_THUNK = PRECODE_UMENTRY_THUNK_VALUE, // Set the value here and not in UMEntryThunk to avoid circular dependency +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + PRECODE_DYNAMIC_HELPERS = 0xa, +#endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS }; inline TADDR StubPrecode::GetMethodDesc() @@ -438,7 +545,13 @@ inline TADDR StubPrecode::GetMethodDesc() #ifdef FEATURE_INTERPRETER case PRECODE_INTERPRETER: #endif // FEATURE_INTERPRETER +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + case PRECODE_DYNAMIC_HELPERS: +#endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS return 0; + + case PRECODE_THISPTR_RETBUF: + return AsThisPtrRetBufPrecode()->GetMethodDesc(); } _ASSERTE(!"Unknown precode type"); @@ -458,6 +571,7 @@ inline BYTE StubPrecode::GetType() case PRECODE_UMENTRY_THUNK: case PRECODE_STUB: case PRECODE_NDIRECT_IMPORT: + case PRECODE_THISPTR_RETBUF: #ifdef FEATURE_INTERPRETER case PRECODE_INTERPRETER: #endif // FEATURE_INTERPRETER @@ -567,7 +681,7 @@ class Precode { if (type == StubPrecode::Type) { - // StubPrecode code is used for both StubPrecode and NDirectImportPrecode, + // StubPrecode code is used for both StubPrecode, NDirectImportPrecode, InterpreterPrecode, and ThisPtrRetBufPrecode, // so we need to get the real type type = AsStubPrecode()->GetType(); } diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 085468f030e9b1..5ac5a3889f9386 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -271,6 +271,7 @@ static const Entry s_QCall[] = DllImportEntry(MultiCoreJIT_InternalStartProfile) #endif DllImportEntry(LoaderAllocator_Destroy) + DllImportEntry(String_StrCns) DllImportEntry(String_Intern) DllImportEntry(String_IsInterned) DllImportEntry(AppDomain_CreateDynamicAssembly) diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index bbc5948412df14..487676d3ba2c40 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -18,8 +18,11 @@ #include "nativeimage.h" #ifndef DACCESS_COMPILE -static PCODE g_pMethodWithSlotAndModule = (PCODE)NULL; -static PCODE g_pClassWithSlotAndModule = (PCODE)NULL; +extern "C" PCODE g_pMethodWithSlotAndModule; +extern "C" PCODE g_pClassWithSlotAndModule; + +PCODE g_pMethodWithSlotAndModule = (PCODE)NULL; +PCODE g_pClassWithSlotAndModule = (PCODE)NULL; PCODE DynamicHelpers::GetDictionaryLookupHelper(CorInfoHelpFunc jitHelper) { @@ -1981,3 +1984,323 @@ bool ReadyToRun_MethodIsGenericMap::IsGeneric(mdMethodDef input, bool *foundResu return false; } + +#ifndef DACCESS_COMPILE +#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS + +PCODE CreateDynamicHelperPrecode(LoaderAllocator *pAllocator, AllocMemTracker *pamTracker, PCODE DynamicHelper, TADDR DynamicHelperArg) +{ + STANDARD_VM_CONTRACT; + + size_t size = sizeof(StubPrecode); + StubPrecode *pPrecode = (StubPrecode *)pamTracker->Track(pAllocator->GetDynamicHelpersStubHeap()->AllocAlignedMem(size, 1)); + pPrecode->Init(pPrecode, DynamicHelperArg, pAllocator, PRECODE_DYNAMIC_HELPERS, DynamicHelper); + return ((Precode*)pPrecode)->GetEntryPoint(); +} + +extern "C" void DynamicHelper_CallHelper_1Arg(); +extern "C" void DynamicHelper_CallHelper_AddSecondArg(); +extern "C" void DynamicHelper_CallHelper_2Arg(); +extern "C" void DynamicHelper_CallHelper_ArgMove(); +extern "C" void DynamicHelper_Return(); +extern "C" void DynamicHelper_ReturnConst(); +extern "C" void DynamicHelper_ReturnIndirConst(); +extern "C" void DynamicHelper_ReturnIndirConstWithOffset(); +extern "C" void DynamicHelper_CallHelper_AddThirdArg(); +extern "C" void DynamicHelper_CallHelper_AddThirdAndFourthArg(); + +extern "C" void DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Class_TestForNull(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Class(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Class_0_0(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Class_0_1(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Class_0_2(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Class_0_3(); + +extern "C" void DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Method_TestForNull(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Method(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Method_0(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Method_1(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Method_2(); +extern "C" void DynamicHelper_GenericDictionaryLookup_Method_3(); + +PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, PCODE target) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Helper = (TADDR)target; + PCODE result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_CallHelper_1Arg, (TADDR)pArgs); + amTracker.SuppressRelease(); + return result; +} + +PCODE EmitDynamicHelperWithArg(LoaderAllocator * pAllocator, AllocMemTracker *pamTracker, TADDR arg, PCODE target) +{ + STANDARD_VM_CONTRACT; + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Helper = (TADDR)target; + PCODE result = CreateDynamicHelperPrecode(pAllocator, pamTracker, (PCODE)DynamicHelper_CallHelper_AddSecondArg, (TADDR)pArgs); + return result; +} + +PCODE DynamicHelpers::CreateHelperWithArg(LoaderAllocator * pAllocator, TADDR arg, PCODE target) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + PCODE result = EmitDynamicHelperWithArg(pAllocator, &amTracker, arg, target); + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, TADDR arg2, PCODE target) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Constant2 = arg2; + pArgs->Helper = (TADDR)target; + PCODE result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_CallHelper_2Arg, (TADDR)pArgs); + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateHelperArgMove(LoaderAllocator * pAllocator, TADDR arg, PCODE target) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Helper = (TADDR)target; + PCODE result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_CallHelper_ArgMove, (TADDR)pArgs); + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateReturn(LoaderAllocator * pAllocator) +{ + LIMITED_METHOD_CONTRACT; + return (PCODE)DynamicHelper_Return; +} + +PCODE DynamicHelpers::CreateReturnConst(LoaderAllocator * pAllocator, TADDR arg) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + PCODE result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_ReturnConst, arg); + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateReturnIndirConst(LoaderAllocator * pAllocator, TADDR arg, INT8 offset) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + PCODE result; + if (offset == 0) + { + result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_ReturnIndirConst, arg); + } + else + { + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Constant2 = (TADDR)offset; + result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_ReturnIndirConstWithOffset, (TADDR)pArgs); + } + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, PCODE target) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Helper = (TADDR)target; + PCODE result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_CallHelper_AddThirdArg, (TADDR)pArgs); + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, TADDR arg2, PCODE target) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + DynamicHelperStubArgs * pArgs = (DynamicHelperStubArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicHelperStubArgs)))); + + pArgs->Constant1 = arg; + pArgs->Constant2 = arg2; + pArgs->Helper = (TADDR)target; + PCODE result = CreateDynamicHelperPrecode(pAllocator, &amTracker, (PCODE)DynamicHelper_CallHelper_AddThirdAndFourthArg, (TADDR)pArgs); + amTracker.SuppressRelease(); + return result; +} + +PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, CORINFO_RUNTIME_LOOKUP * pLookup, DWORD dictionaryIndexAndSlot, Module * pModule) +{ + STANDARD_VM_CONTRACT; + + AllocMemTracker amTracker; + + PCODE helperAddress = GetDictionaryLookupHelper(pLookup->helper); + + WORD slotOffset = (WORD)(dictionaryIndexAndSlot & 0xFFFF) * sizeof(Dictionary*); + + // It's available only via the run-time helper function + PCODE helper = (PCODE)NULL; + if (pLookup->indirections == CORINFO_USEHELPER) + { + GenericHandleArgs * pArgs = (GenericHandleArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(GenericHandleArgs)))); + pArgs->dictionaryIndexAndSlot = dictionaryIndexAndSlot; + pArgs->signature = pLookup->signature; + pArgs->module = (CORINFO_MODULE_HANDLE)pModule; + PCODE result = EmitDynamicHelperWithArg(pAllocator, &amTracker, (TADDR)pArgs, helperAddress); + amTracker.SuppressRelease(); + return result; + } + else + { + PCODE result; + GenericDictionaryDynamicHelperStubData dictLookupData = {0}; + dictLookupData.SizeOffset = (UINT32)pLookup->sizeOffset; + dictLookupData.SlotOffset = slotOffset; + bool needsDictLookupData = false; + + if (pLookup->indirections == 3) + { + // Class! + _ASSERTE(helperAddress == g_pClassWithSlotAndModule); + _ASSERTE(pLookup->offsets[0] == offsetof(MethodTable, m_pPerInstInfo)); + dictLookupData.SecondIndir = (UINT32)pLookup->offsets[1]; + dictLookupData.LastIndir = (UINT32)pLookup->offsets[2]; + if (pLookup->testForNull && pLookup->sizeOffset != CORINFO_NO_SIZE_CHECK) + { + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class_SizeCheck_TestForNull; + needsDictLookupData = true; + } + else if (pLookup->testForNull) + { + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class_TestForNull; + needsDictLookupData = true; + } + else + { + _ASSERTE(pLookup->sizeOffset == CORINFO_NO_SIZE_CHECK); + if ((dictLookupData.SecondIndir == 0) && (dictLookupData.LastIndir <= sizeof(TADDR) * 3)) + { + needsDictLookupData = false; + switch (dictLookupData.LastIndir / sizeof(TADDR)) + { + case 0: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class_0_0; + break; + case 1: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class_0_1; + break; + case 2: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class_0_2; + break; + case 3: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class_0_3; + break; + } + } + else + { + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Class; + needsDictLookupData = true; + } + } + } + else if (pLookup->indirections == 2) + { + // Method! + _ASSERTE(helperAddress == g_pMethodWithSlotAndModule); + _ASSERTE(pLookup->offsets[0] == offsetof(InstantiatedMethodDesc, m_pPerInstInfo)); + dictLookupData.LastIndir = (UINT32)pLookup->offsets[1]; + if (pLookup->testForNull && pLookup->sizeOffset != CORINFO_NO_SIZE_CHECK) + { + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method_SizeCheck_TestForNull; + needsDictLookupData = true; + } + else if (pLookup->testForNull) + { + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method_TestForNull; + needsDictLookupData = true; + } + else + { + _ASSERTE(pLookup->sizeOffset == CORINFO_NO_SIZE_CHECK); + if ((dictLookupData.SecondIndir == 0) && (dictLookupData.LastIndir <= sizeof(TADDR) * 3)) + { + needsDictLookupData = false; + switch (dictLookupData.LastIndir / sizeof(TADDR)) + { + case 0: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method_0; + break; + case 1: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method_1; + break; + case 2: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method_2; + break; + case 3: + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method_3; + break; + } + } + else + { + helper = (PCODE)DynamicHelper_GenericDictionaryLookup_Method; + needsDictLookupData = true; + } + } + } + + if (needsDictLookupData) + { + GenericHandleArgs * pArgs = (GenericHandleArgs *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(GenericHandleArgs)))); + pArgs->dictionaryIndexAndSlot = dictionaryIndexAndSlot; + pArgs->signature = pLookup->signature; + pArgs->module = (CORINFO_MODULE_HANDLE)pModule; + + dictLookupData.HandleArgs = pArgs; + + GenericDictionaryDynamicHelperStubData *pDictLookupData = (GenericDictionaryDynamicHelperStubData *)amTracker.Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(GenericDictionaryDynamicHelperStubData)))); + *pDictLookupData = dictLookupData; + + _ASSERTE(helper != (PCODE)NULL); + result = CreateDynamicHelperPrecode(pAllocator, &amTracker, helper, (TADDR)pDictLookupData); + } + else + { + result = helper; + } + + amTracker.SuppressRelease(); + return result; + } +} +#endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS +#endif // DACCESS_COMPILE \ No newline at end of file diff --git a/src/coreclr/vm/readytoruninfo.h b/src/coreclr/vm/readytoruninfo.h index 74456a6e82aa17..7ff51806dbd088 100644 --- a/src/coreclr/vm/readytoruninfo.h +++ b/src/coreclr/vm/readytoruninfo.h @@ -372,4 +372,20 @@ class DynamicHelpers static PCODE CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, CORINFO_RUNTIME_LOOKUP * pLookup, DWORD dictionaryIndexAndSlot, Module * pModule); }; +struct DynamicHelperStubArgs +{ + TADDR Constant1; + TADDR Constant2; + TADDR Helper; +}; + +struct GenericDictionaryDynamicHelperStubData +{ + UINT32 SecondIndir; + UINT32 LastIndir; + UINT32 SizeOffset; + UINT32 SlotOffset; + GenericHandleArgs *HandleArgs; +}; + #endif // _READYTORUNINFO_H_ diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index f817791062aba2..937372b0bd39c3 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -32,6 +32,9 @@ ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::Inline #define DynamicHelperFrameFlags_ObjectArg 1 #define DynamicHelperFrameFlags_ObjectArg2 2 +#define ThisPtrRetBufPrecodeData__Target 0x00 +ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target)); + #define Thread__m_fPreemptiveGCDisabled 0x04 #define Thread__m_pFrame 0x08 diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index de3158440ae48c..e548ddd32d31c6 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -968,4 +968,14 @@ LOCAL_LABEL(JIT_PollGCRarePath): PREPARE_EXTERNAL_VAR g_pPollGC, t0 ld t0, 0(t0) jr t0 -LEAF_END JIT_PollGC, _TEXT \ No newline at end of file +LEAF_END JIT_PollGC, _TEXT + +//a0 -This pointer +//a1 -ReturnBuffer +LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT + ld t2, ThisPtrRetBufPrecodeData__Target(METHODDESC_REGISTER) + mv t6, a0 // Move first arg pointer to temp register + mv a0, a1 // Move ret buf arg pointer from location in ABI for return buffer for instance method to location in ABI for return buffer for static method + mv a1, t6 // Move temp register to first arg register for static method with return buffer + EPILOG_BRANCH_REG t2 +LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT diff --git a/src/coreclr/vm/riscv64/cgencpu.h b/src/coreclr/vm/riscv64/cgencpu.h index b6dac4cc709ec0..38cd6c9b0730a4 100644 --- a/src/coreclr/vm/riscv64/cgencpu.h +++ b/src/coreclr/vm/riscv64/cgencpu.h @@ -417,46 +417,4 @@ struct HijackArgs }; }; -// Precode to shuffle this and retbuf for closed delegates over static methods with return buffer -struct ThisPtrRetBufPrecode { - - static const int Type = 0x93; - - UINT32 m_rgCode[6]; - TADDR m_pTarget; - TADDR m_pMethodDesc; - - void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); - - TADDR GetMethodDesc() - { - LIMITED_METHOD_DAC_CONTRACT; - - return m_pMethodDesc; - } - - PCODE GetTarget() - { - LIMITED_METHOD_DAC_CONTRACT; - return m_pTarget; - } - -#ifndef DACCESS_COMPILE - BOOL SetTargetInterlocked(TADDR target, TADDR expected) - { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - } - CONTRACTL_END; - - ExecutableWriterHolder precodeWriterHolder(this, sizeof(ThisPtrRetBufPrecode)); - return (TADDR)InterlockedCompareExchange64( - (LONGLONG*)&precodeWriterHolder.GetRW()->m_pTarget, (TADDR)target, (TADDR)expected) == expected; - } -#endif // !DACCESS_COMPILE -}; -typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; - #endif // __cgencpu_h__ diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index fdb6f46023526e..20e7c20142f14f 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -467,30 +467,6 @@ void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool update ClearRegDisplayArgumentAndScratchRegisters(pRD); } -#ifndef DACCESS_COMPILE -void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) -{ - WRAPPER_NO_CONTRACT; - - //Initially - //a0 -This ptr - //a1 -ReturnBuffer - m_rgCode[0] = 0x00050f93; // addi t6, a0, 0x0 - m_rgCode[1] = 0x00058513; // addi a0, a1, 0x0 - m_rgCode[2] = 0x000f8593; // addi a1, t6, 0x0 - m_rgCode[3] = 0x00000f97; // auipc t6, 0 - m_rgCode[4] = 0x00cfbf83; // ld t6, 12(t6) - m_rgCode[5] = 0x000f8067; // jalr x0, 0(t6) - - _ASSERTE((UINT32*)&m_pTarget == &m_rgCode[6]); - _ASSERTE(6 == ARRAY_SIZE(m_rgCode)); - - m_pTarget = GetPreStubEntryPoint(); - m_pMethodDesc = (TADDR)pMD; -} - -#endif // !DACCESS_COMPILE - void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * pCalleeSaved) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index c84c6105fcff30..817cbb65514628 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -440,6 +440,10 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers /*= NULL*/, EECodeInfo * pCodeInfo /*= NULL*/) { +#ifdef TARGET_WASM + _ASSERTE("VirtualUnwindCallFrame is not supported on WebAssembly"); + return 0; +#else CONTRACTL { NOTHROW; @@ -542,6 +546,7 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, #endif // !DACCESS_COMPILE return uControlPc; +#endif // TARGET_WASM } #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index 4b652513b6aade..59869297e99f02 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -1015,6 +1015,9 @@ BOOL PrecodeStubManager::CheckIsStub_Internal(PCODE stubStartAddress) case PRECODE_STUB: case PRECODE_NDIRECT_IMPORT: case PRECODE_UMENTRY_THUNK: +#ifdef HAS_THISPTR_RETBUF_PRECODE + case PRECODE_THISPTR_RETBUF: +#endif // HAS_THISPTR_RETBUF_PRECODE return TRUE; default: return FALSE; @@ -1501,7 +1504,6 @@ BOOL RangeSectionStubManager::CheckIsStub_Internal(PCODE stubStartAddress) switch (GetStubKind(stubStartAddress)) { - case STUB_CODE_BLOCK_PRECODE: case STUB_CODE_BLOCK_JUMPSTUB: case STUB_CODE_BLOCK_STUBLINK: case STUB_CODE_BLOCK_METHOD_CALL_THUNK: @@ -1533,9 +1535,6 @@ BOOL RangeSectionStubManager::DoTraceStub(PCODE stubStartAddress, TraceDestinati switch (GetStubKind(stubStartAddress)) { - case STUB_CODE_BLOCK_PRECODE: - return PrecodeStubManager::g_pManager->DoTraceStub(stubStartAddress, trace); - case STUB_CODE_BLOCK_JUMPSTUB: return JumpStubStubManager::g_pManager->DoTraceStub(stubStartAddress, trace); @@ -1572,9 +1571,6 @@ LPCWSTR RangeSectionStubManager::GetStubManagerName(PCODE addr) switch (GetStubKind(addr)) { - case STUB_CODE_BLOCK_PRECODE: - return W("MethodDescPrestub"); - case STUB_CODE_BLOCK_JUMPSTUB: return W("JumpStub"); diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 4fc2242095a37b..06216ef18fb9d8 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -15,10 +15,6 @@ #ifndef DACCESS_COMPILE -#if defined(TARGET_ANDROID) -#include -#endif // defined(TARGET_ANDROID) - thread_local size_t t_ThreadType; void ClrFlsSetThreadType(TlsThreadTypeFlag flag) @@ -124,8 +120,7 @@ LPVOID CQuickHeap::Alloc(UINT sz) // Output functions that avoid the crt's. //---------------------------------------------------------------------------- -static -void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite) +void PrintToStdErrA(const char *pszString) { CONTRACTL { @@ -135,58 +130,7 @@ void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite) } CONTRACTL_END - if (Handle == INVALID_HANDLE_VALUE || Handle == NULL) - return; - - BOOL success; - DWORD dwBytesWritten; - const size_t maxWriteFileSize = 32767; // This is somewhat arbitrary limit, but 2**16-1 doesn't work - - while (BytesToWrite > 0) { - DWORD dwChunkToWrite = (DWORD) min(BytesToWrite, maxWriteFileSize); - - // Try to write to handle. If this is not a CUI app, then this is probably - // not going to work unless the dev took special pains to set their own console - // handle during CreateProcess. So try it, but don't yell if it doesn't work in - // that case. Also, if we redirect stdout to a pipe then the pipe breaks (ie, we - // write to something like the UNIX head command), don't complain. - success = WriteFile(Handle, pszString, dwChunkToWrite, &dwBytesWritten, NULL); - if (!success) - { -#if defined(_DEBUG) - // This can happen if stdout is a closed pipe. This might not help - // much, but we'll have half a chance of seeing this. - OutputDebugStringA("CLR: Writing out an unhandled exception to stdout failed!\n"); - OutputDebugStringA(pszString); -#endif //_DEBUG - - break; - } - else { - _ASSERTE(dwBytesWritten == dwChunkToWrite); - } - pszString = pszString + dwChunkToWrite; - BytesToWrite -= dwChunkToWrite; - } - -} - -void PrintToStdErrA(const char *pszString) { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - FORBID_FAULT; - } - CONTRACTL_END - -#if defined(TARGET_ANDROID) - __android_log_write(ANDROID_LOG_FATAL, MAIN_CLR_MODULE_NAME_A, pszString); -#else - HANDLE Handle = GetStdHandle(STD_ERROR_HANDLE); - size_t len = strlen(pszString); - NPrintToHandleA(Handle, pszString, len); -#endif // defined(TARGET_ANDROID) + minipal_log_write_error(pszString); } void PrintToStdErrW(const WCHAR *pwzString) diff --git a/src/coreclr/vm/wasm/asmconstants.h b/src/coreclr/vm/wasm/asmconstants.h new file mode 100644 index 00000000000000..c43f599357ea26 --- /dev/null +++ b/src/coreclr/vm/wasm/asmconstants.h @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// asmconstants.h - +// +// This header defines field offsets and constants used by assembly code +// Be sure to rebuild clr/src/vm/ceemain.cpp after changing this file, to +// ensure that the constants match the expected C/C++ values + +#define DynamicHelperFrameFlags_ObjectArg 1 +#define DynamicHelperFrameFlags_ObjectArg2 2 diff --git a/src/coreclr/vm/wasm/cgencpu.h b/src/coreclr/vm/wasm/cgencpu.h new file mode 100644 index 00000000000000..2093a7a80a5499 --- /dev/null +++ b/src/coreclr/vm/wasm/cgencpu.h @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#ifndef __cgenwasm_h__ +#define __cgenwasm_h__ + +#include "stublink.h" +#include "utilcode.h" + +// preferred alignment for data +#define DATA_ALIGNMENT 4 + +#define CODE_SIZE_ALIGN 4 +#define LOG2SLOT LOG2_PTRSIZE + +// looks like this is mandatory for now +#define HAS_NDIRECT_IMPORT_PRECODE 1 +#define HAS_FIXUP_PRECODE 1 +// ThisPtrRetBufPrecode one is necessary for closed delegates over static methods with return buffer +#define HAS_THISPTR_RETBUF_PRECODE 1 + +#define BACK_TO_BACK_JUMP_ALLOCATE_SIZE 8 // # bytes to allocate for a back to back jump instruction + +//********************************************************************** +// Parameter size +//********************************************************************** + +inline unsigned StackElemSize(unsigned parmSize, bool isValueType = false /* unused */, bool isFloatHfa = false /* unused */) +{ + _ASSERTE("The function is not implemented on wasm"); + return 0; +} + +inline TADDR GetSP(const T_CONTEXT * context) +{ + _ASSERTE("The function is not implemented on wasm, it lacks registers"); + return 0; +} + +struct HijackArgs +{ +}; + +inline LPVOID STDCALL GetCurrentSP() +{ + _ASSERTE("The function is not implemented on wasm, it lacks registers"); + return nullptr; +} + +extern PCODE GetPreStubEntryPoint(); + +#define GetEEFuncEntryPoint(pfn) GFN_TADDR(pfn) + +//********************************************************************** +// Frames +//********************************************************************** + +//-------------------------------------------------------------------- +// This represents the callee saved (non-volatile) registers saved as +// of a FramedMethodFrame. +//-------------------------------------------------------------------- +typedef DPTR(struct CalleeSavedRegisters) PTR_CalleeSavedRegisters; +struct CalleeSavedRegisters { +}; + +//-------------------------------------------------------------------- +// This represents the arguments that are stored in volatile registers. +// This should not overlap the CalleeSavedRegisters since those are already +// saved separately and it would be wasteful to save the same register twice. +// If we do use a non-volatile register as an argument, then the ArgIterator +// will probably have to communicate this back to the PromoteCallerStack +// routine to avoid a double promotion. +//-------------------------------------------------------------------- +typedef DPTR(struct ArgumentRegisters) PTR_ArgumentRegisters; +struct ArgumentRegisters { +}; +#define NUM_ARGUMENT_REGISTERS 0 +#define ARGUMENTREGISTERS_SIZE sizeof(ArgumentRegisters) + +#define ENREGISTERED_RETURNTYPE_MAXSIZE 16 // not sure here, 16 bytes is v128 + +#define STACKWALK_CONTROLPC_ADJUST_OFFSET 0 + +class StubLinkerCPU : public StubLinker +{ +public: + static void Init(); + void EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray); + VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg); +}; + +//********************************************************************** +// Exception handling +//********************************************************************** + +inline PCODE GetIP(const T_CONTEXT * context) { + _ASSERT("GetIP is not implemented on wasm, it lacks registers"); + return 0; +} + +inline void SetIP(T_CONTEXT *context, PCODE eip) { + _ASSERT("SetIP is not implemented on wasm, it lacks registers"); +} + +inline void SetSP(T_CONTEXT *context, TADDR esp) { + _ASSERT("SetSP is not implemented on wasm, it lacks registers"); +} + +inline void SetFP(T_CONTEXT *context, TADDR ebp) { + _ASSERT("SetFP is not implemented on wasm, it lacks registers"); +} + +inline TADDR GetFP(const T_CONTEXT * context) +{ + _ASSERT("GetFP is not implemented on wasm, it lacks registers"); + return 0; +} + +#define ENUM_CALLEE_SAVED_REGISTERS() + +#define ENUM_FP_CALLEE_SAVED_REGISTERS() + +// ClrFlushInstructionCache is used when we want to call FlushInstructionCache +// for a specific architecture in the common code, but not for other architectures. +// On IA64 ClrFlushInstructionCache calls the Kernel FlushInstructionCache function +// to flush the instruction cache. +// We call ClrFlushInstructionCache whenever we create or modify code in the heap. +// Currently ClrFlushInstructionCache has no effect on X86 +// + +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) +{ + // no-op on wasm + return true; +} + +// +// On IA64 back to back jumps should be separated by a nop bundle to get +// the best performance from the hardware's branch prediction logic. +// For all other platforms back to back jumps don't require anything special +// That is why we have these two wrapper functions that call emitJump and decodeJump +// + +//------------------------------------------------------------------------ +inline void emitBackToBackJump(LPBYTE pBufferRX, LPBYTE pBufferRW, LPVOID target) +{ + _ASSERTE("emitBackToBackJump is not implemented on wasm"); +} + +//------------------------------------------------------------------------ +inline PCODE decodeBackToBackJump(PCODE pBuffer) +{ + _ASSERTE("decodeBackToBackJump is not implemented on wasm"); + return 0; +} + +FORCEINLINE int64_t PalInterlockedCompareExchange64(_Inout_ int64_t volatile *pDst, int64_t iValue, int64_t iComparand) +{ + int64_t result = __sync_val_compare_and_swap(pDst, iComparand, iValue); + __sync_synchronize(); + return result; +} + +#endif // __cgenwasm_h__ diff --git a/src/coreclr/vm/wasm/excepcpu.h b/src/coreclr/vm/wasm/excepcpu.h new file mode 100644 index 00000000000000..7ca5a994a60760 --- /dev/null +++ b/src/coreclr/vm/wasm/excepcpu.h @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// copied from arm and left empty. wasm cannot do most of it + +#ifndef __excepcpu_h__ +#define __excepcpu_h__ + +#define THROW_CONTROL_FOR_THREAD_FUNCTION ThrowControlForThread + +#define STATUS_CLR_GCCOVER_CODE STATUS_ILLEGAL_INSTRUCTION + +class Thread; +class FaultingExceptionFrame; + +#define INSTALL_EXCEPTION_HANDLING_RECORD(record) +#define UNINSTALL_EXCEPTION_HANDLING_RECORD(record) +#define DECLARE_CPFH_EH_RECORD(pCurThread) + +// +// Retrieves the redirected CONTEXT* from the stack frame of one of the +// RedirectedHandledJITCaseForXXX_Stub's. +// +PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext); + +inline +PCODE GetAdjustedCallAddress(PCODE returnAddress) +{ + return returnAddress; +} + +BOOL AdjustContextForVirtualStub(EXCEPTION_RECORD *pExceptionRecord, T_CONTEXT *pContext); + +#endif // __excepcpu_h__ diff --git a/src/coreclr/vm/wasm/gmscpu.h b/src/coreclr/vm/wasm/gmscpu.h new file mode 100644 index 00000000000000..5355cfbc546ee6 --- /dev/null +++ b/src/coreclr/vm/wasm/gmscpu.h @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __gmscpu_h__ +#define __gmscpu_h__ + +#define __gmscpu_h__ + + // A MachState indicates the register state of the processor at some point in time (usually + // just before or after a call is made). It can be made one of two ways. Either explicitly + // (when you for some reason know the values of all the registers), or implicitly using the + // GET_STATE macros. + + typedef DPTR(struct MachState) PTR_MachState; + struct MachState { + + BOOL isValid() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; } + TADDR GetRetAddr() { LIMITED_METHOD_DAC_CONTRACT; return 0; } + + friend class HelperMethodFrame; + friend class CheckAsmOffsets; + friend struct LazyMachState; + }; + + /********************************************************************/ + /* This allows you to defer the computation of the Machine state + until later. Note that we don't reuse slots, because we want + this to be threadsafe without locks */ + + struct LazyMachState : public MachState { + // compute the machine state of the processor as it will exist just + // after the return after at most'funCallDepth' number of functions. + // if 'testFtn' is non-NULL, the return address is tested at each + // return instruction encountered. If this test returns non-NULL, + // then stack walking stops (thus you can walk up to the point that the + // return address matches some criteria + + // Normally this is called with funCallDepth=1 and testFtn = 0 so that + // it returns the state of the processor after the function that called 'captureState()' + void setLazyStateFromUnwind(MachState* copy); + static void unwindLazyState(LazyMachState* baseState, + MachState* lazyState, + DWORD threadId, + int funCallDepth = 1); + + friend class HelperMethodFrame; + friend class CheckAsmOffsets; + }; + + // R4 - R11 + #define NUM_NONVOLATILE_CONTEXT_POINTERS 8 + + inline void LazyMachState::setLazyStateFromUnwind(MachState* copy) + { + _ASSERTE("LazyMachState::setLazyStateFromUnwind is not implemented"); + } + typedef DPTR(LazyMachState) PTR_LazyMachState; + + // Do the initial capture of the machine state. This is meant to be + // as light weight as possible, as we may never need the state that + // we capture. Thus to complete the process you need to call + // 'getMachState()', which finishes the process + EXTERN_C void LazyMachStateCaptureState(struct LazyMachState *pState); + + // CAPTURE_STATE captures just enough register state so that the state of the + // processor can be deterined just after the routine that has CAPTURE_STATE in + // it returns. + + #define CAPTURE_STATE(machState, ret) \ + LazyMachStateCaptureState(machState) + + #endif diff --git a/src/installer/tests/Directory.Build.targets b/src/installer/tests/Directory.Build.targets index 23bb37cf3fa2aa..3aaa7130200a5a 100644 --- a/src/installer/tests/Directory.Build.targets +++ b/src/installer/tests/Directory.Build.targets @@ -60,6 +60,12 @@ File="$(OutDir)TestContextVariables.txt" Overwrite="true" Lines="@(TestContextVariable)" /> + + + diff --git a/src/installer/tests/HostActivation.Tests/DependencyResolution/DependencyResolutionCommandResultExtensions.cs b/src/installer/tests/HostActivation.Tests/DependencyResolution/DependencyResolutionCommandResultExtensions.cs index 8933efc79501fd..7e057cff09cec4 100644 --- a/src/installer/tests/HostActivation.Tests/DependencyResolution/DependencyResolutionCommandResultExtensions.cs +++ b/src/installer/tests/HostActivation.Tests/DependencyResolution/DependencyResolutionCommandResultExtensions.cs @@ -18,10 +18,11 @@ public static class DependencyResolutionCommandResultExtensions public static AndConstraint HaveRuntimePropertyContaining(this CommandResultAssertions assertion, string propertyName, params string[] values) { string propertyValue = GetAppMockPropertyValue(assertion, propertyName); + AssertionChain assertionChain = AssertionChain.GetOrCreate(); foreach (string value in values) { - Execute.Assertion.ForCondition(propertyValue != null && propertyValue.Contains(value)) + assertionChain.ForCondition(propertyValue != null && propertyValue.Contains(value)) .FailWith($"The property {propertyName} doesn't contain expected value: '{value}'{Environment.NewLine}" + $"{propertyName}='{propertyValue}'" + $"{assertion.GetDiagnosticsInfo()}"); @@ -33,10 +34,11 @@ public static AndConstraint HaveRuntimePropertyContaini public static AndConstraint NotHaveRuntimePropertyContaining(this CommandResultAssertions assertion, string propertyName, params string[] values) { string propertyValue = GetAppMockPropertyValue(assertion, propertyName); + AssertionChain assertionChain = AssertionChain.GetOrCreate(); foreach (string value in values) { - Execute.Assertion.ForCondition(propertyValue != null && !propertyValue.Contains(value)) + assertionChain.ForCondition(propertyValue != null && !propertyValue.Contains(value)) .FailWith($"The property {propertyName} contains unexpected value: '{value}'{Environment.NewLine}" + $"{propertyName}='{propertyValue}'" + $"{assertion.GetDiagnosticsInfo()}"); @@ -80,10 +82,11 @@ public static AndConstraint HaveResolvedComponentDepend params string[] values) { string propertyValue = GetComponentMockPropertyValue(assertion, propertyName); + AssertionChain assertionChain = AssertionChain.GetOrCreate(); foreach (string value in values) { - Execute.Assertion.ForCondition(propertyValue != null && propertyValue.Contains(value)) + assertionChain.ForCondition(propertyValue != null && propertyValue.Contains(value)) .FailWith($"The resolved {propertyName} doesn't contain expected value: '{value}'{Environment.NewLine}" + $"{propertyName}='{propertyValue}'" + $"{assertion.GetDiagnosticsInfo()}"); @@ -98,10 +101,11 @@ public static AndConstraint NotHaveResolvedComponentDep params string[] values) { string propertyValue = GetComponentMockPropertyValue(assertion, propertyName); + AssertionChain assertionChain = AssertionChain.GetOrCreate(); foreach (string value in values) { - Execute.Assertion.ForCondition(propertyValue != null && !propertyValue.Contains(value)) + assertionChain.ForCondition(propertyValue != null && !propertyValue.Contains(value)) .FailWith($"The resolved {propertyName} contains unexpected value: '{value}'{Environment.NewLine}" + $"{propertyName}='{propertyValue}'" + $"{assertion.GetDiagnosticsInfo()}"); diff --git a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs index 122930edf12547..d23a2593b2a223 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs @@ -237,6 +237,32 @@ public void Hostfxr_resolve_sdk2_with_global_json_and_disallowing_previews() } } + [Fact] + public void Hostfxr_resolve_sdk2_GlobalJson_Paths() + { + // With global.json specifying custom search paths, no version. + // Return first search location match (latest in that location). + + var f = sharedTestState.SdkAndFrameworkFixture; + using (TestArtifact workingDir = TestArtifact.Create(nameof(workingDir))) + { + string globalJson = GlobalJson.Write(workingDir.Location, new GlobalJson.Sdk() { Paths = [ f.SelfRegistered, f.LocalSdkDir ] }); + string expectedData = string.Join(';', new[] + { + ("resolved_sdk_dir", Path.Combine(f.SelfRegisteredGlobalSdkDir, "15.1.4-preview")), + ("global_json_path", globalJson) + }); + + string api = ApiNames.hostfxr_resolve_sdk2; + TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, f.ExeDir, workingDir.Location, "0") + .EnableTracingAndCaptureOutputs() + .Execute() + .Should().Pass() + .And.ReturnStatusCode(api, Constants.ErrorCode.Success) + .And.HaveStdOutContaining($"{api} data:[{expectedData}]"); + } + } + [Fact] public void Hostfxr_corehost_set_error_writer_test() { diff --git a/src/installer/tests/HostActivation.Tests/SDKLookup.cs b/src/installer/tests/HostActivation.Tests/SDKLookup.cs index 923bf60568b265..7a4e5876781226 100644 --- a/src/installer/tests/HostActivation.Tests/SDKLookup.cs +++ b/src/installer/tests/HostActivation.Tests/SDKLookup.cs @@ -38,7 +38,7 @@ public SDKLookup(SharedTestState sharedState) } [Fact] - public void SdkLookup_Global_Json_Single_Digit_Patch_Rollup() + public void GlobalJson_SingleDigitPatch() { // Set specified SDK version = 9999.3.4-global-dummy string requestedVersion = "9999.3.4-global-dummy"; @@ -133,7 +133,7 @@ public void SdkLookup_Global_Json_Single_Digit_Patch_Rollup() } [Fact] - public void SdkLookup_Global_Json_Two_Part_Patch_Rollup() + public void GlobalJson_TwoPartPatch() { // Set specified SDK version = 9999.3.304-global-dummy string requestedVersion = "9999.3.304-global-dummy"; @@ -226,7 +226,7 @@ public void SdkLookup_Global_Json_Two_Part_Patch_Rollup() } [Fact] - public void SdkLookup_Negative_Version() + public void NegativeVersion() { GlobalJson.CreateEmpty(SharedState.CurrentWorkingDir); @@ -257,7 +257,7 @@ public void SdkLookup_Negative_Version() } [Fact] - public void SdkLookup_Must_Pick_The_Highest_Semantic_Version() + public void PickHighestSemanticVersion() { GlobalJson.CreateEmpty(SharedState.CurrentWorkingDir); @@ -355,7 +355,7 @@ public void SdkLookup_Must_Pick_The_Highest_Semantic_Version() [InlineData("Latestfeature")] [InlineData("latestMINOR")] [InlineData("latESTMajor")] - public void It_allows_case_insensitive_roll_forward_policy_names(string rollForward) + public void RollForwardPolicy_CaseInsensitive(string rollForward) { const string Requested = "9999.0.100"; AddAvailableSdkVersions(Requested); @@ -369,7 +369,7 @@ public void It_allows_case_insensitive_roll_forward_policy_names(string rollForw [Theory] [MemberData(nameof(InvalidGlobalJsonData))] - public void It_falls_back_to_latest_sdk_for_invalid_global_json(string globalJsonContents, string[] messages) + public void InvalidGlobalJson_FallsBackToLatestSdk(string globalJsonContents, string[] messages) { AddAvailableSdkVersions("9999.0.100", "9999.0.300-dummy.9", "9999.1.402"); @@ -387,7 +387,7 @@ public void It_falls_back_to_latest_sdk_for_invalid_global_json(string globalJso [Theory] [MemberData(nameof(SdkRollForwardData))] - public void It_rolls_forward_as_expected(string policy, string requested, bool allowPrerelease, string expected, string[] installed) + public void RollForward(string policy, string requested, bool allowPrerelease, string expected, string[] installed) { AddAvailableSdkVersions(installed); @@ -409,7 +409,7 @@ public void It_rolls_forward_as_expected(string policy, string requested, bool a } [Fact] - public void It_uses_latest_stable_sdk_if_allow_prerelease_is_false() + public void AllowPrereleaseFalse_UseLatestRelease() { var installed = new string[] { "9999.1.702", @@ -437,6 +437,172 @@ public void It_uses_latest_stable_sdk_if_allow_prerelease_is_false() .And.HaveStdErrContaining($"SDK path resolved to [{Path.Combine(ExecutableDotNet.BinPath, "sdk", ExpectedVersion)}]"); } + [Fact] + public void GlobalJson_Paths() + { + GlobalJson.Sdk sdk = new() { Paths = [] }; + string globalJsonPath = GlobalJson.Write(SharedState.CurrentWorkingDir, sdk ); + + // Add SDK versions + AddAvailableSdkVersions("9999.0.4"); + + // Paths: none + // Exe: 9999.0.4 + // Expected: no SDKs found + RunTest() + .Should().Fail() + .And.FindAnySdk(false) + .And.HaveStdErrContaining($"Empty search paths specified in global.json file: {globalJsonPath}"); + + sdk.Paths = [ GlobalJson.HostSdkPath ]; + globalJsonPath = GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Paths: $host$ + // Exe: 9999.0.4 + // Expected: 9999.0.4 from exe dir + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.4")); + + using TestArtifact custom = TestArtifact.Create("sdkPath"); + AddSdkToCustomPath(custom.Location, "9999.0.4"); + sdk.Paths = [ custom.Location ]; + globalJsonPath = GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Paths: custom (absolute) + // Custom: 9999.0.4 + // Exe: 9999.0.4 + // Expected: 9999.0.4 from custom dir + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.4", custom.Location)); + + string relativePath = Path.GetRelativePath(SharedState.CurrentWorkingDir, custom.Location); + sdk.Paths = [ relativePath ]; + GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Paths: custom (relative, outside current directory) + // Custom: 9999.0.4 + // Exe: 9999.0.4 + // Expected: 9999.0.4 from custom dir + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.4", custom.Location)); + + string underCurrent = SharedState.CurrentWorkingDirArtifact.GetUniqueSubdirectory("sdkPath"); + AddSdkToCustomPath(underCurrent, "9999.0.4"); + + relativePath = Path.GetRelativePath(SharedState.CurrentWorkingDir, underCurrent); + sdk.Paths = [relativePath]; + GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Paths: custom (relative, under current directory) + // Custom: 9999.0.4 + // Exe: 9999.0.4 + // Expected: 9999.0.4 from custom dir + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.4", Path.Combine(SharedState.CurrentWorkingDir, relativePath))); + } + + [Fact] + public void GlobalJson_Paths_Multiple() + { + using TestArtifact custom = TestArtifact.Create("sdkPath"); + AddSdkToCustomPath(custom.Location, "9999.0.0"); + + GlobalJson.Sdk sdk = new() { Paths = [ custom.Location, GlobalJson.HostSdkPath ] }; + GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Add SDK versions + AddAvailableSdkVersions("9999.0.4"); + + // Specified SDK + // version: none + // paths: custom, $host$ + // Custom: 9999.0.0 + // Exe: 9999.0.4 + // Expected: 9999.0.0 from custom dir + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.0", custom.Location)); + + sdk.Version = "9999.0.3"; + GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Specified SDK + // version: 9999.0.3 + // paths: custom, $host$ + // Custom: 9999.0.0 + // Exe: 9999.0.4 + // Expected: 9999.0.4 from exe dir + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.4")); + + sdk.Version = "9999.0.5"; + string globalJsonPath = GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Specified SDK + // version: 9999.0.5 + // paths: custom, $host$ + // Custom: 9999.0.0 + // Exe: 9999.0.4 + // Expected: no compatible version + RunTest() + .Should().Fail() + .And.NotFindCompatibleSdk(globalJsonPath, sdk.Version) + .And.FindAnySdk(true); + + // Verify we have the expected SDK versions + RunTest("--list-sdks") + .Should().Pass() + .And.HaveStdOutContaining($"9999.0.0 [{custom.Location}") + .And.HaveStdOutContaining($"9999.0.4 [{ExecutableDotNet.BinPath}"); + } + + [Fact] + public void GlobalJson_Paths_FirstMatch() + { + using TestArtifact custom1 = TestArtifact.Create("sdkPath1"); + AddSdkToCustomPath(custom1.Location, "9999.0.0"); + using TestArtifact custom2 = TestArtifact.Create("sdkPath2"); + AddSdkToCustomPath(custom2.Location, "9999.0.2"); + AddAvailableSdkVersions("9999.0.1"); + + GlobalJson.Sdk sdk = new() { Version = "9999.0.1", Paths = [ custom1.Location, custom2.Location, GlobalJson.HostSdkPath ] }; + GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + // Specified SDK + // version: none + // paths: custom1, custom2, $host$ + // Custom1: 9999.0.0 + // Custom2: 9999.0.2 + // Exe: 9999.0.1 + // Expected: 9999.0.2 from custom2 - first match is used, not best match (which would be exe which is an exact match) + RunTest() + .Should().Pass() + .And.HaveStdErrContaining(ExpectedResolvedSdkOutput("9999.0.2", custom2.Location)); + + // Verify we have the expected SDK versions + RunTest("--list-sdks") + .Should().Pass() + .And.HaveStdOutContaining($"9999.0.0 [{custom1.Location}") + .And.HaveStdOutContaining($"9999.0.2 [{custom2.Location}") + .And.HaveStdOutContaining($"9999.0.1 [{ExecutableDotNet.BinPath}"); + } + + [Fact] + public void GlobalJson_ErrorMessage() + { + GlobalJson.Sdk sdk = new() { ErrorMessage = "Custom SDK resolution error" }; + GlobalJson.Write(SharedState.CurrentWorkingDir, sdk); + + RunTest() + .Should().Fail() + .And.HaveStdErrContaining(sdk.ErrorMessage); + } + public static IEnumerable InvalidGlobalJsonData { get @@ -472,7 +638,7 @@ public static IEnumerable InvalidGlobalJsonData // Use an invalid version value yield return new object[] { - GlobalJson.FormatVersionSettings(version: "invalid"), + GlobalJson.FormatSettings(new GlobalJson.Sdk() { Version = "invalid" }), new[] { "Version 'invalid' is not valid for the 'sdk/version' value", IgnoringSDKSettings @@ -490,7 +656,7 @@ public static IEnumerable InvalidGlobalJsonData // Use a policy but no version yield return new object[] { - GlobalJson.FormatVersionSettings(policy: "latestPatch"), + GlobalJson.FormatSettings(new GlobalJson.Sdk() { RollForward = "latestPatch" }), new[] { "The roll-forward policy 'latestPatch' requires a 'sdk/version' value", IgnoringSDKSettings @@ -499,7 +665,7 @@ public static IEnumerable InvalidGlobalJsonData // Use an invalid policy value yield return new object[] { - GlobalJson.FormatVersionSettings(policy: "invalid"), + GlobalJson.FormatSettings(new GlobalJson.Sdk() { RollForward = "invalid" }), new[] { "The roll-forward policy 'invalid' is not supported for the 'sdk/rollForward' value", IgnoringSDKSettings @@ -517,7 +683,7 @@ public static IEnumerable InvalidGlobalJsonData // Use a prerelease version and allowPrerelease = false yield return new object[] { - GlobalJson.FormatVersionSettings(version: "9999.1.402-preview1", allowPrerelease: false), + GlobalJson.FormatSettings(new GlobalJson.Sdk() { Version = "9999.1.402-preview1", AllowPrerelease = false }), new[] { "Ignoring the 'sdk/allowPrerelease' value" } }; } @@ -992,6 +1158,15 @@ public static IEnumerable SdkRollForwardData } } + private static void AddSdkToCustomPath(string sdkRoot, string version) + { + DotNetBuilder.AddMockSDK(sdkRoot, version, version); + + // Add a mock framework matching the runtime version for the mock SDK + // This allows the host to successfully resolve frameworks for the SDK at the custom location + DotNetBuilder.AddMicrosoftNETCoreAppFrameworkMockHostPolicy(sdkRoot, version); + } + // This method adds a list of new sdk version folders in the specified directory. // The actual contents are 'fake' and the minimum required for SDK discovery. // The dotnet.runtimeconfig.json created uses a dummy framework version (9999.0.0) @@ -1003,8 +1178,8 @@ private void AddAvailableSdkVersions(params string[] availableVersions) } } - private string ExpectedResolvedSdkOutput(string expectedVersion) - => Path.Combine("Using .NET SDK dll=[", ExecutableDotNet.BinPath, "sdk", expectedVersion, "dotnet.dll]"); + private string ExpectedResolvedSdkOutput(string expectedVersion, string rootPath = null) + => $"Using .NET SDK dll=[{Path.Combine(rootPath == null ? ExecutableDotNet.BinPath : rootPath, "sdk", expectedVersion, "dotnet.dll")}]"; private CommandResult RunTest() => RunTest("help"); @@ -1021,6 +1196,7 @@ public sealed class SharedTestState : IDisposable { public TestArtifact BaseArtifact { get; } + public TestArtifact CurrentWorkingDirArtifact { get; } public string CurrentWorkingDir { get; } public SharedTestState() @@ -1035,10 +1211,12 @@ public SharedTestState() .AddMockSDK("10000.0.0", "9999.0.0") .Build(); CurrentWorkingDir = currentWorkingSdk.BinPath; + CurrentWorkingDirArtifact = new TestArtifact(CurrentWorkingDir); } public void Dispose() { + CurrentWorkingDirArtifact.Dispose(); BaseArtifact.Dispose(); } } diff --git a/src/installer/tests/TestUtils/Assertions/CommandResultAssertions.cs b/src/installer/tests/TestUtils/Assertions/CommandResultAssertions.cs index 8d4d65ab723bfb..25acf3d3123e32 100644 --- a/src/installer/tests/TestUtils/Assertions/CommandResultAssertions.cs +++ b/src/installer/tests/TestUtils/Assertions/CommandResultAssertions.cs @@ -14,9 +14,12 @@ public class CommandResultAssertions { public CommandResult Result { get; } - public CommandResultAssertions(CommandResult commandResult) + public AssertionChain CurrentAssertionChain { get; } + + public CommandResultAssertions(CommandResult commandResult, AssertionChain assertionChain) { Result = commandResult; + CurrentAssertionChain = assertionChain; } public AndConstraint ExitWith(int expectedExitCode) @@ -25,112 +28,112 @@ public AndConstraint ExitWith(int expectedExitCode) if (!OperatingSystem.IsWindows()) expectedExitCode = expectedExitCode & 0xFF; - Execute.Assertion.ForCondition(Result.ExitCode == expectedExitCode) + CurrentAssertionChain.ForCondition(Result.ExitCode == expectedExitCode) .FailWith($"Expected command to exit with {expectedExitCode} but it did not.{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint Pass() { - Execute.Assertion.ForCondition(Result.ExitCode == 0) + CurrentAssertionChain.ForCondition(Result.ExitCode == 0) .FailWith($"Expected command to pass but it did not.{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint Fail() { - Execute.Assertion.ForCondition(Result.ExitCode != 0) + CurrentAssertionChain.ForCondition(Result.ExitCode != 0) .FailWith($"Expected command to fail but it did not.{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdOut() { - Execute.Assertion.ForCondition(!string.IsNullOrEmpty(Result.StdOut)) + CurrentAssertionChain.ForCondition(!string.IsNullOrEmpty(Result.StdOut)) .FailWith($"Command did not output anything to stdout{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdOut(string expectedOutput) { - Execute.Assertion.ForCondition(Result.StdOut.Equals(expectedOutput, StringComparison.Ordinal)) + CurrentAssertionChain.ForCondition(Result.StdOut.Equals(expectedOutput, StringComparison.Ordinal)) .FailWith($"Command did not output with Expected Output. Expected: '{expectedOutput}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdOutContaining(string pattern) { - Execute.Assertion.ForCondition(Result.StdOut.Contains(pattern)) + CurrentAssertionChain.ForCondition(Result.StdOut.Contains(pattern)) .FailWith($"The command output did not contain expected result: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint NotHaveStdOutContaining(string pattern) { - Execute.Assertion.ForCondition(!Result.StdOut.Contains(pattern)) + CurrentAssertionChain.ForCondition(!Result.StdOut.Contains(pattern)) .FailWith($"The command output contained a result it should not have contained: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) { - Execute.Assertion.ForCondition(Regex.IsMatch(Result.StdOut, pattern, options)) + CurrentAssertionChain.ForCondition(Regex.IsMatch(Result.StdOut, pattern, options)) .FailWith($"Matching the command output failed. Pattern: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint NotHaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) { - Execute.Assertion.ForCondition(!Regex.IsMatch(Result.StdOut, pattern, options)) + CurrentAssertionChain.ForCondition(!Regex.IsMatch(Result.StdOut, pattern, options)) .FailWith($"The command output matched a pattern is should not have matched. Pattern: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdErr() { - Execute.Assertion.ForCondition(!string.IsNullOrEmpty(Result.StdErr)) + CurrentAssertionChain.ForCondition(!string.IsNullOrEmpty(Result.StdErr)) .FailWith($"Command did not output anything to stderr.{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdErrContaining(string pattern) { - Execute.Assertion.ForCondition(Result.StdErr.Contains(pattern)) + CurrentAssertionChain.ForCondition(Result.StdErr.Contains(pattern)) .FailWith($"The command error output did not contain expected result: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint NotHaveStdErrContaining(string pattern) { - Execute.Assertion.ForCondition(!Result.StdErr.Contains(pattern)) + CurrentAssertionChain.ForCondition(!Result.StdErr.Contains(pattern)) .FailWith($"The command error output contained a result it should not have contained: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint HaveStdErrMatching(string pattern, RegexOptions options = RegexOptions.None) { - Execute.Assertion.ForCondition(Regex.IsMatch(Result.StdErr, pattern, options)) + CurrentAssertionChain.ForCondition(Regex.IsMatch(Result.StdErr, pattern, options)) .FailWith($"Matching the command error output failed. Pattern: '{pattern}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint NotHaveStdOut() { - Execute.Assertion.ForCondition(string.IsNullOrEmpty(Result.StdOut)) + CurrentAssertionChain.ForCondition(string.IsNullOrEmpty(Result.StdOut)) .FailWith($"Expected command to not output to stdout but it did:{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint NotHaveStdErr() { - Execute.Assertion.ForCondition(string.IsNullOrEmpty(Result.StdErr)) + CurrentAssertionChain.ForCondition(string.IsNullOrEmpty(Result.StdErr)) .FailWith($"Expected command to not output to stderr but it did:{GetDiagnosticsInfo()}"); return new AndConstraint(this); } public AndConstraint FileExists(string path) { - Execute.Assertion.ForCondition(System.IO.File.Exists(path)) + CurrentAssertionChain.ForCondition(System.IO.File.Exists(path)) .FailWith($"The command did not write the expected file: '{path}'{GetDiagnosticsInfo()}"); return new AndConstraint(this); } @@ -138,7 +141,7 @@ public AndConstraint FileExists(string path) public AndConstraint FileContains(string path, string pattern) { string fileContent = System.IO.File.ReadAllText(path); - Execute.Assertion.ForCondition(fileContent.Contains(pattern)) + CurrentAssertionChain.ForCondition(fileContent.Contains(pattern)) .FailWith($"The command did not write the expected result '{pattern}' to the file: '{path}'{GetDiagnosticsInfo()}{Environment.NewLine}file content: >>{fileContent}<<"); return new AndConstraint(this); } @@ -146,7 +149,7 @@ public AndConstraint FileContains(string path, string p public AndConstraint NotFileContains(string path, string pattern) { string fileContent = System.IO.File.ReadAllText(path); - Execute.Assertion.ForCondition(!fileContent.Contains(pattern)) + CurrentAssertionChain.ForCondition(!fileContent.Contains(pattern)) .FailWith($"The command did not write the expected result '{pattern}' to the file: '{path}'{GetDiagnosticsInfo()}{Environment.NewLine}file content: >>{fileContent}<<"); return new AndConstraint(this); } diff --git a/src/installer/tests/TestUtils/Assertions/CommandResultExtensions.cs b/src/installer/tests/TestUtils/Assertions/CommandResultExtensions.cs index 5430b1d905f2a1..5f30b2169f4200 100644 --- a/src/installer/tests/TestUtils/Assertions/CommandResultExtensions.cs +++ b/src/installer/tests/TestUtils/Assertions/CommandResultExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using FluentAssertions.Execution; using Microsoft.DotNet.Cli.Build.Framework; using System; @@ -11,13 +12,13 @@ public static class CommandResultExtensions { public static CommandResultAssertions Should(this CommandResult commandResult) { - return new CommandResultAssertions(commandResult); + return new CommandResultAssertions(commandResult, AssertionChain.GetOrCreate()); } public static CommandResult StdErrAfter(this CommandResult commandResult, string pattern) { int i = commandResult.StdErr.IndexOf(pattern); - i.Should().BeGreaterOrEqualTo( + i.Should().BeGreaterThanOrEqualTo( 0, "Trying to filter StdErr after '{0}', but such string can't be found in the StdErr.{1}{2}", pattern, diff --git a/src/installer/tests/TestUtils/Assertions/DirectoryInfoAssertions.cs b/src/installer/tests/TestUtils/Assertions/DirectoryInfoAssertions.cs index 9dccb26045ca78..8138a68368a458 100644 --- a/src/installer/tests/TestUtils/Assertions/DirectoryInfoAssertions.cs +++ b/src/installer/tests/TestUtils/Assertions/DirectoryInfoAssertions.cs @@ -13,17 +13,19 @@ namespace Microsoft.DotNet.CoreSetup.Test public class DirectoryInfoAssertions { private DirectoryInfo _dirInfo; + private AssertionChain _assertionChain; - public DirectoryInfoAssertions(DirectoryInfo dir) + public DirectoryInfoAssertions(DirectoryInfo dir, AssertionChain assertionChain) { _dirInfo = dir; + _assertionChain = assertionChain; } public DirectoryInfo DirectoryInfo => _dirInfo; public AndConstraint Exist() { - Execute.Assertion.ForCondition(_dirInfo.Exists) + _assertionChain.ForCondition(_dirInfo.Exists) .FailWith($"Expected directory '{_dirInfo.FullName}' does not exist."); return new AndConstraint(this); } @@ -31,7 +33,7 @@ public AndConstraint Exist() public AndConstraint HaveFile(string expectedFile) { var file = _dirInfo.EnumerateFiles(expectedFile, SearchOption.TopDirectoryOnly).SingleOrDefault(); - Execute.Assertion.ForCondition(file != null) + _assertionChain.ForCondition(file != null) .FailWith($"Expected File '{expectedFile}' cannot be found in directory '{_dirInfo.FullName}."); return new AndConstraint(this); } @@ -39,7 +41,7 @@ public AndConstraint HaveFile(string expectedFile) public AndConstraint NotHaveFile(string expectedFile) { var file = _dirInfo.EnumerateFiles(expectedFile, SearchOption.TopDirectoryOnly).SingleOrDefault(); - Execute.Assertion.ForCondition(file == null) + _assertionChain.ForCondition(file == null) .FailWith($"File '{expectedFile}' should not be found in directory '{_dirInfo.FullName}'."); return new AndConstraint(this); } @@ -67,19 +69,19 @@ public AndConstraint NotHaveFiles(IEnumerable e public AndConstraint HaveDirectory(string expectedDir) { var dir = _dirInfo.EnumerateDirectories(expectedDir, SearchOption.TopDirectoryOnly).SingleOrDefault(); - Execute.Assertion.ForCondition(dir != null) + _assertionChain.ForCondition(dir != null) .FailWith($"Expected directory '{expectedDir}' cannot be found inside directory '{_dirInfo.FullName}'."); - return new AndConstraint(new DirectoryInfoAssertions(dir)); + return new AndConstraint(new DirectoryInfoAssertions(dir, _assertionChain)); } public AndConstraint NotHaveDirectory(string expectedDir) { var dir = _dirInfo.EnumerateDirectories(expectedDir, SearchOption.TopDirectoryOnly).SingleOrDefault(); - Execute.Assertion.ForCondition(dir == null) + _assertionChain.ForCondition(dir == null) .FailWith($"Directory '{expectedDir}' should not be found in found inside directory '{_dirInfo.FullName}'."); - return new AndConstraint(new DirectoryInfoAssertions(dir)); + return new AndConstraint(new DirectoryInfoAssertions(dir, _assertionChain)); } public AndConstraint OnlyHaveFiles(IEnumerable expectedFiles) @@ -89,10 +91,10 @@ public AndConstraint OnlyHaveFiles(IEnumerable var extraFiles = Enumerable.Except(actualFiles, expectedFiles); var nl = Environment.NewLine; - Execute.Assertion.ForCondition(!missingFiles.Any()) + _assertionChain.ForCondition(!missingFiles.Any()) .FailWith($"Following files cannot be found inside directory {_dirInfo.FullName} {nl} {string.Join(nl, missingFiles)}"); - Execute.Assertion.ForCondition(!extraFiles.Any()) + _assertionChain.ForCondition(!extraFiles.Any()) .FailWith($"Following extra files are found inside directory {_dirInfo.FullName} {nl} {string.Join(nl, extraFiles)}"); return new AndConstraint(this); @@ -103,7 +105,7 @@ public AndConstraint NotBeModifiedAfter(DateTime timeUt _dirInfo.Refresh(); DateTime writeTime = _dirInfo.LastWriteTimeUtc; - Execute.Assertion.ForCondition(writeTime <= timeUtc) + _assertionChain.ForCondition(writeTime <= timeUtc) .FailWith($"Directory '{_dirInfo.FullName}' should not be modified after {timeUtc}, but is modified at {writeTime}."); return new AndConstraint(this); diff --git a/src/installer/tests/TestUtils/Assertions/DirectoryInfoExtensions.cs b/src/installer/tests/TestUtils/Assertions/DirectoryInfoExtensions.cs index 0f240d6a91bc2d..192bd1fad255fc 100644 --- a/src/installer/tests/TestUtils/Assertions/DirectoryInfoExtensions.cs +++ b/src/installer/tests/TestUtils/Assertions/DirectoryInfoExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using FluentAssertions.Execution; using System.IO; namespace Microsoft.DotNet.CoreSetup.Test @@ -9,7 +10,7 @@ public static class DirectoryInfoExtensions { public static DirectoryInfoAssertions Should(this DirectoryInfo dir) { - return new DirectoryInfoAssertions(dir); + return new DirectoryInfoAssertions(dir, AssertionChain.GetOrCreate()); } } } diff --git a/src/installer/tests/TestUtils/DotNetBuilder.cs b/src/installer/tests/TestUtils/DotNetBuilder.cs index 2ff602fd4b4f0b..b761b76b517c4b 100644 --- a/src/installer/tests/TestUtils/DotNetBuilder.cs +++ b/src/installer/tests/TestUtils/DotNetBuilder.cs @@ -48,17 +48,28 @@ public DotNetBuilder(string basePath, string builtDotnet, string name) /// Product runtime binaries are not added. All the added mock framework will contain is a mock version of host policy. /// public DotNetBuilder AddMicrosoftNETCoreAppFrameworkMockHostPolicy(string version) + { + AddMicrosoftNETCoreAppFrameworkMockHostPolicy(_path, version); + return this; + } + + /// + /// Add a mock of the Microsoft.NETCore.App framework with the specified version to the specified directory + /// + /// Version to add + /// + /// Product runtime binaries are not added. All the added mock framework will contain is a mock version of host policy. + /// + public static void AddMicrosoftNETCoreAppFrameworkMockHostPolicy(string directory, string version) { // ./shared/Microsoft.NETCore.App/ - create a mock of the root framework - string netCoreAppPath = AddFramework(Constants.MicrosoftNETCoreApp, version); + string netCoreAppPath = AddFramework(directory, Constants.MicrosoftNETCoreApp, version); // ./shared/Microsoft.NETCore.App//hostpolicy.dll - this is a mock, will not actually load CoreCLR File.Copy( Binaries.HostPolicy.MockPath, Path.Combine(netCoreAppPath, Binaries.HostPolicy.FileName), true); - - return this; } /// @@ -175,7 +186,16 @@ public DotNetBuilder AddMockSDK( string sdkVersion, string runtimeVersion) { - string path = Path.Combine(_path, "sdk", sdkVersion); + AddMockSDK(_path, sdkVersion, runtimeVersion); + return this; + } + + public static void AddMockSDK( + string directory, + string sdkVersion, + string runtimeVersion) + { + string path = Path.Combine(directory, "sdk", sdkVersion); Directory.CreateDirectory(path); using var _ = File.Create(Path.Combine(path, "dotnet.dll")); @@ -183,12 +203,13 @@ public DotNetBuilder AddMockSDK( RuntimeConfig dotnetRuntimeConfig = new RuntimeConfig(Path.Combine(path, "dotnet.runtimeconfig.json")); dotnetRuntimeConfig.WithFramework(new RuntimeConfig.Framework("Microsoft.NETCore.App", runtimeVersion)); dotnetRuntimeConfig.Save(); - - return this; } + private string AddFramework(string name, string version) + => AddFramework(_path, name, version); + /// - /// Add a minimal mock framework with the specified framework name and version + /// Add a minimal mock framework with the specified framework name and version to the specified directory /// /// Framework name /// Framework version @@ -196,10 +217,10 @@ public DotNetBuilder AddMockSDK( /// /// The added mock framework will only contain a deps.json. /// - private string AddFramework(string name, string version) + private static string AddFramework(string directory, string name, string version) { // ./shared// - create a mock of effectively the framework - string path = Path.Combine(_path, "shared", name, version); + string path = Path.Combine(directory, "shared", name, version); Directory.CreateDirectory(path); // ./shared///.deps.json - empty file diff --git a/src/installer/tests/TestUtils/GlobalJson.cs b/src/installer/tests/TestUtils/GlobalJson.cs index b309bd438e30db..74f65c747082e5 100644 --- a/src/installer/tests/TestUtils/GlobalJson.cs +++ b/src/installer/tests/TestUtils/GlobalJson.cs @@ -2,30 +2,44 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Microsoft.DotNet.TestUtils { public static class GlobalJson { + public class Sdk + { + [JsonPropertyName("version")] + public string Version { get; set; } + + [JsonPropertyName("rollForward")] + public string RollForward { get; set; } + + [JsonPropertyName("allowPrerelease")] + public bool? AllowPrerelease { get; set; } + + [JsonPropertyName("paths")] + public string[] Paths { get; set; } + + [JsonPropertyName("errorMessage")] + public string ErrorMessage { get; set; } + } + + public const string HostSdkPath = "$host$"; + public static string CreateEmpty(string directory) => Write(directory, "{}"); public static string CreateWithVersion(string directory, string version) - => Write(directory, @$"{{ ""sdk"": {{ ""version"": ""{version}"" }} }}"); + => Write(directory, new Sdk { Version = version }); public static string CreateWithVersionSettings(string directory, string version = null, string policy = null, bool? allowPrerelease = null) - => Write(directory, FormatVersionSettings(version, policy, allowPrerelease)); - - public static string FormatVersionSettings(string version = null, string policy = null, bool? allowPrerelease = null) - => $$""" - { - "sdk": { - "version": {{(version != null ? $"\"{version}\"" : "null")}}, - "rollForward": {{(policy != null ? $"\"{policy}\"" : "null")}}, - "allowPrerelease": {{(allowPrerelease.HasValue ? $"{allowPrerelease.Value.ToString().ToLowerInvariant()}" : "null")}} - } - } - """; + => Write(directory, new Sdk { Version = version, RollForward = policy, AllowPrerelease = allowPrerelease }); + + public static string FormatSettings(Sdk sdk) + => JsonSerializer.Serialize(new { sdk = sdk }, new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }); public static string Write(string directory, string contents) { @@ -34,5 +48,7 @@ public static string Write(string directory, string contents) return file; } + public static string Write(string directory, Sdk sdk) + => Write(directory, FormatSettings(sdk)); } } diff --git a/src/installer/tests/TestUtils/TestContext.cs b/src/installer/tests/TestUtils/TestContext.cs index 4c2f7994c98906..6f0afbff217d89 100644 --- a/src/installer/tests/TestUtils/TestContext.cs +++ b/src/installer/tests/TestUtils/TestContext.cs @@ -2,6 +2,7 @@ using System.Collections.Immutable; using System.IO; using Microsoft.DotNet.Cli.Build; +using Microsoft.DotNet.TestUtils; namespace Microsoft.DotNet.CoreSetup.Test { @@ -45,6 +46,10 @@ static TestContext() TestArtifactsPath = GetTestContextVariable("TEST_ARTIFACTS"); Directory.CreateDirectory(TestArtifactsPath); + // Create an empty global.json, so running tests from test artifacts is not affected + // by any global.json in parent directiers + GlobalJson.CreateEmpty(TestArtifactsPath); + BuiltDotNet = new DotNetCli(Path.Combine(TestAssetsOutput, "sharedFrameworkPublish")); } diff --git a/src/installer/tests/TestUtils/TestUtils.csproj b/src/installer/tests/TestUtils/TestUtils.csproj index 2db347c9361631..bc3968f7de2a13 100644 --- a/src/installer/tests/TestUtils/TestUtils.csproj +++ b/src/installer/tests/TestUtils/TestUtils.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index ff72852caa75c6..b77702a6d4d9a0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -120,9 +120,9 @@ internal static X500DistinguishedName LoadX500Name(IntPtr namePtr) return new X500DistinguishedName(buf); } - internal static byte[] GetX509PublicKeyParameterBytes(SafeX509Handle x509) + internal static byte[]? GetX509PublicKeyParameterBytes(SafeX509Handle x509) { - return GetDynamicBuffer(GetX509PublicKeyParameterBytes, x509); + return GetNullableDynamicBuffer(GetX509PublicKeyParameterBytes, x509); } internal static void X509StoreSetVerifyTime(SafeX509StoreHandle ctx, DateTime verifyTime) @@ -168,6 +168,34 @@ internal static byte[] GetDynamicBuffer(NegativeSizeReadMethod return bytes; } + internal static byte[]? GetNullableDynamicBuffer(NegativeSizeReadMethod method, THandle handle) + { + const int MissingData = 2; + const int DataCopied = 1; + int returnValue = method(handle, null, 0); + + if (returnValue == MissingData) + { + return null; + } + + if (returnValue > 0) + { + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + + byte[] bytes = new byte[-returnValue]; + + int ret = method(handle, bytes, bytes.Length); + + if (ret != DataCopied) + { + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + + return bytes; + } + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetMemoryUse")] private static partial void GetMemoryUse(ref long memoryUse, ref long allocationCount); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs index 923930fd6ef42a..8b299a12219e6e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs @@ -172,7 +172,7 @@ internal static partial bool DsaKeyCreateByExplicitParameters( /// /// Return the maximum value in the array; assumes non-negative values. /// - private static int GetMax(int[] values) + private static int GetMax(ReadOnlySpan values) { int max = 0; diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Kem.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Kem.cs new file mode 100644 index 00000000000000..be1756075bde53 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Kem.cs @@ -0,0 +1,169 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Crypto + { + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemDecapsulate")] + private static partial int CryptoNative_EvpKemDecapsulate( + SafeEvpPKeyHandle kem, + ReadOnlySpan ciphertext, + int ciphertextLength, + Span sharedSecret, + int sharedSecretLength); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemGeneratePkey", StringMarshalling = StringMarshalling.Utf8)] + private static partial SafeEvpPKeyHandle CryptoNative_EvpKemGeneratePkey( + string kemName, + ReadOnlySpan seed, + int seedLength); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemExportPrivateSeed")] + private static partial int CryptoNative_EvpKemExportPrivateSeed( + SafeEvpPKeyHandle key, + Span destination, + int destinationLength); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemExportDecapsulationKey")] + private static partial int CryptoNative_EvpKemExportDecapsulationKey( + SafeEvpPKeyHandle key, + Span destination, + int destinationLength); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemExportEncapsulationKey")] + private static partial int CryptoNative_EvpKemExportEncapsulationKey( + SafeEvpPKeyHandle key, + Span destination, + int destinationLength); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemEncapsulate")] + private static partial int CryptoNative_EvpKemEncapsulate( + SafeEvpPKeyHandle kem, + Span ciphertext, + int ciphertextLength, + Span sharedSecret, + int sharedSecretLength); + + internal static SafeEvpPKeyHandle EvpKemGeneratePkey(string kemName) + { + SafeEvpPKeyHandle handle = CryptoNative_EvpKemGeneratePkey(kemName, ReadOnlySpan.Empty, 0); + + if (handle.IsInvalid) + { + Exception ex = CreateOpenSslCryptographicException(); + handle.Dispose(); + throw ex; + } + + return handle; + } + + internal static SafeEvpPKeyHandle EvpKemGeneratePkey(string kemName, ReadOnlySpan seed) + { + if (seed.IsEmpty) + { + Debug.Fail("Generating a key with a seed requires a non-empty seed."); + throw new CryptographicException(); + } + + SafeEvpPKeyHandle handle = CryptoNative_EvpKemGeneratePkey(kemName, seed, seed.Length); + + if (handle.IsInvalid) + { + Exception ex = CreateOpenSslCryptographicException(); + handle.Dispose(); + throw ex; + } + + return handle; + } + + internal static void EvpKemDecapsulate(SafeEvpPKeyHandle key, ReadOnlySpan ciphertext, Span sharedSecret) + { + const int Success = 1; + const int Fail = 0; + + int ret = CryptoNative_EvpKemDecapsulate(key, ciphertext, ciphertext.Length, sharedSecret, sharedSecret.Length); + + switch (ret) + { + case Success: + return; + case Fail: + sharedSecret.Clear(); + throw CreateOpenSslCryptographicException(); + default: + sharedSecret.Clear(); + Debug.Fail($"Unexpected return value {ret} from {nameof(CryptoNative_EvpKemDecapsulate)}."); + throw new CryptographicException(); + } + } + + internal static void EvpKemExportPrivateSeed(SafeEvpPKeyHandle key, Span destination) => + ExportKeyContents(key, destination, CryptoNative_EvpKemExportPrivateSeed); + + internal static void EvpKemExportDecapsulationKey(SafeEvpPKeyHandle key, Span destination) => + ExportKeyContents(key, destination, CryptoNative_EvpKemExportDecapsulationKey); + + internal static void EvpKemExportEncapsulationKey(SafeEvpPKeyHandle key, Span destination) => + ExportKeyContents(key, destination, CryptoNative_EvpKemExportEncapsulationKey); + + internal static void EvpKemEncapsulate(SafeEvpPKeyHandle key, Span ciphertext, Span sharedSecret) + { + const int Success = 1; + const int Fail = 0; + + int ret = CryptoNative_EvpKemEncapsulate(key, ciphertext, ciphertext.Length, sharedSecret, sharedSecret.Length); + + switch (ret) + { + case Success: + return; + case Fail: + ciphertext.Clear(); + sharedSecret.Clear(); + throw CreateOpenSslCryptographicException(); + default: + ciphertext.Clear(); + sharedSecret.Clear(); + Debug.Fail($"Unexpected return value {ret} from {nameof(CryptoNative_EvpKemEncapsulate)}."); + throw new CryptographicException(); + } + } + + private static void ExportKeyContents( + SafeEvpPKeyHandle key, + Span destination, + Func, int, int> action) + { + const int Success = 1; + const int Fail = 0; + const int NotRetrievable = -1; + + int ret = action(key, destination, destination.Length); + + switch (ret) + { + case Success: + return; + case NotRetrievable: + destination.Clear(); + throw new CryptographicException(SR.Cryptography_NotRetrievable); + case Fail: + destination.Clear(); + throw CreateOpenSslCryptographicException(); + default: + destination.Clear(); + Debug.Fail($"Unexpected return value {ret}."); + throw new CryptographicException(); + } + } + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.KemAlgs.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.KemAlgs.cs new file mode 100644 index 00000000000000..5fb770ddea82e4 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.KemAlgs.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Crypto + { + internal static partial class EvpKemAlgs + { + internal static string? MlKem512 { get; } + internal static string? MlKem768 { get; } + internal static string? MlKem1024 { get; } + + static EvpKemAlgs() + { + CryptoInitializer.Initialize(); + + // Do not use property initializers for these because we need to ensure CryptoInitializer.Initialize + // is called first. Property initializers happen before cctors, so instead set the property after the + // initializer is run. + MlKem512 = EvpKemAvailable(MLKemAlgorithm.MLKem512.Name); + MlKem768 = EvpKemAvailable(MLKemAlgorithm.MLKem768.Name); + MlKem1024 = EvpKemAvailable(MLKemAlgorithm.MLKem1024.Name); + } + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpKemAvailable", StringMarshalling = StringMarshalling.Utf8)] + private static partial int CryptoNative_EvpKemAvailable(string algorithm); + + private static string? EvpKemAvailable(string algorithm) + { + const int Available = 1; + const int NotAvailable = 0; + + int ret = CryptoNative_EvpKemAvailable(algorithm); + return ret switch + { + Available => algorithm, + NotAvailable => null, + int other => throw Fail(other), + }; + + static CryptographicException Fail(int result) + { + Debug.Fail($"Unexpected result {result} from {nameof(CryptoNative_EvpKemAvailable)}"); + return new CryptographicException(); + } + } + } + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs index 70f5a2fcc34264..b5cf5295e47872 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs @@ -96,6 +96,34 @@ internal static SafeEcKeyHandle EcKeyCreateByExplicitCurve(ECCurve curve) return key; } + [LibraryImport(Libraries.CryptoNative)] + private static partial int CryptoNative_EvpPKeyGetEcGroupNid(SafeEvpPKeyHandle pkey, out int nid); + + internal static bool EvpPKeyHasCurveName(SafeEvpPKeyHandle pkey) + { + int rc = CryptoNative_EvpPKeyGetEcGroupNid(pkey, out int nidCurveName); + if (rc == 1) + { + // Key is invalid or doesn't have a curve + return (nidCurveName != Interop.Crypto.NID_undef); + } + + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + + /// + /// Returns the OID as a string or null if curve is not named. + /// + internal static string? EvpPKeyGetCurveName(SafeEvpPKeyHandle pkey) + { + int rc = CryptoNative_EvpPKeyGetEcGroupNid(pkey, out int nidCurveName); + if (rc == 1) + { + return nidCurveName != Interop.Crypto.NID_undef ? CurveNidToOidValue(nidCurveName) : null; + } + + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } [LibraryImport(Libraries.CryptoNative)] private static partial int CryptoNative_GetECKeyParameters( @@ -105,6 +133,14 @@ private static partial int CryptoNative_GetECKeyParameters( out SafeBignumHandle qy_bn, out int y_cb, out IntPtr d_bn_not_owned, out int d_cb); + [LibraryImport(Libraries.CryptoNative)] + private static partial int CryptoNative_EvpPKeyGetEcKeyParameters( + SafeEvpPKeyHandle key, + [MarshalAs(UnmanagedType.Bool)] bool includePrivate, + out SafeBignumHandle qx_bn, out int x_cb, + out SafeBignumHandle qy_bn, out int y_cb, + out SafeBignumHandle d_bn, out int d_cb); + internal static ECParameters GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate) @@ -112,7 +148,6 @@ internal static ECParameters GetECKeyParameters( SafeBignumHandle qx_bn, qy_bn, d_bn; IntPtr d_bn_not_owned; int qx_cb, qy_cb, d_cb; - ECParameters parameters = default; bool refAdded = false; try @@ -142,20 +177,11 @@ internal static ECParameters GetECKeyParameters( // Match Windows semantics where qx, qy, and d have same length int keySizeBits = EcKeyGetSize(key); int expectedSize = (keySizeBits + 7) / 8; - int cbKey = GetMax(qx_cb, qy_cb, d_cb); - - Debug.Assert( - cbKey <= expectedSize, - $"Expected output size was {expectedSize}, which a parameter exceeded. qx={qx_cb}, qy={qy_cb}, d={d_cb}"); - - cbKey = GetMax(cbKey, expectedSize); - - parameters.Q = new ECPoint - { - X = Crypto.ExtractBignum(qx_bn, cbKey), - Y = Crypto.ExtractBignum(qy_bn, cbKey) - }; - parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey); + return GetEcParameters( + expectedSize, + qx_bn, qx_cb, + qy_bn, qy_cb, + d_bn, d_cb); } } } @@ -164,6 +190,69 @@ internal static ECParameters GetECKeyParameters( if (refAdded) key.DangerousRelease(); } + } + + internal static ECParameters EvpPKeyGetEcKeyParameters( + SafeEvpPKeyHandle key, + bool includePrivate) + { + SafeBignumHandle qx_bn, qy_bn, d_bn; + int qx_cb, qy_cb, d_cb; + + int rc = CryptoNative_EvpPKeyGetEcKeyParameters( + key, + includePrivate, + out qx_bn, out qx_cb, + out qy_bn, out qy_cb, + out d_bn, out d_cb); + + using (qx_bn) + using (qy_bn) + using (d_bn) + { + if (rc == -1) + { + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + } + else if (rc != 1) + { + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + + // Match Windows semantics where qx, qy, and d have same length + int expectedSize = GetEvpPKeySizeBytes(key); + return GetEcParameters( + expectedSize, + qx_bn, qx_cb, + qy_bn, qy_cb, + d_bn, d_cb); + } + } + + private static ECParameters GetEcParameters( + int expectedKeySizeBytes, + SafeBignumHandle qx_bn, int qx_cb, + SafeBignumHandle qy_bn, int qy_cb, + SafeBignumHandle d_bn, int d_cb + ) + { + ECParameters parameters = default; + + // Match Windows semantics where qx, qy, and d have same length + int cbKey = GetMax(qx_cb, qy_cb, d_cb); + + Debug.Assert( + cbKey <= expectedKeySizeBytes, + $"Expected output size was {expectedKeySizeBytes}, which a parameter exceeded. qx={qx_cb}, qy={qy_cb}, d={d_cb}"); + + cbKey = GetMax(cbKey, expectedKeySizeBytes); + + parameters.Q = new ECPoint + { + X = Crypto.ExtractBignum(qx_bn, cbKey), + Y = Crypto.ExtractBignum(qy_bn, cbKey) + }; + parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey); return parameters; } @@ -185,6 +274,23 @@ private static partial int CryptoNative_GetECCurveParameters( out SafeBignumHandle cofactor, out int cofactor_cb, out SafeBignumHandle seed, out int seed_cb); + [LibraryImport(Libraries.CryptoNative)] + private static unsafe partial int CryptoNative_EvpPKeyGetEcCurveParameters( + SafeEvpPKeyHandle key, + [MarshalAs(UnmanagedType.Bool)] bool includePrivate, + out ECCurve.ECCurveType curveType, + out SafeBignumHandle qx, out int x_cb, + out SafeBignumHandle qy, out int y_cb, + out SafeBignumHandle d, out int d_cb, + out SafeBignumHandle p, out int P_cb, + out SafeBignumHandle a, out int A_cb, + out SafeBignumHandle b, out int B_cb, + out SafeBignumHandle gx, out int Gx_cb, + out SafeBignumHandle gy, out int Gy_cb, + out SafeBignumHandle order, out int order_cb, + out SafeBignumHandle cofactor, out int cofactor_cb, + out SafeBignumHandle seed, out int seed_cb); + internal static ECParameters GetECCurveParameters( SafeEcKeyHandle key, bool includePrivate) @@ -236,60 +342,19 @@ internal static ECParameters GetECCurveParameters( using (var d_h = new SafeBignumHandle(d_bn_not_owned, false)) { - int cbFieldLength; - int pFieldLength; - if (curveType == ECCurve.ECCurveType.Characteristic2) - { - // Match Windows semantics where a,b,gx,gy,qx,qy have same length - // Treat length of m separately as it is not tied to other fields for Char2 (Char2 not supported by Windows) - cbFieldLength = GetMax(new[] { a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); - pFieldLength = p_cb; - } - else - { - // Match Windows semantics where p,a,b,gx,gy,qx,qy have same length - cbFieldLength = GetMax(new[] { p_cb, a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); - pFieldLength = cbFieldLength; - } - - // Match Windows semantics where order and d have same length - int cbSubgroupOrder = GetMax(order_cb, d_cb); - - // Copy values to ECParameters - ECParameters parameters = default; - parameters.Q = new ECPoint - { - X = Crypto.ExtractBignum(qx_bn, cbFieldLength), - Y = Crypto.ExtractBignum(qy_bn, cbFieldLength) - }; - parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_h, cbSubgroupOrder); - - var curve = parameters.Curve; - curve.CurveType = curveType; - curve.A = Crypto.ExtractBignum(a_bn, cbFieldLength)!; - curve.B = Crypto.ExtractBignum(b_bn, cbFieldLength)!; - curve.G = new ECPoint - { - X = Crypto.ExtractBignum(gx_bn, cbFieldLength), - Y = Crypto.ExtractBignum(gy_bn, cbFieldLength) - }; - curve.Order = Crypto.ExtractBignum(order_bn, cbSubgroupOrder)!; - - if (curveType == ECCurve.ECCurveType.Characteristic2) - { - curve.Polynomial = Crypto.ExtractBignum(p_bn, pFieldLength)!; - } - else - { - curve.Prime = Crypto.ExtractBignum(p_bn, pFieldLength)!; - } - - // Optional parameters - curve.Cofactor = cofactor_cb == 0 ? null : Crypto.ExtractBignum(cofactor_bn, cofactor_cb); - curve.Seed = seed_cb == 0 ? null : Crypto.ExtractBignum(seed_bn, seed_cb); - - parameters.Curve = curve; - return parameters; + return GetEcCurveParameters( + curveType, + qx_bn, qx_cb, + qy_bn, qy_cb, + d_h, d_cb, + p_bn, p_cb, + a_bn, a_cb, + b_bn, b_cb, + gx_bn, gx_cb, + gy_bn, gy_cb, + order_bn, order_cb, + cofactor_bn, cofactor_cb, + seed_bn, seed_cb); } } } @@ -299,5 +364,136 @@ internal static ECParameters GetECCurveParameters( key.DangerousRelease(); } } + + internal static unsafe ECParameters EvpPKeyGetEcCurveParameters( + SafeEvpPKeyHandle key, + bool includePrivate) + { + ECCurve.ECCurveType curveType; + SafeBignumHandle qx_bn, qy_bn, d_bn, p_bn, a_bn, b_bn, gx_bn, gy_bn, order_bn, cofactor_bn, seed_bn; + int qx_cb, qy_cb, p_cb, a_cb, b_cb, gx_cb, gy_cb, order_cb, cofactor_cb, seed_cb, d_cb; + + int rc = CryptoNative_EvpPKeyGetEcCurveParameters( + key, + includePrivate, + out curveType, + out qx_bn, out qx_cb, + out qy_bn, out qy_cb, + out d_bn, out d_cb, + out p_bn, out p_cb, + out a_bn, out a_cb, + out b_bn, out b_cb, + out gx_bn, out gx_cb, + out gy_bn, out gy_cb, + out order_bn, out order_cb, + out cofactor_bn, out cofactor_cb, + out seed_bn, out seed_cb); + + using (qx_bn) + using (qy_bn) + using (d_bn) + using (p_bn) + using (a_bn) + using (b_bn) + using (gx_bn) + using (gy_bn) + using (order_bn) + using (cofactor_bn) + using (seed_bn) + { + if (rc == -1) + { + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + } + else if (rc != 1) + { + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + + return GetEcCurveParameters( + curveType, + qx_bn, qx_cb, + qy_bn, qy_cb, + d_bn, d_cb, + p_bn, p_cb, + a_bn, a_cb, + b_bn, b_cb, + gx_bn, gx_cb, + gy_bn, gy_cb, + order_bn, order_cb, + cofactor_bn, cofactor_cb, + seed_bn, seed_cb); + } + } + + private static ECParameters GetEcCurveParameters( + ECCurve.ECCurveType curveType, + SafeBignumHandle qx_bn, int qx_cb, + SafeBignumHandle qy_bn, int qy_cb, + SafeBignumHandle d_bn, int d_cb, + SafeBignumHandle p_bn, int p_cb, + SafeBignumHandle a_bn, int a_cb, + SafeBignumHandle b_bn, int b_cb, + SafeBignumHandle gx_bn, int gx_cb, + SafeBignumHandle gy_bn, int gy_cb, + SafeBignumHandle order_bn, int order_cb, + SafeBignumHandle cofactor_bn, int cofactor_cb, + SafeBignumHandle seed_bn, int seed_cb) + { + int cbFieldLength; + int pFieldLength; + if (curveType == ECCurve.ECCurveType.Characteristic2) + { + // Match Windows semantics where a,b,gx,gy,qx,qy have same length + // Treat length of m separately as it is not tied to other fields for Char2 (Char2 not supported by Windows) + cbFieldLength = GetMax([ a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb ]); + pFieldLength = p_cb; + } + else + { + // Match Windows semantics where p,a,b,gx,gy,qx,qy have same length + cbFieldLength = GetMax([ p_cb, a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb ]); + pFieldLength = cbFieldLength; + } + + // Match Windows semantics where order and d have same length + int cbSubgroupOrder = GetMax(order_cb, d_cb); + + // Copy values to ECParameters + ECParameters parameters = default; + parameters.Q = new ECPoint + { + X = Crypto.ExtractBignum(qx_bn, cbFieldLength), + Y = Crypto.ExtractBignum(qy_bn, cbFieldLength) + }; + parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbSubgroupOrder); + + ECCurve curve = parameters.Curve; + curve.CurveType = curveType; + curve.A = Crypto.ExtractBignum(a_bn, cbFieldLength)!; + curve.B = Crypto.ExtractBignum(b_bn, cbFieldLength)!; + curve.G = new ECPoint + { + X = Crypto.ExtractBignum(gx_bn, cbFieldLength), + Y = Crypto.ExtractBignum(gy_bn, cbFieldLength) + }; + curve.Order = Crypto.ExtractBignum(order_bn, cbSubgroupOrder)!; + + if (curveType == ECCurve.ECCurveType.Characteristic2) + { + curve.Polynomial = Crypto.ExtractBignum(p_bn, pFieldLength)!; + } + else + { + curve.Prime = Crypto.ExtractBignum(p_bn, pFieldLength)!; + } + + // Optional parameters + curve.Cofactor = cofactor_cb == 0 ? null : Crypto.ExtractBignum(cofactor_bn, cofactor_cb); + curve.Seed = seed_cb == 0 ? null : Crypto.ExtractBignum(seed_bn, seed_cb); + + parameters.Curve = curve; + return parameters; + } } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs index 05be5f75837258..5e92c58e2ecaba 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs @@ -44,6 +44,7 @@ internal static int EcKeyGetSize(SafeEcKeyHandle key) { return keySize; } + throw Interop.Crypto.CreateOpenSslCryptographicException(); } @@ -52,34 +53,41 @@ internal static int EcKeyGetSize(SafeEcKeyHandle key) internal static string EcKeyGetCurveName(SafeEcKeyHandle key) { - int nidCurveName; - int rc = CryptoNative_EcKeyGetCurveName(key, out nidCurveName); + int rc = CryptoNative_EcKeyGetCurveName(key, out int nidCurveName); if (rc == 1) { - if (nidCurveName == Interop.Crypto.NID_undef) - { - Debug.Fail("Key is invalid or doesn't have a curve"); - return string.Empty; - } - - IntPtr objCurveName = Interop.Crypto.ObjNid2Obj(nidCurveName); - if (objCurveName != IntPtr.Zero) - { - return Interop.Crypto.GetOidValue(objCurveName); - } + return CurveNidToOidValue(nidCurveName); } + throw Interop.Crypto.CreateOpenSslCryptographicException(); } internal static bool EcKeyHasCurveName(SafeEcKeyHandle key) { - int nidCurveName; - int rc = CryptoNative_EcKeyGetCurveName(key, out nidCurveName); + int rc = CryptoNative_EcKeyGetCurveName(key, out int nidCurveName); if (rc == 1) { // Key is invalid or doesn't have a curve return (nidCurveName != Interop.Crypto.NID_undef); } + + throw Interop.Crypto.CreateOpenSslCryptographicException(); + } + + internal static string CurveNidToOidValue(int nidCurveName) + { + if (nidCurveName == Interop.Crypto.NID_undef) + { + Debug.Fail("Key is invalid or doesn't have a curve"); + return string.Empty; + } + + IntPtr objCurveName = Interop.Crypto.ObjNid2Obj(nidCurveName); + if (objCurveName != IntPtr.Zero) + { + return Interop.Crypto.GetOidValue(objCurveName); + } + throw Interop.Crypto.CreateOpenSslCryptographicException(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs index f5129fe32d643a..559ede03ae1072 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs @@ -19,6 +19,27 @@ internal static partial class Crypto [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeyBits")] internal static partial int EvpPKeyBits(SafeEvpPKeyHandle pkey); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeyFromData", StringMarshalling = StringMarshalling.Utf8)] + private static partial SafeEvpPKeyHandle CryptoNative_EvpPKeyFromData( + string algorithmName, + ReadOnlySpan key, + int keyLength, + [MarshalAs(UnmanagedType.Bool)] bool privateKey); + + internal static SafeEvpPKeyHandle EvpPKeyFromData(string algorithmName, ReadOnlySpan key, bool privateKey) + { + SafeEvpPKeyHandle handle = CryptoNative_EvpPKeyFromData(algorithmName, key, key.Length, privateKey); + + if (handle.IsInvalid) + { + Exception ex = CreateOpenSslCryptographicException(); + handle.Dispose(); + throw ex; + } + + return handle; + } + internal static int GetEvpPKeySizeBytes(SafeEvpPKeyHandle pkey) { // EVP_PKEY_size returns the maximum suitable size for the output buffers for almost all operations that can be done with the key. diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index f3ff16df4c564d..65c0d37e3d5a30 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -123,7 +123,14 @@ internal static unsafe ReadOnlySpan SslGetAlpnSelected(SafeSslHandle ssl) internal static partial IntPtr SslGetCertificate(IntPtr ssl); [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerCertChain")] - internal static partial SafeSharedX509StackHandle SslGetPeerCertChain(SafeSslHandle ssl); + private static partial SafeSharedX509StackHandle SslGetPeerCertChain_private(SafeSslHandle ssl); + + internal static SafeSharedX509StackHandle SslGetPeerCertChain(SafeSslHandle ssl) + { + return SafeInteriorHandle.OpenInteriorHandle( + SslGetPeerCertChain_private, + ssl); + } [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerFinished")] internal static partial int SslGetPeerFinished(SafeSslHandle ssl, IntPtr buf, int count); diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AccessControlLists.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AccessControlLists.cs new file mode 100644 index 00000000000000..0e799856afdb87 --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AccessControlLists.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Advapi32 + { + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool InitializeAcl(nint pAcl, int nAclLength, int dwAclRevision); + + [LibraryImport(Libraries.Advapi32, EntryPoint = "SetEntriesInAclW", SetLastError = true)] + internal static unsafe partial int SetEntriesInAcl( + int cCountOfExplicitEntries, + EXPLICIT_ACCESS* pListOfExplicitEntries, + nint OldAcl, + out SafeLocalAllocHandle NewAcl); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static unsafe partial bool GetAce(ACL* pAcl, int dwAceIndex, out ACE* pAce); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool AddMandatoryAce( + nint pAcl, + int dwAceRevision, + int AceFlags, + int MandatoryPolicy, + nint pLabelSid); + + internal const int ACL_REVISION = 2; + + // Values for ACE_HEADER.AceType + internal const byte ACCESS_ALLOWED_ACE_TYPE = 0x0; + + // Values for MandatoryPolicy in AddMandatoryAce() + internal const int SYSTEM_MANDATORY_LABEL_NO_WRITE_UP = 0x1; + internal const int SYSTEM_MANDATORY_LABEL_NO_READ_UP = 0x2; + + // Values for the RID portion of a mandatory label SID, which indicates the integrity level + internal const uint SECURITY_MANDATORY_MEDIUM_RID = 0x2000; + + [StructLayout(LayoutKind.Sequential)] + internal struct ACL + { + public byte AclRevision; + public byte Sbz1; + public ushort AclSize; + public ushort AceCount; + public ushort Sbz2; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ACE + { + public ACE_HEADER Header; + public uint Mask; + public uint SidStart; + + public static int SizeOfSidPortionInAce => sizeof(uint); + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ACE_HEADER + { + public byte AceType; + public byte AceFlags; + public ushort AceSize; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct EXPLICIT_ACCESS + { + public int grfAccessPermissions; + public ACCESS_MODE grfAccessMode; + public int grfInheritance; + public TRUSTEE Trustee; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct TRUSTEE + { + public nint pMultipleTrustee; + public int MultipleTrusteeOperation; + public TRUSTEE_FORM TrusteeForm; + public TRUSTEE_TYPE TrusteeType; + public nint ptstrName; + } + + internal enum ACCESS_MODE + { + NOT_USED_ACCESS, + GRANT_ACCESS, + SET_ACCESS, + DENY_ACCESS, + REVOKE_ACCESS, + SET_AUDIT_SUCCESS, + SET_AUDIT_FAILURE + } + + // Constants for EXPLICIT_ACCESS.grfInheritance + internal const int EXPLICIT_ACCESS_NO_INHERITANCE = 0; + + internal enum TRUSTEE_FORM + { + TRUSTEE_IS_SID, + TRUSTEE_IS_NAME, + TRUSTEE_BAD_FORM, + TRUSTEE_IS_OBJECTS_AND_SID, + TRUSTEE_IS_OBJECTS_AND_NAME + } + + internal enum TRUSTEE_TYPE + { + TRUSTEE_IS_UNKNOWN, + TRUSTEE_IS_USER, + TRUSTEE_IS_GROUP, + TRUSTEE_IS_DOMAIN, + TRUSTEE_IS_ALIAS, + TRUSTEE_IS_WELL_KNOWN_GROUP, + TRUSTEE_IS_DELETED, + TRUSTEE_IS_INVALID, + TRUSTEE_IS_COMPUTER + } + } +} diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs index aba754cd2a5e49..9cec916f5a1032 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs @@ -8,11 +8,29 @@ internal static partial class Interop { internal static partial class Advapi32 { - [LibraryImport(Interop.Libraries.Advapi32, EntryPoint = "CreateWellKnownSid", SetLastError = true)] + private const int SID_MAX_SUB_AUTHORITIES = 15; + internal const int SECURITY_MAX_SID_SIZE = + 12 /* sizeof(SID) */ - 4 /* sizeof(DWORD) */ + SID_MAX_SUB_AUTHORITIES * 4 /* sizeof(DWORD) */; + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] internal static partial int CreateWellKnownSid( int sidType, byte[]? domainSid, byte[] resultSid, ref uint resultSidLength); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool CreateWellKnownSid( + int sidType, + nint domainSid, + nint resultSid, + ref uint resultSidLength); + + internal enum WELL_KNOWN_SID_TYPE + { + WinBuiltinAdministratorsSid = 26, + WinMediumLabelSid = 67 + } } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EqualSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EqualSid.cs new file mode 100644 index 00000000000000..34e996f704d7d4 --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EqualSid.cs @@ -0,0 +1,15 @@ +// 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.InteropServices; + +internal static partial class Interop +{ + internal static partial class Advapi32 + { + [LibraryImport(Interop.Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool EqualSid(nint pSid1, nint pSid2); + } +} diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs index 1f4b8cdea76cc5..b3d5589eebda23 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs @@ -18,5 +18,28 @@ internal static unsafe partial uint GetSecurityInfoByHandle( IntPtr* dacl, IntPtr* sacl, IntPtr* securityDescriptor); + + // Values for objectType + internal enum SE_OBJECT_TYPE + { + SE_UNKNOWN_OBJECT_TYPE, + SE_FILE_OBJECT, + SE_SERVICE, + SE_PRINTER, + SE_REGISTRY_KEY, + SE_LMSHARE, + SE_KERNEL_OBJECT, + SE_WINDOW_OBJECT, + SE_DS_OBJECT, + SE_DS_OBJECT_ALL, + SE_PROVIDER_DEFINED_OBJECT, + SE_WMIGUID_OBJECT, + SE_REGISTRY_WOW64_32KEY, + SE_REGISTRY_WOW64_64KEY + } + + // Values for securityInformation + internal const uint OWNER_SECURITY_INFORMATION = 0x1; + internal const uint DACL_SECURITY_INFORMATION = 0x4; } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs index bae76b5a6efe91..f44153841a67d3 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs @@ -1,41 +1,19 @@ // 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.InteropServices; -using System.Security.Principal; using Microsoft.Win32.SafeHandles; internal static partial class Interop { internal static partial class Advapi32 { - [LibraryImport(Interop.Libraries.Advapi32, SetLastError = true)] + [LibraryImport(Libraries.Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool OpenThreadToken( - IntPtr ThreadHandle, - TokenAccessLevels dwDesiredAccess, - [MarshalAs(UnmanagedType.Bool)] bool bOpenAsSelf, - out SafeAccessTokenHandle phThreadToken); - - internal static bool OpenThreadToken(TokenAccessLevels desiredAccess, WinSecurityContext openAs, out SafeAccessTokenHandle tokenHandle) - { - bool openAsSelf = true; - if (openAs == WinSecurityContext.Thread) - openAsSelf = false; - - if (OpenThreadToken(Kernel32.GetCurrentThread(), desiredAccess, openAsSelf, out tokenHandle)) - return true; - - if (openAs == WinSecurityContext.Both) - { - openAsSelf = false; - tokenHandle.Dispose(); - if (OpenThreadToken(Kernel32.GetCurrentThread(), desiredAccess, openAsSelf, out tokenHandle)) - return true; - } - - return false; - } + internal static partial bool OpenThreadToken( + nint ThreadHandle, + int DesiredAccess, + [MarshalAs(UnmanagedType.Bool)] bool OpenAsSelf, + out SafeTokenHandle TokenHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeAccessTokenHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeAccessTokenHandle.cs new file mode 100644 index 00000000000000..bae76b5a6efe91 --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeAccessTokenHandle.cs @@ -0,0 +1,41 @@ +// 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.InteropServices; +using System.Security.Principal; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Advapi32 + { + [LibraryImport(Interop.Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool OpenThreadToken( + IntPtr ThreadHandle, + TokenAccessLevels dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)] bool bOpenAsSelf, + out SafeAccessTokenHandle phThreadToken); + + internal static bool OpenThreadToken(TokenAccessLevels desiredAccess, WinSecurityContext openAs, out SafeAccessTokenHandle tokenHandle) + { + bool openAsSelf = true; + if (openAs == WinSecurityContext.Thread) + openAsSelf = false; + + if (OpenThreadToken(Kernel32.GetCurrentThread(), desiredAccess, openAsSelf, out tokenHandle)) + return true; + + if (openAs == WinSecurityContext.Both) + { + openAsSelf = false; + tokenHandle.Dispose(); + if (OpenThreadToken(Kernel32.GetCurrentThread(), desiredAccess, openAsSelf, out tokenHandle)) + return true; + } + + return false; + } + } +} diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SecurityDescriptors.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SecurityDescriptors.cs new file mode 100644 index 00000000000000..fef71470ee073a --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SecurityDescriptors.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Advapi32 + { + internal const int SECURITY_DESCRIPTOR_MIN_LENGTH = // AlignUp(4, sizeof(nint)) + 4 * sizeof(nint) +#if TARGET_64BIT + 40; +#else + 20; +#endif + + internal const int SECURITY_DESCRIPTOR_REVISION = 1; + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool InitializeSecurityDescriptor(nint pSecurityDescriptor, int dwRevision); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetSecurityDescriptorOwner( + nint pSecurityDescriptor, + nint pOwner, + [MarshalAs(UnmanagedType.Bool)] bool bOwnerDefaulted); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetSecurityDescriptorGroup( + nint pSecurityDescriptor, + nint pGroup, + [MarshalAs(UnmanagedType.Bool)] bool bGroupDefaulted); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetSecurityDescriptorDacl( + nint pSecurityDescriptor, + [MarshalAs(UnmanagedType.Bool)] bool bDaclPresent, + nint pDacl, + [MarshalAs(UnmanagedType.Bool)] bool bDaclDefaulted); + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetSecurityDescriptorSacl( + nint pSecurityDescriptor, + [MarshalAs(UnmanagedType.Bool)] bool bSaclPresent, + nint pSacl, + [MarshalAs(UnmanagedType.Bool)] bool bSaclDefaulted); + } +} diff --git a/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs b/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs index 237c5c214b0276..61dea5abb10c06 100644 --- a/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs +++ b/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs @@ -38,6 +38,7 @@ internal static partial class Errors internal const int ERROR_INVALID_NAME = 0x7B; internal const int ERROR_INVALID_LEVEL = 0x7C; internal const int ERROR_MOD_NOT_FOUND = 0x7E; + internal const int ERROR_PROC_NOT_FOUND = 0x7F; internal const int ERROR_NEGATIVE_SEEK = 0x83; internal const int ERROR_DIR_NOT_EMPTY = 0x91; internal const int ERROR_BAD_PATHNAME = 0xA1; diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Constants.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Constants.cs index 9a376d2f101ad1..7262faf453a53c 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Constants.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Constants.cs @@ -10,6 +10,10 @@ internal static partial class Kernel32 internal const int WAIT_ABANDONED = 0x00000080; internal const int MAXIMUM_ALLOWED = 0x02000000; + internal const int STANDARD_RIGHTS_REQUIRED = 0x000F0000; + internal const int READ_CONTROL = 0x00020000; + internal const int WRITE_DAC = 0x00040000; + internal const int WRITE_OWNER = 0x00080000; internal const int SYNCHRONIZE = 0x00100000; internal const int MUTEX_MODIFY_STATE = 0x00000001; internal const int SEMAPHORE_MODIFY_STATE = 0x00000002; diff --git a/src/libraries/Common/src/System/HexConverter.cs b/src/libraries/Common/src/System/HexConverter.cs index 0339a186f7c55d..2ce0f59691fd0b 100644 --- a/src/libraries/Common/src/System/HexConverter.cs +++ b/src/libraries/Common/src/System/HexConverter.cs @@ -104,8 +104,8 @@ internal static (Vector128, Vector128) AsciiToHexVector128(Vector128 Vector128 lowNibbles = Vector128.UnpackLow(shiftedSrc, src); Vector128 highNibbles = Vector128.UnpackHigh(shiftedSrc, src); - return (Vector128.ShuffleUnsafe(hexMap, lowNibbles & Vector128.Create((byte)0xF)), - Vector128.ShuffleUnsafe(hexMap, highNibbles & Vector128.Create((byte)0xF))); + return (Vector128.ShuffleNative(hexMap, lowNibbles & Vector128.Create((byte)0xF)), + Vector128.ShuffleNative(hexMap, highNibbles & Vector128.Create((byte)0xF))); } [CompExactlyDependsOn(typeof(Ssse3))] diff --git a/src/libraries/Common/src/System/Net/CookieComparer.cs b/src/libraries/Common/src/System/Net/CookieComparer.cs index a2980c5c8746ec..5a1e06f292362b 100644 --- a/src/libraries/Common/src/System/Net/CookieComparer.cs +++ b/src/libraries/Common/src/System/Net/CookieComparer.cs @@ -23,11 +23,8 @@ internal static bool Equals(Cookie left, Cookie right) } internal static bool EqualDomains(ReadOnlySpan left, ReadOnlySpan right) - { - if (left.StartsWith('.')) left = left.Slice(1); - if (right.StartsWith('.')) right = right.Slice(1); + => StripLeadingDot(left).Equals(StripLeadingDot(right), StringComparison.OrdinalIgnoreCase); - return left.Equals(right, StringComparison.OrdinalIgnoreCase); - } + internal static ReadOnlySpan StripLeadingDot(ReadOnlySpan s) => s.StartsWith('.') ? s[1..] : s; } } diff --git a/src/libraries/Common/src/System/Net/SecurityProtocol.cs b/src/libraries/Common/src/System/Net/SecurityProtocol.cs deleted file mode 100644 index cca3e0d16620cf..00000000000000 --- a/src/libraries/Common/src/System/Net/SecurityProtocol.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Security.Authentication; - -namespace System.Net -{ - internal static class SecurityProtocol - { - public const SslProtocols DefaultSecurityProtocols = -#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK - SslProtocols.Tls13 | -#endif -#pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete - SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; -#pragma warning restore SYSLIB0039 - - public const SslProtocols SystemDefaultSecurityProtocols = SslProtocols.None; - } -} diff --git a/src/libraries/Common/src/System/Obsoletions.cs b/src/libraries/Common/src/System/Obsoletions.cs index d79c8a8de4366e..1947cc3324a5ba 100644 --- a/src/libraries/Common/src/System/Obsoletions.cs +++ b/src/libraries/Common/src/System/Obsoletions.cs @@ -183,7 +183,7 @@ internal static class Obsoletions internal const string X509CtorCertDataObsoleteMessage = "Loading certificate data through the constructor or Import is obsolete. Use X509CertificateLoader instead to load certificates."; internal const string X509CtorCertDataObsoleteDiagId = "SYSLIB0057"; - internal const string TlsCipherAlgorithmEnumsMessage = "KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead."; + internal const string TlsCipherAlgorithmEnumsMessage = "KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead."; internal const string TlsCipherAlgorithmEnumsDiagId = "SYSLIB0058"; internal const string SystemEventsEventsThreadShutdownMessage = "SystemEvents.EventsThreadShutdown callbacks are not run before the process exits. Use AppDomain.ProcessExit instead."; diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs index 32a463bd31caf1..a064f682ca65c6 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs @@ -92,7 +92,15 @@ public override byte[] DeriveRawSecretAgreement(ECDiffieHellmanPublicKey otherPa using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(_key.Value)) { - thisIsNamed = Interop.Crypto.EcKeyHasCurveName(ecKey); + if (ecKey == null || ecKey.IsInvalid) + { + // This may happen when EVP_PKEY was created by provider and getting EC_KEY is not possible. + thisIsNamed = Interop.Crypto.EvpPKeyHasCurveName(_key.Value); + } + else + { + thisIsNamed = Interop.Crypto.EcKeyHasCurveName(ecKey); + } } ECDiffieHellmanOpenSslPublicKey? otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey; diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs index eff1ba80a346b4..a629dc22c76b2f 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.cs @@ -111,21 +111,13 @@ public override void ImportParameters(ECParameters parameters) public override ECParameters ExportExplicitParameters(bool includePrivateParameters) { ThrowIfDisposed(); - - using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(_key.Value)) - { - return ECOpenSsl.ExportExplicitParameters(ecKey, includePrivateParameters); - } + return ECOpenSsl.ExportExplicitParameters(_key.Value, includePrivateParameters); } public override ECParameters ExportParameters(bool includePrivateParameters) { ThrowIfDisposed(); - - using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(_key.Value)) - { - return ECOpenSsl.ExportParameters(ecKey, includePrivateParameters); - } + return ECOpenSsl.ExportParameters(_key.Value, includePrivateParameters); } public override void ImportEncryptedPkcs8PrivateKey( diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs index 2dfbaa92a030ca..8a225c5b4b3951 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSslPublicKey.cs @@ -20,14 +20,19 @@ internal ECDiffieHellmanOpenSslPublicKey(SafeEvpPKeyHandle pkeyHandle) // If ecKey is valid it has already been up-ref'd, so we can just use this handle as-is. SafeEcKeyHandle key = Interop.Crypto.EvpPkeyGetEcKey(pkeyHandle); - if (key.IsInvalid) + if (key == null || key.IsInvalid) { - Exception e = Interop.Crypto.CreateOpenSslCryptographicException(); - key.Dispose(); - throw e; - } + key?.Dispose(); - _key = new ECOpenSsl(key); + // This may happen when EVP_PKEY was created by provider and getting EC_KEY is not possible. + // Since you cannot mix EC_KEY and EVP_PKEY params API we need to export and re-import the public key. + ECParameters ecParams = ECOpenSsl.ExportParameters(pkeyHandle, includePrivateParameters: false); + _key = new ECOpenSsl(ecParams); + } + else + { + _key = new ECOpenSsl(key); + } } internal ECDiffieHellmanOpenSslPublicKey(ECParameters parameters) diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs index b683d88442c2c4..f399895d490f57 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDsaOpenSsl.cs @@ -292,21 +292,13 @@ private SafeEvpPKeyHandle GenerateKeyFromSize() public override ECParameters ExportExplicitParameters(bool includePrivateParameters) { ThrowIfDisposed(); - - using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(_key.Value)) - { - return ECOpenSsl.ExportExplicitParameters(ecKey, includePrivateParameters); - } + return ECOpenSsl.ExportExplicitParameters(_key.Value, includePrivateParameters); } public override ECParameters ExportParameters(bool includePrivateParameters) { ThrowIfDisposed(); - - using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(_key.Value)) - { - return ECOpenSsl.ExportParameters(ecKey, includePrivateParameters); - } + return ECOpenSsl.ExportParameters(_key.Value, includePrivateParameters); } public override void ImportEncryptedPkcs8PrivateKey( diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECOpenSsl.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/ECOpenSsl.ImportExport.cs index bfa3ae2cec0aa1..625b532a023015 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECOpenSsl.ImportExport.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECOpenSsl.ImportExport.cs @@ -169,6 +169,95 @@ private static void CheckInvalidKey(SafeEcKeyHandle key) } } + private static void CheckInvalidKey(SafeEvpPKeyHandle key) + { + if (key == null || key.IsInvalid) + { + throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); + } + } + + public static ECParameters ExportParameters(SafeEvpPKeyHandle pkey, bool includePrivateParameters) + { + CheckInvalidKey(pkey); + + using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(pkey)) + { + if (ecKey == null || ecKey.IsInvalid) + { + // This may happen when EVP_PKEY was created by provider and getting EC_KEY is not possible. + return ExportECParametersFromEvpPKeyUsingParams(pkey, includePrivateParameters); + } + + return ECOpenSsl.ExportParameters(ecKey, includePrivateParameters); + } + } + + public static ECParameters ExportExplicitParameters(SafeEvpPKeyHandle pkey, bool includePrivateParameters) + { + CheckInvalidKey(pkey); + + using (SafeEcKeyHandle ecKey = Interop.Crypto.EvpPkeyGetEcKey(pkey)) + { + if (ecKey == null || ecKey.IsInvalid) + { + // This may happen when EVP_PKEY was created by provider and getting EC_KEY is not possible. + return ExportExplicitCurveParametersFromEvpPKeyUsingParams(pkey, includePrivateParameters); + } + + return ECOpenSsl.ExportExplicitParameters(ecKey, includePrivateParameters); + } + } + + /// + /// Extracts ECParameters from an EVP_PKEY* using OpenSSL 3 params API. + /// This is needed in case EVP_PKEY* was created by provider and getting EC_KEY is not possible. + /// For keys created with EC_KEY, ECOpenSsl.ExportParameters should be used. + /// + private static ECParameters ExportECParametersFromEvpPKeyUsingParams(SafeEvpPKeyHandle pkey, bool includePrivateParameters) + { + string? curveName = Interop.Crypto.EvpPKeyGetCurveName(pkey); + if (curveName == null) + { + return ExportExplicitCurveParametersFromEvpPKeyUsingParams(pkey, includePrivateParameters); + } + else + { + return ExportNamedCurveParametersFromEvpPKeyUsingParams(pkey, curveName, includePrivateParameters); + } + } + + private static ECParameters ExportNamedCurveParametersFromEvpPKeyUsingParams(SafeEvpPKeyHandle pkey, string curveName, bool includePrivateParameters) + { + Debug.Assert(curveName != null); + ECParameters parameters = Interop.Crypto.EvpPKeyGetEcKeyParameters(pkey, includePrivateParameters); + + bool hasPrivateKey = (parameters.D != null); + + if (hasPrivateKey != includePrivateParameters) + { + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + } + + // Assign Curve + parameters.Curve = ECCurve.CreateFromValue(curveName); + + return parameters; + } + + private static ECParameters ExportExplicitCurveParametersFromEvpPKeyUsingParams(SafeEvpPKeyHandle pkey, bool includePrivateParameters) + { + ECParameters parameters = Interop.Crypto.EvpPKeyGetEcCurveParameters(pkey, includePrivateParameters); + + bool hasPrivateKey = (parameters.D != null); + if (hasPrivateKey != includePrivateParameters) + { + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + } + + return parameters; + } + public static SafeEcKeyHandle GenerateKeyByKeySize(int keySize) { string oid; diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs b/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs new file mode 100644 index 00000000000000..c15fa1aa7d9686 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs @@ -0,0 +1,457 @@ +// 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.Diagnostics.CodeAnalysis; + +#pragma warning disable CA1510, CA1513 + +namespace System.Security.Cryptography +{ + /// + /// Represents an ML-KEM key. + /// + /// + /// + /// This algorithm is specified by FIPS-203. + /// + /// + /// Developers are encouraged to program against the MLKem base class, + /// rather than any specific derived class. + /// The derived classes are intended for interop with the underlying system + /// cryptographic libraries. + /// + /// + [Experimental(Experimentals.PostQuantumCryptographyDiagId)] + public abstract class MLKem : IDisposable + { + private bool _disposed; + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported => MLKemImplementation.IsSupported; + + /// + /// Gets the algorithm of the current instance. + /// + /// + /// A value representing the ML-KEM algorithm. + /// + public MLKemAlgorithm Algorithm { get; } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The specific ML-KEM algorithm for this key. + /// + /// + /// is + /// + protected MLKem(MLKemAlgorithm algorithm) + { + if (algorithm is null) + { + throw new ArgumentNullException(nameof(algorithm)); + } + + Algorithm = algorithm; + } + + /// + /// Generates a new ML-KEM key. + /// + /// + /// An algorithm identifying what kind of ML-KEM key to generate. + /// + /// + /// The generated key. + /// + /// + /// is + /// + /// + /// An error occured generating the ML-KEM key. + /// + /// + /// The platform does not support ML-KEM. Callers can use the property + /// to determine if the platform supports MK-KEM. + /// + public static MLKem GenerateKey(MLKemAlgorithm algorithm) + { + if (algorithm is null) + { + throw new ArgumentNullException(nameof(algorithm)); + } + + ThrowIfNotSupported(); + return MLKemImplementation.GenerateKeyImpl(algorithm); + } + + /// + /// Creates an encapsulation ciphertext and shared secret, writing them into the provided buffers. + /// + /// + /// The buffer to receive the ciphertext. + /// + /// + /// The buffer to receive the shared secret. + /// + /// + /// An error occurred during encapsulation. + /// -or - + /// overlaps with . + /// + /// + /// is not the correct size. + /// -or- + /// is not the correct size. + /// + /// The object has already been disposed. + public void Encapsulate(Span ciphertext, Span sharedSecret) + { + if (ciphertext.Length != Algorithm.CiphertextSizeInBytes) + { + throw new ArgumentException( + SR.Format(SR.Argument_DestinationImprecise, Algorithm.CiphertextSizeInBytes), + nameof(ciphertext)); + } + + if (sharedSecret.Length != Algorithm.SharedSecretSizeInBytes) + { + throw new ArgumentException( + SR.Format(SR.Argument_DestinationImprecise, Algorithm.SharedSecretSizeInBytes), + nameof(sharedSecret)); + } + + if (ciphertext.Overlaps(sharedSecret)) + { + throw new CryptographicException(SR.Cryptography_OverlappingBuffers); + } + + ThrowIfDisposed(); + EncapsulateCore(ciphertext, sharedSecret); + } + + /// + /// When overridden in a derived class, creates an encapsulation ciphertext and shared secret, writing them + /// into the provided buffers. + /// + /// + /// The buffer to receive the ciphertext. + /// + /// + /// The buffer to receive the shared secret. + /// + /// + /// An error occurred during encapsulation. + /// + protected abstract void EncapsulateCore(Span ciphertext, Span sharedSecret); + + /// + /// Decapsulates a shared secret from a provided ciphertext. + /// + /// + /// The ciphertext. + /// + /// + /// The buffer to receive the shared secret. + /// + /// + /// An error occurred during decapsulation. + /// + /// + /// is not the correct size. + /// -or- + /// is not the correct size. + /// + /// The object has already been disposed. + public void Decapsulate(ReadOnlySpan ciphertext, Span sharedSecret) + { + if (ciphertext.Length != Algorithm.CiphertextSizeInBytes) + { + throw new ArgumentException(SR.Argument_KemInvalidCiphertextLength, nameof(ciphertext)); + } + + if (sharedSecret.Length != Algorithm.SharedSecretSizeInBytes) + { + throw new ArgumentException( + SR.Format(SR.Argument_DestinationImprecise, Algorithm.SharedSecretSizeInBytes), + nameof(sharedSecret)); + } + + ThrowIfDisposed(); + DecapsulateCore(ciphertext, sharedSecret); + } + + /// + /// When overridden in a derived class, decapsulates a shared secret from a provided ciphertext. + /// + /// + /// The ciphertext. + /// + /// + /// The buffer to receive the shared secret. + /// + /// + /// An error occurred during decapsulation. + /// + protected abstract void DecapsulateCore(ReadOnlySpan ciphertext, Span sharedSecret); + + /// + /// Throws if the current instance is disposed. + /// + protected void ThrowIfDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(MLKem)); + } + } + + /// + /// Exports the private seed into the provided buffer. + /// + /// + /// The buffer to receive the private seed. + /// + /// + /// is the incorrect length to receive the private seed. + /// + /// + /// The current instance cannot export a seed. + /// -or- + /// An error occurred while exporting the key. + /// + public void ExportPrivateSeed(Span destination) + { + if (destination.Length != Algorithm.PrivateSeedSizeInBytes) + { + throw new ArgumentException( + SR.Format(SR.Argument_DestinationImprecise, Algorithm.PrivateSeedSizeInBytes), + nameof(destination)); + } + + ThrowIfDisposed(); + ExportPrivateSeedCore(destination); + } + + /// + /// When overridden in a derived class, exports the private seed into the provided buffer. + /// + /// + /// The buffer to receive the private seed. + /// + protected abstract void ExportPrivateSeedCore(Span destination); + + /// + /// Imports an ML-KEM key from its private seed value. + /// + /// The specific ML-KEM algorithm for this key. + /// The private seed. + /// The imported key. + /// + /// has a length that is not the + /// from . + /// + /// + /// is + /// + /// + /// An error occurred while importing the key. + /// + /// + /// The platform does not support ML-KEM. Callers can use the property + /// to determine if the platform supports MK-KEM. + /// + public static MLKem ImportPrivateSeed(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + if (algorithm is null) + { + throw new ArgumentNullException(nameof(algorithm)); + } + + if (source.Length != algorithm.PrivateSeedSizeInBytes) + { + throw new ArgumentException(SR.Argument_KemInvalidSeedLength, nameof(source)); + } + + ThrowIfNotSupported(); + return MLKemImplementation.ImportPrivateSeedImpl(algorithm, source); + } + + /// + /// Imports an ML-KEM key from a decapsulation key. + /// + /// The specific ML-KEM algorithm for this key. + /// The decapsulation key. + /// The imported key. + /// + /// has a length that is not valid for the ML-KEM algorithm. + /// + /// + /// is + /// + /// + /// An error occurred while importing the key. + /// + /// + /// The platform does not support ML-KEM. Callers can use the property + /// to determine if the platform supports MK-KEM. + /// + public static MLKem ImportDecapsulationKey(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + if (algorithm is null) + { + throw new ArgumentNullException(nameof(algorithm)); + } + + if (source.Length != algorithm.DecapsulationKeySizeInBytes) + { + throw new ArgumentException(SR.Argument_KemInvalidDecapsulationKeyLength, nameof(source)); + } + + ThrowIfNotSupported(); + return MLKemImplementation.ImportDecapsulationKeyImpl(algorithm, source); + } + + /// + /// Imports an ML-KEM key from a encapsulation key. + /// + /// The specific ML-KEM algorithm for this key. + /// The encapsulation key. + /// The imported key. + /// + /// has a length that is not valid for the ML-KEM algorithm. + /// + /// + /// is + /// + /// + /// An error occurred while importing the key. + /// + /// + /// The platform does not support ML-KEM. Callers can use the property + /// to determine if the platform supports MK-KEM. + /// + public static MLKem ImportEncapsulationKey(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + if (algorithm is null) + { + throw new ArgumentNullException(nameof(algorithm)); + } + + if (source.Length != algorithm.EncapsulationKeySizeInBytes) + { + throw new ArgumentException(SR.Argument_KemInvalidEncapsulationKeyLength, nameof(source)); + } + + ThrowIfNotSupported(); + return MLKemImplementation.ImportEncapsulationKeyImpl(algorithm, source); + } + + /// + /// Exports the decapsulation key into the provided buffer. + /// + /// + /// The buffer to receive the decapsulation key. + /// + /// + /// is the incorrect length to receive the decapsulation key. + /// + /// + /// The current instance cannot export a decapsulation key. + /// -or- + /// An error occurred while importing the key. + /// + /// The object has already been disposed. + public void ExportDecapsulationKey(Span destination) + { + if (destination.Length != Algorithm.DecapsulationKeySizeInBytes) + { + throw new ArgumentException( + SR.Format(SR.Argument_DestinationImprecise, Algorithm.DecapsulationKeySizeInBytes), + nameof(destination)); + } + + ThrowIfDisposed(); + ExportDecapsulationKeyCore(destination); + } + + /// + /// When overridden in a derived class, exports the decapsulation key into the provided buffer. + /// + /// + /// The buffer to receive the decapsulation key. + /// + protected abstract void ExportDecapsulationKeyCore(Span destination); + + /// + /// Exports the encapsulation key into the provided buffer. + /// + /// + /// The buffer to receive the encapsulation key. + /// + /// + /// is the incorrect length to receive the encapsulation key. + /// + /// The object has already been disposed. + public void ExportEncapsulationKey(Span destination) + { + if (destination.Length != Algorithm.EncapsulationKeySizeInBytes) + { + throw new ArgumentException( + SR.Format(SR.Argument_DestinationImprecise, Algorithm.EncapsulationKeySizeInBytes), + nameof(destination)); + } + + ThrowIfDisposed(); + ExportEncapsulationKeyCore(destination); + } + + /// + /// When overridden in a derived class, exports the encapsulation key into the provided buffer. + /// + /// + /// The buffer to receive the encapsulation key. + /// + protected abstract void ExportEncapsulationKeyCore(Span destination); + + /// + /// Releases all resources used by the class. + /// + public void Dispose() + { + if (!_disposed) + { + _disposed = true; + Dispose(true); + GC.SuppressFinalize(this); + } + } + + /// + /// Called by the Dispose() and Finalize() methods to release the managed and unmanaged + /// resources used by the current instance of the class. + /// + /// + /// to release managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + } + + private protected static void ThrowIfNotSupported() + { + if (!IsSupported) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(MLKem))); + } + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLKemAlgorithm.cs b/src/libraries/Common/src/System/Security/Cryptography/MLKemAlgorithm.cs new file mode 100644 index 00000000000000..6edef3e1623e46 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/MLKemAlgorithm.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + /// + /// Represents a specific algorithm within the ML-KEM family. + /// + /// + [DebuggerDisplay("{Name,nq}")] + [Experimental(Experimentals.PostQuantumCryptographyDiagId)] + public sealed class MLKemAlgorithm : IEquatable + { + private MLKemAlgorithm( + string name, + int encapsulationKeySizeInBytes, + int decapsulationKeySizeInBytes, + int ciphertextSizeInBytes) + { + Name = name; + EncapsulationKeySizeInBytes = encapsulationKeySizeInBytes; + DecapsulationKeySizeInBytes = decapsulationKeySizeInBytes; + CiphertextSizeInBytes = ciphertextSizeInBytes; + } + + // Values are from NIST FIPS-203 table 3. + + /// + /// Gets an ML-KEM algorithm identifier for the ML-KEM-512 algorithm. + /// + /// + /// An ML-KEM algorithm identifier for the ML-KEM-512 algorithm. + /// + public static MLKemAlgorithm MLKem512 { get; } = new("ML-KEM-512", 800, 1632, 768); + + /// + /// Gets an ML-KEM algorithm identifier for the ML-KEM-768 algorithm. + /// + /// + /// An ML-KEM algorithm identifier for the ML-KEM-768 algorithm. + /// + public static MLKemAlgorithm MLKem768 { get; } = new("ML-KEM-768", 1184, 2400, 1088); + + /// + /// Gets an ML-KEM algorithm identifier for the ML-KEM-1024 algorithm. + /// + /// + /// An ML-KEM algorithm identifier for the ML-KEM-1024 algorithm. + /// + public static MLKemAlgorithm MLKem1024 { get; } = new("ML-KEM-1024", 1568, 3168, 1568); + + /// + /// Gets the name of the algorithm. + /// + /// + /// An a string representing the algorithm name. + /// + public string Name { get; } + + /// + /// Gets size of the encapsulation key for the algorithm, in bytes. + /// + /// + /// The size of the encapsulation key for the algorithm, in bytes. + /// + public int EncapsulationKeySizeInBytes { get; } + + /// + /// Gets size of the decapsulation key for the algorithm, in bytes. + /// + /// + /// The size of the decapsulation key for the algorithm, in bytes. + /// + public int DecapsulationKeySizeInBytes { get; } + + /// + /// Gets size of the ciphertext for the algorithm, in bytes. + /// + /// + /// The size of the ciphertext for the algorithm, in bytes. + /// + public int CiphertextSizeInBytes { get; } + + /// + /// Gets size of the shared secret for the algorithm, in bytes. + /// + /// + /// The size of the shared secret for the algorithm, in bytes. + /// + // Right now every shared secret for ML-KEM is 32 bytes. If or when a different shared secret + // size is needed, then it can be provided as input to the private constructor. + public int SharedSecretSizeInBytes { get; } = 32; + + /// + /// Gets size of the private seed for the algorithm, in bytes. + /// + /// + /// The size of the private seed for the algorithm, in bytes. + /// + // Right now every seed for ML-KEM is 64 bytes. If or when a different seed + // size is needed, then it can be provided as input to the private constructor. + public int PrivateSeedSizeInBytes { get; } = 64; + + /// + /// Compares two objects. + /// + /// + /// An object to be compared to the current object. + /// + /// + /// if the objects are considered equal; otherwise, . + /// + // This is a closed type, so all we need to compare are the names. + public bool Equals(MLKemAlgorithm? other) => other is not null && other.Name == Name; + + /// + public override bool Equals(object? obj) => obj is MLKemAlgorithm alg && alg.Name == Name; + + /// + public override int GetHashCode() => Name.GetHashCode(); + + /// + /// Determines whether two objects specify the same algorithm name. + /// + /// + /// An object that specifies an algorithm name. + /// + /// + /// A second object, to be compared to the object that is identified by the parameter. + /// + /// + /// if the objects are considered equal; otherwise, . + /// + public static bool operator ==(MLKemAlgorithm? left, MLKemAlgorithm? right) + { + return left is null ? right is null : left.Equals(right); + } + + /// + /// Determines whether two objects do not specify the same algorithm name. + /// + /// + /// An object that specifies an algorithm name. + /// + /// + /// A second object, to be compared to the object that is identified by the parameter. + /// + /// + /// if the objects are not considered equal; otherwise, . + /// + public static bool operator !=(MLKemAlgorithm? left, MLKemAlgorithm? right) + { + return !(left == right); + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLKemImplementation.NotSupported.cs b/src/libraries/Common/src/System/Security/Cryptography/MLKemImplementation.NotSupported.cs new file mode 100644 index 00000000000000..2aa6517bc2d169 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/MLKemImplementation.NotSupported.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.Diagnostics; + +namespace System.Security.Cryptography +{ + internal sealed class MLKemImplementation : MLKem + { + internal static new bool IsSupported => false; + + private MLKemImplementation(MLKemAlgorithm algorithm) : base(algorithm) + { + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + internal static MLKem GenerateKeyImpl(MLKemAlgorithm algorithm) + { + _ = algorithm; + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + internal static MLKem ImportPrivateSeedImpl(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + _ = algorithm; + _ = source; + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + internal static MLKem ImportDecapsulationKeyImpl(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + _ = algorithm; + _ = source; + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + internal static MLKem ImportEncapsulationKeyImpl(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + _ = algorithm; + _ = source; + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + protected override void DecapsulateCore(ReadOnlySpan ciphertext, Span sharedSecret) + { + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + protected override void EncapsulateCore(Span ciphertext, Span sharedSecret) + { + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + protected override void ExportPrivateSeedCore(Span destination) + { + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + protected override void ExportDecapsulationKeyCore(Span destination) + { + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + + protected override void ExportEncapsulationKeyCore(Span destination) + { + Debug.Fail("Caller should have checked platform availability."); + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/Oids.cs b/src/libraries/Common/src/System/Security/Cryptography/Oids.cs index 9970d7935b1314..d438e7f0f34ab7 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Oids.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Oids.cs @@ -104,6 +104,31 @@ internal static partial class Oids internal const string MLDsa65PreHashSha512 = "2.16.840.1.101.3.4.3.33"; internal const string MLDsa87PreHashSha512 = "2.16.840.1.101.3.4.3.34"; + internal const string SlhDsaSha2_128s = "2.16.840.1.101.3.4.3.20"; + internal const string SlhDsaSha2_128f = "2.16.840.1.101.3.4.3.21"; + internal const string SlhDsaSha2_192s = "2.16.840.1.101.3.4.3.22"; + internal const string SlhDsaSha2_192f = "2.16.840.1.101.3.4.3.23"; + internal const string SlhDsaSha2_256s = "2.16.840.1.101.3.4.3.24"; + internal const string SlhDsaSha2_256f = "2.16.840.1.101.3.4.3.25"; + internal const string SlhDsaShake_128s = "2.16.840.1.101.3.4.3.26"; + internal const string SlhDsaShake_128f = "2.16.840.1.101.3.4.3.27"; + internal const string SlhDsaShake_192s = "2.16.840.1.101.3.4.3.28"; + internal const string SlhDsaShake_192f = "2.16.840.1.101.3.4.3.29"; + internal const string SlhDsaShake_256s = "2.16.840.1.101.3.4.3.30"; + internal const string SlhDsaShake_256f = "2.16.840.1.101.3.4.3.31"; + internal const string SlhDsaSha2_128sPreHashSha256 = "2.16.840.1.101.3.4.3.35"; + internal const string SlhDsaSha2_128fPreHashSha256 = "2.16.840.1.101.3.4.3.36"; + internal const string SlhDsaSha2_192sPreHashSha512 = "2.16.840.1.101.3.4.3.37"; + internal const string SlhDsaSha2_192fPreHashSha512 = "2.16.840.1.101.3.4.3.38"; + internal const string SlhDsaSha2_256sPreHashSha512 = "2.16.840.1.101.3.4.3.39"; + internal const string SlhDsaSha2_256fPreHashSha512 = "2.16.840.1.101.3.4.3.40"; + internal const string SlhDsaShake_128sPreHashShake128 = "2.16.840.1.101.3.4.3.41"; + internal const string SlhDsaShake_128fPreHashShake128 = "2.16.840.1.101.3.4.3.42"; + internal const string SlhDsaShake_192sPreHashShake256 = "2.16.840.1.101.3.4.3.43"; + internal const string SlhDsaShake_192fPreHashShake256 = "2.16.840.1.101.3.4.3.44"; + internal const string SlhDsaShake_256sPreHashShake256 = "2.16.840.1.101.3.4.3.45"; + internal const string SlhDsaShake_256fPreHashShake256 = "2.16.840.1.101.3.4.3.46"; + internal const string Mgf1 = "1.2.840.113549.1.1.8"; internal const string PSpecified = "1.2.840.113549.1.1.9"; diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs new file mode 100644 index 00000000000000..c0d0738108b1d4 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs @@ -0,0 +1,1280 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Formats.Asn1; +using System.Security.Cryptography.Asn1; + +// The type being internal is making unused parameter warnings fire for +// not-implemented methods. Suppress those warnings. +#pragma warning disable IDE0060 + +namespace System.Security.Cryptography +{ + /// + /// Represents an SLH-DSA key. + /// + /// + /// Developers are encouraged to program against the SlhDsa base class, + /// rather than any specific derived class. + /// The derived classes are intended for interop with the underlying system + /// cryptographic libraries. + /// + [Experimental(Experimentals.PostQuantumCryptographyDiagId)] + internal abstract partial class SlhDsa : IDisposable +#if DESIGNTIMEINTERFACES +#pragma warning disable SA1001 + , IImportExportShape +#pragma warning restore SA1001 +#endif + { + private const int MaxContextLength = 255; + + private bool _disposed; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The specific SLH-DSA algorithm for this key. + /// + protected SlhDsa(SlhDsaAlgorithm algorithm) + { + Algorithm = algorithm; + } + + protected void ThrowIfDisposed() + { + ObjectDisposedException.ThrowIf(_disposed, this); + } + + /// + /// Gets a value indicating whether the current platform supports SLH-DSA. + /// + /// + /// if the current platform supports SLH-DSA; otherwise, . + /// + public static bool IsSupported { get; } = SlhDsaImplementation.SupportsAny(); + + /// + /// Gets the specific SLH-DSA algorithm for this key. + /// + /// + /// The specific SLH-DSA algorithm for this key. + /// + public SlhDsaAlgorithm Algorithm { get; } + + /// + /// Releases all resources used by the class. + /// + public void Dispose() + { + Dispose(true); + _disposed = true; + GC.SuppressFinalize(this); + } + + /// + /// Sign the specified data, writing the signature into the provided buffer. + /// + /// + /// The data to sign. + /// + /// + /// The buffer to receive the signature. + /// + /// + /// An optional context-specific value to limit the scope of the signature. + /// The default value is an empty buffer. + /// + /// + /// The number of bytes written to the buffer. + /// + /// + /// The buffer in is too small to hold the signature. + /// + /// + /// has a in excess of + /// 255 bytes. + /// + /// + /// This instance has been disposed. + /// + /// + /// The instance represents only a public key. + /// -or- + /// An error occurred while signing the data. + /// + public int SignData(ReadOnlySpan data, Span destination, ReadOnlySpan context = default) + { + ThrowIfDisposed(); + + if (context.Length > MaxContextLength) + { + throw new ArgumentOutOfRangeException( + nameof(context), + context.Length, + SR.Argument_SignatureContextTooLong255); + } + + int signatureSizeInBytes = Algorithm.SignatureSizeInBytes; + + if (destination.Length < signatureSizeInBytes) + { + throw new ArgumentException(nameof(destination), SR.Argument_DestinationTooShort); + } + + SignDataCore(data, context, destination.Slice(0, signatureSizeInBytes)); + return signatureSizeInBytes; + } + + /// + /// Verifies that the specified signature is valid for this key and the provided data. + /// + /// + /// The data to verify. + /// + /// + /// The signature to verify. + /// + /// + /// The context value which was provided during signing. + /// The default value is an empty buffer. + /// + /// + /// if the signature validates the data; otherwise, . + /// + /// + /// has a in excess of + /// 255 bytes. + /// + /// + /// This instance has been disposed. + /// + /// + /// The instance represents only a public key. + /// -or- + /// An error occurred while signing the data. + /// + public bool VerifyData(ReadOnlySpan data, ReadOnlySpan signature, ReadOnlySpan context = default) + { + ThrowIfDisposed(); + + if (context.Length > MaxContextLength) + { + throw new ArgumentOutOfRangeException( + nameof(context), + context.Length, + SR.Argument_SignatureContextTooLong255); + } + + if (signature.Length != Algorithm.SignatureSizeInBytes) + { + return false; + } + + return VerifyDataCore(data, context, signature); + } + + /// + /// Exports the public-key portion of the current key in the X.509 SubjectPublicKeyInfo format. + /// + /// + /// A byte array containing the X.509 SubjectPublicKeyInfo representation of the public-key portion of this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// An error occurred while exporting the key. + /// + public byte[] ExportSubjectPublicKeyInfo() + { + ThrowIfDisposed(); + + AsnWriter writer = ExportSubjectPublicKeyInfoCore(); + return writer.Encode(); + } + + /// + /// Attempts to export the public-key portion of the current key in the X.509 SubjectPublicKeyInfo format + /// into the provided buffer. + /// + /// + /// The buffer to receive the X.509 SubjectPublicKeyInfo value. + /// + /// + /// When this method returns, contains the number of bytes written to the buffer. + /// This parameter is treated as uninitialized. + /// + /// + /// if was large enough to hold the result; + /// otherwise, . + /// + /// + /// This instance has been disposed. + /// + /// + /// An error occurred while exporting the key. + /// + public bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) + { + ThrowIfDisposed(); + + AsnWriter writer = ExportSubjectPublicKeyInfoCore(); + return writer.TryEncode(destination, out bytesWritten); + } + + /// + /// Exports the public-key portion of the current key in a PEM-encoded representation of + /// the X.509 SubjectPublicKeyInfo format. + /// + /// + /// A string containing the PEM-encoded representation of the X.509 SubjectPublicKeyInfo + /// representation of the public-key portion of this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// An error occurred while exporting the key. + /// + public string ExportSubjectPublicKeyInfoPem() + { + ThrowIfDisposed(); + + AsnWriter writer = ExportSubjectPublicKeyInfoCore(); + return writer.Encode(static span => PemEncoding.WriteString(PemLabels.SpkiPublicKey, span)); + } + + /// + /// Exports the current key in the PKCS#8 PrivateKeyInfo format. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public byte[] ExportPkcs8PrivateKey() + { + ThrowIfDisposed(); + + // TODO: When defining this, provide a virtual method whose base implementation is to + // call ExportPrivateSeed and/or ExportSecretKey, and then assemble the result, + // but allow the derived class to override it in case they need to implement those + // others in terms of the PKCS8 export from the underlying provider. + + throw new NotImplementedException("The PKCS#8 format is still under debate"); + } + + /// + /// Attempts to export the current key in the PKCS#8 PrivateKeyInfo format + /// into the provided buffer. + /// + /// + /// The buffer to receive the PKCS#8 PrivateKeyInfo value. + /// + /// + /// When this method returns, contains the number of bytes written to the buffer. + /// This parameter is treated as uninitialized. + /// + /// + /// if was large enough to hold the result; + /// otherwise, . + /// + /// + /// This instance has been disposed. + /// + /// + /// An error occurred while exporting the key. + /// + public bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) + { + ThrowIfDisposed(); + + // TODO: Once the minimum size of a PKCS#8 export is known, add an early return false. + + throw new NotImplementedException("The PKCS#8 format is still under debate"); + } + + /// + /// Exports the current key in a PEM-encoded representation of the PKCS#8 PrivateKeyInfo format. + /// + /// + /// A string containing the PEM-encoded representation of the PKCS#8 PrivateKeyInfo + /// representation of the public-key portion of this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// An error occurred while exporting the key. + /// + public string ExportPkcs8PrivateKeyPem() + { + ThrowIfDisposed(); + + throw new NotImplementedException("The PKCS#8 format is still under debate"); + } + + /// + /// Exports the current key in the PKCS#8 EncryptedPrivateKeyInfo format with a char-based password. + /// + /// + /// The password to use when encrypting the key material. + /// + /// + /// The password-based encryption (PBE) parameters to use when encrypting the key material. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan password, PbeParameters pbeParameters) + { + ThrowIfDisposed(); + + // TODO: Validation on pbeParameters. + + AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(password, pbeParameters); + + try + { + return writer.Encode(); + } + finally + { + writer.Reset(); + } + } + + /// + /// Exports the current key in the PKCS#8 EncryptedPrivateKeyInfo format with a byte-based password. + /// + /// + /// The bytes to use as a password when encrypting the key material. + /// + /// + /// The password-based encryption (PBE) parameters to use when encrypting the key material. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// specifies a KDF that requires a char-based password. + /// -or- + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, PbeParameters pbeParameters) + { + ThrowIfDisposed(); + + // TODO: Validation on pbeParameters. + + AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(passwordBytes, pbeParameters); + + try + { + return writer.Encode(); + } + finally + { + writer.Reset(); + } + } + + /// + /// Attempts to export the current key in the PKCS#8 EncryptedPrivateKeyInfo format into a provided buffer, + /// using a char-based password. + /// + /// + /// The password to use when encrypting the key material. + /// + /// + /// The password-based encryption (PBE) parameters to use when encrypting the key material. + /// + /// + /// The buffer to receive the PKCS#8 EncryptedPrivateKeyInfo value. + /// + /// + /// When this method returns, contains the number of bytes written to the buffer. + /// This parameter is treated as uninitialized. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + ThrowIfDisposed(); + + AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(password, pbeParameters); + + try + { + return writer.TryEncode(destination, out bytesWritten); + } + finally + { + writer.Reset(); + } + } + + /// + /// Attempts to export the current key in the PKCS#8 EncryptedPrivateKeyInfo format into a provided buffer, + /// using a byte-based password. + /// + /// + /// The bytes to use as a password when encrypting the key material. + /// + /// + /// The password-based encryption (PBE) parameters to use when encrypting the key material. + /// + /// + /// The buffer to receive the PKCS#8 EncryptedPrivateKeyInfo value. + /// + /// + /// When this method returns, contains the number of bytes written to the buffer. + /// This parameter is treated as uninitialized. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// specifies a KDF that requires a char-based password. + /// -or- + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) + { + ThrowIfDisposed(); + + AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(passwordBytes, pbeParameters); + + try + { + return writer.TryEncode(destination, out bytesWritten); + } + finally + { + writer.Reset(); + } + } + + /// + /// Exports the current key in a PEM-encoded representation of the PKCS#8 EncryptedPrivateKeyInfo representation of this key, + /// using a char-based password. + /// + /// + /// The bytes to use as a password when encrypting the key material. + /// + /// + /// The password-based encryption (PBE) parameters to use when encrypting the key material. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public string ExportEncryptedPkcs8PrivateKeyPem( + ReadOnlySpan password, + PbeParameters pbeParameters) + { + ThrowIfDisposed(); + + // TODO: Validation on pbeParameters. + + AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(password, pbeParameters); + + try + { + return writer.Encode(static span => PemEncoding.WriteString(PemLabels.EncryptedPkcs8PrivateKey, span)); + } + finally + { + writer.Reset(); + } + } + + /// + /// Exports the current key in a PEM-encoded representation of the PKCS#8 EncryptedPrivateKeyInfo representation of this key, + /// using a byte-based password. + /// + /// + /// The bytes to use as a password when encrypting the key material. + /// + /// + /// The password-based encryption (PBE) parameters to use when encrypting the key material. + /// + /// + /// A byte array containing the PKCS#8 PrivateKeyInfo representation of the this key. + /// + /// + /// This instance has been disposed. + /// + /// + /// specifies a KDF that requires a char-based password. + /// -or- + /// This instance only represents a public key. + /// -or- + /// The private key is not exportable. + /// -or- + /// An error occurred while exporting the key. + /// + public string ExportEncryptedPkcs8PrivateKeyPem( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) + { + ThrowIfDisposed(); + + // TODO: Validation on pbeParameters. + + AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(passwordBytes, pbeParameters); + + try + { + return writer.Encode(static span => PemEncoding.WriteString(PemLabels.EncryptedPkcs8PrivateKey, span)); + } + finally + { + writer.Reset(); + } + } + + /// + /// Exports the public-key portion of the current key in the FIPS 205 public key format. + /// + /// + /// The buffer to receive the public key. + /// + /// + /// The number of bytes written to . + /// + /// + /// is too small to hold the public key. + /// + public int ExportSlhDsaPublicKey(Span destination) + { + ThrowIfDisposed(); + + int publicKeySizeInBytes = Algorithm.PublicKeySizeInBytes; + + if (destination.Length < publicKeySizeInBytes) + { + throw new ArgumentException(nameof(destination), SR.Argument_DestinationTooShort); + } + + ExportSlhDsaPublicKeyCore(destination.Slice(0, publicKeySizeInBytes)); + return publicKeySizeInBytes; + } + + /// + /// Exports the current key in the FIPS 205 secret key format. + /// + /// + /// The buffer to receive the secret key. + /// + /// + /// The number of bytes written to . + /// + /// + /// is too small to hold the secret key. + /// + /// + /// An error occurred while exporting the key. + /// + public int ExportSlhDsaSecretKey(Span destination) + { + ThrowIfDisposed(); + + int secretKeySizeInBytes = Algorithm.SecretKeySizeInBytes; + + if (destination.Length < secretKeySizeInBytes) + { + throw new ArgumentException(nameof(destination), SR.Argument_DestinationTooShort); + } + + ExportSlhDsaSecretKeyCore(destination.Slice(0, secretKeySizeInBytes)); + return secretKeySizeInBytes; + } + + /// + /// Exports the private seed of the current key. + /// + /// + /// The buffer to receive the private seed. + /// + /// + /// The number of bytes written to . + /// + /// + /// is too small to hold the private seed. + /// + /// + /// An error occurred while exporting the private seed. + /// + public int ExportSlhDsaPrivateSeed(Span destination) + { + ThrowIfDisposed(); + + int privateSeedSizeInBytes = Algorithm.PrivateSeedSizeInBytes; + + if (destination.Length < privateSeedSizeInBytes) + { + throw new ArgumentException(nameof(destination), SR.Argument_DestinationTooShort); + } + + ExportSlhDsaPrivateSeedCore(destination.Slice(0, privateSeedSizeInBytes)); + return privateSeedSizeInBytes; + } + + /// + /// Generates a new SLH-DSA key for the specified algorithm. + /// + /// + /// The generated object. + /// + public static SlhDsa GenerateKey(SlhDsaAlgorithm algorithm) => + SlhDsaImplementation.GenerateKeyCore(algorithm); + + /// + /// Imports an SLH-DSA public key from an X.509 SubjectPublicKeyInfo structure. + /// + /// + /// The bytes of an X.509 SubjectPublicKeyInfo structure in the ASN.1-DER encoding. + /// + /// + /// The imported key. + /// + /// + /// + /// The contents of do not represent an ASN.1-DER-encoded X.509 SubjectPublicKeyInfo structure. + /// + /// -or- + /// + /// The SubjectPublicKeyInfo value does not represent an SLH-DSA key. + /// + /// -or- + /// + /// The algorithm-specific import failed. + /// + /// + public static SlhDsa ImportSubjectPublicKeyInfo(ReadOnlySpan source) + { + ThrowIfNotSupported(); + + unsafe + { + fixed (byte* pointer = source) + { + using (PointerMemoryManager manager = new(pointer, source.Length)) + { + AsnValueReader reader = new AsnValueReader(source, AsnEncodingRules.DER); + SubjectPublicKeyInfoAsn.Decode(ref reader, manager.Memory, out SubjectPublicKeyInfoAsn spki); + + SlhDsaAlgorithm algorithm = SlhDsaAlgorithm.GetAlgorithmFromOid(spki.Algorithm.Algorithm); + + if (spki.Algorithm.Parameters.HasValue) + { + AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); + spki.Algorithm.Encode(writer); + ThrowAlgorithmUnknown(writer); + Debug.Fail("Execution should have halted in the throw-helper."); + } + + return SlhDsaImplementation.ImportPublicKey(algorithm, spki.SubjectPublicKey.Span); + } + } + } + } + + /// + /// Imports an SLH-DSA private key from a PKCS#8 PrivateKeyInfo structure. + /// + /// + /// The bytes of a PKCS#8 PrivateKeyInfo structure in the ASN.1-DER encoding. + /// + /// + /// The imported key. + /// + /// + /// + /// The contents of do not represent an ASN.1-BER-encoded PKCS#8 PrivateKeyInfo structure. + /// + /// -or- + /// + /// The PrivateKeyInfo value does not represent an SLH-DSA key. + /// + /// -or- + /// + /// The algorithm-specific import failed. + /// + /// + public static SlhDsa ImportPkcs8PrivateKey(ReadOnlySpan source) + { + ThrowIfNotSupported(); + + unsafe + { + fixed (byte* pointer = source) + { + using (PointerMemoryManager manager = new(pointer, source.Length)) + { + AsnValueReader reader = new AsnValueReader(source, AsnEncodingRules.DER); + PrivateKeyInfoAsn.Decode(ref reader, manager.Memory, out PrivateKeyInfoAsn pki); + + SlhDsaAlgorithm info = SlhDsaAlgorithm.GetAlgorithmFromOid(pki.PrivateKeyAlgorithm.Algorithm); + + if (pki.PrivateKeyAlgorithm.Parameters.HasValue) + { + AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); + pki.PrivateKeyAlgorithm.Encode(writer); + ThrowAlgorithmUnknown(writer); + Debug.Fail("Execution should have halted in the throw-helper."); + } + + return SlhDsaImplementation.ImportPkcs8PrivateKeyValue(info, pki.PrivateKey.Span); + } + } + } + } + + /// + /// Imports an SLH-DSA private key from a PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// + /// The bytes to use as a password when decrypting the key material. + /// + /// + /// The bytes of a PKCS#8 EncryptedPrivateKeyInfo structure in the ASN.1-BER encoding. + /// + /// + /// The imported key. + /// + /// + /// + /// The contents of do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The specified password is incorrect. + /// + /// -or- + /// + /// The EncryptedPrivateKeyInfo indicates the Key Derivation Function (KDF) to apply is the legacy PKCS#12 KDF, + /// which requires -based passwords. + /// + /// -or- + /// + /// The value does not represent an SLH-DSA key. + /// + /// -or- + /// + /// The algorithm-specific import failed. + /// + /// + public static SlhDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, ReadOnlySpan source) + { + ThrowIfNotSupported(); + + return KeyFormatHelper.DecryptPkcs8( + passwordBytes, + source, + ImportPkcs8PrivateKey, + out _); + } + + /// + /// Imports an SLH-DSA private key from a PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// + /// The password to use when decrypting the key material. + /// + /// + /// The bytes of a PKCS#8 EncryptedPrivateKeyInfo structure in the ASN.1-BER encoding. + /// + /// + /// The imported key. + /// + /// + /// + /// The contents of do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The specified password is incorrect. + /// + /// -or- + /// + /// The value does not represent an SLH-DSA key. + /// + /// -or- + /// + /// The algorithm-specific import failed. + /// + /// + public static SlhDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan password, ReadOnlySpan source) + { + ThrowIfNotSupported(); + + return KeyFormatHelper.DecryptPkcs8( + password, + source, + ImportPkcs8PrivateKey, + out _); + } + + /// + /// Imports an SLH-DSA key from an RFC 7468 PEM-encoded string. + /// + /// + /// The text of the PEM key to import. + /// + /// + /// The imported SLH-DSA key. + /// + /// + /// contains an encrypted PEM-encoded key. + /// -or- + /// contains multiple PEM-encoded SLH-DSA keys. + /// -or- + /// contains no PEM-encoded SLH-DSA keys. + /// + /// + /// An error occurred while importing the key. + /// + public static SlhDsa ImportFromPem(ReadOnlySpan source) + { + ThrowIfNotSupported(); + + // TODO: Match the behavior of ECDsa.ImportFromPem. + // Double-check that the base64-decoded data has no trailing contents. + throw new NotImplementedException(); + } + + /// + /// Imports an SLH-DSA key from an RFC 7468 PEM-encoded string. + /// + /// + /// The text of the PEM key to import. + /// + /// + /// The password to use when decrypting the key material. + /// + /// + /// if the source did not contain a PEM-encoded SLH-DSA key; + /// if the source contains an SLH-DSA key and it was successfully imported; + /// otherwise, an exception is thrown. + /// + /// + /// contains an encrypted PEM-encoded key. + /// -or- + /// contains multiple PEM-encoded SLH-DSA keys. + /// -or- + /// contains no PEM-encoded SLH-DSA keys. + /// + /// + /// An error occurred while importing the key. + /// + public static SlhDsa ImportFromEncryptedPem(ReadOnlySpan source, ReadOnlySpan password) + { + ThrowIfNotSupported(); + + // TODO: Match the behavior of ECDsa.ImportFromEncryptedPem. + throw new NotImplementedException(); + } + + /// + /// Imports an SLH-DSA key from an RFC 7468 PEM-encoded string. + /// + /// + /// The text of the PEM key to import. + /// + /// + /// The password to use when decrypting the key material. + /// + /// + /// if the source did not contain a PEM-encoded SLH-DSA key; + /// if the source contains an SLH-DSA key and it was successfully imported; + /// otherwise, an exception is thrown. + /// + /// + /// contains an encrypted PEM-encoded key. + /// -or- + /// contains multiple PEM-encoded SLH-DSA keys. + /// -or- + /// contains no PEM-encoded SLH-DSA keys. + /// + /// + /// An error occurred while importing the key. + /// + public static SlhDsa ImportFromEncryptedPem(ReadOnlySpan source, ReadOnlySpan passwordBytes) + { + ThrowIfNotSupported(); + + // TODO: Match the behavior of ECDsa.ImportFromEncryptedPem. + throw new NotImplementedException(); + } + + /// + /// Imports an SLH-DSA public key in the FIPS 205 public key format. + /// + /// + /// The specific SLH-DSA algorithm for this key. + /// + /// + /// The bytes of a FIPS 205 public key. + /// + /// + /// The imported key. + /// + /// + /// + /// is not a valid SLH-DSA algorithm identifier. + /// + /// -or- + /// + /// is not the correct size for the specified algorithm. + /// + /// -or- + /// + /// An error occurred while importing the key. + /// + /// + public static SlhDsa ImportSlhDsaPublicKey(SlhDsaAlgorithm algorithm, ReadOnlySpan source) + { + ThrowIfNotSupported(); + ArgumentNullException.ThrowIfNull(algorithm); + + if (source.Length != algorithm.PublicKeySizeInBytes) + { + throw new CryptographicException(SR.Cryptography_KeyWrongSizeForAlgorithm); + } + + return SlhDsaImplementation.ImportPublicKey(algorithm, source); + } + + /// + /// Imports an SLH-DSA private key in the FIPS 205 secret key format. + /// + /// + /// The specific SLH-DSA algorithm for this key. + /// + /// + /// The bytes of a FIPS 205 secret key. + /// + /// + /// The imported key. + /// + /// + /// + /// is not a valid SLH-DSA algorithm identifier. + /// + /// -or- + /// + /// is not the correct size for the specified algorithm. + /// + /// -or- + /// + /// An error occurred while importing the key. + /// + /// + public static SlhDsa ImportSlhDsaSecretKey(SlhDsaAlgorithm algorithm, ReadOnlySpan source) + { + ThrowIfNotSupported(); + ArgumentNullException.ThrowIfNull(algorithm); + + if (source.Length != algorithm.SecretKeySizeInBytes) + { + throw new CryptographicException(SR.Cryptography_KeyWrongSizeForAlgorithm); + } + + return SlhDsaImplementation.ImportSecretKey(algorithm, source); + } + + /// + /// Imports an SLH-DSA private key from its private seed value. + /// + /// + /// The specific SLH-DSA algorithm for this key. + /// + /// + /// The bytes the key seed. + /// + /// + /// The imported key. + /// + /// + /// + /// is not a valid SLH-DSA algorithm identifier. + /// + /// -or- + /// + /// is not the correct size for the specified algorithm. + /// + /// -or- + /// + /// An error occurred while importing the key. + /// + /// + public static SlhDsa ImportSlhDsaPrivateSeed(SlhDsaAlgorithm algorithm, ReadOnlySpan source) + { + ThrowIfNotSupported(); + + if (source.Length != algorithm.PrivateSeedSizeInBytes) + { + throw new CryptographicException(SR.Cryptography_KeyWrongSizeForAlgorithm); + } + + return SlhDsaImplementation.ImportSeed(algorithm, source); + } + + /// + /// Called by the Dispose() and Finalize() methods to release the managed and unmanaged + /// resources used by the current instance of the class. + /// + /// + /// to release managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + } + + /// + /// When overridden in a derived class, computes the signature of the specified data and context, + /// writing it into the provided buffer. + /// + /// + /// The data to sign. + /// + /// + /// The signature context. + /// + /// + /// The buffer to receive the signature, which will always be the exactly correct size for the algorithm. + /// + /// + /// An error occurred while signing the data. + /// + protected abstract void SignDataCore(ReadOnlySpan data, ReadOnlySpan context, Span destination); + + /// + /// When overridden in a derived class, verifies the signature of the specified data and context. + /// + /// + /// The data to verify. + /// + /// + /// The signature context. + /// + /// + /// The signature to verify. + /// + /// + /// if the signature validates the data; otherwise, . + /// + /// + /// An error occurred while signing the data. + /// + protected abstract bool VerifyDataCore(ReadOnlySpan data, ReadOnlySpan context, ReadOnlySpan signature); + + /// + /// When overridden in a derived class, exports the FIPS 205 public key to the specified buffer. + /// + /// + /// The buffer to receive the public key. + /// + protected abstract void ExportSlhDsaPublicKeyCore(Span destination); + + /// + /// When overridden in a derived class, exports the FIPS 205 secret key to the specified buffer. + /// + /// + /// The buffer to receive the secret key. + /// + protected abstract void ExportSlhDsaSecretKeyCore(Span destination); + + /// + /// When overridden in a derived class, exports the private seed to the specified buffer. + /// + /// + /// The buffer to receive the private seed. + /// + protected abstract void ExportSlhDsaPrivateSeedCore(Span destination); + + private AsnWriter ExportSubjectPublicKeyInfoCore() + { + ThrowIfDisposed(); + + byte[] rented = CryptoPool.Rent(Algorithm.PublicKeySizeInBytes); + + try + { + Span keySpan = rented.AsSpan(0, Algorithm.PublicKeySizeInBytes); + ExportSlhDsaPublicKey(keySpan); + + AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); + + using (writer.PushSequence()) + { + using (writer.PushSequence()) + { + writer.WriteObjectIdentifier(Algorithm.Oid); + } + + writer.WriteBitString(keySpan); + } + + return writer; + } + finally + { + // Public key doesn't need to be cleared + CryptoPool.Return(rented, 0); + } + } + + private AsnWriter ExportEncryptedPkcs8PrivateKeyCore(ReadOnlySpan passwordBytes, PbeParameters pbeParameters) + { + ThrowIfDisposed(); + + // TODO: Determine a more appropriate maximum size once the format is actually known. + int size = Algorithm.SecretKeySizeInBytes * 2; + // The buffer is only being passed out as a span, so the derived type can't meaningfully + // hold on to it without being malicious. + byte[] rented = CryptoPool.Rent(size); + int written; + + while (!TryExportPkcs8PrivateKey(rented, out written)) + { + size = rented.Length; + CryptoPool.Return(rented, 0); + rented = CryptoPool.Rent(size * 2); + } + + AsnWriter tmp = new AsnWriter(AsnEncodingRules.BER); + + try + { + tmp.WriteEncodedValueForCrypto(rented.AsSpan(0, written)); + return KeyFormatHelper.WriteEncryptedPkcs8(passwordBytes, tmp, pbeParameters); + } + finally + { + tmp.Reset(); + CryptoPool.Return(rented, written); + } + } + + private AsnWriter ExportEncryptedPkcs8PrivateKeyCore(ReadOnlySpan password, PbeParameters pbeParameters) + { + ThrowIfDisposed(); + + // TODO: Determine a more appropriate maximum size once the format is actually known. + int initialSize = Algorithm.SecretKeySizeInBytes * 2; + // The buffer is only being passed out as a span, so the derived type can't meaningfully + // hold on to it without being malicious. + byte[] rented = CryptoPool.Rent(initialSize); + int written; + + while (!TryExportPkcs8PrivateKey(rented, out written)) + { + CryptoPool.Return(rented, 0); + rented = CryptoPool.Rent(rented.Length * 2); + } + + AsnWriter tmp = new AsnWriter(AsnEncodingRules.BER); + + try + { + tmp.WriteEncodedValueForCrypto(rented.AsSpan(0, written)); + return KeyFormatHelper.WriteEncryptedPkcs8(password, tmp, pbeParameters); + } + finally + { + tmp.Reset(); + CryptoPool.Return(rented, written); + } + } + + internal static void ThrowIfNotSupported() + { + if (!IsSupported) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(SlhDsa))); + } + } + + [DoesNotReturn] + private static void ThrowAlgorithmUnknown(AsnWriter encodedId) + { +#if NET9_0_OR_GREATER + throw encodedId.Encode(static encoded => + new CryptographicException( + SR.Format(SR.Cryptography_UnknownAlgorithmIdentifier, Convert.ToHexString(encoded)))); +#else + throw new CryptographicException( + SR.Format(SR.Cryptography_UnknownAlgorithmIdentifier, Convert.ToHexString(encodedId.Encode()))); +#endif + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsaAlgorithm.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaAlgorithm.cs new file mode 100644 index 00000000000000..70acf8f6958d7a --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaAlgorithm.cs @@ -0,0 +1,220 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + /// + /// Represents a specific algorithm within the SHL-DSA family. + /// + [DebuggerDisplay("{Name,nq}")] + [Experimental(Experimentals.PostQuantumCryptographyDiagId)] + internal sealed class SlhDsaAlgorithm + { + /// + /// Gets the underlying string representation of the algorithm name. + /// + /// + /// The underlying string representation of the algorithm name. + /// + public string Name { get; } + + /// + /// Gets the size of the secret key in bytes for this algorithm. + /// + /// + /// The size of the secret key in bytes for this algorithm. + /// + public int SecretKeySizeInBytes { get; } + + /// + /// Gets the size of the public key in bytes for this algorithm. + /// + /// + /// The size of the public key in bytes for this algorithm. + /// + public int PublicKeySizeInBytes { get; } + + /// + /// Gets the size of the signature in bytes for this algorithm. + /// + /// + /// The size of the signature in bytes for this algorithm. + /// + public int SignatureSizeInBytes { get; } + + /// + /// Gets the size of the private seed in bytes for this algorithm. + /// + /// + /// The size of the private seed in bytes for this algorithm. + /// + internal int PrivateSeedSizeInBytes { get; } + + /// + /// Gets the Object Identifier (OID) for this algorithm. + /// + /// + /// The Object Identifier (OID) for this algorithm. + /// + internal string Oid { get; } + + /// + /// Initializes a new instance of the structure with a custom name. + /// + /// + /// The name of the algorithm. + /// + /// + /// The "security parameter" as described in FIPS 205. + /// + /// + /// The size of the signature in bytes for this algorithm. + /// + /// + /// The Object Identifier (OID) for this algorithm. + /// + private SlhDsaAlgorithm(string name, int n, int signatureSizeInBytes, string oid) + { + Name = name; + + // The seed, secret key and public key sizes are shown to be 3n, 4n and 2n respectively in + // section 9.1 "Key Generation", particularly figure 15 and 16. + PrivateSeedSizeInBytes = 3 * n; + SecretKeySizeInBytes = 4 * n; + PublicKeySizeInBytes = 2 * n; + SignatureSizeInBytes = signatureSizeInBytes; + Oid = oid; + } + + // SLH-DSA parameter sets, and the sizes associated with them, + // are defined in FIPS 205, section 11 "Parameter Sets", + // particularly Table 2 "SLH-DSA parameter sets". + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHA2-128s algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHA2-128s algorithm. + /// + public static SlhDsaAlgorithm SlhDsaSha2_128s { get; } = new SlhDsaAlgorithm("SLH-DSA-SHA2-128s", 16, 7856, Oids.SlhDsaSha2_128s); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-128s algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-128s algorithm. + /// + public static SlhDsaAlgorithm SlhDsaShake128s { get; } = new SlhDsaAlgorithm("SLH-DSA-SHAKE-128s", 16, 7856, Oids.SlhDsaShake_128s); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHA2-128f algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHA2-128f algorithm. + /// + public static SlhDsaAlgorithm SlhDsaSha2_128f { get; } = new SlhDsaAlgorithm("SLH-DSA-SHA2-128f", 16, 17088, Oids.SlhDsaSha2_128f); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-128f algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-128f algorithm. + /// + public static SlhDsaAlgorithm SlhDsaShake128f { get; } = new SlhDsaAlgorithm("SLH-DSA-SHAKE-128f", 16, 17088, Oids.SlhDsaShake_128f); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHA2-192s algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHA2-192s algorithm. + /// + public static SlhDsaAlgorithm SlhDsaSha2_192s { get; } = new SlhDsaAlgorithm("SLH-DSA-SHA2-192s", 24, 15616, Oids.SlhDsaSha2_192s); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-192s algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-192s algorithm. + /// + public static SlhDsaAlgorithm SlhDsaShake192s { get; } = new SlhDsaAlgorithm("SLH-DSA-SHAKE-192s", 24, 15616, Oids.SlhDsaShake_192s); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHA2-192f algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHA2-192f algorithm. + /// + public static SlhDsaAlgorithm SlhDsaSha2_192f { get; } = new SlhDsaAlgorithm("SLH-DSA-SHA2-192f", 24, 35664, Oids.SlhDsaSha2_192f); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-192f algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-192f algorithm. + /// + public static SlhDsaAlgorithm SlhDsaShake192f { get; } = new SlhDsaAlgorithm("SLH-DSA-SHAKE-192f", 24, 35664, Oids.SlhDsaShake_192f); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHA2-256s algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHA2-256s algorithm. + /// + public static SlhDsaAlgorithm SlhDsaSha2_256s { get; } = new SlhDsaAlgorithm("SLH-DSA-SHA2-256s", 32, 29792, Oids.SlhDsaSha2_256s); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-256s algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-256s algorithm. + /// + public static SlhDsaAlgorithm SlhDsaShake256s { get; } = new SlhDsaAlgorithm("SLH-DSA-SHAKE-256s", 32, 29792, Oids.SlhDsaShake_256s); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHA2-256f algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHA2-256f algorithm. + /// + public static SlhDsaAlgorithm SlhDsaSha2_256f { get; } = new SlhDsaAlgorithm("SLH-DSA-SHA2-256f", 32, 49856, Oids.SlhDsaSha2_256f); + + /// + /// Gets an SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-256f algorithm. + /// + /// + /// An SLH-DSA algorithm identifier for the SLH-DSA-SHAKE-256f algorithm. + /// + public static SlhDsaAlgorithm SlhDsaShake256f { get; } = new SlhDsaAlgorithm("SLH-DSA-SHAKE-256f", 32, 49856, Oids.SlhDsaShake_256f); + + internal static SlhDsaAlgorithm GetAlgorithmFromOid(string oid) + { + return oid switch + { + Oids.SlhDsaSha2_128s => SlhDsaSha2_128s, + Oids.SlhDsaShake_128s => SlhDsaShake128s, + Oids.SlhDsaSha2_128f => SlhDsaSha2_128f, + Oids.SlhDsaShake_128f => SlhDsaShake128f, + Oids.SlhDsaSha2_192s => SlhDsaSha2_192s, + Oids.SlhDsaShake_192s => SlhDsaShake192s, + Oids.SlhDsaSha2_192f => SlhDsaSha2_192f, + Oids.SlhDsaShake_192f => SlhDsaShake192f, + Oids.SlhDsaSha2_256s => SlhDsaSha2_256s, + Oids.SlhDsaShake_256s => SlhDsaShake256s, + Oids.SlhDsaSha2_256f => SlhDsaSha2_256f, + Oids.SlhDsaShake_256f => SlhDsaShake256f, + + _ => ThrowAlgorithmUnknown(oid), + }; + } + + [DoesNotReturn] + private static SlhDsaAlgorithm ThrowAlgorithmUnknown(string algorithmId) + { + throw new CryptographicException( + SR.Format(SR.Cryptography_UnknownAlgorithmIdentifier, algorithmId)); + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.NotSupported.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.NotSupported.cs new file mode 100644 index 00000000000000..42318fc267a8bc --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.NotSupported.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + internal sealed partial class SlhDsaImplementation : SlhDsa + { + internal static partial bool SupportsAny() => false; + + private SlhDsaImplementation(SlhDsaAlgorithm algorithm) : base(algorithm) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa GenerateKeyCore(SlhDsaAlgorithm info) => + throw new PlatformNotSupportedException(); + + // The instance override methods are unreachable, as the constructor will always throw. + protected override void SignDataCore(ReadOnlySpan data, ReadOnlySpan context, Span destination) => + throw new PlatformNotSupportedException(); + + protected override bool VerifyDataCore(ReadOnlySpan data, ReadOnlySpan context, ReadOnlySpan signature) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaPublicKeyCore(Span destination) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaSecretKeyCore(Span destination) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaPrivateSeedCore(Span destination) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportPublicKey(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportPkcs8PrivateKeyValue(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportSecretKey(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportSeed(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.OpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.OpenSsl.cs new file mode 100644 index 00000000000000..1d8d660aa3e77c --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.OpenSsl.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + internal sealed partial class SlhDsaImplementation : SlhDsa + { + internal static partial bool SupportsAny() => false; + + // TODO: Define this in terms of OpenSSL + private SlhDsaImplementation(/* SafeEvpPKeyHandle handle, */ SlhDsaAlgorithm algorithm) : base(algorithm) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa GenerateKeyCore(SlhDsaAlgorithm info) => + throw new PlatformNotSupportedException(); + + protected override void SignDataCore(ReadOnlySpan data, ReadOnlySpan context, Span destination) => + throw new PlatformNotSupportedException(); + + protected override bool VerifyDataCore(ReadOnlySpan data, ReadOnlySpan context, ReadOnlySpan signature) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaPublicKeyCore(Span destination) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaSecretKeyCore(Span destination) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaPrivateSeedCore(Span destination) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportPublicKey(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportPkcs8PrivateKeyValue(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportSecretKey(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportSeed(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.Windows.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.Windows.cs new file mode 100644 index 00000000000000..58f3e212c9d4c7 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.Windows.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + internal sealed partial class SlhDsaImplementation : SlhDsa + { + internal static partial bool SupportsAny() => false; + + // TODO: Define this in terms of Windows BCrypt.dll (ephemeral keys) + private SlhDsaImplementation(/* CngKey key, */ SlhDsaAlgorithm algorithm) : base(algorithm) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa GenerateKeyCore(SlhDsaAlgorithm info) => + throw new PlatformNotSupportedException(); + + protected override void SignDataCore(ReadOnlySpan data, ReadOnlySpan context, Span destination) => + throw new PlatformNotSupportedException(); + + protected override bool VerifyDataCore(ReadOnlySpan data, ReadOnlySpan context, ReadOnlySpan signature) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaPublicKeyCore(Span destination) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaSecretKeyCore(Span destination) => + throw new PlatformNotSupportedException(); + + protected override void ExportSlhDsaPrivateSeedCore(Span destination) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportPublicKey(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportPkcs8PrivateKeyValue(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportSecretKey(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + + internal static partial SlhDsa ImportSeed(SlhDsaAlgorithm info, ReadOnlySpan source) => + throw new PlatformNotSupportedException(); + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.cs new file mode 100644 index 00000000000000..8a9d0181876c1b --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Security.Cryptography +{ + [Experimental(Experimentals.PostQuantumCryptographyDiagId)] + internal sealed partial class SlhDsaImplementation : SlhDsa + { + internal static partial bool SupportsAny(); + internal static partial SlhDsa GenerateKeyCore(SlhDsaAlgorithm info); + internal static partial SlhDsa ImportPublicKey(SlhDsaAlgorithm info, ReadOnlySpan source); + internal static partial SlhDsa ImportPkcs8PrivateKeyValue(SlhDsaAlgorithm info, ReadOnlySpan source); + internal static partial SlhDsa ImportSecretKey(SlhDsaAlgorithm info, ReadOnlySpan source); + internal static partial SlhDsa ImportSeed(SlhDsaAlgorithm info, ReadOnlySpan source); + } +} diff --git a/src/libraries/Common/src/System/Threading/OpenExistingResult.cs b/src/libraries/Common/src/System/Threading/OpenExistingResult.cs index 16d9abaf3f781c..67cf9cbeb6e28e 100644 --- a/src/libraries/Common/src/System/Threading/OpenExistingResult.cs +++ b/src/libraries/Common/src/System/Threading/OpenExistingResult.cs @@ -12,6 +12,7 @@ internal enum OpenExistingResult Success, NameNotFound, PathNotFound, - NameInvalid + NameInvalid, + ObjectIncompatibleWithCurrentUserOnly } } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs index c5bed9f4567390..b0a274ad787fcf 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs @@ -244,11 +244,6 @@ await LoopbackServerFactory.CreateServerAsync(async (server, url) => var req = new HttpRequestMessage(HttpMethod.Get, url) { Version = UseVersion }; req.Headers.ConnectionClose = connectionClose; -#if TARGET_BROWSER - var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); - req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); -#endif - Task getResponse = client.SendAsync(TestAsync, req, HttpCompletionOption.ResponseHeadersRead, cts.Token); await ValidateClientCancellationAsync(async () => { diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index b45f2a5b232b72..946381dee0b4b8 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -1005,12 +1005,9 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; if (PlatformDetection.IsBrowser) { - if (enableWasmStreaming) - { #if !NETFRAMEWORK - request.Options.Set(new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"), true); + request.Options.Set(new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"), enableWasmStreaming); #endif - } } using (var client = new HttpMessageInvoker(CreateHttpClientHandler())) @@ -1239,7 +1236,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => // Boolean properties returning correct values Assert.True(responseStream.CanRead); Assert.False(responseStream.CanWrite); - Assert.Equal(PlatformDetection.IsBrowser, responseStream.CanSeek); + Assert.False(responseStream.CanSeek); // Not supported operations Assert.Throws(() => responseStream.BeginWrite(new byte[1], 0, 1, null, null)); @@ -1270,11 +1267,14 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => Assert.Throws(() => { responseStream.CopyToAsync(Stream.Null, -1, default); }); Assert.Throws(() => { responseStream.CopyToAsync(nonWritableStream, 100, default); }); Assert.Throws(() => { responseStream.CopyToAsync(disposedStream, 100, default); }); - Assert.Throws(() => responseStream.Read(null, 0, 100)); - Assert.Throws(() => responseStream.Read(new byte[1], -1, 1)); - Assert.ThrowsAny(() => responseStream.Read(new byte[1], 2, 1)); - Assert.Throws(() => responseStream.Read(new byte[1], 0, -1)); - Assert.ThrowsAny(() => responseStream.Read(new byte[1], 0, 2)); + if (PlatformDetection.IsNotBrowser) + { + Assert.Throws(() => responseStream.Read(null, 0, 100)); + Assert.Throws(() => responseStream.Read(new byte[1], -1, 1)); + Assert.ThrowsAny(() => responseStream.Read(new byte[1], 2, 1)); + Assert.Throws(() => responseStream.Read(new byte[1], 0, -1)); + Assert.ThrowsAny(() => responseStream.Read(new byte[1], 0, 2)); + } Assert.Throws(() => responseStream.BeginRead(null, 0, 100, null, null)); Assert.Throws(() => responseStream.BeginRead(new byte[1], -1, 1, null, null)); Assert.ThrowsAny(() => responseStream.BeginRead(new byte[1], 2, 1, null, null)); @@ -1284,29 +1284,37 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => Assert.Throws(() => { responseStream.CopyTo(null); }); Assert.Throws(() => { responseStream.CopyToAsync(null, 100, default); }); Assert.Throws(() => { responseStream.CopyToAsync(null, 100, default); }); - Assert.Throws(() => { responseStream.Read(null, 0, 100); }); Assert.Throws(() => { responseStream.ReadAsync(null, 0, 100, default); }); Assert.Throws(() => { responseStream.BeginRead(null, 0, 100, null, null); }); // Empty reads var buffer = new byte[1]; - Assert.Equal(-1, responseStream.ReadByte()); - Assert.Equal(0, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, 1, null)); + if (PlatformDetection.IsNotBrowser) + { + Assert.Equal(-1, responseStream.ReadByte()); + Assert.Equal(0, await Task.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, 1, null)); + } #if !NETFRAMEWORK Assert.Equal(0, await responseStream.ReadAsync(new Memory(buffer))); #endif Assert.Equal(0, await responseStream.ReadAsync(buffer, 0, 1)); + if (PlatformDetection.IsNotBrowser) + { #if !NETFRAMEWORK - Assert.Equal(0, responseStream.Read(new Span(buffer))); + Assert.Equal(0, responseStream.Read(new Span(buffer))); #endif - Assert.Equal(0, responseStream.Read(buffer, 0, 1)); + Assert.Equal(0, responseStream.Read(buffer, 0, 1)); + } // Empty copies var ms = new MemoryStream(); await responseStream.CopyToAsync(ms); Assert.Equal(0, ms.Length); - responseStream.CopyTo(ms); - Assert.Equal(0, ms.Length); + if (PlatformDetection.IsNotBrowser) + { + responseStream.CopyTo(ms); + Assert.Equal(0, ms.Length); + } } } }, @@ -1322,9 +1330,6 @@ public async Task ReadAsStreamAsync_StreamingCancellation() await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; -#if !NETFRAMEWORK - request.Options.Set(new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"), true); -#endif var cts = new CancellationTokenSource(); using (var client = new HttpMessageInvoker(CreateHttpClientHandler())) diff --git a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs index 61958c04a26b0c..786ee3c4ccf6ad 100644 --- a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs @@ -25,6 +25,8 @@ public static IEnumerable RemoteServersAndReadModes() { for (int i = 0; i < 8; i++) { + if (PlatformDetection.IsBrowser && i is 0 or 2 or 4 or 5 or 6) continue; // ignore sync reads + yield return new object[] { remoteServer, i }; } } @@ -176,10 +178,13 @@ public async Task GetStreamAsync_ReadZeroBytes_Success(Configuration.Http.Remote using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer)) using (Stream stream = await client.GetStreamAsync(remoteServer.EchoUri)) { - Assert.Equal(0, stream.Read(new byte[1], 0, 0)); + if (PlatformDetection.IsNotBrowser) + { + Assert.Equal(0, stream.Read(new byte[1], 0, 0)); #if !NETFRAMEWORK - Assert.Equal(0, stream.Read(new Span(new byte[1], 0, 0))); + Assert.Equal(0, stream.Read(new Span(new byte[1], 0, 0))); #endif + } Assert.Equal(0, await stream.ReadAsync(new byte[1], 0, 0)); } } @@ -200,7 +205,7 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders cts.Cancel(); // Verify that the task completed. - Assert.True(((IAsyncResult)task).AsyncWaitHandle.WaitOne(new TimeSpan(0, 5, 0))); + Assert.Same(task, await Task.WhenAny(task, Task.Delay(TimeSpan.FromMinutes(5)))); Assert.True(task.IsCompleted, "Task was not yet completed"); // Verify that the task completed successfully or is canceled. @@ -327,12 +332,10 @@ public async Task BrowserHttpHandler_StreamingResponseAbort(HttpMethod method, s public async Task BrowserHttpHandler_Streaming() { var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingRequest"); - var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); var req = new HttpRequestMessage(HttpMethod.Post, Configuration.Http.RemoteHttp2Server.BaseUri + "echobody.ashx"); req.Options.Set(WebAssemblyEnableStreamingRequestKey, true); - req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); byte[] body = new byte[1024 * 1024]; Random.Shared.NextBytes(body); @@ -578,16 +581,12 @@ public async Task BrowserHttpHandler_StreamingRequest_Http1Fails() } [OuterLoop] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] public async Task BrowserHttpHandler_StreamingResponseLarge() { - var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); - var size = 1500 * 1024 * 1024; var req = new HttpRequestMessage(HttpMethod.Get, Configuration.Http.RemoteSecureHttp11Server.BaseUri + "large.ashx?size=" + size); - req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); - using (HttpClient client = CreateHttpClientForRemoteServer(Configuration.Http.RemoteSecureHttp11Server)) // we need to switch off Response buffering of default ResponseContentRead option using (HttpResponseMessage response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead)) @@ -605,7 +604,7 @@ public async Task BrowserHttpHandler_StreamingResponseLarge() int fetchedCount = 0; do { - // with WebAssemblyEnableStreamingResponse option set, we will be using https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader/read + // we will be using https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader/read fetchedCount = await stream.ReadAsync(buffer, 0, buffer.Length); totalCount += fetchedCount; } while (fetchedCount != 0); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/ByteUtils.cs b/src/libraries/Common/tests/System/Security/Cryptography/ByteUtils.cs index 569ef966f13cb6..0b7e708f3eb22b 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/ByteUtils.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/ByteUtils.cs @@ -24,6 +24,9 @@ internal static byte[] AsciiBytes(string s) internal static byte[] HexToByteArray(this string hexString) { +#if NET9_0_OR_GREATER + return Convert.FromHexString(hexString); +#else byte[] bytes = new byte[hexString.Length / 2]; for (int i = 0; i < hexString.Length; i += 2) @@ -33,6 +36,7 @@ internal static byte[] HexToByteArray(this string hexString) } return bytes; +#endif } internal static string ByteArrayToHex(this byte[] bytes) @@ -52,6 +56,9 @@ internal static string ByteArrayToHex(this ReadOnlyMemory bytes) internal static string ByteArrayToHex(this ReadOnlySpan bytes) { +#if NET9_0_OR_GREATER + return Convert.ToHexString(bytes); +#else StringBuilder builder = new StringBuilder(bytes.Length * 2); for (int i = 0; i < bytes.Length; i++) @@ -60,20 +67,43 @@ internal static string ByteArrayToHex(this ReadOnlySpan bytes) } return builder.ToString(); +#endif } internal static byte[] RepeatByte(byte b, int count) { + byte[] value = new byte[count]; +#if NET + value.AsSpan().Fill(b); +#else for (int i = 0; i < count; i++) { value[i] = b; } +#endif return value; } + internal static bool ContainsAnyExcept(this ReadOnlySpan bytes, byte value) + { +#if NET9_0_OR_GREATER + return bytes.ContainsAnyExcept(value); +#else + foreach (byte b in bytes) + { + if (b != value) + { + return true; + } + } + + return false; +#endif + } + internal static string PemEncode(string label, byte[] data) { #if NET diff --git a/src/libraries/Common/tests/System/Security/Cryptography/MLKemAlgorithmTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/MLKemAlgorithmTests.cs new file mode 100644 index 00000000000000..6d55a15c59774d --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/MLKemAlgorithmTests.cs @@ -0,0 +1,74 @@ +// 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.Globalization; +using Microsoft.DotNet.XUnitExtensions; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public static partial class MLKemAlgorithmTests + { + [Fact] + public static void Algorithms_AreSame() + { + Assert.Same(MLKemAlgorithm.MLKem512, MLKemAlgorithm.MLKem512); + Assert.Same(MLKemAlgorithm.MLKem768, MLKemAlgorithm.MLKem768); + Assert.Same(MLKemAlgorithm.MLKem1024, MLKemAlgorithm.MLKem1024); + } + + [Theory] + [MemberData(nameof(MLKemAlgorithms))] + public static void Algorithms_Equal(MLKemAlgorithm algorithm) + { + Assert.True(algorithm.Equals(algorithm), nameof(algorithm.Equals)); + Assert.True(algorithm.Equals((object)algorithm), nameof(algorithm.Equals)); + Assert.False(algorithm.Equals(null), nameof(algorithm.Equals)); + } + + [Theory] + [MemberData(nameof(MLKemAlgorithms))] + public static void Algorithms_GetHashCode(MLKemAlgorithm algorithm) + { + Assert.Equal(algorithm.Name.GetHashCode(), algorithm.GetHashCode()); + } + + [Fact] + public static void Algorithms_Equality() + { + Assert.True(MLKemAlgorithm.MLKem512 == MLKemAlgorithm.MLKem512, "MLKemAlgorithm.MLKem512 == MLKemAlgorithm.MLKem512"); + Assert.True(MLKemAlgorithm.MLKem768 == MLKemAlgorithm.MLKem768, "MLKemAlgorithm.MLKem768 == MLKemAlgorithm.MLKem768"); + Assert.True(MLKemAlgorithm.MLKem1024 == MLKemAlgorithm.MLKem1024, "MLKemAlgorithm.MLKem1024 == MLKemAlgorithm.MLKem1024"); + + Assert.False(MLKemAlgorithm.MLKem512 == MLKemAlgorithm.MLKem768, "MLKemAlgorithm.MLKem512 == MLKemAlgorithm.MLKem768"); + Assert.False(MLKemAlgorithm.MLKem768 == MLKemAlgorithm.MLKem1024, "MLKemAlgorithm.MLKem768 == MLKemAlgorithm.MLKem1024"); + Assert.False(MLKemAlgorithm.MLKem1024 == MLKemAlgorithm.MLKem512, "MLKemAlgorithm.MLKem1024 == MLKemAlgorithm.MLKem512"); + } + + [Fact] + public static void Algorithms_Inquality() + { + Assert.False(MLKemAlgorithm.MLKem512 != MLKemAlgorithm.MLKem512, "MLKemAlgorithm.MLKem512 != MLKemAlgorithm.MLKem512"); + Assert.False(MLKemAlgorithm.MLKem768 != MLKemAlgorithm.MLKem768, "MLKemAlgorithm.MLKem768 != MLKemAlgorithm.MLKem768"); + Assert.False(MLKemAlgorithm.MLKem1024 != MLKemAlgorithm.MLKem1024, "MLKemAlgorithm.MLKem1024 != MLKemAlgorithm.MLKem1024"); + + Assert.True(MLKemAlgorithm.MLKem512 != MLKemAlgorithm.MLKem768, "MLKemAlgorithm.MLKem512 != MLKemAlgorithm.MLKem768"); + Assert.True(MLKemAlgorithm.MLKem768 != MLKemAlgorithm.MLKem1024, "MLKemAlgorithm.MLKem768 != MLKemAlgorithm.MLKem1024"); + Assert.True(MLKemAlgorithm.MLKem1024 != MLKemAlgorithm.MLKem512, "MLKemAlgorithm.MLKem1024 != MLKemAlgorithm.MLKem512"); + } + + public static IEnumerable MLKemAlgorithms + { + get + { + return + [ + [ MLKemAlgorithm.MLKem512 ], + [ MLKemAlgorithm.MLKem768 ], + [ MLKemAlgorithm.MLKem1024 ], + ]; + } + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.ArgValidation.cs b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.ArgValidation.cs new file mode 100644 index 00000000000000..8d3861a936e231 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.ArgValidation.cs @@ -0,0 +1,217 @@ +// 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.Globalization; +using Microsoft.DotNet.XUnitExtensions; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public static partial class MLKemTests + { + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void Generate_NullAlgorithm() + { + AssertExtensions.Throws("algorithm", static () => MLKem.GenerateKey(null)); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ImportPrivateSeed_NullAlgorithm() + { + AssertExtensions.Throws("algorithm", static () => + MLKem.ImportPrivateSeed(null, new byte[MLKemAlgorithm.MLKem512.PrivateSeedSizeInBytes])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ImportPrivateSeed_WrongSize(MLKemAlgorithm algorithm) + { + AssertExtensions.Throws("source", () => + MLKem.ImportPrivateSeed(algorithm, new byte[algorithm.PrivateSeedSizeInBytes + 1])); + + AssertExtensions.Throws("source", () => + MLKem.ImportPrivateSeed(algorithm, new byte[algorithm.PrivateSeedSizeInBytes - 1])); + + AssertExtensions.Throws("source", () => + MLKem.ImportPrivateSeed(algorithm, [])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ImportDecapsulationKey_NullAlgorithm() + { + AssertExtensions.Throws("algorithm", static () => + MLKem.ImportDecapsulationKey(null, new byte[MLKemAlgorithm.MLKem512.DecapsulationKeySizeInBytes])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ImportDecapsulationKey_WrongSize(MLKemAlgorithm algorithm) + { + AssertExtensions.Throws("source", () => + MLKem.ImportDecapsulationKey(algorithm, new byte[algorithm.DecapsulationKeySizeInBytes + 1])); + + AssertExtensions.Throws("source", () => + MLKem.ImportDecapsulationKey(algorithm, new byte[algorithm.DecapsulationKeySizeInBytes - 1])); + + AssertExtensions.Throws("source", () => + MLKem.ImportDecapsulationKey(algorithm, [])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ImportEncapsulationKey_NullAlgorithm() + { + AssertExtensions.Throws("algorithm", static () => + MLKem.ImportEncapsulationKey(null, new byte[MLKemAlgorithm.MLKem512.EncapsulationKeySizeInBytes])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ImportEncapsulationKey_WrongSize(MLKemAlgorithm algorithm) + { + AssertExtensions.Throws("source", () => + MLKem.ImportEncapsulationKey(algorithm, new byte[algorithm.EncapsulationKeySizeInBytes + 1])); + + AssertExtensions.Throws("source", () => + MLKem.ImportEncapsulationKey(algorithm, new byte[algorithm.EncapsulationKeySizeInBytes - 1])); + + AssertExtensions.Throws("source", () => + MLKem.ImportEncapsulationKey(algorithm, [])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void Encapsulate_WrongSize(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + + AssertExtensions.Throws("ciphertext", () => kem.Encapsulate( + new byte[algorithm.CiphertextSizeInBytes + 1], + new byte[algorithm.SharedSecretSizeInBytes])); + + AssertExtensions.Throws("ciphertext", () => kem.Encapsulate( + new byte[algorithm.CiphertextSizeInBytes - 1], + new byte[algorithm.SharedSecretSizeInBytes])); + + AssertExtensions.Throws("ciphertext", () => kem.Encapsulate( + [], + new byte[algorithm.SharedSecretSizeInBytes])); + + AssertExtensions.Throws("sharedSecret", () => kem.Encapsulate( + new byte[algorithm.CiphertextSizeInBytes], + new byte[algorithm.SharedSecretSizeInBytes + 1])); + + AssertExtensions.Throws("sharedSecret", () => kem.Encapsulate( + new byte[algorithm.CiphertextSizeInBytes], + new byte[algorithm.SharedSecretSizeInBytes - 1])); + + AssertExtensions.Throws("sharedSecret", () => kem.Encapsulate( + new byte[algorithm.CiphertextSizeInBytes], + [])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void Decapsulate_WrongSize(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + + AssertExtensions.Throws("ciphertext", () => kem.Decapsulate( + new byte[algorithm.CiphertextSizeInBytes + 1], + new byte[algorithm.SharedSecretSizeInBytes])); + + AssertExtensions.Throws("ciphertext", () => kem.Decapsulate( + new byte[algorithm.CiphertextSizeInBytes - 1], + new byte[algorithm.SharedSecretSizeInBytes])); + + AssertExtensions.Throws("ciphertext", () => kem.Decapsulate( + [], + new byte[algorithm.SharedSecretSizeInBytes])); + + AssertExtensions.Throws("sharedSecret", () => kem.Decapsulate( + new byte[algorithm.CiphertextSizeInBytes], + new byte[algorithm.SharedSecretSizeInBytes + 1])); + + AssertExtensions.Throws("sharedSecret", () => kem.Decapsulate( + new byte[algorithm.CiphertextSizeInBytes], + new byte[algorithm.SharedSecretSizeInBytes - 1])); + + AssertExtensions.Throws("sharedSecret", () => kem.Decapsulate( + new byte[algorithm.CiphertextSizeInBytes], + [])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ExportPrivateSeed_WrongSize(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + + AssertExtensions.Throws("destination", () => kem.ExportPrivateSeed( + new byte[algorithm.PrivateSeedSizeInBytes + 1])); + + AssertExtensions.Throws("destination", () => kem.ExportPrivateSeed( + new byte[algorithm.PrivateSeedSizeInBytes - 1])); + + AssertExtensions.Throws("destination", () => kem.ExportPrivateSeed( + [])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ExportDecapsulationKey_WrongSize(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + + AssertExtensions.Throws("destination", () => kem.ExportDecapsulationKey( + new byte[algorithm.DecapsulationKeySizeInBytes + 1])); + + AssertExtensions.Throws("destination", () => kem.ExportDecapsulationKey( + new byte[algorithm.DecapsulationKeySizeInBytes - 1])); + + AssertExtensions.Throws("destination", () => kem.ExportDecapsulationKey( + [])); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ExportEncapsulationKey_WrongSize(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + + AssertExtensions.Throws("destination", () => kem.ExportEncapsulationKey( + new byte[algorithm.EncapsulationKeySizeInBytes + 1])); + + AssertExtensions.Throws("destination", () => kem.ExportEncapsulationKey( + new byte[algorithm.EncapsulationKeySizeInBytes - 1])); + + AssertExtensions.Throws("destination", () => kem.ExportEncapsulationKey( + [])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void UseAfterDispose() + { + MLKem kem = MLKem.GenerateKey(MLKemAlgorithm.MLKem512); + kem.Dispose(); + kem.Dispose(); // Assert.NoThrow + + Assert.Throws(() => kem.Encapsulate( + new byte[MLKemAlgorithm.MLKem512.CiphertextSizeInBytes], + new byte[MLKemAlgorithm.MLKem512.SharedSecretSizeInBytes])); + + Assert.Throws(() => kem.Decapsulate( + new byte[MLKemAlgorithm.MLKem512.CiphertextSizeInBytes], + new byte[MLKemAlgorithm.MLKem512.SharedSecretSizeInBytes])); + + Assert.Throws(() => kem.ExportPrivateSeed( + new byte[MLKemAlgorithm.MLKem512.PrivateSeedSizeInBytes])); + + Assert.Throws(() => kem.ExportDecapsulationKey( + new byte[MLKemAlgorithm.MLKem512.DecapsulationKeySizeInBytes])); + + Assert.Throws(() => kem.ExportEncapsulationKey( + new byte[MLKemAlgorithm.MLKem512.EncapsulationKeySizeInBytes])); + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.Encapsulation.cs b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.Encapsulation.cs new file mode 100644 index 00000000000000..6423acf8141330 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.Encapsulation.cs @@ -0,0 +1,284 @@ +// 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 Microsoft.DotNet.XUnitExtensions; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public static partial class MLKemTests + { + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void DecapsulateVectors() + { + foreach (MLKemTestDecapsulationVector vector in MLKemDecapsulationTestVectors) + { + byte[] decapsulationKeyBytes = vector.DecapsulationKey.HexToByteArray(); + byte[] encapsulationKeyBytes = vector.EncapsulationKey.HexToByteArray(); + + using MLKem kem = MLKem.ImportDecapsulationKey(vector.Algorithm, decapsulationKeyBytes); + byte[] exportedEncapsulationKey = new byte[vector.Algorithm.EncapsulationKeySizeInBytes]; + kem.ExportEncapsulationKey(exportedEncapsulationKey); + AssertExtensions.SequenceEqual(encapsulationKeyBytes, exportedEncapsulationKey); + + byte[] sharedSecretBuffer = new byte[vector.Algorithm.SharedSecretSizeInBytes]; + byte[] expectedSharedSecret = vector.SharedSecret.HexToByteArray(); + kem.Decapsulate(vector.Ciphertext.HexToByteArray(), sharedSecretBuffer); + + AssertExtensions.SequenceEqual(expectedSharedSecret, sharedSecretBuffer); + } + } + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [InlineData(true)] + [InlineData(false)] + public static void DecapsulateVectors_OverlappingBuffers(bool partial) + { + foreach (MLKemTestDecapsulationVector vector in MLKemDecapsulationTestVectors) + { + byte[] decapsulationKeyBytes = vector.DecapsulationKey.HexToByteArray(); + byte[] ciphertextBytes = vector.Ciphertext.HexToByteArray(); + using MLKem kem = MLKem.ImportDecapsulationKey(vector.Algorithm, decapsulationKeyBytes); + + Span sharedSecretBuffer = ciphertextBytes.AsSpan( + partial ? 1 : 0, + vector.Algorithm.SharedSecretSizeInBytes); + + ReadOnlySpan expectedSharedSecret = vector.SharedSecret.HexToByteArray(); + + kem.Decapsulate(ciphertextBytes, sharedSecretBuffer); + AssertExtensions.SequenceEqual(expectedSharedSecret, sharedSecretBuffer); + } + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void Decapsulate_OnlyEncapsulationKey() + { + foreach (MLKemTestDecapsulationVector vector in MLKemDecapsulationTestVectors) + { + byte[] encapsulationKeyBytes = vector.EncapsulationKey.HexToByteArray(); + using MLKem kem = MLKem.ImportEncapsulationKey(vector.Algorithm, encapsulationKeyBytes); + byte[] sharedSecretBuffer = new byte[vector.Algorithm.SharedSecretSizeInBytes]; + + Assert.ThrowsAny(() => kem.Decapsulate( + vector.Ciphertext.HexToByteArray(), + sharedSecretBuffer)); + } + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void DecapsulateVectors_ModifiedCiphertext() + { + foreach (MLKemTestDecapsulationVector vector in MLKemDecapsulationTestVectors) + { + byte[] decapsulationKeyBytes = vector.DecapsulationKey.HexToByteArray(); + using MLKem kem = MLKem.ImportDecapsulationKey(vector.Algorithm, decapsulationKeyBytes); + + byte[] sharedSecretBuffer = new byte[vector.Algorithm.SharedSecretSizeInBytes]; + byte[] expectedSharedSecret = vector.SharedSecret.HexToByteArray(); + byte[] ciphertext = vector.Ciphertext.HexToByteArray(); + + Tamper(ciphertext); + kem.Decapsulate(ciphertext, sharedSecretBuffer); + + AssertExtensions.SequenceNotEqual(expectedSharedSecret, sharedSecretBuffer); + } + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void Encapsulate_NonDeterministic(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + + byte[] ciphertext1 = new byte[algorithm.CiphertextSizeInBytes]; + byte[] sharedSecret1 = new byte[algorithm.SharedSecretSizeInBytes]; + byte[] ciphertext2 = new byte[algorithm.CiphertextSizeInBytes]; + byte[] sharedSecret2 = new byte[algorithm.SharedSecretSizeInBytes]; + kem.Encapsulate(ciphertext1, sharedSecret1); + kem.Encapsulate(ciphertext2, sharedSecret2); + AssertExtensions.SequenceNotEqual(ciphertext1, ciphertext2); + AssertExtensions.SequenceNotEqual(sharedSecret1, sharedSecret2); + } + + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [InlineData(false)] + [InlineData(true)] + public static void Encapsulate_Overlaps(bool partial) + { + using MLKem kem = MLKem.GenerateKey(MLKemAlgorithm.MLKem512); + byte[] buffer = new byte[MLKemAlgorithm.MLKem512.CiphertextSizeInBytes]; + + Assert.Throws(() => + { + Span sharedSecret = buffer.AsSpan(partial ? 1 : 0, MLKemAlgorithm.MLKem512.SharedSecretSizeInBytes); + Span ciphertext = buffer.AsSpan(0, MLKemAlgorithm.MLKem512.CiphertextSizeInBytes); + kem.Encapsulate(ciphertext, sharedSecret); + }); + } + + private static void Tamper(Span buffer) + { + buffer[buffer.Length - 1] ^= 0xFF; + } + + public record MLKemTestDecapsulationVector(MLKemAlgorithm Algorithm, string EncapsulationKey, string DecapsulationKey, string Ciphertext, string SharedSecret); + + public static IEnumerable MLKemDecapsulationTestVectors + { + get + { + // Vectors that have zeros to ensure they round-trip correctly. + yield return new + ( + MLKemAlgorithm.MLKem512, + "002645126709F87B5C6DF9116BA175020895C5C3031AFBBFCDF95AF2839095396A21F23BB1232091EB8F983BCBC95400D4A335C555187FC2311B79402A261AEB276F1DE4CA62458D5AA772F0C25C3A4824DC095AB63584CF863CD4DCA9736CAAFADC1CA2249475946B4BF4B208334EC419C916157E84C9056DE713CD055D69009D295C1C1A6A07E008297BD1B167D4641ED946E0432CDD285A5E9794E6D3CF7422012999AC50C42CACC68E659C37CDD93A70166192719CC0E22D1317C1A3F00715004D505A2B606055626421611BCC64425D2F1452E32B8D68B2584A66180D648B8925467DB306DFC39859EAC383AB60B1F9793051C8AE2151621166B3F862B52C44CD796602C80F45D3C095749EA9D65EB6024752761B364891C7669441E3AE30E43178D13B2D1C3B3AFC999FD4B444E3591320A766ACCA6C4059B8F34289211F82C5A333EA029154C716B640AAC1BC7D516DFB00881EFA9472725A9BC57DD1781E7A0689C5E399CB1B1F41A031D33C3528D421047A48A29C91222074FCC538814242C78520D201171615518D36CC98BC885F2127CE182BA15041B07737A8ABA7ACC4C0A22624D49C4854674A54F11AFFB03D7AE6B90E7413B854A131A6496D02744A66BA7E4B8DF973577EA902E7D1B7CA40CA7AA63F2C04B5D6DA87A735148F003F78395010B11AC9C87E1AB7BDCD8B18CEBA7226E6899DD3A7F2937686D52F7BA21D1A439A7DA06B367C240F644058C434337880FFE79DE9F2A277B13B0B82907E22104F0134423A3F06167FF8254276922361C0368CBC73BFB8C35CD1C0A79076C420B053E604C7098C74344F9A5094983B17ADD46C34984CA317CDED2B0A1ECC12C52124655389FDB813DBBA8B04310259F0A9EE57B03AB04B18079ABFA336FFF854DA70BD82760A39FB3D9BB2837DF052E925449C88680242B73A39AB9D332A9C0371CD06663FC6A65968CA27663E44984B91C8B51A2CB0B6364CCE2097DB286E01FB8D2C871472C68117EA6497196F5F56A3CE778D48B687DAF440BB483748B7C2F0889F02DAB06EC64F33E59E49931A20084C7E78563A766B5223909DC385C5BC4BD8AFF51B5CC52F60FD181D8AC43537254ABC2F29E8FCB8698CD4", + "00E5CDA3A6960283140B49775D0111591493BD0A8C002C1701B53442FAB2A6C7C60B7AB64F1B90104460986803C8C464FA4AA334513887F28A7A4810073301ED40BACD4B1123D73679F63735D17F2EF39B40B92A0A65A170A7A14721C8D23350FE1B90C913C7955A5E3DDB701417C6C505667377A611AA26F5AC981C4953A058BC51E1519B47780702A65407722B9C32BC4819181B675C05AE55116C96B084E58CAFAA5BA1FB9AA893C2B4C399B6C1503AD7782FF6568EEE402451C874EBB8A4417A2AF04A102ABC7D4064BF7E451B81508ECFF32529491126536D64A65142F9AD804881B802433F89C3C38701DCC670628A7E8DCB77F5086C972397D777982B7C420ACA22492720D218B69AAC36A5509FEEAC0324BB9E3263B38251C8BEF95BCADC953749C3F4B886EFC8A880366177D8A45E3C433809C7D5889893C588B5216E3C47683D79318BB90E20EC09F481B0AD77B6433773458C24FDE361AE050BE76959A069530771AC66D4BEA1F4285C462260C48EC894AC444582DA3C1F4DBC03FB6046AEF9BE8DE01A479156DC200FED2518E36A7EC4915AF7E59096037C35B5B3F1C4C8CA96C30A372B8D72B54E91B57E8050B464B27AB671B2EC44D6244020D1098709AB5A79A2B5CC47CCF3480DB0BE27509C162CCB842671E3D5BB571986BA02548A81668F41BC5F6A7C4F66639262CD37C69FAC6BA024183B1D4902773C82F9156EADF17E7057B8FCCA21D8C895A92B080879B49A001DF8E88FB4F667D069CDCDC237324A51297224DEF542F65904F7FCBC4ED66A1BA90321172C3570BCDA36415DE93522984C0CAB3EF1819A31808B294ACFF1D517E045A0D2D59BD1E1374DA3AE97F09D6720C0516B9CC4352A2CD6479309335C300E4596AF5424B5E7D4A5FF06685481407FAB8AB32B0CA336886F5892135B6D49906DB9497244C7983AD6A474194329081AB26920724B317DDB59FD43108F97BDDBEA49E6C7A681A11ACF374AD5AC01443203A53281C143114A19CE2CE427A78C1B24A603372BC1A3E16ED826639D294047F89CFEE17CC1E00CB69A0EA71C20B37A4C208C5FB9CA44002645126709F87B5C6DF9116BA175020895C5C3031AFBBFCDF95AF2839095396A21F23BB1232091EB8F983BCBC95400D4A335C555187FC2311B79402A261AEB276F1DE4CA62458D5AA772F0C25C3A4824DC095AB63584CF863CD4DCA9736CAAFADC1CA2249475946B4BF4B208334EC419C916157E84C9056DE713CD055D69009D295C1C1A6A07E008297BD1B167D4641ED946E0432CDD285A5E9794E6D3CF7422012999AC50C42CACC68E659C37CDD93A70166192719CC0E22D1317C1A3F00715004D505A2B606055626421611BCC64425D2F1452E32B8D68B2584A66180D648B8925467DB306DFC39859EAC383AB60B1F9793051C8AE2151621166B3F862B52C44CD796602C80F45D3C095749EA9D65EB6024752761B364891C7669441E3AE30E43178D13B2D1C3B3AFC999FD4B444E3591320A766ACCA6C4059B8F34289211F82C5A333EA029154C716B640AAC1BC7D516DFB00881EFA9472725A9BC57DD1781E7A0689C5E399CB1B1F41A031D33C3528D421047A48A29C91222074FCC538814242C78520D201171615518D36CC98BC885F2127CE182BA15041B07737A8ABA7ACC4C0A22624D49C4854674A54F11AFFB03D7AE6B90E7413B854A131A6496D02744A66BA7E4B8DF973577EA902E7D1B7CA40CA7AA63F2C04B5D6DA87A735148F003F78395010B11AC9C87E1AB7BDCD8B18CEBA7226E6899DD3A7F2937686D52F7BA21D1A439A7DA06B367C240F644058C434337880FFE79DE9F2A277B13B0B82907E22104F0134423A3F06167FF8254276922361C0368CBC73BFB8C35CD1C0A79076C420B053E604C7098C74344F9A5094983B17ADD46C34984CA317CDED2B0A1ECC12C52124655389FDB813DBBA8B04310259F0A9EE57B03AB04B18079ABFA336FFF854DA70BD82760A39FB3D9BB2837DF052E925449C88680242B73A39AB9D332A9C0371CD06663FC6A65968CA27663E44984B91C8B51A2CB0B6364CCE2097DB286E01FB8D2C871472C68117EA6497196F5F56A3CE778D48B687DAF440BB483748B7C2F0889F02DAB06EC64F33E59E49931A20084C7E78563A766B5223909DC385C5BC4BD8AFF51B5CC52F60FD181D8AC43537254ABC2F29E8FCB8698CD4C74CD655ECCF259367D8B329389410E01AFB493B6A1D936E1F3D2F8E8CC43B72226FD2493AF33A6A92282E3FF0E5BA8AB9F09529C53671CBA1D98981DA8FE800", + "0064E3F787270054815A894CF8029A8E0FAC063176FDC2D6A1879A58A3564BF51CF8114476FB62A9F9F1A4C685A2BED8DDF330AFDC450465C78DCC29B6D1342A9835980C0CC9361254C42E61B17C21772DC304F50C0ED1BAEB0DDF9717720E6F2AB7E630BDF84CEB61774C1A41CBC130683B6139FC3FCBE67DE6E1C302B412E5429F821648E43FF264DE7C694E2ACCFFCB8026E5F2D4DC0744AD7516403804ED7B3097B6E7D5F6434923F24B71328F357A0D5220399DCDF1DABC0C77A19744A015D0DD29644E1242921ED699C234E7D64BCC45F0426BBA9BAED9E734E9ABBEACD7C9798C520002DF4589C2858C7BC3310CA39285E4E4B42BF6EDFB7D9C65288FFEF35433DEE0E168DC15FE66DA2001959D88CF6DD6F5017899CE5B208EE664503CFBA74C836C0FBEC7D3C94C64035327912199418B748DE629AE2438185147A44F8B3F12EEF939F85331833E6D802B7469D57926EAC1044CF8B5F76A4522EDD4DFA97437451582A04C0D406128AA054E1EE09EF0B328B36E3B0DDB4C0761469A6B38A52D7A139F4E9D80F4EBAAD5EEFCD024C60C8771B425B48F776B6F1D6AD57C2ACAB1C642F504B77E6C7E9428D8F2BF58C8F57D1E2EB5CC12728591D9DF0DAC723BDA312F451C82905498CF002A33A8FAE34463763D13F78EF40EA4587C5737810A76AEC4F532B80F6529F271EE49F2C084E62737CBE645AF3E7ECFBCEF97A17F7A7E8C8A8C7A1B48431820041AB6937EE1F5DDA1F8AC03452A2892B385C78DCF50095635949B505441821F7A2CC8337637171034AAA61D464F5EC6C06B32A60D5458A7BD33187CB624429ECE4CA24CB9EE70444FFD612E59FD253DAC257DEE0BC4C5491BC7351F6346C39141AFCA31A24766A334419A42375E0810300979B8B30D42BDFEA9C908C3BC626426041F7D3C1EA1590C41F1659ADC840729B0A882710E1A15538A55DE2ECB5EBA36EBAF24A3AF3F50AB7E92C30019AF02716FEB53058DF03825A688273E926A5A438D5B77F2CBECF5DC795BC229C87ECF27B3DF4A4DA6FF34A9D6884D30FB7EA4CD8FA96A88C2BFAA229D4AAB93F30EB947565E", + "00EABC238C885A769E985B6E4EF925CE5EC37FAD6FC3CD5A4087952D76A6617A" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "004CC39FBA232249A0519A474D2CC7D2C205C3832F736B5D9AC6649CF123FE5C586258A4D3E50362D73AEB81BF669827D75232EF8C084DEC5284B218F9B466957967EDACC0BB6955A094C13E1C9D15B156E8465E92424D769887C9804E81B3A3AAC4099E991A5B965E61F59D54963DA0E33D6C4008E65670F6BA0BE9AA03569353C753C92A78029A08519E31BF61268C3F8A407018A2A5654F6C071A9C4999D5FA37BF936EBF79490ED78EE9289EBD7222CE047753D1620C0BA3B6F7A3819C86C53C19474CA4BCD65020045118060D9A81BCC42B954143439C142C9C6A78323A872F680FB5641FFB936AE23C69A1670735F98A05587DCC3A1636CCB1BEF42103D97E4A9157ED671C77E16437726C8A12C3490784130A1AE53A4E1DA3606776BA50185593C326079151EB49184ED22F3FBB2BB5B3B1CCF325B6725166928DE717402BD52D343B2A3D07676552966713488BA5461BEC0435AB2B4F77B54932C5FECCBBCD7A62EFE1AD4DDA0E83F9CF1947634B3087A05BBD8CFA6B5D890F4670434E4B6B63A2BBFCAC66F7901EBB562209068769FC431CCAC6382262336726C861A962C42BDF383F9F745001763F5FF52F9520C16E4621213C679F820382A97749474F87A222FF3892A891CC60725F1C7962E526000054AB42CB81A73A88CC19CB1DD67623823F00F16256D3A8D4D75FBE0B268867933AC397255437B32A010D2834353A9BD6E018E5087B78028A6679425550AACFB0B2BBE3529DFB81AD7BB7C527A093271F8012856800AA3F205993460FE023BEADCA01684128C8B54D1E73BA6E247BE02874C96A92FEC0569BD56D1D46763EE3BAFFCBCB3E150FC171AC2A3C1E11EA5460E40B0A231317330689F57DE87C8D9422341DBA11EE22A749F56DAC7A0B5BD70F8EB46043C40BB1646B4D0C4D12591E54B885F5DB02A2325F96EC3317592C077CB99B506D50CC0B34D3554D80B9ED5AC7CCD158F439AC109B0E7F4C282A031B38569F3DF1B47712915994970EB28CE99646305021D435CCA6437AAA6C62554A6D0F59113DB10F84E8B3B257001AF3069E545F1887C131FC8A3728A60EB303F8A9B6558313C209509AFC46EEF34EBDBB4420CB7D40393D45388CA84563AAB1A184F88FDFD3AB147161AEC08637EA9F331BB34DBA7BAC170E6114C780018DEC400C74C02C76AC98CC976D005D000DEB7B856897F469A7161C251C7614CD46A62AC579AFFAC61A5BB72E92885F30AB08F51086D2428BEB4FE83930FB909AA7AC33572C688F02510F3758AAD4B8DAD7C5650079188C95720965E57634A89B5127F79DF6EB9B37F783BE471D1FC059D94982D0DB19D6522E5CD18599EBA1168C73F7F942569ACA85176F739A23070A155D13CB04607AD8E641158068D2A24BF52AC4FFA982B2B594D7A7BFCE952B246997483C40BA17BBDFD501BC640719D37A52904943AC3235D953BAB86DD1D97B8EBB9238EC02C2F3A7C8AC2E1B60608D925CC05218D09C8792272B3B796992FC92710343FD0197DD843254F7AA40CC0C9023B49F6036A408C39CB505501AB80010032940B06F677EDFE9C729E728E2787FE30B88ED6426D5F04252D278269C20C77BC18DB274F5F9C948184D38BB3228D8E28522BB2268373F8FE3A5FD107F185D7765BB0F4054ED87A8ACB9199E32", + "0017C4E1540CD43A3A57058D91E614E324BC6298C91B802C97922056F03363B8764A8A59E207C0486A6566CAAF6D9B1C75A89369CB336C4A862EC9562126196413AFEA263614AB70E8658BA72508E9383461056CF88B26B7204C3E3AB8641149D95C2EB1F444587BC5170213EFEA20C73B24F2E37323E54F6F147FFC075B03B468C22A307E265E165BB14B091EEF5A2CFE632C8371930F060A8BA3602F0098E1F1B104386C5D2430F69903A7041A96B1547A2941E9014E7622340D9B1C81E46B5B51C8CC4B2F3FF05C5484B6151BC4874730564540248804515BB13A757E45D329416064F80A26499600F709A050D6394A16A53CB227C71672D52147E24973AD960BE1F780E5963A7CA3AB3FA7B94F185839A20BB8D47F7B75B5A7B55ABA1B8CC123AA68C95B56C4B56EF26FA0835BFF5003206A3ED7745DD75259E159C1580A1F4F2108E5CC747D321599DC5A610584F8B786D0F33E923578FF0BD051176091E645929A344122A682B82972A2746C885C09584E3A33A693055FCA24BB9CF8BB64E98BBA451A11A2B7AE3087D7FA711C9CBE75585768467542F9C1C5E13C5C0450275478EFFA9BD2066DB62A1864C67796B197A31AC311A71377C4340953195CF15E6052BBF7C85BFCB494B52CC4F0BA87C94A00CCD65502E7A4745944408B66B6C65ABB3982869A27CA21322120A8BC04B7270C8210A08929726517539791182E1506B199D392ED854F69E74B0560615DA96B0F0A4E10FB6596EACD2D6C0323527A3BEB306049467E52BB6737C0782A0409395231617CF181C6BF074854D35B94B2151AD3898EE6826F887546D5B36C303F56F07C939810DE619AB2752700F8B43C3A8A34623FC875411672A39AC64265A61CFEF648B5BC04727157FD58B5B3F8A378A1848C979FDE4C96E0833A7072986141833C703D507303528401FAB5927BB1CA8044A8D5C4B7E367415E69BC9ADCA5A79C6D1455B872DC1B97C0C64C4922FE16AA246B4D6604BAB6866D2988B98AF4A5998327D4A1A6070B78394C6F979298A6FC1D2C7A5514BC8534EB7ABD98C7D0B5106D80042199339C6031D951A66164C98516BDE772AD4735959ABAB9CDEB54F9AC13C3049D5F752AD8A42B020302139A68C482C509D113CD4B4492E220AE498AF8E0930EFB4833C43E87E44F0CA713F12721DCE91D61A65F08822D1B43CDE69A232BA8ACFF40C31A1C82EB7C26C57C992252775502722C244179539D51E737E4B77F0443B3C51BC7C9B848751975BE25985C3A25E63CA629F8A21E144809C47477797CFC368D4357253DB58EE17316D2AB37431B49741617230B17F84A32F092696111AEF314AFE369B3E8D3927079BBD69C327E183E09A10ED3EC3F16BB93578C51312819B13B003B912D00D737014075A328A2F9F007F8101E92D60D03E22B5A83A75A6841FC9A8392166832BA1DD0904C131C5BC763413BC21C20A2B854E7434887008B616001C22E83A140A7F13B03E23BA3074E4FD26253C99C06463B534A9EBDBC7712F349A5BA8D0A033CDDD2204EC0BD321A260EF048C1023A4993432FFC4232ACA5D1808C79B915775A73141A9397BA10B87367BFBC9EA2C79977F54805A3A08B57721A664E045ACC004CC39FBA232249A0519A474D2CC7D2C205C3832F736B5D9AC6649CF123FE5C586258A4D3E50362D73AEB81BF669827D75232EF8C084DEC5284B218F9B466957967EDACC0BB6955A094C13E1C9D15B156E8465E92424D769887C9804E81B3A3AAC4099E991A5B965E61F59D54963DA0E33D6C4008E65670F6BA0BE9AA03569353C753C92A78029A08519E31BF61268C3F8A407018A2A5654F6C071A9C4999D5FA37BF936EBF79490ED78EE9289EBD7222CE047753D1620C0BA3B6F7A3819C86C53C19474CA4BCD65020045118060D9A81BCC42B954143439C142C9C6A78323A872F680FB5641FFB936AE23C69A1670735F98A05587DCC3A1636CCB1BEF42103D97E4A9157ED671C77E16437726C8A12C3490784130A1AE53A4E1DA3606776BA50185593C326079151EB49184ED22F3FBB2BB5B3B1CCF325B6725166928DE717402BD52D343B2A3D07676552966713488BA5461BEC0435AB2B4F77B54932C5FECCBBCD7A62EFE1AD4DDA0E83F9CF1947634B3087A05BBD8CFA6B5D890F4670434E4B6B63A2BBFCAC66F7901EBB562209068769FC431CCAC6382262336726C861A962C42BDF383F9F745001763F5FF52F9520C16E4621213C679F820382A97749474F87A222FF3892A891CC60725F1C7962E526000054AB42CB81A73A88CC19CB1DD67623823F00F16256D3A8D4D75FBE0B268867933AC397255437B32A010D2834353A9BD6E018E5087B78028A6679425550AACFB0B2BBE3529DFB81AD7BB7C527A093271F8012856800AA3F205993460FE023BEADCA01684128C8B54D1E73BA6E247BE02874C96A92FEC0569BD56D1D46763EE3BAFFCBCB3E150FC171AC2A3C1E11EA5460E40B0A231317330689F57DE87C8D9422341DBA11EE22A749F56DAC7A0B5BD70F8EB46043C40BB1646B4D0C4D12591E54B885F5DB02A2325F96EC3317592C077CB99B506D50CC0B34D3554D80B9ED5AC7CCD158F439AC109B0E7F4C282A031B38569F3DF1B47712915994970EB28CE99646305021D435CCA6437AAA6C62554A6D0F59113DB10F84E8B3B257001AF3069E545F1887C131FC8A3728A60EB303F8A9B6558313C209509AFC46EEF34EBDBB4420CB7D40393D45388CA84563AAB1A184F88FDFD3AB147161AEC08637EA9F331BB34DBA7BAC170E6114C780018DEC400C74C02C76AC98CC976D005D000DEB7B856897F469A7161C251C7614CD46A62AC579AFFAC61A5BB72E92885F30AB08F51086D2428BEB4FE83930FB909AA7AC33572C688F02510F3758AAD4B8DAD7C5650079188C95720965E57634A89B5127F79DF6EB9B37F783BE471D1FC059D94982D0DB19D6522E5CD18599EBA1168C73F7F942569ACA85176F739A23070A155D13CB04607AD8E641158068D2A24BF52AC4FFA982B2B594D7A7BFCE952B246997483C40BA17BBDFD501BC640719D37A52904943AC3235D953BAB86DD1D97B8EBB9238EC02C2F3A7C8AC2E1B60608D925CC05218D09C8792272B3B796992FC92710343FD0197DD843254F7AA40CC0C9023B49F6036A408C39CB505501AB80010032940B06F677EDFE9C729E728E2787FE30B88ED6426D5F04252D278269C20C77BC18DB274F5F9C948184D38BB3228D8E28522BB2268373F8FE3A5FD107F185D7765BB0F4054ED87A8ACB9199E327D120DCDBA0767AE1336D8E1CC713556634E6E694AAFE29AED935066F4BE4E8C04150BD6B5A2E7E237795334EA683215868A5ACED024E77889C143B2AC209A00", + "0036F61043581C5C8F846C10410AB92359C7D405D6D84D26D5D0C69CE17B35EB0C5F3876DB4D66245E2E65BB6C3802075E315823455A214FF969AC6050A2FBD0CEE7523A33930FF416C71EA17C57E9EF458275B7ED856B3B19C50696371CAF78F60E859DDF5083AF74CA59E08BEDF0AC971B1A6AEEDE5DCC0608D8AAFB228F235795A3045903D6EF86E2054D9DF864259778CE8176A1D0483317A32FB796FF7477DDB03E30EB6A85EA1A580BB74CD8DB191B76B2CC99028741825BDA6F4F59F013DB9DA762BDB6C68933FF6E20229F90E2A7395B7138326BEAAFED2E2E2CA7867035A761BCAAAC3DECD9BA4D95CB998F411935B6D1AC3CDB4BA33690FE170F98EAE72F27FC029EC4F300FC09FFD84110EF75D4447E370DC3950463CE0F79C90DE22D2DBC3BA6347825921A970F688DF800BC68B0E6DAE39645FE332901307B52563D2B1E79C375462AFAA2DF5A116FF44383FEFE0ED97BB76CC58D0AEE1804D09346EF9A7F0E348CC7D026646749A543C4197454611268F3634A6E8C29503857DB57635B6D3C95B3658DE656C424C867095458DBAE38C559113293CD1F328642616C29829647E908F01143876C3EFFCDC318A15E22A96C6B75E83E00DC8ED5BC6B14E8CEFBDDDE16F3A81FD0EC57B9AC054F1E745EF17CE9D58F61531602844EEAC10F34C0E9E4F12B9080D7B8FA6DD1E6431A58D2023EEB393873FABCBD1C87092FAB21E30D0F5FA2276561613416807E6F81C235FDA360D21BBB10543AAB82F0A9A99073317E243857FCBD481C969E814FAE82CEF545BBF1147AB8CDBFB7C8213D44C6DAFFA634768190464A8F9F764FDC21CEACA0EF1B08A7FA13E3CAFB72404046CF86A2CD4C7A4933C5CA2BE80261A2CA89FE25C823C60E5D140C5BA24DA042C1B799FDAA88E4D8EE4AD00B5E31B8EB38B4EA76B3F9418EF9BE1DA54436E0EC737E77046C9D4949BD9E1AB02761EC209CFFFDA8BD21F1C7206C23CC4B274AFB80FBFAC9EA4F8BA2B1786C7D8ABBEED50EB43DCC9EB56C9EE8F2F76EC382790E850D1EADDCBEC35570185C4AB011192CC31BAB3084BAC0EB31EB1A156914084CA8A6BC0EC92E9AA14283C655371B36F02F5CCCE5C3AA51E4A9C05547D53419996592DE78EA58812222FAB5EE7ABEB57D401EF02B410C0F65652F52830C1C93B968D21E74FCC84B6A2FF5874228034A1FF09C6344EE6B744538185D467C84F870ACAD8CD06B10283DC2398D9FA42840116F0D8E6F1255C0175C231F297D1DFD3ED67A3F79F6BE83FE5EC20B6D2A4DA441D5E93A465688B9D62EC26A35E3FD8AE7036AA2663298060CF03C852DC45FBA92A8AB04706B5F8A1D4881E8EF0855C1489BB9471208EC773F628A583C5082148FEA9A2E6BBB765F0C745FDC2FD7E9B7EDAC00AE99C414EC646C69BDA64E17A1458638F2F3983A71FED2BB969FD6AD13D82A2D1BEE16AD6FC21169354263414CB1F83A493757A7F832A53CA305292E27A9A3E9F98EB0D2CE8C66AEB43C2966090130D72919A0263EB4601E7A528640", + "00DA90F4B7AA3DBE6502F6B3A41CBE2E11C4DAF7341C103F93AFDAABA5BF4702" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "0081607A3102A51C8831B22E77DA270A21582E987D5E0CA251485B36B52B97A26EADF13506266491729283817BCC779474B11C7AF525BF000E8CFB551AA4C71EA8A479EA266BD3692AC8A708EBC682828067C8120C1051464118DB169392E49CCFA55C98B5279E26839BDC0F7C6B40E6C151C4B84C5C1CA7EEC2505A36480E481069855891CC834CF18223C80865A83719D9B57D06ACCA7213D4D3658B587F3B516388859C8988BCD4486C4D74A7E2099D31A014FBA96BA386B4E932659E783ED5E84D88116D2CCC17A14196B445CE652354DFF39613461A6DE17FB762C6462881676500B13365A769A435509651F8A371320A463ABD6103AD680B18DCF826C2FC279D575172F25B149686FB52BC0D77535521349A10CEFE4C94CCA61A60B586DF41CFB889990E388FBF8C40768CB60140A5B7A7C26B20B63EC78AA0A6B5E3E174ABCCA76F013FFA91B95254884F1CB7F1C74A48F3803F733C3645B999DA6DFDA8ACE3660BC55A106AC52658491F190B5B1DA403A03893562B75F1730EC5D18A60493C6A1262F0C3C9B6565106BCC3B4784C1F820F098130A08A5E8463377FA3C29C505F718ACC37C25472E2B7CBB6C94B467CC1DB37AAF58E28B8C4ED553AAFD69BE4A8387F38732C091D86B1C53DD6308D03822CD03A1A30AA6745CE6045BBC3932A95B942C2E366DC75692BEC2D46F13A29458B0071845F8325A65B8951742EE38A59A9045F8373799ABC822B603DFC30B684C911F3900AECB9834F14711098C7477946DB584BC67A93B8F13989E38F32641150915B2173A03DA6552E290AAC8588FD341879494A5E9B0A5DF3B005A65E08D186542B8076385EE4ECBF3C4C008C6CA56908C3EC6924827B3F9117686805BC31432353225AAF012EBAEACF90A07632DAAE4796C0D03289C363543F85214F2A6C34B46DD3D61DE314CBE1467117C89897164E2FB12052743EFF04A406B55E24335730E0C9BAA610CA35AB7BA060B48458DCBB274D2B64D8259001CB5DA8C00ACFF5BE250474DDFBAC99F25CCD7B6720CA7B4CA47BA13C1592EC4749AC5AC58CAC763855583C2C86A59FACF016D0E9607EF37AD1EB1B9ECC2B8E2320B17580AC52B30CF3586FF3B0D979BD2AA68B7552A2C9409CAEAC4AD565A061C95D3003C146055AA8422F54E7C0043BB14B038A1255AD7D26A27D243F8126A2BCE5BB291B421C9BCEC62A56363B270A36AF2E617B51D79A25730275AA474237865FD44679A29B335A9BB0C03EC116B6390B513A9C663AA02D34680F6ED135F5397CD8C41BD9D8C76014B42FDCA075757E877A6222593B9FBC388A02833B54135E226D71A273E64298D8864C5B205CA90721BD0481C3C84D68677CDCB0A43D47772D54C3AAC5A4B98A80594A1842CB43230913F7DA9377A58D227990F50147F3E912450751D5541509204DF17A0347E5040A9643ED13088605B23E4AA18C75549916B11541600624C71CD2CD67180B7A221FEB51AF2099780515434B1A01CAB13CCF2454E1016042F40125774BF90222BE9326837A4D5BFA50B82981D414CBB62B227297A19D147849D25A5713711E0C6B3C565DCFD096C91879BF01A22B7C51E44B08479B1C517CA33C3B7DB8F0C69428704D36269FC944F154AA19F230A9366E7936BEAAFC1200475B89FC2CE14A34DD62A08088BF39580BD17A4124BA4D951A407226AB7620A57FD08DF8710D98466AF23564E58A34FEDA022BD699A812A4E9B5564FD384C1678B8C21C4720BC45FECA326BC00D69039F73807AA2AAE0EC895EE02D0DD651B2A7C14418514D877A0C2146544874F5C79132085895A528BC5514CAC6095D9A2351151A131A42D4B0052468CA26A8A730609C635DB7E50D77BFEB26C5761892CF306CCC86C5701893EB40F1476075F8090CD33573AC73941988EEEC6C70B7A1ED2E6AB680BA64E4B67F5C02D08D288BB714ACFA7B8B72A421F908B04D175D5553C31B1234879ACAC63BFB1D8917B3087EFE22B1D702284382FA42098FAC6C470FB2DD7FC1CE5BC8241256E61343301543A6436582ED989F1C30E4E93BA7C34458895AAB5B9985F4143C69732D4D776D4267BB645692DB348342AAE69C844D54841B9F42EFB837378B449E0FB734B0C968D98C3AB0481288A126CD99096F095A3FB7C180CB2A47425AE24262A918FD7BBEB39B06EE1EB5B8C9EBF8DDE0EE6A5C64C5F902748ED76C3FB44CB", + "00479BF9F16267C39094D36B2CA200A870A551A30EB5F3BA45A155E100CD313083E5579B3E837551036FC3289320E24DD5A815AFF88127D720EB381BEE523906900DF7B3BFAB1595BB20A016A0C214241A6C63635D4978012BC293D21BE1FB63364A25B9558B21C1346B0AAF7ABB4544A10BB28854566A4783A5712157AC367B5C64EA070566A3F7E049E40A79334B1B497AC0A72572CC02C09D281575E647D9E86FC9C60FBC9322B0993FCFB26483324B4443C663B82DE3FB7B2DF88A5B2B562F53B2BBF06800319500880DAEF98740F03C80D118E170A01A507E7BEC22DB08A9ECB968D92054EB36227190A4D72BC085EC225236083696CBE1D08AAE54B24F9638A9241423387EF5B6832B11C0BB51B904523E653A5C104C9EF92B4929193366F0828DF499E1560E107A6322A6C4A062A2B8F37D0D4070C86A0BCE580D9E195017161DE9D4349D509979000E88371BD2AB863BC847B66A8AA1B255F6DBAED40566BB462AFA7743D9E773ADF2A5D28987A153B9DEA3CD93560FAFFB43971C7A7BB55DF477BC7E610DD3B7A470AA4B7912A5944B6AEDDB3D88AA7C14646E05BAA69B9B344C53A687AA03543361C083CFEDF25DED5461C12B075692C29FD7741A40979F855DA8125AFC4C9424347E982AB534FA5552F8A6DE3A87B99C43777C1EBEACB5B3525E89F054130351B2CA6FCFA37EB442CFDA702DD321A55DA71236EB7742607670F793AF7575F775B0F3210D0365CE30C1492FD61696704E4DF1966500B3B611AEF41A3CBB91B90744634E19773E24B9212A4249AC41D0861F0DA9C2C8542B1829412F2585FA75A56AB36262D22806DA0379F2A2B2332CAED03A7AF570A8B9871766B990B5700F8572599CAF32D4A175268679A3428334514593264C135160606951437CAD503D74685FCD20B122EB18B8DB5BB6BAADE17C1D15D81D16032D3E72381960B200DA1227791EA3E926D513905F5B3AA33773BF968F27D028A32284C3501A94B1CDB7942CD215C863FB28F92545C2D762C97502BFD53264378F01BCC1A4F948A9B327E72B3A211647C82368726A50470274F8BA00EEB04F22F924AF3BCEE27A3AE27955B33ACEC16C6D079420D53A2EF93522732A77EB6039A4FB30E13C69EB157DA1202D16C97E0C049645787AE85A7534F58057A3309934606ED150C655C09C14C7B3D7BCDA06689CC04B4272B4E4C88702CB2D4051BB9F856A0A283A1856BEF451A0966C7B0C5A4F3B004A32206D26BC59519622C0E6133CA77304FA817BE5694344172AF362B6077E284AB09C08051B0C7F9CC877374B45FC0A84D2B25A127761A022A0AB23057940069942397640010796BADABC1CC362A845932185706C32C73485383E861C75A5BB48213634DD88775EF221B3832D41206FB51B16D4F942FC214C59D273C68007B423CB11CAA85948047A796A7C5C2842AC57612A5ACC4C056AFB182BD98CF4151792E32B055575A30A14C093A4BFAC078DC96EFD967E5C84727C781D3D9C47EDFA81FC935C83B60220658047CB194CAC47B9E096C8D0AEFA47C9BE779034C323CB99B4A07C36EC207367220FA9C053F38BADD3EC3456362E64E5262431A89EB58070567644E94E1F575C352BC81E4C7916862CE8DBBD29420F10D01FD0C539B104106ADB61D21041C50BC1CD1B07736754EFA41D6427BD31B38BC6806E8A240E3EAAC9FC53A95E866CBB93B588F741E01A8194530C8F1967A216B807B236F36480059B65E5603409F63580DBA58EC10B662A8012910C7A6C711B87102430C8DBF4CA87C8C784497555A1CD570749B4E2393448BD4D6C5BEF098A61D57756865106EC03878A452F510F81AB0D654908667C7D1ACCCA26999F74011300DD198B02192FE68E1E6145AE428D3A7C8AD242675BE631476AC789B6A474224E12D595A8DB00CDAB0972385ABE22CBB2F996523C90419066D5999E5217CD6DD45591552951653172A0AD271838CA2C7F8733556F717A86B84C656AC20D3A24C4954DF5D93E44CC5AD4A63743CC19DA259CF119C48B6541904199F7806A538523445CB6B61561086A1D5B69C205A1B15EF2CB91742F8F165B1E682F76DC987D4A6BCA540956B12B15CC394698330F0BB6ABD20CBEAA8E08E9A291E7484845084FFAA59C843B68027B6AD8C3F756CF5379980081607A3102A51C8831B22E77DA270A21582E987D5E0CA251485B36B52B97A26EADF13506266491729283817BCC779474B11C7AF525BF000E8CFB551AA4C71EA8A479EA266BD3692AC8A708EBC682828067C8120C1051464118DB169392E49CCFA55C98B5279E26839BDC0F7C6B40E6C151C4B84C5C1CA7EEC2505A36480E481069855891CC834CF18223C80865A83719D9B57D06ACCA7213D4D3658B587F3B516388859C8988BCD4486C4D74A7E2099D31A014FBA96BA386B4E932659E783ED5E84D88116D2CCC17A14196B445CE652354DFF39613461A6DE17FB762C6462881676500B13365A769A435509651F8A371320A463ABD6103AD680B18DCF826C2FC279D575172F25B149686FB52BC0D77535521349A10CEFE4C94CCA61A60B586DF41CFB889990E388FBF8C40768CB60140A5B7A7C26B20B63EC78AA0A6B5E3E174ABCCA76F013FFA91B95254884F1CB7F1C74A48F3803F733C3645B999DA6DFDA8ACE3660BC55A106AC52658491F190B5B1DA403A03893562B75F1730EC5D18A60493C6A1262F0C3C9B6565106BCC3B4784C1F820F098130A08A5E8463377FA3C29C505F718ACC37C25472E2B7CBB6C94B467CC1DB37AAF58E28B8C4ED553AAFD69BE4A8387F38732C091D86B1C53DD6308D03822CD03A1A30AA6745CE6045BBC3932A95B942C2E366DC75692BEC2D46F13A29458B0071845F8325A65B8951742EE38A59A9045F8373799ABC822B603DFC30B684C911F3900AECB9834F14711098C7477946DB584BC67A93B8F13989E38F32641150915B2173A03DA6552E290AAC8588FD341879494A5E9B0A5DF3B005A65E08D186542B8076385EE4ECBF3C4C008C6CA56908C3EC6924827B3F9117686805BC31432353225AAF012EBAEACF90A07632DAAE4796C0D03289C363543F85214F2A6C34B46DD3D61DE314CBE1467117C89897164E2FB12052743EFF04A406B55E24335730E0C9BAA610CA35AB7BA060B48458DCBB274D2B64D8259001CB5DA8C00ACFF5BE250474DDFBAC99F25CCD7B6720CA7B4CA47BA13C1592EC4749AC5AC58CAC763855583C2C86A59FACF016D0E9607EF37AD1EB1B9ECC2B8E2320B17580AC52B30CF3586FF3B0D979BD2AA68B7552A2C9409CAEAC4AD565A061C95D3003C146055AA8422F54E7C0043BB14B038A1255AD7D26A27D243F8126A2BCE5BB291B421C9BCEC62A56363B270A36AF2E617B51D79A25730275AA474237865FD44679A29B335A9BB0C03EC116B6390B513A9C663AA02D34680F6ED135F5397CD8C41BD9D8C76014B42FDCA075757E877A6222593B9FBC388A02833B54135E226D71A273E64298D8864C5B205CA90721BD0481C3C84D68677CDCB0A43D47772D54C3AAC5A4B98A80594A1842CB43230913F7DA9377A58D227990F50147F3E912450751D5541509204DF17A0347E5040A9643ED13088605B23E4AA18C75549916B11541600624C71CD2CD67180B7A221FEB51AF2099780515434B1A01CAB13CCF2454E1016042F40125774BF90222BE9326837A4D5BFA50B82981D414CBB62B227297A19D147849D25A5713711E0C6B3C565DCFD096C91879BF01A22B7C51E44B08479B1C517CA33C3B7DB8F0C69428704D36269FC944F154AA19F230A9366E7936BEAAFC1200475B89FC2CE14A34DD62A08088BF39580BD17A4124BA4D951A407226AB7620A57FD08DF8710D98466AF23564E58A34FEDA022BD699A812A4E9B5564FD384C1678B8C21C4720BC45FECA326BC00D69039F73807AA2AAE0EC895EE02D0DD651B2A7C14418514D877A0C2146544874F5C79132085895A528BC5514CAC6095D9A2351151A131A42D4B0052468CA26A8A730609C635DB7E50D77BFEB26C5761892CF306CCC86C5701893EB40F1476075F8090CD33573AC73941988EEEC6C70B7A1ED2E6AB680BA64E4B67F5C02D08D288BB714ACFA7B8B72A421F908B04D175D5553C31B1234879ACAC63BFB1D8917B3087EFE22B1D702284382FA42098FAC6C470FB2DD7FC1CE5BC8241256E61343301543A6436582ED989F1C30E4E93BA7C34458895AAB5B9985F4143C69732D4D776D4267BB645692DB348342AAE69C844D54841B9F42EFB837378B449E0FB734B0C968D98C3AB0481288A126CD99096F095A3FB7C180CB2A47425AE24262A918FD7BBEB39B06EE1EB5B8C9EBF8DDE0EE6A5C64C5F902748ED76C3FB44CBB119CEE210E060B66EBE080206DFB483E300CE2B96B4B33057895A75926F98D563B1AD5C313C2F4D6F7E6AFB3576F0668792FE722DF04041FAAB9E97907B1500", + "00ECC79E0B6E53533C7EB1540A7D0743229897CB5C5AE0882B9D50655843B4D3C625B3335AF7AB7C0BD555372D7B412F73EFC84867C5ED7B6EF5C492578A7DB35CF0F44E6F1B482CBE03C5E12DE7E12C46812A326862CA8D938A6D56415C2A1D22AD5D33EF232DE6073E8AD016BCF4000BA7E2138B01D35A154CAA0BC67BB358E4BD617CA1F6806935C8DF7C948EEE65614C7B18F0F048AE2CFE04E011BBDEDE210CB8204F4822F02FAD2BF15A901FA21D7C420347C66C6A9B4A062209123E8E06B6C308965A44BC0DA0212B7567B3E94224CE6E381793FEC66BECF10C544A7E292F09898AB2AE505F56C8844364135B16B6D6AB0841796B6C756DC581B8EE96A93B3E837FBB56FC0D9FD9E443B2CA45603BE6908B8A08A6FA694FA66555478F008259EBE064610860261DF51907B9C6A9EDB0559CE029A47A3848DAFAF4247EDD728AA0CFDE37362D584C4A60A7F36FF9FE7C3BF63B87A36628CC12ADE8A1428F88F15C0F2EF0A5F360BF085D9E3707A9E6EB3B1C35EF1DD7FC2A5D10860BCCCC93CB7E974AABA2BBE4ED47D4DDA738AD9CFB711656E54571CDD1E64B2B62FCC1896D46251AC403C5A68F73BC5E94B9F65BC4B66B4CD70085E171946C2E45C4FAD9CDBFAFA2A02C253C27B58E03B5BCCA978D08B71B5D0543E5FC0A1D56857719052E716F3B3686830ECEF59760B2405866234C8CB5DF37C6F82038DB5ADDC58551E61FADC30365553069F063A3BB2716864AA3782279760A598BF07222D3ED6936862F53020CAC5F89D46266D887580B53A3CBD547D1557141066DBD8D36664955287EF0760A090FB3C1FB853A5E7D835276A5BF63FD191B07C06FA6683B8948CE11EFBC93F01DDE89348A750FA7AB59ED15A9A793F21EF24FDBBB86832AC023E42C0BDC5808E0FFE48A4706B5DF61F11A16CDBAD29BAC8759E8A6817F98709E5FE56AB8766501D1FD1DB4DEE6A84D2728701A86D5D9735292F468077793E12A3BFA4D21D618211AB19A1B721EB1AE914869F8B7AE6DF45EC0324494AC983B2E8CEC4C3DC59E66BBC99913D5EF9BE1DEDF94068F6DC5600BF147B496AB033C19EDFED92A9258E47C9A209E2A557C1E83DCA34471B8C5A7049AA838B0598008548841D06586BD0E1E292CF530FC793007971C0B1E486A00BFDB0AAB048CEF187CAA9DBAE1973B901FB374B5B47FAFCC4904FF8704FD9BA6C17DEF67AEDC9C4A5CED6CD4088B7A5E09123BAABAFFC20A2DA6C4181C9B47A0D46EBF177CB570ECA03F251B5A0AC7086EF6C231B5BF6E260FA14F2962AC9336812F6BA25F4EEA76AD2BA20C0B0E9F0F6B568D01BD703672DC34F4CB619DAA8D1A2E50861666D32C62C446EF3EB99633E3AEBA1A9FAE515D1CEAA46415225AEF74A12B1B14A3804D8504368B1939DB7A5502390192092B9D8A64E6E8A278CC09F6EBF368BA5BFC412FA320A8F479DABAF2F574AECDD62365E8F4A0E7A0C48905104DFAD1145249186430763E95C65644C6FE0A011E6E21EC4B5A3C002F8CE4866F56D7BDC65D6FA6331B4975179D4E8B46109B18C905B03AFFDFD9B28A595808826D095274C1C842D4A1D5EEC83DFA0573253C5AD3E355483DFC682FA98B61BC12E2BABB99116C5FE20F47904995E4B34EE13D6CBDC7C305ADF4AC0B3D238AD95BD61872301E9F74FCF6F167FCE053CDA25A201CD21A95BDFAF956D956CB007B19C0BF2BAAF2E6A4741AA17250755B590A1AE893BC13AD3253EC14D04EAC7E4CC9DFA8336BA1AE69A7A058B45FBA562783F8AAA3D83471E5565EA5B0E72FC07B530465BBDEA70C77E64D6866665849AB0C719EC5A945D8B69501FD1B441FA2742751736752484947F7EFE07921C369AFE853D89F13ABACB79302882A74CD456043917A206FE1D4075EC0B7EE411F944D052985169558D731FDEB0A9504850716957192A0E6563E3347645E805989CDDC84DDF15D76CFF4D7A0678A5E567F62D9B1693CC622EB02CA439360E2A4ACE7AB09BF5A553BB5D3295AE69FC9EF3E32E1E899EE3BCEE3D4D8E64D321DDDD52385121934418160138488E1FC5F373A31EBCD28ECB6BFF7C54CD9C64EC5C3C458F3EF80D642B4BC3A8A61AAB206104D91EB49CF1D1F5A7BF46AEC379C4E2320966663149BFAE333F7E8B0022CF97539ABD4A67D29335C8D88DD2072F983B1CD0E9F1D3C2C7AF4B5444086C7FD97A6C9231984E63A042BC81B3D", + "00F059D296257A6182AB750EF13C77D3FC15FB13021121588F56D909C6D51665" + ); + + // The vectors below are generated from the NIST ACVP projections. + // https://github.com/usnistgov/ACVP-Server/blob/85f8742965b2691862079172982683757d8d91db/gen-val/json-files/ML-KEM-encapDecap-FIPS203/internalProjection.json + yield return new + ( + MLKemAlgorithm.MLKem512, + "8D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A21791", + "FFB93E594AB462B4070F2684B3845649B96474760BED1BAAD22A38B2667B7765C504B03D65EBB1B88B613C978518428097650320821454B971C3107962E00E4A575EADA990B1B945BE845FB9411D9C8303224B7CB1D27E0286213C1AC1052C363ACA3B0C053FAF48577FE4107BF35343FC39F7A5305A98AB2CC315A84C5C60D9940E409D65B63BFB3694FA249556F87BD27C28D00A62A3299FBAC0501A3634A11267584A216F365614563FA327686CA32B38E3102E7305E48A7DE910737E688351E94DA054CF1D17944305678000BDD9CC8B93333660A85AE6B8C4612A6535E5AE8C959125141E6536AE662C741AEA0D783B53962B5CC612750AB3AEA3708445EC97B2BA1EF3589CE9F94D3A4B91E4052A746635A595568640B375E5872E30777137874A429A4741AA81CA63A90884E54527A48B84F274C0E04B92386304D50048D78713BE0A9008A69DD49CB886CB6E7BFC7CA9EA03F09896D739C292C3021B2A985CD858DE5A574A7C431CA3795CDC436EE58596B10A1507B60267B1C735BE22E05F5E6AAA12F132FB932DC815B2411CAC97EB729EBBA95D5C1CD7280A339CBC56E85D00763A1B6A371735CAA1B8A699C431EFD2182366AD4E7B4765E9A842ABAB175128AD4127BA447157F56098B3C14C561502406531FA06863C85A406494CF330E591BF58FC0216B9A66CFC39EC26C10FF97FD50017CEA705363B0BBCC9874BB2BCD0AB08631140923AA88E0AC43531757C689F3F075FEB3B59767BC1A327C1EC8A7E0670415ABAC9D0CC1D7854620E8339B5456E3D5A1AC3562E8F78808611CEEDB57BF0DAA937CC8E2C1780DAEC6FD08ACA72876EE010C290AA6136EA91E71605C6F2BEDF89B9519A5AA353C3E7415F4D4915907461C1A0559CEC7232F7A90A17821C84864739CDA43C7C94A63197DA4EC3E82DE870CCDCE4988DAB713530B8CD889A010A769DFC148CC896C2AA00AE28041B4AC0905373408082992142F61B817152609759807105C2A43C508FBB4748F094DC4A2EB6330A70543B405CC34D1842F6711B41F790E82316F6A44CB99262FC4338455863515AB67FE6898D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A217913DFA277AD62F7CAEAA930284E348256EDCCA5578A06528678CBAD23F0A8DE1D40BAD0A76BA218C111C0DBB15963741113EACF5407A795D689E6E1EF1DE8B0351", + "C9C81034C5481BCBD90DEE95F277DEAEEDA9240AC844B27AF04C5351256B3B2122C0FD22F18D82C82C80875253EEEA45C3F7F2C4C40F321412460025596C196354E14D870892FB2A862E52FDD3E77BE07F500417F29784D3D2FAA477F10406C5FAE13B1B925B1ECA3FF4C8C3AF2F7A14CD30C301892EFBF0DEAE245DFC3816F32A6641C208E800E3BD3CE678013B70D0B588174E6AB0E03D095F009EB301497E6E36EBFD215FBFFCD78EB9D8372B034525CB41EAF5CBA3D5F2F434F2F6B85CB011E97475F5252D6407C92A0467286646E8CC49F669E6C6579ABFFD28F4451241BB559027F37BEB0E4EC110519C5D3C5C8F5A39A67681188F9E173FFC1601D35F79DA24462B1A4FF5A04EC9C4C5C0F4F276E4807DAB94ED35A7B1F99D78BA5F767F9D6FDF1CE4C01B696FA10F49CB500CDD0CB921665FEE23CA153AB9E823BA88B944240FD6638D261B06FDE5302CDCBFF66D2E55AA6DE9C14CC177752513BEBF6C4DC3BE8C293285DD0F643A11A31293419B34D4B18B9A46223964DD7B8482D96E27449E85EC16E663D6AF2B85A1B630B84CCB87CCAE6DEBD515A5A2D9B05BF0324670284EA5F1ABE69BB4B6EFA261712A28CC520CB72881DC7DD788AAC865BE8B51F0BF414EA7B8CC9F4473AC2D03B73FD9E9A7CCDEE38C7B170FD5A34FE562ADFC41E8E45957CE426F6432001238CA36B5162D79FB3C9FB6A9071E453C8E9CA05CB52A859EF21C8051E8B8DFEDB5370FA9E57A45B04FE383394F72407BA397CCA87E017B32D22673F50E6E1244A81DDD6B381BC1E67099484DFCD087E7BDF479A8AF559D7893671802EE10D114379480E4DC11EDEC1605A81059C0D40400B3032D50620F3236A28F068D07FC7EF14121FD4701763AE2A8E4731EFF8D1C103EE4DB6B89FE4ACEB94C5F78A7CAAF5FE2D28831A9213964A8782EFD2170F5B2D966C49181BDA6CAC6A22C7A6D65713DB7DDA24537A711B06E7B0BF975C22F9CF33B5A7D6B5E3903AFD353326EE33D755DC747D76320FA8587087B9F5D106D6C3792B4BB25EDB2ABBE2699C7FF3D3B8B65919E508A5BE06F2D2138A1BEB2BB136F", + "57AE473989DFACA8266BE8C640B4CADE4DA7B02280E6C9D67612AD4B975381E9" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "8D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A21791", + "FFB93E594AB462B4070F2684B3845649B96474760BED1BAAD22A38B2667B7765C504B03D65EBB1B88B613C978518428097650320821454B971C3107962E00E4A575EADA990B1B945BE845FB9411D9C8303224B7CB1D27E0286213C1AC1052C363ACA3B0C053FAF48577FE4107BF35343FC39F7A5305A98AB2CC315A84C5C60D9940E409D65B63BFB3694FA249556F87BD27C28D00A62A3299FBAC0501A3634A11267584A216F365614563FA327686CA32B38E3102E7305E48A7DE910737E688351E94DA054CF1D17944305678000BDD9CC8B93333660A85AE6B8C4612A6535E5AE8C959125141E6536AE662C741AEA0D783B53962B5CC612750AB3AEA3708445EC97B2BA1EF3589CE9F94D3A4B91E4052A746635A595568640B375E5872E30777137874A429A4741AA81CA63A90884E54527A48B84F274C0E04B92386304D50048D78713BE0A9008A69DD49CB886CB6E7BFC7CA9EA03F09896D739C292C3021B2A985CD858DE5A574A7C431CA3795CDC436EE58596B10A1507B60267B1C735BE22E05F5E6AAA12F132FB932DC815B2411CAC97EB729EBBA95D5C1CD7280A339CBC56E85D00763A1B6A371735CAA1B8A699C431EFD2182366AD4E7B4765E9A842ABAB175128AD4127BA447157F56098B3C14C561502406531FA06863C85A406494CF330E591BF58FC0216B9A66CFC39EC26C10FF97FD50017CEA705363B0BBCC9874BB2BCD0AB08631140923AA88E0AC43531757C689F3F075FEB3B59767BC1A327C1EC8A7E0670415ABAC9D0CC1D7854620E8339B5456E3D5A1AC3562E8F78808611CEEDB57BF0DAA937CC8E2C1780DAEC6FD08ACA72876EE010C290AA6136EA91E71605C6F2BEDF89B9519A5AA353C3E7415F4D4915907461C1A0559CEC7232F7A90A17821C84864739CDA43C7C94A63197DA4EC3E82DE870CCDCE4988DAB713530B8CD889A010A769DFC148CC896C2AA00AE28041B4AC0905373408082992142F61B817152609759807105C2A43C508FBB4748F094DC4A2EB6330A70543B405CC34D1842F6711B41F790E82316F6A44CB99262FC4338455863515AB67FE6898D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A217913DFA277AD62F7CAEAA930284E348256EDCCA5578A06528678CBAD23F0A8DE1D40BAD0A76BA218C111C0DBB15963741113EACF5407A795D689E6E1EF1DE8B0351", + "4D18E11B61F670F19330C7893B620DABD0E01B1DEEDEB2AFE73921078FFCA2DF210EBA11AFD214632ADEC9E136A35B4C90C418CD1C3A4E7895FE8400419118BBDA76486F26336646905A633C0E5EFDF8EF0DDDA6BF759DCB2873A9F4F9894A8B075FA763E07F96EFB540332E34BF8273861D0CAEA2DA268130CCE8433C0D457F9FFB2B9657A6FD277DD93157FFB9DEA6EDC2D3C30A069C999A49A45D59C2C4BC152077A8F063B3DF095E58F366A724342A4AA9E3440A867B98CAD924D5DAB546259AA48026E57A4A8E5B8FC1B4FF0D29B5149EC831CD0A5E6FAB4DFB9AFF96B2B1E5E8444084089C88A0435B57DE995A3A627D17CCEDD937C765DC72BC1C04B689030228FE9F127D0363485A53EF4F8800FB39F6DE6733ADFB77D2850EB2A26B30E2DB37F1EC5B4A40979CCD0D7746C7085285F6470200611094C0C83C0327E6308880F9D846F0B51F297660239B3F381DCE91179C3E58BDFA9BCF86A6EFA0E8A5BE21DD9166C7508FC4CC634E7224F27085CE2A7572EB21AF4BDF05680E8397F6989A3899356294AEAEAB57C9F039F4123E84D1A2CD4F660615699373662EBB9367A2EDFAB31801CBB5E0900FAEF108AFF7F8819A40BF5D794067BB5F72E840903B9A318FA998DE5F933B5DA834D3E2A0A4DBA54EA8F538DCC6114826AA1B5CB32A31981950AAC2D0CDB2E23DDD155D4890CEC21F56AD686179E1E51D136D733BFCBB95EEC363F1BEB25151CA019002451613C7431D9FF6E00F7210E641C9A53CACDD54C9A90EA394C0E88B547B6A637B98D8C894009A18D22774D979DCA660CA1CB3557326D2A24719549770E7C533A17C4B18C8CE590ADAF9FD4721D7D74CC66D1C252D99C5082522900813520080BEF39C3517FEA9D0FE404EAB5BE97F8E4444FF63BBD87123944E0B6BF91B7732FBBF0AA877F507A8A5DDBAC7A96525ECA11B3BEBFAB1A9F88A4C0D80E85E06D3EF9A2CF32BF4D186FEDD7B5C6D8664CC8F2F8B8C7E999EC42D36064CA0D363AB3B1B14A41C09C434F8591735285EBE4BDBB11AB4B16A25205B9CE0A73938F9C97799A0DE80747D56D98D7E5A6231F9ED", + "22D9E05E0D01B56BB5042AFB69D497909F66B47CF236E9C77FA06F9D81A16AFB" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "8D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A21791", + "FFB93E594AB462B4070F2684B3845649B96474760BED1BAAD22A38B2667B7765C504B03D65EBB1B88B613C978518428097650320821454B971C3107962E00E4A575EADA990B1B945BE845FB9411D9C8303224B7CB1D27E0286213C1AC1052C363ACA3B0C053FAF48577FE4107BF35343FC39F7A5305A98AB2CC315A84C5C60D9940E409D65B63BFB3694FA249556F87BD27C28D00A62A3299FBAC0501A3634A11267584A216F365614563FA327686CA32B38E3102E7305E48A7DE910737E688351E94DA054CF1D17944305678000BDD9CC8B93333660A85AE6B8C4612A6535E5AE8C959125141E6536AE662C741AEA0D783B53962B5CC612750AB3AEA3708445EC97B2BA1EF3589CE9F94D3A4B91E4052A746635A595568640B375E5872E30777137874A429A4741AA81CA63A90884E54527A48B84F274C0E04B92386304D50048D78713BE0A9008A69DD49CB886CB6E7BFC7CA9EA03F09896D739C292C3021B2A985CD858DE5A574A7C431CA3795CDC436EE58596B10A1507B60267B1C735BE22E05F5E6AAA12F132FB932DC815B2411CAC97EB729EBBA95D5C1CD7280A339CBC56E85D00763A1B6A371735CAA1B8A699C431EFD2182366AD4E7B4765E9A842ABAB175128AD4127BA447157F56098B3C14C561502406531FA06863C85A406494CF330E591BF58FC0216B9A66CFC39EC26C10FF97FD50017CEA705363B0BBCC9874BB2BCD0AB08631140923AA88E0AC43531757C689F3F075FEB3B59767BC1A327C1EC8A7E0670415ABAC9D0CC1D7854620E8339B5456E3D5A1AC3562E8F78808611CEEDB57BF0DAA937CC8E2C1780DAEC6FD08ACA72876EE010C290AA6136EA91E71605C6F2BEDF89B9519A5AA353C3E7415F4D4915907461C1A0559CEC7232F7A90A17821C84864739CDA43C7C94A63197DA4EC3E82DE870CCDCE4988DAB713530B8CD889A010A769DFC148CC896C2AA00AE28041B4AC0905373408082992142F61B817152609759807105C2A43C508FBB4748F094DC4A2EB6330A70543B405CC34D1842F6711B41F790E82316F6A44CB99262FC4338455863515AB67FE6898D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A217913DFA277AD62F7CAEAA930284E348256EDCCA5578A06528678CBAD23F0A8DE1D40BAD0A76BA218C111C0DBB15963741113EACF5407A795D689E6E1EF1DE8B0351", + "58A1D50BD43788B872FBEA3B765FD9CC911352CC7C4A6DF1C37B16B33EF4E58C4C94E4BCCE87E2F40B3FE6012216C49F0DD147EED2CEECE1909C626659C29363CFC9C5CCC147FA5A4C54A0755F9ACBD5EECA6C058E3BB27B5F4B762435A2F9C4C9F3F1BCCA10F49CF79AF6407ADECC839137936922E802803B906FAF2C2F61A58EA70256A8F344810CAB862A5D205D01D9454731143461FEFBB15216E3AF8E013B8AD62626A9B6BA3EC8D8E936EE95FA368FF8B65D0622DBB6EDE36B849066019A57FF0D858B6D6B3D577573688A7930440AF4DAA2EE22478FFC3230C2BFC28982B11DBB475C77561D8A1ADA11E5A79DA2ECF8519C2532B969BFED42B66B6B2052DC1D02B11640AD354AD11805D26CE1888A9B1971F8C0345AA5919B722F97FD2F13DDEDF82F275774928AC437016C7F917C67352984B0C1B9AEDC8078329E8B51DDE09FE46DD5056E0BB12C42FD7690ED529ED13EA628813D4BCF524ACE4A0C98856B0216872D7A3567392F4DD37713115A03993618E3CEA8D9B6AEFFEEBBBC27557612648BE6B3EDAD1B97CC99516E394C9A4888D5F4063F2A37A8B32C422195CB2F9E7E17D79DB17FAC28FD7EF0B327E6101B5733479FC73E4AB9EF654888715EC4C4E1FA95F1D4D6DD1BAE0AB249C371F6937C86C6CBC77BCB9A7F0B7AF45591EDCFB73903106001869B46D9894F7FB5FFF7A5079ED46CB0B596BEF936859D1E7B32820C2138B5546AFAEF00274EF86B179D796C5624143E8F500B8D9AC2EC4607088F97D74FE8183DE58C9152A1B7C510F7B00D82A0E3F8A0463D00AA168E238E0F19E6A14041624409AA4FE212D10664E6CBB0FA5D910A8494AD5054C69961444C3A34DE8BEE095F2E757F9AFF846A8AD0F6D3090A29789BDD5A59782F80CE081618A407B58C9E2AC05866AF57CFE915F261D18BFD29C7308383A716C75BFE357240A93AA410941656D62F0E1C3BE6C4487594E00838523E1B88B68A68C7BFCE22EB805C91E6E2AB3E0369EB4F077B3064B2106ECDB7FACB419631E8128B1CE21BFB51F52C2B0841160A4815E0524FEDAC9A75D014C47ECBA9580E7FE9", + "6D7A3AC0A410D5457233E862F2BC5A4ED3A5ADA47070A888AAC44599AA6A6E5A" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "8D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A21791", + "FFB93E594AB462B4070F2684B3845649B96474760BED1BAAD22A38B2667B7765C504B03D65EBB1B88B613C978518428097650320821454B971C3107962E00E4A575EADA990B1B945BE845FB9411D9C8303224B7CB1D27E0286213C1AC1052C363ACA3B0C053FAF48577FE4107BF35343FC39F7A5305A98AB2CC315A84C5C60D9940E409D65B63BFB3694FA249556F87BD27C28D00A62A3299FBAC0501A3634A11267584A216F365614563FA327686CA32B38E3102E7305E48A7DE910737E688351E94DA054CF1D17944305678000BDD9CC8B93333660A85AE6B8C4612A6535E5AE8C959125141E6536AE662C741AEA0D783B53962B5CC612750AB3AEA3708445EC97B2BA1EF3589CE9F94D3A4B91E4052A746635A595568640B375E5872E30777137874A429A4741AA81CA63A90884E54527A48B84F274C0E04B92386304D50048D78713BE0A9008A69DD49CB886CB6E7BFC7CA9EA03F09896D739C292C3021B2A985CD858DE5A574A7C431CA3795CDC436EE58596B10A1507B60267B1C735BE22E05F5E6AAA12F132FB932DC815B2411CAC97EB729EBBA95D5C1CD7280A339CBC56E85D00763A1B6A371735CAA1B8A699C431EFD2182366AD4E7B4765E9A842ABAB175128AD4127BA447157F56098B3C14C561502406531FA06863C85A406494CF330E591BF58FC0216B9A66CFC39EC26C10FF97FD50017CEA705363B0BBCC9874BB2BCD0AB08631140923AA88E0AC43531757C689F3F075FEB3B59767BC1A327C1EC8A7E0670415ABAC9D0CC1D7854620E8339B5456E3D5A1AC3562E8F78808611CEEDB57BF0DAA937CC8E2C1780DAEC6FD08ACA72876EE010C290AA6136EA91E71605C6F2BEDF89B9519A5AA353C3E7415F4D4915907461C1A0559CEC7232F7A90A17821C84864739CDA43C7C94A63197DA4EC3E82DE870CCDCE4988DAB713530B8CD889A010A769DFC148CC896C2AA00AE28041B4AC0905373408082992142F61B817152609759807105C2A43C508FBB4748F094DC4A2EB6330A70543B405CC34D1842F6711B41F790E82316F6A44CB99262FC4338455863515AB67FE6898D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A217913DFA277AD62F7CAEAA930284E348256EDCCA5578A06528678CBAD23F0A8DE1D40BAD0A76BA218C111C0DBB15963741113EACF5407A795D689E6E1EF1DE8B0351", + "7F0B3336C74E01C6D3965CFAEB2FC8E3F76A7A15289E2A71E4B29F68B961786699DA603AAC6C27346E7E2DEE36D07BD4075007654FA3A38EC2885C204B4037FC247BEC1A129BC918A7EEC0BDF69DD181918875E6335D6803D882B15119C135738D636EE0A08CACF8434E968A0F4BC510FACB6A73E5F51E82A90DF199BA40C727772F3212918E7C7FE5CA720768C4E40EFFF2C341B50036EE286C6AF559026563256DDFC5E59CD4C9641B3F6B914970544128D16430AE1C0635E498818E7032C432306FDC41EE93E163867FB5FBE6FC35729FC6277D10A83ABF16190CE4450C1558FBC807F578B2CFDB10987E1CDE0D1417475D191825A4C31A65961E2C5894BE974AF20757A20D00ECA9F6CBDA704BAC3B94A1E8212D05DE26F33F26A1EA3F47E498BF0101A517F91069977425850847AE8B2D1F832C0987E8C44FBA4A57D773E85D8195CB92DE2FD8D6FCCA20EE700001295AE314C2ECF75CD90B6EDC2B0D206A00CFBB20AF2502D3FA64A1AEF7EBF982F9CF6ECEF15C83ECEAD7D0A35680E4C3984AE4A66F45910256932BAF2BC39C1DEB6F3CF1B4F96CB631AB9F2077C17EF6EC801044DB8B69AEB3DF1B983C3A473856994AEA20FFB0E004255E7A069217A44C42C8637C7EC8D921C8A37ED0C49515874ADF22650E64C569BABDAF493444FCDAF7F2CA4BF456ECB017A74F1C8BA79E1F5FC8E3F37472C4FC1AE1DCA976D418C775E029BE5C1781D4982C29AD8B4A077D05932700D821192066BC987445B164CDA9111954CA18FD4AC9E19E97A7193054D8724A8FE449997F157D4AE8F5C987F34E849EBA3A8055C945B6423C915544C4C15B9D3B7AB4698DAA792D62DEED7DD7FDDC73AC378CCBDC2479A0B7F7616405F23A9B98BAC787282A2812D0B4E27C1230FBA11D765DE5766FE51047E411DD9A47B4C762F013B90FAF727A70BEF3E4699B0991C36A0B86A071DE39AE7CCD7ACDE7C016BA396EFCB41BE92B9935FA5C6A154CA799D3D6DF188FA33DFCA6092B05F1F24B05D5890523E538F16BCAF6E64DF926BB26C06D1E2DAF5E597A0EB06F9E6357F3828F66262D530BF09C24EE", + "B532BF7A54A929B96481284CCD33558EBAAF080763A327A2F1EA81BE52A0B171" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "8D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A21791", + "FFB93E594AB462B4070F2684B3845649B96474760BED1BAAD22A38B2667B7765C504B03D65EBB1B88B613C978518428097650320821454B971C3107962E00E4A575EADA990B1B945BE845FB9411D9C8303224B7CB1D27E0286213C1AC1052C363ACA3B0C053FAF48577FE4107BF35343FC39F7A5305A98AB2CC315A84C5C60D9940E409D65B63BFB3694FA249556F87BD27C28D00A62A3299FBAC0501A3634A11267584A216F365614563FA327686CA32B38E3102E7305E48A7DE910737E688351E94DA054CF1D17944305678000BDD9CC8B93333660A85AE6B8C4612A6535E5AE8C959125141E6536AE662C741AEA0D783B53962B5CC612750AB3AEA3708445EC97B2BA1EF3589CE9F94D3A4B91E4052A746635A595568640B375E5872E30777137874A429A4741AA81CA63A90884E54527A48B84F274C0E04B92386304D50048D78713BE0A9008A69DD49CB886CB6E7BFC7CA9EA03F09896D739C292C3021B2A985CD858DE5A574A7C431CA3795CDC436EE58596B10A1507B60267B1C735BE22E05F5E6AAA12F132FB932DC815B2411CAC97EB729EBBA95D5C1CD7280A339CBC56E85D00763A1B6A371735CAA1B8A699C431EFD2182366AD4E7B4765E9A842ABAB175128AD4127BA447157F56098B3C14C561502406531FA06863C85A406494CF330E591BF58FC0216B9A66CFC39EC26C10FF97FD50017CEA705363B0BBCC9874BB2BCD0AB08631140923AA88E0AC43531757C689F3F075FEB3B59767BC1A327C1EC8A7E0670415ABAC9D0CC1D7854620E8339B5456E3D5A1AC3562E8F78808611CEEDB57BF0DAA937CC8E2C1780DAEC6FD08ACA72876EE010C290AA6136EA91E71605C6F2BEDF89B9519A5AA353C3E7415F4D4915907461C1A0559CEC7232F7A90A17821C84864739CDA43C7C94A63197DA4EC3E82DE870CCDCE4988DAB713530B8CD889A010A769DFC148CC896C2AA00AE28041B4AC0905373408082992142F61B817152609759807105C2A43C508FBB4748F094DC4A2EB6330A70543B405CC34D1842F6711B41F790E82316F6A44CB99262FC4338455863515AB67FE6898D895727F11672FB1A064C7A1F53AAE3AABC55296A44C3758BACC25866A78F587B6804548EABB93F70A931E0576B3584A075BBEC98C14BE62846E579F01542C5125E29BBC449E4BE2A14BBF879192FFC272B0977876895F610B2E5C4236533240D07CBBE67412E8C7B3A143542F94B73BB776EDB8F079136AF08883E30411A6AB3415340698837C9F6B314A206E2A7906275BA04DC442DE87D00D57C6A35B2CEABB4C0CA9366B6897FF03D2B212169EC7555FCC462C568C9E3346203A9AA5064A2F4ABF97115E5E2C77AD9101D5502554A26E5366FEE2177E33055956224CF522B2FEBCBEF3C4631354077153ED996C9D8D2961153C373D66C3889087D7BCE35378DA5F32EE806A3D525C6A243176BE5856B687299A56331CC4C448AA07C23BD937C0FDB96C118485B17250A9BCC464B8046A57C8D1DAB3DF5D751C8C2B2999A3BD4F134DA7740D4948EF0A796C5EB0BD2D6CE75B853CBA17EA1F2B1DD2025C6752FEFFA324D463F722898821A537B78812F52921622111EE26E69450D5934238A6A5BE752169BEA78348A4C22434EEAB726D9E126BCF8951915428CD18CD771426B3A984E50B4D7F303392607C217120751942C4CBFE07A21862C9B0165565A487DD0E72EFED935EC99360933923AF601C097BB99312EC8F213F5D53D56687E89FA1E3E9219341A62953631551A568115CD56A20E1B088900CC286125AE8B450F8428269D943C2354278B184DC135BF79345A39601D33FB901B97467D950E981644E2C500885A7D9B3243AC3463D755A57F2A659108244A070DE13154F83A06CF4928741568505965E1E06D6501540DC8972FDC951A862C6A35CCED9245D1B2B85933550D96B60FBA9FBAC34888E87B6B335BE41AAA72447FD5D9A64E529CD29A365B6603ECF9736429B02FE46FBAE82EBC8003E127508BA518303382655C51551CBA7F0A48C4E58D1052C6A1648509E308A3F95814D7138DD28ACE9306AA0529A9712BB6827AAFAA6CAB67CAD96CAD4FF4903CA02954D26132551961C0B680000F01DC08CC361BC9FB449D455793CB2659D800016C87A1B98433CA191CC663BDD64304BEBAD0D3333C2036619F936ACE5A0B62805EA5FB49D9AD8106A217913DFA277AD62F7CAEAA930284E348256EDCCA5578A06528678CBAD23F0A8DE1D40BAD0A76BA218C111C0DBB15963741113EACF5407A795D689E6E1EF1DE8B0351", + "35F0EFC059699AD0E32C2B349A262661CEBE7DC3AFDAE847B3F30ABC14638B9EB3072F850CC0B7F71672441C12D27A355955CACFAA404C18A2550872CD6458CAFECC77B77E403F05F1E52585D4EF03B3918585C1FA53A154CC120457CE3A2A9DC472F160AE5840222A301F44D5E34B671D664E10FC71108F1A3934704432C00F4E1C244882938FEA598C64BC12234961A92357F4237C3EEE9517C50B4998049345B28D28E434EB47386185439A39C9E8D1BC0265276DA6C2DE621A45D2BCE109612785913DF508198A88171DFC4582BCDFCE3232EFE2D22633AF0EE70A198B72EC0F7D5ECECDEEBEB678273F459079E810BF95D1510FACE9C27A352AFC513EA369A770E49ECA43C286B460FECE7B0DFEFE74F32FBD0BEFCA954130A15DBFC4E714DE083E38FEA4FB7BAB28FF7034A97C6B50F0BD77C76B039302D5A0376022A7D3952E290054AAB9DBB9E196874BE23E9FD7B9708AABF38B22B41024D37AF2C6C38ED12B4196ED79B99CF36244A84F7AB94111016127837CC21842C1AB14781D318519E4C05CA5BAAF7A7332AE26AD67F6298A295046C432D52785A768C4FDEF981974C299A19CAEC9AB1ACEF3B911A3653EF5DA6D9D15F0799A7F08CCE77629BA818341037EDAE829DEDB6B905A484A5916AC78AD0654B506950DE6FEE550056AABC63764F996FCFF57A66B44153AA02613D74003ED5AD2216BA38B951D21FBAE7CBB5C422559DF6CCE9B8F38F2BE909D55851E4CE80A97E5FB83FAF63016B810755507A88297FEDF0450E13EB961B26F1BB6C885BF39DADA5652FCF227645A74C44AF060F2B219D60B2BC536732CB6471138EFC377EE6421B529FAFE5E49F44B69376E49429132F21313F6706D7F7030BD7049F199798F78B727895AAAB38B9FCDC7AA70D80475A9A40ED9F4023DB1ADD41DC406333238C7C81361A0F704B0F9C295416F6F06CDA2154A531424A51D5C24EACDB51F21C96A0183C4FB177FF4BFC48DDAB3783EC041E920829C97B3A37DA7B7F3C78D29A46762882665203761AC906E9FBC1E788FA5803F05F9E16642372DC463E79DF833C72C510844EA3BB5", + "707365FDAD892AD8725A50D5DBCE635DC80F6D4D6B5FF28CEE1FE361C067BB32" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D1602", + "21015917953F3926871D0BB9BF7802978493FF5A24D684CDEE1B76681902FC8A9B63283C362C33FDB2385419462F4AAF9C6A9588F06A5FE52F2BC923F87123B0099D0A2B456D350B21050F14BA0EC2A56974C9A1403518330C809DF69966D55FBFB70DA27136DE5793F7E73C71ABA60A5906CD36C5653A2BECACC4459756D9E37E14E6587F40389C0895E94BC5C105C4A394098F3A5F27EBB0D4E5B338466F1C964F79322E0CC9AC17B68BD6D20FE77996A740ABF95790B69168320C320BA6602B9624CBF12C84F549E6C40CCFEABD939A934E46A8C63CB627E499D9936C8BE3927294523179224307872F9B8667B175349BA867CABC3DAC47A48A46BC001B647B7AE03878F55A7029894173039D8D1C1F9F49BE12E88743DC709F101280662EE604CB25E75215A570D3FA03A88867E8C4A84F0351AE051F90E36441366714545236CA643BD8B85FA947ECF4A536C13DD7CC6BE7485405C0CC204B91244B364E7A33A60494683A99F5E3C21BF57379061AACA63E569C0E82164633A691BE803B2CD9464996C050323C21080E8C0822730B904FFA7A656C1B568708168A4CB1F54377A02542C42694BBCC38B4CC27F7B735418346FCC8D09B52E89B8F88627BDFF73A87A07B58299AFB321B0BFB1228E53DEB899AE7582066520CC85276A0236276738B58231FC610C3C40B326C4763AFA309435B05AF1C66E84C49430B98F7D4A76A843A627693BE3A67F57C20140B94ED694A1F671C0FD378DA3CAFEED30E5C366C3509AB1E14AB1E08D029A18BE1200D1A8916A1F011B7D0A9A47860F0B09DF996939D2377BC53B7E7CBC3A9517C31A78BFA724B6DE96EE101782C0641E2EA187375B8E5579426995BAF9C30466C4160780F8900867DA89944B1AAB84BAA7F987ACF2AAD97ECA9C222BF2C34BA5F8BBBDEC2C434E43828696FC38903F4C3B7DDE727E1D36A71F9BDBC71C878A3399D346669924E1C3CC2B2AA0DB08A0F30FA703DC308E54857E4142846F9235A48538E291D683409E25CC5AD1C56B690039DF5AEEA596F52AC991E1B3D16E809BFB723A7004A0DB59F0B40885189C88D4CBAEF3ACA2951314ED90789E366EEE8AEEC84798FE931CBB3A42E847870ACC06B3885C0EB2DDE149DD802C1F32953AC20CB87899C0855B2E1D6B8B5F6929D3B9603C73BAE5C528509AC1FDB34FAB2C63773C44195010CE80A229696CE075ED4409A0D0CAA966B20D6C356C4F44272E1501B897159D544F34B7C3B0280D7FC54E223AD865307BCB36CA13729FBD36DB285CF5650C7FD451CD8B305280338C7460385464672D73C5D30A4301A611DE6751C76CFA0BC08D8958F9A170C6D0ABD75007327E891A874181BA87A9260C14378068F183EA9E1CBE1E571530856D7118D9F1AADE546691BF328E5460B114A7DE834B2B218B22BD4C83A3A4580B2C59B325B1BC68231C3732F9AB666C726BC4471E204800C27783DC8BCF6B6315FA8ACE005CCCEC92116D7B34490880452A82098B692552279609D073CB0FD58C82CA888673A093F4696F7A4CECC169DFA336FC736BC995615496B9FB527C83A6192F893386C122B6C5C67E51352A7CC6CA4A7ABFC4006E6105DC7838229D44387C971375933DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D16025BE307C628551E3A1503B1D1B2C2F92108D98FD965AAF9949B00BD097F17B8B0631B752A02D85CCC07627E044EDB8C61E43DCF8A864DFE086D28C2D72CA8B428", + "084E32F1DF38B6A73FAF446541B746AA3F026119FD6D53410FBA8DCAA060AEE99E5A325ADAE77A4157E0F6372B5F34D24B05C2D6BF9589D9CFD8426C73464C350757DD655C35F577664CF2FDBDD1C8455E0271185494D6D2A42DFC62B61367B2236D6463A3A55F225BC7E66FF42A9C06BB419F7DF5F26A343792B82A81BA6F450D2D3F91272518879D283A6F4C1E4C58918CA24357FC4E38799635BAE556BD6D47082E71874C7160DD5F12E2295C39E1E148ABA3D58AD86998FFDCE98E79A0E3CDC3D7BAB4EDAD60975A494870B12E0DC53D33A33A645ADA5743E3B65F2D0F9BE54E2CAF124199584FC1A0DD9008DCB372D045FBA0D1BB1FA127E0E00F6FA03E0B8EC677371FF9B1A135696F7D79344AB7FEC2D21C2CF832B3A8708B2B80865F68A29FB86A419C135A69C3BD431961ECDF12DA631FAD16017A06BB8D1F04A9412A7CD8FA1BCE38E27ADABBCEFB99A0470694C5018E7FA4F3FA53FEF1095526B6644E999A645044F38C1DEA7BF8D9FE0E778A22486EB754FEE50CD6DD4D144E622B0D0856C008A657F4CA32A3FCB06F20A9AA75F8DFA15689B225EC64C790FBE895457E2C5707A43FAA8A5A4D5DE16B0434FBD55B6306D96FE74A5556CAA56A7AEEC92E6DE19DD83CB874D6A1AE599C0A24C5FFEE10170521E300D67EB35F5286F70D1C9D36BB72E43C81B3EFF19D2DB06B18D45C94D6B451BDFD23BA368374FB21A7371A93887F5AF30CEF230FE6A7F31B65CA27E7817195A812FED07155F0F5279F8ECBA5842292C194E03822F73CEA74BAEC375C578B5E32488AE8001E00D09F379B0E033804AD124FC0785E5091EB1679E927DEC51A6655039EA7C87657D1158DE0304881ED4F9C18AA2E8875D5A9A78BD211DFB2DF89C442B89C78BDAE7187044638DBCD6F9D99319FBE52775C4FA2CCCA0B39099E687ECBE334FA75842879C73573833510E41FB453ED8EDA633374B69B9E2717ED824F8B7DFEBBD2A5F14BF9885AB9DA241D2ACF97FD00CD3CB4D7844859579115F994AA4D1595502E646F2226E66712715D7751775220717A277FEFDEE5ECE96AD4181B953B617C4986BF839B6E79DE379425814D69885FC45B050786F7B559AC44046C8F58478CCFC2C02D7ACC699FE615226701E7F4D18567E755E0C1A3C3EEFBF51C45A6FCEE3FE0CDF24CCA87120BE2A18A50E3DEB4DB7EF35BF2BC8A5C0F5990220E73DECF7CB00E54D2D4CEAAF996E920A7F8004271B940B8F7A79C8308D9782758040EDCAA45C5337DDD2149DC8EC8B5FDD50FD77DF961C5ACCD3852983FFD42AD9C0AC2800EF86CADADA670CCCB280147E89F791E4FF092DC59016F0763AC38E23F2E4F9737812984F0B2A674C5E5AC764CC65B70BFD0E9CE2E4C3345FABA845BCBF48C8F785E04B50D3972BA5108E32B5AD3F32095C48CDDBB12E597A18732FACEA5DB9F2F980DD220F58C1AAE13A246F5C9783AEF2EF1494EB9C6FF7C197A02A4D58C418012867A62D9591F445D99E88F90FAF629A8C5FEF87BDEF2DA8D66CC588DF252EB", + "C4E4EFFE05FA703BF8D2F1BDE47FF70745EEC5A5C039FB7B41A45622F14051E4" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D1602", + "21015917953F3926871D0BB9BF7802978493FF5A24D684CDEE1B76681902FC8A9B63283C362C33FDB2385419462F4AAF9C6A9588F06A5FE52F2BC923F87123B0099D0A2B456D350B21050F14BA0EC2A56974C9A1403518330C809DF69966D55FBFB70DA27136DE5793F7E73C71ABA60A5906CD36C5653A2BECACC4459756D9E37E14E6587F40389C0895E94BC5C105C4A394098F3A5F27EBB0D4E5B338466F1C964F79322E0CC9AC17B68BD6D20FE77996A740ABF95790B69168320C320BA6602B9624CBF12C84F549E6C40CCFEABD939A934E46A8C63CB627E499D9936C8BE3927294523179224307872F9B8667B175349BA867CABC3DAC47A48A46BC001B647B7AE03878F55A7029894173039D8D1C1F9F49BE12E88743DC709F101280662EE604CB25E75215A570D3FA03A88867E8C4A84F0351AE051F90E36441366714545236CA643BD8B85FA947ECF4A536C13DD7CC6BE7485405C0CC204B91244B364E7A33A60494683A99F5E3C21BF57379061AACA63E569C0E82164633A691BE803B2CD9464996C050323C21080E8C0822730B904FFA7A656C1B568708168A4CB1F54377A02542C42694BBCC38B4CC27F7B735418346FCC8D09B52E89B8F88627BDFF73A87A07B58299AFB321B0BFB1228E53DEB899AE7582066520CC85276A0236276738B58231FC610C3C40B326C4763AFA309435B05AF1C66E84C49430B98F7D4A76A843A627693BE3A67F57C20140B94ED694A1F671C0FD378DA3CAFEED30E5C366C3509AB1E14AB1E08D029A18BE1200D1A8916A1F011B7D0A9A47860F0B09DF996939D2377BC53B7E7CBC3A9517C31A78BFA724B6DE96EE101782C0641E2EA187375B8E5579426995BAF9C30466C4160780F8900867DA89944B1AAB84BAA7F987ACF2AAD97ECA9C222BF2C34BA5F8BBBDEC2C434E43828696FC38903F4C3B7DDE727E1D36A71F9BDBC71C878A3399D346669924E1C3CC2B2AA0DB08A0F30FA703DC308E54857E4142846F9235A48538E291D683409E25CC5AD1C56B690039DF5AEEA596F52AC991E1B3D16E809BFB723A7004A0DB59F0B40885189C88D4CBAEF3ACA2951314ED90789E366EEE8AEEC84798FE931CBB3A42E847870ACC06B3885C0EB2DDE149DD802C1F32953AC20CB87899C0855B2E1D6B8B5F6929D3B9603C73BAE5C528509AC1FDB34FAB2C63773C44195010CE80A229696CE075ED4409A0D0CAA966B20D6C356C4F44272E1501B897159D544F34B7C3B0280D7FC54E223AD865307BCB36CA13729FBD36DB285CF5650C7FD451CD8B305280338C7460385464672D73C5D30A4301A611DE6751C76CFA0BC08D8958F9A170C6D0ABD75007327E891A874181BA87A9260C14378068F183EA9E1CBE1E571530856D7118D9F1AADE546691BF328E5460B114A7DE834B2B218B22BD4C83A3A4580B2C59B325B1BC68231C3732F9AB666C726BC4471E204800C27783DC8BCF6B6315FA8ACE005CCCEC92116D7B34490880452A82098B692552279609D073CB0FD58C82CA888673A093F4696F7A4CECC169DFA336FC736BC995615496B9FB527C83A6192F893386C122B6C5C67E51352A7CC6CA4A7ABFC4006E6105DC7838229D44387C971375933DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D16025BE307C628551E3A1503B1D1B2C2F92108D98FD965AAF9949B00BD097F17B8B0631B752A02D85CCC07627E044EDB8C61E43DCF8A864DFE086D28C2D72CA8B428", + "471773AF71058A5ECD58972E92A786BE8154871AE947C83025005A4F3C8D7B3F633D715FCD058431BA2CBC7E335BF25EC01A746EACC15C7538D9D1595719DFBE7E7D17305A476D816FDF3939968B97934607A592DD9EAF425A80BE250A3220763DA9BBC5E757530CAA2E188EDFFDB50DEBF6679A7C9D6650BFF7B4FBBBB7C857CD53F71C7DA5062F0329836185F5D01E8906E10C0617EA54D2109E7B13ABA51C645289EE592BAC10269B3F18868DA72839F2456FDD32B53A67C4B7BA0D67A2BF0547B0DCFEB9C626BCBEA28E90BE3A71B01F2236380F0B752A4A5E0AA680B1682F49B1B970489BAC43CFE84A2809FCDFA1BC2BA7616451C0BD65C6B5402C6D479BFF759183D0C35CC89A182BFD90B0EC368DE8B26D5995E4BC95215445701BD5F31453F578F4C5B1380E4EEA53155B9F7C73C349E8814EFBDBDB667CE7B1FDC34D02C9672A3573EBD65B1903C79C6DFEF23445DC732C4B694EC2C946A78FF7E7E3AECA89A3DA169AD7A0C9DCEAE31DAC66EC0BD66208084576C059E1F2E5F38A033A1B5C1F4B0A4F76145E29B9C47A889A47D45534640651EA4285447056FFF0167ABF1C49D16560A98DD3E2741EB246045AE365B9507B3DFEF050E43503C5A847B3BDC77E7FC87A00B4CA0519010AF0E4719965CB9F80FA3FFD2E8A149332968E81E4291F789C77B16098611E0E229227B0911757F57F4F57B9B26690191310D0714251E7460FF94D1E93B004E8716F7AF19F3F675158206662C55007039FD6F23DD54E600A39B352010CED4254D53B66A85E4B94AE985A53471F4686A483474A183F5E08A3BBDA7B1BD7708DF06800510AEB111B12ECD5C8F080D4FD165BB47F3EF6DB08175707BDE1AD3AFA560401A9F4F1484C091F5B4055F55D5394407BACAFAE553AB2F0D9A15BEFD9BE05A08614A30D55460051572D2FBFA5FD8CC0F8A9E1BA77B37570F12E4521853FA1787E6A688D5827B852FFFFEED93C01E96EC979E3288188066708339964F393B627C516BCB9460A5C9FE44F42C02432D9CD4489138F773640CD6A4D8EB188073BF95E0A40FE9BB6D49AB19BFC1BA31CAF36C2FC6535B587BC6164598B3D8E1C17BFE5D31C4D3834993DDFA54D08D1EC5F54D2A7A2FF3F11C00259D5352D94330F564177B2FB1F20F793A422F487FB6ABC7A3980241BA64BCAB5C1DE337C4A28C787B89603A581CE90788E43DBE566F1BE9CDAF70DD5C2DB269626028B5A3D6CCB1954D04E83312EB1FBF9E56F29F7A873C41021F9FE67B93274DBB03C2713C843D8B153087929E5B393971C9175FCB8D193870DAE1FDED1DF282281987C0617DE7AB275AB3782EF2EAB8F736B3F1181901AC21BFB6BEC1A071B76F622293050F4D632D0C538CC636F9E1CB6E5CBF611DADF9016DE70569CA8B31D781396F4490520A287E5BA155B388A2486BEE900397DCC033EFC09DEDF6A0581A0267176EDA21948CBC024C9B798CD2AA56A0F121E46B0D626AA2913513F7012CF17D9CF4488B193F921BB38EFFB6D67D158F16D0F616FDE", + "8EC48F32FADDB6C32DE93112DB405CE8BC525BD8FB9004999CC8AF13448D9B0B" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D1602", + "21015917953F3926871D0BB9BF7802978493FF5A24D684CDEE1B76681902FC8A9B63283C362C33FDB2385419462F4AAF9C6A9588F06A5FE52F2BC923F87123B0099D0A2B456D350B21050F14BA0EC2A56974C9A1403518330C809DF69966D55FBFB70DA27136DE5793F7E73C71ABA60A5906CD36C5653A2BECACC4459756D9E37E14E6587F40389C0895E94BC5C105C4A394098F3A5F27EBB0D4E5B338466F1C964F79322E0CC9AC17B68BD6D20FE77996A740ABF95790B69168320C320BA6602B9624CBF12C84F549E6C40CCFEABD939A934E46A8C63CB627E499D9936C8BE3927294523179224307872F9B8667B175349BA867CABC3DAC47A48A46BC001B647B7AE03878F55A7029894173039D8D1C1F9F49BE12E88743DC709F101280662EE604CB25E75215A570D3FA03A88867E8C4A84F0351AE051F90E36441366714545236CA643BD8B85FA947ECF4A536C13DD7CC6BE7485405C0CC204B91244B364E7A33A60494683A99F5E3C21BF57379061AACA63E569C0E82164633A691BE803B2CD9464996C050323C21080E8C0822730B904FFA7A656C1B568708168A4CB1F54377A02542C42694BBCC38B4CC27F7B735418346FCC8D09B52E89B8F88627BDFF73A87A07B58299AFB321B0BFB1228E53DEB899AE7582066520CC85276A0236276738B58231FC610C3C40B326C4763AFA309435B05AF1C66E84C49430B98F7D4A76A843A627693BE3A67F57C20140B94ED694A1F671C0FD378DA3CAFEED30E5C366C3509AB1E14AB1E08D029A18BE1200D1A8916A1F011B7D0A9A47860F0B09DF996939D2377BC53B7E7CBC3A9517C31A78BFA724B6DE96EE101782C0641E2EA187375B8E5579426995BAF9C30466C4160780F8900867DA89944B1AAB84BAA7F987ACF2AAD97ECA9C222BF2C34BA5F8BBBDEC2C434E43828696FC38903F4C3B7DDE727E1D36A71F9BDBC71C878A3399D346669924E1C3CC2B2AA0DB08A0F30FA703DC308E54857E4142846F9235A48538E291D683409E25CC5AD1C56B690039DF5AEEA596F52AC991E1B3D16E809BFB723A7004A0DB59F0B40885189C88D4CBAEF3ACA2951314ED90789E366EEE8AEEC84798FE931CBB3A42E847870ACC06B3885C0EB2DDE149DD802C1F32953AC20CB87899C0855B2E1D6B8B5F6929D3B9603C73BAE5C528509AC1FDB34FAB2C63773C44195010CE80A229696CE075ED4409A0D0CAA966B20D6C356C4F44272E1501B897159D544F34B7C3B0280D7FC54E223AD865307BCB36CA13729FBD36DB285CF5650C7FD451CD8B305280338C7460385464672D73C5D30A4301A611DE6751C76CFA0BC08D8958F9A170C6D0ABD75007327E891A874181BA87A9260C14378068F183EA9E1CBE1E571530856D7118D9F1AADE546691BF328E5460B114A7DE834B2B218B22BD4C83A3A4580B2C59B325B1BC68231C3732F9AB666C726BC4471E204800C27783DC8BCF6B6315FA8ACE005CCCEC92116D7B34490880452A82098B692552279609D073CB0FD58C82CA888673A093F4696F7A4CECC169DFA336FC736BC995615496B9FB527C83A6192F893386C122B6C5C67E51352A7CC6CA4A7ABFC4006E6105DC7838229D44387C971375933DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D16025BE307C628551E3A1503B1D1B2C2F92108D98FD965AAF9949B00BD097F17B8B0631B752A02D85CCC07627E044EDB8C61E43DCF8A864DFE086D28C2D72CA8B428", + "7D092F092F100B95CD9E18B6DC23C39A8B7EED57229EEE522368CE83A23C766FC3302CFFEC6BF67C558BA2F5F20F277879B8D676C75CAB877A060BB4DBCA827F4E35D54BBF0067FB0DCC82702610CFB7DCC90307D733CF59CDA8A84981BD24DD3E146D17C3ECF2DADC2CC973CE3AE1D2881D143A1A55B60D0574291F7E1D77C9D8EA09F71C7F9285DDF072850386B0718D14E788582A92815661EDC2441C57529F63B9F0EF9846C1ED907FA1712B37D9814C70DFB5CB63B385586C1C4B7E91A900BBF532041EFA0EA49358136E916DCA2FCCE4E17BE8A2FF3295BAEBE474C5257069102A50CA9801597E5EFE64DB41A7A82E22B1291F83945FED077F4360F56329CDF2063C3939AA1B284C6BAB65A1DDF20BD97E17B41D03098544B56242FDA328FCD7F69DD372A05B8FDA48F8E5CE27F1B2A917344078000E5CFA5C498FDDB77256827226D63576B51B6BC8ADF81C6FDE9343D469FC866968A37AE506287945AD358FD3E8A3A37FC7FC86DBA5D29CA91F7C80E62D1341B23539A96B38DAE2FC4B615BCE7A3C44448D7ECF7E77B60DC2FAD8BAB64FA3EEDD9F1F5A92F9AF7832305705EAC6BFA9E83D0D2BF162A567E82E59E763775983B5ACB6669AEAF70E756365C14951B963410CAD7944A9AD8D8229D18F0871D8BAEE7C241DC69C0B525B08817593FD136555837AD2F580ACA465F75D1832681652E0ABF66976096AC9A72509A9C34CA839AF15FC33F25B7234EFE562B5EB7597D116499C56CD931EE99611619029A6D5EED99A03C7A45E1FAA6F82BDEC813BB39183AB62721F7FC1BEDAE5BE2F1D1CB22806C9992C1DED298515A63A9C8DEAC6B094F56C363FECA93C2D051E85AC1DB7A153A511A7B3EAF0EC7D29F8B593C2A77BC93E649BEFC306A4AA766099F4FC9FA30882E9790D0F3A77001989CCF41C58EA1562FBAEA842E20502650848F2670D0B9706122678FC910865BEAB5977649D6B04438AA77FA49D434C30F4946E53DF2AD529682C68E20DC0CB0BEE2FA1CC507F73E42645B40971E211C6AE319955168EF22D85FB7EFD9E75408121B0BEA27B537DC088F044C2B7831122B494A356EED1B306C8A114D668EFBDE1F75DCD07AC7AC832449B6F15B0ED9B9CC70482019AC8A3799C1A5EF0CBC1A3CF0B10DBAF16A61795EE27E35C0202AE18CFCDF0BA102D6E40DA93CCDF09C529ACE87C09EBA80D63D8167F3EF89020ED6D1EAC29FBF40912E8D3595B57059653445BCE7B8AF49B575AD4C14D9CF2218865B6FCCE13533C06B15E94B6B8FD1341CD56776E17AB9B2742BBDDA91450527336C596711B236F52DC63357C47602570495BF208D3D9906AEDD466A0C0518910D0954F375173452C2D4DEC28B139D04B7376EE694669CA675771C7F351079ACEB1C71A5FAE69B99C00F4AD93C9CE08A291FC6DA670534624747D8AFBBDA6875EB20A4C03529C67F7B3D0172359E826C38B3C7067DE1B2E7FCBD4A7BEFA3D6BC3B4B44E1833428E81CBEF09BCF2E359DD4DDFC5A353AA779DB26537BF5B5B351E", + "498DA668615D45F52F47EF960E634A7BAF74B0A6EE8D73DECAB67E5C096C4FB0" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D1602", + "21015917953F3926871D0BB9BF7802978493FF5A24D684CDEE1B76681902FC8A9B63283C362C33FDB2385419462F4AAF9C6A9588F06A5FE52F2BC923F87123B0099D0A2B456D350B21050F14BA0EC2A56974C9A1403518330C809DF69966D55FBFB70DA27136DE5793F7E73C71ABA60A5906CD36C5653A2BECACC4459756D9E37E14E6587F40389C0895E94BC5C105C4A394098F3A5F27EBB0D4E5B338466F1C964F79322E0CC9AC17B68BD6D20FE77996A740ABF95790B69168320C320BA6602B9624CBF12C84F549E6C40CCFEABD939A934E46A8C63CB627E499D9936C8BE3927294523179224307872F9B8667B175349BA867CABC3DAC47A48A46BC001B647B7AE03878F55A7029894173039D8D1C1F9F49BE12E88743DC709F101280662EE604CB25E75215A570D3FA03A88867E8C4A84F0351AE051F90E36441366714545236CA643BD8B85FA947ECF4A536C13DD7CC6BE7485405C0CC204B91244B364E7A33A60494683A99F5E3C21BF57379061AACA63E569C0E82164633A691BE803B2CD9464996C050323C21080E8C0822730B904FFA7A656C1B568708168A4CB1F54377A02542C42694BBCC38B4CC27F7B735418346FCC8D09B52E89B8F88627BDFF73A87A07B58299AFB321B0BFB1228E53DEB899AE7582066520CC85276A0236276738B58231FC610C3C40B326C4763AFA309435B05AF1C66E84C49430B98F7D4A76A843A627693BE3A67F57C20140B94ED694A1F671C0FD378DA3CAFEED30E5C366C3509AB1E14AB1E08D029A18BE1200D1A8916A1F011B7D0A9A47860F0B09DF996939D2377BC53B7E7CBC3A9517C31A78BFA724B6DE96EE101782C0641E2EA187375B8E5579426995BAF9C30466C4160780F8900867DA89944B1AAB84BAA7F987ACF2AAD97ECA9C222BF2C34BA5F8BBBDEC2C434E43828696FC38903F4C3B7DDE727E1D36A71F9BDBC71C878A3399D346669924E1C3CC2B2AA0DB08A0F30FA703DC308E54857E4142846F9235A48538E291D683409E25CC5AD1C56B690039DF5AEEA596F52AC991E1B3D16E809BFB723A7004A0DB59F0B40885189C88D4CBAEF3ACA2951314ED90789E366EEE8AEEC84798FE931CBB3A42E847870ACC06B3885C0EB2DDE149DD802C1F32953AC20CB87899C0855B2E1D6B8B5F6929D3B9603C73BAE5C528509AC1FDB34FAB2C63773C44195010CE80A229696CE075ED4409A0D0CAA966B20D6C356C4F44272E1501B897159D544F34B7C3B0280D7FC54E223AD865307BCB36CA13729FBD36DB285CF5650C7FD451CD8B305280338C7460385464672D73C5D30A4301A611DE6751C76CFA0BC08D8958F9A170C6D0ABD75007327E891A874181BA87A9260C14378068F183EA9E1CBE1E571530856D7118D9F1AADE546691BF328E5460B114A7DE834B2B218B22BD4C83A3A4580B2C59B325B1BC68231C3732F9AB666C726BC4471E204800C27783DC8BCF6B6315FA8ACE005CCCEC92116D7B34490880452A82098B692552279609D073CB0FD58C82CA888673A093F4696F7A4CECC169DFA336FC736BC995615496B9FB527C83A6192F893386C122B6C5C67E51352A7CC6CA4A7ABFC4006E6105DC7838229D44387C971375933DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D16025BE307C628551E3A1503B1D1B2C2F92108D98FD965AAF9949B00BD097F17B8B0631B752A02D85CCC07627E044EDB8C61E43DCF8A864DFE086D28C2D72CA8B428", + "69FF299E2D6B9D9644BC6A51D99B4C7090B5D1B57D07940FA9FDA30700EFF7DB60D970D56F65667D5F9B40224E00D0499030EB3A3419043D366534BB688F9ABAB691D4B6042B992FE700B8D9CD692BE1D866B6109330190F1BB62BCA02B3C4AF50291142A05C47E94833F10E3E603C7D4E609117944924C4DA9E25E7DE5923B29CEFD0D2D369D7BEF447B63E7E4A332AE9041571DD91B20C459E5A96A58FF51622672DEDE9889564334C841625F5A0053E28EB4C253C1FBAB0C526F5C76918502CBF76CDDCDDB8DBA2CDEAE6653F6B885D678F4E495603591412DF7022F3A80DA638968EA9506F66DAD3D3BD10C06EC8377237F6CA2C35B32E40C989ACE1B51C2ADF4818586C01B92B3FBAC7275A1A2AF8F6A75F030D99349D5229BD87181B6A033B82192D686B3177EB51A07EAEEC2DC4C6471315C9D9939F613F7BE64F48C9050C0EB4FAC15AD553D3249CB9D8AB8EDBB1E4A97E1B8C5EFAB114DA0177FBB12737F1EA0828A0B6C4F1F67E2F5B0017183D07A77ABACB823C59285B730AE0FE574567F4A9FBC638F21CC567EC8F317C0E9729B21D82E3DD8169CC55BC67D2182EEEF38349A3AE589A4C3970B1D9EB9FB6DD540BAC5CA72EA0DC5C88FFAFBFF6B5F1F1F5C33E2471342D42F4483CE4BE0161B27F3692CCDC98AA3843263BD74B93B9198A768659787A19F3369DCA71E8BE2F861A3837F095D84B3AF06A780487660498A9723609BB89F368D2B1111F61B8188D54C67DF9C9DB6C742553A133ECDAA1A4DCA5774A69C1B656834C4ABCA3E1A402DDE6DD2C21ECF9E50D861CE2F98439990848744E7B0441B5A26F43E4C9515FA65F163B85DCE55DE645CE14CAAE06E95C1D7FD427DE8D440806B2E2C0F92C1FB6C4C4D9C6419821D4CF16C305F73B80F3C4765A6C4120106A530C2371921F1D75DA16C460A0197AEC0139B610F5C8DA33DB072A933180C5E3D30541B6DF54C19CBF101BD0DD0AEE88D75C54245DE8BD88741979FAF6A075D6C8DD98FF3F43B7EBAE04AA10966DD915C41397D1C951754DAF4621C59FBA51E13900218B12D1DD819D811909C31FAF7209C5E4ECFE8592C2F53C5CBA07DAE50EA43041F1E1823B0DF4A959F763D9888721550C00929C395D7202C452AC256A86A996C0758AF340BCCA0CE7F474471ED34A49F99584957FA76C431DC8963A22C640BAD8EBABB0E8D73570F985A374CCF137F7D6D24E65837C5A822C4BEB8B065B408A962D618A5C8807A524CFB70A18D74FC5F4CC3C38FE19F613A9083BFED79A806B00825CD07DBFD119BDD7DE7EA766F6B988E631E4D7F5AA614F43B3DA3DCA03DC8F63FA51A9A07D325B9A2E4AE42C3CAFC7BA46479B398E770A9D627761F0C0BDD0F51D42420D2FA9188339DC8BD15ADB83C816DDD5D884496744D5F620A4382F9DF60CB6EA326035CE8B0E38AF6DDD17C5ADB5AF0C091DB487646DA758B6E464B3564C452FF040D84E1A50ABC4B4CECA7F54C27ED31918C6DA8F5746CC02D58BA8E198E62C0066FFCF449DB78ACD9FE94A2AD5", + "572D524CE030EC1E68403DAB418C05D2322A3B824576DBA8BE2829F17005D7F3" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D1602", + "21015917953F3926871D0BB9BF7802978493FF5A24D684CDEE1B76681902FC8A9B63283C362C33FDB2385419462F4AAF9C6A9588F06A5FE52F2BC923F87123B0099D0A2B456D350B21050F14BA0EC2A56974C9A1403518330C809DF69966D55FBFB70DA27136DE5793F7E73C71ABA60A5906CD36C5653A2BECACC4459756D9E37E14E6587F40389C0895E94BC5C105C4A394098F3A5F27EBB0D4E5B338466F1C964F79322E0CC9AC17B68BD6D20FE77996A740ABF95790B69168320C320BA6602B9624CBF12C84F549E6C40CCFEABD939A934E46A8C63CB627E499D9936C8BE3927294523179224307872F9B8667B175349BA867CABC3DAC47A48A46BC001B647B7AE03878F55A7029894173039D8D1C1F9F49BE12E88743DC709F101280662EE604CB25E75215A570D3FA03A88867E8C4A84F0351AE051F90E36441366714545236CA643BD8B85FA947ECF4A536C13DD7CC6BE7485405C0CC204B91244B364E7A33A60494683A99F5E3C21BF57379061AACA63E569C0E82164633A691BE803B2CD9464996C050323C21080E8C0822730B904FFA7A656C1B568708168A4CB1F54377A02542C42694BBCC38B4CC27F7B735418346FCC8D09B52E89B8F88627BDFF73A87A07B58299AFB321B0BFB1228E53DEB899AE7582066520CC85276A0236276738B58231FC610C3C40B326C4763AFA309435B05AF1C66E84C49430B98F7D4A76A843A627693BE3A67F57C20140B94ED694A1F671C0FD378DA3CAFEED30E5C366C3509AB1E14AB1E08D029A18BE1200D1A8916A1F011B7D0A9A47860F0B09DF996939D2377BC53B7E7CBC3A9517C31A78BFA724B6DE96EE101782C0641E2EA187375B8E5579426995BAF9C30466C4160780F8900867DA89944B1AAB84BAA7F987ACF2AAD97ECA9C222BF2C34BA5F8BBBDEC2C434E43828696FC38903F4C3B7DDE727E1D36A71F9BDBC71C878A3399D346669924E1C3CC2B2AA0DB08A0F30FA703DC308E54857E4142846F9235A48538E291D683409E25CC5AD1C56B690039DF5AEEA596F52AC991E1B3D16E809BFB723A7004A0DB59F0B40885189C88D4CBAEF3ACA2951314ED90789E366EEE8AEEC84798FE931CBB3A42E847870ACC06B3885C0EB2DDE149DD802C1F32953AC20CB87899C0855B2E1D6B8B5F6929D3B9603C73BAE5C528509AC1FDB34FAB2C63773C44195010CE80A229696CE075ED4409A0D0CAA966B20D6C356C4F44272E1501B897159D544F34B7C3B0280D7FC54E223AD865307BCB36CA13729FBD36DB285CF5650C7FD451CD8B305280338C7460385464672D73C5D30A4301A611DE6751C76CFA0BC08D8958F9A170C6D0ABD75007327E891A874181BA87A9260C14378068F183EA9E1CBE1E571530856D7118D9F1AADE546691BF328E5460B114A7DE834B2B218B22BD4C83A3A4580B2C59B325B1BC68231C3732F9AB666C726BC4471E204800C27783DC8BCF6B6315FA8ACE005CCCEC92116D7B34490880452A82098B692552279609D073CB0FD58C82CA888673A093F4696F7A4CECC169DFA336FC736BC995615496B9FB527C83A6192F893386C122B6C5C67E51352A7CC6CA4A7ABFC4006E6105DC7838229D44387C971375933DDEB6980B1367D597D82860227EBC0962198D10B10492469F083B09D884C6F9C80AA0035B3B342D1AC1C9AE7A6F5AAAAA9037ACC496C49965CBAE11C72190374E85C9D5060B9F04D29D289A0D2B59A71C6514B47A6360950D2285EA342F618293109719448633A58311842CA4D66963F122252E0C4D1B3CBB4153C23C2C52E602A1CF47305C6994AF0C27E804C5AFB464EE5A899A8607880865CF57FF8C1C0AA063E44F25AA751B52968221DDB5F81B87D71876615C158E0A0275191BA1D7785C7516A3C604871261B7C319C1688153C9C8EA9E0B14AB708E2481A1FDC99C0D912D8C16B308428BCF28A47DB1F79918406981409405C00133446C30D2CE71755B06303BBC91B2A0AED4583244596F251C42F2B3339B15E74663816EC5A8CF920B25419B7F1435F158ABEBB6E4165C055166913074A48608B51628115E78A4ADBCCAC736712A304FEF240536423D4BC25B3A32C863CAA306744E570360D54B555903982B00175436E143BCD6E62A23C7907203AA3A84670DEDC0F36C327D8DB6936A34487EBA771B48F15F6810780B031705CAB2146D81A7B9A608C6DD1134D8C7D515CA6CC91131D1A89D2B18F46935F03A990E2A72161F720FD75CADB62B4FAEC98B751BDCEC389E35B13529AC319A62EDB44484158A1099B4BF0BA2623D19C5F09338A042BD929683C6C4E7010A770F20C81EC1266898520C27F78C663B43A9B72F41BAA2921436986AA1A8D39B397A0F79DCE4CA356837C36F476EF4A849A074D84A91CFFA66958B75D99B729F61742E1C117936B55006AC8DF970F80229B479547A37244D465B800F5A773930B8F2445205C6AAFB9C5E44C4107B67A63F97DA51421B790311079002FF2A3C0D6896A9386A9C2CD2E09CAADF9559327370B180ED57236D24810098A619BBC89CC2091E160AD2364CD51466BEADB68DAB41861A4A364BAAAF0C33C6770CF71A03021E8125E726B428647A5C3AE88B536F9DC46D5A72DB7B9AD6F622D3251C59BD544CDA92AFAC7CC2594A93BB18350191408E67B39E63E7E0329C3398197DA4A229C3694947455DC2B901431C8CA6C32051A2CF416850301631972D3C0B3E1612770F063039917ED41C517669503572AD83709539A4135CBA39BCAB3EF170645B231B86BC4F84892A69C91D2F73CE08B1E478A93F0EB067C777E373926E8466CF1E0BBAFD05D6E29A7DCD730534C5D88B31D7C7B93CC3991A4150E2218729040A4C76AA384309518AC1D1605CDB1F5A6373C8DDE597B10B60D752AA5FA90123E57290715A0AE559DB657B7ADA285761559A1634253F122EBA738370363D0699C3007CB39C04EC27C433C89228FE664B72661ED144E5AE2CCFD02BE9C25A89012CC4C6543962507E6485426FB60DA1943CA168B25341F8AB51490FBCDB762CF08A9622AE9358D912D7604520281558CE1CBDB55CDA6255773B463202B7390C093A4AA3CD1C254CE54167E82808D40B496350E86E97E6C0288383339C3451DBFD29782072DBC0C0C317C716511AB9EE4BA4C1385C9AC326600C1D749B35429649B06151124A1B5212E605C1E6839A07DD363E567CDAE535C4A54AA85C728E9B496EB554307051011288E49A5BC30B8C34DF8355BFF525095E557427BD1041C5260E664AFAC328F50CA91C06612DEFF490D16025BE307C628551E3A1503B1D1B2C2F92108D98FD965AAF9949B00BD097F17B8B0631B752A02D85CCC07627E044EDB8C61E43DCF8A864DFE086D28C2D72CA8B428", + "27FA207180726428640D04D6C7581B1A959D504177882AF4956163526A84757E416CB21109A69FEE7794B03580CF4513140F0DF1E9850EBA999103B547DF82F0DA7C5D42EB9A665A45633C72944331ECD86AB636AF3956895B2A10981126BA7C853EA010E7902D07559269E15209FD1F70AD84F9011639753AC9174C98897C2965D47941B26C4EC1716E794756A24949763A6CCB410A779116811D4D544D12F19416F1E2D10E33664905840110F7E05BA356FAC2121E0E74B4B27A77E70AB6BA99770A3FCDD4E97D1B07EDA187C6AD20FEC18CF897D2393288A2FAE08FE800FBA5C2541C62E30E3E390BE141A5468A7C7879D1533F1DBF8A5E37861B889A28369D4495ED3B8969E8DB21498FA8B8F4EBD971D19586004E03EEBBD9AF1660140199986C2531B2AA23C6EBE511F962E35F18F730892B72F4084CA29BBBDE04CA6BF722BFDCBDC329BF32A34DBAED2EB7706153F17CD44205A9A01A7BC010D857ACF4B4E18B9EF9502A8F9739A5199DF95F65F271983E8668747F399CB72ED7541525B2F7B2ACFD1559E217AF2EFD76EE638F11D909DAD84FFD10F5E7395B5451800F0744192240DD2A3A8C8CC720B8EB1C0E8B0F94EE863C02CC72384FBE527BCE76E9BCDAA53D13BEA3A3C983540B86344BD66FF650A19251C7F29724D144612DFF8CBE9C80F56817C48E9A6C189AADD20A5C4E21981560D7FA102FD5138DD5235D75BD28A139F0A8BB6BC0D4B82E3D816A75AB6916DB36C948D78F97705E4C0E7FD0E768C165DDBAF51BB103BFFC0C43324DF12F6F4722D11D7CEB3BE089103AA59419E114C3E830445C5F68D016C861EDCA24232C60E61FCE57D8CBEBC00ED17775701CABF02E3B57BB83FE92249356719F06728A107A8E25AC69E947E42998B285500B10625DE05DE0E18842EE828C4203C4AD8441336FE08B746E6F72206D4B9E9C6A08A5028BF7B7FEC2051B9799DC8E0DAA1EF92CE80B41ABFAF2596325F67AC0833589499E2418C55406D40EECEA4FA122D8509107B5787455B8A58A0E43872AFCB7F3D945CE1DD98F95706765F2108B211EE88B1B60453879DE5183025E0904DE762E219BACFA402400489C0DF991E16BEDC388EC3B1587AF497F212B8136F377F8BE3BE43E5829C6B4068C0F498F26C6A6B056D4BCDE4123B71F96BB8DC44DD435E34FD7E722160942FDA43597DF6850641303AD72C8AE73D578ECFD32A6E68610CD547F4849421C3468C810D174A0C372325BD3312B6673BA791057AF7B2791A36B007F5D21D53B4D9A8ABEC826591869146D2CD819FA1E7B53F194D242B85D157F98F5DF69BB50D44A31CC789407F2BCA0C93CF8AE5BF6370D679638E6D4E042B785394AFDF9015A75A849559131DD1B64987D48C9C6E8C7F84A2D3F356EEBCE942B8C1A68F19B1EEE3AE01AC807B4B2EAE66396564E3C298781943F0562629B992FBC288092B046E9BB865D97CB3B592A18B56A48283900C3CD39EEA21CB11D4EAE3E3CFBDCE4042383B5DA5F479F9F667C2A8C8EC0D461A5FCE0", + "9D83535A535F248E2F90932240AE440E670C859C750AA41E813C209892B9BE91" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "C1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7", + "13E490ADD15409C73E2BC9B0496A9513FC89D3857C5E0A9661E8B8CDA9B3B0B81778863940AA9A970123BE3ACF07E97BCC397BF9E6C245029ED518BA64A20AA1E8154C3C736A1C17B43770AE695C38E96B6EE270DE3C81228497E74206272124E3112FCF7ABE938B9B8B51B874FC4362066559C6AA41E462F912026726377BF6681431BCC5D6AE9567230A5681E3192AA6586031DA7A41891C0FE61F9041C475D33570F2AEBFE03910C43B28E549E5C1C21BE2146352CAE4A66FF8D9ABD769963D93BB6F7C8E1856B2DB4311468645C3D8A824720D2FB93CA547A0A7BB15DB3B6A6E04367837AA378734A88064E033C9B8295099F336B1A80493FB8129F79640D263E943B6E535AAD7459F657A59A1CB12B19C8121F15310357D9125825D745F3C6B788DCA96F743C0F7DA9C033A6F2C8A9F998277F1B053756166DB866D2C2AC427E85AF361C7DED10D292A5F876C8B228A655871BA227C1A56B98B8B962F233C3A570A98A01600296249E64ABD84C70CFE91050CBA61D3588406E7A7A1CB199D07862D65C9F617433D173E557B385FD86EB3A642C75494E2273FC7B904E66B4E58B97CD82549A4635070224E5E039D76E7CC055872A356529E39A27E160D64570B5C92A9B9513A6670A227F7C9CEB3450F55B2AC50C1155AA1611A5DED59A069F43B9E3A9E4DC70F4D1164C830AD7BAB499491115D9201518B60CE8175F43327F8756E3DE2B34F653FC4933381F64EF9926D30686FF981C860A517040BB9EE140D0B541FFCE389F1F51DBB4CB51AC393DFEA5B6A55500D3C305EF88112985E623205516807AB1664CC8ABCC107583B8BB3E2E585F95B89AEDB45E5278C4D7B0960355307453E4A954B51B0A6E817CC16AB1D47839095798E6F7C53EB9BBDFDD0B5005C244774BF3AFA35810226E5D4C7C194C285CB8BD6DC2800963D2C1C7204B43B7290ABE6C17AED934D50F538AEDA48F28527DEF27C331B9F122C2941B884C2BC3E950C1A15A6AD5CD17623339C09872FB899245FB18EF879C5B53602C9436A15B79324753A9090851C3184F699CF75E0648AE1849E401385706521219DAFC8326CE8968BBCA21FC059E62963A532A096DA91457427C2A65B45C22E06038429B52B5F732C87C053E2AB38E67457F3EB967F402B7E0762AE4507AFE1196F22AE9E6797BE959D69DBA5B6FA6493E84EE8B3807FBABAD2C07180D8877F17CA92E08E0356CDCCFA9B9ED6268D19196E0BBD14693BFE72510F6151A9407338128449D3806C230B617525E9E01290AA21EB8BC8C70AC60028492A79B354407F5B8C786239368800C1B2D412DC6B14FA9226D1E765BE1780C0C346BCE1147D692A0BF195A1A2CACB75C1076B59222B214F682B8DEB7B7F51BF7BD9C775AA5474C4CE52963C546170B5539DC39C6ECB963D9C260D7253CF99F404DD49BFB7B4C3A90726B3692704910CFFA2AB8AE528D2A944E80735FE25917F960FC9D1014AAC200380A3591638ECBB44F5975708F584C0C392F2A20D2D1B698706853E28117C9139F303AF622286BE0176AB91812C962BA1C311AA9AA8F334C387424177EA6564EB318F832A68C11DA2418FB4BB6B74F1736955CAFE3170CB467F19F5CBEA7A8CC93692A3673CCD8450AA85860AA04BD4EB8008E63EDAE0A32C4413B3242AA9EB1E94371D8A02BA93173BBC93840EC2347560AED85A97D3DBBF0D7CA052635C794B824BD66798E01E70929FB1CBB81E865E0819749B92063EA99DED733751024A143339ACBA3BC9B065A19006E28B522D2A10B22B325E723E6804A2F19270C5744B1754A13B2128F1C3BE87D3968C8213E5B55442E6749FB21C49396B0B427C030A3D9F397525D8B8953B945C132E5B506B5130708A55C41D8B9F7C9B0781D5340D029E538378640A1A57340DE7697A8CD37B58C64FBD7518F55AA276650C94B40C71B435FC83927740222BA32BD8947B7FE3277D9301B1524ECB735EA358AB6BC41682728DA25B70D1AA2E35A4606BA27351A54C88353A3D455651C3118AA578C4B19C557A6DC1B290AB2C97CCF96665C10FBB67A935477168E0185ACC1155A0132011C4F2523732373BD5425AFA7C061BC66C7883803039296C989224A0BDE9BC4B8B6698EABC6C40A10A842C697B3873D84BBCE048B69DC705E6A7BB6C813BC1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7D26129D71267870D23C3FCBA53A325F5F4EFDD0818753D68930C0C2797E74DD2FA9550567AC47E70FE9D84F482BDAB1A8CC149AA7889E4ABF8ED76F68D624DE6", + "766DD902E7CEF070AF64F46A73AB46A62DFB60F93592EEE73FC5542B0A057F7AA182C01CB65197D87546ABB8AE3B2412CFC89C762F3D1DB07D2B8BB4B0A714383D8913BF2C2217AD0E18166D86FD645290C705906CF31AFF16A63CF7E6CC0C7CBC75B5ED4358611658ADAED95C84347CA582A8B2E50D8A2C33966BC47BDAD9D473BF455B4B5E9E238B9352FCFF07D21A3E8BBB4BE27825111E8B10CAB55B44C6F7A0F28044A0AB2BD460262D31A31F43140FF54A7B8994979D6784FEDF6AFA278C0B0ACFF94460123E8CF08D3417481782196899FEB79B614C3C5A24328CAD9AE5937C0771BD49BA8E682EDE7E24296BD1069CB15217C962045FC246295F479FF6D2FE30AF64341E1BB786F903FAF2476F1C6D8D0051E66AE35A63C71206D4D4D9E3879EDCB10905AE914267330D781A7A4BA25B51C7E47DAE067BD25FFBF585DC99D8B60DCF106B22AEF1346A76EF7A887B62B54BE14CD7A1E84362BDB615B03AF33ABB6B06D4628D43AF197DC99F749EF0D3BDA839EC5EBB48736A56A62032C4486670026A7C9D3DCFE04982F02D1DB462FAF5A6DAD1AAC0C6B38DB644F607EAF69CA5790EAA1361D5E1FA1A8C8116A874236D25A55E9218FFAFC8AA8F752334ABD574F01CC324DBA192EAEE5B13668E253880445E58542C50CA8B048FA89637BAD44CD5CBF4C12CBF13B9D00E5297B25137D045D8BD33DBADBB3B9AE5C433F962081177CD8CC523FDBAD322D8562259B06E5CD925B8521930B90BE6357C75CDFBD3DC32762C73260FBFD534789EBE97BF30F0E3F1A968D92AC2D12A0AB3D05164F2CBDFCAF7FC7BE60CD758233303524ED3716E4DAC9ABAB3A01C86A4EF8818CA787E5AEBCEFE18D8223BBC1E70CF276729E50B7D1498964A572AF6F5800B513B8ED49C6CAEF578D6230689D061D70301565E296D9D27055296C93A9308C7F94B3941948F509EF817309CC742D7C0E079F731FB6C6AD4535203D8423722152F2A9AD0E00BE0AF94CF5FD58BFD0E3E720CF1BA7A7566DD350FFF8C1DE97570FD6894A0D3B5E23343D902A81FE23AB3A19C5D1AD08800CBEB667E05054DC749B663052E57D9A97194BF2CBB153BE50B9BFB3ECDC88ACD756DC9FBB717A3B544AAA6D0F289D436F7F2F96E4D20A7D2748687E1C55F1D416DC9A0B51C6318925A621CDBE80A5400326168DEB50DD39BF0EF2073C6573B753C55E5B352B5F69942FABE9D34DC59D70BB349FF01430A69C54A7D7F33333B112DB2E559DC5971273BB9BCFC7E7779506BCB1C51003B11AE1FA6F33537F44CAE9CC50F74DCF0B61FC01A89090CFA56460F9224A575D6C073DE405CB69E559901284943CAFFD04F4F252051B70A0A18AFA18526403FE4417BBFEAF27AA98B92066709669EB6901E33817EAF46B83AB8FE89035F34E38E135ADD10D86194C51CFCB3350AD051FE506C92DFAB055E7594AA49C151605F5FC45698AC0B780F2005B19132C6B56E40C341D4C918E73DB18BFC9468C998BBFB1B6F872C2DD0806DC57CCFB9AE5CB7DADA91C29AABAD1C03A0DB4452EF62734994CD3CE74C58445A491623C2F6194AB5B7BA8387CE1C0A0905E24FB2738182DBE0FB24822A022DD51E63DDC4016A08364E5E2E77D2C05DC1636972599AEF1357325612218DA843302196E7DF43D9D81568051548096284C51FC676C9806C2F2FE40033641E1945260F3E9E2E52A5CC307F48F72F6B673E5BAD14023E4076EA2494EFA47278D734AC5751EA4A86C155C39E6491EC614E3C4FD6AD53D74BE932361B3F4F8290D0603FA7076D452A1CFC77B178F69F5609A7B37BB5701B9A46B4D321385EFE772EBDBB8A0CA01293C77AA0C7571B3F594827E4FE7A1CEA31642BA197BB8187CC31D539574803A7603796AE02728370B2A1A35334B1D9DB5F6363EEED00D70311542C88F9D041DEAD6BD1399F46E0C0381F030C68C84E0F4251349E8039BCED39DB028B95A96BCCECEE7097FBFF9B6B9A679DA6C191B82385EA00A8C07E8A395470238D5A1198DDE7F0A9C5A91A1E4D7C35ACFCCDBC5FBB029ED17B0415ED954ACF25A3184A5309B74421E059EF2C9A864051E35FBACE79A7F85023E2442E3647BB6A795DB6D1A667497A3925ED5BBDAB3D801311C5825DB4E10B667572C5DAA81FD1A5A8C013B9D02B78D8CF2CAC9CD0E7B8735A6732754D6D7AF1254EBE066264586D93EBACDFA434B8CF29D400", + "02BFD61BE5523C69628AC9154794B2DBCB45FF5A8671C8D5A95EAF9414865943" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "C1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7", + "13E490ADD15409C73E2BC9B0496A9513FC89D3857C5E0A9661E8B8CDA9B3B0B81778863940AA9A970123BE3ACF07E97BCC397BF9E6C245029ED518BA64A20AA1E8154C3C736A1C17B43770AE695C38E96B6EE270DE3C81228497E74206272124E3112FCF7ABE938B9B8B51B874FC4362066559C6AA41E462F912026726377BF6681431BCC5D6AE9567230A5681E3192AA6586031DA7A41891C0FE61F9041C475D33570F2AEBFE03910C43B28E549E5C1C21BE2146352CAE4A66FF8D9ABD769963D93BB6F7C8E1856B2DB4311468645C3D8A824720D2FB93CA547A0A7BB15DB3B6A6E04367837AA378734A88064E033C9B8295099F336B1A80493FB8129F79640D263E943B6E535AAD7459F657A59A1CB12B19C8121F15310357D9125825D745F3C6B788DCA96F743C0F7DA9C033A6F2C8A9F998277F1B053756166DB866D2C2AC427E85AF361C7DED10D292A5F876C8B228A655871BA227C1A56B98B8B962F233C3A570A98A01600296249E64ABD84C70CFE91050CBA61D3588406E7A7A1CB199D07862D65C9F617433D173E557B385FD86EB3A642C75494E2273FC7B904E66B4E58B97CD82549A4635070224E5E039D76E7CC055872A356529E39A27E160D64570B5C92A9B9513A6670A227F7C9CEB3450F55B2AC50C1155AA1611A5DED59A069F43B9E3A9E4DC70F4D1164C830AD7BAB499491115D9201518B60CE8175F43327F8756E3DE2B34F653FC4933381F64EF9926D30686FF981C860A517040BB9EE140D0B541FFCE389F1F51DBB4CB51AC393DFEA5B6A55500D3C305EF88112985E623205516807AB1664CC8ABCC107583B8BB3E2E585F95B89AEDB45E5278C4D7B0960355307453E4A954B51B0A6E817CC16AB1D47839095798E6F7C53EB9BBDFDD0B5005C244774BF3AFA35810226E5D4C7C194C285CB8BD6DC2800963D2C1C7204B43B7290ABE6C17AED934D50F538AEDA48F28527DEF27C331B9F122C2941B884C2BC3E950C1A15A6AD5CD17623339C09872FB899245FB18EF879C5B53602C9436A15B79324753A9090851C3184F699CF75E0648AE1849E401385706521219DAFC8326CE8968BBCA21FC059E62963A532A096DA91457427C2A65B45C22E06038429B52B5F732C87C053E2AB38E67457F3EB967F402B7E0762AE4507AFE1196F22AE9E6797BE959D69DBA5B6FA6493E84EE8B3807FBABAD2C07180D8877F17CA92E08E0356CDCCFA9B9ED6268D19196E0BBD14693BFE72510F6151A9407338128449D3806C230B617525E9E01290AA21EB8BC8C70AC60028492A79B354407F5B8C786239368800C1B2D412DC6B14FA9226D1E765BE1780C0C346BCE1147D692A0BF195A1A2CACB75C1076B59222B214F682B8DEB7B7F51BF7BD9C775AA5474C4CE52963C546170B5539DC39C6ECB963D9C260D7253CF99F404DD49BFB7B4C3A90726B3692704910CFFA2AB8AE528D2A944E80735FE25917F960FC9D1014AAC200380A3591638ECBB44F5975708F584C0C392F2A20D2D1B698706853E28117C9139F303AF622286BE0176AB91812C962BA1C311AA9AA8F334C387424177EA6564EB318F832A68C11DA2418FB4BB6B74F1736955CAFE3170CB467F19F5CBEA7A8CC93692A3673CCD8450AA85860AA04BD4EB8008E63EDAE0A32C4413B3242AA9EB1E94371D8A02BA93173BBC93840EC2347560AED85A97D3DBBF0D7CA052635C794B824BD66798E01E70929FB1CBB81E865E0819749B92063EA99DED733751024A143339ACBA3BC9B065A19006E28B522D2A10B22B325E723E6804A2F19270C5744B1754A13B2128F1C3BE87D3968C8213E5B55442E6749FB21C49396B0B427C030A3D9F397525D8B8953B945C132E5B506B5130708A55C41D8B9F7C9B0781D5340D029E538378640A1A57340DE7697A8CD37B58C64FBD7518F55AA276650C94B40C71B435FC83927740222BA32BD8947B7FE3277D9301B1524ECB735EA358AB6BC41682728DA25B70D1AA2E35A4606BA27351A54C88353A3D455651C3118AA578C4B19C557A6DC1B290AB2C97CCF96665C10FBB67A935477168E0185ACC1155A0132011C4F2523732373BD5425AFA7C061BC66C7883803039296C989224A0BDE9BC4B8B6698EABC6C40A10A842C697B3873D84BBCE048B69DC705E6A7BB6C813BC1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7D26129D71267870D23C3FCBA53A325F5F4EFDD0818753D68930C0C2797E74DD2FA9550567AC47E70FE9D84F482BDAB1A8CC149AA7889E4ABF8ED76F68D624DE6", + "E80B4738ACEB3ED9BAC18CFE16151B91FB34814594369002C4A92232409BBAB226E302551C01CAE01ED07759FE5EB79FB3CA262C9B55475179A789E92FAA7812858082281405659D163A593F61F15F07EC945941E0DC2AA3DE1EE12EF9041933BF9BBA268C447E81541BACBBECE207AF25199CD8A6E4C2480ACCED8DF80F8748C6AFB26C55542E73EA0D42E9F01218E78A6F21B19BD4C64B2FFCF510C953AC9E05ECF8114E91878FE6437A296DE8AD37BB4B634382FD76D039C006E3AEFB1E85CF1510D24EFEC428175601E5C78A3583E52134A69A2EE5DDC1B33EA2AF27287EFB843271C73D31F78152D8103136DCB655F483B5F4AF2BCE96FB730855BA929A59A5BBAB7A45732026E6FAD23068A1D8C57AD634E63CC92BF7A3B83B72476B5488172CFE6DEEFC62AC13E33A3C67EF1A360C5E671555B389D884E5B159BB43EEC56D3B1B934F8E6E339C5DF6A53777472557EFFB3A6E0695F09A8161AF7A3374083F1BA16BC17EC5C550CEC84BB00B550864348F82679BA32CB9F174733D0A874F15C39837A5CCD54EEC16D783053369B860F34EA5E339BD48B70F0C7A2E6FBAA8CB3CF4D7F0AAA204CCD5042D8C77E8D73DBBD8DDAE719DA6207C92DB8DCBE258EAD6C67E9AA66AF817B005A83C39BEF8CED728E569293F92310E75D0C75BE298BE201BAADC319FB33CCA65C725CFF71D02D33727B1AE30080C9895D5C5C2AF301FBBDABC3F23047AD6BB4F1C5E41D9935519E091885A3BF4EA3F1794C79AF719698D49AA7786A0554577D90FAB6F86D1ED048E35E1711BB2D597E3D13BE3079C2E8AE931BD15D6E7B2F805A339B1E88257E1EEA7D84FCB5DCA1E4C304139DA752A19C0E01376D94E9223DA8C298A63A60145E2A732001D6596F12156048977FB2A348237C5B82ADE97626A7BAF264768A593B0E908A3836843ED936BB037ED4A41B0F1EACDFE101CD0A7EA18CD3B009AF5ED2DDD450A2FF456373041981C6479A5EEAAF1D4453281C6ACCAC590B7B0A4B8412A2DD2ACCCC321BE10FC369789F21F3A53155F9E493CBA6C9651710F45928217E2345386D6C559CD0CEDDF9C2BE2F500A637F3A3C423D3D832782BC4A871FD8B1E95099B23514505A1527C504683D9E3AE37FCB94C67C5B3C08BDB6A2B17A612258B5B1570AE36D829D62C108B7C5C0E3DFAAEDBC00D49EE43CC4E360C44BC2E5403D0E17B514B3D055C4772EF077AB733DF9052CACD4A2025EF42099D06EECDC3B12086BA38C84B733E793662CB5F4A09AD25C6BB7B0DC51912DB42CBF7CC457B9E85D6EEE03CBA2A1E17DD61BAD8B06694443CBAC0424B83DE4DC153A4FA13011C2D5EE86839AC0BA531E4520F8482E94D92BB14FD54BF218B2731F426F24C6F015633C884F78656E23678AD34D63E67DB6F8F8A1185C3C31632CEFF78F17F6AD923A0BBAA3ADE397D61D35C86D36B3A915F705CAAB1B72D51B5A4771CD47593D73626BCE0B8491951B0E160B7370AD062E7BFAC5C1AC81165C3386B386D181C0C12C05CE332A6687080523A1A493AFA7E106FF9DA419B7A04075FFD4849E6EAFA0DBBEA0ED8140D6CE551268AC6CC161B024601AA012332FE9D02B5AB632B2B2EC5D7665B6580ACE5C819A1A857AF163F5E9CA93370BB5D07C86A7367B5A35029D100A81AD166FDF8B4CF96E9D9B43EDB8AC40846BA5A33C7FD314B0BFA84D89FD5A5397C9B4148499B75F290FECAAA06B88BC48B07994EEF65917CE4F69B72A8E3AE6C8EEE9C6CBA65EDE2493EB77975B67DC8779736F68E6D59BC6618E09B855D9F85E85F5C8B64EFF4B13B0A643540F7685A95F51F5064E34DEA21BDFB7DB6825FAD8614C08CC5CBA89661E1AFA7FBACB992AF7E56EE4758A90ED28261EBBC931920B2765A44043CED4D3758D71A0D6114A25DFAEAE551764A93A536CFBDB27A0BE464BFE978830B6EF0AD9C962582576515A1345436407E9625200D57F5DB90254D40D3EF006A5361D907ED473BDFD2371769F42DBADFA52201D63431BC6AD691D755CEA136B1524D3D19B833DD9295B327CDEDBA4D6B8EE5CFBEBB49166FF85C2A40CAE024051C23433A3C62000BD3AFE9FF51518547000A78D31B08D51803A8AD4FF04DF7AFE15152D3FAD850D7742ADE9ABE1C1216AC0BAE559194026DBD1D7217D8B76212E4C5462B9EF29A6976FF216D98E3F3EAEF7BE8AB432E1B6CCEEC83CD46D621EE4CD532", + "458A7BB577EFB1BD795037BD062CD5C90766A8885ED8E8EFF24FB166EB8BC0E7" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "C1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7", + "13E490ADD15409C73E2BC9B0496A9513FC89D3857C5E0A9661E8B8CDA9B3B0B81778863940AA9A970123BE3ACF07E97BCC397BF9E6C245029ED518BA64A20AA1E8154C3C736A1C17B43770AE695C38E96B6EE270DE3C81228497E74206272124E3112FCF7ABE938B9B8B51B874FC4362066559C6AA41E462F912026726377BF6681431BCC5D6AE9567230A5681E3192AA6586031DA7A41891C0FE61F9041C475D33570F2AEBFE03910C43B28E549E5C1C21BE2146352CAE4A66FF8D9ABD769963D93BB6F7C8E1856B2DB4311468645C3D8A824720D2FB93CA547A0A7BB15DB3B6A6E04367837AA378734A88064E033C9B8295099F336B1A80493FB8129F79640D263E943B6E535AAD7459F657A59A1CB12B19C8121F15310357D9125825D745F3C6B788DCA96F743C0F7DA9C033A6F2C8A9F998277F1B053756166DB866D2C2AC427E85AF361C7DED10D292A5F876C8B228A655871BA227C1A56B98B8B962F233C3A570A98A01600296249E64ABD84C70CFE91050CBA61D3588406E7A7A1CB199D07862D65C9F617433D173E557B385FD86EB3A642C75494E2273FC7B904E66B4E58B97CD82549A4635070224E5E039D76E7CC055872A356529E39A27E160D64570B5C92A9B9513A6670A227F7C9CEB3450F55B2AC50C1155AA1611A5DED59A069F43B9E3A9E4DC70F4D1164C830AD7BAB499491115D9201518B60CE8175F43327F8756E3DE2B34F653FC4933381F64EF9926D30686FF981C860A517040BB9EE140D0B541FFCE389F1F51DBB4CB51AC393DFEA5B6A55500D3C305EF88112985E623205516807AB1664CC8ABCC107583B8BB3E2E585F95B89AEDB45E5278C4D7B0960355307453E4A954B51B0A6E817CC16AB1D47839095798E6F7C53EB9BBDFDD0B5005C244774BF3AFA35810226E5D4C7C194C285CB8BD6DC2800963D2C1C7204B43B7290ABE6C17AED934D50F538AEDA48F28527DEF27C331B9F122C2941B884C2BC3E950C1A15A6AD5CD17623339C09872FB899245FB18EF879C5B53602C9436A15B79324753A9090851C3184F699CF75E0648AE1849E401385706521219DAFC8326CE8968BBCA21FC059E62963A532A096DA91457427C2A65B45C22E06038429B52B5F732C87C053E2AB38E67457F3EB967F402B7E0762AE4507AFE1196F22AE9E6797BE959D69DBA5B6FA6493E84EE8B3807FBABAD2C07180D8877F17CA92E08E0356CDCCFA9B9ED6268D19196E0BBD14693BFE72510F6151A9407338128449D3806C230B617525E9E01290AA21EB8BC8C70AC60028492A79B354407F5B8C786239368800C1B2D412DC6B14FA9226D1E765BE1780C0C346BCE1147D692A0BF195A1A2CACB75C1076B59222B214F682B8DEB7B7F51BF7BD9C775AA5474C4CE52963C546170B5539DC39C6ECB963D9C260D7253CF99F404DD49BFB7B4C3A90726B3692704910CFFA2AB8AE528D2A944E80735FE25917F960FC9D1014AAC200380A3591638ECBB44F5975708F584C0C392F2A20D2D1B698706853E28117C9139F303AF622286BE0176AB91812C962BA1C311AA9AA8F334C387424177EA6564EB318F832A68C11DA2418FB4BB6B74F1736955CAFE3170CB467F19F5CBEA7A8CC93692A3673CCD8450AA85860AA04BD4EB8008E63EDAE0A32C4413B3242AA9EB1E94371D8A02BA93173BBC93840EC2347560AED85A97D3DBBF0D7CA052635C794B824BD66798E01E70929FB1CBB81E865E0819749B92063EA99DED733751024A143339ACBA3BC9B065A19006E28B522D2A10B22B325E723E6804A2F19270C5744B1754A13B2128F1C3BE87D3968C8213E5B55442E6749FB21C49396B0B427C030A3D9F397525D8B8953B945C132E5B506B5130708A55C41D8B9F7C9B0781D5340D029E538378640A1A57340DE7697A8CD37B58C64FBD7518F55AA276650C94B40C71B435FC83927740222BA32BD8947B7FE3277D9301B1524ECB735EA358AB6BC41682728DA25B70D1AA2E35A4606BA27351A54C88353A3D455651C3118AA578C4B19C557A6DC1B290AB2C97CCF96665C10FBB67A935477168E0185ACC1155A0132011C4F2523732373BD5425AFA7C061BC66C7883803039296C989224A0BDE9BC4B8B6698EABC6C40A10A842C697B3873D84BBCE048B69DC705E6A7BB6C813BC1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7D26129D71267870D23C3FCBA53A325F5F4EFDD0818753D68930C0C2797E74DD2FA9550567AC47E70FE9D84F482BDAB1A8CC149AA7889E4ABF8ED76F68D624DE6", + "40C229A23E71E694C2154594D972A719206BDB236B79C2401E7D67C80BCBB4EDAE122352AB5CCD69047FA196C24C9E00D7E9A7F803F64C0B6E48BB60977AA532FC399E70E457347607C4CF143AF741EC437F3F35A90656E581D592A9913D8B59A05D156DA4CD8A4F47F7522E90F68C49B0EEA77102111C343ACBA4108F32BD40E9276528D59084AFE7E8D13051C909C11BF5A4950BDA966AE5A0DD9370DDD4B7C5AE5DF67A388B4B5B4C6E988515A1C734FD6E4EF14A933320F43A1DCF45A94D8636C5B664D00260C5EA4A149600BEDCA87F6D84A8208EA08569F0BD18D9A273710147F83C1E6F932CE732BF83BE24DCB1A9B7DEB176049665E28FEF039DBC1A94FC8285635D6C5C7EA905632A0448F3083C3DE9477755552657DF46DA79B3BABBCBD14B74E74CD9F86A0971E4881D778FCBF6E7FE2D69F662CA956AF2B71340AF14866336809E223160651DA19878107AA511FDD21ECA681C942ABCE8D8B73BD115036E56AB9773FE48829D92922AB686D4A32A74AD62A131F5062CCDD45774A686677AC42598A07B416BCCA695A10D79271CFBCAD2F8DE73674912E3C0C77FFEC70A4A9EE37462FE96D0C90FB90CBAAF00B2909AA8604B21501376C20CA7DDABAD95792EFC4F0689D9A10125EB002959824E1DD99EAE87BD0A2895768EAD9835DA4BEF9371228166EE433CCB4D3CC45D57B28FB06DD27BF19986C1902BA229E49EF89DB36EF7BBFB3C542E00B9AC908734FE05865783D2A492005CE9B6E0825F4A2C9F4C2990AD59B51FB6D664FE34ABB33DF8A23A614CD735747265D18B93936F80D47A01AA04FE841BD466825201BA91E8432900F46FF16E3D1D6DF3240C8D59FDB87F8402A7216B2151360FC109E77D8AA624C757640C010633C7F0334F98142A411A98ED20EC986F4ABBA76D58A4AA5DE534B26E01B30421EB2823990DDD87177F869B3EB97EB3B1AFCCF3D77A00E1B94BB13B952E68475010FD13ECE8846690807DEF4B7191B9902E44E6C35639EC521EFB56BCB72D72C5E1C3BBA47258D64FD9E098EB6BD30E7C7D7A92F3DA526A05FC15983D5D79A47F749792D8B125BC61250CDE347EA4BF69EDE22F4FDA412476CA261F01E08E1BFECE625E687B6C2828D07B9CF51F46BE6B58E010A2EBDAD09F43254AD0F221E263703B60513398439FD8025AAB3B40A959786B86599E48DDDF35AF8C4C5B9AFC0C8FF4E084DFECAA7EB738BDF499323262EA0BB8A6319777ABFD9666EBEAB7060EB3DEDEFE0C8379C15D7B2EF6F5ACAFEFC6D575737C085BE884BF01AA5B7F3F275DFD39971C627EC56FFDC78D62D4CF8F52CE9399F7F4F5D8AB9F134F041B894520A277E272C2D5A0D7DAB09DBF81EE358F85A6470F42BC1DCDEC1FE87D6A13C58579C6507FD8D494FEC91CA089F4CFD90A8DD439262027103476CB54838A06A3BB4390713653D4DDF903D93748F95A260BF65CB9802B1423598170FFB4F24FEEBF53E974A85C6F0DF4E9191B07B7C8FE780F0A0F1058BEC9257FE32915D0E6A1992E895CFE097E7877BA12C1627683CAB2D974A7033954732DFDC69B455CA3F927273C294AE8B48813640CF691D68CC86DE9CF1D56B79C7B26860039161719894CDA2FB26147A90E60FCF0C7C0D516CFEE7F9719A8A36BECB2B8BDAD33CA4A6CCF5B39342DF89229FD8404C2D5C25A9B771B1B9A3BA588E47838AE1D9EB8392294F561BE9EE83F89FEB3D48882C882C08552B64FC95D5A7084736F9C7A0C9448853E47DDD8819C0927642CF49FE88E8DA02B0528B32CA5BC9DC85B558A4821B1D7DB6E779CBD2D78787DA23DE5EE5ED2A965D5DCAA1491A663E640736096BF703CCB2FD42342937101C536DC74D31D8E51D376AD20ADB51DF34E0B69CF4783BC1D2AA592B2C6AFABE7D9394FD7EF2A3C60F22B68ED4F31CE57F376205E6F0292D1BB5CEFE52ED30CE526EF14382F8BE594A7EBB401FAE8DE7980E8AB83D90503B9228DDBD4198917B77F507C96B7CC58A073ECA250D33FF55071A633F99C57F3ADB2ADE11199104D80A98B36A509406DC77AD8766A4432992D5921CE05617E24F7CA025D03D451FD9F8BA8FBAB41AB6A801B53F1B593031E596C465180923AF867AE30C02A127DC76E9D60F3CA7C24DC536DB2C2767D2560D2C35609224ABA7952F9B620562C7E954A94258CAE9A13E71DAD2A204395E024E4C13D30129B7CA676990176E3", + "AFBE52F2DD9F6575ECB165CFAD5F5646D89C1B8DB398A1C51CBD6A532D0D46F5" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "C1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7", + "13E490ADD15409C73E2BC9B0496A9513FC89D3857C5E0A9661E8B8CDA9B3B0B81778863940AA9A970123BE3ACF07E97BCC397BF9E6C245029ED518BA64A20AA1E8154C3C736A1C17B43770AE695C38E96B6EE270DE3C81228497E74206272124E3112FCF7ABE938B9B8B51B874FC4362066559C6AA41E462F912026726377BF6681431BCC5D6AE9567230A5681E3192AA6586031DA7A41891C0FE61F9041C475D33570F2AEBFE03910C43B28E549E5C1C21BE2146352CAE4A66FF8D9ABD769963D93BB6F7C8E1856B2DB4311468645C3D8A824720D2FB93CA547A0A7BB15DB3B6A6E04367837AA378734A88064E033C9B8295099F336B1A80493FB8129F79640D263E943B6E535AAD7459F657A59A1CB12B19C8121F15310357D9125825D745F3C6B788DCA96F743C0F7DA9C033A6F2C8A9F998277F1B053756166DB866D2C2AC427E85AF361C7DED10D292A5F876C8B228A655871BA227C1A56B98B8B962F233C3A570A98A01600296249E64ABD84C70CFE91050CBA61D3588406E7A7A1CB199D07862D65C9F617433D173E557B385FD86EB3A642C75494E2273FC7B904E66B4E58B97CD82549A4635070224E5E039D76E7CC055872A356529E39A27E160D64570B5C92A9B9513A6670A227F7C9CEB3450F55B2AC50C1155AA1611A5DED59A069F43B9E3A9E4DC70F4D1164C830AD7BAB499491115D9201518B60CE8175F43327F8756E3DE2B34F653FC4933381F64EF9926D30686FF981C860A517040BB9EE140D0B541FFCE389F1F51DBB4CB51AC393DFEA5B6A55500D3C305EF88112985E623205516807AB1664CC8ABCC107583B8BB3E2E585F95B89AEDB45E5278C4D7B0960355307453E4A954B51B0A6E817CC16AB1D47839095798E6F7C53EB9BBDFDD0B5005C244774BF3AFA35810226E5D4C7C194C285CB8BD6DC2800963D2C1C7204B43B7290ABE6C17AED934D50F538AEDA48F28527DEF27C331B9F122C2941B884C2BC3E950C1A15A6AD5CD17623339C09872FB899245FB18EF879C5B53602C9436A15B79324753A9090851C3184F699CF75E0648AE1849E401385706521219DAFC8326CE8968BBCA21FC059E62963A532A096DA91457427C2A65B45C22E06038429B52B5F732C87C053E2AB38E67457F3EB967F402B7E0762AE4507AFE1196F22AE9E6797BE959D69DBA5B6FA6493E84EE8B3807FBABAD2C07180D8877F17CA92E08E0356CDCCFA9B9ED6268D19196E0BBD14693BFE72510F6151A9407338128449D3806C230B617525E9E01290AA21EB8BC8C70AC60028492A79B354407F5B8C786239368800C1B2D412DC6B14FA9226D1E765BE1780C0C346BCE1147D692A0BF195A1A2CACB75C1076B59222B214F682B8DEB7B7F51BF7BD9C775AA5474C4CE52963C546170B5539DC39C6ECB963D9C260D7253CF99F404DD49BFB7B4C3A90726B3692704910CFFA2AB8AE528D2A944E80735FE25917F960FC9D1014AAC200380A3591638ECBB44F5975708F584C0C392F2A20D2D1B698706853E28117C9139F303AF622286BE0176AB91812C962BA1C311AA9AA8F334C387424177EA6564EB318F832A68C11DA2418FB4BB6B74F1736955CAFE3170CB467F19F5CBEA7A8CC93692A3673CCD8450AA85860AA04BD4EB8008E63EDAE0A32C4413B3242AA9EB1E94371D8A02BA93173BBC93840EC2347560AED85A97D3DBBF0D7CA052635C794B824BD66798E01E70929FB1CBB81E865E0819749B92063EA99DED733751024A143339ACBA3BC9B065A19006E28B522D2A10B22B325E723E6804A2F19270C5744B1754A13B2128F1C3BE87D3968C8213E5B55442E6749FB21C49396B0B427C030A3D9F397525D8B8953B945C132E5B506B5130708A55C41D8B9F7C9B0781D5340D029E538378640A1A57340DE7697A8CD37B58C64FBD7518F55AA276650C94B40C71B435FC83927740222BA32BD8947B7FE3277D9301B1524ECB735EA358AB6BC41682728DA25B70D1AA2E35A4606BA27351A54C88353A3D455651C3118AA578C4B19C557A6DC1B290AB2C97CCF96665C10FBB67A935477168E0185ACC1155A0132011C4F2523732373BD5425AFA7C061BC66C7883803039296C989224A0BDE9BC4B8B6698EABC6C40A10A842C697B3873D84BBCE048B69DC705E6A7BB6C813BC1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7D26129D71267870D23C3FCBA53A325F5F4EFDD0818753D68930C0C2797E74DD2FA9550567AC47E70FE9D84F482BDAB1A8CC149AA7889E4ABF8ED76F68D624DE6", + "9523B02541D5005CF145D86EA3A697313FCD491D30DC16E0913F518444DE77A78BD70B2B0E5B155DC83CA7C0EB250BC6B4EE649022FFAD6A7EF7ECFE5D48C10DF6FAAABED91CF12830AF3E8B12FE4EE4D8E60D70729CDB32AC8617E1FA95D21419FDDF5FC16F72FC97D083C198220FA2C1351E6D2D6FE68C2B21087A629BE2C7060CDF002531A28E4DB769A592C3E65420B5BD53DE0431A961B9E52A9FC53CD8DACA088444C97E710282AA880DC7275362CEEAF2AB57BBD6D1DCAC1C84176563BD2E36EF5832A0CDA96ADDFC7FF8CC385D1ACAC69242A23BCAE7A1791DC3E4D114B8D4843B587CFCE504996F362AB5D48F171D28507F5B606DD72A038BBEC5D5DA13FFB3E9BEFDF1B821F2FEA3DDA7408A0261598DFBFD0FFF4E60401241C9A85FC2B321229C3D38A13A9FAC868026B0FCFEB55B7D143268EAC680C4B86F5807771BDB33560A1808808B186DC2AA9F72206590FD15B149FEFC6E6FA6FE8CD286D6DC6F71B2AC44D008A8817CE7F12C4BFF9A4DF9F4224D85BA32D16C3E8FB3A17AD3D4F4AF081AE31C2B6856B72225265A41CB374BAAB6D41726FAAE615E0F875F0996BF0893E7ED27C434F3EE36F24197069ED2BCD683F7995C204064A13E35459CE5987D38165A2E1B83DF82D2C7A2E4887B11F89D91A63714F4FBE1F92D1CF212F6D1DD6340301E66BFE2301DE8266BEF53B2F50D001FB05833E46E55859C7EA95E8D18EC11917CD02A17C0A8551E5606E5BBC038047136401A8EDB6C63CAE400B03F4F38DEACE95B7A046EE9641D7C1AB15EBA9F6E6CB067194C7EC6A16A9D8CCCBC182F68FC862CB5B92CA3BB817261247A0F9690930AFEE80272F11F774C556FF3B69D5C2BAD61057FB4483A470D51F332CD279EAD27B335C7188B8DE176E06284172D511CC3872F29193D157F0DB74D5C7AD28AE23132F0928983E7CE21CF2318332F5676C38B01D912BDC7592DC667F218C6785C91CCF0FE61791E80C5C02E3ED16897ABF0F44401F296CDBB29DC6E8FEAF2CA27CDBDBF4297148B260E64AA3121295D1BA38646C5FC614510B73B067798C479214B847799AA39DF423CC11AC8E7C5990840FC488946DF08C20A8B95E7356E2BF83EA45F61F4DF34F2593177D6A6FC5D1240CF6C96F873391D7BAFC3D65FA106049CAC0D97E7B1B93E3AFCE3DA5C71A48260A7114753C0ACDF18A9E945A25E0B3EC7E765AB95BDB9F41E1D2E9E928BAE1B287D954A489BA289135F2E12D79D3EC2D3E92C62AA2B94CE23AFF987CD70764702732E8DE36880A60AE0B12EA6CA974ABF4734120425E3FF3A313373AECDF1F07B523400763BA26F85CEF1C24DF96A3161D5CF4E50D0D9278DA25DA99D267B1F635504DEB2816194698D5F92056ED4F535B5EA3BDF6765DB131B93BEBC00020980E9E282BCD8528BB973E9A1B62548C645228428496AE50CA8875EDF0321C7D3E67B46109B49C1780C0A702E99FDCCABEDF2DA22F6AC2CA7612283C4CF9D24A5A1173C1387DCDE0CEB4D18D34FE4220B0A6BF333432B064F9B5E2E8D259119063FC12A169D1A8EFAD064603AF0C3C66B44BA8760085DFB89434F5FD32DE121226719A014BE785680E5A26E7C9E76F028B027CF030C430A47FCA785F1585F6F04C98792DAE168CE7B40CF27E5E7E11B6171E441D71A371105CDF9EE857F9393D8F6C86A163CA5B67EDB2BE2E26C01369149E13520781896D580834CAAB024F212C6CAD02FFF6D4843437FB851674EA00AC199E0C06410183B6FFE771A28D23B7035ED78912DC1D17F79D1A705627A3069AAB7089D4152EC1E2E3EE1EDD97F185C4214691B71FACEC1264E1EBD911DD2CF015911CEDC13462786023CE96C82288336BB7AA3D138B94EFAE190A69647C1C8143212B5B0C6B3DED79D9EC3042FCCCE7CF6C6214152E08B784DF321F7E3F633E3F6AE3CCDA5F72B37C287673B73F25CFEE7AF6CA242307B09A1486841CF56949F3E1087D619D1FECB08C9647F15B256C21DBF4E23587437D6C68BDD3B5479D9DDB22D532D44E388D27981C9121FE914ADAEA5063927D78C6EEB3878828DFDE4B3E7065F63272F162601CB458D644177B8BD3CEDA62049E85E28A0154816B9C9719F77ADB5C329578ED5768FEEC8C40160A89BA0319D1CBECDD974547A31AFF3397AD3037D9836C97F02D9615A0D61C4FA34369494129CF1D72B0E38B9169987635081EBD4391699", + "CA17438D4B82B0CBE1007EDF321C1D128DC9BE1AB1D1E7A82E61413AD321B31C" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "C1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7", + "13E490ADD15409C73E2BC9B0496A9513FC89D3857C5E0A9661E8B8CDA9B3B0B81778863940AA9A970123BE3ACF07E97BCC397BF9E6C245029ED518BA64A20AA1E8154C3C736A1C17B43770AE695C38E96B6EE270DE3C81228497E74206272124E3112FCF7ABE938B9B8B51B874FC4362066559C6AA41E462F912026726377BF6681431BCC5D6AE9567230A5681E3192AA6586031DA7A41891C0FE61F9041C475D33570F2AEBFE03910C43B28E549E5C1C21BE2146352CAE4A66FF8D9ABD769963D93BB6F7C8E1856B2DB4311468645C3D8A824720D2FB93CA547A0A7BB15DB3B6A6E04367837AA378734A88064E033C9B8295099F336B1A80493FB8129F79640D263E943B6E535AAD7459F657A59A1CB12B19C8121F15310357D9125825D745F3C6B788DCA96F743C0F7DA9C033A6F2C8A9F998277F1B053756166DB866D2C2AC427E85AF361C7DED10D292A5F876C8B228A655871BA227C1A56B98B8B962F233C3A570A98A01600296249E64ABD84C70CFE91050CBA61D3588406E7A7A1CB199D07862D65C9F617433D173E557B385FD86EB3A642C75494E2273FC7B904E66B4E58B97CD82549A4635070224E5E039D76E7CC055872A356529E39A27E160D64570B5C92A9B9513A6670A227F7C9CEB3450F55B2AC50C1155AA1611A5DED59A069F43B9E3A9E4DC70F4D1164C830AD7BAB499491115D9201518B60CE8175F43327F8756E3DE2B34F653FC4933381F64EF9926D30686FF981C860A517040BB9EE140D0B541FFCE389F1F51DBB4CB51AC393DFEA5B6A55500D3C305EF88112985E623205516807AB1664CC8ABCC107583B8BB3E2E585F95B89AEDB45E5278C4D7B0960355307453E4A954B51B0A6E817CC16AB1D47839095798E6F7C53EB9BBDFDD0B5005C244774BF3AFA35810226E5D4C7C194C285CB8BD6DC2800963D2C1C7204B43B7290ABE6C17AED934D50F538AEDA48F28527DEF27C331B9F122C2941B884C2BC3E950C1A15A6AD5CD17623339C09872FB899245FB18EF879C5B53602C9436A15B79324753A9090851C3184F699CF75E0648AE1849E401385706521219DAFC8326CE8968BBCA21FC059E62963A532A096DA91457427C2A65B45C22E06038429B52B5F732C87C053E2AB38E67457F3EB967F402B7E0762AE4507AFE1196F22AE9E6797BE959D69DBA5B6FA6493E84EE8B3807FBABAD2C07180D8877F17CA92E08E0356CDCCFA9B9ED6268D19196E0BBD14693BFE72510F6151A9407338128449D3806C230B617525E9E01290AA21EB8BC8C70AC60028492A79B354407F5B8C786239368800C1B2D412DC6B14FA9226D1E765BE1780C0C346BCE1147D692A0BF195A1A2CACB75C1076B59222B214F682B8DEB7B7F51BF7BD9C775AA5474C4CE52963C546170B5539DC39C6ECB963D9C260D7253CF99F404DD49BFB7B4C3A90726B3692704910CFFA2AB8AE528D2A944E80735FE25917F960FC9D1014AAC200380A3591638ECBB44F5975708F584C0C392F2A20D2D1B698706853E28117C9139F303AF622286BE0176AB91812C962BA1C311AA9AA8F334C387424177EA6564EB318F832A68C11DA2418FB4BB6B74F1736955CAFE3170CB467F19F5CBEA7A8CC93692A3673CCD8450AA85860AA04BD4EB8008E63EDAE0A32C4413B3242AA9EB1E94371D8A02BA93173BBC93840EC2347560AED85A97D3DBBF0D7CA052635C794B824BD66798E01E70929FB1CBB81E865E0819749B92063EA99DED733751024A143339ACBA3BC9B065A19006E28B522D2A10B22B325E723E6804A2F19270C5744B1754A13B2128F1C3BE87D3968C8213E5B55442E6749FB21C49396B0B427C030A3D9F397525D8B8953B945C132E5B506B5130708A55C41D8B9F7C9B0781D5340D029E538378640A1A57340DE7697A8CD37B58C64FBD7518F55AA276650C94B40C71B435FC83927740222BA32BD8947B7FE3277D9301B1524ECB735EA358AB6BC41682728DA25B70D1AA2E35A4606BA27351A54C88353A3D455651C3118AA578C4B19C557A6DC1B290AB2C97CCF96665C10FBB67A935477168E0185ACC1155A0132011C4F2523732373BD5425AFA7C061BC66C7883803039296C989224A0BDE9BC4B8B6698EABC6C40A10A842C697B3873D84BBCE048B69DC705E6A7BB6C813BC1491219D429AEC6B9559BC714E17C27600E225AB2398223B9247952B73562B78E6F690561E62951B758AD815E3AC031933CBA45749EF836012456C3E4677347DB502A564A41295FF44449E4E5A53A60A0564A8FA062BCB071C42858A9FEB134BEC8281A57525A6A1D4008483BFBAAFEA86C3BD96BEBE0B842652553542406EC555F8C91AB1953B036A0EE5401C7B9727B7150B2FA50C328B7D5BA337457BB3A7936C0F2443EF816E9B881A7D15C7E6B5FDED996F7ABBBEB1435F70AAEB48B309422C95CD48B66E033BB8212DB82C39F0736E55C7722567CBDF89F1E682343F63ABE16ABF8742CBDBCAB3AF5845269776CEC36920B5B442C986AF62CD5124F10E61B9DB446079AC0A93625A3C15A9709CF01130CB4D721E32B03675B3073B5B3B6E387462399DB7B1F0D18311DEB57C2A33834F8B6BE3574F358A75E6905C0F68A391822E48762E126B62A61194A5707A01083060BA8CDD5376302794565BF647C2F506958C9B4AA0A539EFB859F15142DB0144558D5237067C67340A6BE56544B174DE7998E25E281D2621951ECB4DF063CAAE648DA5B87A69B3D06E779C38C9F8B443BA627398A5301156BA76C27414DD30B29393B77481153DA6AEA138C39AA9049219E4D6C73C2C28EE8F57BBCA2B43B3247E49736261CCA9C52987B0BB7242013BE083B5F770C97E78602A7B0FECB8DF584B86B5C1866FC9C1841C3D3DC17D45BC0B76A6792CB83B3983B553876CCB63DDC1720F782AE08E1A7BA329464E0B8345127867B34EAAC7911AA8DE5BC91FF7479F46105C9E0A5318A780C3156C7C40B2FB7ACD47969E0F7094966BAA7C5C211666B4784B5B10AB1C24677F863615763678BE15A7FBAA38D238253B92C96A76071B50B0CD0222FB4BD57D052CA695E8B3AAF2ED35C131C7EDECC04DB9C25A8EA266B34A4C2B446EC23AB0385501DD4516AB286965BB4322C854AF7CABCF2144B36881899AECC3CCA1D1868AEC77F63AB0EAA85AF792972231BC381EA561F4BA5F455128E90842E44C932F43EE27A0C495A6C784707FA4950C9715D2201AE5A04A0D8820576E322FED4AA20443844E727DD600D58E27691A879124570C858C050E076D003CFA28A149C517E67B58C9F53762149265B9AB37FA3BB32A14911A02FE91A4F8F70329C49A010ACCC0C1259A94A458AC0A99F219C6BBB0141393E09607B94B6138862AE0E809CB5910A48D7C92035496EB2731D70C90F866CE0988896E5944CF5CA000911B817621008244848907E9C75A0241519B08C13282A76B07441953BBCE7C9A55CB2E0442D20415C5455B9B5B6B98F34AC68C33ED0849D826C051A1B1221D08520E8A8285C983FF9025773B6265BBDAB802A03C68F21224A68A7A7FAD62D22AAC1E8E7A6AF04A4C05732EE522CC55587A0A55F1A145DD34724B062BE5EDC7E716360CE0341CB9B7751917207E228C5E452C1CB66043116CA375BEB5C9981219BA8551762B55BF562215F840202E6535903286E31AAE3085CC0A3BF92CC8C3C943DBA7876A5A8CB909CA91746BCCE402712705E8CB84890C983A62534E064A53D013188FB38D4EA69B07B75F04B315CA86E7E9A9E94089DCB9A0A7026CBA238010B48ABAEA51483D255ED7A5700C8C4CFA5BEE4189302C12DE462613BB74B776271D174CC7F3642F7F158F5E70EFDC62E48E36D215264F7227F57006C2FE2B6C4D02008CC85F5D21FB146714424457EFC1F826942B0824FFB30812D5570EBA48FCD365566E09D12E75D4593803F2BA841082FE65501FB2271A902286E3B20F7637F1DA87A779918EC022C85B1242ED78E3A79A3223B5D73C4582E430D46696EB16A3A22BAAD70F88CEC827A65CB3228B44638E0BDC7D361AD40405FB22A3599673B407D8B7B5BB24281042B834F140D3D5C8D3AB2029582C46388A33D370692E2677DA34ACD4A748C69130B8886AFA88BEDE95DD27122A4F4827172029B00708E701F0763B2B5F388FDC82FFAF57AF804725915C432A2B0D671673D41C3BB04C868B35C700045B9A056B7B2359772670C9AC5840C5BB0DC2B9FAC5B4ED12A20251A91085C87A8B24DBCC165D94307965EDE4B8FCE38158BE4BDF3473D160184F745053BD99410091C15BC1288F1130EA2277054CA106438EDBB4F3CF893B5A9007B8C192863BA52A17E39EFDC7060E0C8316936A289684F107DA9B710FC15EE55A9D7439071F7D26129D71267870D23C3FCBA53A325F5F4EFDD0818753D68930C0C2797E74DD2FA9550567AC47E70FE9D84F482BDAB1A8CC149AA7889E4ABF8ED76F68D624DE6", + "C5A8C763C511EE6848FE90241B7358BFF186BBC4B6C0B696EAE1A9CE9B388C1965DF06F76FFC7979EEA1812FCCB17E307E971115CA491DA1793D63CF514062092D284B9C180669CBF357B87CCF45D6FCAF1AA539822BD1992151057C70C81B4D00C6085A419BD7B93D4F6D708CE9745F1C7007F37B57C654C0BE8B951847271494FC23DE9DEC4454A3C0A6107D53A570115430EE2330508DA9B67A915C6391BA12FF56680B8C8B5CF133DBA70198B788B5AF664FF776910AFCA238A4861267ED9B0E42CB4920B8011B1A3797C214B0715F7EB164D6D1D3C67BAB22E6C07BB617608740D98A1F381FFF9C43DC17CD1A568C2B6FF9FC0A081ED729CDD6D8B5A9FC482321400A2C0F0FFE1F9E5469BA4822AD6C967E854CE4155541D84ED6D1AFA6CED139E876AFD711CF0B732C4969BB4D5E940BE686D8E0336AF3B6C1566E49FEB3BAFDCA994E262DF17FA85596E8544D56FEA430B93C99770FF155DA4DF18F45F2EEDFD07349CD467FE522EE9E7AFFA2059DEB3D812C981B4D45FE0519FC5115940AD9E0BC36FAB95EBCEADA29442D8A2912D765A5D72EA88B7D043AB94F0240387FCD3A462148042F5DF105AD3ED9951253EBEC64CACBC7089B450E74EC8E0C84A5748CDD13664F91E830DEBA7D6A7C79A394420E26DDE66585D8A90456964C8D1933C959071D6688F979CB7D60F8FDBCC17D9177B395E12BCFA372ECA0B74CDB264299AFB6AD57F720A10E1B08695C9838791972AAE361B61BD191AF410505ACA62E9EB055D73443CB2003B77A486EDB58451CAC8204AA68DCC489B40F0098FE426B156C4C4B8C23610D682DBAD6D2F74566409C9DAEC9739DF320DE679CB432A55434AD4B8AFF5FC0A544CA275742EED6917CB6B3F9916A8458C7F5063246EBF47FF20EC8FE04B7E5CD37E9A11C654F964D5E3BB34404572B7C2EA39BC482696BCDDC76EFBE3820E4CC662D3340A4FE3DC85F44EC4599F813B0C14F3B9540F906E1DC40BF9634743937EA4F34D79115077F0AE09CF317C0E004A21901911F26632A826F65476732BBFBF15B657029DDDFC1F333863332C67C415FBED95F078DD3B66D650B6BC78EEDDAFC3BA2C47337C0AF44BF1AE8539377C1655330D68B97527CF9DF13A2A418F6E5E1C61089E09717D6CA06A9B4546E0E9CA4C78A533AB648A38914FE9E8407A5404D687B86694E3EBB5342A54100DC5FC81ADA0FB01A3A9440EFD4C9C694BC5F29A9AD513C0469BF85ECAD67E4C2F725DC6FBE0A926EECD77E5A4F6D08F30A9621D24215731B81C1039AC1E7D92917EA2BF686DF95C7FC2BE16DEDBCD6142291C025BEADED6A7B8D17D20E2712DFB4985B351C9EDE71495C7A759776627AF670C4107431441489352B0852258AF90E53F8BDA2A95A84113358C3896D11043928CDFA6E293315A2BF58B5310D47C7901D7498E5125F498F265D4F3F525E1C2A1CE5CDB76F27A803E8CE907DC87F95A676D1A6D009A9FE1658A6AD162E14EB571547940020F45949ADCC4372D0E10122BB4DDDC7BD461B93AE92B7A735B7297D8432FB2B52030D470CE3C7F703AE04F4059DB091E5A51DEB02C87DE63E796B74A640F7B61E06BFEE6EC20DE6C84E0A042FA2138B769F052FAF408725AB40728A183141FE3D72DAE6FE456FC6855CEB6F274A221F01E2F7221A6980465079FAF749415653DF8C681AA2760E116EB08D988E22CCBE85498023B9E49DC59D08BD8805BB34EA1625904F220DE43754C081CE1BCFAE84CCB370B9C6E39B3C325C7E4A3270A78E91ED7ED89EEF8FEAAA471869E5DCCA09E027B07028149CA55E873855CD5C0CFCB6F3F71A9070FAEAD3ACC0B8B59DFB553C275FE138061CC42976B2C68F461090B7BDF1FA7EEF62C2ED16C42FC20A53A984492E579125F0CAB1A22A11E8ACDE90B657A4BFDD66931985EEACE6616259D8A70FC2EE622DF95F081C134ACAD18DD420C12870F577AC9AE4C882994FE19E4AEA6282524F8F7784F47AF9463B5BCEB37E6CFED95999D38A0408C91D6E609698BDFD0ED7E3B0369ADAB16A1CC2E44F9F803F5C8F7CD87B1190DBE05DEC987C3760C472A5C43011C98B6D6EF6909927A81DB3AE40EBFF9DB6D7C49C34C623482277FF608AC8DCB63B5402BCBF279E1F996D743E756F8FF74513B6107007A4F2AAB970E87FEE06A9C1AC2C6763AD407FC8429A52F6FBBC1F3AF31D1AFA4F7B6B47D40BDE", + "0FD1E5C9576B598CD1A90B7749A31487E996470FF9C234127A6DDB7D2DA22B27" + ); + } + } + + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.Keys.cs b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.Keys.cs new file mode 100644 index 00000000000000..0228f2c5efca45 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.Keys.cs @@ -0,0 +1,721 @@ +// 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.Globalization; +using System.Linq; +using Microsoft.DotNet.XUnitExtensions; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public static partial class MLKemTests + { + [ConditionalTheory(typeof(MLKem), nameof(MLKem.IsSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void Generate_Roundtrip(MLKemAlgorithm algorithm) + { + using MLKem kem = MLKem.GenerateKey(algorithm); + Assert.Equal(algorithm, kem.Algorithm); + + Span seed = new byte[algorithm.PrivateSeedSizeInBytes]; + + kem.ExportPrivateSeed(seed); + Assert.True(seed.ContainsAnyExcept((byte)0)); + + using MLKem kem2 = MLKem.ImportPrivateSeed(algorithm, seed); + Span seed2 = new byte[algorithm.PrivateSeedSizeInBytes]; + kem2.ExportPrivateSeed(seed2); + AssertExtensions.SequenceEqual(seed, seed2); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void Generate_NistVectors() + { + foreach (MLKemGenerateTestVector vector in MLKemGenerateTestVectors) + { + using MLKem kem = MLKem.ImportPrivateSeed(vector.Algorithm, vector.Seed.HexToByteArray()); + Assert.Equal(vector.Algorithm, kem.Algorithm); + + byte[] decapsKey = new byte[vector.Algorithm.DecapsulationKeySizeInBytes]; + kem.ExportDecapsulationKey(decapsKey); + AssertExtensions.SequenceEqual(vector.DecapsulationKey.HexToByteArray(), decapsKey); + + byte[] encapsKey = new byte[vector.Algorithm.EncapsulationKeySizeInBytes]; + kem.ExportEncapsulationKey(encapsKey); + AssertExtensions.SequenceEqual(vector.EncapsulationKey.HexToByteArray(), encapsKey); + } + } + + [ConditionalTheory(nameof(IsNotSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void Generate_NotSupported(MLKemAlgorithm algorithm) + { + Assert.Throws(() => MLKem.GenerateKey(algorithm)); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ImportEncapsulationKey_Roundtrip() + { + foreach (MLKemGenerateTestVector vector in MLKemGenerateTestVectors) + { + byte[] encapsulationKeyBytes = vector.EncapsulationKey.HexToByteArray(); + using MLKem kem = MLKem.ImportEncapsulationKey(vector.Algorithm, encapsulationKeyBytes); + Assert.Equal(vector.Algorithm, kem.Algorithm); + + byte[] exportedEncapsulationKey = new byte[vector.Algorithm.EncapsulationKeySizeInBytes]; + kem.ExportEncapsulationKey(exportedEncapsulationKey); + AssertExtensions.SequenceEqual(encapsulationKeyBytes, exportedEncapsulationKey); + } + } + + [ConditionalTheory(nameof(IsNotSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ImportEncapsulationKey_NotSupported(MLKemAlgorithm algorithm) + { + Assert.Throws(() => MLKem.ImportEncapsulationKey( + algorithm, + new byte[algorithm.EncapsulationKeySizeInBytes])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ImportDecapsulationKey_Roundtrip() + { + foreach (MLKemGenerateTestVector vector in MLKemGenerateTestVectors) + { + byte[] decapsulationKeyBytes = vector.DecapsulationKey.HexToByteArray(); + byte[] encapsulationKeyBytes = vector.EncapsulationKey.HexToByteArray(); + using MLKem kem = MLKem.ImportDecapsulationKey(vector.Algorithm, decapsulationKeyBytes); + Assert.Equal(vector.Algorithm, kem.Algorithm); + + byte[] exportedDecapsulationKey = new byte[vector.Algorithm.DecapsulationKeySizeInBytes]; + kem.ExportDecapsulationKey(exportedDecapsulationKey); + AssertExtensions.SequenceEqual(decapsulationKeyBytes, exportedDecapsulationKey); + + byte[] exportedEncapsulationKey = new byte[vector.Algorithm.EncapsulationKeySizeInBytes]; + kem.ExportEncapsulationKey(exportedEncapsulationKey); + AssertExtensions.SequenceEqual(encapsulationKeyBytes, exportedEncapsulationKey); + } + } + + [ConditionalTheory(nameof(IsNotSupported))] + [MemberData(nameof(MLKemAlgorithms))] + public static void ImportDecapsulationKey_NotSupported(MLKemAlgorithm algorithm) + { + Assert.Throws(() => MLKem.ImportDecapsulationKey( + algorithm, + new byte[algorithm.DecapsulationKeySizeInBytes])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ExportPrivateSeed_OnlyHasDecapsulationKey() + { + MLKemGenerateTestVector vector = MLKemGenerateTestVectors.First(); + using MLKem kem = MLKem.ImportDecapsulationKey( + vector.Algorithm, + vector.DecapsulationKey.HexToByteArray()); + + Assert.Throws(() => kem.ExportPrivateSeed( + new byte[vector.Algorithm.PrivateSeedSizeInBytes])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ExportPrivateSeed_OnlyHasEncapsulationKey() + { + MLKemGenerateTestVector vector = MLKemGenerateTestVectors.First(); + using MLKem kem = MLKem.ImportEncapsulationKey( + vector.Algorithm, + vector.EncapsulationKey.HexToByteArray()); + + Assert.Throws(() => kem.ExportPrivateSeed( + new byte[vector.Algorithm.PrivateSeedSizeInBytes])); + } + + [ConditionalFact(typeof(MLKem), nameof(MLKem.IsSupported))] + public static void ExportDecapsulationKey_OnlyHasEncapsulationKey() + { + MLKemGenerateTestVector vector = MLKemGenerateTestVectors.First(); + using MLKem kem = MLKem.ImportEncapsulationKey( + vector.Algorithm, + vector.EncapsulationKey.HexToByteArray()); + + Assert.Throws(() => kem.ExportDecapsulationKey( + new byte[vector.Algorithm.DecapsulationKeySizeInBytes])); + } + + public static IEnumerable MLKemAlgorithms + { + get + { + return + [ + [ MLKemAlgorithm.MLKem512 ], + [ MLKemAlgorithm.MLKem768 ], + [ MLKemAlgorithm.MLKem1024 ], + ]; + } + } + + public record class MLKemGenerateTestVector(MLKemAlgorithm Algorithm, string Seed, string EncapsulationKey, string DecapsulationKey); + + public static IEnumerable MLKemGenerateTestVectors + { + get + { + // Vectors that have zeros to ensure they round-trip correctly. + yield return new + ( + MLKemAlgorithm.MLKem512, + "00F8418B8BE63D8433058E3AFEBEFA43F434B2393896C2E75750FAFA5E9AE9A4226FD2493AF33A6A92282E3FF0E5BA8AB9F09529C53671CBA1D98981DA8FE800", + "002645126709F87B5C6DF9116BA175020895C5C3031AFBBFCDF95AF2839095396A21F23BB1232091EB8F983BCBC95400D4A335C555187FC2311B79402A261AEB276F1DE4CA62458D5AA772F0C25C3A4824DC095AB63584CF863CD4DCA9736CAAFADC1CA2249475946B4BF4B208334EC419C916157E84C9056DE713CD055D69009D295C1C1A6A07E008297BD1B167D4641ED946E0432CDD285A5E9794E6D3CF7422012999AC50C42CACC68E659C37CDD93A70166192719CC0E22D1317C1A3F00715004D505A2B606055626421611BCC64425D2F1452E32B8D68B2584A66180D648B8925467DB306DFC39859EAC383AB60B1F9793051C8AE2151621166B3F862B52C44CD796602C80F45D3C095749EA9D65EB6024752761B364891C7669441E3AE30E43178D13B2D1C3B3AFC999FD4B444E3591320A766ACCA6C4059B8F34289211F82C5A333EA029154C716B640AAC1BC7D516DFB00881EFA9472725A9BC57DD1781E7A0689C5E399CB1B1F41A031D33C3528D421047A48A29C91222074FCC538814242C78520D201171615518D36CC98BC885F2127CE182BA15041B07737A8ABA7ACC4C0A22624D49C4854674A54F11AFFB03D7AE6B90E7413B854A131A6496D02744A66BA7E4B8DF973577EA902E7D1B7CA40CA7AA63F2C04B5D6DA87A735148F003F78395010B11AC9C87E1AB7BDCD8B18CEBA7226E6899DD3A7F2937686D52F7BA21D1A439A7DA06B367C240F644058C434337880FFE79DE9F2A277B13B0B82907E22104F0134423A3F06167FF8254276922361C0368CBC73BFB8C35CD1C0A79076C420B053E604C7098C74344F9A5094983B17ADD46C34984CA317CDED2B0A1ECC12C52124655389FDB813DBBA8B04310259F0A9EE57B03AB04B18079ABFA336FFF854DA70BD82760A39FB3D9BB2837DF052E925449C88680242B73A39AB9D332A9C0371CD06663FC6A65968CA27663E44984B91C8B51A2CB0B6364CCE2097DB286E01FB8D2C871472C68117EA6497196F5F56A3CE778D48B687DAF440BB483748B7C2F0889F02DAB06EC64F33E59E49931A20084C7E78563A766B5223909DC385C5BC4BD8AFF51B5CC52F60FD181D8AC43537254ABC2F29E8FCB8698CD4", + "00E5CDA3A6960283140B49775D0111591493BD0A8C002C1701B53442FAB2A6C7C60B7AB64F1B90104460986803C8C464FA4AA334513887F28A7A4810073301ED40BACD4B1123D73679F63735D17F2EF39B40B92A0A65A170A7A14721C8D23350FE1B90C913C7955A5E3DDB701417C6C505667377A611AA26F5AC981C4953A058BC51E1519B47780702A65407722B9C32BC4819181B675C05AE55116C96B084E58CAFAA5BA1FB9AA893C2B4C399B6C1503AD7782FF6568EEE402451C874EBB8A4417A2AF04A102ABC7D4064BF7E451B81508ECFF32529491126536D64A65142F9AD804881B802433F89C3C38701DCC670628A7E8DCB77F5086C972397D777982B7C420ACA22492720D218B69AAC36A5509FEEAC0324BB9E3263B38251C8BEF95BCADC953749C3F4B886EFC8A880366177D8A45E3C433809C7D5889893C588B5216E3C47683D79318BB90E20EC09F481B0AD77B6433773458C24FDE361AE050BE76959A069530771AC66D4BEA1F4285C462260C48EC894AC444582DA3C1F4DBC03FB6046AEF9BE8DE01A479156DC200FED2518E36A7EC4915AF7E59096037C35B5B3F1C4C8CA96C30A372B8D72B54E91B57E8050B464B27AB671B2EC44D6244020D1098709AB5A79A2B5CC47CCF3480DB0BE27509C162CCB842671E3D5BB571986BA02548A81668F41BC5F6A7C4F66639262CD37C69FAC6BA024183B1D4902773C82F9156EADF17E7057B8FCCA21D8C895A92B080879B49A001DF8E88FB4F667D069CDCDC237324A51297224DEF542F65904F7FCBC4ED66A1BA90321172C3570BCDA36415DE93522984C0CAB3EF1819A31808B294ACFF1D517E045A0D2D59BD1E1374DA3AE97F09D6720C0516B9CC4352A2CD6479309335C300E4596AF5424B5E7D4A5FF06685481407FAB8AB32B0CA336886F5892135B6D49906DB9497244C7983AD6A474194329081AB26920724B317DDB59FD43108F97BDDBEA49E6C7A681A11ACF374AD5AC01443203A53281C143114A19CE2CE427A78C1B24A603372BC1A3E16ED826639D294047F89CFEE17CC1E00CB69A0EA71C20B37A4C208C5FB9CA44002645126709F87B5C6DF9116BA175020895C5C3031AFBBFCDF95AF2839095396A21F23BB1232091EB8F983BCBC95400D4A335C555187FC2311B79402A261AEB276F1DE4CA62458D5AA772F0C25C3A4824DC095AB63584CF863CD4DCA9736CAAFADC1CA2249475946B4BF4B208334EC419C916157E84C9056DE713CD055D69009D295C1C1A6A07E008297BD1B167D4641ED946E0432CDD285A5E9794E6D3CF7422012999AC50C42CACC68E659C37CDD93A70166192719CC0E22D1317C1A3F00715004D505A2B606055626421611BCC64425D2F1452E32B8D68B2584A66180D648B8925467DB306DFC39859EAC383AB60B1F9793051C8AE2151621166B3F862B52C44CD796602C80F45D3C095749EA9D65EB6024752761B364891C7669441E3AE30E43178D13B2D1C3B3AFC999FD4B444E3591320A766ACCA6C4059B8F34289211F82C5A333EA029154C716B640AAC1BC7D516DFB00881EFA9472725A9BC57DD1781E7A0689C5E399CB1B1F41A031D33C3528D421047A48A29C91222074FCC538814242C78520D201171615518D36CC98BC885F2127CE182BA15041B07737A8ABA7ACC4C0A22624D49C4854674A54F11AFFB03D7AE6B90E7413B854A131A6496D02744A66BA7E4B8DF973577EA902E7D1B7CA40CA7AA63F2C04B5D6DA87A735148F003F78395010B11AC9C87E1AB7BDCD8B18CEBA7226E6899DD3A7F2937686D52F7BA21D1A439A7DA06B367C240F644058C434337880FFE79DE9F2A277B13B0B82907E22104F0134423A3F06167FF8254276922361C0368CBC73BFB8C35CD1C0A79076C420B053E604C7098C74344F9A5094983B17ADD46C34984CA317CDED2B0A1ECC12C52124655389FDB813DBBA8B04310259F0A9EE57B03AB04B18079ABFA336FFF854DA70BD82760A39FB3D9BB2837DF052E925449C88680242B73A39AB9D332A9C0371CD06663FC6A65968CA27663E44984B91C8B51A2CB0B6364CCE2097DB286E01FB8D2C871472C68117EA6497196F5F56A3CE778D48B687DAF440BB483748B7C2F0889F02DAB06EC64F33E59E49931A20084C7E78563A766B5223909DC385C5BC4BD8AFF51B5CC52F60FD181D8AC43537254ABC2F29E8FCB8698CD4C74CD655ECCF259367D8B329389410E01AFB493B6A1D936E1F3D2F8E8CC43B72226FD2493AF33A6A92282E3FF0E5BA8AB9F09529C53671CBA1D98981DA8FE800" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "002BF35FBD830602325D2FBA9E36F2C527DA7D017DB31474D6908749790DF1D504150BD6B5A2E7E237795334EA683215868A5ACED024E77889C143B2AC209A00", + "004CC39FBA232249A0519A474D2CC7D2C205C3832F736B5D9AC6649CF123FE5C586258A4D3E50362D73AEB81BF669827D75232EF8C084DEC5284B218F9B466957967EDACC0BB6955A094C13E1C9D15B156E8465E92424D769887C9804E81B3A3AAC4099E991A5B965E61F59D54963DA0E33D6C4008E65670F6BA0BE9AA03569353C753C92A78029A08519E31BF61268C3F8A407018A2A5654F6C071A9C4999D5FA37BF936EBF79490ED78EE9289EBD7222CE047753D1620C0BA3B6F7A3819C86C53C19474CA4BCD65020045118060D9A81BCC42B954143439C142C9C6A78323A872F680FB5641FFB936AE23C69A1670735F98A05587DCC3A1636CCB1BEF42103D97E4A9157ED671C77E16437726C8A12C3490784130A1AE53A4E1DA3606776BA50185593C326079151EB49184ED22F3FBB2BB5B3B1CCF325B6725166928DE717402BD52D343B2A3D07676552966713488BA5461BEC0435AB2B4F77B54932C5FECCBBCD7A62EFE1AD4DDA0E83F9CF1947634B3087A05BBD8CFA6B5D890F4670434E4B6B63A2BBFCAC66F7901EBB562209068769FC431CCAC6382262336726C861A962C42BDF383F9F745001763F5FF52F9520C16E4621213C679F820382A97749474F87A222FF3892A891CC60725F1C7962E526000054AB42CB81A73A88CC19CB1DD67623823F00F16256D3A8D4D75FBE0B268867933AC397255437B32A010D2834353A9BD6E018E5087B78028A6679425550AACFB0B2BBE3529DFB81AD7BB7C527A093271F8012856800AA3F205993460FE023BEADCA01684128C8B54D1E73BA6E247BE02874C96A92FEC0569BD56D1D46763EE3BAFFCBCB3E150FC171AC2A3C1E11EA5460E40B0A231317330689F57DE87C8D9422341DBA11EE22A749F56DAC7A0B5BD70F8EB46043C40BB1646B4D0C4D12591E54B885F5DB02A2325F96EC3317592C077CB99B506D50CC0B34D3554D80B9ED5AC7CCD158F439AC109B0E7F4C282A031B38569F3DF1B47712915994970EB28CE99646305021D435CCA6437AAA6C62554A6D0F59113DB10F84E8B3B257001AF3069E545F1887C131FC8A3728A60EB303F8A9B6558313C209509AFC46EEF34EBDBB4420CB7D40393D45388CA84563AAB1A184F88FDFD3AB147161AEC08637EA9F331BB34DBA7BAC170E6114C780018DEC400C74C02C76AC98CC976D005D000DEB7B856897F469A7161C251C7614CD46A62AC579AFFAC61A5BB72E92885F30AB08F51086D2428BEB4FE83930FB909AA7AC33572C688F02510F3758AAD4B8DAD7C5650079188C95720965E57634A89B5127F79DF6EB9B37F783BE471D1FC059D94982D0DB19D6522E5CD18599EBA1168C73F7F942569ACA85176F739A23070A155D13CB04607AD8E641158068D2A24BF52AC4FFA982B2B594D7A7BFCE952B246997483C40BA17BBDFD501BC640719D37A52904943AC3235D953BAB86DD1D97B8EBB9238EC02C2F3A7C8AC2E1B60608D925CC05218D09C8792272B3B796992FC92710343FD0197DD843254F7AA40CC0C9023B49F6036A408C39CB505501AB80010032940B06F677EDFE9C729E728E2787FE30B88ED6426D5F04252D278269C20C77BC18DB274F5F9C948184D38BB3228D8E28522BB2268373F8FE3A5FD107F185D7765BB0F4054ED87A8ACB9199E32", + "0017C4E1540CD43A3A57058D91E614E324BC6298C91B802C97922056F03363B8764A8A59E207C0486A6566CAAF6D9B1C75A89369CB336C4A862EC9562126196413AFEA263614AB70E8658BA72508E9383461056CF88B26B7204C3E3AB8641149D95C2EB1F444587BC5170213EFEA20C73B24F2E37323E54F6F147FFC075B03B468C22A307E265E165BB14B091EEF5A2CFE632C8371930F060A8BA3602F0098E1F1B104386C5D2430F69903A7041A96B1547A2941E9014E7622340D9B1C81E46B5B51C8CC4B2F3FF05C5484B6151BC4874730564540248804515BB13A757E45D329416064F80A26499600F709A050D6394A16A53CB227C71672D52147E24973AD960BE1F780E5963A7CA3AB3FA7B94F185839A20BB8D47F7B75B5A7B55ABA1B8CC123AA68C95B56C4B56EF26FA0835BFF5003206A3ED7745DD75259E159C1580A1F4F2108E5CC747D321599DC5A610584F8B786D0F33E923578FF0BD051176091E645929A344122A682B82972A2746C885C09584E3A33A693055FCA24BB9CF8BB64E98BBA451A11A2B7AE3087D7FA711C9CBE75585768467542F9C1C5E13C5C0450275478EFFA9BD2066DB62A1864C67796B197A31AC311A71377C4340953195CF15E6052BBF7C85BFCB494B52CC4F0BA87C94A00CCD65502E7A4745944408B66B6C65ABB3982869A27CA21322120A8BC04B7270C8210A08929726517539791182E1506B199D392ED854F69E74B0560615DA96B0F0A4E10FB6596EACD2D6C0323527A3BEB306049467E52BB6737C0782A0409395231617CF181C6BF074854D35B94B2151AD3898EE6826F887546D5B36C303F56F07C939810DE619AB2752700F8B43C3A8A34623FC875411672A39AC64265A61CFEF648B5BC04727157FD58B5B3F8A378A1848C979FDE4C96E0833A7072986141833C703D507303528401FAB5927BB1CA8044A8D5C4B7E367415E69BC9ADCA5A79C6D1455B872DC1B97C0C64C4922FE16AA246B4D6604BAB6866D2988B98AF4A5998327D4A1A6070B78394C6F979298A6FC1D2C7A5514BC8534EB7ABD98C7D0B5106D80042199339C6031D951A66164C98516BDE772AD4735959ABAB9CDEB54F9AC13C3049D5F752AD8A42B020302139A68C482C509D113CD4B4492E220AE498AF8E0930EFB4833C43E87E44F0CA713F12721DCE91D61A65F08822D1B43CDE69A232BA8ACFF40C31A1C82EB7C26C57C992252775502722C244179539D51E737E4B77F0443B3C51BC7C9B848751975BE25985C3A25E63CA629F8A21E144809C47477797CFC368D4357253DB58EE17316D2AB37431B49741617230B17F84A32F092696111AEF314AFE369B3E8D3927079BBD69C327E183E09A10ED3EC3F16BB93578C51312819B13B003B912D00D737014075A328A2F9F007F8101E92D60D03E22B5A83A75A6841FC9A8392166832BA1DD0904C131C5BC763413BC21C20A2B854E7434887008B616001C22E83A140A7F13B03E23BA3074E4FD26253C99C06463B534A9EBDBC7712F349A5BA8D0A033CDDD2204EC0BD321A260EF048C1023A4993432FFC4232ACA5D1808C79B915775A73141A9397BA10B87367BFBC9EA2C79977F54805A3A08B57721A664E045ACC004CC39FBA232249A0519A474D2CC7D2C205C3832F736B5D9AC6649CF123FE5C586258A4D3E50362D73AEB81BF669827D75232EF8C084DEC5284B218F9B466957967EDACC0BB6955A094C13E1C9D15B156E8465E92424D769887C9804E81B3A3AAC4099E991A5B965E61F59D54963DA0E33D6C4008E65670F6BA0BE9AA03569353C753C92A78029A08519E31BF61268C3F8A407018A2A5654F6C071A9C4999D5FA37BF936EBF79490ED78EE9289EBD7222CE047753D1620C0BA3B6F7A3819C86C53C19474CA4BCD65020045118060D9A81BCC42B954143439C142C9C6A78323A872F680FB5641FFB936AE23C69A1670735F98A05587DCC3A1636CCB1BEF42103D97E4A9157ED671C77E16437726C8A12C3490784130A1AE53A4E1DA3606776BA50185593C326079151EB49184ED22F3FBB2BB5B3B1CCF325B6725166928DE717402BD52D343B2A3D07676552966713488BA5461BEC0435AB2B4F77B54932C5FECCBBCD7A62EFE1AD4DDA0E83F9CF1947634B3087A05BBD8CFA6B5D890F4670434E4B6B63A2BBFCAC66F7901EBB562209068769FC431CCAC6382262336726C861A962C42BDF383F9F745001763F5FF52F9520C16E4621213C679F820382A97749474F87A222FF3892A891CC60725F1C7962E526000054AB42CB81A73A88CC19CB1DD67623823F00F16256D3A8D4D75FBE0B268867933AC397255437B32A010D2834353A9BD6E018E5087B78028A6679425550AACFB0B2BBE3529DFB81AD7BB7C527A093271F8012856800AA3F205993460FE023BEADCA01684128C8B54D1E73BA6E247BE02874C96A92FEC0569BD56D1D46763EE3BAFFCBCB3E150FC171AC2A3C1E11EA5460E40B0A231317330689F57DE87C8D9422341DBA11EE22A749F56DAC7A0B5BD70F8EB46043C40BB1646B4D0C4D12591E54B885F5DB02A2325F96EC3317592C077CB99B506D50CC0B34D3554D80B9ED5AC7CCD158F439AC109B0E7F4C282A031B38569F3DF1B47712915994970EB28CE99646305021D435CCA6437AAA6C62554A6D0F59113DB10F84E8B3B257001AF3069E545F1887C131FC8A3728A60EB303F8A9B6558313C209509AFC46EEF34EBDBB4420CB7D40393D45388CA84563AAB1A184F88FDFD3AB147161AEC08637EA9F331BB34DBA7BAC170E6114C780018DEC400C74C02C76AC98CC976D005D000DEB7B856897F469A7161C251C7614CD46A62AC579AFFAC61A5BB72E92885F30AB08F51086D2428BEB4FE83930FB909AA7AC33572C688F02510F3758AAD4B8DAD7C5650079188C95720965E57634A89B5127F79DF6EB9B37F783BE471D1FC059D94982D0DB19D6522E5CD18599EBA1168C73F7F942569ACA85176F739A23070A155D13CB04607AD8E641158068D2A24BF52AC4FFA982B2B594D7A7BFCE952B246997483C40BA17BBDFD501BC640719D37A52904943AC3235D953BAB86DD1D97B8EBB9238EC02C2F3A7C8AC2E1B60608D925CC05218D09C8792272B3B796992FC92710343FD0197DD843254F7AA40CC0C9023B49F6036A408C39CB505501AB80010032940B06F677EDFE9C729E728E2787FE30B88ED6426D5F04252D278269C20C77BC18DB274F5F9C948184D38BB3228D8E28522BB2268373F8FE3A5FD107F185D7765BB0F4054ED87A8ACB9199E327D120DCDBA0767AE1336D8E1CC713556634E6E694AAFE29AED935066F4BE4E8C04150BD6B5A2E7E237795334EA683215868A5ACED024E77889C143B2AC209A00" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "00EF362328DF9AF7EEACBA98DFDB6908CAC76CB15C790EAD244930CA00BDD9D163B1AD5C313C2F4D6F7E6AFB3576F0668792FE722DF04041FAAB9E97907B1500", + "0081607A3102A51C8831B22E77DA270A21582E987D5E0CA251485B36B52B97A26EADF13506266491729283817BCC779474B11C7AF525BF000E8CFB551AA4C71EA8A479EA266BD3692AC8A708EBC682828067C8120C1051464118DB169392E49CCFA55C98B5279E26839BDC0F7C6B40E6C151C4B84C5C1CA7EEC2505A36480E481069855891CC834CF18223C80865A83719D9B57D06ACCA7213D4D3658B587F3B516388859C8988BCD4486C4D74A7E2099D31A014FBA96BA386B4E932659E783ED5E84D88116D2CCC17A14196B445CE652354DFF39613461A6DE17FB762C6462881676500B13365A769A435509651F8A371320A463ABD6103AD680B18DCF826C2FC279D575172F25B149686FB52BC0D77535521349A10CEFE4C94CCA61A60B586DF41CFB889990E388FBF8C40768CB60140A5B7A7C26B20B63EC78AA0A6B5E3E174ABCCA76F013FFA91B95254884F1CB7F1C74A48F3803F733C3645B999DA6DFDA8ACE3660BC55A106AC52658491F190B5B1DA403A03893562B75F1730EC5D18A60493C6A1262F0C3C9B6565106BCC3B4784C1F820F098130A08A5E8463377FA3C29C505F718ACC37C25472E2B7CBB6C94B467CC1DB37AAF58E28B8C4ED553AAFD69BE4A8387F38732C091D86B1C53DD6308D03822CD03A1A30AA6745CE6045BBC3932A95B942C2E366DC75692BEC2D46F13A29458B0071845F8325A65B8951742EE38A59A9045F8373799ABC822B603DFC30B684C911F3900AECB9834F14711098C7477946DB584BC67A93B8F13989E38F32641150915B2173A03DA6552E290AAC8588FD341879494A5E9B0A5DF3B005A65E08D186542B8076385EE4ECBF3C4C008C6CA56908C3EC6924827B3F9117686805BC31432353225AAF012EBAEACF90A07632DAAE4796C0D03289C363543F85214F2A6C34B46DD3D61DE314CBE1467117C89897164E2FB12052743EFF04A406B55E24335730E0C9BAA610CA35AB7BA060B48458DCBB274D2B64D8259001CB5DA8C00ACFF5BE250474DDFBAC99F25CCD7B6720CA7B4CA47BA13C1592EC4749AC5AC58CAC763855583C2C86A59FACF016D0E9607EF37AD1EB1B9ECC2B8E2320B17580AC52B30CF3586FF3B0D979BD2AA68B7552A2C9409CAEAC4AD565A061C95D3003C146055AA8422F54E7C0043BB14B038A1255AD7D26A27D243F8126A2BCE5BB291B421C9BCEC62A56363B270A36AF2E617B51D79A25730275AA474237865FD44679A29B335A9BB0C03EC116B6390B513A9C663AA02D34680F6ED135F5397CD8C41BD9D8C76014B42FDCA075757E877A6222593B9FBC388A02833B54135E226D71A273E64298D8864C5B205CA90721BD0481C3C84D68677CDCB0A43D47772D54C3AAC5A4B98A80594A1842CB43230913F7DA9377A58D227990F50147F3E912450751D5541509204DF17A0347E5040A9643ED13088605B23E4AA18C75549916B11541600624C71CD2CD67180B7A221FEB51AF2099780515434B1A01CAB13CCF2454E1016042F40125774BF90222BE9326837A4D5BFA50B82981D414CBB62B227297A19D147849D25A5713711E0C6B3C565DCFD096C91879BF01A22B7C51E44B08479B1C517CA33C3B7DB8F0C69428704D36269FC944F154AA19F230A9366E7936BEAAFC1200475B89FC2CE14A34DD62A08088BF39580BD17A4124BA4D951A407226AB7620A57FD08DF8710D98466AF23564E58A34FEDA022BD699A812A4E9B5564FD384C1678B8C21C4720BC45FECA326BC00D69039F73807AA2AAE0EC895EE02D0DD651B2A7C14418514D877A0C2146544874F5C79132085895A528BC5514CAC6095D9A2351151A131A42D4B0052468CA26A8A730609C635DB7E50D77BFEB26C5761892CF306CCC86C5701893EB40F1476075F8090CD33573AC73941988EEEC6C70B7A1ED2E6AB680BA64E4B67F5C02D08D288BB714ACFA7B8B72A421F908B04D175D5553C31B1234879ACAC63BFB1D8917B3087EFE22B1D702284382FA42098FAC6C470FB2DD7FC1CE5BC8241256E61343301543A6436582ED989F1C30E4E93BA7C34458895AAB5B9985F4143C69732D4D776D4267BB645692DB348342AAE69C844D54841B9F42EFB837378B449E0FB734B0C968D98C3AB0481288A126CD99096F095A3FB7C180CB2A47425AE24262A918FD7BBEB39B06EE1EB5B8C9EBF8DDE0EE6A5C64C5F902748ED76C3FB44CB", + "00479BF9F16267C39094D36B2CA200A870A551A30EB5F3BA45A155E100CD313083E5579B3E837551036FC3289320E24DD5A815AFF88127D720EB381BEE523906900DF7B3BFAB1595BB20A016A0C214241A6C63635D4978012BC293D21BE1FB63364A25B9558B21C1346B0AAF7ABB4544A10BB28854566A4783A5712157AC367B5C64EA070566A3F7E049E40A79334B1B497AC0A72572CC02C09D281575E647D9E86FC9C60FBC9322B0993FCFB26483324B4443C663B82DE3FB7B2DF88A5B2B562F53B2BBF06800319500880DAEF98740F03C80D118E170A01A507E7BEC22DB08A9ECB968D92054EB36227190A4D72BC085EC225236083696CBE1D08AAE54B24F9638A9241423387EF5B6832B11C0BB51B904523E653A5C104C9EF92B4929193366F0828DF499E1560E107A6322A6C4A062A2B8F37D0D4070C86A0BCE580D9E195017161DE9D4349D509979000E88371BD2AB863BC847B66A8AA1B255F6DBAED40566BB462AFA7743D9E773ADF2A5D28987A153B9DEA3CD93560FAFFB43971C7A7BB55DF477BC7E610DD3B7A470AA4B7912A5944B6AEDDB3D88AA7C14646E05BAA69B9B344C53A687AA03543361C083CFEDF25DED5461C12B075692C29FD7741A40979F855DA8125AFC4C9424347E982AB534FA5552F8A6DE3A87B99C43777C1EBEACB5B3525E89F054130351B2CA6FCFA37EB442CFDA702DD321A55DA71236EB7742607670F793AF7575F775B0F3210D0365CE30C1492FD61696704E4DF1966500B3B611AEF41A3CBB91B90744634E19773E24B9212A4249AC41D0861F0DA9C2C8542B1829412F2585FA75A56AB36262D22806DA0379F2A2B2332CAED03A7AF570A8B9871766B990B5700F8572599CAF32D4A175268679A3428334514593264C135160606951437CAD503D74685FCD20B122EB18B8DB5BB6BAADE17C1D15D81D16032D3E72381960B200DA1227791EA3E926D513905F5B3AA33773BF968F27D028A32284C3501A94B1CDB7942CD215C863FB28F92545C2D762C97502BFD53264378F01BCC1A4F948A9B327E72B3A211647C82368726A50470274F8BA00EEB04F22F924AF3BCEE27A3AE27955B33ACEC16C6D079420D53A2EF93522732A77EB6039A4FB30E13C69EB157DA1202D16C97E0C049645787AE85A7534F58057A3309934606ED150C655C09C14C7B3D7BCDA06689CC04B4272B4E4C88702CB2D4051BB9F856A0A283A1856BEF451A0966C7B0C5A4F3B004A32206D26BC59519622C0E6133CA77304FA817BE5694344172AF362B6077E284AB09C08051B0C7F9CC877374B45FC0A84D2B25A127761A022A0AB23057940069942397640010796BADABC1CC362A845932185706C32C73485383E861C75A5BB48213634DD88775EF221B3832D41206FB51B16D4F942FC214C59D273C68007B423CB11CAA85948047A796A7C5C2842AC57612A5ACC4C056AFB182BD98CF4151792E32B055575A30A14C093A4BFAC078DC96EFD967E5C84727C781D3D9C47EDFA81FC935C83B60220658047CB194CAC47B9E096C8D0AEFA47C9BE779034C323CB99B4A07C36EC207367220FA9C053F38BADD3EC3456362E64E5262431A89EB58070567644E94E1F575C352BC81E4C7916862CE8DBBD29420F10D01FD0C539B104106ADB61D21041C50BC1CD1B07736754EFA41D6427BD31B38BC6806E8A240E3EAAC9FC53A95E866CBB93B588F741E01A8194530C8F1967A216B807B236F36480059B65E5603409F63580DBA58EC10B662A8012910C7A6C711B87102430C8DBF4CA87C8C784497555A1CD570749B4E2393448BD4D6C5BEF098A61D57756865106EC03878A452F510F81AB0D654908667C7D1ACCCA26999F74011300DD198B02192FE68E1E6145AE428D3A7C8AD242675BE631476AC789B6A474224E12D595A8DB00CDAB0972385ABE22CBB2F996523C90419066D5999E5217CD6DD45591552951653172A0AD271838CA2C7F8733556F717A86B84C656AC20D3A24C4954DF5D93E44CC5AD4A63743CC19DA259CF119C48B6541904199F7806A538523445CB6B61561086A1D5B69C205A1B15EF2CB91742F8F165B1E682F76DC987D4A6BCA540956B12B15CC394698330F0BB6ABD20CBEAA8E08E9A291E7484845084FFAA59C843B68027B6AD8C3F756CF5379980081607A3102A51C8831B22E77DA270A21582E987D5E0CA251485B36B52B97A26EADF13506266491729283817BCC779474B11C7AF525BF000E8CFB551AA4C71EA8A479EA266BD3692AC8A708EBC682828067C8120C1051464118DB169392E49CCFA55C98B5279E26839BDC0F7C6B40E6C151C4B84C5C1CA7EEC2505A36480E481069855891CC834CF18223C80865A83719D9B57D06ACCA7213D4D3658B587F3B516388859C8988BCD4486C4D74A7E2099D31A014FBA96BA386B4E932659E783ED5E84D88116D2CCC17A14196B445CE652354DFF39613461A6DE17FB762C6462881676500B13365A769A435509651F8A371320A463ABD6103AD680B18DCF826C2FC279D575172F25B149686FB52BC0D77535521349A10CEFE4C94CCA61A60B586DF41CFB889990E388FBF8C40768CB60140A5B7A7C26B20B63EC78AA0A6B5E3E174ABCCA76F013FFA91B95254884F1CB7F1C74A48F3803F733C3645B999DA6DFDA8ACE3660BC55A106AC52658491F190B5B1DA403A03893562B75F1730EC5D18A60493C6A1262F0C3C9B6565106BCC3B4784C1F820F098130A08A5E8463377FA3C29C505F718ACC37C25472E2B7CBB6C94B467CC1DB37AAF58E28B8C4ED553AAFD69BE4A8387F38732C091D86B1C53DD6308D03822CD03A1A30AA6745CE6045BBC3932A95B942C2E366DC75692BEC2D46F13A29458B0071845F8325A65B8951742EE38A59A9045F8373799ABC822B603DFC30B684C911F3900AECB9834F14711098C7477946DB584BC67A93B8F13989E38F32641150915B2173A03DA6552E290AAC8588FD341879494A5E9B0A5DF3B005A65E08D186542B8076385EE4ECBF3C4C008C6CA56908C3EC6924827B3F9117686805BC31432353225AAF012EBAEACF90A07632DAAE4796C0D03289C363543F85214F2A6C34B46DD3D61DE314CBE1467117C89897164E2FB12052743EFF04A406B55E24335730E0C9BAA610CA35AB7BA060B48458DCBB274D2B64D8259001CB5DA8C00ACFF5BE250474DDFBAC99F25CCD7B6720CA7B4CA47BA13C1592EC4749AC5AC58CAC763855583C2C86A59FACF016D0E9607EF37AD1EB1B9ECC2B8E2320B17580AC52B30CF3586FF3B0D979BD2AA68B7552A2C9409CAEAC4AD565A061C95D3003C146055AA8422F54E7C0043BB14B038A1255AD7D26A27D243F8126A2BCE5BB291B421C9BCEC62A56363B270A36AF2E617B51D79A25730275AA474237865FD44679A29B335A9BB0C03EC116B6390B513A9C663AA02D34680F6ED135F5397CD8C41BD9D8C76014B42FDCA075757E877A6222593B9FBC388A02833B54135E226D71A273E64298D8864C5B205CA90721BD0481C3C84D68677CDCB0A43D47772D54C3AAC5A4B98A80594A1842CB43230913F7DA9377A58D227990F50147F3E912450751D5541509204DF17A0347E5040A9643ED13088605B23E4AA18C75549916B11541600624C71CD2CD67180B7A221FEB51AF2099780515434B1A01CAB13CCF2454E1016042F40125774BF90222BE9326837A4D5BFA50B82981D414CBB62B227297A19D147849D25A5713711E0C6B3C565DCFD096C91879BF01A22B7C51E44B08479B1C517CA33C3B7DB8F0C69428704D36269FC944F154AA19F230A9366E7936BEAAFC1200475B89FC2CE14A34DD62A08088BF39580BD17A4124BA4D951A407226AB7620A57FD08DF8710D98466AF23564E58A34FEDA022BD699A812A4E9B5564FD384C1678B8C21C4720BC45FECA326BC00D69039F73807AA2AAE0EC895EE02D0DD651B2A7C14418514D877A0C2146544874F5C79132085895A528BC5514CAC6095D9A2351151A131A42D4B0052468CA26A8A730609C635DB7E50D77BFEB26C5761892CF306CCC86C5701893EB40F1476075F8090CD33573AC73941988EEEC6C70B7A1ED2E6AB680BA64E4B67F5C02D08D288BB714ACFA7B8B72A421F908B04D175D5553C31B1234879ACAC63BFB1D8917B3087EFE22B1D702284382FA42098FAC6C470FB2DD7FC1CE5BC8241256E61343301543A6436582ED989F1C30E4E93BA7C34458895AAB5B9985F4143C69732D4D776D4267BB645692DB348342AAE69C844D54841B9F42EFB837378B449E0FB734B0C968D98C3AB0481288A126CD99096F095A3FB7C180CB2A47425AE24262A918FD7BBEB39B06EE1EB5B8C9EBF8DDE0EE6A5C64C5F902748ED76C3FB44CBB119CEE210E060B66EBE080206DFB483E300CE2B96B4B33057895A75926F98D563B1AD5C313C2F4D6F7E6AFB3576F0668792FE722DF04041FAAB9E97907B1500" + ); + + // The vectors below are generated from the NIST ACVP projections. + // https://github.com/usnistgov/ACVP-Server/blob/85f8742965b2691862079172982683757d8d91db/gen-val/json-files/ML-KEM-keyGen-FIPS203/internalProjection.json + yield return new + ( + MLKemAlgorithm.MLKem512, + "1EB4400A01629D517974E2CD85B9DEF59082DE508E6F9C2B0E341E12965955CA1A394111163803FE2E8519C335A6867556338EADAFA22B5FC557430560CCD693", + "5B318622F73E6FC6CBA5571D0537894AA890426B835640489AA218972180BB2534BCC477C62CC839135934F3B14CD0808A11557D331103B30F9A8C0CB0FA8F0A2A152E802E48E408087510D5114D4D2399A51530616C7E310528308176D0042710BC8344EC3D4CA810A92978BFABB516D81CAB0753CDF325AC2377A1F96EFC73C15F5AA367A1582A13651B0337C7943C1D54637669686BEBBD392511FFFC9E3A68CBEEC0CE2CF59A8D51C4DE288EB4641DF6610C82D09CDDA418ACD83F0DCA2859B27117E87981AAA8EBA47515812DA2C27ADF9C682E373D5AF294BE3104474B8D14173788965ECCD80322B6CA04240E7D150F2CD4B04066C1924039B9E4A9E06C2B55DBA2FDDABB4065CFE7EBC5AE01CD45C76374683CB1820C34A841836391B9D8C2AA22B29E7436CFCAB789B3CE8AE2700351C1165B7B4F72CC53E913E5668AE75170352A0DE68A5E3819443DB4113161A2019C4930C97011F31540B833E9A890503A7EC3F38C0D94BE3C7501C6161F39099E3CAC0139ACC7271B70D1664A36A89FA4D22857C6C15AD4C52D5C26E23B81DCDA9FD7A49980C5818888AB2538AD91F54E691B7558C63FAE433A7FAB51485989F4335E6187B65041401238AA0A5A932356207796AF2C70363034546F4615499245E1228BFF2C76674634A60C9A04E00FB276C6C00A114BF1B2C8961E740A082940CEEAAB464370BBBB3919C7421BC81C732415A711AA935A4C2C02CB5D0BCBB99CE830EDDBAE4C228E4F095E29FBC27EA2B881697A1D309D28C480C3E9691FB63480BC5C6239B6CCAA41CD52A6209038C2C887BC71C1BD514A0FAA21721A2A5B30ACB168227833A8260422C1F4815EC2ADB207389FB1B817D78FC96063434B6728E18469475DB5D712BC403D8231CF9C8926D0A94B6830881FA5678AD04499F40D5CA83479BA85A70B1196C32A68A6B7FFB40EA6FC3FF020768B91B27F653746546C5E256B14069E827C1616FC7647F8B70F8A32DB551CF715BBB315B7B9BC20FF76847CFC4AEAC23DDC1302EC928CFE40447C761143194DA1415D3D8389F61BAB41EB605729123A320BB54B3B3FBCBC787C46F354C7D7D60F8DFE3729375AEF1891C08A79DE237E39E860061D", + "EA35075D429C8E81ADA6C4BB97D78624C602FB173DFFC78E5C744FF2FAC345B55E04A3B7325A63F58B43EEF168E259910C35A0952A7ADCF43634889C98918A1CE7B62671C1968A02688160C09B7DE9978B77A557D265A40F7C79F3124247FA0C14F8A9F2C2B939470CAD5ACA5E664ADD7B5444643B559C4BF84C524A063DA7E552C9107BB0887BC22C73F76B63ABA60955A06D1CF34491275859D46FEDEA738FEC14D9920458A7C31E657549A6160480784D5C229AD88932B384A0B0A16DD6C8FCEA56B61A50E67442FB9928B4676D92A6717A564D8E939BB7957D750BB70D2B20D8445A8912BC7940489AE01584DC7D7952A686F245D09C547EF40B74C6748B318059F66F2B76C72ECBB3A64167CAE08C27368902B76DFF684A14482AFAE5837CB6838E685987FA4E3FF7CC4A36631CBA1F77915E7C580853E3C6C84859ADC8C2A15CB131E78305F4BCB4A8100AAB206EC97D14862CF5DA4D3AE2066D4C41BBA9187BECBE0809CE6AAC1FE20BCAE87714BE1542BA9053F1802B65C82909594984A186841B2BFCB3AF38100C5E685E7B9B85515C469CA50B1F799229E024B68A4A412A185677444491689957A576F5029C742DB64C3F63614B43AA23C433A1B37811CDC1184E11BB7D9C20E587A862B364EF59651259B26F8375E4510CBB12A475816A364BA72C07566D50A2B4E4503188B7B465080DB88EE663928C894367492E1617CCBF36CF844B9D17072A3178809629B4B9729CF82C9935AA9B1205AEA6631C8EE23CEE832C46E0583FAC43C5BC5131B934527740AB12877D295C72089073E6A2567B655CCB2965FAA3DECA8315815E7B6514F05BACE8A7000B548993734DE3964F2709542496122BE58A7E536CC827839693492AE88E75EA13154AB109E6BD16F4486EE1C3EA61B8FA259283B3BC2BFB589D3206A3C77521AA08C253B4E4CC8B5F87467EEA18EBD48D92604382DB0C0087A3B501066CB55EC9602D2696380A6A5DF33C05C9B01700B61D0FC169DEBC28B3108B096B24D93B8FFE67066286B0E1461265896E33A8089D8B0B81A9781700A983B28022125A4934575220325B318622F73E6FC6CBA5571D0537894AA890426B835640489AA218972180BB2534BCC477C62CC839135934F3B14CD0808A11557D331103B30F9A8C0CB0FA8F0A2A152E802E48E408087510D5114D4D2399A51530616C7E310528308176D0042710BC8344EC3D4CA810A92978BFABB516D81CAB0753CDF325AC2377A1F96EFC73C15F5AA367A1582A13651B0337C7943C1D54637669686BEBBD392511FFFC9E3A68CBEEC0CE2CF59A8D51C4DE288EB4641DF6610C82D09CDDA418ACD83F0DCA2859B27117E87981AAA8EBA47515812DA2C27ADF9C682E373D5AF294BE3104474B8D14173788965ECCD80322B6CA04240E7D150F2CD4B04066C1924039B9E4A9E06C2B55DBA2FDDABB4065CFE7EBC5AE01CD45C76374683CB1820C34A841836391B9D8C2AA22B29E7436CFCAB789B3CE8AE2700351C1165B7B4F72CC53E913E5668AE75170352A0DE68A5E3819443DB4113161A2019C4930C97011F31540B833E9A890503A7EC3F38C0D94BE3C7501C6161F39099E3CAC0139ACC7271B70D1664A36A89FA4D22857C6C15AD4C52D5C26E23B81DCDA9FD7A49980C5818888AB2538AD91F54E691B7558C63FAE433A7FAB51485989F4335E6187B65041401238AA0A5A932356207796AF2C70363034546F4615499245E1228BFF2C76674634A60C9A04E00FB276C6C00A114BF1B2C8961E740A082940CEEAAB464370BBBB3919C7421BC81C732415A711AA935A4C2C02CB5D0BCBB99CE830EDDBAE4C228E4F095E29FBC27EA2B881697A1D309D28C480C3E9691FB63480BC5C6239B6CCAA41CD52A6209038C2C887BC71C1BD514A0FAA21721A2A5B30ACB168227833A8260422C1F4815EC2ADB207389FB1B817D78FC96063434B6728E18469475DB5D712BC403D8231CF9C8926D0A94B6830881FA5678AD04499F40D5CA83479BA85A70B1196C32A68A6B7FFB40EA6FC3FF020768B91B27F653746546C5E256B14069E827C1616FC7647F8B70F8A32DB551CF715BBB315B7B9BC20FF76847CFC4AEAC23DDC1302EC928CFE40447C761143194DA1415D3D8389F61BAB41EB605729123A320BB54B3B3FBCBC787C46F354C7D7D60F8DFE3729375AEF1891C08A79DE237E39E860061D2B87926182B602639ABB65FEBAF116F6A2FCCC167A51A2E2E6F4494C58336A2E1A394111163803FE2E8519C335A6867556338EADAFA22B5FC557430560CCD693" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "47877987835EF38823A23B37CA4CE2844BC017F9A1EFADF8C5D73CB5562C81A461846347FDE6757082E3D56EA060CEB773D5F38A84B8D8AACF776EF9CF766CF8", + "B67136147474B5A56BA8663BF0157518A3C806C20259F4CBC59314710336328BA6945983838ABC65A91820536791048ECD17B7BBE4650C0A32EAA77FC799CF2797C27F35566E630C2BA6B05F608B12818231D67D4886CFF09B286443C7972376EBBA08ECD71C04E945A9A75F82F08E726057DF829D96CB83E4848B92E4263F9596007A1F6B224D794244EA58052EB574896870828C8053658F051BBF1699B657591826348E520707EF8666AB138DB4C3B0E401361A5BABADE2059932356734BCFDFC69146250DF2A78E5A530661446089C030B224F27B3748D2A8239C13D20F10E70F473B82BC3B0CB7C2C82200121478EB60E120C6993A3961AC5850BB25577688EACAABD7F031345AAA692754C3EC48484583D13AC7B11565D9B08A356A1A902067676B20C80DC67D20246B47C199EEC3A934C3D24634ACB119B76BCB3A8A823AFD0CA2CE9277CD9BF03A5565AEA2CDFB811548237D1644F8FBC233EDA44C195241AA0C3C9C94317913A7A8A69566B5166022540B96CBD7781CC5C30529CBA9FEC5E5038BA66A7491F8A0C5CA7B662123B1C5C7F90D0320D617C4CE04F31B466C26A56E1E1CB4721B8C0AC75CDD815C6D37A0D6462D31B264D88A7303A857C333C173C8F09C34F38740E5C87A494003B9347418973462D78B7D57694941B062B06C762F70DF64323DAB70411932349A986C40795187696A672108B1C11357C0D5EB3502E5406DE2721D6C677594B39D9480A7B3B67F3041B6B82C53399335C821940604DD8D03C7D3198167BC83F8C830C785773EC8221986DCCF0C19B462EC5475E878B16C3E2A85C3099C6107A30483CB6E27965DA0D40EACEB7567553396CCD5A1BA6941BA57A33A3A0CAB7B35A31057E24130822D9C78FE9C5AC98268E36BB3D210313A60C3A3359030C6CD1D9C49A277B5EA4825133285B9019CDE943F18CA1FCFC3A33036E88416E22C61B0A6731B395159355009F753B6158B834896D8779A237B783631CB1FEC799F2A25D6A7C0E3B14AEA275CBF87530333869DB5A9CCCA513063C717911275864B2E732484A044E0E73C970F69E15B1263C69A2D0811531DBC5DBB0E759A103FECB7101BA8797658CCA85C45C3CA938FE44B75F", + "5286B4B3C06BEE778B11B81D093018E38544E1065129567A818986ED9669D1457CA897C0358410D2B70BC3DA06F58032CFC32FEA6AC0BE1650B3B535B94028FC9094D5761D5D50693E99C73C2893A466613FF22A8517ACC7640D3FCABF0EF9761637291ABB3829DB5FF1D60E128AA199411B08985C97384D278CC8960499A3080970FB98F050AAB2D30024F429EB465A50038E7F470ED7E2746842A1175AA9D2F080814559508999366B777E447463E21565765B8A6028EC0474A7F4A80127ACCD27AE64C38863188220D2BDCE896441A5192C7600EC561A820C5A47EB98CCC3359BE65996690DAF6B67E4813A74920888D39951D159CF32787A268B6C63BDC440AB8D781774EB9451858AEF27923062451D1856C006B592D501FF542FCE90619F46C94784C79DA73DCB576B10468CCE053EFE0535F6233974D7CB5ED4C0734267C2CCA5ED0688C7C370E4C60CDEBA8DBDCCAA14511CC22014B1DB245EBC59038BC31AAC22E08613A4BA88E00B4C2412623FD21E0944931F5A1E23D0710A503738482A73E7C1DAFC724BFC7CD0F838B2C86D307B918FA42B37388B2D047DCE5B9799D1CA1E359F948CBB20EA5DF75A4C644695B37A92D246B25678B110E68400859600715655A87DD991B7115BC8D008771523437DB06DCBC2BACD460176DC843F41584DAC737E62A0925780BC217669AB609A9454DD7813D65183C361846DA05793E73100D30F7FA3818E59676092A3CFE4065E0AA26A258BE45772AD91BF48979C6F097BF7259313457976019A6751BDF6428A18487A7A32AF479680CB0C34428BC13EABAC1989171A379C7BEB978DEB3BF4F162B1BBCEDE5C726AC52DD06C488CF63682D40E00F08A675CAD6A4C136A0CBF85059401A6C0E5D2B0BDCBA64BB0B6DDF1C476C14759610E2A90B27E913905671D999687BD335FD671010729AE01018FD7B81986057586813D4FE17881463F1838B5E70421479028A0846CFDB0178E0A748C64651877846A609CE86C024A43CB161090D10780786B38C6AA6DBC6461E78C7DDF656AE01A3B0A717ABB415D0E7C8564B83DA2521E98D55361FB14B67136147474B5A56BA8663BF0157518A3C806C20259F4CBC59314710336328BA6945983838ABC65A91820536791048ECD17B7BBE4650C0A32EAA77FC799CF2797C27F35566E630C2BA6B05F608B12818231D67D4886CFF09B286443C7972376EBBA08ECD71C04E945A9A75F82F08E726057DF829D96CB83E4848B92E4263F9596007A1F6B224D794244EA58052EB574896870828C8053658F051BBF1699B657591826348E520707EF8666AB138DB4C3B0E401361A5BABADE2059932356734BCFDFC69146250DF2A78E5A530661446089C030B224F27B3748D2A8239C13D20F10E70F473B82BC3B0CB7C2C82200121478EB60E120C6993A3961AC5850BB25577688EACAABD7F031345AAA692754C3EC48484583D13AC7B11565D9B08A356A1A902067676B20C80DC67D20246B47C199EEC3A934C3D24634ACB119B76BCB3A8A823AFD0CA2CE9277CD9BF03A5565AEA2CDFB811548237D1644F8FBC233EDA44C195241AA0C3C9C94317913A7A8A69566B5166022540B96CBD7781CC5C30529CBA9FEC5E5038BA66A7491F8A0C5CA7B662123B1C5C7F90D0320D617C4CE04F31B466C26A56E1E1CB4721B8C0AC75CDD815C6D37A0D6462D31B264D88A7303A857C333C173C8F09C34F38740E5C87A494003B9347418973462D78B7D57694941B062B06C762F70DF64323DAB70411932349A986C40795187696A672108B1C11357C0D5EB3502E5406DE2721D6C677594B39D9480A7B3B67F3041B6B82C53399335C821940604DD8D03C7D3198167BC83F8C830C785773EC8221986DCCF0C19B462EC5475E878B16C3E2A85C3099C6107A30483CB6E27965DA0D40EACEB7567553396CCD5A1BA6941BA57A33A3A0CAB7B35A31057E24130822D9C78FE9C5AC98268E36BB3D210313A60C3A3359030C6CD1D9C49A277B5EA4825133285B9019CDE943F18CA1FCFC3A33036E88416E22C61B0A6731B395159355009F753B6158B834896D8779A237B783631CB1FEC799F2A25D6A7C0E3B14AEA275CBF87530333869DB5A9CCCA513063C717911275864B2E732484A044E0E73C970F69E15B1263C69A2D0811531DBC5DBB0E759A103FECB7101BA8797658CCA85C45C3CA938FE44B75F6932DAC5B2D5DCB4B510D87F7F195DF2B6A63B3354988B96947A64B462F12F2161846347FDE6757082E3D56EA060CEB773D5F38A84B8D8AACF776EF9CF766CF8" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "DAAA521D7780E6C72D3A6626B8D5DF8ABBC5AE44A9ABC647576035A9A6A9DB4D2056FB9B4E06A790F1D1538BA6D81DE1953902D9D50EA8D646A0231F11D89981", + "D0BC1226CCBAA1558CB1D97BE2239CF6D889B3B64C5D22516C26A230C38291923828A889E44B1C11E495F5D0C0E889057AF35A96B8B10F159A2DD81A518B89017C8019042232C59396C1CE8103747BD981B739CF24CC732F01CC27952E69467566140D4ED27B7B016352E73C4EEC6512E592C18368F8664ACF50C4A82637A58A2A76915BFC8CC5F2D577243A1D5F5646414844921C79896031C772CFF75772CAC91B28795DC5DB2AC558094B3301BC83684D8BB8578660E9C392000807BFAB7E37152DB7E0B89B5A237F5B99CD7757D15006CA617694370C8F09A669467BEFE4BC444359FC105986A592C2AC756812B5DDB6437B038B51AB09AC3A68B9C95103C751EFA07B1AA51A2E579E545503B97A0E595102FF578336E8A19C9616ABB38B4A05CA054023100939910159C2278DA72811CA342E15D0AF20D17923E3AA8C5A9A7CD1BF525009FD51B2AC91B0BB3A2BDCC2AF9AE057FE4219A5994CD8B52FFB14C6C0493AB37C7561DCA143667F92FC8CC1A70EA3024E1A2880F6209A39996F8A6A59ADD159C20577CDEBA9259733A9B7838BFA2D8C213CEDAB87939A4E2AA2634EA3621F789D05C74AA867ADE527B2A0973195812425FB9D7B7866428B8B9A533405707AE3804AC336527FB5A45869C6B5596E293A0981E30038C489C63147E9E412581410FAB669B3253B914571F396232527328EBA8661E8B5554B6077AA8CE6286E376380A99BBC100CC024326870282EDD3363899C8EA1783B5B784FF66333950A146B52B9F7047983443DF0655E0FACBE4D16AE7F629586C3AB4FAA25D7135ED8128BFA1227FB916D4E297F02B7A4CDB9873FA4B1B479C8F9B311A2A2A96128126B031836CB908F79BAB12158464CB731D9331F4CAEC2C96CF484A8E6752899299C13D261FCF6649672CD55432AD12B6FCDB9BBA52319A982A31EA1231CD14EE52122DC0B38D82C853F77189B650894D09E65F924CDC3BB9EB01EBC513E4964A1E4E59B984BB1F4170BF6C68271BA3D18D270ABD56F659C854B252B3F2C006EAA4472C0409FFC902B589A937992094419D7758FA9861E9E89B46810BA280F36FC0C276F0E5E97A0F7D9F06E216FF1BD0A6E0533CF1172A771D31F222F", + "6803B7244577FF638450A497035441C1553FED9675BDA13DDA17BF850C579C3B2AE2E41A10D619E9ACA4EF2B3B83228E40F49CD7FA82065382A574770A5309D9CA80FF5B8C748447967A94FEB74024160FBC7207CA09A635D720285A92BC628FAC214E46C2086D947F703B8EF03005A7C8CC9CEB95AB897C9435AD9F3C53B0F5AFE7819EB22B2638E648BD080874A4BBB62223E07AA1347496A539C9F6DCA1C1D25255F805EE088196F53469AC18D131B714A55619E4481C286293D65D59348B507C2729F0AB9194A0841501C35A531EB04B696B001F8C319BE86888E17FB3D40B897B0CBD05636048BBD33AC42BAB42FCBA2B58F27553612ED585354D68C9DC92896C6B8E62F393310A1461D56E51B34671B587E42991F8CC07DEC156F0FAB4EE4C07D4D23FF6C56E28E596F8A7C0CA4830D5A13C74865472137EE2E95BC79C1E3529B6E2F98850B34A5A723BFC533F431B0634D455E4A69A7F57265386280499BDF92A4E243768C03C13E759CFDC3B7DDBBA8A674B74B8006F4FBA3F06312754241B499814EB118403AA9C86FB44C75413FFCC0DF7253F26445880E8B33634B1C209A69D755458EC77F005491DD57D4E2C7965B41EA62A72CAE09C05DC8BB328708ED6A989A9CCE2D35E8E943647A46DB805A4AE3A931975390B4511A7A10423A70CCD1C9FEA226956D7ABD2A33C37617F2633849EC3BF642892B95A46F98287E8844C8B4519F11BA5160C1C7C139E05D8A87DEB7D8B1C5BE1E90E6787B3C3666A6CA9314843BF055C9A5D1B94AB2736284018FCA0218B99BDB41014349AB0E3C88070F6541CA54F1A5BCC14283A3E8C7926456560FC18A35579523653A211BA3BE8C67E085FD7E14768288AAFF9704FF93B39A771D4E1C15E5A0A0A4C3A8B2A27C5B8AE2AC7B992656E8D151614C8901D669B0CB26176F50717A22C64B97F9FC9AA63C7523B876D91B8A5FB972B853439B3F66781A23B42238DADE336641B28F95BC4E1E7A2387ACF63A03D54F7C17CA61626F6BD61D88D889568A0A73B63024FB5D62DBBB615B584A49554524E843892B750932C5D93C1AAA8B05EC56AC8D0BC1226CCBAA1558CB1D97BE2239CF6D889B3B64C5D22516C26A230C38291923828A889E44B1C11E495F5D0C0E889057AF35A96B8B10F159A2DD81A518B89017C8019042232C59396C1CE8103747BD981B739CF24CC732F01CC27952E69467566140D4ED27B7B016352E73C4EEC6512E592C18368F8664ACF50C4A82637A58A2A76915BFC8CC5F2D577243A1D5F5646414844921C79896031C772CFF75772CAC91B28795DC5DB2AC558094B3301BC83684D8BB8578660E9C392000807BFAB7E37152DB7E0B89B5A237F5B99CD7757D15006CA617694370C8F09A669467BEFE4BC444359FC105986A592C2AC756812B5DDB6437B038B51AB09AC3A68B9C95103C751EFA07B1AA51A2E579E545503B97A0E595102FF578336E8A19C9616ABB38B4A05CA054023100939910159C2278DA72811CA342E15D0AF20D17923E3AA8C5A9A7CD1BF525009FD51B2AC91B0BB3A2BDCC2AF9AE057FE4219A5994CD8B52FFB14C6C0493AB37C7561DCA143667F92FC8CC1A70EA3024E1A2880F6209A39996F8A6A59ADD159C20577CDEBA9259733A9B7838BFA2D8C213CEDAB87939A4E2AA2634EA3621F789D05C74AA867ADE527B2A0973195812425FB9D7B7866428B8B9A533405707AE3804AC336527FB5A45869C6B5596E293A0981E30038C489C63147E9E412581410FAB669B3253B914571F396232527328EBA8661E8B5554B6077AA8CE6286E376380A99BBC100CC024326870282EDD3363899C8EA1783B5B784FF66333950A146B52B9F7047983443DF0655E0FACBE4D16AE7F629586C3AB4FAA25D7135ED8128BFA1227FB916D4E297F02B7A4CDB9873FA4B1B479C8F9B311A2A2A96128126B031836CB908F79BAB12158464CB731D9331F4CAEC2C96CF484A8E6752899299C13D261FCF6649672CD55432AD12B6FCDB9BBA52319A982A31EA1231CD14EE52122DC0B38D82C853F77189B650894D09E65F924CDC3BB9EB01EBC513E4964A1E4E59B984BB1F4170BF6C68271BA3D18D270ABD56F659C854B252B3F2C006EAA4472C0409FFC902B589A937992094419D7758FA9861E9E89B46810BA280F36FC0C276F0E5E97A0F7D9F06E216FF1BD0A6E0533CF1172A771D31F222FE7C46E89DF5DE2178D9423967A9AE021110724B526D36CE1B57E832E939F254B2056FB9B4E06A790F1D1538BA6D81DE1953902D9D50EA8D646A0231F11D89981" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "01026FDD554810181EF771310C94168CC0925D7F62032554049873927DDB99FE0AA3C89691B236AC7FE67013D397FAC23E8107587856A5C99900908CF48FFF8F", + "8B772D7EB64F387418C76C872019AB8C4114B3DA51AD132D545B4BDB3473D88712CE832CE4284B4C824365000D0826516DD19AB8210D7CB73A344074026505C3C6096F624ECBEA67D26B1481F48A72025426296C0120C368B0B2B263A3E8D48060648F0CAA4EBEEC81C995CE55E81197B906783A0B230C5200082739E4175245280D728ABAD725EABB5F58870DC3E944331AB7B78C231ECA88E5F99F085C6021668C2307434147B1A1532FA5F98CF86A069D434B50B0C7CD6C7B2CF03DBF7A48650C49A797BFB5498B96531E5D3C3CAFB6B36FB89AC2A04402D8B7C652C3A4D0CC7CB984B0B001D737053B82CE71D83622A931D7CB87F8461FB5831A98424BE4B70370A8471C2C529FBB175885725F3698E32039FA3B1125C8BA3525377829A5DBA2255D40BDA49469D6CCAC37B626311A8DC96145EDD1B65B354B0C51BFCFB0C01E5BB7A7E02BB1A04221443A7551547972570FA92DD0CC390C965EA8207893E306BFACCA055A8C88EC57E296436182493CC44BC369CE62E0ABBEF01130D920CBE61612F14786722251D331C3806F0BF676B867A85CA1602058CDA887CB3DD78CB4BA76D2671541A42CC24A96E1126B5BC70DB58C2A8269AC6338506DBC31132239127451E551CF82F903EB58783ED177E3950CBCC72E4C1869F176102966AE25269A5CE2606978C762659030775D05178181E37352C88C394233A8968AB23B029F89B41F6B1729CB2CCBDCA05F2B20C44229D0DA8EDA66B16B4A39B8A96526CAAAA92C03615A02DED4AD15918F82ACA02277CCA7A7AD660A56096552F8ECC9D1CACD9D87764FDB6083A765EFB839AE6CB93C9886B9493018A336B418A8DC6A272CDC208618610EB4B24597C3488C0FDBD73C821BB6F521191AD775B0E5BBEE6C88EE627DAEAA6A8484A02E925E3B7C4E9DB3CFEF88CAD5FB17ED3598C1C634592650AE6A61BBC812921564BFA94379A0523085B55075B40703CC113647EFBBA2A593BB22D23DC85175B61388E98398E90B9DDA18528B874326E36C6AFC813B79515D662ACED3B697699E917C4F0B8BC6DD385C1B58CF8DD1A676877C9A2511797E34415FFF7A77CAC769C91D2DF95D16704A933B539936DE505A4DC914E757", + "2C126E25633B90901DA28B91B878C42F288546564A3132A6121653ADD708681C7F367907175673C5EA3C2AE010E1D4B21A1AB3794820CE58A1734B5E5EC8A713047740335D29DB9AF4277824B8920B432EF1E9AB4EE787B8393612153BD1197EB7D9685F83569C029ADDF06F8AD44AB13A32B52C4EC895B48913B99CFA1595443853AA1EA53396F2D476172B67E919BB89659993705E6C5C2F0778906A0C50A5C4A701BCA18A80701300267BE684AE813D88921751748502ABAF61E358A42ABE1398B167FC729E5732D24BA18D982CE1C95FC01A7458B0C82FC839FB7669AB821AD83B963E37148FF3233E0C56DDB693206629C0B8C8F30136B76C3186A178B2E0B739EBA440D352A34A7BD6750320D935DEFC164248691DB018D3F141C92C6D8BF23F97714E3C10C8D35140E278C86EE203B226CD4B51A94A51586FB74A771BC26E19778BF12AC6370D9787257D036261BC13E65355355601C3D787FD24A9C80B489DF29153A790E645B76BCBB1349B9D78C66A36B98ED0F2946716613103142F045AC9D49676422CE431808D8C2F1F3C9E6C2BCCBC1C30831C983B46AED799908F57A2D683AC19772B652443B65B4F73016302A733C6E8504485CF22A39A56C71C31001F2E285F2D9B6800AD2115AB7B4B0A5E0934266E9581AFCCBB9E85043C34161180896D24CBA0A95DABF65C8187B2926CA02D89AB67606000BA1A5F47007B444A74F55965D0A24013192C59A922002BEB0B82994184662339B594C3270087E618A0BC839A340C8FA36B168178ADC27BC8C1D879D2E422103126B3045D07DCA27F95A67FD6AFC61809AA26239A9249FC91A1BCD1AAFABBAD0DD37EFAD26D2EE49684C6CA00758D715614FF735BE86A4D2D9BC3DEDC6BC9065D6B0B9CBB961CC97B91B49854BF28A6F49935BD7A9648587344559E42F5B132A34EF026C2C907C3A440929FCC5399F1BB480506A220264517BE50987BA0621DAD188FFD92AE91394F4196C891CC39CA5210FB0362C89C8CB8D81E779041E33606F5588AC292513FE60714B8B34284A3ABE2B24DF39D4D5CCF704247F8DA1693850CDDC7608B772D7EB64F387418C76C872019AB8C4114B3DA51AD132D545B4BDB3473D88712CE832CE4284B4C824365000D0826516DD19AB8210D7CB73A344074026505C3C6096F624ECBEA67D26B1481F48A72025426296C0120C368B0B2B263A3E8D48060648F0CAA4EBEEC81C995CE55E81197B906783A0B230C5200082739E4175245280D728ABAD725EABB5F58870DC3E944331AB7B78C231ECA88E5F99F085C6021668C2307434147B1A1532FA5F98CF86A069D434B50B0C7CD6C7B2CF03DBF7A48650C49A797BFB5498B96531E5D3C3CAFB6B36FB89AC2A04402D8B7C652C3A4D0CC7CB984B0B001D737053B82CE71D83622A931D7CB87F8461FB5831A98424BE4B70370A8471C2C529FBB175885725F3698E32039FA3B1125C8BA3525377829A5DBA2255D40BDA49469D6CCAC37B626311A8DC96145EDD1B65B354B0C51BFCFB0C01E5BB7A7E02BB1A04221443A7551547972570FA92DD0CC390C965EA8207893E306BFACCA055A8C88EC57E296436182493CC44BC369CE62E0ABBEF01130D920CBE61612F14786722251D331C3806F0BF676B867A85CA1602058CDA887CB3DD78CB4BA76D2671541A42CC24A96E1126B5BC70DB58C2A8269AC6338506DBC31132239127451E551CF82F903EB58783ED177E3950CBCC72E4C1869F176102966AE25269A5CE2606978C762659030775D05178181E37352C88C394233A8968AB23B029F89B41F6B1729CB2CCBDCA05F2B20C44229D0DA8EDA66B16B4A39B8A96526CAAAA92C03615A02DED4AD15918F82ACA02277CCA7A7AD660A56096552F8ECC9D1CACD9D87764FDB6083A765EFB839AE6CB93C9886B9493018A336B418A8DC6A272CDC208618610EB4B24597C3488C0FDBD73C821BB6F521191AD775B0E5BBEE6C88EE627DAEAA6A8484A02E925E3B7C4E9DB3CFEF88CAD5FB17ED3598C1C634592650AE6A61BBC812921564BFA94379A0523085B55075B40703CC113647EFBBA2A593BB22D23DC85175B61388E98398E90B9DDA18528B874326E36C6AFC813B79515D662ACED3B697699E917C4F0B8BC6DD385C1B58CF8DD1A676877C9A2511797E34415FFF7A77CAC769C91D2DF95D16704A933B539936DE505A4DC914E75734BC1268C6703EFC230E2EAC031512BF9BD2C4868C226320BF8CE73413FEC0740AA3C89691B236AC7FE67013D397FAC23E8107587856A5C99900908CF48FFF8F" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "BB340F80FAE62CAAC952C11D038CA6B48B481E32C3D23256A8B3734AF66D4C491CF9C6E284F7A0274D54A824029FA75B614DC0C0284B33811793789A0E7AFE72", + "6BC02A993B7AE4CA512AB647F8E37EB6F175B7D59B8016CD35D41FA51A7DF8878AC69B53018395FED12F152A9074F47652C21ECB00B73F84048C754EDBC3912626A812061CB5532A9B14BAFF5739284AAC55B51599FB6BB6E9B61679CA82B951BC76B5C648904185502972022C6546536A9FD5D45A79E154A1F0A7A3056CB306AC6FE10E7AA45EA3C6BF0D0840264B2DDD979CB3945DD3887C316B70D572945A249A42914754377947A12990DA44C75A1047988FEF87CC63360AD58A5B2CB694664BA42CE7BB20660470362BE585A3A55AC93C11887A366DD4ABBA8A8C812D418C6857904F080A010356F8C49DCC44257C9C4DACA950F9D137A367AD3788AD46FA92B2F27F9D72B1B5712B6F70AB5BD6C45A780904713F838A206FB37E174C5F7E9708DCB7BEBECACC6D5A57EF3A35C2E71404B3AB100A04FBAAC056048798C35678D456C8E5B010712DB4F79637347CD2C8AFEA4AA7B14083842B4F682352C8331250821D9EF3B7ED97275816B5C2966C3E66A707185EA97B84BFEA09A7437A83C18C1BBA892B1C8574C21A19A0BFA8537322B90B96610CE3A9524BD8BF19285473D3A2B8314FC7AB9D267042480A879252C280F76561879428A650BC0B3757062C16F61D131AB1DA83443EB547A4A641BBB09D6E3B183910656EF8A7DE93108EC3CFAF8A1FCD2214A1056A2F83C6F38A4867A00C9CE31532C141872257B32C500735CAD72842A6A65200696C2D723C0F3147ECF0AD864B219D6616D36C7389B03014065A9AC69155B08CBDB4BAED38CC06F2C121636087783D5299B3B07494DE79B80A1AB59B11B5302C5EA0B18208EB96574A2DACCBB48E4645058203829B62C709A9F74AA0B9C890B2FA06329595FEA79D291864724186F1D98E010B73A380B830958B6DFC811B4143A5A4A570D17659C0A448E40097FBB11B35BB66EA47EFECA10DA14D0B7560DA5023BB2B76B37C24725C6B934B8CFBFB32A7CC6AE556C22114BFC7C6C5E3B6CA2EB43244A13E7A2C362686A54AE66368559A9A33AAD1FA459F786249135DCBA89163DBAC0414C7E769CA8FA8975EEB9ED2960C63CC526DBDAC994C54BAD10A310D76190D645207F683CE9DD28519E6BBED8D42787371", + "417A31563BC1423B77ED209741C64DA6281B8C733F2E3623B22B5F14C17888957CCA0B88C4222AAE9B1FA45636F22B2C2EF23E21442852CB7BCC2A6F63E7B4BE001922B682FF926F879775615686B3F59EEB04AA4C00AC03E8C267555114756FF2F63456E1AAFC040CBBF3BF3DD12F7C1C7FFAB643A4DB0986A86AB1D2A49C4A64CB4BC421B03E669481FF822C2B9573B9B2B5A8B17EEC6CB4ABF3CC86135569EC5FB7A9AFF8E4296ABB0EF06A20718A71BFE8406C8AB35B3BB511D81D1D030C4B08C1B485423BB26C7506364BD06CA95A9E9F730EACA84D09CB91DC894CF5C025C699BEB3CC84BD953260136BD8F000D8CA0A9F4B3E635B1A9731A232562D50F9C8F16A8929FB20659105DD6A44E06C065E46475622C0FDE6B32C5368F28803DE995E225CB3BCF021BA6C90A012005EBA3E93856781B408CD7A72E18C8DA3B3AA7C154D9E916BB50B6D1EB57A36739CFC314699B241AF5303505BCD7D118D0610AB49D0BA2A55516D3587B24633B6DC269DA63069012940153D2293B20A5695C0A0C9D1E391246659499498706716D8827CA457AD984CB211157871021E608091531C8578F5399DE0C0BE9B7387D297F049176876057F1411D58094AF8468018992CDEC7E1DE980F6046B20D378FE5450E254B417149AAB9CB1395352A7988E96136118E5C22999ABA6E0233542B3F5C293162C4D1982440A6B6D88E8B60D25178DE0B945D02A4A74537D37CFC984A7E6B0749251753A4C80FD9819CB0417F3FC7B9FD6AC0A974C58563087348716B89010A7881C6A9C8DF1626E139EE53A13A358B805659B2C438B26A5A399564E3B39C74EE1656F6A4098E44E6FD4CC77479ED72727816A56DFCB16D728BD8909379388185537484EAA124EF8B82A4286033973185274EF2206982889D0FA384C025FC9C63430F96786D245000A5ECDB2ADF577BD8410C2A1A5119E653FF3D6795E924C0964C40539555024C98B753D631C83BCAC48B4FA6F5C52471486B9E893A98EE307F1237DD4242BFC11CFA26797FF1BB67B0136E1A25067756AE67472C8F53199F115241C697B9C18FCAC71D6C3C76BC02A993B7AE4CA512AB647F8E37EB6F175B7D59B8016CD35D41FA51A7DF8878AC69B53018395FED12F152A9074F47652C21ECB00B73F84048C754EDBC3912626A812061CB5532A9B14BAFF5739284AAC55B51599FB6BB6E9B61679CA82B951BC76B5C648904185502972022C6546536A9FD5D45A79E154A1F0A7A3056CB306AC6FE10E7AA45EA3C6BF0D0840264B2DDD979CB3945DD3887C316B70D572945A249A42914754377947A12990DA44C75A1047988FEF87CC63360AD58A5B2CB694664BA42CE7BB20660470362BE585A3A55AC93C11887A366DD4ABBA8A8C812D418C6857904F080A010356F8C49DCC44257C9C4DACA950F9D137A367AD3788AD46FA92B2F27F9D72B1B5712B6F70AB5BD6C45A780904713F838A206FB37E174C5F7E9708DCB7BEBECACC6D5A57EF3A35C2E71404B3AB100A04FBAAC056048798C35678D456C8E5B010712DB4F79637347CD2C8AFEA4AA7B14083842B4F682352C8331250821D9EF3B7ED97275816B5C2966C3E66A707185EA97B84BFEA09A7437A83C18C1BBA892B1C8574C21A19A0BFA8537322B90B96610CE3A9524BD8BF19285473D3A2B8314FC7AB9D267042480A879252C280F76561879428A650BC0B3757062C16F61D131AB1DA83443EB547A4A641BBB09D6E3B183910656EF8A7DE93108EC3CFAF8A1FCD2214A1056A2F83C6F38A4867A00C9CE31532C141872257B32C500735CAD72842A6A65200696C2D723C0F3147ECF0AD864B219D6616D36C7389B03014065A9AC69155B08CBDB4BAED38CC06F2C121636087783D5299B3B07494DE79B80A1AB59B11B5302C5EA0B18208EB96574A2DACCBB48E4645058203829B62C709A9F74AA0B9C890B2FA06329595FEA79D291864724186F1D98E010B73A380B830958B6DFC811B4143A5A4A570D17659C0A448E40097FBB11B35BB66EA47EFECA10DA14D0B7560DA5023BB2B76B37C24725C6B934B8CFBFB32A7CC6AE556C22114BFC7C6C5E3B6CA2EB43244A13E7A2C362686A54AE66368559A9A33AAD1FA459F786249135DCBA89163DBAC0414C7E769CA8FA8975EEB9ED2960C63CC526DBDAC994C54BAD10A310D76190D645207F683CE9DD28519E6BBED8D42787371D3BF625ED315EA37EDF783E30384EBA9DAD0BA992895590B9BE5142A0B18C14F1CF9C6E284F7A0274D54A824029FA75B614DC0C0284B33811793789A0E7AFE72" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "B9D7B2FB98BD6A3251534E088C92B8E5DD7148AA3A66F9B8269F9B68C8544C310DE000E8490D449A103FD744767006AE2662A8993BDE5DBAC0FB09DD577B7128", + "A2C7B45E3CC718B5071FA09041A84C1476B4D7081DE0890EB1A76BC0454D60A87CE7E299BDDC8DA4D15C128357BAC549A756B7F1D8596879A293C749AB44A6296385BED93271893790E36C9B1A4C390363CFBA9F1BA27EA546AE15B99249B7B90ED83589F7CC4DEC65F1E896F9D18A90A81C774301DF221C6674A3F7EB861B1CC70E57699C6652AE8510474A53E236BEB3AC54F34C64D0F0588771C4312760BAA99034C251FB69952BE644EABC042BBB5D68B7B30CB35DD772BF63A248083B97DCAA395F607809A14F1FB791F023240B98A9593352F8DC8C976CAF1C63B4B7ECB161632C35ABACD67387A14BABC4044F9526B29BC35B4B923D91F8649D60539A0939645040E2257F570C32E989CD8E9CB1ECC288E91A389268A2549BB1D38C7859086B7448A91A5B8107C25B2E053E9445780EC35F5D753B9205ADF2B3C0593C9EAB2A217212AFABA7A6BDF38E59AA7727BA90DB59A9AD85AB163662C48AB9F5E4B907993B2D66C1B9CC5D58681818F9974FB5801E8255BFF41436C9813E8660F278780D807A498892DCE51CE43452FB0C1BE84C74BCF313578272BBB5127577C2A3E3490000B7CD2349CB49625519B124649AF331CC7AD06B28315507462A7375AD22239C6DD326BCFC5F1C02529BC35715051973EAC90DC4C3D1227AE6BA8E150143E76C5E83ACB6EAEC6BB3CB5FA573C94D46C39EF019D85A4C7A6614794BA310A0763B4A9C358434274626C6162C94D44867DB00D9886AA3AC8D0260209C4A241AB3444D513A86829B8446913DDA4FB0307124172993B9BF80B067FB2B9EBF082FE1821A5FB04131C0BF8AF0702B443251771296C047FA6A1498DA8E5618426841A22A2A4C25277ED341C830197B716A96B380CCD36481F33CBA46F828667CB1B5AB5F07C51D6A3B863F404D93E548D5E3905509131D842FA2247043A9C05B4838B6B03E11CC6E085115C8F408EBF05D600A4A68339892012666257B6F0816C6648B422A38068AB045DB34C41BBB34AA270407363010AFE89CCC372A25D2EBA178292E33837B399271EA4237B6C580C41750EFE4ADED3361B2185A1C73648C5B5E04E760DF705268122C916EA5DA43C89235801D975812BC1521C4C7A9D3", + "4DB87872E317B79C6D42157C41ECC9DACA0091761F00A2B251D946042943EC89B5F555CE4B9845574967D7EC21A1D432AD587795D66CA6C603BC700BE3F295FE0B3CEFCB8313E9CDF02C3DC8A758C33073BB50BB8D64856F406DEDA03D77784A98180222C011C4F1B9F4D1B3D2932F9FBB446A214B14D1049665A8C469BB2439506276CB14A84ABEA0B2D2B60221D20D1ED17D5E95AB382A69829C08C75754B0982B98EC518073BAAC58A5A054482F72223FB85D23E73534B18FAF00B243B372A1118417487B9B48954989029786074902B98C1483946AAFC834C672B28558D69BC88709F6018B20EBB664EB32DF221B7EF70E7212727BE7189FAC983A3B7D633A9DB8157FDC76630E61314D547FF345AD41A05E705975591A1DBAE786CDC652D0C87A52F4B5F51BC43F637E8549A7743C82E305021B2CB881B4B98FB48960AC614D7514D68B13E583B85F2C0ED9BC10B7311B2A38A9E4342CE7D94F2A8BB74D0C997E7C1219C84001C211E4BC2704595CA2300EFFE9775FA0CC01995E9AD80CD2C41EF3F51F8D5C3DFA065613D14F896BBFFD220B3B3CC7BC4A5012F30D439346283041E229C3EE5748B6D8AF950250E432ADFB1CA2532A4571B8614404954BC742F4095B1F24100F1634C5C810F756480265A19CB72EFE3324E8823650D7727798670E44BCAF65A2C00843E67A797BAC0670C0C31759905DE752D51A289FD65B9DB330DDBB3A1B5220CCD99F293814B8FA1EC4A93A77FA8E2C03CC5DF4500E25A4465B64667B07DB8A64B0ACAE5AF10F55E82EAFC10E15B95A18097D08124A1337951DF09179717A63AA33466BC0D0C299E7782669227AC9D059ED666DF5272DFA7C58AA789E44F523EB0567BB4AB06B7A39CEA8ACD5EA2ECE689AEF01C4AA483D4851BD7FC863B434A3A33819D4C615590A5BA837A32E7BAA8A1CB38EF13794E2B514EA70135091D43C14C1896CFDC77108D41032C78FE26A9040304A1F478D79B5361A75C55CA7C3A19304083B9173FBA36695271A7704FBF2685ECBCEEA035F26C15AEC8CB91F091A4B1BA3B7EA107097C0DF824ABFF6B3544ACC5F189EA2C7B45E3CC718B5071FA09041A84C1476B4D7081DE0890EB1A76BC0454D60A87CE7E299BDDC8DA4D15C128357BAC549A756B7F1D8596879A293C749AB44A6296385BED93271893790E36C9B1A4C390363CFBA9F1BA27EA546AE15B99249B7B90ED83589F7CC4DEC65F1E896F9D18A90A81C774301DF221C6674A3F7EB861B1CC70E57699C6652AE8510474A53E236BEB3AC54F34C64D0F0588771C4312760BAA99034C251FB69952BE644EABC042BBB5D68B7B30CB35DD772BF63A248083B97DCAA395F607809A14F1FB791F023240B98A9593352F8DC8C976CAF1C63B4B7ECB161632C35ABACD67387A14BABC4044F9526B29BC35B4B923D91F8649D60539A0939645040E2257F570C32E989CD8E9CB1ECC288E91A389268A2549BB1D38C7859086B7448A91A5B8107C25B2E053E9445780EC35F5D753B9205ADF2B3C0593C9EAB2A217212AFABA7A6BDF38E59AA7727BA90DB59A9AD85AB163662C48AB9F5E4B907993B2D66C1B9CC5D58681818F9974FB5801E8255BFF41436C9813E8660F278780D807A498892DCE51CE43452FB0C1BE84C74BCF313578272BBB5127577C2A3E3490000B7CD2349CB49625519B124649AF331CC7AD06B28315507462A7375AD22239C6DD326BCFC5F1C02529BC35715051973EAC90DC4C3D1227AE6BA8E150143E76C5E83ACB6EAEC6BB3CB5FA573C94D46C39EF019D85A4C7A6614794BA310A0763B4A9C358434274626C6162C94D44867DB00D9886AA3AC8D0260209C4A241AB3444D513A86829B8446913DDA4FB0307124172993B9BF80B067FB2B9EBF082FE1821A5FB04131C0BF8AF0702B443251771296C047FA6A1498DA8E5618426841A22A2A4C25277ED341C830197B716A96B380CCD36481F33CBA46F828667CB1B5AB5F07C51D6A3B863F404D93E548D5E3905509131D842FA2247043A9C05B4838B6B03E11CC6E085115C8F408EBF05D600A4A68339892012666257B6F0816C6648B422A38068AB045DB34C41BBB34AA270407363010AFE89CCC372A25D2EBA178292E33837B399271EA4237B6C580C41750EFE4ADED3361B2185A1C73648C5B5E04E760DF705268122C916EA5DA43C89235801D975812BC1521C4C7A9D325611692C645FF61151D18FABBA776D8FEAE8A0791BC06F3C2C04C03C83D176D0DE000E8490D449A103FD744767006AE2662A8993BDE5DBAC0FB09DD577B7128" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "8832AF93DA473A24913CED5C41630E344B89915AD753190F1C60F5F8E3B3C4E06EBD1DD09EF84345BE9DFC145D865D60B4E43598DA1AE4A5034D8C1D8CF9C18D", + "9236226CC39D8B9B08E2A986B8534BE09400A1182D61B699F7C44FBC9218417A5AD20207B79A77F70A62358900D827C0BD605535E18566952956AB917D28815A7C629DEBCDE809B44F9C54F1CAADC162998A0CB239767585F15F2A45575B497DBF805BA8D000F469A9E2BA1697D41280AB54EA0A2D681C1F0F34B703C94C37DBBF9B912A7EAB13DDCA070572A8AAE7C095679C9A15813962B53FFBCBED171A6EBB2E669A14048B97876279E90C8B31004C1F0510BAA797D4E07E47A2C1B9B9593446200BF54B98A9B19D2C04616904CAA1BECCEA231EA448A5C0057F52ADBDFCB4822A2A0EB898E8F6994039140F2BA1F11CBD8240B427793449F2CBBB054028F49121F509FCA849F9036BC7646163EAB7FB041EA80CB780EB7E69E56B49F9B9C2F5011FAA8CBD21BE144321F4D015695591FF2CB9C44A3C9506740721BE0A783D836CBC2AD7886251854745845089920AE59C07D2940B310F9FF45AF179B48B03C483D562AAE4310168884F0893A47263F9DB6228C292F1BC6B5F83147276A36A32A488ABAD1CF90666356CBCEB9487E5951BAB61F91BA7501A7D55B89A15319277D71DE43A96160421AE605B91871F290B4E746B0C3C90C22279367AF76AC64C762FC6725C7B4BAB99A300F29783EA96D9C6410D103D56813BB974A7C9C563D9CC6F22D620536406BF0C4B2ED2185F612B8B685DCD2200171869847628DECC9C436122C5A42DAE482A6EC3778C71926260AE4094471C448E6CC839B1DBC26BA57870C856F1DC5EF36C23470892CCEB95BDE336035806F936A015267E3AE87E81994B5D220FB04B03C971A60ACBAC9152769D56868B98808AEACDBBA6291946CA27D7CA48D7717547690FD9CE9A0278B1F56F76988102B5613F865DC77021878397CA27A79F3A8EE0034A042885A9E188B2E30542AA0405245B269BAA3C55277CA6A289531208AC9C6BAC93F7190209FB58488C7A5BE3C537C8AA118C8C3238B9CD68294784C81DD54949A7293C2B6B174A3CF2AC5DB36543AA02598195BF5A4AC1756A3E4481127B111EB9343594F8CF7367199363A0E292939B951853216C27C423399B123084BCCBCB8C9A6649493E775BAE4533F795CB8E7FCDC0448496", + "49529112F57300DCAF63A20DAF213E1AA3B5625382F5E0CE36C64B2C2B7B83B446CE95A26AB26B4CC85E5D729B9E97603B767D21450EB59B91C31C9E41B5161D8568A6D07935EB545FF1B5C70C9E561B8299F482D9A65378E25EA9168ADAD82EABEC6D95B06A4F606C23168F9D0A3442329627E9337541C10DEB3A9B235C1EC63AB1FB3F0BC334D5A081B7498AF3E602A4E7C35DE86446E82FB0B3563A772FA934A184196871BB6D2266062D25C97832BC6B57454D1C70A0DC39B82178964C2709762B06AB3E2A92B8071B764D9A3774995948D67E405C129646521FF9B3109203155B84753A31E4161B417597443C46A7463043A8AECA51411DAA5D64853F3F83631F8880C92036058A244BE85436162EA8A85052F22FFD0A5943B8A883C81FA5047AE0DCA384893D8CD2A4F4A31181610B92C8364EEB0B7EE50507C9016B9C1D383A6E8C991058848D22FA5948953D0E320A1C0C129A66590BD0B042E727B351956EA7C59E01178AB95140B54BD79C0A069661F27464314ACEB27152954A7CFE971B58B7877A0AAE2AD2821A6946A064634DBBC35FC77E6DB59A8142370BC7C665B38B609250CC36BEC99210B3432446B171070C012A55844FA435EC4BB118A151525B222F20B720BC574A863BD7810FA4572821B97513257A111016D39A81EE3ACC42AC05612C83CB0955B1E4A7BC76007F073C4D900C31361BA1A165D63526E5E48B430735B2C7C3EF840067111576A239B983074CF8B5FCD38A69E69BD2378C9F8324DB5968BE06C82EC700DA6339D78B35AAF2A06907C6597B2D70B39757A9AD78E68AB8313D2E319143784AA650447FB24D3738549054911AEC04ABB062B7E88F199405776652321059C0F3AE912C253520283CA3B05A4C1D2058BE1B5099FC29495927C7A4EC32301B86E168AD55542919C0BFE0D51FAEC1887F32992CB601A99B19CF8710C05020F9520A4428AC78E4C0F873642A5A3B6D970D372B5C1C302267D9694A85607A0161E8D5B172E34EBBC01C405B558B04330A72A938530F32D0459934C8D073B9D364963D13B283ECCC7B6C251BFA55F20A8DFF912F9236226CC39D8B9B08E2A986B8534BE09400A1182D61B699F7C44FBC9218417A5AD20207B79A77F70A62358900D827C0BD605535E18566952956AB917D28815A7C629DEBCDE809B44F9C54F1CAADC162998A0CB239767585F15F2A45575B497DBF805BA8D000F469A9E2BA1697D41280AB54EA0A2D681C1F0F34B703C94C37DBBF9B912A7EAB13DDCA070572A8AAE7C095679C9A15813962B53FFBCBED171A6EBB2E669A14048B97876279E90C8B31004C1F0510BAA797D4E07E47A2C1B9B9593446200BF54B98A9B19D2C04616904CAA1BECCEA231EA448A5C0057F52ADBDFCB4822A2A0EB898E8F6994039140F2BA1F11CBD8240B427793449F2CBBB054028F49121F509FCA849F9036BC7646163EAB7FB041EA80CB780EB7E69E56B49F9B9C2F5011FAA8CBD21BE144321F4D015695591FF2CB9C44A3C9506740721BE0A783D836CBC2AD7886251854745845089920AE59C07D2940B310F9FF45AF179B48B03C483D562AAE4310168884F0893A47263F9DB6228C292F1BC6B5F83147276A36A32A488ABAD1CF90666356CBCEB9487E5951BAB61F91BA7501A7D55B89A15319277D71DE43A96160421AE605B91871F290B4E746B0C3C90C22279367AF76AC64C762FC6725C7B4BAB99A300F29783EA96D9C6410D103D56813BB974A7C9C563D9CC6F22D620536406BF0C4B2ED2185F612B8B685DCD2200171869847628DECC9C436122C5A42DAE482A6EC3778C71926260AE4094471C448E6CC839B1DBC26BA57870C856F1DC5EF36C23470892CCEB95BDE336035806F936A015267E3AE87E81994B5D220FB04B03C971A60ACBAC9152769D56868B98808AEACDBBA6291946CA27D7CA48D7717547690FD9CE9A0278B1F56F76988102B5613F865DC77021878397CA27A79F3A8EE0034A042885A9E188B2E30542AA0405245B269BAA3C55277CA6A289531208AC9C6BAC93F7190209FB58488C7A5BE3C537C8AA118C8C3238B9CD68294784C81DD54949A7293C2B6B174A3CF2AC5DB36543AA02598195BF5A4AC1756A3E4481127B111EB9343594F8CF7367199363A0E292939B951853216C27C423399B123084BCCBCB8C9A6649493E775BAE4533F795CB8E7FCDC0448496BB36BCE0CE75236C71F05D81BD08F60D11E12CC013F9E15E03DC0F2800BB73FE6EBD1DD09EF84345BE9DFC145D865D60B4E43598DA1AE4A5034D8C1D8CF9C18D" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "12ACE472A49609E131BD7627EBBFD9925CC0FBDABBDD5E5DA7D8B43A5694D73CE6AAF266FA60B4FE09D01C8EFD61B1F7308BB1462379740512DFD3599413B14E", + "F82C8FC5A972DF3CCECB329B91C9A9ADFC355B0650D2B66120CAADC1D394A9C77243048AC861445AD553F5CA87532B3E82CA909BA6672017AF5C3236A463CA40AB83FAF05074B810C09725F7F901AB5209D0B53D4F290711B0052E924F93B61810EA8C4C3A38F17B5C1E982B8DFCA3D084992865395535C41E3C533B1C8415A13BFC16ACE1711A6BE6A82D0A396F957A71831E9764BFA6396AB5699E94651BE32CAFD577C96017AC9B12258241A9185A81E4C72C62B638B893B9F91787F7B65F620BC2332C2908F08FC276B4A6B6448C52C613A357511C45F130298D97CE8465851D9B9535D063E1A4C6FFCC4C9557A54D039CD0E9A31660B60F8B0F7F758E59EC6B45C395046A24567BB0ADC488D420BECC5C91D2D091712474FA25A1B06349F93344625857B2E820FB6C1FDC3CAB90C69EB093780B9CC23879B23CC54804571A3CB25BA5CB707FC319D1DA433F502019BAB8362C58A5F4120AF6B65E0316F1BAA619164CF9B358BFD361C70C6809A683C86C870E92379AA77B15667B9A3284D17B0025109BF1374A2887923C184A82A76669B259CDFB33C9ACCD5E0CB6F57BCEAC45B29C009411298370A9AABAB0AFFD4863E9786694F2251373BB58F965F3A76E252A3FB4D50E5F705355A53A92BA080482BA5D5A9660135B96869B1413464FB06E1AA46B2B30BFAC6618DF852030BA043BC721F3651288900C38BB3E15CC8B6A86750F24B2A498C785772E86931F54CC89D0D96964D5748CB9CEE9C4594D7116E590BC4D8105D7B1AAD729542F568CD64300705A6F62348FC4656C21FB280FC41B2A8125607A1F400915D7BA52357656312A2579C8A8792B296FDC6DC98322734C7DD7801BFD6306EB620009272485CCB8C3315507254CB7B11C27758B4C1C465BF9A38D668B2A3B97A6B564BD022208646BC92B5182BB834F397BD4C48FD36C3DD742BA631BCE9D184260125F7E0847D294C3AF430207AA1FE7CB7840F00CAAB33AE0C6AE0BA97E4AEB9BBC34C82D0A3345F53969268FFD77066D8C400BEB40BD4444BDF60EE5B357ECC99B83CA546E01C3E4295D42A034BC2A13F54CC699E4DD47D7BCEE5C54356A407D12C7E267D4BF17605738973228DBC836E0B80D", + "455C2813ECC6DD31C31535753E7BAE717A6DD2E337C3D5AD93780845665F311B31A6DB915726A3289641188C1D0361489B99481331080107AEBBF18A6A179F0C7A191EA3630E75C62932395EA31B84C8C6FEF5C17E8312A19A02BCD39C4D8609355C376845C728A738482A09B120C7F9B80002A18DF1C1529363C17ED8B922C6457B789CA0409A0305351C49A7BCD75B21F69CBF6B037708B14A6CAC5AFA7F3A72316FA0AC9EB3AA9BE0CBF11527A326915DD622C5874FDAA2133187543EA249198739E4326CBF0055F3194B42DC4332C10DD9F3195E571CD84C682252384E45872E8449F9D2B504CBA2242395D2734C11FC7776142EBFA89E31B4CEC05BC7D2631DBEC93D9933118A5C52C69C63A6694F8BD1248C95B3EB4461D4F4A84E22699250819434B5DC018A6919035609AA5612007F70CEA68A1FDC9A0B3C10C9C2A62477988E708B685E443D60B34F98BA86A721B54DF91E58C7AE35C558E72BC82F09CE927B9440633050450A4A94272FF9850A8992ADA09FF8DC0AA24C80690076F55106A975717A67C7C09795F071B30F9376FF2C7BE8369C12A5CC148A33668BAAC3A5935FF13052769B925A5A6F2B20EDDA1319E3881778CDF44531411225907563BE1BA09A224E1944AAD9C52BBEF82FADFC337E737573506FAE54426C10C9A5F150B8A5021D9A69B5062EAEC33609FC524A93367836A8B272506D74C561C60C29C781278AB0CF118807D36B38F160A83C0C2F4A9B035873E362B268346E1CC63A87017D15582806813DCBCA2AE6B0CF9203B26C79070ED95586D58A5139760A483DD123635C6AAED1956C3D57AB6D19BA3EA1CE9A4C58F555197A162CC7C8CD85832951C4289676A8C1FA24053C5E88A58812709B1BA0481CC88E01F9B7BB850137DB5C6EBB1EF0B15C5048B7CC24A60A2CC290BB46AFD6A05D42C25A52931AD728AD746765C5CB548345ACEB4D0A5C8202CBCB053BB7DB661C9D890FDAF2CD2082B8D1E43E6B161947BB95A1825AAC15523CAA7B6F196348F07A3F62C579DA2B25444D78FA34A51A08B1C19CC03239E4C1231C134244694D1B9C72F533A0F82C8FC5A972DF3CCECB329B91C9A9ADFC355B0650D2B66120CAADC1D394A9C77243048AC861445AD553F5CA87532B3E82CA909BA6672017AF5C3236A463CA40AB83FAF05074B810C09725F7F901AB5209D0B53D4F290711B0052E924F93B61810EA8C4C3A38F17B5C1E982B8DFCA3D084992865395535C41E3C533B1C8415A13BFC16ACE1711A6BE6A82D0A396F957A71831E9764BFA6396AB5699E94651BE32CAFD577C96017AC9B12258241A9185A81E4C72C62B638B893B9F91787F7B65F620BC2332C2908F08FC276B4A6B6448C52C613A357511C45F130298D97CE8465851D9B9535D063E1A4C6FFCC4C9557A54D039CD0E9A31660B60F8B0F7F758E59EC6B45C395046A24567BB0ADC488D420BECC5C91D2D091712474FA25A1B06349F93344625857B2E820FB6C1FDC3CAB90C69EB093780B9CC23879B23CC54804571A3CB25BA5CB707FC319D1DA433F502019BAB8362C58A5F4120AF6B65E0316F1BAA619164CF9B358BFD361C70C6809A683C86C870E92379AA77B15667B9A3284D17B0025109BF1374A2887923C184A82A76669B259CDFB33C9ACCD5E0CB6F57BCEAC45B29C009411298370A9AABAB0AFFD4863E9786694F2251373BB58F965F3A76E252A3FB4D50E5F705355A53A92BA080482BA5D5A9660135B96869B1413464FB06E1AA46B2B30BFAC6618DF852030BA043BC721F3651288900C38BB3E15CC8B6A86750F24B2A498C785772E86931F54CC89D0D96964D5748CB9CEE9C4594D7116E590BC4D8105D7B1AAD729542F568CD64300705A6F62348FC4656C21FB280FC41B2A8125607A1F400915D7BA52357656312A2579C8A8792B296FDC6DC98322734C7DD7801BFD6306EB620009272485CCB8C3315507254CB7B11C27758B4C1C465BF9A38D668B2A3B97A6B564BD022208646BC92B5182BB834F397BD4C48FD36C3DD742BA631BCE9D184260125F7E0847D294C3AF430207AA1FE7CB7840F00CAAB33AE0C6AE0BA97E4AEB9BBC34C82D0A3345F53969268FFD77066D8C400BEB40BD4444BDF60EE5B357ECC99B83CA546E01C3E4295D42A034BC2A13F54CC699E4DD47D7BCEE5C54356A407D12C7E267D4BF17605738973228DBC836E0B80DD6E05C4892A63748237D7413F729C4CBA8EC224A30465409F9DB4509847F945DE6AAF266FA60B4FE09D01C8EFD61B1F7308BB1462379740512DFD3599413B14E" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "77BDFD425F4C0699AACD7045E62093D55EE7419FF244F75233C9B597AEB0CBE75F8985ADBDBF2287F3127CBAC269ADB9B364C5A9FA4E69FD6BBB0182D4F9AB26", + "40A1765A99C6CA801DB608C6DB79ACC2615B690991826BBC61501900E170ACE025C0D8771F79524DD5A6BC563BE69C16FA0A2161866A42F1955B7405DB52B52385C2D5E0B98DE180309666B2B53D4CF62772CC56515C155CCB458179382FC82240ECA71423499590BAD96337F6904DC75AB63E8C9596630966E8310378638C8C200FBB2921E98B21D97FD8066C57CB657C57B5674791C83C57C53930A7C92C78B44C31916D0A06CBDDCA63549A4097243538623DFC4593FF73A0DC170B1F013883BB9232CA3D6B6C3F59925AC6DC63C168668198C6A78C44DCA311B9B25F5AC168EAB2CE0CDB9B2A0C1776B5A75EB51242C414E74C49C5CC4CCA6A656A95233C79692153051B115DB3B2BA02D1B0DA6478C3B106753237704459FA04AEEF5916F756428B1B7C003C10EAEC1965A41E03F63411757E46D6BBD908D0621A42643B2B7A186A68695D9CB20417233A79D433F5498DE3A548FE66738A579CE9F2BCBE322B6E2B14FE11A571ACA89C80596AB76A645117FF4C9AB9057ED1CB45B9F4568D26A05A4A250282C112FC041D170F2E627182CB8A93E3C2F1171BA32606BD375EB624376BCC022F0B3C43AC89C1298B0DC4C691D8667F26C9FD37A671D56736C92B46913346FA0E2459CDC2F893A330683D6B5EFCDB162AB871A7767B945C50C0D57CE30124CFF31C4008AD7D12111F751810C981CB370B0D84BAB3D165409C0C499AB764487C69A6411288C3983A748DBA2C21977C911A18569B5A9691B95EA5C1BA8B3998294738570E029505306865B172B25D36996E734676253D72C07F0D285562E3893068BC9496783CCA8283B8BE719953E301C7DDB1638EC5B1F473B2B7A8CF24501AE167B46F2101B2C83E18FB4C63658A24535454413D69692BE57B4073B41F63491ACF03B2786CB2294208CCD689F6FA2E11908A8DFB201759B8F546236D63306102BD4562B4F4F02E32610542DC8914806AC0F14CAA67985CE458DD0746780B5AC6B2A825C6700D9AC119A5CB2E7B8D7D5B74B40B4242B28FE9F6B8846613616741E80460DB19848673BAFA6A2F40E0B9DF38C304219AD654C721BEC2D45FCF567AFC43F48C0EE3185A745399D3562034E732A82180C21E4C4A", + "224B292ECCB1D6B35109D58820A72F0A0774B3D11165495CCE78AB6B632614A96E57E9B631E6A375253890E7CCA924943EEA8EB4C018F4885CCBD96009870DAF45925D43135AF60B73EA988CE4AB232C75EBC37479A2213373BE9B429BD8413433BCCA3725763B3484E6026F4DE34798BC8171183CB7001B17841CC3EA34448156322604DDF75B4771AC52330C9FB4330B711C2EB1B152151CDAA45BBA880F1ED0B683E871F9AA2A19846A73060FAA81B189B2A80FD0893ECCC37BD5A701E74F18E91E6BC85C01D962DB3A71B5DA7C57C66F392CCD3A315AA47A81FE78B51FD1425844602FD8C9035AA1BA36C4E851C11DE3A7EE62869988654FA516BAF707276B139C55B1E6468DB0E19F31C0450195658C22BB7A953866DC8407A23A82059F7C02AA5C85BE9B57A7D200022CDA38A0F64FBF674712CCCA8DA9AF0228783D163181044AFCB800FD3401E9A2190C07627C266B40D76E995282E50B682391C30A23A1EDB282FCA104104054B2F677ACCCB7857B3581E055A47CA498F408A98902A7883824D128A5183D995B5E082ACD40237480C37EF5A995E1E1740520B2A7900DC1A4A1CA3A02D19B2B95D5521C0C5FC765B55B9ACF06ABAC9BCC6B995961CFAABD24273829365467184DE5F0A8DEA2C1FE67C2E39345F0D779878073A6354C90035F8B26A7FBFC32529C93E9A06FE8C248B11A3FD9E49F04867E061CB2BA7C8BC02AAF77077FD944AFB1424203187D2A53286D662C41062A49538925A0AC17B07904931240C548393B123C2B9561A953F827C727F248E16812E6910C5753B692F225AD6172B886A3B4D906E5592BB7E24F018CB824B128220B9E2B641038530FB5722934E44545EA620BFBBAA59716050A59181628FEB6659447837FCA998FCA54777ACFCDB19320A87AF58131499755AFA7A627727314585398C44A3118BC41700DB67A04FB279C8E60B9F754AA4CAA2E73329361841768A62F49B549CD1512681068B2F36D1DE459C1882B472959C70C2DF338541BF48AA75C6E085C66BAE1B1DEC9C662694306A3015366AE798B0D61C79ACA689AA6EB6B86E305E6E36540A1765A99C6CA801DB608C6DB79ACC2615B690991826BBC61501900E170ACE025C0D8771F79524DD5A6BC563BE69C16FA0A2161866A42F1955B7405DB52B52385C2D5E0B98DE180309666B2B53D4CF62772CC56515C155CCB458179382FC82240ECA71423499590BAD96337F6904DC75AB63E8C9596630966E8310378638C8C200FBB2921E98B21D97FD8066C57CB657C57B5674791C83C57C53930A7C92C78B44C31916D0A06CBDDCA63549A4097243538623DFC4593FF73A0DC170B1F013883BB9232CA3D6B6C3F59925AC6DC63C168668198C6A78C44DCA311B9B25F5AC168EAB2CE0CDB9B2A0C1776B5A75EB51242C414E74C49C5CC4CCA6A656A95233C79692153051B115DB3B2BA02D1B0DA6478C3B106753237704459FA04AEEF5916F756428B1B7C003C10EAEC1965A41E03F63411757E46D6BBD908D0621A42643B2B7A186A68695D9CB20417233A79D433F5498DE3A548FE66738A579CE9F2BCBE322B6E2B14FE11A571ACA89C80596AB76A645117FF4C9AB9057ED1CB45B9F4568D26A05A4A250282C112FC041D170F2E627182CB8A93E3C2F1171BA32606BD375EB624376BCC022F0B3C43AC89C1298B0DC4C691D8667F26C9FD37A671D56736C92B46913346FA0E2459CDC2F893A330683D6B5EFCDB162AB871A7767B945C50C0D57CE30124CFF31C4008AD7D12111F751810C981CB370B0D84BAB3D165409C0C499AB764487C69A6411288C3983A748DBA2C21977C911A18569B5A9691B95EA5C1BA8B3998294738570E029505306865B172B25D36996E734676253D72C07F0D285562E3893068BC9496783CCA8283B8BE719953E301C7DDB1638EC5B1F473B2B7A8CF24501AE167B46F2101B2C83E18FB4C63658A24535454413D69692BE57B4073B41F63491ACF03B2786CB2294208CCD689F6FA2E11908A8DFB201759B8F546236D63306102BD4562B4F4F02E32610542DC8914806AC0F14CAA67985CE458DD0746780B5AC6B2A825C6700D9AC119A5CB2E7B8D7D5B74B40B4242B28FE9F6B8846613616741E80460DB19848673BAFA6A2F40E0B9DF38C304219AD654C721BEC2D45FCF567AFC43F48C0EE3185A745399D3562034E732A82180C21E4C4A846A567BD8C81A3C737E76A689D122848AF9BF9178526CB11B39CAF4612C57935F8985ADBDBF2287F3127CBAC269ADB9B364C5A9FA4E69FD6BBB0182D4F9AB26" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "A524C3BEBA5320D30ADF207C6EB093DACCF28DD76C127CE45E3E521447F1CAB17934341E3175621AC6BFBF328C6704F4022F143F2F9FBAD942F5341D6EE792C9", + "F71347DB4300F8645F8BD4A98130A9C49CC838F198DDF1306ECA75EC59A813B731F2F554E4C11AE46B1E8A6B313EF8486B2A408B572DE7553B36B136DAF2209C0852273B596B5C2CED878226621650961D8CC804A142B7A2D78D027A7792F7850CEA24B8747176060C8063585F83B8BEC7BDCC1C1350D2CBEBBC716D404D7C1BA40EA1AB453B8EAC79070F45465D412F58D12A80D46B1DF99B84FA51CB7340BC3C94FE67276AD15F723966B06CBF1F8CCF8E039FFF21483D56CDA1B86AAD3B96B143664C8B4494A0B841F7C7E7317984316CF12530697A4B1B75250D032CC35C5412D77031854200E41C56490F0FD27A0C59019538B9C61C937374CF156611DFF4CA218A45B62814DC49A090A42E10BAA303C17E1C123D8C898C4D9385C6878B865CA3FFC61CBB75BEB1C918EA2A5C4679A4A161AECEB1242C39802DF0A9717255518430A3F828CA41576618CF0D456741E3574EE0C36F45088EA3A22FC59A5F0176B4578267FCB85AA97147925E4968220163020618611C3C3DFACCAB6F3007A1C1A6774047999B4160D3C614594B228222D2B20634C066AB30AC35A6895305503905C14796BEEF8A3DDD47A8A4194C2A601224099895322D43E86633BB7DB3DA030674CF04F960E3ECAF49A3A287136EF9473922B1CBE711257C76B09F303E63912F7CF0C5C0830197F25583C50DBB491A2CE01E25BB101C5576D9E72DF36B05E1900D8F385A7F754B27508215EC6ED8F52DA47660441A784E99589ED7AE4B197E5E726DF41599C9F6BEBE34022C0781EA42BC64980201CC743A227DF759265921B7AEF22CDF460EA04C37BC91A16402981407CF1C6A3EEF165BCB091CF13779F267BA582C431E33700FDCB14DA57A191700F18236C2C054A5690BB05BA83EBCCC01F5014160C3EE2BB08998978C0531D90C416C95A80D1BCB97054423572E1728C704175B6CDB91938BB42AA2C49E4237AEF174F6F61FCBFC50EFE362A6718FE823AE174853640B2662C5C467458E62A6A53B2B42178087F6506BCFB162EB26C30B0279BC5893D784B6A14747B7E132119C14871197045499BC66358F95A4A6FFD534996B1692277B792964F489319ACD20A3B1C472A9085CADFFEF500BBC", + "14571C5F463A7F408591C228D7DB86AF355B47CCBA54615322253828F99F68E6C142447316B79379443A69979F9F02504F536A1CC90BF7B7516E03C1ECCB706913AAE68C0355A8195FFC43EB304821736D533B96AE256C85C245EC103F94D82583D2B1ECCC544E3168FE100891929F0DDC88F99299119BA76ED14D504031229B76A93B8FB2A2610612C0FC5438CBC39EB7336E2B966DB3602BCE13947AA504B8688D038B262680A6006B4096F0BAA9695921558EEF43CC5CC979DF40B64B590C4AF1A9DC3546D18A88D40A470224CD8D3225BFB5942F804244555AC357BE65C8086172BE42C6227CD6055856AF7A3900ABC30C1FDB97C681694F7527D225AF1137C5B4A45B781A2C22BAACE7D099C6F92845D372EF5336CF7B9AC59A5AF5D830C2D8939FAC189C374CB0C95B9B18A632E352E46CA0095ACD26624B4E4649A4C1380456698E66276E768D9C07980E4A2A01C66C38881399826D9E5BCBFBC11A3FBC5E4B90875BCC174160A873184E0C15BF2808BF787A2C389C2E10D67500136172013E58E44E99606EB976CB81206A3C90344752CB1B049A25434EDA5120DD88CCE60C3FB8C340A3B7650D76945EC88B5118B58C17447FAC6DE6EA96D5F450205750D14C7A34A1A8BCB6B8F8729B684070D48C4FAB0239F845173FD1BCC5030694731CB8854EAEB482FD7BCBA6819D60374348B989220757B636348829672A576D42A92A35C85C0FB855ECA9BA6FD6B9FDB56F0F18930E890D71448DDBA90BC274031A4214547B654AA98B6E52BE9565C42990177D132727955AB740034F763EAB02B3FA7893CD336351EB378B79CBD8F69FDEAC077F433399D5C223479F671131D4B33093C347F9538475F1A93BF4C348466049982DDB867B72F9CAF4111D556AA5A16948EC01A7B5301A0BB04899809159801746288782D30BB28129AE3235F14464BCD11E92FCC27477242714166E987C87CB5071A0A1C2D73A9733C8DEB305BE40164C18A0BD66902C77497582C39005945B803E24EA03F67561AB67194476A06F2C6A18C24021408A955C88A36C104FC9170EE2A24A650456D98BC9C33CF71347DB4300F8645F8BD4A98130A9C49CC838F198DDF1306ECA75EC59A813B731F2F554E4C11AE46B1E8A6B313EF8486B2A408B572DE7553B36B136DAF2209C0852273B596B5C2CED878226621650961D8CC804A142B7A2D78D027A7792F7850CEA24B8747176060C8063585F83B8BEC7BDCC1C1350D2CBEBBC716D404D7C1BA40EA1AB453B8EAC79070F45465D412F58D12A80D46B1DF99B84FA51CB7340BC3C94FE67276AD15F723966B06CBF1F8CCF8E039FFF21483D56CDA1B86AAD3B96B143664C8B4494A0B841F7C7E7317984316CF12530697A4B1B75250D032CC35C5412D77031854200E41C56490F0FD27A0C59019538B9C61C937374CF156611DFF4CA218A45B62814DC49A090A42E10BAA303C17E1C123D8C898C4D9385C6878B865CA3FFC61CBB75BEB1C918EA2A5C4679A4A161AECEB1242C39802DF0A9717255518430A3F828CA41576618CF0D456741E3574EE0C36F45088EA3A22FC59A5F0176B4578267FCB85AA97147925E4968220163020618611C3C3DFACCAB6F3007A1C1A6774047999B4160D3C614594B228222D2B20634C066AB30AC35A6895305503905C14796BEEF8A3DDD47A8A4194C2A601224099895322D43E86633BB7DB3DA030674CF04F960E3ECAF49A3A287136EF9473922B1CBE711257C76B09F303E63912F7CF0C5C0830197F25583C50DBB491A2CE01E25BB101C5576D9E72DF36B05E1900D8F385A7F754B27508215EC6ED8F52DA47660441A784E99589ED7AE4B197E5E726DF41599C9F6BEBE34022C0781EA42BC64980201CC743A227DF759265921B7AEF22CDF460EA04C37BC91A16402981407CF1C6A3EEF165BCB091CF13779F267BA582C431E33700FDCB14DA57A191700F18236C2C054A5690BB05BA83EBCCC01F5014160C3EE2BB08998978C0531D90C416C95A80D1BCB97054423572E1728C704175B6CDB91938BB42AA2C49E4237AEF174F6F61FCBFC50EFE362A6718FE823AE174853640B2662C5C467458E62A6A53B2B42178087F6506BCFB162EB26C30B0279BC5893D784B6A14747B7E132119C14871197045499BC66358F95A4A6FFD534996B1692277B792964F489319ACD20A3B1C472A9085CADFFEF500BBCAD04832A8B888967CBD1D48E9F06C20DC2248C9F317A86EFBC57E8679D117C4B7934341E3175621AC6BFBF328C6704F4022F143F2F9FBAD942F5341D6EE792C9" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "34A702EF41FD50C390A4729EE6D7725E9B4B65B22BEF1962FF1E16622E5ACA45452BEE93E45A01BD819BFC9274A4E7059BA4E491DE2E3E233AE64942BAD25E8D", + "437827E1D842BDD37E772A52A4F0601303027F32A4FCA965F57967385657FF981034D39C73BA5EC59115E3C8CB3375164F5B1062394836C4448461C2512B8C96205B24B3BF906167A7D7630DFB9D67632368973CDDA76141399055E6912A8B8374EC9DE265B877F91930D12E2E827FE6CA4E665B0557E21A82069685930BAA442EDFD926572A0825F11A4DFB1B328A6A62D09FDACBB22451289A261416A87916B700546BA5D61A67DFE45CD6C9208C545E5B422A897463BD827E5E542CF28C30C008AEE3F8472A38066247297E1A4880CB4B98CA9C3CE8B019C049441831E2757CD2A08B44600B2C353F1F0B0A7270CF59B6C6AAD0351486018B74AC21444EA9C1451342A3215624AE72653F75C9738B7A27C7349C8AAB77F403742C8CFACC626E5640FA517C53C57D3DE900C18816DA364E7D8A396C35AA268AA998040FBB9B076E75208CE22D87FA16ADBA2EA47769DB1560FED51C34B1C182868A47BC04B1BA632274650AE443AF42A09012BD985C9EC5467227698F6EEA68B0ABA9ECCB979148C6D7E90121CB19042851F56B8F92078D48E6B17C82595F9292ADDB727FCCC194EB224156A18A73C65F86C3BF27C0BEA33BAB0B3493D61C75F5933A383AA6E3220F557D3BACAAC7011870591D03F4AC94E52704BBAA1B697025D619ED5A7D1B251B93B237023C6078D124CA532F1DA64DDA759B6036CDC4A606F3079E6469AB0AF701B986BA4B5B26A5B84E3BC0045A21C8B2B4560CB081745B00DAEB764AEC840176B0A25C397D05A77AE1C7ADC15D92D41FD03CBE9F97CD47B27A52F18C7579C2FB025341D696E0CB80C3C1798426BD22B0A0D616CF1E1809CC5C08E675AD76B623E7D894A306300C5CB0DCCC91093CAA93D49576306278A99808EBCE2F582C7E2AB02094481BA951463A8746AB441644B68388BD0C704043E1AF94E25EDD6B3D45A676FF02458895850C4938C531BEC7B62488B513CDD0878EE766503761955298FFB0152EC31DBA428F3DD51A89F914C103B5BAA983B7B93476C4A2F4F81FCA3372E1F8020E52AEE0F64624108AE73691172521D6C52F1C0101011186476FDA16B16D602FA89ADE65C1573353C7E43D488E165E821A7595DE64244452", + "8A236C24506179484DC9813388F68D9896C6BC0CCDB5F62B1A79BD2A79030869024CBBB7196BCF0C28C7FBE064B5B5845FC23D4D07CFC8B1CB2A27A08B85A9DF04CA0FDA409802B24B012EE0F2C15EFB3705F83FF134778464BE28E5A86677CFB1795B73420AABDC7742E200D309B88B3655CD7538CBA0654F61463415539416522F973E928560D05807A089C5B179BAFAA00D6EAB3D6F222531D1A7BCE49355F24C5ED58432A62ACFA9BA7F9075AE05B0EB3C3AC3F77BA89022F2E06540784E9F55037C0C800C792EC2D91D3A6A5E353A368B298315E90A60CA419BF4C37C1A052D78BEC79CAFCEB6A79459344E94A44FF36895A40D095BC375574D94B980D774401775444649CCE0CC63182A43E7A09A63007D95851A59C83D15B36172A47C19FA823ED7756DD5A56081A20D03988CC49BAC74C46DB66A4FD42A65C97BD139756404B347BC8745B5B1E13139F6A691A6BC632697ABB5F170BB684171DA20BDFC3EF6D1B985E069978213AAB4C10B1B7E518309614C727146298D6915EEF12C2466199BF93C6DAC81E6278A16334ED16B16B992603779A1175A8AE8640CE64B1C393911439961EAF150566C7C5C7395E841820CDBC7E0A7B4CE088A8FC2327A9CB6F9E6AA6EC63B952448342715A4E658B582196794AC35EB786BD49F46E3CD3DC4CCAD145B9E307A72F36FA8D7844E133710601FFEB5055DC271AB3B83717477D4C03E7DE6BECFF14143A50F6A1BBF3A99605FAB37A7E9216C7CCA4AA045FFF681080B43F75384C588C53BA038E3A6B7E0C275D150ABE836AF7523C26E9836604C38C0A80B37F24BE013A0E94C19E1B8833136CB99474067C49468029156FCAA20BC77D6E7383B1B96AEF111194613F4A23A76767DA9F5CC7AA59586574CAE9386B0D21403B213618310EB9063DB4A9DCEE335985A02183B7EC9C80CE2383B8EE04AE46525DB7624C1EA893767C309757123D27BB78049F230C6E0B0BF02B21FA4002605723981C52127BC6C17E9563B2549C668C8065025B0B0B933168A5AC684E04131767045D04495E9CB8B1C23B703D210EEA215A490372AD16E7E930F437827E1D842BDD37E772A52A4F0601303027F32A4FCA965F57967385657FF981034D39C73BA5EC59115E3C8CB3375164F5B1062394836C4448461C2512B8C96205B24B3BF906167A7D7630DFB9D67632368973CDDA76141399055E6912A8B8374EC9DE265B877F91930D12E2E827FE6CA4E665B0557E21A82069685930BAA442EDFD926572A0825F11A4DFB1B328A6A62D09FDACBB22451289A261416A87916B700546BA5D61A67DFE45CD6C9208C545E5B422A897463BD827E5E542CF28C30C008AEE3F8472A38066247297E1A4880CB4B98CA9C3CE8B019C049441831E2757CD2A08B44600B2C353F1F0B0A7270CF59B6C6AAD0351486018B74AC21444EA9C1451342A3215624AE72653F75C9738B7A27C7349C8AAB77F403742C8CFACC626E5640FA517C53C57D3DE900C18816DA364E7D8A396C35AA268AA998040FBB9B076E75208CE22D87FA16ADBA2EA47769DB1560FED51C34B1C182868A47BC04B1BA632274650AE443AF42A09012BD985C9EC5467227698F6EEA68B0ABA9ECCB979148C6D7E90121CB19042851F56B8F92078D48E6B17C82595F9292ADDB727FCCC194EB224156A18A73C65F86C3BF27C0BEA33BAB0B3493D61C75F5933A383AA6E3220F557D3BACAAC7011870591D03F4AC94E52704BBAA1B697025D619ED5A7D1B251B93B237023C6078D124CA532F1DA64DDA759B6036CDC4A606F3079E6469AB0AF701B986BA4B5B26A5B84E3BC0045A21C8B2B4560CB081745B00DAEB764AEC840176B0A25C397D05A77AE1C7ADC15D92D41FD03CBE9F97CD47B27A52F18C7579C2FB025341D696E0CB80C3C1798426BD22B0A0D616CF1E1809CC5C08E675AD76B623E7D894A306300C5CB0DCCC91093CAA93D49576306278A99808EBCE2F582C7E2AB02094481BA951463A8746AB441644B68388BD0C704043E1AF94E25EDD6B3D45A676FF02458895850C4938C531BEC7B62488B513CDD0878EE766503761955298FFB0152EC31DBA428F3DD51A89F914C103B5BAA983B7B93476C4A2F4F81FCA3372E1F8020E52AEE0F64624108AE73691172521D6C52F1C0101011186476FDA16B16D602FA89ADE65C1573353C7E43D488E165E821A7595DE642444524F4786816B53E4D686846ACDBB310255795A70F1FD4B94E2F5F3342A73FC0AC6452BEE93E45A01BD819BFC9274A4E7059BA4E491DE2E3E233AE64942BAD25E8D" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "9CFE35504744F6969872C77278049482A0D213C4FED821880221B44004F35A13E68535A032D34A9FA916F17828244ABD2C747E59CCDD20D29E682492E39FAC8A", + "202A8FD3FA108B9C0398C8522C016492219F5BE71ED003CC254917521A0CF42034A45BCE92044F32D048FDCA144D045BACD4649202A7899036D5E57DDAD53A43E675E61815E162029D9C39836B6DF771294F5623A7424D9B0A0C2CEC40AE7B7A94E92063BCA462047185B0836E85CEA6050ADC616610D49BED50CE87EB6FF803CBD0E8A2B4C967F0E20B221B1F919A4B5DB6A60123C601793FE6DA4334FC582A459AF7381582C4057D91BFC243B9BD88A1C1829FD9AC9E3681CF67A4B8AB69A948E030EDD48EE843C43DCB656F46587E4A715DB47D7DFC30BC353341752DA204AA0C44531A749E4E163CB6915F0FE0A8A6D05AE3FA2637D893BE3AC624865750F8A3D134B1999A81E7884AD555CA0D429AC9AA9BE69C990B5191382089F40661912B4C10F49885612C065A55401B97AD195892A3800FD435C31B0ADAB331EC3884AA77A4B8E17F6CD22885BA0C2F90768E983C67D8990118C9D69457DAC4057E0C48F2A81517D9549689196320BB10E87878596275F2112C4460F7848C83242F9D47CC7B937D12524C1FA681C230B1FBC0A54B231583648ED7B16EB7F297F4C901B87849CD3150226CBDCE44355FA218A79519FD7A881AA21981C6A956D47DE688A874769F8AB40810A25E4694073D7579180CAB1E02C95ED0A6F72A42C46CA668FC016B8979D3957525CB632DCC1D84E67E990C52917B5C6B911F58F7B4859B30BEB6859A72502E890327426D79ACC1B654C5EFFA98717B1715F9410489A9EB89A03009C5B70333DDD14C3CD37E3502CA60856EF2552583AACD369A25DB855EB30009379A84E5927308695A80BB200C821F904420920A40FF2B47DE4A0E3FBAA8CF3CCEB21C11F59359305A91E95B69F1E755E3807E2A52B9D6B0753D58A69806562F7285773832E46A21CD8287766BCFC9EB1AE5046966BC2D1C6955954CB92C6B82E9F8C3D5900DA0707779EC1C8A8403CF6C06B3896A48999601EA5DBBBA1051C78C5C25B4404A1DCE37098E5CAF1E6420D7AA87A312B52FD89D5059133FD957AD5508A2956973F69CF4E35DF6269956832C5F4A464325B28B92AB841741E24219E52C7E722CA7F35DC065DCB1D15C0FF7ECAA99ADC8BB06024F0C8015D5", + "E4D4C4EB85571775C84145104FA771F1A914FD8C5988852E5E3362A8AA33E05C1B404B72D13979DDDCB3075C6EB6A288F9548E70A5A74A851AC7664B24A36654D80F82B297B4667F7B006E82E4437C376F8744100540133C25978FD65B332B6559C02B03C7C088340528175723801B7556C9C68630766898F11479E4E997EFAC4F721780694A180C48B785C310E941449B9B7CB5628644771EBFD856B074A9A93BAB201377CC17C1EB618A8161B6C61192EC19181229880977C8C988B446100D57F55C29D8BAA8915130B71D168CAE51B609A92803E29702428300D1A3240D088F525796C466C5E10129483151721B0E09027059005A8758AA0C489BA7F07C080004FFD574CE1901B33522FF3616B378B4406ABFC0E6572BD650481B1A94086BA9EA47BFC20B0ACC5ABC77313C627E224CC96EE7302F194003A99095D5A74DECBB84AC2F76072598D7912176C78AA6222978C92BF182510A3D3BD44A95426F96C94637B6BCD6406FA267ADFFE3579800671B74CD5913186E1C1A910B53B8700E036B3B6C3B75ECD597D1E641FC14BA3D3C0B08A58F9DAC25CA99CCCDB73E7863235C2CC58DC40F053705CC695F034A98EB6A8FEB61B0B183882EFC0FB7378E3B7B21DD694283F98332599F90488BB658991E838FF4BA4735BCA2A8A39F51022D4FD10A886C9ACB262BACE58B9B9108BAE79F4BBB46D90333B1348F2E37082DF59E91A1A23ED55798A37499D0502D74956279BE2507467B676091A852AE366453FB4AC5C48993B8279F02CF86648190BA2703F73ABC142169840978BA24EC161682027EDE0734DF64685F10142298619ACB7FD53862E6122ECE6B83DB9749280C2C94D21A805C6799F391C5353409A40AF147CF37690871523185A67A8F91254198B99F0B03D63A451A9A8D04439BE019280FA0AAD264A9BA4007CC4C621743634B5884DC8252523301C605B03CB89FF6687ADDD2324C525443DC92AE99047997BE67817A529795941516E182AF11AC24724CA47966AD39A24B23CAC6901C55AF794D5A289A71478EDA587494C6801182405ED75C4E71434AB6B55EA276DB5A51202A8FD3FA108B9C0398C8522C016492219F5BE71ED003CC254917521A0CF42034A45BCE92044F32D048FDCA144D045BACD4649202A7899036D5E57DDAD53A43E675E61815E162029D9C39836B6DF771294F5623A7424D9B0A0C2CEC40AE7B7A94E92063BCA462047185B0836E85CEA6050ADC616610D49BED50CE87EB6FF803CBD0E8A2B4C967F0E20B221B1F919A4B5DB6A60123C601793FE6DA4334FC582A459AF7381582C4057D91BFC243B9BD88A1C1829FD9AC9E3681CF67A4B8AB69A948E030EDD48EE843C43DCB656F46587E4A715DB47D7DFC30BC353341752DA204AA0C44531A749E4E163CB6915F0FE0A8A6D05AE3FA2637D893BE3AC624865750F8A3D134B1999A81E7884AD555CA0D429AC9AA9BE69C990B5191382089F40661912B4C10F49885612C065A55401B97AD195892A3800FD435C31B0ADAB331EC3884AA77A4B8E17F6CD22885BA0C2F90768E983C67D8990118C9D69457DAC4057E0C48F2A81517D9549689196320BB10E87878596275F2112C4460F7848C83242F9D47CC7B937D12524C1FA681C230B1FBC0A54B231583648ED7B16EB7F297F4C901B87849CD3150226CBDCE44355FA218A79519FD7A881AA21981C6A956D47DE688A874769F8AB40810A25E4694073D7579180CAB1E02C95ED0A6F72A42C46CA668FC016B8979D3957525CB632DCC1D84E67E990C52917B5C6B911F58F7B4859B30BEB6859A72502E890327426D79ACC1B654C5EFFA98717B1715F9410489A9EB89A03009C5B70333DDD14C3CD37E3502CA60856EF2552583AACD369A25DB855EB30009379A84E5927308695A80BB200C821F904420920A40FF2B47DE4A0E3FBAA8CF3CCEB21C11F59359305A91E95B69F1E755E3807E2A52B9D6B0753D58A69806562F7285773832E46A21CD8287766BCFC9EB1AE5046966BC2D1C6955954CB92C6B82E9F8C3D5900DA0707779EC1C8A8403CF6C06B3896A48999601EA5DBBBA1051C78C5C25B4404A1DCE37098E5CAF1E6420D7AA87A312B52FD89D5059133FD957AD5508A2956973F69CF4E35DF6269956832C5F4A464325B28B92AB841741E24219E52C7E722CA7F35DC065DCB1D15C0FF7ECAA99ADC8BB06024F0C8015D56C868FA8B1C9DC7E083185439ADFC06EEB42635E3B5474FD7B04BF79CECC7F32E68535A032D34A9FA916F17828244ABD2C747E59CCDD20D29E682492E39FAC8A" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "DDE35BC33D452011114F5271799C21CA740F0FBFD34CD6637CE8836025A3CBFB8FB1127BEBA4B6667EDE28F67D08514443F4EAF93E8E46F05F4767F4AB9EEF39", + "88E9CECAC580BBD381649276FC4872B11281F178074450B7CCA2B3901946FE865B430067458082189050A8B07B5EB823F4E82FF8B7490D4A8D9B639E3464201D0C443066358577489E0919DAD250A3032B37898F36995118C70AF358051B7AA2A1F9C7FD57BC22F4595C4610EDD040E69229459C91DC7C39E240A5B11BBAE4DB46DEA84A1D9A2C3F9595634019BDA2B8DC814ED6C9404DF4BEA4C5C70BA4287F08A07EA25058B0186E74484E8741FDF50BFC3B5D37E34F9DCA9374B77E056454B1EBC7E92235037C6A9C5A44D293C722491CBE7C54185CB0FBF817232CC25ECA5739C386F314530E6911D3B9B604197989560F5B3720B8D1BA7F18031A735A45116FD5932EC947BDD8A8026CC781CA32C92B082A226B2D7664BACAB7A175CCB553016E30382A18810AAE139ABAB40E0F749BAAFB693BC4AA69BBAD00BB9C092B5A8FCC55657C6C01199971A61D5A13CACC76A31E3787BD909563D4036653A23441ABC5BB54EE7BB743153F6A875B75A33703B29EE7B874CF545D1E1418425975B4B0540EE65A78E8373B7B4CD4282C88CC3710F8288CF078BF654F8F18C7838C06A7B234CF8B74C5B930741C1CD1B7698C217D8CC91ABEC21C07B8C60A2826A7D9834BC881F179831DF9014C444DE1B37381D93B26DC90F8D1C0C0793C8F2A19E66953EEA336115558E8A51E4E1A851898B09440A686D37E0CE62A7D2450A747C8C880B3BBE3C4895AAD5AF1144D342BCE122AB45A235677482C26A69FCA137820CA5E1A29B5E2687714C9BB16662A5B47BB99965973478F22AD408191A6180AFA57C2AE97B7FBA081B0CA6337C46011B64AF187C573157897C586E1C22C8D8B54D621AE879674D31C294EE226D0F12432E18959B66250C405C6632384B09EDFE44B3E6B2DC053912DA55364F41F7D2926B2C38926F88032343EF5160828CA3307B2380A52AAC2E98F98555E7447002269C9CD8B1C9744AF37D43EBF433DCFA9C6C5705FB58AC07C252A1B02CE20B6280E3686503B13CE915D9BA8516DABAAF00757F172060443734A7C0CBA770D6C758A23148114C98F7208BE0242BB9664CB86E122E05F76BDC74E0747413A82CB261BA52FF80C9C2F1B498F0A2D88D19DC8", + "1FAB27CAF69708E0C9C2000B2941029FB3B86694355109CD32885E1C779482104814B2C7BFFB355B10B29CE5706DF81E55958A48DA1ED04B6495C05E0B62A4704145416C36D503C4387C8B9351CD3CA1368F7A77F6BB603145C38728AFF0F1037CB13DB038538DA40756A1350EE1C55E9C66027524C930BE50EC5CF0952AFFEC7A42A34972D79F1531600EE9A75E3552CCC7C78CD8178FAA37CE62838AD8535F430436B0BE5FE90476E2CDE41066D26A023156A8C43ACDDA5AB93D5AB979BBAF113B1A466BA29B5C1208054FF10147106149955305FEDB880B2270ACCB33E37173FBB389D31B6246C3BE87B8A0B00B8CBD174C27D24959887693B60ADB5032ED00331DF25EEC22CAD5F984282609B29A6C2BE1C90F06390B6333B679BE785AC12D498E83B86CF93C4F62E99DDA361A4623720D356E92C92F2CD8AFCCB2ACD67560838C7700288392E548723548CC17C2B6B5982A5BB2A222766A518BB14B42CDE58FFF83C760A065E8101AD00A577851227158C2F6A60ABCC220D93CC88A459F33D65A01C177F2A241C4FAB38BEB40A3C17C79191E40A7BAFCC336FFABA87DA892EBB35335F6B206269E4F915FCE9A9E57162A7E15AC92170928D78616DAC4266ACF74D15280DB8612683B8AA346C785878F887634C7AD291B6A01E8BC0C380030A0854DA356289A4192C353C26B4D9A441E6011A260614F6949361499A7087C99776B07CAD9AE339846C40357D817870642281E43263FE555CF35309BC0A932783BC79B5F3620706F14C1FC4074DA1B5BF9E22A40DC4840A9B97CC6BABA820FB99C5E9E97189E7BB52CDB523297287721AFD2208138A22AF87B4FA88930F8474A3E5814E4AA535A25A63F679AD0B362928807107708EAAA671443352468030D9426F86C5DDB4A8E909414D1B8AA25A37ED3133EB51848B167370E1B0FED75736CDB3AD1204EA1C202C149AB32D0A3DE4A53D92190C016B6FA009988963F23BC83CFF0BCB5091363D02AAC8BAC5CE945CCD6254765BC32114903913BDA8B02FDE45E87A22E07CCA2BD0691D02024B0F31AE8910CDA526D64EAB9194735E82B4588E9CECAC580BBD381649276FC4872B11281F178074450B7CCA2B3901946FE865B430067458082189050A8B07B5EB823F4E82FF8B7490D4A8D9B639E3464201D0C443066358577489E0919DAD250A3032B37898F36995118C70AF358051B7AA2A1F9C7FD57BC22F4595C4610EDD040E69229459C91DC7C39E240A5B11BBAE4DB46DEA84A1D9A2C3F9595634019BDA2B8DC814ED6C9404DF4BEA4C5C70BA4287F08A07EA25058B0186E74484E8741FDF50BFC3B5D37E34F9DCA9374B77E056454B1EBC7E92235037C6A9C5A44D293C722491CBE7C54185CB0FBF817232CC25ECA5739C386F314530E6911D3B9B604197989560F5B3720B8D1BA7F18031A735A45116FD5932EC947BDD8A8026CC781CA32C92B082A226B2D7664BACAB7A175CCB553016E30382A18810AAE139ABAB40E0F749BAAFB693BC4AA69BBAD00BB9C092B5A8FCC55657C6C01199971A61D5A13CACC76A31E3787BD909563D4036653A23441ABC5BB54EE7BB743153F6A875B75A33703B29EE7B874CF545D1E1418425975B4B0540EE65A78E8373B7B4CD4282C88CC3710F8288CF078BF654F8F18C7838C06A7B234CF8B74C5B930741C1CD1B7698C217D8CC91ABEC21C07B8C60A2826A7D9834BC881F179831DF9014C444DE1B37381D93B26DC90F8D1C0C0793C8F2A19E66953EEA336115558E8A51E4E1A851898B09440A686D37E0CE62A7D2450A747C8C880B3BBE3C4895AAD5AF1144D342BCE122AB45A235677482C26A69FCA137820CA5E1A29B5E2687714C9BB16662A5B47BB99965973478F22AD408191A6180AFA57C2AE97B7FBA081B0CA6337C46011B64AF187C573157897C586E1C22C8D8B54D621AE879674D31C294EE226D0F12432E18959B66250C405C6632384B09EDFE44B3E6B2DC053912DA55364F41F7D2926B2C38926F88032343EF5160828CA3307B2380A52AAC2E98F98555E7447002269C9CD8B1C9744AF37D43EBF433DCFA9C6C5705FB58AC07C252A1B02CE20B6280E3686503B13CE915D9BA8516DABAAF00757F172060443734A7C0CBA770D6C758A23148114C98F7208BE0242BB9664CB86E122E05F76BDC74E0747413A82CB261BA52FF80C9C2F1B498F0A2D88D19DC856B514206A952AFF5DC524E584EAA5B1A2E67C54D8ABDA7DE97DAF03139CFEB08FB1127BEBA4B6667EDE28F67D08514443F4EAF93E8E46F05F4767F4AB9EEF39" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "CA530DA877D570D5BDC677702D9858735E63A7ACF6079FD27EA695F3253787CAAEEDA4F351997FA6552ACC9D38C4C6936208A47CD832A86E475F42F67BC6FF8A", + "2C70AF1E561D8647C50111429F9218A0E699B048962E89ADB1F00DFEB6BEDFB8520AA02E98362DCD8184ED211A65321864B04373ACCC02F0B33ADC9491937BF341C8BF736DD31ABA15630E8C7CC95BF42C1BA3BB22A1B87D5CAA4BF476C5078FC4D579799349D32952FA6A65F11376EA4520F31815C10040632A370AB65926A81F14D72286983F2D15868EBB753DC278181B8027D5541D427A354960067C43CB404695316B7B694EC319AA77289E3B89556CB598A91789A566AF00E40DE7DB3D1E854000ED7D13F2ABFAF1AE59D935D912A7BAC8102F496427870BAFBB949A9A51A8370B267C93D92C80F5F3BE18A92A49722138129C98F26A0E3494A7AC3E45465756F1CB329964D78062A5209C6FFACFCB248E780381A43B9D71649AE44BB6264B46C0F68C957405CB34CF27323C11A243D50C9907D897FE07C9D0A77261C42F68B964B2CC8EBB3446D7D99711022718D758D687C44EA45B556CCC2D172F9F0A634CD3410CD3C09BA49A2339917C8022EC163640365B9CB1358E914659211136CA49E6F6B00D738F07EC9C7787A931408A141B9D1364200C1C736CE7C048E52644B2C3A6FA1B7F814C253074E77A3CC9829BCA7C4D3B6C1BF559180FC7699AA1C6D8D761BEB8BAB7B4846E91A038653E78E6026692CBADDC3CEB8B37BC5123C7C50553A944328268EB602EE39556B60BAC91C05DC250991B8A08370B4982C126E52AA6643511BF9309040A3166C03D8816A00D9B3673F830C8A62873A3572C0A3DE62079653178AF56A26F429E2A224FBAFB6142555B99809B82B9064BE5BF01F182F2B5A612283B1A86420C2B04A90AA031D85CFFC61E13D6727AFA9A18E5B1C5859186FA62C1684024E56C1F68B571ACA4270185AA6A83B6CA662BB156541B157A1190A5A9B3E0555FED0BBABA476B984B95529331FDB157B379A6716980B94556075119453964C57BAE0E33C2262989B2465C74C32337E30442C121A80634B6B12811762B5A59231E98592665305AD62746EC5985391E73EB56A1253C63B16AD05C2AE0BB0304A679786928BE0A7164A7AB9529C341A5497284C3BAF867D9A83DF9BEC7A5D38C721C1C2326116039BB6F21281B86ED75F9039D7FD14F60", + "FF135CC3D863C199424F066600E732B2744ADAA4C0D0B077CAFBA7572CBCD79B3EF68B6E636C155C142187C1AE094C81507BB4B94167A5218C03C82BB1A1C1BCDC1EE5E8768F5855186BB86BD2BA55408EC482499691C5A8B654DFB8C2C40241843B42D7110C853A06610A6155BA7CAF99CE11E8C3B4D2402D47C53C2AA01A8CCA2F6531BEB5896FB30EA2FCC63DA5A4FBDB793EA940CA4479776201997C9025F6BD691CB21E1B42F296700F27336F2C1E56A468F1A940C2D8A3E108CB6B863F2C0056100431424362CF5AC0D31984DA1C9BB04C5E6F5C36551857B2AB4F4DDC7F68046C45D93593A208B7342E4F00A1AB978018124A9C49BFA0E95F02706CF5B9CA09A11BEF417AAF549B3486642FDC1E022597244374F3DBBC745513C03A7D6173A0AE526563723BD24227A09C81E6513A2D8B4CD4D21B5299438FFB242D7364DEE7412EE259DE56AFEBBC8A1887BB2BF1679E5A148C54293A68B036732E6A59C77EDC8481F59C52B2932532B89F17C5B0A679C6BA984C039BB675717DB326A9704AF0C7A7E91B2F49DC33867A38AC583025108EAC06353FE7A7D9524CC36CCA718391438669610B6FD522230E44AA0D541B84CB1A261C687AEA637AD1BE22BBBB6789271CE925E0ACA48EB93322F5014F147BC9542F15B9C2156A37F92B99FB90118B5A1AE73A75F35626ABF2BDCF0C0A803549FFFA7A19004F8435A7E8B12D6F88ABAEE3CC41543B42890CC0CA9DEFF16957640EBDC84065BA52D92750C1A395DD8597D2A3A68C69140E472F7373497FA939F56C67A5A935BF5616B577B67DF4591A653B1BF543805C7F0643C18E59274978810F36740CF1815822B3855AB34A87C5D9DB8A0E92B713422E0A53BB41978C1ABCAD6053568299C7F66A9621679B8B6C95B7993C4AD57F43C27B0CB8482D6A2288B2C6A2D6BE328426CB344079C587F17A0F3868AD5F4347729CA8677C12427A4A31372F83818A73C53660E9399C0A69AF0432AF382DC83C5F1B181AFFD523BD05CBED92C785EB45DC1C8478391709987AFEFC2BA43B5CE96382F2951D71DA3F888A063AF02E7B453D753B552C70AF1E561D8647C50111429F9218A0E699B048962E89ADB1F00DFEB6BEDFB8520AA02E98362DCD8184ED211A65321864B04373ACCC02F0B33ADC9491937BF341C8BF736DD31ABA15630E8C7CC95BF42C1BA3BB22A1B87D5CAA4BF476C5078FC4D579799349D32952FA6A65F11376EA4520F31815C10040632A370AB65926A81F14D72286983F2D15868EBB753DC278181B8027D5541D427A354960067C43CB404695316B7B694EC319AA77289E3B89556CB598A91789A566AF00E40DE7DB3D1E854000ED7D13F2ABFAF1AE59D935D912A7BAC8102F496427870BAFBB949A9A51A8370B267C93D92C80F5F3BE18A92A49722138129C98F26A0E3494A7AC3E45465756F1CB329964D78062A5209C6FFACFCB248E780381A43B9D71649AE44BB6264B46C0F68C957405CB34CF27323C11A243D50C9907D897FE07C9D0A77261C42F68B964B2CC8EBB3446D7D99711022718D758D687C44EA45B556CCC2D172F9F0A634CD3410CD3C09BA49A2339917C8022EC163640365B9CB1358E914659211136CA49E6F6B00D738F07EC9C7787A931408A141B9D1364200C1C736CE7C048E52644B2C3A6FA1B7F814C253074E77A3CC9829BCA7C4D3B6C1BF559180FC7699AA1C6D8D761BEB8BAB7B4846E91A038653E78E6026692CBADDC3CEB8B37BC5123C7C50553A944328268EB602EE39556B60BAC91C05DC250991B8A08370B4982C126E52AA6643511BF9309040A3166C03D8816A00D9B3673F830C8A62873A3572C0A3DE62079653178AF56A26F429E2A224FBAFB6142555B99809B82B9064BE5BF01F182F2B5A612283B1A86420C2B04A90AA031D85CFFC61E13D6727AFA9A18E5B1C5859186FA62C1684024E56C1F68B571ACA4270185AA6A83B6CA662BB156541B157A1190A5A9B3E0555FED0BBABA476B984B95529331FDB157B379A6716980B94556075119453964C57BAE0E33C2262989B2465C74C32337E30442C121A80634B6B12811762B5A59231E98592665305AD62746EC5985391E73EB56A1253C63B16AD05C2AE0BB0304A679786928BE0A7164A7AB9529C341A5497284C3BAF867D9A83DF9BEC7A5D38C721C1C2326116039BB6F21281B86ED75F9039D7FD14F60CB3C2AADA4973514F817346DC7415C0DFE62978860046CDA86E5E9828A2CEA84AEEDA4F351997FA6552ACC9D38C4C6936208A47CD832A86E475F42F67BC6FF8A" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "57E4DC20779D50918E6AFB7C83C46E75468A722BD30AB0D485A4C53DC102AE05448ECF05372ACB6596886A1BBB2416BDA3BA5557CD6BA226EA134B4302E71AF8", + "A150BF17218357CCB38D267020D9113D22B61FD02EEA861642F89B1273C979D1C1F6E53BD3D87DEA8804C77CC06AC40144BA4FD00791C38036F63496AED2713809798F44C365991A36E81DB5E6759FA440B2C78BBF04C4AED9A46AF369B493627824A73C477539459494C12B5B378C659B5835547CEF9B20B7E07429F7CB923B2FBBA778936200A56B9A4E483B847C413A797941716B51655045E331312415DFC60C3B4713A79B062868049AB2B1EB120B3D4392D4E915E28A6085BBC656EA2023039D5A651EA2CC275267005561411A76B9B7752AC9814B34076FB96AB9F238C951D9400C544CB845863851473FF29F13D542EA8B0533F552AB457CE9C43C9C202C4FE0A09194B321306CA96C599E110E3057C7580718D9E4C0E694C3267C628BA69F0AA55F3B8BAC007584832C3C611A33EEEA1D309B260A6989C0FC202F1490E9AA4397D960E9D1C934417639025161ACC25E3AA7857536F2B6B3930CA1F48A7482E90F074B226A990038A65657C53D96640427D0C87ED8CF0A1A9D06F740A8942E31AA5E0D0B25F79C7D3C6296AC1C79C1CC197BF1A528C179B2C611C114C6C2E07C0030C55B5895DC8C36DCD625BCE0A00E5CA75C530454D80D42AC2FFAB7288A6175A161CA841160B5A5970C34017E42792AF59DBFA5912BEA3FE3BC0D0D5392733B08E030805EA61894637F3F988F9D8A80BB0100ED357C773481F1C981BF5A47C6F76916DB22BDBAC5A0BBB5C8D92AD51359992B99CDC071EB02B11ED6A1B8AC11CC4A34EB5811D652608B388D5CA7651718966390AEC6B38DF5F3BB670018CF5209C819BA63D400480CBE99DC07299985E22994D220589C3C6105779275A699D9A4C6F79CB8DAC45AC5AC615D7B48B1B0327442AA105C8B8CA443A9A78F69315FE8F55BCEF15F96196A531CA89D73B61DA52A6351A334281C7B8695790287B540C4494A263AA381CEE47632A00B11488DE0E97AB2863522556F382A5EE7EB372589C20CC118DCF2C938CBA9944B5CF18C818C8B7A8E98600D6C26A33369D06A1D8697BDCFCA3313E86732756F4DFC9B131AA356A018B41C25DC84A0D0F6F65975B3106AF8BDE7C173B18335125EB6DB5290BB24B7F432691A567034", + "067029C7A8A0A2299A32C46A804239DB5146E6AA9054E30F36E585B3FB6BA5525810C3351ED44FC2D920B7A7C48E2068512034B159316C41CD6D01B48738BC1B731B699B18F1860F9374C5E26280F727836858B4AA6451C91A066E3044E17C7569A971BFE474C24BA4DA2AC4776B0DADA68A05859705BA085736BCB4A74178D3B546C16FF5406E37009A79745DEEC59E48A935FB125216D27888082F99BA1A82B2B51B9A0982DA3747E549F7E05129A68C660AC2F3D3BEADE794A0F15F4302C3ED95B2951069EF7981F9D0A1647534CB5B1B37EB3EF0EA209FDA4E0C5BA97A380856980DC31558B5D36E40D922B1639CCFC01E0D6B2C873081793649383338EF629C33CC1EBA087270C7BDCB8181862170D8187319674C6A6662E897976990240E6369AB956D48F941A35B536FD10A0C72C63C63C2705A9443C57E7EC697394A86D1931ABC5499D19BA4D6A96B83C3A6DFAB4EF7131AF1FC7F764A6060C8318CEC2455325B65CA6F726849E4630C31E246DBAC7043F35A2CA66F32B7303ED4C821BB8F83A777CDE75D8BE9C30A2CBF44FC2F17E5B109B45E2706B14FA60CDFF71A2EDCB0767A68799299DED1943BBC5C6DD5948AD2C911E817161A4C6EF6545A8407D14CAA017AC3FE98954A185FA110AAD05B9E1BF2001BF45F40DC2A3420247C039B39D64A75FB632D30798AC875F296AA9832189EF37EBE0090408AB34A525070F4AB4953B5B91564B17B7114292A8C3A0420A360DBD537131488EAF5A7F1DB7C63A4B114B8BC97206FAF817570B4315FCB0F79621E7FCBCC37A06EB785A8A7B03614801654D86D244C1CE3338DF09BC837764C8F69C188FB888FD26834120032B01AD0AA060DF14B99F57E394978367B44E8DCB53BEC21F4E9B80F696A3C1372299056BD0CBCCF744B3E12BC0914935F06597D3325BF7945CFAB312CA6733C51397B41219E27636EA2BE98A1B1BFA257DD1A1BF2443308458AF0FA3717253B7781CB46F8813FA51FB73B2FFAB9745AE455D8A770A0A3628260CBA5634C363023FED9A7D00B255BF5856AE465D82308DC514244832C7681B19D4557ABEC86A150BF17218357CCB38D267020D9113D22B61FD02EEA861642F89B1273C979D1C1F6E53BD3D87DEA8804C77CC06AC40144BA4FD00791C38036F63496AED2713809798F44C365991A36E81DB5E6759FA440B2C78BBF04C4AED9A46AF369B493627824A73C477539459494C12B5B378C659B5835547CEF9B20B7E07429F7CB923B2FBBA778936200A56B9A4E483B847C413A797941716B51655045E331312415DFC60C3B4713A79B062868049AB2B1EB120B3D4392D4E915E28A6085BBC656EA2023039D5A651EA2CC275267005561411A76B9B7752AC9814B34076FB96AB9F238C951D9400C544CB845863851473FF29F13D542EA8B0533F552AB457CE9C43C9C202C4FE0A09194B321306CA96C599E110E3057C7580718D9E4C0E694C3267C628BA69F0AA55F3B8BAC007584832C3C611A33EEEA1D309B260A6989C0FC202F1490E9AA4397D960E9D1C934417639025161ACC25E3AA7857536F2B6B3930CA1F48A7482E90F074B226A990038A65657C53D96640427D0C87ED8CF0A1A9D06F740A8942E31AA5E0D0B25F79C7D3C6296AC1C79C1CC197BF1A528C179B2C611C114C6C2E07C0030C55B5895DC8C36DCD625BCE0A00E5CA75C530454D80D42AC2FFAB7288A6175A161CA841160B5A5970C34017E42792AF59DBFA5912BEA3FE3BC0D0D5392733B08E030805EA61894637F3F988F9D8A80BB0100ED357C773481F1C981BF5A47C6F76916DB22BDBAC5A0BBB5C8D92AD51359992B99CDC071EB02B11ED6A1B8AC11CC4A34EB5811D652608B388D5CA7651718966390AEC6B38DF5F3BB670018CF5209C819BA63D400480CBE99DC07299985E22994D220589C3C6105779275A699D9A4C6F79CB8DAC45AC5AC615D7B48B1B0327442AA105C8B8CA443A9A78F69315FE8F55BCEF15F96196A531CA89D73B61DA52A6351A334281C7B8695790287B540C4494A263AA381CEE47632A00B11488DE0E97AB2863522556F382A5EE7EB372589C20CC118DCF2C938CBA9944B5CF18C818C8B7A8E98600D6C26A33369D06A1D8697BDCFCA3313E86732756F4DFC9B131AA356A018B41C25DC84A0D0F6F65975B3106AF8BDE7C173B18335125EB6DB5290BB24B7F432691A5670342D7F52EDAC950F94735D27BBBD738553390ED03E53DDCD2F2C4BEB0F6300AB39448ECF05372ACB6596886A1BBB2416BDA3BA5557CD6BA226EA134B4302E71AF8" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "A0B7E77AF241CA39AD959BB5955BF7DC8BD03CD17DE97E735EC1D59D834790B2F6E414BA470D63920B930E3DCAC99BCB238658BE8328D8B4722E8855D3D6CDBC", + "462BAA997A8C7DA79A6C96A216E73089A3CDD1F38B49E4A5D67BABD64C867378ACE9BA902D511DAE2604524C54FF3775B5A9BE870488672C60C8E8973FA15F13FC6412E830C96939E6490FB0656B2A352C56561D608264A996672BEA5CCFA7482460C4F8A0972A46A10661C8F03188AA9A3A4F763A402B393BA18EE2934C0B0A5127110C69E67C3E121420A523547B45EC3291E7441A428895C7739B895268DEB15E6CA31D8E14670343AC191070E5958308D1B4C6E4557497C7417B4487A9BEBB628E682A2037BB4A8777B32E509DEB44940A7007B3E5ACFC28AE0247B66B13C3B76931F1698C6F6C3F7A97C813C6B30B7698484486896289F9B31DC929398E376509CAAF11F950CA31C6BAF94BBCD43DC3F12181320057F7B54DE0711A7581FE860FCBA00E2A5B537005153D9C719F549A3C3294C90A52107883C45585F1745FDE397C8188C60A747839BAA84640091E6747EB08893956A42E621604D57C5C623893E729B3E340925710DD24C78DF87E4E73691365644C2C7831136232520C2BA75E425493B02A3403B041F14937C85034EA5837BC989D174BB577D090475936FFFB0F7528C20C236785BBBD6658AD599B960744998827B45BD5C2C638558D587721365226F24381089065C19166266864631FFA478F9C6C992130736DC808073456DA231A45C3557D3326A0526AE680553CE3B329347507938E7E764FC006B1CECA9B09F37DA7866ECE5702173B652AB4BF06F84A431AC0DF5AB77E8C4846941B8AB064A8738AF2455ACFF481E370C72C255BFA357C64E92ED7F30C9160B635AB2C3E103CB0B72772932F47A216DA638F53E44250A76C52A70AF271531C845A7E696DE1D04BA9EA448D3A396E7383C92811F4564DDCD084E3C67AACE09C39A73484FA0D6C6A03771C053E45ABCED48116188540270B0D32329CB3C0DC16047F63B30B87BA67E3B5BC5B7EEA558939E25C13213DABDB3BDE1637498AB6B04C9666434FD5822D630528C470C462F92806A86F81F9CE1D7760C66B8BB9346A16037891EB3E40173FE47076F9728D83546E11E753D8F5C5A90A7172A58EEE79A6471695141F80A35AAC292AD3B45C42EAF9153948F4951EA33F7BF5753CBFBCB1", + "E7C61840E8B9D26A86B6A2800DE221C4FA72E38C4BC0EA85EF4143138A600FC41244C41C1AB79A68582642E62D1E9415968B76B4A68D31D3C5832434C98B68733A0831F6A833B45E128B48CD533B5A2C96A8A9832F049D9407594A603FAC33827C7A62881450F4F9425BA231FCF9212ED02B9334A409A8CDA7A931DE7488B967696270068CE76C9BBC0C387214D534A60EB0814234B7877B8FA1A7859DF483C68C75F83352C5DA273F429FDB3295D7E3B210F4427090A525000C096A3A6C979065314AB9C29542D488DCE6CB6172B73500C0ED9CC3F1F8177CC56BED3CCE05E61AC0F2895365245F625F97CC205AF1911A872EA6B47195E40DDE9415D2B319626880354322783592ECD9C03799C343117F475407D0F21EFA4A8CC99C9F9125C05A235C52154293C9206FBC8CA2FB72DD4838E6094FF6895858C4A1A6A198EF9A13491B5753969408894276818506265339058340E64FE75685D99B76085751484B46EE895688278F5662AC983BBBDD0575742B7B5759BC4FEC45F9979C475B72DC145F38D336F9C265F7C92E80581B5BA9020EA49F39C0B04EBA19A8C67FA37B88F3E8AA60A8C01050BEA362980484666538577C92068A0661FD17CFA69B25CE304659A4CC784A6599FA6B63ECB16F5767AF0C79BD679ACE64258C568C03980143499B848A8B7ABC2564800F6DE278FA52053FB4B5B3152C6B0B783A1ABB7873687F3618452A60F927083CFC962B7478413793C92B2837E92E0F4042964A3FAFD2AD9D24B0BF427473504A02AC61B1C55C57B39D83DBB74DBC0782D17E78B0034EC61A9E084A1C3322A6B5C603A21FD8D77BB5308684C8C62781C7155965FB61C50DF26409FCC0DD7948C7193A78468F14729B3C7393736880E6C2B75193991C6A04F76AB63D625D213B9FF4C10117D1A1DEE0240C711DF6F88A759C0F7F183AB46C87D75246B3DB939B74CC31C32E0368CD2053194040A0E44960C1E9B6EB526585B0BE28305196AA3D65649065E7AF0EDCCB029AABE30603C67A052E333C95C305073152190A93DEEB0DB020B817E446773B699DCC1A50F68EF2B42708E4C5462BAA997A8C7DA79A6C96A216E73089A3CDD1F38B49E4A5D67BABD64C867378ACE9BA902D511DAE2604524C54FF3775B5A9BE870488672C60C8E8973FA15F13FC6412E830C96939E6490FB0656B2A352C56561D608264A996672BEA5CCFA7482460C4F8A0972A46A10661C8F03188AA9A3A4F763A402B393BA18EE2934C0B0A5127110C69E67C3E121420A523547B45EC3291E7441A428895C7739B895268DEB15E6CA31D8E14670343AC191070E5958308D1B4C6E4557497C7417B4487A9BEBB628E682A2037BB4A8777B32E509DEB44940A7007B3E5ACFC28AE0247B66B13C3B76931F1698C6F6C3F7A97C813C6B30B7698484486896289F9B31DC929398E376509CAAF11F950CA31C6BAF94BBCD43DC3F12181320057F7B54DE0711A7581FE860FCBA00E2A5B537005153D9C719F549A3C3294C90A52107883C45585F1745FDE397C8188C60A747839BAA84640091E6747EB08893956A42E621604D57C5C623893E729B3E340925710DD24C78DF87E4E73691365644C2C7831136232520C2BA75E425493B02A3403B041F14937C85034EA5837BC989D174BB577D090475936FFFB0F7528C20C236785BBBD6658AD599B960744998827B45BD5C2C638558D587721365226F24381089065C19166266864631FFA478F9C6C992130736DC808073456DA231A45C3557D3326A0526AE680553CE3B329347507938E7E764FC006B1CECA9B09F37DA7866ECE5702173B652AB4BF06F84A431AC0DF5AB77E8C4846941B8AB064A8738AF2455ACFF481E370C72C255BFA357C64E92ED7F30C9160B635AB2C3E103CB0B72772932F47A216DA638F53E44250A76C52A70AF271531C845A7E696DE1D04BA9EA448D3A396E7383C92811F4564DDCD084E3C67AACE09C39A73484FA0D6C6A03771C053E45ABCED48116188540270B0D32329CB3C0DC16047F63B30B87BA67E3B5BC5B7EEA558939E25C13213DABDB3BDE1637498AB6B04C9666434FD5822D630528C470C462F92806A86F81F9CE1D7760C66B8BB9346A16037891EB3E40173FE47076F9728D83546E11E753D8F5C5A90A7172A58EEE79A6471695141F80A35AAC292AD3B45C42EAF9153948F4951EA33F7BF5753CBFBCB1CDC8342E2CDDA632B9283B864BE383A95B2860DD096F2BFD4EBB0E423614C76CF6E414BA470D63920B930E3DCAC99BCB238658BE8328D8B4722E8855D3D6CDBC" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "B280280A639A63E76C9DFE81FDF471A0919E4EB062C7C44CDFFB28B78494B478AE78239F751AF50099C9EDE00B3658C30AF77341B59A93D61F9D25599AFCB059", + "A243B0EE496A23743D2D0753A47B6A312B200CAA9528ECBCDF23CFF19906D689B088E2400FB79DDED6CD8F4912F5D5B4CE1194A8FA3032D3A53CA15F5F1060D36276D26920BC90CFD117A8747A2996115D5AB54739F85F632787238884C011400CFA9CB2557E37D04B813B5F83C8CDE487A89D39AEE713771F5067FE0A60F6E160C0F8A1F85C9B40A6942A231AFCC6C0161A6931416C80EB9C09792A03E38EAE1327CF665914A026224258361C14C7F468186B528222A508199A4451C5ABD02162E106F4664F56F5215FC086A881938432636DE2BAEEA4151D2C84880101EB562213892CF7F161B45C63FE86B5086BC8EFD26FB322C8DBF237D7C1BF9024471F414B51404605D1532EA563BBA2A04C43659034B2F55323C3F7524B66102AD04AD836B1C24739ED724DDAD021F36954B2A94412E192D3A97B9BF52F62D91371179AE0A539A61332DDE254A3D40FF4724F1AC486B45667ADEA5D6F054E4A13840E1977C3168B9099031C6B908468048929B317836B0F9A9A163831D75C1825209731011BE3159F480BB8D97480110181AD33CDF1E7AAE952231C30386EA16166EBCF56A207633220DBC9B80FEB05C2978C8DCB9683A31FFDCC1F272AC4AA387E58CCCBDAFB3536A840BBA60AE7901835E8636FA697A3B48D30E3B16724C5DC70C4E939AB86852510B65E4B8634E587AB3C80BFEA71CDA5F3296E555D75B9AFDDC91B3BA1B445FCB4F14B28374038E20A2F3ECB0E85604ECD4188CB23AF26CA89A4810FAEA9CED8822C520BC6C6219BBF92B7996384846C8EE9D9806E37BA88165ED17216C836B25F589FBAC77FA9D516A46A4981249919299C69CCA1AC91BEB700A26F408CF7B705770BBC54FC3A44657ABF0211786B7D0AB9600B36452E24AA3332549E1BB2989236B9CAB7B8E4C8B4660E68B45FC438483612701762CCA6C61F70A8B8A222497489CC28B64BB39726FCF30A7AF103302CC6EADC17F948AEE8FAC4539C4F317435B9205D2AD4363647012C3B4B42D66995B437FEFCA0B1D8952CA7C04C2908F9C15499C19ED23862F94101C75167CBC79EA0E4559BA10902E479BE89D92ADDB45A5B1A369BEF80450A4575CAAD582004AECB03A9EC5FCEDCD7B5", + "C334B145539175F8562A572127410E56D915CBA84C78F67050D5A30AC45AAB89BF570B680FDA9CC43A5396E39CE3655912FC93D3F24B2B42BF9573B249407FFC424F25C49E811285F36013392900AA0945BA8B4BA9D989A635967DCA3446A81906338C8A925CF0125301499243B343D9767979943A373C7D56996E7D050490EA060764A15FEA2659C4B5D57A25BC8C401DF287DB07875E9489D804402BB0C59436A5390063783904F3E3C73422BE6E45A561E39CBB0729A125BF8B197060043AA9D4ACD26A3663DC38A17029EF5C839BA7961272388781A8D6917CCBE79ABF7567C5590FCF7B25745A0A18445700E1644464230EF4A6CAEC6595AA80BF8C3298EAAE62117E627B3CE2614045D26FEC43A6407B7DD9F9C0FBE839A62B45E62CC966ACAE5C601711D4664C7421E50950F57230CE3564281AA7D4452FD1BC3D1D8B070A240F23E0AA61E7903E3B23863AC58D4C1BA8BC5383434611D879355B3A5B645D8D86A63E745F356CA620B5735C5591F6A54C64C166352170BF8762DF3A340C337E9C6288C3A92120DA02D6EA5E3F6055F0B10D3FC35FE0E65635282A11D9B276B17F0D34207F6526220C77F7912EB71073E32156D24C5C32162591E701C1B3842616AE8A2576583520D272666ADAB5C0D51D648A1F2BE73A42C0B2A0E118BA65AC02CAAEAF65291CB4143920047EC243243156DC95AD5E22952E1C9EB3223528C33B74047F1DFB8D06A054BFC662B70592F08B2AD4B994C7F4785BD97FF85A907A220D4AF03ACCE0AE5A6C75011474552A5410B31B166C760D5197A4C77C514500095B0918601971B60EA92842D5DC2A80424AA5BB39E86581E262C959BACC6AB9295CF32752B322F52A46A8780B31662ABD6256A83B471F2C13B62816DB1382AB23863B32811B71B303B02305F32F9875C2ACABBCD111899999BFB535248DB417986C843FD39372926166822482BA8CEC1B46E9BB60A96468FC52A55C171F451B5D304CA3650A3910200BEEC9188D477C50D586BFA67203E03776DA5F5BE8C42104C6D7219C5326AB04C5685C68A5E1DB7112326B6B0015DB7417500B20A243B0EE496A23743D2D0753A47B6A312B200CAA9528ECBCDF23CFF19906D689B088E2400FB79DDED6CD8F4912F5D5B4CE1194A8FA3032D3A53CA15F5F1060D36276D26920BC90CFD117A8747A2996115D5AB54739F85F632787238884C011400CFA9CB2557E37D04B813B5F83C8CDE487A89D39AEE713771F5067FE0A60F6E160C0F8A1F85C9B40A6942A231AFCC6C0161A6931416C80EB9C09792A03E38EAE1327CF665914A026224258361C14C7F468186B528222A508199A4451C5ABD02162E106F4664F56F5215FC086A881938432636DE2BAEEA4151D2C84880101EB562213892CF7F161B45C63FE86B5086BC8EFD26FB322C8DBF237D7C1BF9024471F414B51404605D1532EA563BBA2A04C43659034B2F55323C3F7524B66102AD04AD836B1C24739ED724DDAD021F36954B2A94412E192D3A97B9BF52F62D91371179AE0A539A61332DDE254A3D40FF4724F1AC486B45667ADEA5D6F054E4A13840E1977C3168B9099031C6B908468048929B317836B0F9A9A163831D75C1825209731011BE3159F480BB8D97480110181AD33CDF1E7AAE952231C30386EA16166EBCF56A207633220DBC9B80FEB05C2978C8DCB9683A31FFDCC1F272AC4AA387E58CCCBDAFB3536A840BBA60AE7901835E8636FA697A3B48D30E3B16724C5DC70C4E939AB86852510B65E4B8634E587AB3C80BFEA71CDA5F3296E555D75B9AFDDC91B3BA1B445FCB4F14B28374038E20A2F3ECB0E85604ECD4188CB23AF26CA89A4810FAEA9CED8822C520BC6C6219BBF92B7996384846C8EE9D9806E37BA88165ED17216C836B25F589FBAC77FA9D516A46A4981249919299C69CCA1AC91BEB700A26F408CF7B705770BBC54FC3A44657ABF0211786B7D0AB9600B36452E24AA3332549E1BB2989236B9CAB7B8E4C8B4660E68B45FC438483612701762CCA6C61F70A8B8A222497489CC28B64BB39726FCF30A7AF103302CC6EADC17F948AEE8FAC4539C4F317435B9205D2AD4363647012C3B4B42D66995B437FEFCA0B1D8952CA7C04C2908F9C15499C19ED23862F94101C75167CBC79EA0E4559BA10902E479BE89D92ADDB45A5B1A369BEF80450A4575CAAD582004AECB03A9EC5FCEDCD7B5F2246D919B2C125DF5CE3DC41DBC52DE12BB18CF23B1A3C6C0BEB104EF4A62F5AE78239F751AF50099C9EDE00B3658C30AF77341B59A93D61F9D25599AFCB059" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "3717730B2F35291F2F8DF2B9CF628351397FDE6CED8DE18E4570464057338B213FE925B8F7C0F435A07B3B913170D00C989B39ECEE157C5DCF6BCB246AC99A6B", + "1449378BD2C64BD10D8BBC3834A4CF2B640F3D9154708B7B156AAC85D3189FE76D10F35CE00C329A487D9A9868562606796427D158238B0B91BE01B98E4C812EB1602C4A42D6180454797FC75728D4E0017CBC830E05604FF9536AD64A46DCB203E6526B009D51604567EB6E3E735260A6B485650924C0741C4652D8592296892DF3F23AF782A1D57ACFC1D429B430C5EEA369D6E314D3CBAEFA9A4C667C39607B278F6953FA84C18008588EB56CB46B61B9B15EEE6B7ABC91308F037EBF3798D7F72724EA3E6CD273A0269A17296EC74AB078A618173A562BC175FC8A5A522ACA8DCAA87CB36EC0B46E3776B9203696604046D4168A02E73A351A6C0DB127E6359D93712FAB89B855F74FDCF87581760854045FAA3BC9FB440D007B935250715B527F7FA47FA3125EA1860907259E43802F1CB4CBC41025C119835BF796F9F96779ABB5D0DB6308685CD01A6A60EB0887A52EECC8B2D10ABEA5C470928BB33F067F29A2A21E52659171243CB215A6C6C96171236CD31F80D930C1EA8C2AE908579333B55AC450FC4896C79394A7CF8C9894D9CC029D687403E545D7E68F3F22A35D6378CA29C3A11456672626C1C9BA4FD86FB77A41BEFB3D45FB6C4172B7D79B51511415C0B012C1338854CB5CB640197F048B7763502FF64090D589180498D497347A7494FC8B864557A7A5BB8B998448C155B1022257BAA0B56FA9974E099739ECC9CA75A587399E6B3B3440048357DB1E840988B2B6CAA67874710B44AECA293BF0935A320C63FC10BC04B186787CA376281935CDD7AA379F5717CE59A3C13C737553B31AF7BFE903CAF2529FB696B08D9A755E3438D9924E77F324B4CC8D87DC63521C54EED49F8E1708E0D249F9373E82C3625FFA95C420B737B665DF54824286868C797BBC056FDEA7286FFB4451E9B434D23316D758F6B92133807B7F1637358C2346377778C7C88E72B792CC28DF32C7AC3407DEAB6B86B72DA428243F457113965552B7A59B6A02F2FC5A96AC99FF60A6B569223601CA73041F79F35E127785FF50001F6650B8A44D62DC35D1B938443A80515B7E9B17CD75712E59A34A1634AA80C508F54CEC691377708DC99B9FFC53174487BF329A8E852472", + "3778B2A1B606002D96813A54B93133CDB737A0FC467297332858C1E704BE8B54509C42095220184329AC5BB5CA634C72D071A4B1639E6CBA52B64CCB7359713C59A2ADB346E7954609C98B4F064D637B5E3F21656E2160A9CA955AE735CE6B22DDF127E95326FC208037209E75DAB16F3CA8D5540D924112AAF7B3791427F3621F552A496712648F0010BA238804FB8001F3AE21EA1E2F656E05762C1B18A63117728933778C738863E65915808A11B8397CAB4ED34C7F20C2B8F9C152BBA266F194918298398459BA4BE8298F61CC38C48FE7F513DE45526BEA39F7A8CE8E6A796BA97715F08B304CCD0D1A148CB4171E890424B3B3F8D905F2A69FC12550600C5A84559789D9C6B627843B873715C2B1DC41A3104A33341A2A94A4BB17285E2C8935D7D02E9EC0910FB67429DC76A7A527A77BC95B98934A6842852B0FF28A41A2E46A64A885C16255523C27AC185DFE440FCAD16867778E1A29CADA9A6A5FAACB565A2AA92B44761323EA7C37E94084D65B0478468BD7F5773133120A4659B51212D958C3E2E53BC2322CC948860CAA507773BC172572695C392770419FE02CD0C50F5AA92296214ED6BA10BEEB7268B35294BC98BD509E38240BB70A299F25B16DB16E598887C1DB434238BB277CC20F6256A5D0B14C64AFA0CCC098A9C46BFB3786C42B64C50D62F51AA6DB39DB95402A9481BE2373795761ACF6360297CDA63AC2AA5380A8B0616A1426AD967CCE2059DD27AFFF6C8DF8D7BDAA04295402A559038095D445B0D720177158D831C57DA100A7E9743F29129C53983456944A83B57D21446AE308272BB15387864D0C5F75A97BA82C1A81FAB2A3D54FE5A37F3B9794A8F69A15FA24D2E3758BF633F9DB798BC11155440D97594E04A401ADCBB7A41020A954C1F9E7419C00B143782F2A24A823EC16D5E857348C1A5AD05E25132C7B39B96B8608E3F41D9F32222E54958A16063C61AF96DA948B10319A25954FC626B54BA437CA153511AB4D2619DAC8317DE80452A23336513C2403523DA5719BC44E0652A03E7358AD8A6E9AB03CBE90531A0C9073F539C781892567971449378BD2C64BD10D8BBC3834A4CF2B640F3D9154708B7B156AAC85D3189FE76D10F35CE00C329A487D9A9868562606796427D158238B0B91BE01B98E4C812EB1602C4A42D6180454797FC75728D4E0017CBC830E05604FF9536AD64A46DCB203E6526B009D51604567EB6E3E735260A6B485650924C0741C4652D8592296892DF3F23AF782A1D57ACFC1D429B430C5EEA369D6E314D3CBAEFA9A4C667C39607B278F6953FA84C18008588EB56CB46B61B9B15EEE6B7ABC91308F037EBF3798D7F72724EA3E6CD273A0269A17296EC74AB078A618173A562BC175FC8A5A522ACA8DCAA87CB36EC0B46E3776B9203696604046D4168A02E73A351A6C0DB127E6359D93712FAB89B855F74FDCF87581760854045FAA3BC9FB440D007B935250715B527F7FA47FA3125EA1860907259E43802F1CB4CBC41025C119835BF796F9F96779ABB5D0DB6308685CD01A6A60EB0887A52EECC8B2D10ABEA5C470928BB33F067F29A2A21E52659171243CB215A6C6C96171236CD31F80D930C1EA8C2AE908579333B55AC450FC4896C79394A7CF8C9894D9CC029D687403E545D7E68F3F22A35D6378CA29C3A11456672626C1C9BA4FD86FB77A41BEFB3D45FB6C4172B7D79B51511415C0B012C1338854CB5CB640197F048B7763502FF64090D589180498D497347A7494FC8B864557A7A5BB8B998448C155B1022257BAA0B56FA9974E099739ECC9CA75A587399E6B3B3440048357DB1E840988B2B6CAA67874710B44AECA293BF0935A320C63FC10BC04B186787CA376281935CDD7AA379F5717CE59A3C13C737553B31AF7BFE903CAF2529FB696B08D9A755E3438D9924E77F324B4CC8D87DC63521C54EED49F8E1708E0D249F9373E82C3625FFA95C420B737B665DF54824286868C797BBC056FDEA7286FFB4451E9B434D23316D758F6B92133807B7F1637358C2346377778C7C88E72B792CC28DF32C7AC3407DEAB6B86B72DA428243F457113965552B7A59B6A02F2FC5A96AC99FF60A6B569223601CA73041F79F35E127785FF50001F6650B8A44D62DC35D1B938443A80515B7E9B17CD75712E59A34A1634AA80C508F54CEC691377708DC99B9FFC53174487BF329A8E85247289B1A5E6E404DC9EFD49CD1EF2A9EC523DD287391E003A036D6AE35822D6E9E23FE925B8F7C0F435A07B3B913170D00C989B39ECEE157C5DCF6BCB246AC99A6B" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "0E381FCE010F6D34612D663374A9A6C99B8EA2A3621D61401551D7D2BA22A622197571D21C352BCAF54A5BE0FCC5C68DC16296B7E033937F0A3B042DD9637EBD", + "D5CB9D93A5C06BEA4081B1C0292241208112540A1380F2CB70792217E69516B89596AAA541425E0C5549F9D34779BA06967925AA2271AA0B5C8257873134B0815355DFD7AFE1BC7269F44DF0E49AE96B78F443ACDD82C3B899175ED946025C1F7607C7EF3A390BF025B48C9F2C6AAA38D4AB1D26C2A6916F5E355D0630846AF143FC13B253113DBC096B8BF459FAA3C662695F26D63D6A331B76864C7844769A91595C086D35B9BD34F70B95824799386800703C00EDB9E0B89B211B16B6BB5EE309331C0B0AF3986D2CC3280875B6E6990BEE4370067A093B94C4E0B898D6998806B48028A985C140CC4E89025331928FD8AFDBBC62E020859E746F35C7ABA0AB2F088CCCB18894D78CC7A48128138BA15923458293C824D728D1A47AC15991151BC088599B64E3C819D7277E88415DCA7774B7B1277C89CAB436220239E8A7ADA54299E4C957CA88A06134BF309B31DF6715882C4140FA12833B2A524738A8C870E249ABB635B17A0462287842D4B96197663DF8CA404505170E163B2A67CECE1A8C25F886E1C15A2DA4C5FAD25C6FF7ACFB14C4CFA06CF306959B63621F108D7BB31F3EBB9931B0C2D0C4A973F496249703C206530B4C65A548813C669EFD838C35D65AD42721525A08AFC2CCDE6B9366F9B526FC769C79281A365B3059A2437C797D7008A6F5C044505228729EA4261D04F3C618665309215E088357734015F634A26AE67F01DA9A9D738759118C9F8B994EC751D9E2661C639A0720CA70688DEFC516C905588458AD15EB144A91065CC0423BA8BE7BC7656CCBB766282FDC95BB6A9272C597864204C3BC914FEBD9C3ADACA5D9D13156714DB38C94D751B2BB07A07DA207322169F9E63E95A3CDC6B0BE8D7B8C6C463008B020F247B349305C202054B26858F2EC94BA683BFA1A9CEEB55495C9A00CF194EF90916B08C2F2F4B3537C100AC4B4C47474386B73CF2C1DADC304A66735466563D790023A5C5BBA156B68604829438A20DABFCDF3CBEE0A50B9D37E35634ACA31B7F8B3AF81BC9C4EE1702E089DCA5CA1F28BBD86EC657F73B2FAC9B6C0B5BEC33336F55C9D0DB5175344ECC591A12B2170887B2C3B39E361ABB1E691C3C161C981AC0E7419", + "27E6CA5E012B40708403C23094F9C7FA13846DC85077F528DAC9AE244C0DC8C009FFBC761501786FBC8EB11105FC758639F356BD2CC7C1D244EFF675E859320217BCD3762CB1927A6F560F971667912B50FA4B471FF1A46623C2F8A65147138E2ADBB0B658873AA7302BE15129FA9B7A20CCAEA5C4FFE7B9A6369C589CA08B02360610C1224C467309909E5B974E93A0A8B8C492D939B2919E34F8BE9A277487A14F273583400940928853E9BB3C0F607A24B2172845B1931608A00C3112966FE56ACA03047E815595A0818193024D183C559D98332060CE30C1A48B927F4F51C318803F3DCC4511F8149734993AC46FF4B48ABE026813B174924C93E5042185376A964C284BD13AEC70686DFB4D344186E647987DDB038364571E316B9E404880F1279F5AB04CA735DF6C376B257DE247745379C2958A3EC79669A604CA62A84437F544B23C3524E2801129BCD560C28820C90F6235D69381A0E93D25A89011D6809A8A178483A7328C6723FCBE8510CC4A5A19B0C413F5534CE8764166A348FC070115697588FAB33E356D51963092F41B640470507501A56050A69A3C08101C80D51AFC82188782C184E891C0FC873BB29A4A789554B83DBCFA495E04B66E2C7A438A0BADF95B85C41F24DB7C400C2C035926A2A6AB8174788AA32DC70892648503690A65910B87E55ACA2812807E874591AB6C1D7B718DA339EFD74500079FF1371F0460AA03734A4D04734DC3325066B15F7CB6F2C54FE3F868473B164F2665CD1A06B289A083B37290CC1BBA490A0BE677C1E8CCCA55A8C95C702009616CD0066DE2B4C2672E8814B1D7CA7E4DDC782F92AA1F18797F451364608F293A7D4AA4A10AE41302950AFE4B19A3A12D7D87AB94A179D3F685DC445B472627BDF8823B8742F33461AA434A6296B0CB183D26648D9BF3BD06A79C248B504C8A91B6BB7D38569ACB3A114C800FC5957FD5620231B8C08CA5C63BC7067CB412ED198719F0C792D155FA1B1BA2425E145339C1DC759C429F52DC685BA88DAD271D3BA94559B91C51E4CFBA553FB7B57F0025837E6B9E80793DDE38B0990B548C2133D5CB9D93A5C06BEA4081B1C0292241208112540A1380F2CB70792217E69516B89596AAA541425E0C5549F9D34779BA06967925AA2271AA0B5C8257873134B0815355DFD7AFE1BC7269F44DF0E49AE96B78F443ACDD82C3B899175ED946025C1F7607C7EF3A390BF025B48C9F2C6AAA38D4AB1D26C2A6916F5E355D0630846AF143FC13B253113DBC096B8BF459FAA3C662695F26D63D6A331B76864C7844769A91595C086D35B9BD34F70B95824799386800703C00EDB9E0B89B211B16B6BB5EE309331C0B0AF3986D2CC3280875B6E6990BEE4370067A093B94C4E0B898D6998806B48028A985C140CC4E89025331928FD8AFDBBC62E020859E746F35C7ABA0AB2F088CCCB18894D78CC7A48128138BA15923458293C824D728D1A47AC15991151BC088599B64E3C819D7277E88415DCA7774B7B1277C89CAB436220239E8A7ADA54299E4C957CA88A06134BF309B31DF6715882C4140FA12833B2A524738A8C870E249ABB635B17A0462287842D4B96197663DF8CA404505170E163B2A67CECE1A8C25F886E1C15A2DA4C5FAD25C6FF7ACFB14C4CFA06CF306959B63621F108D7BB31F3EBB9931B0C2D0C4A973F496249703C206530B4C65A548813C669EFD838C35D65AD42721525A08AFC2CCDE6B9366F9B526FC769C79281A365B3059A2437C797D7008A6F5C044505228729EA4261D04F3C618665309215E088357734015F634A26AE67F01DA9A9D738759118C9F8B994EC751D9E2661C639A0720CA70688DEFC516C905588458AD15EB144A91065CC0423BA8BE7BC7656CCBB766282FDC95BB6A9272C597864204C3BC914FEBD9C3ADACA5D9D13156714DB38C94D751B2BB07A07DA207322169F9E63E95A3CDC6B0BE8D7B8C6C463008B020F247B349305C202054B26858F2EC94BA683BFA1A9CEEB55495C9A00CF194EF90916B08C2F2F4B3537C100AC4B4C47474386B73CF2C1DADC304A66735466563D790023A5C5BBA156B68604829438A20DABFCDF3CBEE0A50B9D37E35634ACA31B7F8B3AF81BC9C4EE1702E089DCA5CA1F28BBD86EC657F73B2FAC9B6C0B5BEC33336F55C9D0DB5175344ECC591A12B2170887B2C3B39E361ABB1E691C3C161C981AC0E7419564C3216F28102E39891ACF8E699E7ECBA701AB757E4924EA694610DAC515D65197571D21C352BCAF54A5BE0FCC5C68DC16296B7E033937F0A3B042DD9637EBD" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "DEA119A81ABA617774ED177E180975BF6281D2894E381388ADD21317A33F1A5EADD51118D30AC5D0BB27CDB127893741CF6782D18A4BF6F0BAEDB3DF8B1D9E41", + "143C00A212CB50B783B71C787B09746585B606BC7BA2400D4983C10FC9333FA44B7B4C9FB6A26866419D38C948D865A6818179E5B1962750189CACA59113379AC2901BB69C65E7025DA1C34025746B383968F845F112841B5A31F4279078D9964CFB74B727A29C7A97C4F7773ADB42A22A19E832AA2DDACECD0AC8E781AE7ADB008F8459CD59ACAEC1211B128435617C0CAA290C535940AA3F8E21124C0A275FA8B017A87419A8230398A61B92170BBA5351055C526C2FAD285281959BB38384C95C0B65738122A799D30999EA734A5272BF015594EEB0CBF195B6A3594F30875F424B3B86516459260851DC7E83ECCE1ED03FD573034344562E069A82F76CCB7647F1B612E9953BD0FA744C092BDED99955060D04EC2395323F14583C4BF4441C1B82793441798523B77BA17655767EB643127B690372BF6E01CBD908AB5BFB58628A4CD30BB233AC9024A51BA8C9327298CCED4571FF34653641038D92292446B772921C83A58F15452D0BD6959CEBBED9715B4414A4FB6641B19BC051F802A41B819E2C3F483BCC5DACCCF08A063C86867C873BAF5743612506FF7B4D25667064D46C4045807E22B1A50444CBD146B7D5A67181A4F7D97A575AA3E9CA46A851B7B5084403AA6A02E38ED9186C1AB36E117110B59A9E742BCAEC7B23BDD92F05695A53A3CEB6D5BE40816EDC38095B9211726AC5C572B60A27AB83541F73362F0C9239749BC665A9CFAEE83BDF79A58B334FC2F1B0516C1E2C23969FD47FF252781955CE83315B62308B57466FC19798E6F48A70125A6206AA8E418FB2796D7070951D293537C003DCCC84D5991DB195799E5AA6E1F64224A8C17DF6660E086791C9B01E8B8D4A524BB32198CED727C2FA67462C042B7856115303A740125261B7B87A4271465837C449A341C2CF47223736116A93069A37208420539EC9CE09E6ABBB56CCC140C5E937BAF2029635F4B69A1BBFF66715ED5CB8DCFABF71F26FB362AF8AB48BCB717CF625325A94698A47A64DD2862BBC87A6F0A29BD098DCCC20D9B898271CCFBD336EFA059E02C58C4C4CCAD3759E4AA08C4C6451B593B388F9A97F5107D775ADBD3C9E76DECD390584A8652A1809775871012518676F81", + "0C26BA72AB58870A3E926B71523960793C50848A251B3241A775CB3DF60F63C1B0B25377D02C20D825C3AE74203B3A24E2F1A1D5F6B91BCC727AD6B67D96AA50407E69F99C8ED74C8C3B92EF8127C83901DF8B242E737157E95A67A20A0A25302C504DEEF4B3FB87004822896CE49C95AAA74BEC8A4138523E79148B9CC924778DD1D4A888EAA6C591381DB7A0E38B5A7B2B745A648A34B16CA9A633DB1CB4DAB13157D97C481436556270B5708D09C7A73EB64E23E073630375C4368A1B1A1945C42100FDCE64F0CC293A1F8F3C3D01D435B6A6330D1ACCAED36632326995DB71A83B5C1927BF6ADA4E0E433CFBF98381EB0B33752A8F58AD6D8AAA60138476BA254BFB583615B106601CD807AA2185AAE6E0C630230D57D31BEA0114C461BAF08C88E38BC57C1613D53A021DE850D213ACFFDB10EAE7894757451036665622B6697BBB96533138993088D524C44459DB986ED833885C4A75E05C8D75E222DF10BB1FF5953D0BC7122C89D30C6CF6823C9EB478DDA30AF3A88A1E8259BF5914488120CDA0084876126890CB3574800D2878129C01D4F6785FE11452F637F3543FDF1336CBAB69B9649BAE54277EDB922115AF4BEB1EEF77B10608038C26AA3160201F2B6546D0BF7696B6C9835604E92728ACA9279B2962C3B57DEAA3B45C86A7DA6D1A32A88FCCC96F319068067389353F545BB7C35CB15EC561D0B2CB800209D9113A70616ADECB53FF2C91A668364D61157E27357A5357887AB83606649DD3601B9A30450CBDCC3CB216626CBD30CEBA7A0C16277A009C6229D97FBE8695DD2075EC278667925D431B93D0B68825E434841C98994BB2148346385A8870972F87E186AA7834806898A5EA6F13676022E70AC13BC125504B2865270FE4A99CD2B255A5A18B489647A0A6413A803CB96DB3A257F8A49B7C53395C8792ACC93B36EC5EA88C9D002B3ACBD916D6337D49E2834E17CF433C47E0B7A6D82278FA60417B528266A90A2293B6CF3497B6558B9CE7C4908650DB1B6016339DAC867A66A230324BA1976BCED2E25E5CA29A1C538C86065625B98153E7C99810311FF114143C00A212CB50B783B71C787B09746585B606BC7BA2400D4983C10FC9333FA44B7B4C9FB6A26866419D38C948D865A6818179E5B1962750189CACA59113379AC2901BB69C65E7025DA1C34025746B383968F845F112841B5A31F4279078D9964CFB74B727A29C7A97C4F7773ADB42A22A19E832AA2DDACECD0AC8E781AE7ADB008F8459CD59ACAEC1211B128435617C0CAA290C535940AA3F8E21124C0A275FA8B017A87419A8230398A61B92170BBA5351055C526C2FAD285281959BB38384C95C0B65738122A799D30999EA734A5272BF015594EEB0CBF195B6A3594F30875F424B3B86516459260851DC7E83ECCE1ED03FD573034344562E069A82F76CCB7647F1B612E9953BD0FA744C092BDED99955060D04EC2395323F14583C4BF4441C1B82793441798523B77BA17655767EB643127B690372BF6E01CBD908AB5BFB58628A4CD30BB233AC9024A51BA8C9327298CCED4571FF34653641038D92292446B772921C83A58F15452D0BD6959CEBBED9715B4414A4FB6641B19BC051F802A41B819E2C3F483BCC5DACCCF08A063C86867C873BAF5743612506FF7B4D25667064D46C4045807E22B1A50444CBD146B7D5A67181A4F7D97A575AA3E9CA46A851B7B5084403AA6A02E38ED9186C1AB36E117110B59A9E742BCAEC7B23BDD92F05695A53A3CEB6D5BE40816EDC38095B9211726AC5C572B60A27AB83541F73362F0C9239749BC665A9CFAEE83BDF79A58B334FC2F1B0516C1E2C23969FD47FF252781955CE83315B62308B57466FC19798E6F48A70125A6206AA8E418FB2796D7070951D293537C003DCCC84D5991DB195799E5AA6E1F64224A8C17DF6660E086791C9B01E8B8D4A524BB32198CED727C2FA67462C042B7856115303A740125261B7B87A4271465837C449A341C2CF47223736116A93069A37208420539EC9CE09E6ABBB56CCC140C5E937BAF2029635F4B69A1BBFF66715ED5CB8DCFABF71F26FB362AF8AB48BCB717CF625325A94698A47A64DD2862BBC87A6F0A29BD098DCCC20D9B898271CCFBD336EFA059E02C58C4C4CCAD3759E4AA08C4C6451B593B388F9A97F5107D775ADBD3C9E76DECD390584A8652A1809775871012518676F8133D2FD9B8BF111868CC7333DC5087AE567E348409901D823BCED8716F52D0945ADD51118D30AC5D0BB27CDB127893741CF6782D18A4BF6F0BAEDB3DF8B1D9E41" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "9E3E07504B4426E4525CD54529CE7660B19E344180B99DB5255D5DFAEF172C916CF6809EE9E9DF03A9028A27001C4D17E8A2F7B7AE0B371EDCF1392B48CFE7DD", + "21F49DD8A02EA3F2A647358CCA91B46BD82E65B30296CB2F8D8077EC879199D99B8FDB9A09B16EBB21CA7970CFBE93A9D7C548F2E9105B80C3C4415AAA67342BA0646C614223B70651883FD8C5A8917602E1C38054592EF20B0EE1D064DD938878FC729824A617C9B0661B66F441BB54D0BC230459F260B06E32B464687B95F7BCB5F53A77CB2258A4AAD338247EC13624B9813FE50F59358DD8CA86364B98B6F327A6C0C825ACA64536A94317C90BA75232A803D8EA9F19EBB9758915A53A7DACB287F8E12DC8D91A0B59264E64BFE1E377DF401E4CCB229806C5A7402AABF3931471B0C313C34CD76CA80ABDD097B54CA3AB67656C0DDBAB254CA4EC9A23DBB40F2AE3639716A30952C085E37FFB593B784879A4C07271924AEB850487664A1337BD1FB5C86FE727B5B611B15CAACC2822446728B3D36C9A961F3DE08660F5BFA196BF360B3E0638BD33340A5C7402A46725AEB3CB842267949BA1F9643A7F0C27EBE55738C0A08781B9FDA49F1384479E374FBBA6C15BE17AD2E137554224AC861C4EFC408A85453088A9C2A830F0C6128E0641BD08264D2667B10C799DD579F53895C3A84A52F43526564B41C8251163CA33B83837F1AEF619A7879406DEF7498AB2B9FF98AF91518D026AB59B47B55FB6A3B35B787DEA1048216103EB140597689A74BD1E426273B10770B11B97337223628FF4D926F990C0F7B255F36051E518AFDC68CC52FA57B302C73C50C8C6E91C92F0B84F1AAA42E06D46706E94954062E2858CC15B60D4190698B84A13284D8245E9334D39D47A0203C4712749FC82135C360B387407E9A39D9860BED3A49AC5FB9E08DA48D99A535878BAE07B19FEB86D480BB5ECCCA644C2AD8A2846023C4B51FC65E1D60AF586B273D2492C5ACFF4BA46CE3BA17A6269FB2BCB43213F1659B9D599307A338CD33387F0206902E198E7EC6FCA79425ABB3336DA8A49C18AE4CB0C04C75287543B334A7227821D88D98C47A08A6AC251B6D09CFC6CA5ACB83BE37A0DC1D1A930877C5A80889D719D2CD3B93A3A164BF7CE67F598B339A97DE5C4DD36C793EC7CE35511CDF59714DE4604C98B78305ABD93321161CA2661C819AD1DFFAA4D2D34F88F08DE653B", + "B5196A7465654CBB1F11286B8EBB4138C7B52B2A363C8C8ED4C9B0BC269216726FD54016708402B9E09493510D499285C7751735A554DA99BD18A25A2DF0BCEBE83C743343B63655C16A7C8FC007E7B057D6E3832971A41409857B248F906769AD196232AABF04D23EF6704F79ECAF8E17AE2B70B5EC2259DC922FEFFA9169FB986CD18B36C032DA0291346B4AD1FCBF6E47C028952EBAB1148CD8A69656A0B3E369501415BE575F43E27817949FA7A93F1DD7477BD1A6FA432522A892F2F772AA83912657B66B09B8021216A7CA851A90C665589B06E766EB61B93673678FEA454BF2A75BC043F1CA27C3E253762418B7C1926BF8441DE9A92AD69274500168FBA7F00C9741E47BC5984120C76834413F6B3223BC165D44489F63EB765F07B9D1FC6DEA9C5ADA951CECC048901882AEDA3DA4255E1C27C472F355629C49A0688064BAA028F21CB772C41EC63243540F6F5AB77AE1CAFEA83343098DBF581D49D188B87C788FA0BA3E59B9C9564CB079371C772B61E0897A097762FA3CBAB55D3071BB0576CFBCACC08A24206DBA65AD3320A5926049CC05CB5C298B470F960621CBFC2EF7181593B5152F2CA14C216FED4174D545ADB78C4D1649AB6B14B11EB63B5E50A5A0E76B1C6710990344E495300B2AA6B5632A3E809781DCC41AA61C5406292B445E43C6053AB435C1C4B3A20BCD23F294FE1C4B0926971E9A622534B94A0092A536CEC0308BEEA42ACAA66023247DBB8B4A57237BB6B087E0244F7C0A5ED3084C9FFA78C439599DD46501513027080029D75F57324D0D2B16B6599C106B72FEE72EC9C3AD175229236A8F9450905D089339756900E658EEC89DF2D0366E0C97FC3C6A663551FD150983E64D0827CAF1F977EB239A6D0747EC73B45A0731FAFB222C8A0BB1A18A006CA7C5E54FD0868FA1F723AA561673935C6F197874A94225F5A6E5A430BF116A49087A3578B41A363BCD0874841966991B83B3F8C170230D14C3C139D349C67B61B80C77524276277398EC3B627D980E8F943F1BE92E8AFA3A89853C71205A7EA7A6E45CCC9D939E59CBCDE92770A9CA4CC2C15521F49DD8A02EA3F2A647358CCA91B46BD82E65B30296CB2F8D8077EC879199D99B8FDB9A09B16EBB21CA7970CFBE93A9D7C548F2E9105B80C3C4415AAA67342BA0646C614223B70651883FD8C5A8917602E1C38054592EF20B0EE1D064DD938878FC729824A617C9B0661B66F441BB54D0BC230459F260B06E32B464687B95F7BCB5F53A77CB2258A4AAD338247EC13624B9813FE50F59358DD8CA86364B98B6F327A6C0C825ACA64536A94317C90BA75232A803D8EA9F19EBB9758915A53A7DACB287F8E12DC8D91A0B59264E64BFE1E377DF401E4CCB229806C5A7402AABF3931471B0C313C34CD76CA80ABDD097B54CA3AB67656C0DDBAB254CA4EC9A23DBB40F2AE3639716A30952C085E37FFB593B784879A4C07271924AEB850487664A1337BD1FB5C86FE727B5B611B15CAACC2822446728B3D36C9A961F3DE08660F5BFA196BF360B3E0638BD33340A5C7402A46725AEB3CB842267949BA1F9643A7F0C27EBE55738C0A08781B9FDA49F1384479E374FBBA6C15BE17AD2E137554224AC861C4EFC408A85453088A9C2A830F0C6128E0641BD08264D2667B10C799DD579F53895C3A84A52F43526564B41C8251163CA33B83837F1AEF619A7879406DEF7498AB2B9FF98AF91518D026AB59B47B55FB6A3B35B787DEA1048216103EB140597689A74BD1E426273B10770B11B97337223628FF4D926F990C0F7B255F36051E518AFDC68CC52FA57B302C73C50C8C6E91C92F0B84F1AAA42E06D46706E94954062E2858CC15B60D4190698B84A13284D8245E9334D39D47A0203C4712749FC82135C360B387407E9A39D9860BED3A49AC5FB9E08DA48D99A535878BAE07B19FEB86D480BB5ECCCA644C2AD8A2846023C4B51FC65E1D60AF586B273D2492C5ACFF4BA46CE3BA17A6269FB2BCB43213F1659B9D599307A338CD33387F0206902E198E7EC6FCA79425ABB3336DA8A49C18AE4CB0C04C75287543B334A7227821D88D98C47A08A6AC251B6D09CFC6CA5ACB83BE37A0DC1D1A930877C5A80889D719D2CD3B93A3A164BF7CE67F598B339A97DE5C4DD36C793EC7CE35511CDF59714DE4604C98B78305ABD93321161CA2661C819AD1DFFAA4D2D34F88F08DE653BF0766E6D2293738BD5AD2B539FDDDAD68650A4B541166CE479962F3F8F982D886CF6809EE9E9DF03A9028A27001C4D17E8A2F7B7AE0B371EDCF1392B48CFE7DD" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "7BA3CF854B04DC90FC0B3E4FA9BE56447418CA2E35E96F1A82B9F19D84DA3180EF2DF47A1CA519E4E97865B564F29FA21A249F5EC4DABA6F1DEB2A65E9C60862", + "D28A54AA8BB1899A29FD82B6DF8AC8D1F57B26A766DEEC1F6143B8E6E2581A10A397194F30C7C3BA8B122BA54B5E293C3C5054F394C3670284D94CBE6EA2276ADA2D0E5767B527A060B770047CAE4671A4018AC3196C0D66300541DA9BDAE88244686E6686BF36154DF78319D6483A2D9181BB7ABA6926CFCF8C56D2E635511B6D13326825B2BDCEC62051258412E4723AAC542F70A7F381407AB69423FA2023804BFFB2C892CA8371D00BB9AA28593619F97CCF77DAB94E1129D1B7C02B7B6FCB147C3314ACB3DAC2D83B5FD811CD9839A99C9ACA4A8BC931C4ABB9878F504537C8C4938E9015AF8290BA4AAC15CAC4945B3D7EAC59F48987DE36B95320263B62308046BBA557738197634E4C74EE09964CB7BBFDB75844D6B6F0BCCDACD47A9D5AAA6A51CF61264435DA8AB872525B091C4A1A6746F41B5ABC0B59F4899AD6322D78178148708DB80A20621F41168F489704FDF208B39850F2FC6206BA02D369AAB1199FA727AB8CCCC6F213B1F8EB9328DA811735C2973119B2D69A1278A4BAC584E2DB17E8344BFDD6A84BF00217324A48811BADFB2FA273A604B74EFFF05B77919C7DC12E97940DF3C6A8BE0B0B9A8BBF72D8CC0694574BF5A9C1E47C1AB2A43BF05593D4012D7ABF5149929A819891727456E7A8CF082CE9365CC01B7EA9E429B1052B93D61D490237BA383CAEFB32E9C251B1835FDDF399D7108BBDEA689269AAE0C6A182B02F99141C8A5209769C80614404152C3322BBB7A54429596455A1CCBBA5D181F13C41C97770578B334AAA82F8C8C51F93A12947540DF055EB941B587B4BD54795BC212F0DEB86546A4D65812BF108122729AAA8DA6386B0621EB25E790B1A491B04A020A2DC2738F4C28FF52C9F99581E763275FA9A25EDE52FFEA969B4AA5F2A1056BAD8B6B2A3571C6C48C55C21A23988E2BCBD4CC9642F0912000043C7E93F1CE04FF721CB982A8BB4FB9F295C6B60453158F2C6D98BA9FC94BFD2A205DFB5665167CFF1805ADB736113D7C1FE8C002B169DCA1698EE8867B6E2B690B27C7BA016FFD9971447CE1A28B624D0242144A2D31B7EB0165E1F581459AC361660EC89F0EE4380E776E11446F9D1692E158E4DFB399EBCFC14", + "E3291F9FD18BBF570E0F353517957A73120F9E1416950B99702017AD846520C9B210541EF5C55CAD4C4E30B1828B6BAEEAA09420D719640702ECA0988E48C0BCF66F2E6005E6D16B53F1A7A998B10BE551F3F84C56FC5F4948C93A3096DCF88DAD5B1E3D838E60C61304B3B7B4BCA7322083C0C80E621A48D4C4952CC73ADCF1506E0B39A4677A1998A44E307D43119AE495ACB3E5A9EB87A449D6A21D828C70592ED1E189A21A9D2DD2A905DC64245155CF605FB7D72525CC0FA1F89EC351AF7652B999B35403D2AA223797FF0B4CCACB22AD1B60BCF8324892487F066846464EA3253580D2B9592A1AF1A36E845680B619C3CD1739FF7A36729B37F5D40F42A208002B93B07C2BC324BA800364B648AF03436E0899C6E7862CFCD6AB4366C605152BE6D631A59A095A5C6582FBC68FDC24857446F3C852612B50E463178ED70334132F7CF4C7358AB0F3BC00852A7639D97387A08A099737C739831BD34EA6369CE41A91E12A888A16ADFFE7156249B1287A7BABE466F05CB16A26C3CCD174020078BF842ACE451756C02A06E17A584B2F1F6A9C1521BEAE01C75C92C108F63B5A0823A3FA6654E50A5AF9206DF602991C26D587355C5A641E53BA08C1626F0568BCF91654F407999B3DCC7CB2E4236E86CA2E13AC60B78C50A044CB5E660789813F9B6284B2CA5913D6546969783461C08EF2515A08BDE44B7F390B54694600CC547E17E52930E43DE53B02E51A8A674B70DA4B1C7DA6C3F379312281AB2C6339214460C4D27BA41375D0794F4196A1DBAC83E6599F8071091F6C190FE3927E086C6218C3E0B8ACA9F2498B0103716C8B8D1C82D9906EE5E837E40A93E57806401AA4EC88CDABA6744F22CE1DC2C5D10A0AF9B8739D9C1352E9B4157892FB15541326129C1A7AF91919DAE7AFCC70B8F1A811AA746019249EA9D2C7F377A7658B4D99057EA7C9805244B595F1A9C05A931DBA4A3C0995AE032DBF53994502924037B3B7CB2149874AD84C90EF44C022B2AD8F217B41F69A744BACC0B1B8ECF7CF3882442403CA1AAC52D49546D7D69A9943392C48B4EE5858DFC8B1FE4A4DD28A54AA8BB1899A29FD82B6DF8AC8D1F57B26A766DEEC1F6143B8E6E2581A10A397194F30C7C3BA8B122BA54B5E293C3C5054F394C3670284D94CBE6EA2276ADA2D0E5767B527A060B770047CAE4671A4018AC3196C0D66300541DA9BDAE88244686E6686BF36154DF78319D6483A2D9181BB7ABA6926CFCF8C56D2E635511B6D13326825B2BDCEC62051258412E4723AAC542F70A7F381407AB69423FA2023804BFFB2C892CA8371D00BB9AA28593619F97CCF77DAB94E1129D1B7C02B7B6FCB147C3314ACB3DAC2D83B5FD811CD9839A99C9ACA4A8BC931C4ABB9878F504537C8C4938E9015AF8290BA4AAC15CAC4945B3D7EAC59F48987DE36B95320263B62308046BBA557738197634E4C74EE09964CB7BBFDB75844D6B6F0BCCDACD47A9D5AAA6A51CF61264435DA8AB872525B091C4A1A6746F41B5ABC0B59F4899AD6322D78178148708DB80A20621F41168F489704FDF208B39850F2FC6206BA02D369AAB1199FA727AB8CCCC6F213B1F8EB9328DA811735C2973119B2D69A1278A4BAC584E2DB17E8344BFDD6A84BF00217324A48811BADFB2FA273A604B74EFFF05B77919C7DC12E97940DF3C6A8BE0B0B9A8BBF72D8CC0694574BF5A9C1E47C1AB2A43BF05593D4012D7ABF5149929A819891727456E7A8CF082CE9365CC01B7EA9E429B1052B93D61D490237BA383CAEFB32E9C251B1835FDDF399D7108BBDEA689269AAE0C6A182B02F99141C8A5209769C80614404152C3322BBB7A54429596455A1CCBBA5D181F13C41C97770578B334AAA82F8C8C51F93A12947540DF055EB941B587B4BD54795BC212F0DEB86546A4D65812BF108122729AAA8DA6386B0621EB25E790B1A491B04A020A2DC2738F4C28FF52C9F99581E763275FA9A25EDE52FFEA969B4AA5F2A1056BAD8B6B2A3571C6C48C55C21A23988E2BCBD4CC9642F0912000043C7E93F1CE04FF721CB982A8BB4FB9F295C6B60453158F2C6D98BA9FC94BFD2A205DFB5665167CFF1805ADB736113D7C1FE8C002B169DCA1698EE8867B6E2B690B27C7BA016FFD9971447CE1A28B624D0242144A2D31B7EB0165E1F581459AC361660EC89F0EE4380E776E11446F9D1692E158E4DFB399EBCFC148F3A3E27382176BB19DD071C2C4682C83E7EAE441DD88FD5196B7138ABC4F71CEF2DF47A1CA519E4E97865B564F29FA21A249F5EC4DABA6F1DEB2A65E9C60862" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "C50CFED6B775C3BE9F845252810CE87B7F4681402AA0591F2CB21111C447144424D5978E539D2717792D7A2E2DD58857B2E867251CBE565C9B5273DE8C3CEC1A", + "9D956DCFAAA1FEAC063B721CB3D92B0DD350A2236067A0052C144610DB19499C48B3951A3C4710D3C494B64B10BF33B081B51FC84B0F742745FBB28DB25A20D3B0B7D1082E6BA50337F8245FC87BA37A4BC131B18FE8C1C4017CEA747341A9C2564A4781F43278615FDFBB108DB4676FC943ABC036E16B423BEA6082DC643890404570026F7468487CC31BC5A3ED2A69FB7869C80C5AEA109AFF9722A6B51025E101F868CD5607C1BB63CD1263AE22334257645FE70CA94C756A25591EB600C98E9C906E163F9102BB4B62BBD0FB4277C3188D2A827D063A6D5760138B27C6B5413558A004A458F999C61391A2E9164240D54841B4848C109E64D94659150D60876DC49C55776390F1986F57744BD19601B59C44336B3EFD74C18EF46735C52FC7E7A382027A53842C90D158FFB9C64EDB43CCA9C168AA831BBBA72C421BDB9BB7D6CC2890F88F98791F91BCC7271972C6087C54E06BCDA60C3B97AAC69A5776A82F7DA5751F5097F8D913D9F24522C4B81AA6AF2FC41F12C82FAB9B71B0B827F7068221BB8A93935E851820E7FC84E55C272117251F3432F26C656DBB54D8287594A525B4CA91A3A749D93ACFC29578A54078F4DAC339C48BFD067D94D73C8ADAB969A21CA322AE91A9562F5B3DFF4A7EF7989399743B696CBB1C85B7378CC00755B1944950585BA540D8C9E09C73DE7A538B7C5E1FF23AD82392B522520AA01B2012CF099208DC95974C144846B3BE8C1434131567697A58212B6C0A6AB59B090CE30A0F4A746894B4288F922B36A8683DA555575B01DEE961C6F51CC83491C5F4CA6553B2B4815EFA94AAE0D98100408137903A946C360D2C0030216897A228A60C04454191DED57CA93C297C5A10A95377E3172817A8A7BA5C867405040D71ABB4B805AE37BE069CCCCF78C6F42A85286A6E6E449112D2C2619241DA3CAF8AB202E9398EFB9571BE3780944994CD30BF8CE13BEA33040CFA82F3D21A3F1963CFD4B5BC807807028EBBA944BBD104C270269A902679F6219C8B170749B5D4AC04E7851712E69B9386B60D187951C9230D64135A10374143CF6119159DF23660261B6785A9B62C25BF46E62ECD45DFF487255970F7E5A8F1D84C3BF025263F", + "5B5C6BB96C3A81C8C2C4A97DA10076AFB02EFE6C78F7A57327053231B43D74104D0002746DB88409557EF82B942B441853E699ED3C033B0040F85189BC877D62708B4C14A4953006E545A160F575FDC13DAC2A2DAB439D249A006E4783C964BD3DCA7D6C3A5244D9CA7D865BFFC9BFB41A7204636D7C6C517344A16BC7757856B0CD455FB5C312D8E6B7EBE01DAB6356564BB962C884221A68F562141AA310550824A5019088A387BDDB6525639B3184656DA311A286C9E533BB021156E12B5B13888C4D986980405D0CA994EF11CF2B423469B521B1C3451C712CCB7034BD8B71B045554F81A24E08AF53F38B01A0A7B6F1B245CB383EE7C4B53828B7223970D74C75AA80BB0C417BB8463B72C2A88C654D609DF6FC5EFE68C2DEC2804D755632C8B0F1037B518121365580F64C7AFA13782ABCA8449923B51AA1B5C4B3AC269A60D04A1CC9128E57B9B6574ED424A2031B54ED373AFEB66CFA280F50BA313FC20ABCA27FCB757D597469BB15C45D2262D9EAA016782FCE6A58C094070B1A284F09CF94AC3C7ACB5A0A3938ACBA35835863B906031CF69E698BB76681CD254843E68B74DC48B6DD90CC0914A48870640ABA2C5AEBC8D24B7D1B788EFC9967B845CC25F207DE5739D3EB71B4774C7701B5F281AFCE641B4AB527F32080D6D380286A19D1D3979F1C0518229EFB02855DB629D7899F7334CC1CACB0BBC894501377F2CC5E0CF99E18F29F60F9572D426E3DC04967F38EE7B3A6B9FBA4379B29CF299F005C8280899A25BC320FEC7D33EA6CC267CC51F731626B6FE27796F73111E23C55D2149B9BF9C8B096C4CB9754E927CA12BCA9DBD432B6227B483B18E4936EEDB57192EB4AF1A11F415892AA3424E5BA642982BA72A2A631E1CFDBB431DAACC0839BA5D326B20BE47E21CAACD98986202395CAF02497E1961752B2AB26C940F11858662BF8E7A24E3B8609A32BAC68C936339A631C4EBBC6BD929510F8F631624735A0B90190533FDEF82A7FB632F78628765B8291489472D71A70C73FEAEBAB0E96809ADC37E1D120FBF19F97D0A165D242589301CBF1A3F18BB6237C209D956DCFAAA1FEAC063B721CB3D92B0DD350A2236067A0052C144610DB19499C48B3951A3C4710D3C494B64B10BF33B081B51FC84B0F742745FBB28DB25A20D3B0B7D1082E6BA50337F8245FC87BA37A4BC131B18FE8C1C4017CEA747341A9C2564A4781F43278615FDFBB108DB4676FC943ABC036E16B423BEA6082DC643890404570026F7468487CC31BC5A3ED2A69FB7869C80C5AEA109AFF9722A6B51025E101F868CD5607C1BB63CD1263AE22334257645FE70CA94C756A25591EB600C98E9C906E163F9102BB4B62BBD0FB4277C3188D2A827D063A6D5760138B27C6B5413558A004A458F999C61391A2E9164240D54841B4848C109E64D94659150D60876DC49C55776390F1986F57744BD19601B59C44336B3EFD74C18EF46735C52FC7E7A382027A53842C90D158FFB9C64EDB43CCA9C168AA831BBBA72C421BDB9BB7D6CC2890F88F98791F91BCC7271972C6087C54E06BCDA60C3B97AAC69A5776A82F7DA5751F5097F8D913D9F24522C4B81AA6AF2FC41F12C82FAB9B71B0B827F7068221BB8A93935E851820E7FC84E55C272117251F3432F26C656DBB54D8287594A525B4CA91A3A749D93ACFC29578A54078F4DAC339C48BFD067D94D73C8ADAB969A21CA322AE91A9562F5B3DFF4A7EF7989399743B696CBB1C85B7378CC00755B1944950585BA540D8C9E09C73DE7A538B7C5E1FF23AD82392B522520AA01B2012CF099208DC95974C144846B3BE8C1434131567697A58212B6C0A6AB59B090CE30A0F4A746894B4288F922B36A8683DA555575B01DEE961C6F51CC83491C5F4CA6553B2B4815EFA94AAE0D98100408137903A946C360D2C0030216897A228A60C04454191DED57CA93C297C5A10A95377E3172817A8A7BA5C867405040D71ABB4B805AE37BE069CCCCF78C6F42A85286A6E6E449112D2C2619241DA3CAF8AB202E9398EFB9571BE3780944994CD30BF8CE13BEA33040CFA82F3D21A3F1963CFD4B5BC807807028EBBA944BBD104C270269A902679F6219C8B170749B5D4AC04E7851712E69B9386B60D187951C9230D64135A10374143CF6119159DF23660261B6785A9B62C25BF46E62ECD45DFF487255970F7E5A8F1D84C3BF025263F485BFD439479764747B3CDCA0A9D177883623A068BC0164DCBCCF5869B04C88E24D5978E539D2717792D7A2E2DD58857B2E867251CBE565C9B5273DE8C3CEC1A" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "24EE8A22B29702351C470CCD3463E71C4C23ADAA83FFF4B621277DE488440E28214750C76485C079BBE501C72B529A9D2751E73E7FBCAF74B5EFA87310BE1A1E", + "80DB3438E4BAB645C334D7098D9178979146B30A6CDB82B7F0F177D780CD2A93C92E490DB90263D13C7C9123B9DE83715E09030CB958E9D895E4E1688628235A47BB8154CC1831BC6DF150E2F4001BC935CA66955CB77F275C4B65B1875C3576CFA2BF1E23689FE0128B48588CDCBC0F77799FB909949422BC600131725D29D742C03980227081E702BBDDAB94026209909324AC3064B4333569B427F2C636E31234274AC3A3F3C7F664046B1AAFC7613EC8497E5EB59426074AF6811333543B6B39AF6C5C9569D6A520152108AA60C45C9811B0529A287ECC6B3E936111FF64150B206798EC936D556B5F82589A3493DC204404B04032A83DBA0A30E65A4139DB8C817675B1F39D37B7090BE98F8E61CEC1641A22AB76A388C56BBA4920F44B29A8A559694D86BBA1A0633E7D5475A768A96BA5A1A1AB141C2871689919FD900410F6B8D614050B9B5FEF4490A990545E23B9190C2BD0E967BED3469E9848691366D9CBC68BB00087A160BA98BEEC785DAFEA59C6C68C75D554B60ACFB1A17821A52EBCD6483891A9A15A687C82A2614C7AEE9164C5245376E82E37811283A4C81B8AAAAEE22677FA9F98C63C66A2C5723CCD1026B79532C84E5CA52EB7552E2633980A8465A82990B37C39A1AFD6C7844A655759B941A9BCC629CA18CEE2A110FC3DA367153F87872CB12B6C26A01379B89163B653664F785857D9DB2CE813AC27C4943038B7F524A4834A930B01CA0C6901CF428F6590B88B2B2766B2960057B615C11ACBE9A89849CF74F7BB993A154662BFA0FA34CF509BBE533098B493DC1C6CB061545C94B0D5F596A151B1216681EEAB7FD9384FE322360F4805594498C68A58339B686079C453171CB5C19EEAF4962E4B6B62EB6050F887CAD593AADC2D06712828E386A44534570A73DA201619E7A4D7A37B1AB5399BB72C737506F16032CC3AB6237C7532A65DE68B06037B6A0886603B6233ED7822BD175EEB7A2D79BBCA059AA9439AADBEB001B18854D2533060EC75C4487C41480468A4228F2586E346A3F77724DE59A5513363DEBA2A8D9B3527757FAD099A3B3549338A083FFE722A02FC7638C74D63F34648879E37C8DD615C23EDD5881131054121674B", + "02E1527DAC4051265A0B86301D9B3A3653106D9987B2A35476A832C9281176065B33E10A5110B62074B1BDB8AA91DC715D40CBA0B804C09C87415ACAC0A864FAA02A17A3690AF9627305062536685546795FDA8F797B3DBC210BC3361DDEB6B91C767956BCBB8016637DF5BBF65050670C57555C8785C39520269284283A6AA44E5CA1906052C025075683101AB36294CE78AA3AC18852F7682A55044434BD6F4602855993C8A94B7E11964F6849B600599E8803C38C7A5BF768D00B5CF4D39D566374EEB263A9091D9C77C671686B6F956B35030D529AA97826A8B145B569E19F7E1A90C8CBB45CAA23FEC5AEF0254CC614433E891508612F02E5263B0234432C1ABB91A00F381B107B3BC47078C0256D7340896F78A9DEA2901DCAB1FF82B676E6C87EBA61DFB3C4B7C95D22654373F8BBF1526B47A12DF745657BC5A35B299780C80CD395C3997C8B2195A344B796C942C3DB106A4D3B20D58281D3FB3518485141E12CDCE0070B781F7DBCA17E660F96A8084307CCCDD31C26F74991284303B37F4DCB30D1C01DF1B3C4CADA0D9FFC843D2A1CBA7B354BC39EEA5883E9FB21451BA72582BAF0672E8D4233B637B14413C65F44615203850F5A9E51A89EF47B96C061B094761348119D536675D2444C4FB438DB4B8E63998808075925F6267B44767BA0CD54790534E2B4375CB0E0EC73AF55AFCC0B4DD51238D0E12D39A999EB650B7FA83B3D32B3C33C29367A18DAD76EED821A0C71B79527C6D7877D1D37B9097B34D8C7BAA989288325429B49180F693176E2A00BD706D8F73DF7330ABCEA80F81440FC4A1C293998E4896B9DD37400F3A0431C80BBB3C94168433C315E8776C0CED17538D1273EF5C0B5C117F2EB26B815B262436D07D2711FA3AA939BB786999DAF6236BDC32B5645338D37CEC2365026EB5CB2F1B2128C9E5492BD040540466410D40A93FA13B1AA1872B67050B622A7D56691AA2A4E5042262AB5AD496CA8F201B68E48864BDB9DB4503460BCC74CF29F20725A2362419236CB6D224917B2B7D5674E9266094A755045112B33E887B21559F63291E6756843AC9A80DB3438E4BAB645C334D7098D9178979146B30A6CDB82B7F0F177D780CD2A93C92E490DB90263D13C7C9123B9DE83715E09030CB958E9D895E4E1688628235A47BB8154CC1831BC6DF150E2F4001BC935CA66955CB77F275C4B65B1875C3576CFA2BF1E23689FE0128B48588CDCBC0F77799FB909949422BC600131725D29D742C03980227081E702BBDDAB94026209909324AC3064B4333569B427F2C636E31234274AC3A3F3C7F664046B1AAFC7613EC8497E5EB59426074AF6811333543B6B39AF6C5C9569D6A520152108AA60C45C9811B0529A287ECC6B3E936111FF64150B206798EC936D556B5F82589A3493DC204404B04032A83DBA0A30E65A4139DB8C817675B1F39D37B7090BE98F8E61CEC1641A22AB76A388C56BBA4920F44B29A8A559694D86BBA1A0633E7D5475A768A96BA5A1A1AB141C2871689919FD900410F6B8D614050B9B5FEF4490A990545E23B9190C2BD0E967BED3469E9848691366D9CBC68BB00087A160BA98BEEC785DAFEA59C6C68C75D554B60ACFB1A17821A52EBCD6483891A9A15A687C82A2614C7AEE9164C5245376E82E37811283A4C81B8AAAAEE22677FA9F98C63C66A2C5723CCD1026B79532C84E5CA52EB7552E2633980A8465A82990B37C39A1AFD6C7844A655759B941A9BCC629CA18CEE2A110FC3DA367153F87872CB12B6C26A01379B89163B653664F785857D9DB2CE813AC27C4943038B7F524A4834A930B01CA0C6901CF428F6590B88B2B2766B2960057B615C11ACBE9A89849CF74F7BB993A154662BFA0FA34CF509BBE533098B493DC1C6CB061545C94B0D5F596A151B1216681EEAB7FD9384FE322360F4805594498C68A58339B686079C453171CB5C19EEAF4962E4B6B62EB6050F887CAD593AADC2D06712828E386A44534570A73DA201619E7A4D7A37B1AB5399BB72C737506F16032CC3AB6237C7532A65DE68B06037B6A0886603B6233ED7822BD175EEB7A2D79BBCA059AA9439AADBEB001B18854D2533060EC75C4487C41480468A4228F2586E346A3F77724DE59A5513363DEBA2A8D9B3527757FAD099A3B3549338A083FFE722A02FC7638C74D63F34648879E37C8DD615C23EDD5881131054121674B71EAA6761B3CDA861357A741D2BF2F9CC109CEEF4FAC91BEF5526D3859AF9E0B214750C76485C079BBE501C72B529A9D2751E73E7FBCAF74B5EFA87310BE1A1E" + ); + yield return new + ( + MLKemAlgorithm.MLKem512, + "D4F529B4DD5DA1F2B3B4EE8ED3959E389F857507A5FB2AF3F762C7265658D11BF43AE8B5C3DE7BA1E7FA9E25BCC44AE2E1AD27A7C45E80BDABEC9259FE88ED51", + "4E64CBAE347CD46994A20B99B6812F6ED39D80352E8A6524DBF35E3EB1BC7F814A8FA2001D3608850C391FE5424FE4AAAE12B6E4459BE0B4A9EDC31328DC37DCF7872474AF884181324A7BCE7527A5A8C0BF1BC2A996BF12648ADC4468A366B9FC1C97F564A46AE40669436BCAD3BA292CB052C2721CCCA58437CAD0132781DC6C2F32AA7123510A811C7D8C7EA42768D2561F0D211F4953309692087EA1C70B6451E12A3B64B8110497AEB9225E4E124A77EA5F1C789A3E023587247F588B201143857894595C6A5383C0041CA5A228F400A236441AB463069C0E769C7024320C0BF10D73DC77F0E15F7BF0AB3AE9BD599485B9A4A9F7AC6E5EF54D5292CD2C1B5AA865219941A0BA2530FBF30516D0075D2C93EF1AB951F1975E818147A3342798141C086FFD336D44E7B658E3368A1A354255CD6295CDEE171CB86CBCED468EC98B5A247CA30C313B415C3BA89C59D31609CE137E66FBA2713475140C24D9368D7D464DFF2C020197759AA92A22A093C6B7373E282E7FC78701289B55416F13E258195CA7B7B19F558040B662239475988685415B02A90B6C697CFB5CFFB4508BB49CF90148F9B13106E31889051AC85193DB051E46C7C90CA88E76980414C60A8B619A16555F92B58B98C702296464032BBB9E2A2AE19B7740E3A61BA1CC85B465ECBA5FBC20C4AE8C251C4A08D8BCC7A572A1BAF55F333CC1168633BC651923430C97D75347D7BAD4981A174624F0251431341093F44842F695A8B96545308269B34017E7C1AD889CEB596C04178412940B27299DAFA140B6C7650312A976C1579FA5AD04F482B0E88F3BF6B7EEAA24639B773D554FCF685E346C974EEB250D3A8BFC45C604E86CCE5B68B65A07BB5B3FCCE19085E21A10E0304371C719E04742D95EB80B3D606C453455BEE13A5127A6398656561C93B744042D74E88D49A74630E253471672E319246E2BBBA0CCC2CD28421DD5621C51B1BDAB0E1C9862E0E1BE6841398D65C668788B0D6B241E5640C96C750622B421CB260B70CEBA10CBA274203AF3829E0593AB8917D2676B701A032A2A350620AE4649946C5631BA466C507CEE64C991E234D629BE2203650FCB8DC9669E5D304E0170FE38E214", + "D70896D8A3B1210524D317B97FC4CEAA2386DE5AAA8774B155131B881428DEA335E74480A84C157C1023B4A91467A5427C48AAD0654CEF664EBCAA850851A225C2549965AA704B54C3532E16B24BAB409E805C24A52CB3C22CBFDCB9B612DA403DC388FD2635941B72023009F4560F90EABD49388D4B490800723FDB714385202F082497F113343F64A9FAC2C83D5B8AC5E24A602A84DDDBA2791843057251B64A7280D47C5A1555CF774269376D345A65FBD193DE36AD8E8C89B652C01622A881EC1233257113DC8E14901EDBD90D8C91B67F2175FC76C1D05584046093D5866187855D828418D5D33E23DA530814B803670B58F3CE34EACAB95989E2F2B2BCB1670BDA8F96E0CE9C89045A5138B619626683422F9C52B0977C1AA9C67715CEF140495269616C57ABFD8AB3DD86B9AB890843DBBF0B4B6CF275002DA255D4C0907E5BCC0A840E1B598A5820824F354EFB16351EA103DED11495AA89C5A69940796BE15AB05868AB7B89C6B83BA1E0F4C948257DD2CCBD5D0758220BB715E6554D0781B3D63C16065057267031D79EE8102003716B8C0A962694B4D2896B40332E188A8BE973C7AB5334E84616C774257B80A17A635C3DEC7D4A157D734A73030206392651F0F36CCA1C8C2020AFF57C6ECB30ACFF6CAAD7338CF38690601A3C44738EC883AF84244426F15157B476F99C2B174A90AF288D85460240CBB85B962C355C8552357FDF39770B2892C82B9610D33FD9C021ECA36054E24F11289D42279CBD475B4232A75918B566084FC9248C05D07EFF7570BA2BA22FD329B45743E619BBABDACA465C51B6958221DBBBA508828DD12D13B29245D6AE70EAAC68C6A4A60361D73A9D77273094AB1D63D09C5B8A5B6E15C7F92511AE894E1B5657B1B1705F4BAA863760E30A0F05001CF258A0AF4210A09AA419848D3CC73E316A94B05B0385D9293047B6CF782BDB121D67C2BAB1A3255ED57D363230A2B31F9AC714BE3BBFD85964089B09E4C30448ACA36E423457FABB00AD5C1C3AB3368958FDE35AA2A67D9FC09E8BB39EF2620B51864F3404150D723851ECACD7E27C4AD6544E64CBAE347CD46994A20B99B6812F6ED39D80352E8A6524DBF35E3EB1BC7F814A8FA2001D3608850C391FE5424FE4AAAE12B6E4459BE0B4A9EDC31328DC37DCF7872474AF884181324A7BCE7527A5A8C0BF1BC2A996BF12648ADC4468A366B9FC1C97F564A46AE40669436BCAD3BA292CB052C2721CCCA58437CAD0132781DC6C2F32AA7123510A811C7D8C7EA42768D2561F0D211F4953309692087EA1C70B6451E12A3B64B8110497AEB9225E4E124A77EA5F1C789A3E023587247F588B201143857894595C6A5383C0041CA5A228F400A236441AB463069C0E769C7024320C0BF10D73DC77F0E15F7BF0AB3AE9BD599485B9A4A9F7AC6E5EF54D5292CD2C1B5AA865219941A0BA2530FBF30516D0075D2C93EF1AB951F1975E818147A3342798141C086FFD336D44E7B658E3368A1A354255CD6295CDEE171CB86CBCED468EC98B5A247CA30C313B415C3BA89C59D31609CE137E66FBA2713475140C24D9368D7D464DFF2C020197759AA92A22A093C6B7373E282E7FC78701289B55416F13E258195CA7B7B19F558040B662239475988685415B02A90B6C697CFB5CFFB4508BB49CF90148F9B13106E31889051AC85193DB051E46C7C90CA88E76980414C60A8B619A16555F92B58B98C702296464032BBB9E2A2AE19B7740E3A61BA1CC85B465ECBA5FBC20C4AE8C251C4A08D8BCC7A572A1BAF55F333CC1168633BC651923430C97D75347D7BAD4981A174624F0251431341093F44842F695A8B96545308269B34017E7C1AD889CEB596C04178412940B27299DAFA140B6C7650312A976C1579FA5AD04F482B0E88F3BF6B7EEAA24639B773D554FCF685E346C974EEB250D3A8BFC45C604E86CCE5B68B65A07BB5B3FCCE19085E21A10E0304371C719E04742D95EB80B3D606C453455BEE13A5127A6398656561C93B744042D74E88D49A74630E253471672E319246E2BBBA0CCC2CD28421DD5621C51B1BDAB0E1C9862E0E1BE6841398D65C668788B0D6B241E5640C96C750622B421CB260B70CEBA10CBA274203AF3829E0593AB8917D2676B701A032A2A350620AE4649946C5631BA466C507CEE64C991E234D629BE2203650FCB8DC9669E5D304E0170FE38E21423E5FA0E4FEB5CA3D872FF3DD13080A119EA1BDE24594FBFFEF8F99D9E51F4BEF43AE8B5C3DE7BA1E7FA9E25BCC44AE2E1AD27A7C45E80BDABEC9259FE88ED51" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "97C4789340DF47850A84889820B9B4307DF3E43A7DE3F5857340C791934F1E99D7F7FE2AA083A10A9C267D3163D0FB888C9D2D7614482095EF1817E1E9E4AC88", + "C4308CB02B4C7A380D1B43CC2B343B01C6655DE002A38CBCB0229DB481BC50C9B6D1DC3A86742AEFAA867AB16122F83726A71446E7B2ABB2CA04FA2FF07A4910B16A73A28B66487483861A1A0A4DC86330F5051E3831631A334EB58B42295C7E4292CB43E8A53A435039A44D74C15598707F46947D45002B80197AD2E28C4FBC1F5CB53E71D808D9D38F52EA7C07A5625959A64B5A81574907337BB43BC283463C557031AF36F08EC20B69AB286258564809EB072AEB0DC69028FFE1407706314BF8538B02778F5921ED40C87102467F5A4580D13B02E508B4140764A3C3265461A7B90A959C028048C723B673F1286B50E70C8AF8730A674EB8F95029D181C8F478B843AA89FA55180B9AC6D3AE6FD75AB356028FB923ED329D38065662D836964811AECA796B1A862905681A39274EBA7AFEFBBA2561A8241847CA38B309003A13433102868882520F17A0049000817B9148DF851D67E09078B6A1C1EA91CE5B7F1D2B2B1C07884DCB07DB46691F9869E8B58323D4695B9073CDE5717FF8C2DC38CEEFBC24FE2630E4790583EC671AD59F6C049AF994659BD075752A4EE7A63D7CDA02E65C6507FA2CEC73B0B6A346A67C9FF5D345169A5FF5390FE2B5C264E9619C24916A271D7838227004C57BF84ED22A3C442895DAD975A96CC5FC949647484EB0872BF55A625353C09A658E1E806B26A51720C4AF3D5CCF739C51A6D744BB103BA67B48AA716CEEA77784C7093646716BF26B1BFB54D2FA114594B7174C567A0C48ADD1236EE8888C551533C7862A3B24D15568E2061C0B41232319476753AE9ECC883D7BB44BD3776ADC95C587C8D5A24D76B787C92CA8A2FB64241442EC751995494A91114D0003212B9C747C1B6D18278318CA979029B637D7A0C2F2345B3BC0BD1B29DD457FE9B8629880B519CC47431066C6AC1687C60B8F961E1547C6DAE75B43104B35801DC0B032FAD18D6B901255E32F09981458F43BC2C63B8C262FFB947304E13B1A05BC883A5106A32E99CB6E651447D1934724F54C0EB37CC019C37228A4537B96259A825A741DE4882737184022E529E803457013123BD925921943706C8BA2C2CF09D68E34753CB6358DF1ACA9A6CC322755333E50050FA207C1EBB1E1142B009C73004AC7BBF20A362A8DF73677767388B3DB57BD278999D99D69DBA055E44051DAC2DD5138255833BE91C4C1054FB3B0994F58A7F6DC3AF92CB9627943237419A8045828E7A62CBC4B15511AE0E2A31E1BAF171A84B7F4BA19F22609B528D3271587A673A7931E0E0678CB017E026426B6770C8AE903C49B79F9219A83B02595D3A7A40B1D7DAA33FCB8760A72BD02B96B2A20513C4A5F9AC772C64A03FE86C80E601D2A1BBDD707B10F71259FC025FAA6B129E81FE5604386269F64E5CC8840A4C3A721DCC819FDE555B8654992EC055131BC69B2CDD19A9343B63E8D098473FC39074C97D899728904A4F539C235E4BBED4024771056E1772FD14503149048D638537F2AA5DD339C4DA15F8E3A05FE0533CCB0167CB74AF29B88EC0C961B164B81626ECAF6ABD876B8B8253BEFEC3163B039088365112422EFB4B3A7E17695AB36CECC06F19AA31104817BC3181BE78DD30C4AD5F7684D142354AA5EC322CEF3AB3A8E906088D2939A35349164DF25688C015D", + "F9C23E5887010816840BC7BE9715B0C3232B94EB64B5C983A67248EAE2623893CDE2F6B4EB421F97D43F71F51804533705D0893B029ABBF5218551B4E1D98CBF3A5A27902F92A66CB4A982CDE622C4F2700BF623FD32A1251B1B067A87BBAA2EBBF03597689D6FA40063BA20FED9C841188D8754641F501B0EA78EC6B5C22B669E45F1C842F070734B409940512003C765F0626BC3764D0BB7DF0B06BE48441C609E53E6B0F8A679560A22307027844949A80B1768E884B69CCD51C3C8EA5C995FA24444103812A918F8A5A861AB974011AB7183060D5B522873A474C28F1E39C9ED434FE6237A0455BEB09C9ADDF16FF537B38EA8923BCAA64C8334D16A3C7050437B350C014561DC3B34057196915B615CEB936E7C8A1AB19F0EA342FC682F48E87C08630D1BCB668F68B35657647546B245721F8FC1AC748A70997BC4AC7B3141A518024299074A4D9198301B2A866E19BE9FA5251493481566BBBC313010C9980FC89BAA464B8CCA92871359ED925A1F6584DA3B7B0BE208A912BF6133B43205C722C585ECCC98AF8224D2286F25F1952EE63C90E41065202AB3C9752CB242FF6A26F071572DF49763C357606127A4048E06E1BBCE1504AEBA1692E62312993B51785820A33E0D62411D187E3738761B601CF5C0C710A6C6FC028036189C011B0EDA97BBD21C9F92744D0D89674003C3BB563F93D7B027C79C0B6718CFB14B80A8934111C644A9A63C30B7CA11A2279B478C8B84470CB11F74A3DDD54D8D395FBE2A54298671BCB08DCA21502B694591B56AE87453B7450DAB8648ABF7AC94A646A9DBAEB82623B92133C94C7A36235B9A874112BB02F1F1B80F02BE5AE6A0370165E854A1ACC74FCAE75CB117255CE08BCF24CB64467E4704A6715A4C5ADBC3BA876CB5B6A34BC3CFE43718F43A04A90C9BAB88CD46EC75708950CC1C1D31FA8DF9BA034DC14FA64A2DEBA28E039622DB241159F05A4815AD8FB774CB807B0667B1BBC9B8CBD8CEB8518C5FD87E16659D26963CB5074AC77046C5053CB4182DAE65037E0C601AD37E25E22DF4A4814EC49CDB21148975B9AADBC290FC0546D2A2F3FB461FB130A457BE4276166622748FDB30E43AB426418E135660BF4A2588653AC2365E63445670CA9CE5E7AFE3378555C29F43DA3C0326012FFC372F356812BC79F77877E415662D788EDAE10E34708FD42808D8BAC0D5B5148A27A41039496CB47C81C5B17A727BAE2057AA33080DD0A71D6718354570CC363AD33381E16B8AC645747ED92B3A16105148069339240EA8118C2250F62691E4D62A3DBC3335019F1BD22AB8F608A8F2AC26DCB483732AFB4190BEB41AB30A3A987251FFC449C90BCB0EC32D2AEC764FE63C19A39A5EF8A4ADA206304267C0A80663A184374A811F903DD08C29AA74C9901A6D0C35506E26B8A8859535DC230DC87236C6A8BAA6CF68A24ABC6565E2A3CE31295916AA55B2C5A15F34A191407430771B8E9318A1688FEC495F6742658646748E8A356CEC16D1A48C1A23747F758EA74BBC382A3A98864AB71055CFB60448A941A374AAC44756047AB40644CDD3987580476253B98033648554E336DCB954D831781B892058DB9E66FA796464412954C0C4308CB02B4C7A380D1B43CC2B343B01C6655DE002A38CBCB0229DB481BC50C9B6D1DC3A86742AEFAA867AB16122F83726A71446E7B2ABB2CA04FA2FF07A4910B16A73A28B66487483861A1A0A4DC86330F5051E3831631A334EB58B42295C7E4292CB43E8A53A435039A44D74C15598707F46947D45002B80197AD2E28C4FBC1F5CB53E71D808D9D38F52EA7C07A5625959A64B5A81574907337BB43BC283463C557031AF36F08EC20B69AB286258564809EB072AEB0DC69028FFE1407706314BF8538B02778F5921ED40C87102467F5A4580D13B02E508B4140764A3C3265461A7B90A959C028048C723B673F1286B50E70C8AF8730A674EB8F95029D181C8F478B843AA89FA55180B9AC6D3AE6FD75AB356028FB923ED329D38065662D836964811AECA796B1A862905681A39274EBA7AFEFBBA2561A8241847CA38B309003A13433102868882520F17A0049000817B9148DF851D67E09078B6A1C1EA91CE5B7F1D2B2B1C07884DCB07DB46691F9869E8B58323D4695B9073CDE5717FF8C2DC38CEEFBC24FE2630E4790583EC671AD59F6C049AF994659BD075752A4EE7A63D7CDA02E65C6507FA2CEC73B0B6A346A67C9FF5D345169A5FF5390FE2B5C264E9619C24916A271D7838227004C57BF84ED22A3C442895DAD975A96CC5FC949647484EB0872BF55A625353C09A658E1E806B26A51720C4AF3D5CCF739C51A6D744BB103BA67B48AA716CEEA77784C7093646716BF26B1BFB54D2FA114594B7174C567A0C48ADD1236EE8888C551533C7862A3B24D15568E2061C0B41232319476753AE9ECC883D7BB44BD3776ADC95C587C8D5A24D76B787C92CA8A2FB64241442EC751995494A91114D0003212B9C747C1B6D18278318CA979029B637D7A0C2F2345B3BC0BD1B29DD457FE9B8629880B519CC47431066C6AC1687C60B8F961E1547C6DAE75B43104B35801DC0B032FAD18D6B901255E32F09981458F43BC2C63B8C262FFB947304E13B1A05BC883A5106A32E99CB6E651447D1934724F54C0EB37CC019C37228A4537B96259A825A741DE4882737184022E529E803457013123BD925921943706C8BA2C2CF09D68E34753CB6358DF1ACA9A6CC322755333E50050FA207C1EBB1E1142B009C73004AC7BBF20A362A8DF73677767388B3DB57BD278999D99D69DBA055E44051DAC2DD5138255833BE91C4C1054FB3B0994F58A7F6DC3AF92CB9627943237419A8045828E7A62CBC4B15511AE0E2A31E1BAF171A84B7F4BA19F22609B528D3271587A673A7931E0E0678CB017E026426B6770C8AE903C49B79F9219A83B02595D3A7A40B1D7DAA33FCB8760A72BD02B96B2A20513C4A5F9AC772C64A03FE86C80E601D2A1BBDD707B10F71259FC025FAA6B129E81FE5604386269F64E5CC8840A4C3A721DCC819FDE555B8654992EC055131BC69B2CDD19A9343B63E8D098473FC39074C97D899728904A4F539C235E4BBED4024771056E1772FD14503149048D638537F2AA5DD339C4DA15F8E3A05FE0533CCB0167CB74AF29B88EC0C961B164B81626ECAF6ABD876B8B8253BEFEC3163B039088365112422EFB4B3A7E17695AB36CECC06F19AA31104817BC3181BE78DD30C4AD5F7684D142354AA5EC322CEF3AB3A8E906088D2939A35349164DF25688C015D345F067D4A9B077FBF18F7561CC71D409D21A3038F1EADD46F165E47B736ED73D7F7FE2AA083A10A9C267D3163D0FB888C9D2D7614482095EF1817E1E9E4AC88" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "A930919E0BD10943E56B216C31D7A9F7949E9A1225FE03C58AC42C401176E9ECC70DEA33B6BC2813484E8D9B60CBB7D2D02E26FC01A74B9363485B34E5529173", + "F547862648868FEC6E3222CF7034524B60C05B116F3BC45038F5033B5705B829791B1C2A2786A8DEB9024E04605A10932690026CAC16A043AFCE573DE6189002741A1966951EE84FF823AF6AA04E9F45BAD98C9A907C0AACBB440B096802745A2EDA13EB444BE641B2FAEB5F2D72C71191805CAB4726B3CF3CC89BFFE8B030DA805BCC62E957A254BB3E1DB2770B946711514AC96CA7484605562A05562B08D5031705C9539057C441A546A71882EE225F50365D072928A5865FCE655CE4AA206799CB0D497563F008BE7623A9C52256A94A662B9E9C85C0B56BB7049884069A68290459836B5506E73EB8070EAA9230A307B14248B6CD302A469B2C31E815F144A43809BF65F1ABDFC20585102257987FFD0A651FD9C79CB299605CBAB700161E999474B44E06853AC1B0AEEAF3867C1A7757E3373FB39123CA1E6F83BA1DFBC55CF57474DCBCB239983C18A9B8283999D878BE159870255F9CA4C684FC7F33B84E47D79FE409B529794A7A943E6BCCBFCBF2A24FA95CA88587723AB560FB028037247E1BC69A76C7B972692945A70ADB03AF7498961BB1C8D98D90714024798DA81A5640418096836A0294575631619B336FAAFA43ACF914A106CD42268F84919015786D0A8ABDA5AB8A16467E30B86AA5119F77F169E148C825DC8F47784F15C6C93486031332C8372A75F8AAC381FB462AE505676941CD3698D0D68C50750865EC12DB113B188332E37C37439A024EF34F5BF8A1A0D55454C315D48A1C6AD81C3C08A9969B6C3CC76EC2600B62BA342CA488C88B3DE0CAC7110CB6D66062F638100CB44CF94A7A745645E64A3C2D2102472379E3EC01B30181AD60787266BA21B71D7B070BDCE0643B0A79FF661C02C053664192D7D585EE871528641A5E7B723B14440505A69E3B17A6C5511AF785216120997400AFFB8D3871A7B6446B160CAA18698F919610F7028FF3764D5A482182611586562A6E767391282C7FBB4885F41D18477015DB7DE8BA9E36382E34D7549AD72A0A03071E3512F221CE4963B1B4C6449301BBFCE81F9E684890C3B4BD1023BB858284352C94B83A9729B42C590EEEDC902DF3ACA69712EA6BA744ECB57F26753FE61E2906A4C7D4436F49588AD81653A7AD6AB6463078090C15AC40F39A37AC2DCE42A6BA94BDE6899263D15D5810BAF0455DEFB0660C5A0C732C65E72790046329CF387A6D41298A984CE7243937A73A2907249747CB3A60B8980118932CC15BECAE3D035868AA5EEDD9BDC766B1A1E67F03B3CD4C37B10BC530FE16C552D42C023C53087413E2290005E5CED1019FF8426F72A596D95AC119E00C88933E100358B99070BC088390738D4B8917CBDC0D3654635EC079C02603D41A62E74C01CFD2A5B7D9807516594DB30904B3A3066494FCB19F70D032C0D5076FC8115777100653C08866086A1B3ADCC072573B5984530727140EFBC99AEE1CB31F874F530C36A0A6480E511752D1C55ED5B726A9395BC533DD9074A72580BFD25D6F929F8EA89CF9E19F1CAC284AD6C6E444B9E901730A3C809D014C4F8BC335215B7AAA7EFB379DC6C25427D827C151434429670AF237B7D810B9ABCEC6A2B7E6A61D367AAC0C33531E215C46F12B8CBD888A1A45DA009357E2E35FDFD794889EEDA28FFC494FDC73303F1DB4A32B", + "2732AD90877C44B9384E72CA274474C22750C2094801A3306DA5B262953B5EE1B31EA9CDC4156E3C4ACF8D25A826FC6FAEC27EE6E512307225833BACACA67B9AA79D49578711565553352B527A9B26E471C5098B304182816A97A5342A7F61B71B59ADBECC56A982C341351F7552046E397DB48A24708A7C5143B7BA1575727A6C68E45553EABDB33238C7A248432B4FB5AB5359E908F2B109F2825109A7838BE600309637DB7ACA5996388039165F7B11DE12BF43843EBF7BA653B83086B960E5422BF7001D73A3462A75C9DE1C49AD763158977F8E721EE6574129A8661BCC272752A4AC980CF76B8368D38AB1A17C57100AADA854402BAE1F4463C5E41879A64C0155B2910A1AFB237374217690B785E6DBB151E49B7183999EE9221856A1ED23B918A3CA8D481C8931B26E8C7C566C444CC4B9A219AB5C1804F8AB6A96205F40CBCF177B1C3BD475BBC33F32AB3CE1BC96DD2800D5A4172F4A1EFF9820ACBA60866077E9B45D57610E14F91E4C034FDF354648C18388592CA850AE9A74232F78893BBA2B9D5876F4D01AF30C446BD5B1A0A0A339A59C3E09B3D0E432E7C18EDB7C6B81C7573BD69859E25FFE57A10012BBC12699742946BB572821A00EDA87B89E59B5D1259019C0BEE3AB809058371354658BF5B6EB40BC8029B6337580EB3A42B3AAACC6F79E5A93ADF65B6720DC55B69B287F6B0CB601C34C1482F880AA9DEB75F8C81C6E4CA8B4B1217816AD44A90E37078396098A562A2C90D61C594B548DD49CBC66C82D10C30F82CE4D1B42274C2BE0350D54882C51D90F6C2B7CBC3887E8346BE654389E8A13D04797A6E998383CCE5413161709BFE6E193E7819110372664F99937E2472FC1B4C727B8595A10800ACD82A2ADED116F42C8CBBF18A9690BC4E2FB5C6831041687696C4388A73CC7197B0543108B6C8C9C9DA9CE5E7B7CC98763B18A6867948721FA42DE612EE9C02F8EF617B3809622A19DEB19A4C8A59E5C9702B8966F728C8B1483A2B6B2568DAB0521A72CF1524DF587905D49076716937C165F02AC53E4924D12C8335267A077D9AD6D1022A9181C319B2217825F51AB632C77736BB5C63CEC2A2ABA0A1F94C8F3F274BDEAB6661157C2C10B92D8CAB859868E22B192DC615A720B8FBA9747903A631B9303E162A8713F292029A7F05B2C1660FBB57C4F326AD99077F5CC09BFD4A10871CB30CB94B795854B62C3BAB83F7E72991A2ABDA41821F661CE2D036ADDF1092BA05A6EEC6AB5AB585A2922A48173D6060F2F211940B14882A3B86C131A526ACD55B099B2E35936966487AB5F673C765B3B72AD18C0FB29153DCB371B15C121D32DA55050392AC8C87C69C3A6B86B163329545513C3A6957279A934089A31923301055A699C533129B2F447435B2CAC2199AD93549B8A86078057AA532FB26B150E3A3EE231CD7CC4C75A260EDE6B7F58E3AD5FA985649B7ACB1AB88509C8D3EB22F3567D56869A5113C76321B7862400C3DA84B940770E09A1DA1792164135A6C4CA82AC166E62B274E3BD6D50ABB4A87781428B6FFCAF91D66FDE068E168B8C8B7139D8E4A2AE2184E5F370DD41BE57584510B773D7222744C0729E122CB4C962B386AA4E2A62F547862648868FEC6E3222CF7034524B60C05B116F3BC45038F5033B5705B829791B1C2A2786A8DEB9024E04605A10932690026CAC16A043AFCE573DE6189002741A1966951EE84FF823AF6AA04E9F45BAD98C9A907C0AACBB440B096802745A2EDA13EB444BE641B2FAEB5F2D72C71191805CAB4726B3CF3CC89BFFE8B030DA805BCC62E957A254BB3E1DB2770B946711514AC96CA7484605562A05562B08D5031705C9539057C441A546A71882EE225F50365D072928A5865FCE655CE4AA206799CB0D497563F008BE7623A9C52256A94A662B9E9C85C0B56BB7049884069A68290459836B5506E73EB8070EAA9230A307B14248B6CD302A469B2C31E815F144A43809BF65F1ABDFC20585102257987FFD0A651FD9C79CB299605CBAB700161E999474B44E06853AC1B0AEEAF3867C1A7757E3373FB39123CA1E6F83BA1DFBC55CF57474DCBCB239983C18A9B8283999D878BE159870255F9CA4C684FC7F33B84E47D79FE409B529794A7A943E6BCCBFCBF2A24FA95CA88587723AB560FB028037247E1BC69A76C7B972692945A70ADB03AF7498961BB1C8D98D90714024798DA81A5640418096836A0294575631619B336FAAFA43ACF914A106CD42268F84919015786D0A8ABDA5AB8A16467E30B86AA5119F77F169E148C825DC8F47784F15C6C93486031332C8372A75F8AAC381FB462AE505676941CD3698D0D68C50750865EC12DB113B188332E37C37439A024EF34F5BF8A1A0D55454C315D48A1C6AD81C3C08A9969B6C3CC76EC2600B62BA342CA488C88B3DE0CAC7110CB6D66062F638100CB44CF94A7A745645E64A3C2D2102472379E3EC01B30181AD60787266BA21B71D7B070BDCE0643B0A79FF661C02C053664192D7D585EE871528641A5E7B723B14440505A69E3B17A6C5511AF785216120997400AFFB8D3871A7B6446B160CAA18698F919610F7028FF3764D5A482182611586562A6E767391282C7FBB4885F41D18477015DB7DE8BA9E36382E34D7549AD72A0A03071E3512F221CE4963B1B4C6449301BBFCE81F9E684890C3B4BD1023BB858284352C94B83A9729B42C590EEEDC902DF3ACA69712EA6BA744ECB57F26753FE61E2906A4C7D4436F49588AD81653A7AD6AB6463078090C15AC40F39A37AC2DCE42A6BA94BDE6899263D15D5810BAF0455DEFB0660C5A0C732C65E72790046329CF387A6D41298A984CE7243937A73A2907249747CB3A60B8980118932CC15BECAE3D035868AA5EEDD9BDC766B1A1E67F03B3CD4C37B10BC530FE16C552D42C023C53087413E2290005E5CED1019FF8426F72A596D95AC119E00C88933E100358B99070BC088390738D4B8917CBDC0D3654635EC079C02603D41A62E74C01CFD2A5B7D9807516594DB30904B3A3066494FCB19F70D032C0D5076FC8115777100653C08866086A1B3ADCC072573B5984530727140EFBC99AEE1CB31F874F530C36A0A6480E511752D1C55ED5B726A9395BC533DD9074A72580BFD25D6F929F8EA89CF9E19F1CAC284AD6C6E444B9E901730A3C809D014C4F8BC335215B7AAA7EFB379DC6C25427D827C151434429670AF237B7D810B9ABCEC6A2B7E6A61D367AAC0C33531E215C46F12B8CBD888A1A45DA009357E2E35FDFD794889EEDA28FFC494FDC73303F1DB4A32B2B7ED888DE8B914BD7B2F28065C1F2DBF4421D4AA7FB3CE591EDB948F2D4B179C70DEA33B6BC2813484E8D9B60CBB7D2D02E26FC01A74B9363485B34E5529173" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "7E09B756B87B9805E0034BF69DE4EA0555C3B435EE338266CFDB1B0D1FD503E4C08AC5F53BAD87BE2D6175370063B23BAB442F9EE170E443FFF3033F3AC56655", + "4760537D8CBA8D01783A48C465ECA42C9390C992181DABCE5BAC3698F865C592034AC90C56FC000F084D67105E90D4A3D207C518E61FC4663471A99F6C1999F3F717556264E227B42D1539DD9285AF880DC42039B81282A372A761F680782B113198868CA71E7C022DD450980409321144139B7B5C2A219E79C95495545966F891E611370A0944D0209FCE566B62B82D11C8BC84016D46E1251B195B60E9AFBE62AD2C687CC247371FD6B82F27324DD2590E5BAA324C3D9670B6644B8FB78C15B689311EB91A089A1C3FB492295A8F09C8AF47356BFE67B0409C4E14592D541A961044A611E9B99914995CD53EF5AB87CD357B0BCC82A7402A29518EE23254FA812BEA3893830410A897BA63A0008EE86585587824F329707137C1C0869831912C065C7F46C0B6CA8BFBA451FC6799576634011871F0E3AD713C237460A78D1C678182A0978156FE7A5094807E61031985C7A289F63D6BCCC40678AA69D8331EB75585C83646B5AE78C66A43F9770AB0A4148167104939A5E691A7FBBCF8939FF7E114256A4236109B13067F77795612B7B8D08C01166921C10CA8F9951C8B87B886159DB8C3C197A27A833561AF9C37D9741EABC5838BDA12DB2C3A97678267BC81FC718917D01622451A27C797495AB1035CCF4EE501DA5AC6C5E202A19320E7912F2AC3A956C33C51931C13970F7702723186101056A11D022BF7526C87C66B99A2C921259E13718A10BB2F0CF7ACDD3689377A75D41284423B3194465A69542CDEA1C63ACC684D1A351D603BBFA28A652595A875B6D0810974BC36920B7A085802AA3B2C2675516B7A0577350F15B9A5EB5465D308D07D216C1E39C05428910DC549357553558B7D77001C372B242D12084AE063D2AB72C397671526360AC0567964CD10A65542861583E61348DA1B0A6085C2EC2D97508911D24BFEA921EEE996861C6E9B32016691CBD7FBA8EF1BC663F62CEA47A2BA989D4E0A47572573B31B411FA862BB2404E8D0C963321626746BAD41397F586DD2BA8698BB6C6CDB79EDC73E22881DC17218FAFA9AA7DA38288154716A8EC9904AEE684AC77C40B922550909B9C7A360F2D50D4840775D1162F9F57737D5314511CB921703D29B7E55A57F1ABC7716700C89AA92307B9ED56B12F84C7376E78EF67CCA81686753CB9B61FA402B96909D20080601A9720C9999B8813CE53203F8A86C9A8DF7A27D56425FE73CA6EFE57C8A5824479665F3388BF133C139688711B36186C7C5303C7038F4309BDA00B4068C27C8A794279928570BDA519702183C69E175823211026664B650C6FBE58CCD295A57E18FC34234A6B15BDC22B6C17642313961DACB50DE79C18F650B27AA9A12B25487739CE715650556A4C1C393FFD5145294A1637A88987B18C0A80979C1AD85A250A1170DD7CCCB8E558DC17C04AFCB658CF0864A8B1C4A2044502948D724732EA17F5D6B96CEA122BB54855A9B80636803F3248F462308361009DB9C558D440D67F8CDC63B5E809128B668B04F353ABCCCB6131CBC714275DD8161CD226AE0B1083D2BBF7BCB0B2AF35BE3443A472A5F4DC4A8CC009D5F7CA9267B378DE82194829095D4BC2AA573A458B60AB9841D256C7405211AC326F050E030E7E8EDBE980E4E94C0AAD40ECF6D83D1C060DE9DF0BB4B7EE9", + "13C958BCF82ED76C18812747B7F583D9AA760E7104B122AA154B9C4532375EF5104A27A08F5BCFBAF05D9999196714840A364AB1F13812499881E97D5E65CBECDCA9C9D0CDCC4643B09B2BD3B8A36BBB493C51113A02423709071E151BF47A519423C6C0217027815BD922B8826B6E7AF99E6EF633B77969DE884A594C7834137EF9618CFA9A1D38DCB115F8863BF2A9E6E92F0DB5021CD20793948ED1D74CF07A970F69293D8BB65651102D84AB69E924AE816128F7C9490574A328CDB0CA82C848621357A8E2F52C800B9C1A35AA815A90576C7F8CAC6FE0C7035FD41FE4ABC90EE6963BBB4D4F94A591C75224D42C77301A00ABA49479417F80AEBEB2C1D9570C5C2052FE47CE7011B5BC12CAC06161CB572E34B60F6A84510E81417D08630565525E278A777BA28C4B7A42A0245AAA34F0918440F348475C7BD0204C4EE72B4B68568AFAC25F2954050530EE87B3D119C243CC851F6549B4C91DE3D84670F7A903B9A3F943B2A7FB7084A73438B716FFC5B73886C0696249F19C2FD3562193C2C8979469E9295BE0488DB575906FB02ED8289B38D01A927BB7A2B13D346A436EE27E564A51C4995867CC6692FA36EFC9CBDC8103A971C42804B28981AD6E1A07F2DA5289DA16F0C1AB5EDA7145351425F3B3AF254D25064170D7806E598EB4EC618D3A3E3867B26E1B854E19797E0CA3EB63AFA24AC2566695B5D76DBF1115CEF8CF83A10ADDF60E10E759D4B34C44D3771DF12C8A2911B011CF8E2214B75A08BF863679EAAE90E8AE4B7B530121C0E5EC042966964C933723D26D2D52C15D4623A01C53F5F426E7D34BC72B47721C0AAB9301F4306848F5349FD22D71C19D1C6B8EC44CA572868B9D1B4EC22C9ED16670075946A613246A28BBE96A499A32A3AF284F1A833E3DABA27CA2C42D4BB650198551744A6B0C68A2046FC0370EDB45C589191B95E96AD92677B0C33FAF371607022C2354BDD2DAA8005D11F3B405414CC013A2A1BCB4B372A8694C7201F9C6920B5BBC1156820980262020971679CA7F70512C627A9DE618A7E233D219111C8989B8007853455F019CA5138530DBE36EFC8A334D6CCC07178516C0CD831275C3029313D66E2D894C8C7697AE7C08524C2196C58E519C3D32D667C0ABAAF260794A70268FF24F10F80D6E25A76F447FE1062CD4FC3BEB4416933C811BB502F9746C5F8876567B177FD8548AC774639BAB6927671721BAC3B22AAB590722061D421782B9A79AF13556AF4B948348B147F2309950634CDCC7BE16C62306428909BE967A54A8784892380EE3FCA79B4373EFB185E806B5C80A49A3A33044902C824C161167678B77CE53C8164BB17E476B535CE401087719B1A15C924881C0FB1B2B90AC154B7FAF8BC17C6B1274C5980E250B3D283E6B703362D67FF81694ADC531FD58838FE66D67EC5A1B6419C3F4AA8D8B3CD2BC3D7CC34DCB972556217E39A63855A58C6080ADE700742576AB836C87545B9C55501219C586FD0B509D30608CB5816427244A589EA96A12709B5221CA768427B25F8A2E4B3C7BED060F1267572F3963DFA64C245B1D1AFB2354F194A803914F101601EB68BD5B9472065DEB27CC11C71F34722047A6A656739B4760537D8CBA8D01783A48C465ECA42C9390C992181DABCE5BAC3698F865C592034AC90C56FC000F084D67105E90D4A3D207C518E61FC4663471A99F6C1999F3F717556264E227B42D1539DD9285AF880DC42039B81282A372A761F680782B113198868CA71E7C022DD450980409321144139B7B5C2A219E79C95495545966F891E611370A0944D0209FCE566B62B82D11C8BC84016D46E1251B195B60E9AFBE62AD2C687CC247371FD6B82F27324DD2590E5BAA324C3D9670B6644B8FB78C15B689311EB91A089A1C3FB492295A8F09C8AF47356BFE67B0409C4E14592D541A961044A611E9B99914995CD53EF5AB87CD357B0BCC82A7402A29518EE23254FA812BEA3893830410A897BA63A0008EE86585587824F329707137C1C0869831912C065C7F46C0B6CA8BFBA451FC6799576634011871F0E3AD713C237460A78D1C678182A0978156FE7A5094807E61031985C7A289F63D6BCCC40678AA69D8331EB75585C83646B5AE78C66A43F9770AB0A4148167104939A5E691A7FBBCF8939FF7E114256A4236109B13067F77795612B7B8D08C01166921C10CA8F9951C8B87B886159DB8C3C197A27A833561AF9C37D9741EABC5838BDA12DB2C3A97678267BC81FC718917D01622451A27C797495AB1035CCF4EE501DA5AC6C5E202A19320E7912F2AC3A956C33C51931C13970F7702723186101056A11D022BF7526C87C66B99A2C921259E13718A10BB2F0CF7ACDD3689377A75D41284423B3194465A69542CDEA1C63ACC684D1A351D603BBFA28A652595A875B6D0810974BC36920B7A085802AA3B2C2675516B7A0577350F15B9A5EB5465D308D07D216C1E39C05428910DC549357553558B7D77001C372B242D12084AE063D2AB72C397671526360AC0567964CD10A65542861583E61348DA1B0A6085C2EC2D97508911D24BFEA921EEE996861C6E9B32016691CBD7FBA8EF1BC663F62CEA47A2BA989D4E0A47572573B31B411FA862BB2404E8D0C963321626746BAD41397F586DD2BA8698BB6C6CDB79EDC73E22881DC17218FAFA9AA7DA38288154716A8EC9904AEE684AC77C40B922550909B9C7A360F2D50D4840775D1162F9F57737D5314511CB921703D29B7E55A57F1ABC7716700C89AA92307B9ED56B12F84C7376E78EF67CCA81686753CB9B61FA402B96909D20080601A9720C9999B8813CE53203F8A86C9A8DF7A27D56425FE73CA6EFE57C8A5824479665F3388BF133C139688711B36186C7C5303C7038F4309BDA00B4068C27C8A794279928570BDA519702183C69E175823211026664B650C6FBE58CCD295A57E18FC34234A6B15BDC22B6C17642313961DACB50DE79C18F650B27AA9A12B25487739CE715650556A4C1C393FFD5145294A1637A88987B18C0A80979C1AD85A250A1170DD7CCCB8E558DC17C04AFCB658CF0864A8B1C4A2044502948D724732EA17F5D6B96CEA122BB54855A9B80636803F3248F462308361009DB9C558D440D67F8CDC63B5E809128B668B04F353ABCCCB6131CBC714275DD8161CD226AE0B1083D2BBF7BCB0B2AF35BE3443A472A5F4DC4A8CC009D5F7CA9267B378DE82194829095D4BC2AA573A458B60AB9841D256C7405211AC326F050E030E7E8EDBE980E4E94C0AAD40ECF6D83D1C060DE9DF0BB4B7EE934E119755019AC71D90C112D9E4B30481E29A4E3497102170612A258AE642BC1C08AC5F53BAD87BE2D6175370063B23BAB442F9EE170E443FFF3033F3AC56655" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "45D079CAE065BE5E094D4D1A3D36AAE4DD2FFF14DD11CC087BF3E1AA03BFB3CCF8652C28EC2F734309C80A0A97C2E341F26BB45F6AE79E72F866F953A9C82714", + "DC085E19BC6265B9343F8861F55C9124854D40C41A4CF633A2BA625EA3B40A071F64034E7D86BEEEA872C8A867A605877F616EF7651A487426F368C8A96B164B064B81599F5ADCA10DC84C78BBA4B93138ED212632C58E48BB4A2D2053D07B63D231B4D9EC5D1DFC6AA82B3B85787108400FDE0BAA9F29568EDAA340028C71AAB2FE48920ECB2C56F19B14DA241B5CA9DA291E26B29CE623A273C7043CC06B590C6DE2E9BEA169A84D4683F4E4692410AE62B84162A5B5C05C4501670D0C8219B57506B708AC6F2B80268454CB45B97B8CBE8D509369C955B4BB71EBB3AA76178BDF439F61D89319857092F772A448620537491ED7A93D1A8B72181544429EAB6A3024860012D122DA61C43E760B91BB93324481F3596D3A9218E69A807B128DC6D645C1B8721D805263241FD78A743920979728B74AC9CC3B850FA0568FD242BDFA9C63A2F14677E779D134946EE05D3236536CFA1EA0E042FAC5834B047FBCC61E8109A06733759CA142AD8AC1D2B8C51F86B7E69765BE722795E7962C03C4DFDB8A8E02AD8F2A6C28F84D49E8C0DBCC9706EA0E0F8776A75C26B34B2E863C7AB13B93DA41A8868A1D04C61C9865C46D07AE354C3AE3EA40A888B1C8759806B575ED6431DDEC51F99AC83BE87FE3DB3A9329A0539A61DF9C0FED93B1D9D90F2D2A2055E062B4869A1ED1C06C92A38CA132504246B7F8BE6C181323C1AD3B373E05BA8091292F3F2697FDC85961783A3467A65A7B0C1A35728D5609F7E605BBD7B1C432A08E390A0602C35A42B6B6AB750E50CF4F5608DFE90E0E8CBC16A94428E85FF550B03CDB0BD1472CB9162EBC1BBECB86A94101C3F4E29D877C12DBC7BDFFC949E32201207181DE2A6850942106768DA641CAEB44BDF13B0F1BB42DC0267751D47D60EB49E2B320B5827180EA7C4830C40AFA58438AB2741B4D7A2280D8028533E3769367ADB9D429EF72B8A8A3AD3C98978D0A472DA9AA7C4081000273C7CC14C146851DB88C56235E14F34BF763CBC4D0316B867B86527F1B0521DF225EF3D950710CC93BAA194D1117FF608319FA2FCDD2662AB182ECE16793FA0CD6755B8A7862C40965119C3DE1BB074F9804D5608F7283ACF1B705F89A2152E6B1D469AA89A7878C101D0BF54E101CBDC7F1491BBB7EA4F147C7BC8497A11BA5317F7392CA02F373ECC96F42D813CCF06A44F05BD74A2347D61B4EABBAD6016A5A037836B142DB0BC88E084445FA83965C87D2E05F66720F5BE69025D3A711F1621EE1918FA97243202B48BA2117E54D08C10F07C40A7B1585AC35191C3A3A5CB1493E551204277AFB5B696DB02F43D2CEB2D901CA515B89E5A4B962B62C93BD9191B75B68740561043429868655B8989A6330231B0AC985226C0951828881093341957178693499D3371A8A41B253C9E848B02B50C57BCA84786ABD0761815A318A94F453D7401B28CB981BD25710B06F323865672B7FCD0A5B69648584153E1FDA2DFB2BA038A62482E20CCD361391635D54E539307925D305574505506E03106286287D303D0096A1A27B7614C37FB6247CB03A016A360F9DA166FC67BD3A457766E911BBFA6FBB9A2103A807EC39A15AA77B7B00551FEC7916E2C27126BF4FCDB67E0E84043F7C76DFD0000675EF04BBC553A790EB73ECCDD203A57F5152", + "36883C1EE235BB379CB7373A3CD275BE5A268983C29E50C09660C496F592DD9B52E7C37E88B906B327BD115A17F989677C08BE3743CEE995B3D198906B119B95019E3E49689083C249FBAD781C7EFE8526418B4A4FAB8DE4B87339F7C05DD30A42CB2E3436ADBBE727B916CE0C163FB4597270F01C4DA53C1EDBBF43165562C1B16FA25516013A173654CB1AB69ADA4E7BE8C3BF2C3EB6D165E2A4160D018B22294AB4B073DEF478BAD35DB73975196C435FAC156838AA9C3BA234457A41164279D95363D6C28080A536A5143667BC35B42B7F8869AA3C3DCF1284C0B652E52194E8192C0590000484459171B2F179C2393CA5964B9E80525D8C1ABC3F888B9347A7B5B82C3C37969A519A4ED09577F025BB58C6F83142350666B0E69C5DE13BA4067046189E5BE3319FCC328804475E5986FDE9A18621385E871E08F9688B484FAA951148FAA67D116C70A41A9D1AA0DDC1C938BB7D8539B820F3020609CBBD09C239E2B8A0212745B21AA3401B130089B2126440036252F26D69E27747BB56AE6429B87993AD15B8B30491E9395922EC55265A9418492B594C6D94F12207F9523134157473347FA27A260C43208CB1DB83AE10F7B0387A3BA40B4161D95167E768D6064C347961C2A09C0085AC70297C6F043D2426CFEFA0A08F2B97429971DEE44F3C142A68075499B0AB326492AEF047204B8CF92044417281A530B6FD0128AF2A77247A692D161CED995ED2A1C25AB93828624793184966DBCE4B70CFE176288F49B3A6BB428294B6B3D9B8D65590A5146C8344A086EC8B24398CE793531D207FF4C9A67718A3D171A0F91151FC20BEC5017F24D3689EBC5E6778BFC5E21B74630805D363C9D46960584A72F91ED395943C0A7A2AF98969A95BB9748F27D459A426975361A412D5CB0E40A6EF312D1E9065F021C1C88A90D89B54A2A9016B806ECB726367353E078089A7ECCB04219BCE3573B73963A6A84D34813913AB00DE53395BB575CCF7C8D026584748CDF13941A9528CED551EA1B50169A38BBDC24CF44B0F4E90A26A9987C2D6B123FB3A3B723EE2392016B09CCB7B673535B4825C282E7220E8CB03DEE3439BB7957B57375C9AC044BBBF030A362C0A05EF2A8167C742AA2476F5D4C4EB848F657BB6CD5A19E4B0B76C94178F934E12022C2107A7EC489A680AC197C42948BC6AB09ABF43A1038640158B92AD5A92BBA9543BF8E770408B7158538EBC170F36D563EF53242DA28E8E3B776F4467BDF7515AC8884305783C00C923266F449B3E6BF445F15886D69B088142205F60A4A8F7CB57710E8BF7ADA6A30CBD312D478700CA6768F06C3A4BD328F4F26083870E2C7CB82583A912879880134E70035357648AFDA95F371634BA0AC752C4962FE0B76E1AC1DA292ED17A0D3B56B816572FCD089E0B0668453B3728A88F53D58CA58672CA0941AF34A88C12351F569991B6549DE49261265A30784EFB7AB5088CCE87E2071BA9758F8A3B43FC63F6801377E69C5520537613C00A80BE36D51898B6824CCB1453758F7AB57D9E2A1EEF2C950A61021ACB98EC607E39D060A3423F27116A53D90717B640E7EAC3A9F11CE5E92B4E2437785B835FD6307E838AE49C1AE48056DC085E19BC6265B9343F8861F55C9124854D40C41A4CF633A2BA625EA3B40A071F64034E7D86BEEEA872C8A867A605877F616EF7651A487426F368C8A96B164B064B81599F5ADCA10DC84C78BBA4B93138ED212632C58E48BB4A2D2053D07B63D231B4D9EC5D1DFC6AA82B3B85787108400FDE0BAA9F29568EDAA340028C71AAB2FE48920ECB2C56F19B14DA241B5CA9DA291E26B29CE623A273C7043CC06B590C6DE2E9BEA169A84D4683F4E4692410AE62B84162A5B5C05C4501670D0C8219B57506B708AC6F2B80268454CB45B97B8CBE8D509369C955B4BB71EBB3AA76178BDF439F61D89319857092F772A448620537491ED7A93D1A8B72181544429EAB6A3024860012D122DA61C43E760B91BB93324481F3596D3A9218E69A807B128DC6D645C1B8721D805263241FD78A743920979728B74AC9CC3B850FA0568FD242BDFA9C63A2F14677E779D134946EE05D3236536CFA1EA0E042FAC5834B047FBCC61E8109A06733759CA142AD8AC1D2B8C51F86B7E69765BE722795E7962C03C4DFDB8A8E02AD8F2A6C28F84D49E8C0DBCC9706EA0E0F8776A75C26B34B2E863C7AB13B93DA41A8868A1D04C61C9865C46D07AE354C3AE3EA40A888B1C8759806B575ED6431DDEC51F99AC83BE87FE3DB3A9329A0539A61DF9C0FED93B1D9D90F2D2A2055E062B4869A1ED1C06C92A38CA132504246B7F8BE6C181323C1AD3B373E05BA8091292F3F2697FDC85961783A3467A65A7B0C1A35728D5609F7E605BBD7B1C432A08E390A0602C35A42B6B6AB750E50CF4F5608DFE90E0E8CBC16A94428E85FF550B03CDB0BD1472CB9162EBC1BBECB86A94101C3F4E29D877C12DBC7BDFFC949E32201207181DE2A6850942106768DA641CAEB44BDF13B0F1BB42DC0267751D47D60EB49E2B320B5827180EA7C4830C40AFA58438AB2741B4D7A2280D8028533E3769367ADB9D429EF72B8A8A3AD3C98978D0A472DA9AA7C4081000273C7CC14C146851DB88C56235E14F34BF763CBC4D0316B867B86527F1B0521DF225EF3D950710CC93BAA194D1117FF608319FA2FCDD2662AB182ECE16793FA0CD6755B8A7862C40965119C3DE1BB074F9804D5608F7283ACF1B705F89A2152E6B1D469AA89A7878C101D0BF54E101CBDC7F1491BBB7EA4F147C7BC8497A11BA5317F7392CA02F373ECC96F42D813CCF06A44F05BD74A2347D61B4EABBAD6016A5A037836B142DB0BC88E084445FA83965C87D2E05F66720F5BE69025D3A711F1621EE1918FA97243202B48BA2117E54D08C10F07C40A7B1585AC35191C3A3A5CB1493E551204277AFB5B696DB02F43D2CEB2D901CA515B89E5A4B962B62C93BD9191B75B68740561043429868655B8989A6330231B0AC985226C0951828881093341957178693499D3371A8A41B253C9E848B02B50C57BCA84786ABD0761815A318A94F453D7401B28CB981BD25710B06F323865672B7FCD0A5B69648584153E1FDA2DFB2BA038A62482E20CCD361391635D54E539307925D305574505506E03106286287D303D0096A1A27B7614C37FB6247CB03A016A360F9DA166FC67BD3A457766E911BBFA6FBB9A2103A807EC39A15AA77B7B00551FEC7916E2C27126BF4FCDB67E0E84043F7C76DFD0000675EF04BBC553A790EB73ECCDD203A57F5152B644348AAD4BAF2C64F830C322180E98396973DAEF3070B78F2E9D59F1883928F8652C28EC2F734309C80A0A97C2E341F26BB45F6AE79E72F866F953A9C82714" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "7E300B66BB2C16A9516CC44CE83929C98A1168444BDAC419E0845E8CEE2D023F0D4553633EE269A829D6941FCE0A36AE3BFABA9941EC79D2944A4924D5407FE5", + "738BC5C23138CCF99BEE78BD874ABA515A2936285678B60DD533A21F3CCC82B36F81B744E3E3325F915DDE071E8C813C07CAA1987033049569B35C72D0F34540D9803BA1A0AB723FC0945ABDA375BC58463E07696327C9CFD9C189916870DBB125C5A7E940789069367E468578650F520B4D1BC693D9465AC53010B9ABABC2385C41309F7C3CB6C39B02938740A4CB29D47B7639F46B99EA2DE8E512F9547EF1CC5221C219C5FA291C4669DEE32C58C06C2CF979E649700DE0C4814CC1AE39ACB6B33B76BAC4BD70AFC102649EC20DD6226FFDE06B2BE92500C8610491C523401E6C029D6F32CC8CB323163094B2780C63074E50F5AA0E2120F3FC6129D304A51310A8B55CA8DB3ABA19719165698694B900DA9E54A0705D6A35B29231E9125B3B218677C6C8A705BE451B6D11A93F04919F59839DE051CE602740BC34CB16F02B8895C66B138B19EA9F8546217B6AC2493A0541F2BD8207CEEEFB023C5373E23AA19DE38FB0A79E9B0067D3354A3632C7A32855F98B99721C5A23E49634582BAA030DCE19A08C77C714B35255A0A472E6474983310D756503F2275CF8C910C910399C335F021DB4EB93CD7C110FEABE1A5418E3C816750B017997B2ED042819E12923917D0AE789730C0447255444A171C597121AD9114630C5FCCAADDC31C652C76A8FF53D98D9A8C959486F7473A9E61378C294EA30638D72836D30659A716FDF91365FFC64CD225353A1C992F8116C869C6CE7C8B29CB145AB08CDE5755D610310D88170F421FB320E50169047C56AB9973AAD1BAE810684DA7BB886284B859BB966CBAF7F0C62E7659CB6C1740096AC061533537C1FE99879C323298C51A3D5D9221BF00C55D4441A77CF6EB646BA45562619BC6437C2C44B25AEEC7E8727BDFA903230F69BC3709D5F1809AB42688BFC55C9D08043A90E3AAC84CD120D84C83D8B013D1E5C02724B8B4FB08B98607BFF64AFFDB06D8FC676A586CBAFA7268DD11BBD2812144BCEEDC538994967D781658250B6F4322963B9A7D46B5AEA411BF3F4AA400B42BF58282D163EBE988A455BB7947A995A27C45F67425813AC75643F1C7C4BFF06289ED853B8887F9C331A7E88C3388790D090829BB6B36B129860C9A10F0610E9F3CDBDD4390AB9879A43BA50A293EEC07E78A4C0F0BCBFA2D140CBB42578081B01A82740179248AA2692C196F5AC55B86933348A39DB3226A45608425343F3C8410BC037BA55AE488831C548510BD570025A1192675A8CEABAFBF9745C480D2596C31E462757E7A4052040C81ABE1BCA03CE731D9DA1060784AE3E34C4D4489346C88154D660B0D2C903888E50EB5371A48603A1548D7891E105C56E8988ED190D950B5BF4EBA7CD9A4FE4357E2E527C9BE28EC05B2DA6681A7D116EBA563EFBB025697868CF2166DDC65BA91062FF1C1C3B9B3E8F3518F7087682B618A499622F7C4E124450A4DA3BB089B99473CC0F9A4C006C17C0D5B44E68B628E250A7FB839D71CBDD6CC87DA36FB28B686C6998A35272CC002FB76A1429FB1166A50626B658163C182685A318834185530474A2556F60C22BA055C6A2B83F9A10F6025DFAF94F8C665593591118B91934E959F51CB850B09880B33F416B6A81CF23AA079E99013B50454AF2E94F6B1B022214C307F8BDE80C55863B", + "517733D08B62D563B01D42C46DDC155D6B17C7B9C169E8420FF2B1C9395100983CD4CC3FA7811FF889B102339BB404436F102BE55276EB36CA82F958F2E777961928C2855A448737D2FB1C5669653690766377C2F037360DDC3A6CD9A4AB86CE8BC4548D27CB60C58AD935852F0938149344195B631AD163216AA02E64824481239B227FB67626581A9E75D587352C74BE47646AE83CABF9194514799C42A835E72E41B43AE6D0C57BA94A8F802660E2A89F44C74CB8BC3E703DA1672A3D43C655FB2D9908BF33983AE7EA8A39CA40FB51245EE150AB387B40D32AF3E55D5AF20A6CE8469B36438D378E41831E30733CD1CB6083EBA36A4016ED9ABC3B100C0B2851805A13FE99019B2A335811AF34103EC415C83A803E1197CC5888625C2907E5D54727BAC32BF2A7211777C758A4067933DC0CBE35809F08385B48B1C26881CC9B414DF3F26C36FC30DBF64768D7C908F5A5ED933842FABF3F1C8E80E37179E80F98B1769AD5626485A005AB02FC8B34BEA2A555D605A22A1F1C4C5F65EC000356A165A4BCB7060C312852C516842E42AFB1B69BDABC484A5002D0B70B7C3998123588F5DA434969CD01D89FD806CF678169DEB784CE09948919757D9B8E49F2428199B91A300E3F96CA21462B31278D590A6DF883933C7724AF7949519C248560BFA5D080E64C288FEB388DB2890EC45BC7334240740551585C57AB7F561724EF4616407C4EFE7A8A1BE369614C5267C6658088A58B01961B98A45CE59222795D2BD231B40B7783A7981A72064DA5320D43B92A244C474058E656ACB85AA7861459D286862C6184BAB6569DA35ABC597B1922AEA48A2C6AE273954AAB4E0B6E5049104AA035CB456518A04B3E56C29BAA7DA39B523C18B2E23BA978179D9CD82C4E7C4FC73C651A61B10BC62EFD11A83180C069398634F341EA724E669815474A8F69301A3FB03A04B25E05D3B9C2A7A0456519C51CC6EFDC61035A749CA6B8E2C79D3FCB238F16638E487BE625AC91521E395928716924D2D3A4C7341897BA1A0DD661D9DC81686CB25FA4293BD937506C444C0C1FAC04BE19CB89F966932A5176DF3910B008220DEB69CED7282B9000E11B6A1C7B0731984FB0A67FB5D9CFA8EB48BE7B1610B4B3DAA07F05519E771316F09B998A1A3B7D463D5C423B24D12C91D6177E35668C1C2179258D9C9C290E23190A140DF04BC8EB26CAE830204D973A677401857AB71863931F1517E6B80CEDBB26AA127012724DC1F98A22856E6724C6A9F36E69894FE7A54D08D6A642056BFBAB498FB252F5044148694727DA205F1824AE8C09D2585823B896AE72694E694B487B008FF99072C27E60C64EEEB9336904C8EED55EF0B4479B49654460C4A15752D6B80B13362E3BAC6C5BF773D141BCE38435DA735C5C590310716C03209A20957D34454B90E8A55737B0FF120E0764CF9E0185364524F5F68F7F741C501621C13AC5ADC254CCB60453C03C9268057C33728A3BAE2D639C39EC447BC82E1079C9D9BC756665285AD9A605F17D0E28A73516C303E082ECBC0DB6339E70B10C84A2ADE45ACDD8770BC5D88D46184EC16CB306A2592E994617BA004B9BB60446527054068926C64242A8096303738BC5C23138CCF99BEE78BD874ABA515A2936285678B60DD533A21F3CCC82B36F81B744E3E3325F915DDE071E8C813C07CAA1987033049569B35C72D0F34540D9803BA1A0AB723FC0945ABDA375BC58463E07696327C9CFD9C189916870DBB125C5A7E940789069367E468578650F520B4D1BC693D9465AC53010B9ABABC2385C41309F7C3CB6C39B02938740A4CB29D47B7639F46B99EA2DE8E512F9547EF1CC5221C219C5FA291C4669DEE32C58C06C2CF979E649700DE0C4814CC1AE39ACB6B33B76BAC4BD70AFC102649EC20DD6226FFDE06B2BE92500C8610491C523401E6C029D6F32CC8CB323163094B2780C63074E50F5AA0E2120F3FC6129D304A51310A8B55CA8DB3ABA19719165698694B900DA9E54A0705D6A35B29231E9125B3B218677C6C8A705BE451B6D11A93F04919F59839DE051CE602740BC34CB16F02B8895C66B138B19EA9F8546217B6AC2493A0541F2BD8207CEEEFB023C5373E23AA19DE38FB0A79E9B0067D3354A3632C7A32855F98B99721C5A23E49634582BAA030DCE19A08C77C714B35255A0A472E6474983310D756503F2275CF8C910C910399C335F021DB4EB93CD7C110FEABE1A5418E3C816750B017997B2ED042819E12923917D0AE789730C0447255444A171C597121AD9114630C5FCCAADDC31C652C76A8FF53D98D9A8C959486F7473A9E61378C294EA30638D72836D30659A716FDF91365FFC64CD225353A1C992F8116C869C6CE7C8B29CB145AB08CDE5755D610310D88170F421FB320E50169047C56AB9973AAD1BAE810684DA7BB886284B859BB966CBAF7F0C62E7659CB6C1740096AC061533537C1FE99879C323298C51A3D5D9221BF00C55D4441A77CF6EB646BA45562619BC6437C2C44B25AEEC7E8727BDFA903230F69BC3709D5F1809AB42688BFC55C9D08043A90E3AAC84CD120D84C83D8B013D1E5C02724B8B4FB08B98607BFF64AFFDB06D8FC676A586CBAFA7268DD11BBD2812144BCEEDC538994967D781658250B6F4322963B9A7D46B5AEA411BF3F4AA400B42BF58282D163EBE988A455BB7947A995A27C45F67425813AC75643F1C7C4BFF06289ED853B8887F9C331A7E88C3388790D090829BB6B36B129860C9A10F0610E9F3CDBDD4390AB9879A43BA50A293EEC07E78A4C0F0BCBFA2D140CBB42578081B01A82740179248AA2692C196F5AC55B86933348A39DB3226A45608425343F3C8410BC037BA55AE488831C548510BD570025A1192675A8CEABAFBF9745C480D2596C31E462757E7A4052040C81ABE1BCA03CE731D9DA1060784AE3E34C4D4489346C88154D660B0D2C903888E50EB5371A48603A1548D7891E105C56E8988ED190D950B5BF4EBA7CD9A4FE4357E2E527C9BE28EC05B2DA6681A7D116EBA563EFBB025697868CF2166DDC65BA91062FF1C1C3B9B3E8F3518F7087682B618A499622F7C4E124450A4DA3BB089B99473CC0F9A4C006C17C0D5B44E68B628E250A7FB839D71CBDD6CC87DA36FB28B686C6998A35272CC002FB76A1429FB1166A50626B658163C182685A318834185530474A2556F60C22BA055C6A2B83F9A10F6025DFAF94F8C665593591118B91934E959F51CB850B09880B33F416B6A81CF23AA079E99013B50454AF2E94F6B1B022214C307F8BDE80C55863BFB07F16368F11AB0BF848FBBFCE5F9CF3E1145E71D6D6A7CAC01CC78E03770AA0D4553633EE269A829D6941FCE0A36AE3BFABA9941EC79D2944A4924D5407FE5" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "CA73AB6AE164B26FA824ACDDCADA823321832E11DBBD83B524D84B9F33AD32F832B452097F559FAE9BA877887A037AE6A8BA3A35F69B111D7C2BBF80124D1720", + "DF947E6354BFE3DA9A921C11744416B285723C1800F50175CC94896B28B79FC6C7722148ACC0CC95259EEA938DB4C81A9A93BC2CA5AD14E27E56145BFA654E02E6093933BDA6321A8069BD0C25C8BC8220E89789AECC7C319888A81B3D34F0A371D85E940610DFA151FB45C63919ABC00C42E46544A2C67F3DFB20BFCB2F93CA26ECC0C6392A4E7D672BC00A560D1456456497F1C52606381F106B9E205733F97AA3BAB588E1F4C90DB61EDE33096D224196D0251B7A50D83B975C669744367D764071C0695AAB1C9E921669091C696109BAAB8B6E2825B41386297D00CCB88BBE27AA1EA810B3D6535978C107AA625A467660994609582655D1A2A64D3AAF59E7B3223A89534B61974430F1630F19E91D8596B4D418619A2725DFD10F24BC64D568A98A11959F7A72D6E53C0D092AABB7A290142DC1A751F6115CDF4350EDBB222BCB165C228F0F40B960DC65BE78813EF165BF69021B5140ACC3824554AF065A15F7EB633BAA3CDDB5655549C8F355BC6DA361D5FA6FA389A53934B24C309DC56765DD7C60A1713C8320AFDDD034DD9220BF4CBBE9597C3638236A009C818A8541F2BF779A6C346880D3307DFFDA5D2F45B921C260CEE80EDEAB6F033001975A3F641794B8E38C3659749F21AFB9E2857AF2099836A42545C8862594AD236567E8B296468D0E267930007E785792BC69A78999B18B152BEDBCB8C1489DA50A4D81FA7986DC29633A8D6C8B9C6BE9C5018C9915FB99C0847DBBC0185E53C6C1A24AA93566F9B8C584B57EA977CD2E3A6841B1C2DA150D1F2412552C2128BC103F41CE33303A01953F6F7787A01B2661C10F35B7076847CCC07CC9D2D49A0780BFDC10A0AE1243105A1EE6508F4D7272178A4C4FA828492913011597EA855CDD9BA07769B254C1A70958159E2490BAE940177C7EDA4051E1C90AABA816D24C059E1477378919C2E77DDE604F37AA526AE73409066D2C28C0376A72F62294ABF720C9F73C8ACC5B8E896A8A3188E93A3CBF526470640A5A1C4A5AA3B57C07BD716315FBA43713BA2F98F889C1A15533706E89447E25012EF01466D995910803346085CC02539EFF5140EEFBC4098B97BB5729A3C29F11E3342CA42FC990933302ACFDC45F19078A881B37A58B27F8172A25E72B893473EE749B12CC64DC446F3C4531A400BCEBAAC116450C44466D8A268EDE093239A758C6A49B5C880F04765A80B92022678D66EA13E0F41079F3C75FA42A54E67EE6D8677E4274CE3161E865A420DC743AA4158076C86D780A964C185890A4D373841D41C618E4039AC419642219234250C735821271B4B7415873C841CB339CBE2AC8791A5D4D54774673AEEBD117DB5CB92C2B15CBF42546F4B1594CB125A12E1B528BF47351B624AEA4F74B0DC55CD276A0302C1BE3B672C121BF7F5424A601C5F039324C8A50A817A684E421249819FC4CB4B698A42AC64D4B32609EC3445DA67F2B120AE6F03466D70D05709C35F87551F382DB318F18C08A4D148E23459A9E15B6A1F3A94B9629A686ACB199628D4340DF1973541B998CA666F4F2C5C69B8A5FD98FCD395AE654AB2BDC70414107DD2BA4ECA3AC25682BA1FB8F86042F10889C2647346529814985B707DB6D8AA10673793DD2E9107CC9BB23EA2098301D646BAE31D56F391E17FF2B", + "B2937BE6B396F5BA5DFDD723F0492EE56AC3E557975D497B8D4C351F4853612B98DBE21260218456475FC8BB9CCA023942563970125B28441E68B46AB5A60E863225A0A644B83B85C026547167AEC8B38C59C466F2C88F52030E8AA793A3B8BC09A441AE50014A1A96D01AC854D559352C698FA5AF527851D50C4CE7C9429AAC5E8DF10919FAAE2A32C0369893065691F4978492FC28BE8950DC7A2374C2B7E7202A2CF370F38A4D38C38A0FD01BFB7B0AEB1C879CA954288C6122C507526C2E08408FFD3917B6420F593B2D8F722368276A6836297911407FA0A41CFCC2A1EB9A43F91D57884EC2207CBD306D4EB00A1E374700C7243E719AACD54FCDA60C07F6BBE7747D6C033546E971696B0ECE2A17A2E729D0892F52495D85699B02201C70186B4401B5AA2C4C1CF52B638C16E3005DE3166CDF4548D4D8A7F07931A1E515351958294638A31BC6611181E9F7216CE7BC559C9384966EBB353111C350DDC6CD009A7E2930790F867587C6AC03624E5AD9CC64BC118FA1C9E61B6DA4E74195399BCA726F29E4C6664A053099B450A74F54439CE9080A13EA7204D10B05553C6D89B66164B873C2773439C132629728F93CB925CE821B59FAF2248A905F2EACB2EAA5AB0CB8C8CBF45D9C8204A5AAB6CD257F2223149C530AE97901E793633909670BD9344DD6CF673C5418096A386AB983569C13803191A9BFA661B29F86296D35CB136CA5EB7468F8213A2C4A515006BBA0D68BEB332878B115F77AB5C240AC5527A7327923EA55C8D3AA9D9B635A0065B6DC70010ED5C956390973DABCC0F025C90A045529237AF55EEC184D94C8C05EA2A0A3D7543A95668C9ABA54846F89023519938467DB0AC8F087A02B54633B4F64B60AA69AB1F3786ECFDAC80DA30ED168C09B67751B632EB5161D79E5B64ED990DCB0C1BE1A4D9799842DAC7AD4998EA76576CC4446C850228FEBBFE172519058BB6A278BB843B6C673CE8391A40101B0C6EB77CEB22278E588B46398B3085D2AEB533C3C2185FB11B9597A4D409BA492580EF669EE9A5F75E54DB1286E43E3C6C3681D1EAB1AB9ACC57E2705A3E782BD20352BB91E53026F51B0663DF88248936734F779406ABED7CC126F591C03D11D46B4CBCA3C2C241A975630A88BF95568F7A1ABA6A37C819D971A6D8E1174593A2288BA099FE28109A53AE5066C0A0A3869F3548E03499AF4C54489218200CDB073B11F040BBDE7C4A8863470F55E7FBBCCEF32A894454F24007C1788AAEE537098C1385771B6AC95810ED19875143857342EAB2C57DE74C3A548B5F10C233F1A4DC2C28813DC6D9AB462C16018C9926D8B60A80A792F475BC9BC84526AA25E5ACC6B2BC305723662E3987836D0A02A5BCB43AB9A97B073280A200003BB36330BE886057E934FA8457E4D4AC8D57072A9732D5A2174E0F28ECBC71203C4A29D10B2B14941D90A4D5E187B367BC5675B4DCB63BA54E61EBDA86714FCCA28422980EC67F05123E65454C91B8C1D3593216B6DCE3CA60A5696BEA14774B49D34F354C6E43CA7E71C89D8966BA017BFA7CF82A82A934488AD38392B24C545DA5E5E6AC91B682AB6194E14827DEE11C8397597D0997C639A64BC4634C46234DF947E6354BFE3DA9A921C11744416B285723C1800F50175CC94896B28B79FC6C7722148ACC0CC95259EEA938DB4C81A9A93BC2CA5AD14E27E56145BFA654E02E6093933BDA6321A8069BD0C25C8BC8220E89789AECC7C319888A81B3D34F0A371D85E940610DFA151FB45C63919ABC00C42E46544A2C67F3DFB20BFCB2F93CA26ECC0C6392A4E7D672BC00A560D1456456497F1C52606381F106B9E205733F97AA3BAB588E1F4C90DB61EDE33096D224196D0251B7A50D83B975C669744367D764071C0695AAB1C9E921669091C696109BAAB8B6E2825B41386297D00CCB88BBE27AA1EA810B3D6535978C107AA625A467660994609582655D1A2A64D3AAF59E7B3223A89534B61974430F1630F19E91D8596B4D418619A2725DFD10F24BC64D568A98A11959F7A72D6E53C0D092AABB7A290142DC1A751F6115CDF4350EDBB222BCB165C228F0F40B960DC65BE78813EF165BF69021B5140ACC3824554AF065A15F7EB633BAA3CDDB5655549C8F355BC6DA361D5FA6FA389A53934B24C309DC56765DD7C60A1713C8320AFDDD034DD9220BF4CBBE9597C3638236A009C818A8541F2BF779A6C346880D3307DFFDA5D2F45B921C260CEE80EDEAB6F033001975A3F641794B8E38C3659749F21AFB9E2857AF2099836A42545C8862594AD236567E8B296468D0E267930007E785792BC69A78999B18B152BEDBCB8C1489DA50A4D81FA7986DC29633A8D6C8B9C6BE9C5018C9915FB99C0847DBBC0185E53C6C1A24AA93566F9B8C584B57EA977CD2E3A6841B1C2DA150D1F2412552C2128BC103F41CE33303A01953F6F7787A01B2661C10F35B7076847CCC07CC9D2D49A0780BFDC10A0AE1243105A1EE6508F4D7272178A4C4FA828492913011597EA855CDD9BA07769B254C1A70958159E2490BAE940177C7EDA4051E1C90AABA816D24C059E1477378919C2E77DDE604F37AA526AE73409066D2C28C0376A72F62294ABF720C9F73C8ACC5B8E896A8A3188E93A3CBF526470640A5A1C4A5AA3B57C07BD716315FBA43713BA2F98F889C1A15533706E89447E25012EF01466D995910803346085CC02539EFF5140EEFBC4098B97BB5729A3C29F11E3342CA42FC990933302ACFDC45F19078A881B37A58B27F8172A25E72B893473EE749B12CC64DC446F3C4531A400BCEBAAC116450C44466D8A268EDE093239A758C6A49B5C880F04765A80B92022678D66EA13E0F41079F3C75FA42A54E67EE6D8677E4274CE3161E865A420DC743AA4158076C86D780A964C185890A4D373841D41C618E4039AC419642219234250C735821271B4B7415873C841CB339CBE2AC8791A5D4D54774673AEEBD117DB5CB92C2B15CBF42546F4B1594CB125A12E1B528BF47351B624AEA4F74B0DC55CD276A0302C1BE3B672C121BF7F5424A601C5F039324C8A50A817A684E421249819FC4CB4B698A42AC64D4B32609EC3445DA67F2B120AE6F03466D70D05709C35F87551F382DB318F18C08A4D148E23459A9E15B6A1F3A94B9629A686ACB199628D4340DF1973541B998CA666F4F2C5C69B8A5FD98FCD395AE654AB2BDC70414107DD2BA4ECA3AC25682BA1FB8F86042F10889C2647346529814985B707DB6D8AA10673793DD2E9107CC9BB23EA2098301D646BAE31D56F391E17FF2B7BC869F739CA75EC8845BA6691836890BA808F91CC00A04918C2E7AD3011835932B452097F559FAE9BA877887A037AE6A8BA3A35F69B111D7C2BBF80124D1720" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "CC365FFA8E50DE9C82952DDDC59A62EFB5E2BB17F84BC28348A6767025694C296EC3011D0FEC9D7EEADB23251709DAC2160AFDAEDEA1BECD546EE72BCFC878A6", + "63D8A297653772364A1A69CDB7E0648513939ED323B1C1B756B28F37F95FB50C5DC901B278A16AEDF3A7BA514F6FB770B166697CC9B4B83A6D98A10B84239E256A4CE8D6AD4407311156A8165898CD52519B6B925BF14D25CBB03F966B9819B7CF71253A16C796691626E4831149A6EDC7B3CD2C2777474D02B17BDDBA1C43B7CBFB1B17DDAA6D8A58CD29EC999752A5205A751D17415198875F19862BA75A7D1B3EBABA13066753E5434B497A00FAB5BAC69C78BB0842F50ACC3464781B423734852EC99573F54522920659C0E3412E7762F451A0CB002BC67047976347F68183BAD213B5E0689A872D1EBA6DF5A664AAC25E3037604B3934EDD828690A3387F99B73E2A60A169E3486212B09CA72CB6C6AC7CFB026A5DA8673701A395416509AC396DEB1A6BAF90AC194024A46C59DA7C726790C022A7EB31C3CE4E1C83944A37A46CF3E0866832B221E6C2C6AE5CA61E996E5DB5759A0476F3AA35828ADC7D73F0D788400134D46CC177CF3CAF5442DA58012F6C708DB417F92174925EBA93C27A9A0995C82E8BFBEA67403338A16199B185C241AF94A842A697A966675822957CACED027539BC75E381124E98C1AFE2A2FDDF212D0E88548E20EBE097BBF311805B42B1C6158FEB9309D2B2D2413C415A44C03F1673D1192BD5B2420744CC641516A154AC6EA48D38792ECFA6887F273D37837F89B8F58A9322E6179A27601562B5D76637E97796524E413A3D1A64711BDCB03113B09BD4C642B22F1C30BB73633FB12602658160C3B163229EC78091D8C8F20183206E2784A9B2F63A9CD09009D42979794AB77D9A570F7D42CC6506A001834F089BFCCB802778638DAD9950FD706675BB891EC765289B313ABBEA80C58E629A87A4737911085B29C2EC0098FDFBC2D9E091EFD238699ECCC1AF81083D46652827E4330472981BA9ECB77A36083E93624516661D959118FECAC6E3746EED74258517EAD71134B455C995615DF1A736E94A581C3B5844C1CB1B46FE89AB3A0635669B064525B262B246E0C985102DA87FA85B8CE24944F13769CD178C6CA0715720541C41ECA8B7CEE8CC2BE5794F9C9A393EBCB79669C4DFA2401B673EAF721551B81BB81666113CB1631BB01583DE5088E8E645CF39B85C31A8A06285A9F54CE785BCD32385FDF2B1EA92A233D4B27EFCC0649E8909993517F57308593B7706184AF568F0BE94C83E57CDF0AC9186C894CBCAF7C031AE322B96C1779907054004A0448B0BE3207CFC76476B73165B4198F963B0AF23A7DBDE51D3216C83476384E31CF0033005388B91564A94E044E95E0152CBA8337408B03E643E7ACA233E95C0116A252D97BA2D19E5BB97521AC5321EB217A8ACEA04712C0179633475B29A81CAF6243A2B57DB3487152615541A5C65AE8C016C439C509741446293078C9129773B268B3E112AEB8A8A2F42C4C60D46AF12A58CC670E9080693369BF48D414B6629DA4074B906B3E174992979A0F91A6081B9AB203B00B885862908A29FB73CA4EC123A8A6101DC235D8112C0FF23D2D85937372725EC6B266E42BB737B9830AB5C428BF44A15C0331ACE72A2B0DCBBB3E2646AA83893454932AE94C0C6C1E6DC22A3E47A79844A8A2B30268E1CB07E9EB4B150EE4AD75F407581F2A12802042A750E0F48F5AE869", + "7B4B1FBDF530E24329D91A43839808B73485A2A44BDDE0A7D252522E15AC674824CF787B64B6C5BE8915347155206C80127223F0A42694A5749E1113778560FBB446A264BF21FA026AD48A288A46CAFB55A265530B67C8D2BAC61DA7A4D083BD703B6DB074007F9800B30B7521A0BB8B82B1336AB2A43B67D69A7E980C53C70A9F656485A26A17D1E9AFDFAACD4A670A39DB6FC737C577D2BC6905CF7D76368A53AF9302B4F10C50BF0034AB57B382F52F54A34C849C6BD03A29C6A91E8A384330C5836758CF88A3CB995422CCFCCAC56107952799E8FB038EF169BF5A157809541618BE93372D37259C321B1496A3AB7D436517E5AC6EDABFE54ACA12513EDDF6B878D216251B79EE083800C565DD35749D4A16D16C8CAB996DF942C9D5527247745F3915CC973801F3AAAFB7E09F30F56A2565ACB859C6197C79AE9BB8BAEA4863C5B26652207F1B42B06959FBC971154775A5677FA3083FC532B17E5315A35448DAF00413956C3967A5F8436540B543F6231E112296748C7992EB709AC8A2EDD38EB8E0152DF49A1CDA8C719C21CC8712F29B01442B1E95F90749944215D90762C270BE379397C00433A2B2E0192A6A6837F66A122AFB2DE3106747571DF0DC075B18309166178FC0575BF124AAC7A750BA441F8CC37C1BC23E180A7EB005EE9037BAAA581BEB67F8C92ACF999F68730B8E847137B5A9B917B03FE016DF9CAE86F42EE3C79BB89A12FADB6CCA00890172A74A219FD0C06ACFD6B7E51C80C959038F694AA418AC4AC51522F81448A21113B17F7D409E4593836A51C68469C9771BC184298DB73858F4B882076106609C722CB317ECB40034C4A638501DB52628116A9F9A169542C688EF00064F18A334D90D4FABB91CB56B691543600603FA124D6F4590B8405DECEC5BD7D8BBE81B8AEAB6A93761C62F6237FC05BC205A8A4428A2115AC45012A683ABA415EB2DE7859014506CA12900E683183BB8ADD7E587FBD97F1250540AB93949825D2E67C7B7C5084A0236CB4C84CFFB650AB6211E7C8016F29A3FB1AA87C9C5B55753A2B182D7220290C39EB54C57F9F889A8F694B8541A94D72F31459711B58EC3E13232B9233781B618D078684BB1E866AEDBB26233A4B93655CB145C2317174E7D4C2BA4450505F5129DF1291D5093282512F5FA865D250E95B569919467BE82A9D5D1C6CAD53A4933BA8E97A9FB4C294F270422B1064B7BAB9F1C39460CA7D77A728124A97A61BF35B19542D2C80E6A4274075562344CBA32985AD48B8166B4A9B48C14C8BB079C0649A139EB614CACEA598682450B458AA3A890B42828C416A7C5DBBEE2DA687CC879727821FE482838FC02C1596BE6999027B595FC75BCFD2B226648A0B22C057FB0368C213FE7093977B3B0DD48C035B8C72CD64A1D81337563CB3BACC3B229A7F153C5A6D0252BE45E797A139E660D761627FE309B50B973A873924853B7D41C692B6B6262800C4DC7847C510049BCBD753444968B012083A6AB25208155027BE830CE51BE2FB713406B7A312091D49031A80861D1D9B5C17C2CE9751E5A480D6F13882A620B7F99C4E26C9D174892BB7877C080232E487C88925F8F6A4118EBB8B4BC30D2A1617D040563D8A297653772364A1A69CDB7E0648513939ED323B1C1B756B28F37F95FB50C5DC901B278A16AEDF3A7BA514F6FB770B166697CC9B4B83A6D98A10B84239E256A4CE8D6AD4407311156A8165898CD52519B6B925BF14D25CBB03F966B9819B7CF71253A16C796691626E4831149A6EDC7B3CD2C2777474D02B17BDDBA1C43B7CBFB1B17DDAA6D8A58CD29EC999752A5205A751D17415198875F19862BA75A7D1B3EBABA13066753E5434B497A00FAB5BAC69C78BB0842F50ACC3464781B423734852EC99573F54522920659C0E3412E7762F451A0CB002BC67047976347F68183BAD213B5E0689A872D1EBA6DF5A664AAC25E3037604B3934EDD828690A3387F99B73E2A60A169E3486212B09CA72CB6C6AC7CFB026A5DA8673701A395416509AC396DEB1A6BAF90AC194024A46C59DA7C726790C022A7EB31C3CE4E1C83944A37A46CF3E0866832B221E6C2C6AE5CA61E996E5DB5759A0476F3AA35828ADC7D73F0D788400134D46CC177CF3CAF5442DA58012F6C708DB417F92174925EBA93C27A9A0995C82E8BFBEA67403338A16199B185C241AF94A842A697A966675822957CACED027539BC75E381124E98C1AFE2A2FDDF212D0E88548E20EBE097BBF311805B42B1C6158FEB9309D2B2D2413C415A44C03F1673D1192BD5B2420744CC641516A154AC6EA48D38792ECFA6887F273D37837F89B8F58A9322E6179A27601562B5D76637E97796524E413A3D1A64711BDCB03113B09BD4C642B22F1C30BB73633FB12602658160C3B163229EC78091D8C8F20183206E2784A9B2F63A9CD09009D42979794AB77D9A570F7D42CC6506A001834F089BFCCB802778638DAD9950FD706675BB891EC765289B313ABBEA80C58E629A87A4737911085B29C2EC0098FDFBC2D9E091EFD238699ECCC1AF81083D46652827E4330472981BA9ECB77A36083E93624516661D959118FECAC6E3746EED74258517EAD71134B455C995615DF1A736E94A581C3B5844C1CB1B46FE89AB3A0635669B064525B262B246E0C985102DA87FA85B8CE24944F13769CD178C6CA0715720541C41ECA8B7CEE8CC2BE5794F9C9A393EBCB79669C4DFA2401B673EAF721551B81BB81666113CB1631BB01583DE5088E8E645CF39B85C31A8A06285A9F54CE785BCD32385FDF2B1EA92A233D4B27EFCC0649E8909993517F57308593B7706184AF568F0BE94C83E57CDF0AC9186C894CBCAF7C031AE322B96C1779907054004A0448B0BE3207CFC76476B73165B4198F963B0AF23A7DBDE51D3216C83476384E31CF0033005388B91564A94E044E95E0152CBA8337408B03E643E7ACA233E95C0116A252D97BA2D19E5BB97521AC5321EB217A8ACEA04712C0179633475B29A81CAF6243A2B57DB3487152615541A5C65AE8C016C439C509741446293078C9129773B268B3E112AEB8A8A2F42C4C60D46AF12A58CC670E9080693369BF48D414B6629DA4074B906B3E174992979A0F91A6081B9AB203B00B885862908A29FB73CA4EC123A8A6101DC235D8112C0FF23D2D85937372725EC6B266E42BB737B9830AB5C428BF44A15C0331ACE72A2B0DCBBB3E2646AA83893454932AE94C0C6C1E6DC22A3E47A79844A8A2B30268E1CB07E9EB4B150EE4AD75F407581F2A12802042A750E0F48F5AE869C27D3ECE8BA4738ABADA8727FA4653FC9BAED0BEE42E15D1536899AA7BF1F2406EC3011D0FEC9D7EEADB23251709DAC2160AFDAEDEA1BECD546EE72BCFC878A6" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "8C92561EE865C444AAA930C5AC586329A834CC6E138ED263633BC8022613525A9B40773133DFE20768CD271350DD0D5C4D6F38289A1B2603C48AFECB6D2C12D1", + "FA83712BABBE08959F65842ED6F7CEDFD0201047B6BE4C35D7C26EBA204CE0CBA57A317632762D5B4965CCA9678DE4A1357B2AB1C72760022EBB13A6D9C561CC3799174B3A82D76488141E825A0ECF0B21B659AC5973C2FEC40FAE53A23A1295C1F773D389917DE59A8EE6A673DA8EF98C764BBC1F1F0628FA11A77E273995C812BBFA36E8C379FA8B09BAD80ADE06B61BC4499113619CE9C803F834CA4B813AE96552E29163B81182C13438EB07CBD8A3A316AC21B07581137C5E8B431BF043F1E6B9308C6BAEA459C9D251F42A7A7AA481908176F1573665C6B1988380F0BBC4A33896AE57B3D0884197388E81F082E7A85B36AA911DD6CD48AA20CEB676065231A51588225B756ABBA633D92D98083ABC54BD8636798D0ABA708147E5A331739A35F6A17B5EC86C73BC8F5BC05F909CC877EBB132B6B428221689C23C13EA6A2971434704600BD82893045F98C1BADB578DEAD97062529E190C06E389457000AC10027919956D0304A8B039925823A775E67E62E85673AC9A074442C412C9D02C2972F33088562AD3608130F132D6843AE8B818F7621A4FA54C5EAB038A2710F805143F3C6C7A165E8F106B1B2C66AEA6015BD42A8ED115C7357F7BF3C0C1D612F432380BF0A145933789D5CAE176A2B622550ED2884C65C3FDE52E07EBC9BD651B31D9CEC63661E1A460D682C1B013B7AF114B2718ABDE4B55DC975328C80CA3C618DCEA4F1B71BA396503766896B7314370C46630003386D790A07A4B18003E278558A1E820209635291A600379286A744B2B9053A54B05A47CB27D093B299B50AED682438C1A35C70A7C769A811618A477CC7E660DAF72B8C20B3571B85BDED1B2FCA89299E8675472259C29523F62152552C66631A658814B26822EB01533867B2076064F47C7712A6A5A965814E3A81DC040A5E35036396B6CC3F5450BD80BCD9360A1FC1AD3EB5CBFF0577FDA98A3F1694DC1789743AF0FA236F0016A1E716C92E10550FA3139B7575EF92F13A3A8C00053C2222121A69399D1BBBCA9C84C26472B2B592FEC50451A491702996F203E28FB4D728B9B5123CEEB805A9555B9E79726C128868E073F381010E8D14892052EE94C8A3A78BA5EB2978EE14F83376E1AE74107EAB6E2F18B008ACB840075ED15A49231BAAD0790177B3DA9C8081332BC56E72C09018758E46495EB9E17CA4C44A4CBF9F80840A2434FE1C9E94152CB5B577E788F9AF2531A429D0A611618B14C8B67267C8279ABC6A4F897B98D07731E6A9AD6BC42921CC966E6AC0508307EC66499F578AED632664537C3844285816278C58C05665AE39579BE5076EF4993CB0162D050901BF1A32CB397EA9071D1789C99699DE4050C33F98AD9797A0C402477357DA51CC795F616EA928C8566084BEB59582883694B96902953F92B1E6016B20112614FCA9328693BE30846203103E2AA6098106C7D6A376FD39557FA799B72A677181978D11A87A9898F15126E134ECD898C5710817355511505D080BA26FE4201DEAA2806E9317BF1494579C336118EDD2BAF09A2C505CA866876A6CEB1A99C809A7D239BA05A225EABB57EE7A3E31788587C8027B47664048DB690368C249EF5498AA1830C06E614D764809748B1D795EA7A0695F5EE5361699D34830FDBC0495429B1DCFBD52899", + "F357C34B0A88C7841E51A4BD61C196CAB78F674A8E7E6B762E9431AFE374DFBA65C0441978F52D37B215E94A85E71A67E7A90D244194DB42A23F49AFEF31C83CAA45CA8730A9F5AAC10A067FF585344A93ABE1A0CC3BCFAE6570B1F4663BFA6179E684B3036BFDF11972D65B6F2350C2048801E8CBF1FC392A760BF8508CEF51CA8553473CB7C2D5E0C5109AA91E118154F2AA636C4A64F4138B42AF078A29731810D91B5381A12C56784BC6D514D0922341835CD8D332DB1C90F93C7891DC85DCEB41D020CEF107290D5A5F9A662EFB48C96880231AB122A5DA2CEB3B482089B650502945AA9EFFD1B598A6061ED872B02823A484057967912132BEA1C20B8264B8491881A87385F8D75B8E823B583506E566B0499C32C345CBC5DB08F073777834C329AAA0BAF6A8565031D6DA4AA4B77B9D155275463002833B9D944AC62ABD89B6142960703D66577B42A281407081DA124DB36ADF5B29FF439F9BC51CEB2BA9EEAB248745BA0A00B7345A744F44021527075E7B37E279B6DAB68AEF69A34F907D0AC792B1288438C93647C5BBD2639510134A8ABB32FB0164AF50791F333FDF89A14C5063D1C357BC116CEE5ACE85DB524BB212732BCF2E733F2E206DC98658731AA375745935BAADAD94CE2C2560FB04218619457E589D7F54A7FEEA219D8C64D7653DD764074ADCCA60571946F45AC049CE8591777EA5315B56CD301C9D089B67F79326BD85A317F30BEBD6834CE9B85F854F0ADB8F2576583572BE22DA0A787867E300CC8445AAC20A8867B057566343CCB327CB34C09F15A03372AA80F607BD538ACC83BD47AA155B1011E92AA97AFAA1453068A1D71C179005E5DB512DE13539736EB9D4830363B1F5AA1122D5BE39507236BCC70FF94B30425413525FA550C49AB731EBC9BCA46C7736F59C4BC31547F35FDE8CC6F5C9AACC3147EFF6C073E4633A15A3ED61247C1602DCA5A08A252427273BA8EC196D9243F6824145F544C645ADEE53A8E6835985B36766E12AB9D88C06180E65919A4485B72710A80744064B79B4818BB66121C5EF2280D6660D2E632342013F6E73265048647CEB1C104187235443E443269B0B8E51F93F1F7958D1C0CC9725148BC514507A784DB21285916B418273432C39A1E56C99F00AB4D6401A2B6E26577498A6CB4769BBE15618E84895990B41B337581DE9687DD68EB00A91D63A6B027A5F2ED67418D5908BCBAD54D23DA46A8908286C80EB9D1D1C7DE6017723DB0F5F877B46287770F721203843D4E621702622B4693E4790CD1BFA7FC02A399B0797313C11BCF2BDC997C06E2053EC074CC0493529B9A9643C02FF33066717069576B7EE094FF191C3DC8100D451C8A0E99C8A49BF47952D6A5A3E0AFB8C610108022471065666338868007645A679B860513A25C6C44C4A014AB75A3B27A4673B6E39B45E8A874C97C764893C31B7D850558AC26A5503C2715C86874DFF64347101123BF72C106238A25595B1B070087151609736F08C3FFC0648A83B81D55C5BC9F7742669A317505F0AF7250348C96D6227E8237C9CF852D1F57F08346D0DFBA8B99C18A78BC77D0A7002A081A181AA83C7C4DED755625B89F2ACBFE5E227EE779FADD961FA83712BABBE08959F65842ED6F7CEDFD0201047B6BE4C35D7C26EBA204CE0CBA57A317632762D5B4965CCA9678DE4A1357B2AB1C72760022EBB13A6D9C561CC3799174B3A82D76488141E825A0ECF0B21B659AC5973C2FEC40FAE53A23A1295C1F773D389917DE59A8EE6A673DA8EF98C764BBC1F1F0628FA11A77E273995C812BBFA36E8C379FA8B09BAD80ADE06B61BC4499113619CE9C803F834CA4B813AE96552E29163B81182C13438EB07CBD8A3A316AC21B07581137C5E8B431BF043F1E6B9308C6BAEA459C9D251F42A7A7AA481908176F1573665C6B1988380F0BBC4A33896AE57B3D0884197388E81F082E7A85B36AA911DD6CD48AA20CEB676065231A51588225B756ABBA633D92D98083ABC54BD8636798D0ABA708147E5A331739A35F6A17B5EC86C73BC8F5BC05F909CC877EBB132B6B428221689C23C13EA6A2971434704600BD82893045F98C1BADB578DEAD97062529E190C06E389457000AC10027919956D0304A8B039925823A775E67E62E85673AC9A074442C412C9D02C2972F33088562AD3608130F132D6843AE8B818F7621A4FA54C5EAB038A2710F805143F3C6C7A165E8F106B1B2C66AEA6015BD42A8ED115C7357F7BF3C0C1D612F432380BF0A145933789D5CAE176A2B622550ED2884C65C3FDE52E07EBC9BD651B31D9CEC63661E1A460D682C1B013B7AF114B2718ABDE4B55DC975328C80CA3C618DCEA4F1B71BA396503766896B7314370C46630003386D790A07A4B18003E278558A1E820209635291A600379286A744B2B9053A54B05A47CB27D093B299B50AED682438C1A35C70A7C769A811618A477CC7E660DAF72B8C20B3571B85BDED1B2FCA89299E8675472259C29523F62152552C66631A658814B26822EB01533867B2076064F47C7712A6A5A965814E3A81DC040A5E35036396B6CC3F5450BD80BCD9360A1FC1AD3EB5CBFF0577FDA98A3F1694DC1789743AF0FA236F0016A1E716C92E10550FA3139B7575EF92F13A3A8C00053C2222121A69399D1BBBCA9C84C26472B2B592FEC50451A491702996F203E28FB4D728B9B5123CEEB805A9555B9E79726C128868E073F381010E8D14892052EE94C8A3A78BA5EB2978EE14F83376E1AE74107EAB6E2F18B008ACB840075ED15A49231BAAD0790177B3DA9C8081332BC56E72C09018758E46495EB9E17CA4C44A4CBF9F80840A2434FE1C9E94152CB5B577E788F9AF2531A429D0A611618B14C8B67267C8279ABC6A4F897B98D07731E6A9AD6BC42921CC966E6AC0508307EC66499F578AED632664537C3844285816278C58C05665AE39579BE5076EF4993CB0162D050901BF1A32CB397EA9071D1789C99699DE4050C33F98AD9797A0C402477357DA51CC795F616EA928C8566084BEB59582883694B96902953F92B1E6016B20112614FCA9328693BE30846203103E2AA6098106C7D6A376FD39557FA799B72A677181978D11A87A9898F15126E134ECD898C5710817355511505D080BA26FE4201DEAA2806E9317BF1494579C336118EDD2BAF09A2C505CA866876A6CEB1A99C809A7D239BA05A225EABB57EE7A3E31788587C8027B47664048DB690368C249EF5498AA1830C06E614D764809748B1D795EA7A0695F5EE5361699D34830FDBC0495429B1DCFBD52899FA1F76F2C7C615FEA2F4425E92C40B758A79C354ECD7B5EB8EB4F8495370F2779B40773133DFE20768CD271350DD0D5C4D6F38289A1B2603C48AFECB6D2C12D1" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "77C4BCABE807024B08467EF75449EA214D81C4F4DFC30DD8A4AEEA8643A86DCC4BFD6EEDC0F4DD25419F843524D730011ABB427B46496FE5B17DA0C52D44EB8C", + "1EE81E4FD69B51973A232C174ABAA6CC51CFB82C0B90483717646E2C5A8BC4B444FCFA05989A65CE2A58D53C9D8152052678293FE68CB757A4D3CC859F283A8D320FBCE38C53495FF5635690D94287527385961F77E71D2B011E44F966718111EB4B7C05608F35B14D0E310980F705C273BF3C720C796864D88821F4940CE6C47D5FE717AEC2499BB98E163858181A3703D01DCB4A55DB238F7D36B374F03937699D1F7A6B562B573456518DE18846A7A1191BBB53A3059CB369837A4051840C21EA82EDA81E927CB0C9594468D1998E610D7DD411CA709CE5DB0D0EC199702C924D8ACAFEBC68FA0811FFD41573594A889B53215524254434E0F50E54B190147A29230A9438F3B3B4470A0993B82B742F09C47DCDFC213519A7A2581A21CB72AC65A04204AC4753576EE3C1F9507AEB34A1ED2C1CA9D275B69CB9D1F584A0E02E53C861DE3590856AC0C7907243903A0D6B5EC85037EC33250CCAA906298FDA1A3A44D67908EB40F31773F307202A36B214D69A7A47AB9EC42746B8C009950FFA1949CADA0C1E77B363E075FB13C79E784AB45804775A04C400A29CA47EC384398FF704F5737303084C5A4A804920846ED0922F0ABFA7B88C276BBCBFE99524CACF6453948BA0563963A69F9ACC4ADA2235F66AFBA3A08DB10133D00AE74B89AA929011108CE9203E0B1B60E9E8A877EC0DBE6A24CD636606DC500D05054184CBE298805B4C74F3402EFD35127157884477B9301527A65927A6474B150C0F3B9B17E864B5D890BCCFF967D2F8256BE764852054C02983810A81779BC08B47A29E6A024C842B5D0C16ADC95273C9B61F3A08C62C3BC2C3CD24411ECF510C46466A5DD8705AF80869BBB1D0D583AB29B48923AD24844D39E23F2750080C272847F1C24896628B4A2C73D6005FF8A19F817DF8C3068654CCB61C4AC57427C1BB4F51E5BD0B552928197E6F977303448BA4627C56696428B54A57CAA60C9A42A0A544EEA50C4FE21989AA16317222E435B80D9B3FB11016F92B8E988A77D6D4712B05CBEF15153DB4B687B17B21E50377D43D771249E02A4450A481D1F194484B80341CBE51B85E01F6022E244A6D984472952F8945A3DEFB59D5450651884B3A6C041B272F8D8A45AAD56D7B33574A77BB6E30250DA691E4638E68923995763EEF05CA33A9285B364797EA04A1487D15C309A78337EE321C0BB6CC73117FA50A627F877348E5CFA4107CEFD0AE762966170B160801033E119837C474E7CA06D99749940322FDE4038C0BBF65F462C2D08906367FCEC14CAD467B0567520A57521213C30FB5001650661FFAACF683B561054663814136B49DCC627E29A65CF1320857A7B3C07687ABA2749ED7B9B6488402D0A4829A45CA614D23D712591B7B457119DB2B6184F442B44830DDC537FD7376C00B96C18698C108CC58154D0A239C53C94416146660F0CFE4273D7D783F9F39076EDB9D34E0835958902C03C76976A1B6A73A20A97652D5281F925C923A553E79A3C6087183A42138EC521B209207261E7DBB5057A4B9B589456DA59708144AB8042717890D652B74BF1C38CB178E3CF3499B018E8AFA877EA31A4E9BA54825207133AF99EA2E432CC04293655059AF6BB45C33D6F7539D3A48B51362884040FEA99E8FFCBD5AE96635216B8660278F", + "75F74B4F338B06B4036512B9A2E60408652F8DB34D280A332ED42044A6917121687E6457D07405EDA12817D66537F3B9FD92520AD52DD564CFD57C8C26CC29E226B7642C8D4679A9F37079219660A8C4C642B783055873F60BCB6018834A1BBC86B55DF61555B1B83935406A0B0692B0958E0E8BAC5F24B6591C7F045052E12C0F268B03B27707785A8B24A7A94C058032D481E6C63725FAC96D0755E165A01E0146195465407319581C70EFBC448AB510844B5763DB35314995FD41199223759CAA79F28447D9DC1F15A2165E5C3FFEC323B9388C6C6551F5A50B7A33BA5472BEB4D5CC6B232BB89918664AAA70D6557AB7B0A14A7BA15509A5BC7CEFF073C26ACD1D649272ABC1AE796C337B08C3F021F5770555E593D7F65FD1C87F7D76B5B7C799BA95538B76378C81091E56BDC1FC03332B30D8AA1CA72410AE6827C809A12E9646881A4FA709228F2C3AAA05B988A3C2CEE603F5C44C25A5032A9C20014A9C5BC3CC99D83C42E1B79994C27E0B4E074867EBD41CB97630A0342AC962A291A40A77B82E590C791824BE28931848463AC9A0427F0810A2D7517CB97EA0992ABD954DE6878B4EC03EA6482F0C3A0CD4E584DCB79D8271197F254979EBB3B609A789F2B77BD503BEFB9EE996861F82B18BB957FF734A36E206575B6377927A9AF6A07623A341C1944CE392D0B3321959C1D6E6B4D5E93451D1122C98B92903B81C892B2C84A0098B775848A56E27CF59A49B67D706AF8B09B82B867BB155F46A635960CEEEE4432E8526D20751542CB1F4E5AF364755CB7A804B43CB39B0A1F2A60BF52ABA8A91B90E8A19710577E6B9268ED71C94B29338F894B084CBA555C1DAA2B7D082A9D7EBB0A624013D722095839BDBA38BE4A4ACD2B7886CD88C33C393085A43F7046C55151EEF203ACBA47E21E9BB65D09FE8328A234C56203A9AB3486CD66A4257B453EA8C7561895397F16C92710FDDC06297DAA3F563C87B8B623624C9C2A468BE54312535ADEB891A82869D5CDA6892A8670A3504ABE1729635CD2C73A2379CABA8A1A3CE076A3A0481E0F3456D37B1AE7BB29F715309FA92EF43390B63A113E855D9F815DD5C40B8A0AFAEE1935024B14105A2B6019137BA99751189261132D16B2BC2F767DAD847F1098C9E0940F4D5124BE27E1836BE70F258E54BB26AF060C4D6059AAA621504A45C18B9F9578F2DF3671EC78E0FC9924BE790FC72CC9DB49ACEC2246DD10F1E1A9590C52580D0C33A2A47A65B903EE7B4B0B385248899F15834F7C09CDD05AA495B5839E23BEF2770A15B02FAB83BA88283C73C70E2433C86D2B88355C4932201838106F83B3CA103709CB636F3047C75E7728E4049E0E09A2CDB315D51713F24A3033B9A5CAB679996490B946EEEBCCF6900A43786B6F00CB627375EE1A96E7B0BB1B878A357C0CBA585626323CB48255B3E5B4B6F561B842831D1A700A880CD12D1B49ECAB8A9E6CDE0F768B86112056CA1299B7A9E7C0D3FF000BBD68BACF3A20D3973701BA1479B49369944B4FC991A21A003405D98C87D37C88EF9A10231D52FBE0A012D18C3824B6DF5C82959C9C3F97169979547B1019980A4B8CF706CC9C274242C637958278900C608BB811EE81E4FD69B51973A232C174ABAA6CC51CFB82C0B90483717646E2C5A8BC4B444FCFA05989A65CE2A58D53C9D8152052678293FE68CB757A4D3CC859F283A8D320FBCE38C53495FF5635690D94287527385961F77E71D2B011E44F966718111EB4B7C05608F35B14D0E310980F705C273BF3C720C796864D88821F4940CE6C47D5FE717AEC2499BB98E163858181A3703D01DCB4A55DB238F7D36B374F03937699D1F7A6B562B573456518DE18846A7A1191BBB53A3059CB369837A4051840C21EA82EDA81E927CB0C9594468D1998E610D7DD411CA709CE5DB0D0EC199702C924D8ACAFEBC68FA0811FFD41573594A889B53215524254434E0F50E54B190147A29230A9438F3B3B4470A0993B82B742F09C47DCDFC213519A7A2581A21CB72AC65A04204AC4753576EE3C1F9507AEB34A1ED2C1CA9D275B69CB9D1F584A0E02E53C861DE3590856AC0C7907243903A0D6B5EC85037EC33250CCAA906298FDA1A3A44D67908EB40F31773F307202A36B214D69A7A47AB9EC42746B8C009950FFA1949CADA0C1E77B363E075FB13C79E784AB45804775A04C400A29CA47EC384398FF704F5737303084C5A4A804920846ED0922F0ABFA7B88C276BBCBFE99524CACF6453948BA0563963A69F9ACC4ADA2235F66AFBA3A08DB10133D00AE74B89AA929011108CE9203E0B1B60E9E8A877EC0DBE6A24CD636606DC500D05054184CBE298805B4C74F3402EFD35127157884477B9301527A65927A6474B150C0F3B9B17E864B5D890BCCFF967D2F8256BE764852054C02983810A81779BC08B47A29E6A024C842B5D0C16ADC95273C9B61F3A08C62C3BC2C3CD24411ECF510C46466A5DD8705AF80869BBB1D0D583AB29B48923AD24844D39E23F2750080C272847F1C24896628B4A2C73D6005FF8A19F817DF8C3068654CCB61C4AC57427C1BB4F51E5BD0B552928197E6F977303448BA4627C56696428B54A57CAA60C9A42A0A544EEA50C4FE21989AA16317222E435B80D9B3FB11016F92B8E988A77D6D4712B05CBEF15153DB4B687B17B21E50377D43D771249E02A4450A481D1F194484B80341CBE51B85E01F6022E244A6D984472952F8945A3DEFB59D5450651884B3A6C041B272F8D8A45AAD56D7B33574A77BB6E30250DA691E4638E68923995763EEF05CA33A9285B364797EA04A1487D15C309A78337EE321C0BB6CC73117FA50A627F877348E5CFA4107CEFD0AE762966170B160801033E119837C474E7CA06D99749940322FDE4038C0BBF65F462C2D08906367FCEC14CAD467B0567520A57521213C30FB5001650661FFAACF683B561054663814136B49DCC627E29A65CF1320857A7B3C07687ABA2749ED7B9B6488402D0A4829A45CA614D23D712591B7B457119DB2B6184F442B44830DDC537FD7376C00B96C18698C108CC58154D0A239C53C94416146660F0CFE4273D7D783F9F39076EDB9D34E0835958902C03C76976A1B6A73A20A97652D5281F925C923A553E79A3C6087183A42138EC521B209207261E7DBB5057A4B9B589456DA59708144AB8042717890D652B74BF1C38CB178E3CF3499B018E8AFA877EA31A4E9BA54825207133AF99EA2E432CC04293655059AF6BB45C33D6F7539D3A48B51362884040FEA99E8FFCBD5AE96635216B8660278F83A0115118DAE444C8769834D86B4E66138CBB79B4AF4D7B62C4DBAF2394CF414BFD6EEDC0F4DD25419F843524D730011ABB427B46496FE5B17DA0C52D44EB8C" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "3A4C594F1F9549846196A5D2768159D31B55D2862B3E3119DAE48A8532E855D334EBB85A36CD907ECB5BDC128ABE278A7836288F989A41F3A68F1DB01315DF3D", + "E3781E62BCBF542ACACE64C2F966B0F7D7016FB4347B79C51AD78147F612AB709026B3B08181628F781A27C1B040C5862131012895CCAED976D8BBA57584441325BE014768AD5104A4130B594A1FF7F9701F60B255251F754BB7EB66CE0D9C4E0E5BB9FC6C1B881865212578E13C423FD7056399A28FD3557ADA9D9EE5BAEE53A9291106A6E00468600E50CB2FDE146268B5713DEA993B985965F713828C072C324F6A97267B39241C0245572C51D9E8AEE13B1BC3542B06707C0674B369833B854A820987B32E679F4BBB47789734D9D3CAC6B976919CA17512CC41449FACC4205AE1635902B9C6D35C1740C052B6592735AB8F09A227BB3F67640E13E39A877490A0B4535F01A551FC0E4A909B40C5ADC4C948B3444430765842F51212FBB086B70F56463EDC250360998032E41A7B6570A526615C438B7E4CCB9BEA153E486BCE50A347B1759BC9654B74C92A10A06DC69518F995A796659AF9945BEACF62A9860392B224815202389B772A07C74823269C1350970203F5439AC9CC19D016BA5C29B9E59E4BD2C63285B4F8E8BC584B3C014B2A45D819A2157017E50D33142F1D319BE7467B5E69B7D4595DD66488E2BC7C76C2AC7C4097F4826A621A6149F103D8B05C6A585BEFD07940528F91249774F870992B793A2B804F417FFA6BA4035AC2E4A751D4AA68DC19B0A701A2597244645A7ED7556C9D7373E1B916C6515F3A8C83E700112133CB1648836B17A69F335CC8599129707CF77232655ABE78413448B1C260097D2E37540AA19D744537010CC580C8CF859818EC5294F769250817366670C7D4F9C64475960D1CB5DAC066E7C054073490D95737250B1F6E405936BB08C07CAB94828DB6BA6182C5AC85FAC9FCF5CB6D19CD3C590136AB7055C1313C63BB24414106C0BB56C31D8CA4BE6A2096538187443B0FF085502AEBB45DBC371AB0A31E5B51DDA47FF1239AA5B88EB27912C2E18DD28A8F0EF281E5A97A8B954123B95EBFC799E5609CCE50C7B1E6475346CB17E81112F60336E589563918DCCA32C7E087F6F688EF8934825C0CB5BA8149C2A0601671DF42152237089B528C1546036E5CB2A0659723CB5601529A225B61F77729E9E664BD4A5AF99873F000827618C996AC6048835F65512817D075CB6529601563760CB4B39500A8E5CB01D8BD1CB251409A2AAEEC5243F1664275423E3C6D30B18F79599DD8E8868726306D14929303AF5BF87A6566152C24982866C9EBA549B4A094A3C7983CC491EC12823C7B4F7706C8F1A12FCD548F33753E76683704889834FC2835423A2F1C9A3BFC5D9CFAB507484A5E608EC3AC646D36AA2F5119CD501B841ABDDC1B7F646BABE2BB11070960BEF82BD8282087568CB6DB42735359CC40650B363C23714F9F06C8D7607DB7D7750649ACCBA853AAD93DB8B9460203A14814BEF49A8B6829A7B831B59BAC9F15112104DAA07E03ABA02531E7306516A87802CB664A462D5A7AA0DBA86EEDBBC42AF302D11275CD4454D49C5A82E318CC54CA481B303CC94BE98CA712903013D4B89CC869DBE68BCF8BBF7C3085E1E22AB941A8FC90424C035495264BF9C63A588A4CDC3C8EBAC9066D0C720739960B325CD1C99C74F399511494A2DF45AE38B715CFAB3293CDFAABD0AF1278174EF92BEDE18AE32D113B", + "79A2CEE385BADC93399056946A9B7211B0283E355091345861E9886660997A8A72B8BB231861539F543A627092FA8403CBDCBB91A07CB391909B39A4306999C2023405AB78BD24B654884DF4EA114E408A87D77F45B7AB3136C7705992A0FC288F0284E59454917B2474934344EA9FB0670159211751F46656CB93C81A68F58476723986AE1686037A3ECBF0542E369205AAA90A7CC4DE45C79106D05B75816A602BC56A0994E3935473C0BBB0B2B7117ACAC039E2947D47848C4AA81D39AA5840239C8042A8280C80873ABDA6802EC755C114B6C828040B0277B52AD7AB5E6C849D2C9063B27A26E45C3A5C08A751472718A6E16C91E03C907D9499C61BB55FA7409BA2084603065A1248BD814DAD30AAED3702D7B3A75A3276DEF14F93E859D1320F3F861CDA089D166BA69D3C79FFA9CA73742B498C072F3B79148CB66B9A2018916BBB2014977BAC0782AAD4508D53228872657BA4D2AE7D08C22B524A3513C7D5881A58A98256F629C286750FE81F8C476AD59AAF8C43415B0C0C6EDC6DF3A909E2A53B822C033D89AF83B48A2AEBAB5F4C72072C169FD824927831F3922E0300309224470DC62C5153537420C2C86A0F0AD505C2CBA47180AA7CB7A47D354155063D5A346AB5224BE032B3E7E6BBC4C8A7E1917410B53850AB1949A71CC994590A92229E82641E740242C48A9525191AA2777BCA0ED286B70D59CF629B24A5015719C1799D8953ECEB70A5FCA962CB2C25229DB2909EFCDB2B7E3CA0A9848872F4AF1E447B5FF60AB7BA8255A30C7A24B28D2C9CC4F6A59BC42B920462186C642C710E9EC4BFE289C45FB1759B06109AB13A354831AE28A5ED7AC592714337FB688C5816E17400AB65CE83C868BCB49151045365566418919D822B98D4FC96B9D97FADDB313008AB12A40F2F7A59547B596F7156FE0205242971E9BA8898D96A6EFC62F236396083592B04C3FDA990B05597BAE09742850484755338D40DDC0C5159E883CDE927329174F3F2B6B5E0A3EF83A3C722303A371A62AB2D25784A7CC52231885AEF16199406BA4024AA45E9A74018773E34C597D5CD0B172D6E90BAFEDAC91B85330D3075F3B79342626B1B13450982534AC135BCA656A0C520BDFA2DADA82E87A142C7FC4825B04CD69C57080248C09639138136E80185B798B0A464CE4E6621E7747A3EA1B444E1746EA87CA95790C7BAA876A2B937DB3963E28143862D6C58085BA86FA1736127226F9B3201CD7840AA4B8142665630E64234A0A6E883707094C23AD09D7901AF4B42A01FC4B1A730575690BC6E390E688C3342A258D09C2818D7AD4D0CA7B3242078E2CAB8AA4E90D919E9A8496D7240D4FB2BDCB4B545F17C1BE1B9177A1C451A024A730ED03489EEBB73845B3D3AA473DA1B3E02D5779C97221D50870F914C2D2B86BF2A946216C144249E0FC0CB408B942032447867A56591196BF84DEFD7A1FD43C816C2843F01A6E66BBAC9A80505C8581C0A3AD807CFBA173635135CA76666F49ACCBCE15A2312BC1F038BA90B8491DB27A3A8B25454C15FC2A6AF8C8993440909C14D02A995E917CC7449AD726705EF866372C3B503249F8E0A3E252541DCD4635258B55161519EE138AF44C0E3781E62BCBF542ACACE64C2F966B0F7D7016FB4347B79C51AD78147F612AB709026B3B08181628F781A27C1B040C5862131012895CCAED976D8BBA57584441325BE014768AD5104A4130B594A1FF7F9701F60B255251F754BB7EB66CE0D9C4E0E5BB9FC6C1B881865212578E13C423FD7056399A28FD3557ADA9D9EE5BAEE53A9291106A6E00468600E50CB2FDE146268B5713DEA993B985965F713828C072C324F6A97267B39241C0245572C51D9E8AEE13B1BC3542B06707C0674B369833B854A820987B32E679F4BBB47789734D9D3CAC6B976919CA17512CC41449FACC4205AE1635902B9C6D35C1740C052B6592735AB8F09A227BB3F67640E13E39A877490A0B4535F01A551FC0E4A909B40C5ADC4C948B3444430765842F51212FBB086B70F56463EDC250360998032E41A7B6570A526615C438B7E4CCB9BEA153E486BCE50A347B1759BC9654B74C92A10A06DC69518F995A796659AF9945BEACF62A9860392B224815202389B772A07C74823269C1350970203F5439AC9CC19D016BA5C29B9E59E4BD2C63285B4F8E8BC584B3C014B2A45D819A2157017E50D33142F1D319BE7467B5E69B7D4595DD66488E2BC7C76C2AC7C4097F4826A621A6149F103D8B05C6A585BEFD07940528F91249774F870992B793A2B804F417FFA6BA4035AC2E4A751D4AA68DC19B0A701A2597244645A7ED7556C9D7373E1B916C6515F3A8C83E700112133CB1648836B17A69F335CC8599129707CF77232655ABE78413448B1C260097D2E37540AA19D744537010CC580C8CF859818EC5294F769250817366670C7D4F9C64475960D1CB5DAC066E7C054073490D95737250B1F6E405936BB08C07CAB94828DB6BA6182C5AC85FAC9FCF5CB6D19CD3C590136AB7055C1313C63BB24414106C0BB56C31D8CA4BE6A2096538187443B0FF085502AEBB45DBC371AB0A31E5B51DDA47FF1239AA5B88EB27912C2E18DD28A8F0EF281E5A97A8B954123B95EBFC799E5609CCE50C7B1E6475346CB17E81112F60336E589563918DCCA32C7E087F6F688EF8934825C0CB5BA8149C2A0601671DF42152237089B528C1546036E5CB2A0659723CB5601529A225B61F77729E9E664BD4A5AF99873F000827618C996AC6048835F65512817D075CB6529601563760CB4B39500A8E5CB01D8BD1CB251409A2AAEEC5243F1664275423E3C6D30B18F79599DD8E8868726306D14929303AF5BF87A6566152C24982866C9EBA549B4A094A3C7983CC491EC12823C7B4F7706C8F1A12FCD548F33753E76683704889834FC2835423A2F1C9A3BFC5D9CFAB507484A5E608EC3AC646D36AA2F5119CD501B841ABDDC1B7F646BABE2BB11070960BEF82BD8282087568CB6DB42735359CC40650B363C23714F9F06C8D7607DB7D7750649ACCBA853AAD93DB8B9460203A14814BEF49A8B6829A7B831B59BAC9F15112104DAA07E03ABA02531E7306516A87802CB664A462D5A7AA0DBA86EEDBBC42AF302D11275CD4454D49C5A82E318CC54CA481B303CC94BE98CA712903013D4B89CC869DBE68BCF8BBF7C3085E1E22AB941A8FC90424C035495264BF9C63A588A4CDC3C8EBAC9066D0C720739960B325CD1C99C74F399511494A2DF45AE38B715CFAB3293CDFAABD0AF1278174EF92BEDE18AE32D113B72A6DC72A2F0F70F1885231F9925E4E4318D4E6190DEA0DDAB595E929C2F045C34EBB85A36CD907ECB5BDC128ABE278A7836288F989A41F3A68F1DB01315DF3D" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "AC27E145C12AED5CB925ACEDDAFFE0E4585EEC4BCDDF1F13FA14336DB158D3489551885BE8D2459405071416AF0B31B09871D8E695AD723482C91706BFF363CE", + "9DC6C6E0C029A2C9B5BD92339A38470D81C86C006FC5C44D37A4B6A57869BF007AD4BB926FA299DD529CC7879B21D75552D714FDEC6BFB7A6C0C0AC90F93AE7623CC8AC18345823786FBC9BB630AB3B0A27E196F33D07CA253035C352C90F03A6710AF339CB5562C89EF4038AD43384B2052D4559812C08867991EEF8B507B2939698402B83B0CA0BB1DE9BA0EC7C26699E82CF17768A67C595FF6C54CA6AA135322342C39ADA321753CC35EC6433AECB904D8B1D06890E8C2BFF6500D4C217B82737C04521E3F41BD8B168730788B1A215A33A50BAEAA664C7C9E9B3C7A9231A6BE3196129A0512A89151731FF7333B7A3B29BAEB35D6C09A57B65C3024A32A4589FD090D2E45B7A09457AEF116D82B6E839AB8763402909358665A9333C95673014E55B40AF06A57F7E20CC8DC8661E7A3ED1971890A95535940E9F02D1CEB3F53224F4CB696A937C701077F2D6A6F958364568494BF183A28630FFCA9277B693A093193270511AB76ACDC1A4BFD4747CE1A791FC29951745DD67233AAD5796FB3B6DD6BAA0379292F9B9CBCE0847B898B55335C16A433CCEB5BE2D209EB43879A1BAB3A5A9BA77A4499514176E91798EC19E32468F6F4C36A239762E5AAAA72CD6BB49A7D3767DCE3659BEA142AE04A6D1C14E6D29EE6DC4FFDEB0EABC69712048D581719F65C60FAF47FC10BA10574C0A2296A14E633EC962D00E8CCF9D20F703372C2325367029A588C1928045573C3B64B8405A3969F88E3CA0EF1AE478818279145B8B38CFEC805A7801CDB319039F6CCA94B84555454384571CDD7CB747300A07C5DD9C102B81B051B6B2032E63D8A8137DD9526FE996FC679050E3B9C99E1888259CC65B1649678272D571036625D7AB79CD69A135ED839261673B1DC1FCA93B393011077EA718946766FC1329B203BB2D102928514D8F0142CF56B03B98F6CD8ABB901968E8351BD646AA8566184B0B0F7E8970774B571C67C320C0DBBE5B7153278CC474D457155ACE19922449290DCA02DA1A54820730CB28CA37456E70ACD5B00A45467455A01A545C56A231B1D8499400918A061CAC3248BC0CEBA03715C154056339CE25B0BD989C7B1BCE6C85528837AF40C9B87A39F772894D4AAC512BA600ED76F0AF8627BB3AE3CC33365502BA54B1831159416390BF78B9C2990CEC8A19C3D1C76E79881BC3CB07B6350EE813F4747C1FFB1408ACAA711A02152611F4286ABF3A54ECA5021231330E2F1CB44179BEE442C2D612E08D60A7E51B97A910EA2F04168744581A7251D9692376C6C1DA71F769293C97B5219FB3B2F53390DF85039993496A55A2ED89D5192BBC3411254BA0428A88097EC51F9EABDCBAA5D500712A2C5C5B57A3F8D9106C03863961B1D84B685FF270C87D5216F0112741817C488B8E59236FBBC9D2D2370AA60B502388F02574F05941F2F34BB1FF4499C06B10D65C6E880876FABA8636C107D21A4ED7231B55762C314BF6D41914671586FC8B8C884CF5FC0C5DB6B1E2259A93F222FB96635A5E4517AE7CF81FC1B262B9EB827749B51381CBB7591E3A075B0535455111149B1125C4303C1659FA4BD32128B00B12168F1AA0AA04FCD1791362CC89037064035A2C1C0BECE5DB437A7E8F4D54784F5B13D31897BC1D153B094252EC51B6E2629CA446A6A", + "951048CE09A9AFA9B5839915EE46A6C1B3C533C06D6C48B06E02210E0280FF6A6021199B06548513A3C392F34BA6294A62004898C9A76F4C910084B83B1A9F15F2CC561894E3B182DAE8CFC474C1E3FC8D683C29C62B996843674D484ABB520166250841B81C88A53AF158751EAC7F914B26B0B97F78DC7C0C51CA97F4AE4A0A97705B4C3FF72D8EA0BC438C925855C61B52B333C80E051A245579AE5EE182CC9526C9F54E6D331B56E64793A4364F1844F910ABCB6ACABB281CAC1A95BBB75968044BB69A5803A8A226E6B3C421B0C0948CF5EA3133F40613AA5F28E80E0F881B45036F61E5929750921FC21E79BCA10D042DA14A5192186179FAACA3568E19EB1CB8D7B02E129EADF7070E030C499036F8E5160CD062873711B2C388B8C90AC6E5677CA21F8EE7865411A3A4FC2649A604C70C5B97D55E67F52A50F8C92C6A473C19A414D43F6A0C6DFD760C29E30FEE2161F78167FD2A93AB7C94A56995094CB3EB65510669CAE4E30314574A6DC0C49129475E69449D577CAA9CA0A1423AD212306EE36EEB449B8318B7B369C89FA74E31BC6215779F26884DC38B270EDB55546C1E6C713BEB340C37C9A57F58CAA49A9B90875A88D829EB8739A9F93D1193917DFB866E39538CA668D284580DD0AF698BCF22694C2A626D3ED8C03447BD6FD08CCA21ABED3CC30CBB8B0D6953266932C83A8E42E78A40505766926F37012DE9B293B64035CFF76E493578976010A9342E79189951766B74ABB357C50B942AAE8CA99153C4BA57DA27DAD013B2D030D2233F6E2406CC18C499B81173928B12E259D6CC9D39649F12EC8732B83A9B14826449214527740C3B4C6EA172E71B2A886A3AD8B959A2C7C597596E2C249EC371BB1BCB427BB0A1E9081B3E47386E655BA313208C78588FD931DFE2AF01335815B4AE62C92E52C1B55A330C81B09DB7775D6E373E1497341606769472038913918ED7199E158D6E6B061E45296EC6B86C3B671E997ED39AC3FB29638E7427AC85C9647224BEB706A474281B1C2D6E750B3F12CBFBCB8BE00878A9D42CE9C7558A498B7255630AA21BC567391799A5E36A32F0040A0110C15A772AD5F20E571015ED08066AA3857E1A594C322171378E90E53E1F4774A21980C95B307CC3174167AA1F105241331A0B7B8A04B2863436B30CBC6A2D5BA90470068AD413B5DAC05D1485B4A4C01C918CDA489035DB82E6212AAA11CC53770AE5F92DFFBBA047F70DE3D8943D859ECA2B5F86D77AA8023ED88BC12A9B930D236DBE501172275683194A5AEA2847B18E1C76ADFC18CCA36180EB2A2BF432C082C1CA514250C2B939E19054C19018589BB54AFCA2245AA4B659884C38799DC899E48148A1D66A79DA148B2487C1021C62D87414F34BCAC05E4E404EFC49AE3DE882E8A2740830CC4204182D84933EEA238FBA1712775964F28F8D4562294CA21D3A196E180FC8D4B205B229FCAB17214602070597159B162098791C2804511512F922BC8E02CBB99C8024207D3553374BC42CEED06B78B51EDCB75BEA82A4E5565032125371D4B5C585C13014952C443A89810BDB2B7C99059E2237475B97CA102A19BFF40847D7BF1644A6A0810D10663AA476B52575309DC6C6E0C029A2C9B5BD92339A38470D81C86C006FC5C44D37A4B6A57869BF007AD4BB926FA299DD529CC7879B21D75552D714FDEC6BFB7A6C0C0AC90F93AE7623CC8AC18345823786FBC9BB630AB3B0A27E196F33D07CA253035C352C90F03A6710AF339CB5562C89EF4038AD43384B2052D4559812C08867991EEF8B507B2939698402B83B0CA0BB1DE9BA0EC7C26699E82CF17768A67C595FF6C54CA6AA135322342C39ADA321753CC35EC6433AECB904D8B1D06890E8C2BFF6500D4C217B82737C04521E3F41BD8B168730788B1A215A33A50BAEAA664C7C9E9B3C7A9231A6BE3196129A0512A89151731FF7333B7A3B29BAEB35D6C09A57B65C3024A32A4589FD090D2E45B7A09457AEF116D82B6E839AB8763402909358665A9333C95673014E55B40AF06A57F7E20CC8DC8661E7A3ED1971890A95535940E9F02D1CEB3F53224F4CB696A937C701077F2D6A6F958364568494BF183A28630FFCA9277B693A093193270511AB76ACDC1A4BFD4747CE1A791FC29951745DD67233AAD5796FB3B6DD6BAA0379292F9B9CBCE0847B898B55335C16A433CCEB5BE2D209EB43879A1BAB3A5A9BA77A4499514176E91798EC19E32468F6F4C36A239762E5AAAA72CD6BB49A7D3767DCE3659BEA142AE04A6D1C14E6D29EE6DC4FFDEB0EABC69712048D581719F65C60FAF47FC10BA10574C0A2296A14E633EC962D00E8CCF9D20F703372C2325367029A588C1928045573C3B64B8405A3969F88E3CA0EF1AE478818279145B8B38CFEC805A7801CDB319039F6CCA94B84555454384571CDD7CB747300A07C5DD9C102B81B051B6B2032E63D8A8137DD9526FE996FC679050E3B9C99E1888259CC65B1649678272D571036625D7AB79CD69A135ED839261673B1DC1FCA93B393011077EA718946766FC1329B203BB2D102928514D8F0142CF56B03B98F6CD8ABB901968E8351BD646AA8566184B0B0F7E8970774B571C67C320C0DBBE5B7153278CC474D457155ACE19922449290DCA02DA1A54820730CB28CA37456E70ACD5B00A45467455A01A545C56A231B1D8499400918A061CAC3248BC0CEBA03715C154056339CE25B0BD989C7B1BCE6C85528837AF40C9B87A39F772894D4AAC512BA600ED76F0AF8627BB3AE3CC33365502BA54B1831159416390BF78B9C2990CEC8A19C3D1C76E79881BC3CB07B6350EE813F4747C1FFB1408ACAA711A02152611F4286ABF3A54ECA5021231330E2F1CB44179BEE442C2D612E08D60A7E51B97A910EA2F04168744581A7251D9692376C6C1DA71F769293C97B5219FB3B2F53390DF85039993496A55A2ED89D5192BBC3411254BA0428A88097EC51F9EABDCBAA5D500712A2C5C5B57A3F8D9106C03863961B1D84B685FF270C87D5216F0112741817C488B8E59236FBBC9D2D2370AA60B502388F02574F05941F2F34BB1FF4499C06B10D65C6E880876FABA8636C107D21A4ED7231B55762C314BF6D41914671586FC8B8C884CF5FC0C5DB6B1E2259A93F222FB96635A5E4517AE7CF81FC1B262B9EB827749B51381CBB7591E3A075B0535455111149B1125C4303C1659FA4BD32128B00B12168F1AA0AA04FCD1791362CC89037064035A2C1C0BECE5DB437A7E8F4D54784F5B13D31897BC1D153B094252EC51B6E2629CA446A6A9698287B9D79CCF9425329AE19A5CEE7E5FCA72CD55426AB0D9814C34132E9999551885BE8D2459405071416AF0B31B09871D8E695AD723482C91706BFF363CE" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "B5EB681B4241CDAA69F9839D79E49E8A22B1753FD8D4844012406C6E2E0A0420C3F615025B1D3A02DD054A998933D55B8745ECED046F7FCBEDC4397C44ABB0B4", + "C220133CD78E2454B6A2785F57B97A8A257440FB7CEC1C581640A568205AE95CBFB1215BA0DB3EF80251AC3163C83CA2295B4D238CC2A2A9CE15BC9B3497AF063CA5E8F46FFFC011274BA5F2D76E87208F96F822634C3ADA540D5A30099D2551642BC4966123D7202BBFE02E0759A6737823477993B64B80C340C3C147C5AFA19ECAA3BDDFAB23FF1579DA183AEFDBA34B1117F890BF8F29145149558AA58C4D326638216797542B33BAAC607786B0739FE5A47676A898D8A255FC43151C735F6A38753E2384AF28052F719A593003ABC9743DC82B08864844E2067B7BBD6BDC128764859C2385E65AAFD55B0B80D3BD8047B5116BBE24155916612F242CA81FA57CBCCA845DB08E600959BF94B61A2B3118F7A837C9C2970B4E4C946561A044192BA977285FBBD1C8F4FCC0CCA80896CA2F236616B161A64833895E757D7DD084807559D62891AFAC3CF7EB55317B96B8A8C86BBC20AC4834A58365298319D27656B5D156F7B11BEA8B5590F34CB5AB088D27280E428E4588B4D4048AC3097A0A0A9CD4F1578CC773A84ACFD032B05799C1645BCB2757BE7B2491974BC5DB39CD84275ED2D1431CF9A8D1EA259A24B1DCE98AEAD72907B67F41339C93DB59556491A1A20B36998713A9BD33C26E3BDB8E85CAB377300CC81B6F26F38A24B454887A65FA3B1831EA531F52B667E4A7EBD1B6F15312BC9468E2B8C05C75B0762A7224B25A7D5B3A1BDC2544276875EA8F64F98E03EBCE5F523AFE76557BB04E7269158F547E911B3B2257004AE2095F7067656A686369BC7E7908DFC63829B84C24520349C661FEA73A4BAB05673234B9993B939C8FB74910E46A498CE6057A6B5A4723896EBCC8F425BBFB93BF965A55F4E74A7BAC1B2E170D9EB6077DAA48C3C4B61263C4ABF04175162348E444A4C90E4517546DD527D68845A3DA7DE8C83DE62662CD8A8B94B42C6640CF1D4C237F46AE42E7CADEA8AE9C6A1DD9C8C4D35269EB8003FAFA7BE5C974C646B28C9217122265C96A4116D693D2E8152F141B4609433C7B9FAB670200372A0A20012D284464DC9ECC734AC7E2929E3CBD72D1C38D44135200A7CEE5A1FB43B0A76805B7EBCF6AB868CDDA9D06A2BFC575787785AE90F91D043B32793B81CC51AEAD83710F95C237E5AD3B904CBF1496062104D5EA513102103B25577DA065A8935A85D2A21BECB7F4D26EE900B2ABD8B335FA7302A898A55840F6F875C280B689C16350B1848CE476E5D5187BE24C9AA20914268752AC94374188EB57ABCD316BC3432578B93FCF67069DCB81209878827A97AE36C73C475D2E53BA04CCCD7DD6669FE4C4236611E353049665B26E9269EC3A3C09390B93432D8480AC4EF433FC74AF3BB66F93479788D7065DD17DF1039F5AE76B9674BF2386B392996AFCD098A5734CDDF1CEC4AC9B76670762E74CD9D00D4F40042C83A5C8456993145791369FB755279E50B39CD466919105A2F3BAA256C76FF671002D0253F62FEB799CE1F2ADB0A76F9C9BA3EEB285CDB8CA8019B1993270DE70204ECA5AB4642C2E5B5A513A7C51C97A49D59A448ACEFC37B27B3903AFF32EF8B34729884798AC259640644CF0B6359B90F189A87B62A1B0B169AAB76F73879570BD18B5796F98F49CC8845DE68D32E3A57859E61B2CF58C1DCF33F0E2", + "7BE0C046D7874D8B2DFC743CABE3880DAA7B4DFA8C185867A5601BE2D84EC4AB5CCF8653170CA68DEB20F2D264DD3C0A855537F34B4EE314518F93AD5EC919921416DC6B77BEC55CF5CBBB6F349D3DC37B16F60500C9CFFD3B4CBF1AC739C0BE50F3CEEC18B28BD98842A82149960D84FBB048F5CE5B50AC75D14DDC8A0773077BBCA1846A889CCB24066D66785DA73298C5223AABCA8D8B44C2B5C439014E97B23052305003A97E9152B997445815F689FEF30F5585290EA8A9ACEA1A48D6BAEA6A768D99136378600CFA4776579F2CB8ABC5184184B9543AC74B99F6C907AACC3AB3421C9B94097A12FDF522B300AFB0F63AB1A30EA60B8E3BB559553A21D5FB3D73EA44E459B02577600260156DF460AC2A85AE777FAF25C6BBA18EA4CC21ADE39BBCEB0654627D092A42D6A98C657473DFFB84EA6858C660C994E6595316814975318BC7563C722A3F05A2999AC3D470C7692794D0C033A2903AE410A65D24726B305A9F8B06B1A9A6365984180851AAA48511626CF43879EF5449B0453C27D440F478CEB79833CDF368DB52A1423C6C1C9C1E79BC93E9A9A159E73BD1C22E8783CA049C5A56EA3F31C29EFBD9C2D38B63EBA99D95EC80628830A3ACA68941115150BF121B22543C2FA0E05EAAD541A9C9BAC694393CD10A26820F56561379367B97A77F3EF539EB9965FF7A8A693C532C865456151884881E2FEC43F5B9BD13594FF891B7D12323EA06542AE94CACCBA5122A691E5311CE20CC3F63B5FB286899A56A543966EAA3C63041165EC94FCFE264CCE02A08BBC2A8E9705A23181D4405B81C075C173806B432235B186534B9474060885C9080B71EB1D16B6B5B8A52C230C69884E3C89FD4D6213076A9E2746C703C517C6BB2665B10F7007F9C1BAD30A522B05C498F6192C5BC58363B09EE7B3AD3828A12A8C11BB1B399062D01562835EC8246206E79D998F1767A522A984472A221B363D9A64A2141C1F5DC9C37D7C2AEC56DA3E12ECBC2CC46BA3294A6739838143C398557988A3482491DC7BC76648885E8754CAA4339B54DE89A7FE17541B31656E07A89EFF88742D5C35624C1475A0698EB5BAF217E25B3BF12C060BEF574B2CBB6B7E91C6628B213976A48A00AC32C78534ABECF259F7A05C95CB13FB9806EEA20B35E064244942BD52B98735A03E9A1616DE8BA4A99962ED97ADD922871A0B4B9A70EF562709F6040D5643120B6CB797A74745B7A64A36BCB604386C406E50481611590C94AB497FA7A28703BF49B5B4EAB9E475C528BA72CB873607F0682A6C7CB0B734704B754C27A173EA07C1B336A6C2580C4A22724D43304C07D0F0501FCB4BAEF4BA315C39D71C957E03459C8D784E08955F4257CDFD4B8A6E14AAEC52029EA2545C9307FB7A6B35A7B35E984D567ABD42C44A5405EF4DC3F5AC68DF71AB2C9B94035608B1AE0CD7FC078BCAC2663F4B589A285EC9137C26128CC6555D71954FA751499BB47E535310586249A660DC5966AD380AE50353BC3A2C627A132E9DAA01959104DC87D0D7B181B1B3B5611280DE281E8D19FCFD30E9E36AD692345164C392E43C135F5CA8D556381791958D20F3D616238676E2A404308069896AB4483F531E9963EC220133CD78E2454B6A2785F57B97A8A257440FB7CEC1C581640A568205AE95CBFB1215BA0DB3EF80251AC3163C83CA2295B4D238CC2A2A9CE15BC9B3497AF063CA5E8F46FFFC011274BA5F2D76E87208F96F822634C3ADA540D5A30099D2551642BC4966123D7202BBFE02E0759A6737823477993B64B80C340C3C147C5AFA19ECAA3BDDFAB23FF1579DA183AEFDBA34B1117F890BF8F29145149558AA58C4D326638216797542B33BAAC607786B0739FE5A47676A898D8A255FC43151C735F6A38753E2384AF28052F719A593003ABC9743DC82B08864844E2067B7BBD6BDC128764859C2385E65AAFD55B0B80D3BD8047B5116BBE24155916612F242CA81FA57CBCCA845DB08E600959BF94B61A2B3118F7A837C9C2970B4E4C946561A044192BA977285FBBD1C8F4FCC0CCA80896CA2F236616B161A64833895E757D7DD084807559D62891AFAC3CF7EB55317B96B8A8C86BBC20AC4834A58365298319D27656B5D156F7B11BEA8B5590F34CB5AB088D27280E428E4588B4D4048AC3097A0A0A9CD4F1578CC773A84ACFD032B05799C1645BCB2757BE7B2491974BC5DB39CD84275ED2D1431CF9A8D1EA259A24B1DCE98AEAD72907B67F41339C93DB59556491A1A20B36998713A9BD33C26E3BDB8E85CAB377300CC81B6F26F38A24B454887A65FA3B1831EA531F52B667E4A7EBD1B6F15312BC9468E2B8C05C75B0762A7224B25A7D5B3A1BDC2544276875EA8F64F98E03EBCE5F523AFE76557BB04E7269158F547E911B3B2257004AE2095F7067656A686369BC7E7908DFC63829B84C24520349C661FEA73A4BAB05673234B9993B939C8FB74910E46A498CE6057A6B5A4723896EBCC8F425BBFB93BF965A55F4E74A7BAC1B2E170D9EB6077DAA48C3C4B61263C4ABF04175162348E444A4C90E4517546DD527D68845A3DA7DE8C83DE62662CD8A8B94B42C6640CF1D4C237F46AE42E7CADEA8AE9C6A1DD9C8C4D35269EB8003FAFA7BE5C974C646B28C9217122265C96A4116D693D2E8152F141B4609433C7B9FAB670200372A0A20012D284464DC9ECC734AC7E2929E3CBD72D1C38D44135200A7CEE5A1FB43B0A76805B7EBCF6AB868CDDA9D06A2BFC575787785AE90F91D043B32793B81CC51AEAD83710F95C237E5AD3B904CBF1496062104D5EA513102103B25577DA065A8935A85D2A21BECB7F4D26EE900B2ABD8B335FA7302A898A55840F6F875C280B689C16350B1848CE476E5D5187BE24C9AA20914268752AC94374188EB57ABCD316BC3432578B93FCF67069DCB81209878827A97AE36C73C475D2E53BA04CCCD7DD6669FE4C4236611E353049665B26E9269EC3A3C09390B93432D8480AC4EF433FC74AF3BB66F93479788D7065DD17DF1039F5AE76B9674BF2386B392996AFCD098A5734CDDF1CEC4AC9B76670762E74CD9D00D4F40042C83A5C8456993145791369FB755279E50B39CD466919105A2F3BAA256C76FF671002D0253F62FEB799CE1F2ADB0A76F9C9BA3EEB285CDB8CA8019B1993270DE70204ECA5AB4642C2E5B5A513A7C51C97A49D59A448ACEFC37B27B3903AFF32EF8B34729884798AC259640644CF0B6359B90F189A87B62A1B0B169AAB76F73879570BD18B5796F98F49CC8845DE68D32E3A57859E61B2CF58C1DCF33F0E23FF88DE9CA421444D12D243136ECCFA4722A7DACDBB725A29D0A3B035174E91FC3F615025B1D3A02DD054A998933D55B8745ECED046F7FCBEDC4397C44ABB0B4" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "0B62B2B97733B9EFA5E6F47BF85FEB902288D5434ABA6472D879A26BA08849C68BE4CF93D24A99FB17414EB9C36B8292553A1624BF576BDAF68503112ED031F4", + "85DB5111A786CFEC515DB6B2FD86CCCC255C82FB7C2F817CA1BBBE1375C2879540A13C329A792039BB14C848AFF4623E8E914A11E09CAAB823ACEA9AECD6990B8275E93530E44BAE234C2F13917EB94B996702CD774A528BB8A70462254EE5A9AA2137A16289B8A13253075A8D95657E462F8FD2176FE56046A922ABC62B1A6A9E13A9A0A620BB4D32C56E329B3BD04CCCD7CBC5EA7E2BEC66ED769F8E5BCF5E939553D83C65C114D802B7F1214861936E58370929936EA030517C7534D48C1B588491DB855DA76588BC74AEBC61B648E1C1BEE822E1F61FAD10CF07799C90955E02F55D94AB0BB2122421D3C35AF598D5FBC8C6D095B74A08F148C953240287D7795EC36BC1F59D2035C19510749F71840CC7ABEA291027997780922299D93F6EE7C562A1A2BF401480C50991D5409668672EA3718D10AD40C577E0E7C93116A393AAAD17210EDDC7B92469BAF5DB2DC4D1AEB1B1212E0A7073C32DACCBA0AEE0CBEBFA8D2CCC9F6CDA1DA2D62F1BC7742023A333F0253703219DB17B2AB442FD53964276935D4CA16615596CC7C302679E2AB27F6F716248381A5C51B4076B8E72AA1E334155E045C8B7EBC85B2B23F7B40C52E0BE6F2B08FBB52836E9759D66C7BAEC3722CC7625ABA255936220B09ECAD6143A80819AD3CB1FAB73829499C9F19D2DF9A0EDD5CABA5C8CB60780DF86C1D596742D38C25E475D5CA3546685C9D659433DBB05A1A744A4D48ED4CABCF5C56D7838CD22B9C1AE2120A694C100FBA814B31EE0EC3F19A35E64C9895A44068278C36382490F443D5D40AC2018AC1B5A39C117989CBB5A8F842994BB9B93C50705FC85D8E25E488C4EBFF710C3D8267A250492F2C6231C8FD9384B08F38960F6CC4656A10CF2899FA9BB702B49924122C81109CB2647B439BD288020BFFC894B600572608438810887A59690289486E4A93E3317D9EB7405A14B986A57D609ADBE2282F10913005098A848CDFC0798F24C45C2C08D8C876774211F891AA4F1362356C65CA0844152808D17057503567650C2A67A13BA71A07381983C3CDC225EFA0AEA9C8FC30583B89486509BC3787B608D818421E75FA8B476CC45085AFCAD709291F4E12FAA9A4CE8290BB6CBA53F7405EDF94DE4596A3AB3CC044B24A1895E68A4169ADC2682E218E8ABB561F564DFB431D7A4687F7A0C07216739F24BF81536A49A519B4B54E7CAAAE46183824C6732439595E0C6A00590CEF2411F391672BBB57CE93EE78C9BA9D24DCF28949EC78E876461CC22B57A9C77ADC47CDC8B15D7E59716B173C716CA25BA93735A19225308D7B1AD0ECA7E9FD36441FB2BC5D6191F9C78C0F34D4AE2119B63250635AE263C536ACB200F898594C1B591E79F7463285F4C5EDACC054853C16A594BB8B1AB8541343084A93AF91656806A73F83C9B77166967CAA934A8A6514EB18C0EBED6B82A4A211273043C801D884C330D1BCE859A7384252C49516F3F6C3E652AB0F7D70710C5CF7D505FCB5002248B8A232619446ABFCC146E0D011B6E3CAB1BFA96FF09C33B6B652DD1AB6F853CC393220281A654E751B0ECCBB53283CBA68A115A0DC6E92E37034EA800BA75853873A1356C6008F608374568C6F61812C40A863B98AD132324E7279A2FAB046A58D26447A8313A0A60DA89DB7573CD1F", + "BF0A7FFED11FB6357F5818B87022671301B1296299C6DB1DD3D9A183483296AA98C693B8192629C30328CD3402E8678038643977931C06008A0CFAA179E90D501520A5AA31E0E2ACA10348A8DB011C6B2FBF99BFC0056D4607135E267DD90179885665C2785D1F5B3C14DA0CE8480D9A893D5263BBA4351D3027524BBB763269A9D970C9DF76B9453659B121491BD99CFD6441FDD9040E169A85514CC0833EF3A9081CD7C2CF63748F850F88AC7B82CC7206402290F5232394CF79CA7F90DBB673F1A0CBE82A7F141AB005454682897F0681C11424EB5274C3AA87A4463A5F0ABF1FA0A34596BEAA73242D363291E106ACECBA9AF41701B7B282BA63E81651C7477414963C84B2BC4A0A65DBF61DE256A1FA150604BAA07900C4CA322F8EB88F21AC83EF150A97E363C92519567C9A7011AFB9C32BD852BFB84021B843BB5697BBAF2377967001EDA31AC6E49017384CCA5380143706228B6F3D19CB03B246E4BA5CC803C670681E2841A6863C0078D420A49367DAA86042F35F27961E82A7C502A22C4461A640742B8BA75023D0A23F520F2B28C216543FC046B245349684103A0DC0CCEB88B59D2BC71221C2E3129EFA33B767862554927D4BF9AF8D44874180C04187257EE8BE7E8376A761B33F30A692438C35E64147C7C537FB82FF75440C8C0DB9572AF87782C9A67C4D7CCF4BB32517277852A8964C34B4D2CA248438A9192A8FF5A631FB302938E91665F69493B342AA1121BEA9723C82CC5AFC97B7626C7251AEFCD96FAF78108ACC4F6CCB2208A3C985A629DACCC118E3495951B6828353F32473E2418907F9BC1A2A2289560DBEA32772E7814FA4634E16B6388B5A84663989592DF3E268D3178E40C3266A59353AB455309246966984DE785D9DC79BFCF1C07BD6AC9E5B715A33CE0C1C816B6A64065628F26633E2FC1A62337B7F7CB2A374B69EF9C9BB463CC1F89C59E4208A3A3F7BB02CE2E030D3C489507882C6F10A88129183803F50EB43C0477D647C9791CA6DB36CCB6617423927CA122876E16286E1575700C41B4470BF26D442CF282FBDE172093107367A4C4F68CBBCE49C5C348AF211084CA3BA665219D54B934FE04C4A406F5D1022F1B433D601A774F43F704649CDB726C959724BA5B57A57775DF389B07986CBF700F8816F07942284F0154F4783466C50BDD51EC1487B9D361D2C4815D167B5686A07C9C966113335F8D4A9B959825A1976E3C6574991A38C44B181751C9E481182A3221700817B1630DADBA2096A1A25477C362329480267BDA956BC250E4B12B0E1D24A2A14541F42B701992087601B71DC0E17FB299ACA6FE803459B8B24790B3D778C299815A83BC9704C6A1302CB41706160921B7357BAB58781713AEB3B95FA06F4658FD529BA2863C639411ED05C9C79261828167C3859CCA3734C270888BD1A70EA778E64AB63EBD3B8AF8894F0A92848F54BA27156303BCDF273AF73646BE282BA8B099BDB8814D61A696A0A7E6A832527E24351B427D05AB14B4811B1B5781A09BB2D70054830ABBCB2822615889500A8C02A8F180CC5679830993AABFF29514882830020128132632942B4E3B29FD0EB1E1DD70BE33B1EA0ABBB9C6AC9EDC32D85DB5111A786CFEC515DB6B2FD86CCCC255C82FB7C2F817CA1BBBE1375C2879540A13C329A792039BB14C848AFF4623E8E914A11E09CAAB823ACEA9AECD6990B8275E93530E44BAE234C2F13917EB94B996702CD774A528BB8A70462254EE5A9AA2137A16289B8A13253075A8D95657E462F8FD2176FE56046A922ABC62B1A6A9E13A9A0A620BB4D32C56E329B3BD04CCCD7CBC5EA7E2BEC66ED769F8E5BCF5E939553D83C65C114D802B7F1214861936E58370929936EA030517C7534D48C1B588491DB855DA76588BC74AEBC61B648E1C1BEE822E1F61FAD10CF07799C90955E02F55D94AB0BB2122421D3C35AF598D5FBC8C6D095B74A08F148C953240287D7795EC36BC1F59D2035C19510749F71840CC7ABEA291027997780922299D93F6EE7C562A1A2BF401480C50991D5409668672EA3718D10AD40C577E0E7C93116A393AAAD17210EDDC7B92469BAF5DB2DC4D1AEB1B1212E0A7073C32DACCBA0AEE0CBEBFA8D2CCC9F6CDA1DA2D62F1BC7742023A333F0253703219DB17B2AB442FD53964276935D4CA16615596CC7C302679E2AB27F6F716248381A5C51B4076B8E72AA1E334155E045C8B7EBC85B2B23F7B40C52E0BE6F2B08FBB52836E9759D66C7BAEC3722CC7625ABA255936220B09ECAD6143A80819AD3CB1FAB73829499C9F19D2DF9A0EDD5CABA5C8CB60780DF86C1D596742D38C25E475D5CA3546685C9D659433DBB05A1A744A4D48ED4CABCF5C56D7838CD22B9C1AE2120A694C100FBA814B31EE0EC3F19A35E64C9895A44068278C36382490F443D5D40AC2018AC1B5A39C117989CBB5A8F842994BB9B93C50705FC85D8E25E488C4EBFF710C3D8267A250492F2C6231C8FD9384B08F38960F6CC4656A10CF2899FA9BB702B49924122C81109CB2647B439BD288020BFFC894B600572608438810887A59690289486E4A93E3317D9EB7405A14B986A57D609ADBE2282F10913005098A848CDFC0798F24C45C2C08D8C876774211F891AA4F1362356C65CA0844152808D17057503567650C2A67A13BA71A07381983C3CDC225EFA0AEA9C8FC30583B89486509BC3787B608D818421E75FA8B476CC45085AFCAD709291F4E12FAA9A4CE8290BB6CBA53F7405EDF94DE4596A3AB3CC044B24A1895E68A4169ADC2682E218E8ABB561F564DFB431D7A4687F7A0C07216739F24BF81536A49A519B4B54E7CAAAE46183824C6732439595E0C6A00590CEF2411F391672BBB57CE93EE78C9BA9D24DCF28949EC78E876461CC22B57A9C77ADC47CDC8B15D7E59716B173C716CA25BA93735A19225308D7B1AD0ECA7E9FD36441FB2BC5D6191F9C78C0F34D4AE2119B63250635AE263C536ACB200F898594C1B591E79F7463285F4C5EDACC054853C16A594BB8B1AB8541343084A93AF91656806A73F83C9B77166967CAA934A8A6514EB18C0EBED6B82A4A211273043C801D884C330D1BCE859A7384252C49516F3F6C3E652AB0F7D70710C5CF7D505FCB5002248B8A232619446ABFCC146E0D011B6E3CAB1BFA96FF09C33B6B652DD1AB6F853CC393220281A654E751B0ECCBB53283CBA68A115A0DC6E92E37034EA800BA75853873A1356C6008F608374568C6F61812C40A863B98AD132324E7279A2FAB046A58D26447A8313A0A60DA89DB7573CD1F96418CE2F31042E0107463DDBA45B8F450D1ECAC1EA58C4FC013E7692F4A81F38BE4CF93D24A99FB17414EB9C36B8292553A1624BF576BDAF68503112ED031F4" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "4B73899DB7091D0D061E532FE2703D7A31494E08E223AF7047A96F186EBA1D5DFFFFFE3ADCE3407E939469D2E9BBAF82F74113B170B04D49AD6680F788B1A26F", + "3BF2CDBEF77C6A89C482947DC20328CFD406A4F6C2DFF523E69CB5005C2E1DB88A03A1C53D328EC4775D380052CE337AAE23868757BE6146CC59C0116F021CD025AF06AA9AE4142928451A45712AF16B0B22FA3DDBC56D85869E896B97B55475E88B8018F6B3EBA452477266B931B9481772185C27067397108AA2C0F68354F83F7414586773578707A2DC1C177BE0CF875A7550EA6930EA3C25092C1CF5928FE227E98A8DE925907B132185A44A82D6BBD4EB748FE2A7D87198783075F569CBA30A3D562125ED5452B202247B768E2BD8A6B2E7263288B38193056B927B2914A5BD728692C69DC43920562542179783E900446CD093C0F93C41321EE79A0206BC7B84B088C9949E02692855EB2C2D940B1F9904F234435945A6D6483B3B85A72FA75EF7E142BEC29171073904C07AB1A172B1105F378053EA9C62A90B6BF6053756AA611ED107188115FA1BA36C13B2C06578DB3A67C648A989AC7310641A5F6A9B6DF28CE663A84869536FD35825C20250BA046028A7DECC231B882F23745057B883CE9C8C67C8169A6C1154E53809AB0120B89DDA5336AA733D09DC7036311839AB371E950DA083BD289A53058574A187352E03C8BC22B2FD9C6D51D437DD6B8C00231C8CD59A45F5C8A4EACE040C391B22134E49B3778270D4E23EA6836374708C9D67C3D570174CA1523093B6DE836E76981C39A69FA58B865B586349A7868C97571EB92F5D1A90B84C5AE21157BDD3096C149B40C057B1A818A08B9291C65A6E7064AACCC468299B82699EF2478B5EB8389FD049FD58351D54324049A2F0FC7DA4571F1A46A7CE9666D724846FA14753272DC3B08CA3387D9F10311F69139B12826EE8A43ABB76E5C3868970CDAD691F46FCBF28368FCA8BBBC69CBE48A527A9234562DA16DBB902BB067B06241F9D4A96FCBBA5FE975D26860F5FBA8943EA3732D38A591BA032823125C45C0A27C850C894A5AA972501B84CF79A9AC274DA6B11941121DA847777024117B261E0C142356358E86B1B9ABC388E292EA3B50CDCA108473BB917ABC33598AFB026BB297903B124A1324A5B73B65A79941998C409426A27F0317B7DB7B04BC94C47961B85996DE0F0A1397C4444883214E88A5E1853558005A9E644D45A52A638A493BAC1865776EF2329C97C1E44F51F4953ACDDF88C22B34366F1258CB2B7CF083FC474431AAC87F1686D0A2A921EE822F3098FD84A79FBE577795958A337487A91574497A89ECAAB8CDAAB3821C8D2A38DFC6918D7226725F3154321BEA5730528766759E95DD973918D6691D0F5621808BFEC3C40977A4D46F47C29732C55F8BE66F64EE0229B6977A2BF830486F20F47C695573AABF91228890CB50620C2D898C0FC0756622CC0A74091C0E907C19001D1A07F73F5404EEAA855315BE7A730B9E4055863C515756C1DC90A36165F75135A3BA11B1F294197B398D1B6987568179FBBBAE5D368A0B86CCAE1AB82A3C6F7F08B5E615EE54964A3A55388F62E160746FA35376E9007B9F78161E02C3C5CA155E33327FC6445DABB42020B9230719D39CB69593299E033F08359102592D8D5B6C5C08647E817800B9B01833FD4DC8CEE76A6973258AFF029273A3620378EA4DDB5A32C82DF49028F00ED7CC885B0518503BFAA37910C33AF0E79EC434E86", + "78F00F469B3BF9215E35C681DB379A41792F523387389526B13121A6F6639EA710B061A341153A74562E72B185E8618DE2CC4A894B3296AC3F26DB0513EA9C4A0293B0380C77C44496838F359B57726348CBA35DCDC5577BD749DEF018F0468A79F05C89017AB0FAB2D3176970189C929ABAD7E6A892AC13D3F0B1652902CF749965378F60D6A4673309B97B4A2DB5B9205B21EB741D8A8894A81CC3E61C5C0AAAA90F66501BC311D10A137FA55D42F2AA735CB1EC28CE1A9875A9D2BAFE356BB9C3B5683341418B408C77C21278677963A4FBD7631A8885E188594AA095B9C024CEE28323D60B920C898DE558CC12307B9245D4AB1B787CA394772CE466199B612E5A692995EACDD1CB63E2CB5B72DC27C88C3FE90C9DE0F9C1C909697D1956127806C237B2953CC7BD118C19C94EBB81A837B17CAB59C792AA195BF551E0583775C85B9EC50CF853C6E4AC962E5071F63919FA02C18480AB1BB83CD60A07FE35B5C9F7025B8A9FD597831EA922376C629839AF9370C569F4A3C8283C3EA40D4D870E912416C536CEC9C44CA186211EE982BAA48AEDB121CAFB60FE616212623D8324265F8BAB906C8FB095C1BAE030402129AD821558B41DDFE8A498702A2F814E5C50CF13034FDC124EC3585BA64052B65A2DB9E8302809696CB59CB403285C19028BE2352CC817B6C60AE04796C9F4795954BB01A89085DC674B74419E968970E822FF0B96E901B7283B774D95844F38157D73396F256447D4842AF7110EB4A6B284CF7EB19C2A4C01540A5DEAD0A928B677CE7A471AA04FA595ACD2E5B2329B1BBBECC4F2859FE56A6E252A22C163548504A203905977651152C53D98EC4BD018CC34597C8D31179416B0E8814992D5682A5566F063AFA7B973C2E23DADF8897369AE76D3ADBD15534A1BAAE3E831FF8AA31679C527A876B5DC5542905AB5B8B2E39928BBE694F2FA8C69AAB5B7157D86CA339DD287E47BACFF03C24E64912BC6219CA72409A821F90B0F7BB3C0D86C51C5B840643B7EFD564D14A29C95880E6843BE786984B235477DE7C181F90357A2A6067A41FDF330CC861E41CC23869834DFE2C4DF1B1F83D80F71CCA3198A08FA3A2AB5E836C2504285021B2548A7F2181FEABBA89B3077DF2065D9FA3D22111B28C069AE917921B305B7BB9D7D3B3A7413CDD4CA545B722181B765F2F613D4298692B21F43D9422567C7AEC258DDAC1FB84690C6287921D0A5A3497720E93D6A3153E5CC0BF18267C07427EEC5BC1EE20DBA98BAD2973B040825B649B7FEF52F022708ED7B90EA1A95A8FBCA67AA7C43160FA6EC598649A346C59C04D70B79600E86FC0B91D0B297874AF3B98393292BA9445DDD65927DF974EBC98B31F886779C180938559E575107444772B89290CCCD21CCBC7A972AAB15029A3166D7390F2EF67EF1D1A71363C1DE60C8D40818D47B6B3D03A0DA40AC550876FA11AE19093F5D9CB6476B11DB653A22288ABC415FD0D4718ED89E4633130B388150D77A210B127880A5117B21EE819808C21D9671601807978FB92C701268CA87847EF79BECCA404B65352F160D6A665E3F251943124701607631528AA1D251EBDA10B7D87A095130A8AC556FD2A55FE1533BF2CDBEF77C6A89C482947DC20328CFD406A4F6C2DFF523E69CB5005C2E1DB88A03A1C53D328EC4775D380052CE337AAE23868757BE6146CC59C0116F021CD025AF06AA9AE4142928451A45712AF16B0B22FA3DDBC56D85869E896B97B55475E88B8018F6B3EBA452477266B931B9481772185C27067397108AA2C0F68354F83F7414586773578707A2DC1C177BE0CF875A7550EA6930EA3C25092C1CF5928FE227E98A8DE925907B132185A44A82D6BBD4EB748FE2A7D87198783075F569CBA30A3D562125ED5452B202247B768E2BD8A6B2E7263288B38193056B927B2914A5BD728692C69DC43920562542179783E900446CD093C0F93C41321EE79A0206BC7B84B088C9949E02692855EB2C2D940B1F9904F234435945A6D6483B3B85A72FA75EF7E142BEC29171073904C07AB1A172B1105F378053EA9C62A90B6BF6053756AA611ED107188115FA1BA36C13B2C06578DB3A67C648A989AC7310641A5F6A9B6DF28CE663A84869536FD35825C20250BA046028A7DECC231B882F23745057B883CE9C8C67C8169A6C1154E53809AB0120B89DDA5336AA733D09DC7036311839AB371E950DA083BD289A53058574A187352E03C8BC22B2FD9C6D51D437DD6B8C00231C8CD59A45F5C8A4EACE040C391B22134E49B3778270D4E23EA6836374708C9D67C3D570174CA1523093B6DE836E76981C39A69FA58B865B586349A7868C97571EB92F5D1A90B84C5AE21157BDD3096C149B40C057B1A818A08B9291C65A6E7064AACCC468299B82699EF2478B5EB8389FD049FD58351D54324049A2F0FC7DA4571F1A46A7CE9666D724846FA14753272DC3B08CA3387D9F10311F69139B12826EE8A43ABB76E5C3868970CDAD691F46FCBF28368FCA8BBBC69CBE48A527A9234562DA16DBB902BB067B06241F9D4A96FCBBA5FE975D26860F5FBA8943EA3732D38A591BA032823125C45C0A27C850C894A5AA972501B84CF79A9AC274DA6B11941121DA847777024117B261E0C142356358E86B1B9ABC388E292EA3B50CDCA108473BB917ABC33598AFB026BB297903B124A1324A5B73B65A79941998C409426A27F0317B7DB7B04BC94C47961B85996DE0F0A1397C4444883214E88A5E1853558005A9E644D45A52A638A493BAC1865776EF2329C97C1E44F51F4953ACDDF88C22B34366F1258CB2B7CF083FC474431AAC87F1686D0A2A921EE822F3098FD84A79FBE577795958A337487A91574497A89ECAAB8CDAAB3821C8D2A38DFC6918D7226725F3154321BEA5730528766759E95DD973918D6691D0F5621808BFEC3C40977A4D46F47C29732C55F8BE66F64EE0229B6977A2BF830486F20F47C695573AABF91228890CB50620C2D898C0FC0756622CC0A74091C0E907C19001D1A07F73F5404EEAA855315BE7A730B9E4055863C515756C1DC90A36165F75135A3BA11B1F294197B398D1B6987568179FBBBAE5D368A0B86CCAE1AB82A3C6F7F08B5E615EE54964A3A55388F62E160746FA35376E9007B9F78161E02C3C5CA155E33327FC6445DABB42020B9230719D39CB69593299E033F08359102592D8D5B6C5C08647E817800B9B01833FD4DC8CEE76A6973258AFF029273A3620378EA4DDB5A32C82DF49028F00ED7CC885B0518503BFAA37910C33AF0E79EC434E864E20997BDEB6F208C3DFF6E99978043E1AC3EF8C7A6FF95B4A108BE4C4841ACAFFFFFE3ADCE3407E939469D2E9BBAF82F74113B170B04D49AD6680F788B1A26F" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "5070646F41C499AB0A1BC5A22AF22DA39EB3EAE28CD4CFE2845101456A3F31332953C78CBE76B378027E5286D85887CBFCD48DE645407417FD22E5F53C9C295D", + "77B775054AA77E6A2A4DE407E0C91CB35C38C0980998F36CCDA707CF689120C02FABC0A3B9D065A0A881D6B3B55690CA685210D7EB4E7426574868CA576B4415207471D528E5390B01587240084B3B147A30A75AF2D5285F5637B690C53603622F4BB38D275AA8848A88106AD9776BE4BCC265166E9F86CF2BD44BA5EB4B76FB930D867E70540F81F59E9FAC92CA9B073846786C87C400DA651258717C681B90A35E41A0C5F4D0A832324CDBE56C1D878E6CF77B25B725E9EAB208183A790A01DED489B530640B036826D74C91D1B044E797AF5231C4C92B28E2672333A6DC17CC8EBC37ED0571228A45FB769623E2CE7DE36874C3BA93922FB41B9FE77C316BDA57AE1702FD0C1CD145A71D24AA66022646F25A45799C82827E62955348729B9D277D5446321F2B51DD6607942A5B3885B14399CF76CB19B648725A60567A626F1737463DB69FAE937E5B005B4E8664D189A34D2B53A4F2684250CB22429FD1D371C6A61C29B796426B5D4A369B9D76406950C4216B56C4499BF9F843DF619E7D3103B3186800E3C2DA72B094587E4A9C34B02C57AEE2C26395B0F7D20BB826A053727A46FA8FC0567E84DB31C546925D5166553524FC1567F8F4676D1CB3895473A8367945B59C3C96B2CCC5B0382821D7B0BFBA11AA470995839C8194A72A11EC4C12988BE637A4DC9281D09484D2755E97F4BC7D91CB074231777A1DD94B8D13479013190E760793217152F83B073041CFA2548B378C16CA2A31FA1C768E603D6C4ACD9B1C3480A805815A02DB30BA621614AEDB9543981238C91841A832B7578301696C8ED10A0173BC2B511F4B159CACF07505D6163AD4C2D5CA0453230F8E81810D63BBF58397B309249A67A9962A8B0462241C40C942C4AA4789520D23099FE03E94D83DF86617F62715877654EFE98043C4427F7A1FC51091FF21CF54F316D0109C18BC65CC91581C3444AFA8AD21434C74D589BE0C224DEC94ADD73CE56192D4E32D30C497FD8595B4AA2212C7924659326A33A449AC9D20D7037E49CE8DD035E8A64672A1B1929B319FD60522C7374E83B601B9206FA16992BC7095F5AAFF7AC947C67C0AD4416D12C1C6F45237A98576D3C2D170759FA47478E3077D10481C8CAE917326515A9B735CBBFFC5AAF31927D29C84C0B6439D62CF995C7FBA82542FD84C91AB9A10515B4251051D8B0C2DB69C7243204A5737EDA10AE1AB89C022BCE6B1C199CBC6D8355DE607C3F9C98C5D7499221C10E20BB343E6918A391803256BAAE91CE67C47BB358F05069956398A6F39B596B3164340368C7B289B8271F25691134BC17A8BA92EE258BB753EE6043CA7A67C9C5474CE70156A3A1A83C4918C302781D2373671A0CE67C816973C6F173B54A5B3F1826874885E49DCA8DA90A4DB7241FA8BC044BAB4E8A58FC172A89D443D933C9537C6B2A1C13335D1C2636C246CC13D52E6A551E177ACA1CC0DF204F9A7A9CAC2949B128B2018B43B7B2DA34BC9D15C2868214B2CC19C9324A6A4B7940C3883FC4A86B5B283F001242862A155375E2E44A250B5AB8B2A380F7C5675C2A12AA185EB0C54276868685B61C6B2ADA789318074A7F760B6021195346B3FA306356FABCDEB4697C3C25AA9327D65FB53B17E1472C9C569D51918B544A2EC2FB19B1EEEFBF591C9", + "CBF94F12048F73AB29545C85D0F758410622BB087508F56377F65709C0542B0A2C576966B8375BBD94B1FAA3B7A0E5141861910F20A53D864C0DD90D76509FEB0359364CB9A2B90939C01B03B6619478B5B41149B028126D275270D3B6EB62AEDCD6C792C82F94337337C1B5A067B33EC346FD1922E35A6DE34CC29E609C3FDCA5852CBB1F35026EB42CB5DB07E56922737690B9CAB9838A1908F2AAE261A543F7CE9DC35656185CDA454FB885B549C809C9A3CC0B95644117761F51A7F01B23D50975EC828A963084D960AF1878BB080850106BBE92367905684B68819AE11A514F574A247C1C21A64C0F2262C02854CAE489AEA36BDEC625F81364F10817A32794C9F2C95551457FE3181072229E9853DD4219754535431936A7017522B4CD56C6564B0218647417B60A1EDC1147565C05AAE55FAC44A127296CCF2CB84D1C9FB73A97919C8D4F74B68C2233F3367C3099246C333DBA9A675056C19BE1801BA82D53876C209460FB8429CF8659C6A55C262A5AD67C7697461F16B1CB8DC2782259A9850A833D9C223C0765BB51043BF97D3BD1573C79B868E123DDA8B031379C80A5CA8B0C9B1D61374163BA7237B3AEF423EE7A25F214A1DF690318C956E918B3DC135E7FC297A83695113BBAB59795613A4C569C0FA14B0C9DB8ADC17078BB11B1F0B77C720A19D6F208E49695F7D7CE0AD5ACFFB8405ED146BA4C1A0EAB57AED29467F6BFD1B29F0771A4DD29BDF3A735F67BAF084A8316DC872D26BB37C1996F5612622C78083C5DEC9C0344440478D6C43895792AC38A97A208ECB86BC6D78881921D53F3787B0230A78608C2631CC592BAE5F87A53CB0B71BA9E448407B4B171124A9EA3B5A60E974C3786875293BB256307A16CC5567B484BF897278A1FE0BB1A2B3B3D19A1C885668BF4C7C9FB144ACC2BAA1F7C6228E68E2F66BA88314657427FCC5786C2005EE3777338341F2921AF6FEC10DD2404A555CBD6E3B19173118245BB156B923BE34F2BF742EF16744D656AC3D85E5A2167AB9B7297469048B43591E47D76020EF958BEBEF7758FA60FB141B436F683F4B10AB6EB54EC9BAC0741C49F8C3075BC08F7505BF3768A110C94EDC16278D5117506198491C223748674C8B46E2A1518A8492C96BC7A14C78F554BC9A4974496048E7C53FB5CBA02D59B5033671737897AC93C6B02548977AF5FC64B8EF19107E7503E617FA55A0ACF7227A53636E4ECCD146B41F2248196472BFC3B6133AA5B6F796AC24956FA90249B64C974676F15A3AB611464F49258BD1586DA66194FB64C8627B8850BCBED2AB0532836B05A33E9F18E3DAA2693BA12267228E40631781B1568A46A90F7B2F579B44AD4BC44F166D0E546A0F4AB8BAB73DFBAA755EBCB084376BEF42EB7989EFA1060202B80A193838685B34D43C3536105165462098A53BEE508C8C77E9F9993597375047980B2483157BC74C844A0C34C1D3363B2FB9105FD360291D472ABA94B66087C7A45B65C3ABB8A4A31D8C3266BE86A77B21E04AC05C3717346684ABA08AD51D982B8EC6476546D9D107EEACC2A643B9AC99C8A549629B05A7AFB4050381816414806C1D796CA5A9A59F911C2360F105B3AE4209C3C72A377B775054AA77E6A2A4DE407E0C91CB35C38C0980998F36CCDA707CF689120C02FABC0A3B9D065A0A881D6B3B55690CA685210D7EB4E7426574868CA576B4415207471D528E5390B01587240084B3B147A30A75AF2D5285F5637B690C53603622F4BB38D275AA8848A88106AD9776BE4BCC265166E9F86CF2BD44BA5EB4B76FB930D867E70540F81F59E9FAC92CA9B073846786C87C400DA651258717C681B90A35E41A0C5F4D0A832324CDBE56C1D878E6CF77B25B725E9EAB208183A790A01DED489B530640B036826D74C91D1B044E797AF5231C4C92B28E2672333A6DC17CC8EBC37ED0571228A45FB769623E2CE7DE36874C3BA93922FB41B9FE77C316BDA57AE1702FD0C1CD145A71D24AA66022646F25A45799C82827E62955348729B9D277D5446321F2B51DD6607942A5B3885B14399CF76CB19B648725A60567A626F1737463DB69FAE937E5B005B4E8664D189A34D2B53A4F2684250CB22429FD1D371C6A61C29B796426B5D4A369B9D76406950C4216B56C4499BF9F843DF619E7D3103B3186800E3C2DA72B094587E4A9C34B02C57AEE2C26395B0F7D20BB826A053727A46FA8FC0567E84DB31C546925D5166553524FC1567F8F4676D1CB3895473A8367945B59C3C96B2CCC5B0382821D7B0BFBA11AA470995839C8194A72A11EC4C12988BE637A4DC9281D09484D2755E97F4BC7D91CB074231777A1DD94B8D13479013190E760793217152F83B073041CFA2548B378C16CA2A31FA1C768E603D6C4ACD9B1C3480A805815A02DB30BA621614AEDB9543981238C91841A832B7578301696C8ED10A0173BC2B511F4B159CACF07505D6163AD4C2D5CA0453230F8E81810D63BBF58397B309249A67A9962A8B0462241C40C942C4AA4789520D23099FE03E94D83DF86617F62715877654EFE98043C4427F7A1FC51091FF21CF54F316D0109C18BC65CC91581C3444AFA8AD21434C74D589BE0C224DEC94ADD73CE56192D4E32D30C497FD8595B4AA2212C7924659326A33A449AC9D20D7037E49CE8DD035E8A64672A1B1929B319FD60522C7374E83B601B9206FA16992BC7095F5AAFF7AC947C67C0AD4416D12C1C6F45237A98576D3C2D170759FA47478E3077D10481C8CAE917326515A9B735CBBFFC5AAF31927D29C84C0B6439D62CF995C7FBA82542FD84C91AB9A10515B4251051D8B0C2DB69C7243204A5737EDA10AE1AB89C022BCE6B1C199CBC6D8355DE607C3F9C98C5D7499221C10E20BB343E6918A391803256BAAE91CE67C47BB358F05069956398A6F39B596B3164340368C7B289B8271F25691134BC17A8BA92EE258BB753EE6043CA7A67C9C5474CE70156A3A1A83C4918C302781D2373671A0CE67C816973C6F173B54A5B3F1826874885E49DCA8DA90A4DB7241FA8BC044BAB4E8A58FC172A89D443D933C9537C6B2A1C13335D1C2636C246CC13D52E6A551E177ACA1CC0DF204F9A7A9CAC2949B128B2018B43B7B2DA34BC9D15C2868214B2CC19C9324A6A4B7940C3883FC4A86B5B283F001242862A155375E2E44A250B5AB8B2A380F7C5675C2A12AA185EB0C54276868685B61C6B2ADA789318074A7F760B6021195346B3FA306356FABCDEB4697C3C25AA9327D65FB53B17E1472C9C569D51918B544A2EC2FB19B1EEEFBF591C98CF060F3D6A20AF76E2A1CFAB9AF1FD3A33E66EEA32977D1C6AA0CE899F6321F2953C78CBE76B378027E5286D85887CBFCD48DE645407417FD22E5F53C9C295D" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "7A9C8AA10EE09CD43C11A315E12506B279720B000F021B771F490A2EB012CD3A54F16968911506FD7719A3651AE8603A45542038C26F36E3041CB614DD13EEE0", + "10C52BF2A21F619ACDCE540E3E87568881601F03B52676566AA279AE151A2D896F3DB848DA4C5A52F4CCDF82989CF818C5849D34A51A8873499121CD57BCB748360FD9040772801C82B384F802792619BA368134603BAC79A32E9B997C338BC3F248BFF7570C95C97017E58D1E527C402351BB14694F18798485AFBB97283A14A608D9B5CCAC1456406F628588D2BB8C249B634B1B3B9C2773FDC0C1A4D94DB33B086D26A443B2A047A970E25801EAF64E5DF661D913AE7F3756DB601DEC8B00C09CA8B42B0F3C3CBC3ADC69893BBD566921A23899AAB31D77095EEA4C9DD788957E28A9399C289DA4CF6E827E692C85EA3085D19B4A456A4E20C1B05170A6C81757AF80457503A1CEF522F5129420A90004B7286038C36ABC81207A55C25CA769A9A952CC6541E22F55263940D80270BBA9573654F448312E16463C48B85ADBC1D0415915FB554F94657881C330F6957F02B4D4D3734D889D9B19797F488E30736950DC6DCA085ECC29C887B25A0A2A475F9837B321C798B99950786D0F040DB18713B50319C72A72011864A9033CF2546D48B7BE9B4C2344359B416C4952936E37945EEFA9477BB347F7685328822AE476A73B618861B6CFC6A964F3EBB823391B8C36BDEBBB839E03B4357AB37FE5986F7C2673A85D24856D7303613295C015A4B49D5950DAE8778746C04B7C83BF68581CE95A084909500759E2D9059AC08F5D6121BD9475F90377FBC9AE9946649EBC1ECFC05533158AEC4BBC96CB028B9C302FB025CA1003E4BBA978911E405C92876898A3C0CBD05801DE1BB835023EC52A43FC18993350AB2CF12D5213BF7AA411EDD62F0DE786B777CAF9C590C5F9291945090B401BB694A93E80BC2DC316BFE918B38819FF49BE215BC2E710724AF77FC4F10E8B318767102BA621C4FB4727BAEB41DF6C530D0BD0A3E74643F925F3317D8E20975AEC6BB994BCE6018C0E85A2396C98AE81415D706019874804703628C49089D4609A14B65C3AC5035172B6C42CD4465A79E69A700003BE6530C402C6415ACB943A5DB6B85D15A37038D5C3A5A89D4C0894250AB88B35888869059334C1E19517EEF37F32B2A6AB169E1E018124708BC9917CF88702B7F886B08BC47EFBA4B2051E9072365E737A37E9814F1C4E055BA8DD3AA79B8A1106129B69F95123D199F3168127C894D1D75D896BCA9614AA98D647BBE64DA21594BD3CB97BF5B2AC55CDA035AF5FF2318265226DECB422B81E07342E34292E066C5F5F013D34D585ED868D9A22022AD3917873637023B24E40B268A6833B99C5D49A77BC7A3A0A103A7E1155C664961DF562765A66E2094417733B52749106A982ECF0295D7713B0B386D1EA43721020C95B23604B7320E5179B01C308A3C18D1C623FF8AD8D76CA6C06B5592154AB612BCE1748E59B6DDE60BA93D77033D231C5D80192553B2C36543B3A70C065649D4188ADC18E8FBC0F5DB99CDCDC68E2A77098E5350397286F1C9406407EF15543CDD0290716461AE000E024C02827B5C9BC2FC8B19D54B3427F65445730BFB4CC32C100CEBE8BAB74CB4402B85DCA9632D2B693FE3982B9513227189F7CE527E5C06BA2931E56E33BF0F7826AD6008DC38B523438BE6CFCA6F2B6B76EE633E18E049D4CB2D36E97578DAD0CEA8AAA41DAC917BD64", + "F280334584CECC04879527AFAA5569BB1A25FF896CD8852F43C60336241629305E88DB5A61B479DC2C0A72B571186418949A9BF0030B5DAA1FB9996CCE541398E2C1052C820BA8A5A79562D92A33D8EA7D4B68A1671065BD865D930205E2592024E27E281C4BAFB0C2C5952E487023A0A57DDD42185D451D6100B423C93FC7027849A2675835B215A25676F11AA02419762B4FBB1B8044C27651802FA401C205215AFAF89D7CD6B5A96C7A3F6B0AF7F71529504831BC4483E3B962DBC5116857B7338DA612193B0A8E6986987004A5050B2E9132212755278A4285C4CC374969604ACC1D508C0196EC418DA6752A41ADA0D86F5101BAF3D412D60B487192A713888E97302EDAC0C144C4BD494CB0EBE8B69A1308D88C59FAEA23BE1C3F7C6B45BD197AD63C2574801AECD0C0D9E70C399AC34CC0287BCB78EC7AAFE070237177945C014771ECAAAD151D5E96B3C68CB2C1D803B5207ABC571A2FAC158FEC306C2084439112078481F15076EA181F386253C9E4629FB4380E161B61BA4771008C55229998F671E4494966D7124C36763432BD4372B0B016B196412D0C9CC3D824590B241EB2F5734CECAEEDC62622C75C64DCA4ED8652D781C69F712B24348B61A3577766339B54B81BE78931BB6B2EA93D490A686075C717788F356746391A4B0061269B023DB6313111F7613CC90429379008F1864C4BB1F9BB866CB50147B0A4FC2B5A8E487FC9A48E7D69C4A7076F5CB323609A41FA7A96B31529AECC7E1911BE183288DCB09921D482A0A8C0C2EB3A3F7331C9AC9F7FB356E625308CF912A57A5F8DD78195D66CF03365CF278813163036666EAE2A4F2A09A26FF13FA0188332B79721971DDDD7A332F0CDF0D0B51D643F62967D35E75EA363330D628B8C46961424CEEA945A05D2C810D77A628C6EC8A75098FC5116A2780B2A6A8867476C462CDC9707016C80E10B6B1CEA9961290596273C030230D2397E008A68B186AC8162BA20E5165C341D15F050D6B9866DB4088333B598E884C804B0E0F43CED106ADA88CE648196AF9B7D5920B905B20D5CD25DEDE570A4D7555D49914C7836D63A813630A8E7C69F40A577EB6B2086B4495A5108CCA65DB3BA96D6E8687C5C557C662552DB081DC48BF44634569A38AAE18FEEA3164B3C60C48520251610B7F63B3233207A538132A3A27EF33B82BC4EF9822FC15375AA12535EA5B93F79B8DF42326608A55C4B170FF3B494713A99105B859170EE2ACAD964C2D80A96E13735E8491973329CE285CD1E3153C41826A818C971243EE8B3B06BA987ADF240E5D3C168E43BF33793C452077C66B0C7345779D229B056946B3799BA8BAEE84708D5575C67A78E1D4664EFF7C65D495DAD058C996C9B83231D549C68437498B03A4714A33DC9FA7D87C5C50816674BA276E336B07A8BBCFCF51CC9F3626A38A39C9BC944930793BB723E7295A4088F1B5670FBF7828E59675A33321F73401184A5D9B6707ECA01D2560A5B05011AE6798EDA313336B2B518C2CFE1B9FF0C46659753B8B1ADCBC94DC197C298E151410A296363C532A758C27435DCB535F8D701DF89C199F41697EAC0BD79A885AA66DA0A1AECF30BA6E614059B16047572F441B510C52BF2A21F619ACDCE540E3E87568881601F03B52676566AA279AE151A2D896F3DB848DA4C5A52F4CCDF82989CF818C5849D34A51A8873499121CD57BCB748360FD9040772801C82B384F802792619BA368134603BAC79A32E9B997C338BC3F248BFF7570C95C97017E58D1E527C402351BB14694F18798485AFBB97283A14A608D9B5CCAC1456406F628588D2BB8C249B634B1B3B9C2773FDC0C1A4D94DB33B086D26A443B2A047A970E25801EAF64E5DF661D913AE7F3756DB601DEC8B00C09CA8B42B0F3C3CBC3ADC69893BBD566921A23899AAB31D77095EEA4C9DD788957E28A9399C289DA4CF6E827E692C85EA3085D19B4A456A4E20C1B05170A6C81757AF80457503A1CEF522F5129420A90004B7286038C36ABC81207A55C25CA769A9A952CC6541E22F55263940D80270BBA9573654F448312E16463C48B85ADBC1D0415915FB554F94657881C330F6957F02B4D4D3734D889D9B19797F488E30736950DC6DCA085ECC29C887B25A0A2A475F9837B321C798B99950786D0F040DB18713B50319C72A72011864A9033CF2546D48B7BE9B4C2344359B416C4952936E37945EEFA9477BB347F7685328822AE476A73B618861B6CFC6A964F3EBB823391B8C36BDEBBB839E03B4357AB37FE5986F7C2673A85D24856D7303613295C015A4B49D5950DAE8778746C04B7C83BF68581CE95A084909500759E2D9059AC08F5D6121BD9475F90377FBC9AE9946649EBC1ECFC05533158AEC4BBC96CB028B9C302FB025CA1003E4BBA978911E405C92876898A3C0CBD05801DE1BB835023EC52A43FC18993350AB2CF12D5213BF7AA411EDD62F0DE786B777CAF9C590C5F9291945090B401BB694A93E80BC2DC316BFE918B38819FF49BE215BC2E710724AF77FC4F10E8B318767102BA621C4FB4727BAEB41DF6C530D0BD0A3E74643F925F3317D8E20975AEC6BB994BCE6018C0E85A2396C98AE81415D706019874804703628C49089D4609A14B65C3AC5035172B6C42CD4465A79E69A700003BE6530C402C6415ACB943A5DB6B85D15A37038D5C3A5A89D4C0894250AB88B35888869059334C1E19517EEF37F32B2A6AB169E1E018124708BC9917CF88702B7F886B08BC47EFBA4B2051E9072365E737A37E9814F1C4E055BA8DD3AA79B8A1106129B69F95123D199F3168127C894D1D75D896BCA9614AA98D647BBE64DA21594BD3CB97BF5B2AC55CDA035AF5FF2318265226DECB422B81E07342E34292E066C5F5F013D34D585ED868D9A22022AD3917873637023B24E40B268A6833B99C5D49A77BC7A3A0A103A7E1155C664961DF562765A66E2094417733B52749106A982ECF0295D7713B0B386D1EA43721020C95B23604B7320E5179B01C308A3C18D1C623FF8AD8D76CA6C06B5592154AB612BCE1748E59B6DDE60BA93D77033D231C5D80192553B2C36543B3A70C065649D4188ADC18E8FBC0F5DB99CDCDC68E2A77098E5350397286F1C9406407EF15543CDD0290716461AE000E024C02827B5C9BC2FC8B19D54B3427F65445730BFB4CC32C100CEBE8BAB74CB4402B85DCA9632D2B693FE3982B9513227189F7CE527E5C06BA2931E56E33BF0F7826AD6008DC38B523438BE6CFCA6F2B6B76EE633E18E049D4CB2D36E97578DAD0CEA8AAA41DAC917BD64CC06B87C860A86B09B65104DAE398225A3CE770695D2B16564865F0C172B50E854F16968911506FD7719A3651AE8603A45542038C26F36E3041CB614DD13EEE0" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "DB0686C838AEF0DC36363AAB0579ED25CA9BC6014CCAF5EE0E6B0783E4C9877EEC7D3B2991DBD5BC973E0F4362DF9B94F2760AA14AA2C8173017A30D6A871B45", + "90C688F598CE9C15B4DB5C652C50088E24A6F9052167BA06A6937C6B58557578BBFA36C82F9B49701A9638C2CC716C91CA43643AF33EEEDC1B20B4B385C1924ABCC9D8419BC4723379628EB731CF99E50E598074F8332B3EF0A48A95477777972BA114D36A0B91CB0C9C2B07AB6B049F815B5B7731BC962C58D7CBEDB1205DEC3A5BD74CDA1A7338B674251726EDF3B397B4A1D0853D1D87C353582BDFC04B1057ACDCEA2136963F44157F6EDBA7E396622AF58F78C9592F626A3FE0BCABBC1B2E0C8978FC921726CAD71C7B491B1955921B77180EAC942CF6CA319FF762BAF7049E4B521DB0B13C8B569886617AD96B72D7B49460BD1F999AB0491D99B64F3DE9017E42B4070B87E57C9EB7F8371B302EBAA05E6CF96284BC2461717CD876AF598B916B8161FF8540103C6706C6C3A2C9378FD986E41342DACC9EECC57253777082478064C3C2EA774E2F190E5069AEE3763EACA541D9B739F0F2257ADAA053BC2873785695577AA9DB718DAA8CF478462569621DF7242192C680E07420557F854BAE99FA2F04E609104A62404A10D9C2766718A50C5555BF524007AAB939DB891A0969DBA08275124ED43C6023354EB42C60A0945F61D18BBB57C38D2802CA7A478B980C2D81A894DBA6B236A791759AFD2AA3B36317F494B07DC402406917AD1737B9F078D8215B09220FA334839CC35CD29C8FDA7022E1F49268470AA129772F8A2293425CBA4558F3C291596C4EC210C215750E5C4861324403A6B785D71A411140C4AAF82A2A0387FFB7C884B79856F724F30510376C81B70537AD3080F42A128895C2785C47C6E36A2EC728AEE1C3AC08378D809CBB945E5463A10DC1961D769E6D808CFBE74C5C29BDE0899CB0A778673204A581A56449086432C7125B5310CB5EAED20ED509A90ED03134587BEE30730226369BB5289DC89DF3168A11522395DA9261475CB129832FEB5D8DA32F397AB21E890F1916175922CADD6BB312D46BB7E77377A873425B78E182452401180C220E13303E7DDB395765813C4230E012B2C6A3403DF6127FB9407C8CC900AB1B7AF37FB411A162DB911AB85BBB9428C30A60371259ED0B8E6ECA9EB616630573419DA4C8EF054BECA84D9BB4744ED57638E93770BB4AA5198D952CB954F932FD42692681BE3CFB263422845CD19DF4EA0B1AA86FB967375E8582B8D2B351C95CA5DC076A4647BA0403CB71A62570ADBD8A2754C1C4A103408F26CB645A52E6545170A00300530D6026336AD8283D1ABB40C244D4F1189BB65BC9CAC334DB76BC0C5009256803A17EFE1532A2974675682DE2547CA9A0992FB777FAFA3AC7819C4D8BBCB7793D038717AE260284C1755DD026B59C9784953DC80392B3C3AA7ADC2057F4BE924987F635CDF5E317C9FB21D1FC5B8FE66C352122F9C82C1354BEF726B6FE9C25FC015A1AF6261D31054B030EDD6B1A147332B10850F5C49B4CC87769A5A32237BC295BC245A8044448361AE03CDA71995C861BD2720E93280F9F12B35D852A18156723A5A6EBA4B572FB24EC2CB387017BE984C45CCCCC43D0897A1A3B36321263CA6586055050A6BCB4298D4F653E03823DC84005805A2353178349C6845ADB91B53C1919754648ADC4D99FB26BA2DBA0270F501C10DCF0B57736F4A4161D9CC8188D2AAB7EF6", + "FAF5BDE1C50F9A7CB86D10B227D62621D0635342C3EB710037E480686B037DE8B8D9322D76E8331C3511BA29794A6575CDFAC5FA1191D6182FBBCB2FEFB3694A20A9CC247AA784B705780D770884F5327D10EA52697B3ED58C8A9BAC6C0F671EBC86BB2BBC8B06D3A4E0D21DCDE90E14690722A03B47E22665427754A8AEBAE76FA4B34B5273C84800C04ABC16D7C1C5631623BB3ABACCD7873817344E31240E3330C23783CB20A948B49ED71B395C05AD08996868A736E8C6B04215AA54919CCBF92B7837CA2C5794F5D357AC895E14538722B082ED31A91B2A429A8C0592319EA5EC07DCF592DC7B853B00A412AB332D13A252BBAB7CB4C0684C93019596C3DB854FA9C7CCB582051A3E99B50B5CA291A8BA0B463298C241374AA4624E81A71483116AE57CF073932930BC29124921CB7FA8FCBF3E44C94461A71E1105EBA764CD9C491FD9A200E48C6D5478C8DB9F934CC604405D462251A5FC795EB1B6180788AF6810C758031A84ACF75B702DF54928F74EA4E8ABAFB50FC81504B5E54EFD0AA241779169C34C0CA6AAF4E9710B4BC6C5A649EAAB81B53C62C3935050B66C14469CD3B2514DC8243325288887C86D87BF8E656991687259B020CA1C39E1F1014132616119365611C7D2328ECCA6245BD9C3B995C52C85036C3880D681932AF50C4D627DD4340BB2FB105C648D181388783982E18A90F6F10050D038474A85D2D7B025F81B7D914948558910BB6AEC34CC60FB3C96B850A31CA2806BC967A0845CE48D678A209549328B2AC519A2088FF66103EC2A3A90A85BA91A1043563559AA690A51C61CC5E0DB6919987AB562AA97D3B28ABC676325672F18202EB6C7CAF0CE48FBB95E5C4E2612AF15161A69A9A4AC388AC59076D634A530A1A1BC7A29801B28569B3059F32E065170C5A742B9174595D4A657C87B019BCC39A88A904194CFA73DC56A13FEE833F7675650F67115B858455BA5CCB0B092BA8622247CA9B38FDDA36C89C7CC7F649E69671EC4637449015B22D8028D1C1EAF641A21EA44ADFA63FB0268349A5551263947A575B64C4D6EC20FD8578A925457E6518D0DB581ABF0ADC8E900CDC445DEF9B96E507CE71116B5348598A5B49D15366EE780923C911337476D4BCEA244BDB56257FC8510BBE781C5FAB1A05099B1375C596B103ABB2709CC63AD747CBFBC4F1BD6CB1C4B1C3DD9649318AEB4468AE71897DBD61C403C5D705CA1D88ACEB0E61A752785FA48247E9902EF676CCC51489D710D14F66D288A5E62B421E3B351569319C8F20FBD873AC1A0A467B58C6A7141C3C507FAE33E8AC0C5C0B52E66B293C3764C1B20716E876187963E942917CC6BCC4A58BB7DEB8DD99063FA3CCD8C905EDB6481A1B3796B0C977D37CD5ECC20BFB61FE706A6E18CBD879A8E76366BA77BBCB90440D143AC99EA0F6E536EE7157BBCEB76C3657B3727AC922B672B224861483E19308D41B17A4EF5C50B5B0E68E0AF3C143EB3A403E262BA0BF6047EA56F79729A5AC797C1D98EDEB3269981A66CC62712F2A22F90AA849A074CFC7227C62738701425339CB3F3B690412A2E144971649B9B309CC6A4B0E9999909319FA14C6C643C5A38D88120A5AF0D5647A2E9CD90C688F598CE9C15B4DB5C652C50088E24A6F9052167BA06A6937C6B58557578BBFA36C82F9B49701A9638C2CC716C91CA43643AF33EEEDC1B20B4B385C1924ABCC9D8419BC4723379628EB731CF99E50E598074F8332B3EF0A48A95477777972BA114D36A0B91CB0C9C2B07AB6B049F815B5B7731BC962C58D7CBEDB1205DEC3A5BD74CDA1A7338B674251726EDF3B397B4A1D0853D1D87C353582BDFC04B1057ACDCEA2136963F44157F6EDBA7E396622AF58F78C9592F626A3FE0BCABBC1B2E0C8978FC921726CAD71C7B491B1955921B77180EAC942CF6CA319FF762BAF7049E4B521DB0B13C8B569886617AD96B72D7B49460BD1F999AB0491D99B64F3DE9017E42B4070B87E57C9EB7F8371B302EBAA05E6CF96284BC2461717CD876AF598B916B8161FF8540103C6706C6C3A2C9378FD986E41342DACC9EECC57253777082478064C3C2EA774E2F190E5069AEE3763EACA541D9B739F0F2257ADAA053BC2873785695577AA9DB718DAA8CF478462569621DF7242192C680E07420557F854BAE99FA2F04E609104A62404A10D9C2766718A50C5555BF524007AAB939DB891A0969DBA08275124ED43C6023354EB42C60A0945F61D18BBB57C38D2802CA7A478B980C2D81A894DBA6B236A791759AFD2AA3B36317F494B07DC402406917AD1737B9F078D8215B09220FA334839CC35CD29C8FDA7022E1F49268470AA129772F8A2293425CBA4558F3C291596C4EC210C215750E5C4861324403A6B785D71A411140C4AAF82A2A0387FFB7C884B79856F724F30510376C81B70537AD3080F42A128895C2785C47C6E36A2EC728AEE1C3AC08378D809CBB945E5463A10DC1961D769E6D808CFBE74C5C29BDE0899CB0A778673204A581A56449086432C7125B5310CB5EAED20ED509A90ED03134587BEE30730226369BB5289DC89DF3168A11522395DA9261475CB129832FEB5D8DA32F397AB21E890F1916175922CADD6BB312D46BB7E77377A873425B78E182452401180C220E13303E7DDB395765813C4230E012B2C6A3403DF6127FB9407C8CC900AB1B7AF37FB411A162DB911AB85BBB9428C30A60371259ED0B8E6ECA9EB616630573419DA4C8EF054BECA84D9BB4744ED57638E93770BB4AA5198D952CB954F932FD42692681BE3CFB263422845CD19DF4EA0B1AA86FB967375E8582B8D2B351C95CA5DC076A4647BA0403CB71A62570ADBD8A2754C1C4A103408F26CB645A52E6545170A00300530D6026336AD8283D1ABB40C244D4F1189BB65BC9CAC334DB76BC0C5009256803A17EFE1532A2974675682DE2547CA9A0992FB777FAFA3AC7819C4D8BBCB7793D038717AE260284C1755DD026B59C9784953DC80392B3C3AA7ADC2057F4BE924987F635CDF5E317C9FB21D1FC5B8FE66C352122F9C82C1354BEF726B6FE9C25FC015A1AF6261D31054B030EDD6B1A147332B10850F5C49B4CC87769A5A32237BC295BC245A8044448361AE03CDA71995C861BD2720E93280F9F12B35D852A18156723A5A6EBA4B572FB24EC2CB387017BE984C45CCCCC43D0897A1A3B36321263CA6586055050A6BCB4298D4F653E03823DC84005805A2353178349C6845ADB91B53C1919754648ADC4D99FB26BA2DBA0270F501C10DCF0B57736F4A4161D9CC8188D2AAB7EF6F1C50CA8F8AAA6A1F54308C2E5B76DC3E39B7BA57A71D92D3F23CF301582B187EC7D3B2991DBD5BC973E0F4362DF9B94F2760AA14AA2C8173017A30D6A871B45" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "36E643CEDC0D0280DD44E16A1353494861D1358DE8012B88FACBA1E6DADF01630510E6BDED49D6D031CC930AB638EEDBCD2422BC35649D1CA33017B3DD344D71", + "86156716C2B1560C028D02C77C4512F196A9F2A1C691F263FACC5502E5074EF45DE2023943710B0E05C0CF15B0CC9CBC3B3861D30195BD682E18E79BC1F16A1FC6C71CCA2344F298C46B95709A765277577285294BAA4505A73560301EE894CC8CACB60DD8C8B897CDBE08C092624CCE4682B47188A791BDE81A36ADB219AE9C0787C5503856CB3C9727ED60B902C927C24BC07A838F53A868964021BA7C656FC04AF866B7AB031203DA2990AA043F1B858DD7821C0754BD94935710A8756A992EE2047AF22CF4B1205F5C911282A1D1E270B98ABE896334F30092ADF0477A747DA1714EC0E12284CB54BF9BCC382020E2462156479C71181DD50B7A87F882FFB3965724A8712C4D69379811C3B94116C415DA8810F8CE2F054983C780740683EAF032F0B33E8F712E8AD6557C7071D17C5837F63DCE245D8E4088066819917857D08C807394926E795B0E23CDFBC65C61989C058750AB0AC419625C17391916EC324D77110C9C8F337B6D8843C077F7B61C564332528BB155AA736A8409AA13D7F1B099BAA9FBDC321B9BC0D0274823C3255E402CA7C173E94C804BDA6C1C12581E5AA1C62A07594C249098C975A59CF3632BC3F49A4AB6C0737420CB177E5BDC2D38D9B20BAC0C62381382415F399926CE62030F710952453E6E207B5B1AA42369CF6AB65DDCFA9D7D9B89F1751085B87F03A55583C117B1ACC550B06A960939FA5319B35109E7D5BF283322D67717831CAFCACA5C0CB126F7126A92745B26DB740EB35ACA510B9B2A098DB1BD8EE908155A14DE9ACC2153907378A9B1C289A0F414D1B333BE8C9B403ACF5FB738B8895CC9C596E64B13B10B95E226867D641A648CB46EBBCA192AAE8948CE0C17593003BBE7650693012AAD4CA45B786CC2126B381409A4403E2EC8C323845752925D00FC3B08897D1FD37E6718534AAC841B767F28C47FD247822921848782CEC825AF523919887A4C8A38B88B6B8C069424A35041AB824CD7C0115C78CD497A02E9DC950FEBA5C5D823C026A8C34ABB44FA9EE46B773CA336B0D299A496ACC4719EE3A64ECA008AE23A0B3895AAAA0A2BD7EA44BE45A06A522D9FBAB09E95C999E4B2E061937DF575AF1782BD25394D70A709BA1DE4C473CAD928BDA68672407115E6C4AE984FAB1049A536C0173BB2BE372B722674B065A318FBC1D8D34F16788297A31B22B14B8A87944147A122BC4533C2CB70C39DDC48190AB748BC20A18FF54596ECBC7F2A16ADFB734182192157BC05EA111DB0054D8A781A94A6524B68219B77D952B158B2179FCB5DB36AAE3E28282994A5EE59B0763882A72664FA1088E09B9DC006757C00064523B54771999D841B696B20261A74E1F2881E037ABB92B8182631091247AFD79D66207867726AC7E22118F922B3F7680EECAC21A9BB44215075A5A049677F8164A9BCC79E1B4645EC24A9980140BBDC367B4527D2FB75C1885224B40E6B7324C831401E10C15D625B641773055199558BA9034C9684D3C3A970AFB6ACA632D185FAB084B81101645C58D6D160237A37323605BB84C7E8BA2F386088D0A3AAD8EB2465889F34F028A22A8B95212D7A76BE7E944209BC321D7C1189C6B4B0700941D0899B711592E3E56180E6A98701E8176636CCCFEDC7A600F67DF39D1C0272A9B59183847D", + "193764E8C7063573AF8AB3A13CEC909D580308E875944455D6437A420B7EFB831A60587E53B19695D2002343BEA111C0EBC752894842E6D387A7189637262388310BDAC27A8C34C0F7B4991292B0A8C1723DAA21A2973FA6242D23728A1AD0443C3A6663E49616A1C3E4CCBE027255E64823553C2A620010ADCA1245CC0F9BE00E4D05734DC2ABF27815D7BB9FBDE3C0D8C0917677480C23A39346091AB4A3C0096919C344E5853BD8936144DC05BDD09F3CD1237FE63AFCDBA1DAB957DCCC93C8F77C113C02B8C51B25C80C0720B0D78019139A2E81A9390FD6A3D7C5B45EDC4BB98849171ABA872B56E033465AC32D50672BA4160F4234B53651AE2D3519F751C07D46A91E9544D43739B2A9436B5C99E2D71F4CD52E07430FDCB71DC77C2B31AB9B5E800FA591A9612B478BC5771CF9015B17743743CF0467912FDB5361107E2A7713C03300EF15A1E2579362DCB06D1016778455CA144DA357B2BCAC66763910CDD7BEFB7492E8928221B6758DBC7844136C10F732C8A195F0E0B883A2072208760DA15FAF3C4172F4058D019918BB09CB25B7A6A0A23A934A4AD5C2C0DB277DC45417EA1FC948BCAE31408524658C3011889AAB16C96DF7D76F0EA73C6C24A08BEA6C73686586C8B84D3B594CC37C500B03D5D320582935BB0C921E0C402C9C806C9A4D252866F617B00D776157E591E0D45362EA5C4CA0AE8979B01F3B4D36444BF2E2AA2AA1908F181865AA19300CAC797791DA033D73B61D89E75982004130CA6388CA0FDC4520A65736420022FD2A938DE83C9AC28F2659471F5051C092318FB46858C6626610CFB22B0F50D80C3100B684874AD19B47E0435AB9768A5C68A3A087B5FFDABD1670904BA75B91BBAFB099816EC52E924494DA502FDC4880A448C5E7513F4B7415F8A7663CFA85BAB5C4619C29E0C774E32C4559998F06A74D59B9BF03BB8A4D6789E0C3680A38433C769FD827B33D8CB517A7CA757931F95A9733B2C24DE68C02185659D38DC155A313A24C1E3C49142CC6F33AC7B118C681E78586894E8260C218C1BC815CA35B5379124A37D6349CF25A01783BA969562A7166B23D026B8E36818D68235967CED90A1A9798BCE82937FCE8C7E6A0BC51D7C33AB20FA20BA3396A40EDCAAD7CB66AAA3A3D09C95E6E21CA206943140014C1C3402DB1CC8D11947039A3547791A0F7C75C1A3B898400FA972A99869552C977FF9A91B2F7019167590A50A6A8F24E1D1552F913048312B44926C88CB48A55E51A94DC69EA87954504C4A107070B27A9C1E90211C9CC16C1B52FE01C0F87307BA041CBF462D937A769563139C829EA757513431D6259B526A7C75A942EAE18C6627B7E4FE812BC1CC5EDD602F217B75B12B5EDC37D76794D7E64A047FB6598BB5D4D659743A7C9D606BE0F7CB6E489921E952D7C8997BD19A1D1E22A83532658E85296A94FF1BC7BA438BB03C4CC7A788AA7724243D028EC1161346B1BC4D82080E7271C023545D6ABAE058F9ABC3DE4A83434820E1554799DB8AA63C465F10B00ED053D6CA14BFBC6C9919553BC1C8331090595B91DA94B8972DA764158B416A7C62C6B692C6B6FF0C25791A45F62D11E01B5BA18D3BA21CAC8C9146B86156716C2B1560C028D02C77C4512F196A9F2A1C691F263FACC5502E5074EF45DE2023943710B0E05C0CF15B0CC9CBC3B3861D30195BD682E18E79BC1F16A1FC6C71CCA2344F298C46B95709A765277577285294BAA4505A73560301EE894CC8CACB60DD8C8B897CDBE08C092624CCE4682B47188A791BDE81A36ADB219AE9C0787C5503856CB3C9727ED60B902C927C24BC07A838F53A868964021BA7C656FC04AF866B7AB031203DA2990AA043F1B858DD7821C0754BD94935710A8756A992EE2047AF22CF4B1205F5C911282A1D1E270B98ABE896334F30092ADF0477A747DA1714EC0E12284CB54BF9BCC382020E2462156479C71181DD50B7A87F882FFB3965724A8712C4D69379811C3B94116C415DA8810F8CE2F054983C780740683EAF032F0B33E8F712E8AD6557C7071D17C5837F63DCE245D8E4088066819917857D08C807394926E795B0E23CDFBC65C61989C058750AB0AC419625C17391916EC324D77110C9C8F337B6D8843C077F7B61C564332528BB155AA736A8409AA13D7F1B099BAA9FBDC321B9BC0D0274823C3255E402CA7C173E94C804BDA6C1C12581E5AA1C62A07594C249098C975A59CF3632BC3F49A4AB6C0737420CB177E5BDC2D38D9B20BAC0C62381382415F399926CE62030F710952453E6E207B5B1AA42369CF6AB65DDCFA9D7D9B89F1751085B87F03A55583C117B1ACC550B06A960939FA5319B35109E7D5BF283322D67717831CAFCACA5C0CB126F7126A92745B26DB740EB35ACA510B9B2A098DB1BD8EE908155A14DE9ACC2153907378A9B1C289A0F414D1B333BE8C9B403ACF5FB738B8895CC9C596E64B13B10B95E226867D641A648CB46EBBCA192AAE8948CE0C17593003BBE7650693012AAD4CA45B786CC2126B381409A4403E2EC8C323845752925D00FC3B08897D1FD37E6718534AAC841B767F28C47FD247822921848782CEC825AF523919887A4C8A38B88B6B8C069424A35041AB824CD7C0115C78CD497A02E9DC950FEBA5C5D823C026A8C34ABB44FA9EE46B773CA336B0D299A496ACC4719EE3A64ECA008AE23A0B3895AAAA0A2BD7EA44BE45A06A522D9FBAB09E95C999E4B2E061937DF575AF1782BD25394D70A709BA1DE4C473CAD928BDA68672407115E6C4AE984FAB1049A536C0173BB2BE372B722674B065A318FBC1D8D34F16788297A31B22B14B8A87944147A122BC4533C2CB70C39DDC48190AB748BC20A18FF54596ECBC7F2A16ADFB734182192157BC05EA111DB0054D8A781A94A6524B68219B77D952B158B2179FCB5DB36AAE3E28282994A5EE59B0763882A72664FA1088E09B9DC006757C00064523B54771999D841B696B20261A74E1F2881E037ABB92B8182631091247AFD79D66207867726AC7E22118F922B3F7680EECAC21A9BB44215075A5A049677F8164A9BCC79E1B4645EC24A9980140BBDC367B4527D2FB75C1885224B40E6B7324C831401E10C15D625B641773055199558BA9034C9684D3C3A970AFB6ACA632D185FAB084B81101645C58D6D160237A37323605BB84C7E8BA2F386088D0A3AAD8EB2465889F34F028A22A8B95212D7A76BE7E944209BC321D7C1189C6B4B0700941D0899B711592E3E56180E6A98701E8176636CCCFEDC7A600F67DF39D1C0272A9B59183847D846DA68F43FAAB1C87C7F643F94A7C2D6AF02615B528780A079CD1161C7EA94C0510E6BDED49D6D031CC930AB638EEDBCD2422BC35649D1CA33017B3DD344D71" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "268D0BAB19A0A48FF67B114997413679B98D65D0CEF327763950FED9CC6B845F7E140F3CACBE34156D8729D55F1AD8008D20F17DB6F5D436CAB76A4EB5111620", + "20385CAD97155EEB6E481526A4461004E00C967A06B34A583197C0F40160048909FBBB420A299C2DB35A18D2C1DEF317CA817110D23F889BCD500A60538463AD0AADF1B45A58EA0D6FDC39F37B95E51CA2F530BD411CBD53F0474431936F739233C6289A6C9E7F6009518B740419ABBB5022C9E32B44ABAA8A028FF4D8BFFDE7AD5DA7539CBA10DEA652757951F0E3CCF3629E8DD37C99137F841176B4637C7C476CC900C28BDA2F0AE9CC26CB5238B017B3913F62A7401ED79A88067FB9162C89C97E237393DFAB2EF9620A78466957EB4E6C1273334B5A0493B8CEC572276B50CA0996879B07A9E6229E98A34EA94C626C7BA709938D0484DC4064E0F9BCA965739BA58968077A4DBB703C0272BB39917B171AF49A6E352714025C9BCC858D0B4AC28B88715C2944FFAC266D30532AEA5409537DF28CC838C018CF76C003366F69E4C34148839DC7BAFBA09FF633203803AFF921AE160482CE5B075AB2689245A21C2A16059828699584E79836E36695EC9446507C8E32FB8A742C4E0B5016B9FAA81832599CDAA4C6A90883412646E674F2EC1A8FA9A5DC8CB9D44BCC37271736CC802EE39DBDD4C0004D7A79E05DC5D8446EA9B79B40194FE4231AF659DFFB8635980731605F7F46A1AC062B05EC5A78E57681950A653866D83B641B5728A4242250808B24BBC6C244AEFD07511C683404DA640F5945E82C0BDF530E5169402F222F8B3B4F69E157D265CB22E75C02B18180741F19026FA425870EA5AE25DC2D77B43483704961F125819992E0E736376C033ED4434A0C9511E4407794486448B318F995F377584AA86997026E97D0091F0523CC856205551EA9847ECCFA4DAEB8051E85BADAF41171003B07841DCC963BA4E7414754C12257CB90077EB54BA8A9B264E4401AA16534D9D78DA6675C76D57B774222D22CC77454A5ED2BCB51BB644AE76655DC34FDC1960AF35E05F118C136643C123B24759A83451030B37CF2B25D79B7A36D899EF257B813E49EA0F83D2A8A4BBAB101AF197085AB11B438A1EAA090ED4B19D9BA41017416AEA7636226A419FCAB082252AFC8BB350CAF43FB8D93228BAE0420BB6785D2582470F20506EA73F704163B9A07AE033981547AB6D61832BBC0D3585E418AB1B17800E6A3180202CAF46A2C99CAB3ADB8CE3EC714A010839BAB0CE29B2609E0C01AC4B97B429D33D9CA4789897F284567D74BE923C647B51FFC827015FC53625C93A1BB9F92AC16684A83931684C225CD9D2B29CC8B7A21EABA26F706B4491863C5C49E88197774AD50814BCDBACECAC1B2401CA86FF8173A393DD5321D0DF5B83DD9C72C30738D97B9E7F07B0C8C9913793D7B98C58AA3966C0439B97AB0A894501F11301780702BC4CC4EDA4D2D60726AC5BB82941D6012A644947417D5635B0676626363A0A53B8C9B0DCFD02AADB2568334122F79C6E408339C899C355C2E64CCC46AF62F6C4AABA263610746CF4DC153F00673681A3495C932343094F10962B352CF6B134DD0CB131CB634BB7915A80A5B9F2C783D4AA6A21755C0F12BF755074E4A86582193B7C81509EC43EEB47D23C143583870983AA7E25539E22828D6F1329029051A472D5237C3C9D9A5BC9966106C17806B26DA64FE0BA8980CC81765D9E8F3B0033A6C2AE2D79374ED1B14D2", + "56293DBE04723D18215ACAC06AF034BBE132494B0099BA909F0AB2C87521810A089ECB93AE28034543BEB3EA677A260A0A775CD2E63C0C3A9108C50BBCA2BBAC32404D0B18B0AC256B935AC5B74AF422C913E837E43B4A97A79D54F90D887C514EA9638B504CFAF351610CC7391347699207CC9644ADD9C5C1B397B380AE83891ECDC07598FB58975CC4366B94A72A9DBC353295692747A4CD9BB5836E596EF8081F68C42EECA234B6245D2E88A381F2BD32FAC4F42CC066477EA16319CDC5B47AF898FE1C79CC7B3A154B000AF31F54C832819B8C21640CA9A1135822243622CFD5C8B6AC622D5263BCB6E50961589DCD2A8FF027687BA989ECA04EB91899C7031DA340B211957C7F0A8B1A7347B35886D1531A7C83A7CD396DBEBA4AB2C44D277BC5AD6133A9641C64A1623F622BEC5AAAE2F65270430829D315074846BDC633CF1024F9D6470537A6DDC88126007AD1500A769899E703A43F11C20B261D9B042CBE6C053DB1C33E483DC431A7D2F750C45909B8FA8C024828239C1AD6652779CB2E63372B7196A626BA32974A8D716C0207EC3187CB84A095CD82105190190DD90A71B000AC3BA68893AA730BA06B5568C13A393CB3F44E35D284452591B8122C0F2615DC440D15C0C37C6B6047B943FEC403996C3E88D24438456FAE9A809FB5B9AB06178A442315B06F88B394D10A178CAB3483B98BF2AC689A9834B046B9ED63896720340A94AAF1609C966BB4536C8D40A98852B45442C98521AAA8756102EEC65B1FA00A0B64A60791358F9430C8C1655EAC5EF3E7C10662A08BA0928AC9C552839B2D222E0004CD7478830D7957117033F1CB8D6CF0892E67BA0AE48BA6DBB045BACD603C62C9267E2BB86A98E301A23847817100B8181BFB1BB295C029C06233E6DB8A2A777B2D499D89AC769E7B5237F2CCDAE7852642618B111E86DA98EC7CAA403B006AA10DA28B599CA33CEA741E42B29B11AC40292064B7A91EDD015695AB2C21D625767BCC3A9B60DF125DE134A41F2A88A168166E73B58ECC57F368704D639B3486486A8877A3A44A75940A68C45ACE6BCC510496D77692E764A15ED8A377BA9B90A75117C791DFB87F44BC336F4B022099935850C0C160B99F764F9ACAC34062AFF5A05828B6272CA92DE5E55D06476BA616461C4C6F2F042B8E69571EA2AC36490C8F9739B77C84B8C0C9A596BFAEA36B7A50B4C90AAFCDC394A57264DF839D7396C581F479AD153696D94AB83457C937301C80A15DCB5668A89017477FE31204EB411163A70AFD918D50684938E58BE75517C87854A862313253B0D9A33CC75632DB125FC97548D0DC21BAD24E83B93F8CF67D21093FC84392A5B45A4493767C60282C4012B3A14A96862E4A26198A73C57301C443D67B9AF17CBDBC072B192F8F640B53B174868956FEC1BBE760694B4C83910A0AC05CC3D6C318A566414AF97A253A832D006855EB4B30212AF5A24A558C05AF8B7EFB60AC35E5527574A131F59424C39BEA0086FADB32D045A2954914CFB475EADB119971282750796D9ABF470195D0B560DD19CE37F91B3486740F1173FE5751572021DBD9293BE42156810F7A74832AB499DBA206E4A4CF90F66D1637AE2D965920385CAD97155EEB6E481526A4461004E00C967A06B34A583197C0F40160048909FBBB420A299C2DB35A18D2C1DEF317CA817110D23F889BCD500A60538463AD0AADF1B45A58EA0D6FDC39F37B95E51CA2F530BD411CBD53F0474431936F739233C6289A6C9E7F6009518B740419ABBB5022C9E32B44ABAA8A028FF4D8BFFDE7AD5DA7539CBA10DEA652757951F0E3CCF3629E8DD37C99137F841176B4637C7C476CC900C28BDA2F0AE9CC26CB5238B017B3913F62A7401ED79A88067FB9162C89C97E237393DFAB2EF9620A78466957EB4E6C1273334B5A0493B8CEC572276B50CA0996879B07A9E6229E98A34EA94C626C7BA709938D0484DC4064E0F9BCA965739BA58968077A4DBB703C0272BB39917B171AF49A6E352714025C9BCC858D0B4AC28B88715C2944FFAC266D30532AEA5409537DF28CC838C018CF76C003366F69E4C34148839DC7BAFBA09FF633203803AFF921AE160482CE5B075AB2689245A21C2A16059828699584E79836E36695EC9446507C8E32FB8A742C4E0B5016B9FAA81832599CDAA4C6A90883412646E674F2EC1A8FA9A5DC8CB9D44BCC37271736CC802EE39DBDD4C0004D7A79E05DC5D8446EA9B79B40194FE4231AF659DFFB8635980731605F7F46A1AC062B05EC5A78E57681950A653866D83B641B5728A4242250808B24BBC6C244AEFD07511C683404DA640F5945E82C0BDF530E5169402F222F8B3B4F69E157D265CB22E75C02B18180741F19026FA425870EA5AE25DC2D77B43483704961F125819992E0E736376C033ED4434A0C9511E4407794486448B318F995F377584AA86997026E97D0091F0523CC856205551EA9847ECCFA4DAEB8051E85BADAF41171003B07841DCC963BA4E7414754C12257CB90077EB54BA8A9B264E4401AA16534D9D78DA6675C76D57B774222D22CC77454A5ED2BCB51BB644AE76655DC34FDC1960AF35E05F118C136643C123B24759A83451030B37CF2B25D79B7A36D899EF257B813E49EA0F83D2A8A4BBAB101AF197085AB11B438A1EAA090ED4B19D9BA41017416AEA7636226A419FCAB082252AFC8BB350CAF43FB8D93228BAE0420BB6785D2582470F20506EA73F704163B9A07AE033981547AB6D61832BBC0D3585E418AB1B17800E6A3180202CAF46A2C99CAB3ADB8CE3EC714A010839BAB0CE29B2609E0C01AC4B97B429D33D9CA4789897F284567D74BE923C647B51FFC827015FC53625C93A1BB9F92AC16684A83931684C225CD9D2B29CC8B7A21EABA26F706B4491863C5C49E88197774AD50814BCDBACECAC1B2401CA86FF8173A393DD5321D0DF5B83DD9C72C30738D97B9E7F07B0C8C9913793D7B98C58AA3966C0439B97AB0A894501F11301780702BC4CC4EDA4D2D60726AC5BB82941D6012A644947417D5635B0676626363A0A53B8C9B0DCFD02AADB2568334122F79C6E408339C899C355C2E64CCC46AF62F6C4AABA263610746CF4DC153F00673681A3495C932343094F10962B352CF6B134DD0CB131CB634BB7915A80A5B9F2C783D4AA6A21755C0F12BF755074E4A86582193B7C81509EC43EEB47D23C143583870983AA7E25539E22828D6F1329029051A472D5237C3C9D9A5BC9966106C17806B26DA64FE0BA8980CC81765D9E8F3B0033A6C2AE2D79374ED1B14D20CABBD18BDB77BE0105E0F27849555A22C339A08553030157F7CD88B0FB4CC987E140F3CACBE34156D8729D55F1AD8008D20F17DB6F5D436CAB76A4EB5111620" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "514AE29EC3C21981216B74BCF91D5CA87D81F1A541162B515CE193B77A64B03359F631BA2FDAE1A68A77AE066C4186960506823D2D1B8383041178A568A3F8D0", + "D830433E9378B6B9AF56E7591FEB8D80C63E91A7281A15C7DCD156D55967FEC57B00B99C5ED171318298CF06CF32C1645DC10DA6C71CBB761B43F501744740C82829EAD216FD99BBB2D6A30A960BC3E6AB6901765BAAA8B97B8CEEE283EC9B82CC6484FB016D439354B37A14342B6E019B6B8106C5D4001C1957338B400D41D56A3B927F4D86928AEA684362C715A3B47AA36AA1C33747B64453F11C9065BB042973B905AD6D858FE7889DC4CC50B17AA6D2054586CBAF9FF258B946832D42C98349223FB3657B3B6A963608DAE210A8F4907E1A94A724B29568B2EBE3429E0B85955A8E0B824C4966C69EA39B29549D21CA33B4DBA247409724DB9145A576572CBDC13A968E263DC3689CF7A43EADAB01E4682EC2022E09A3BC058B7FA038804BD207938000EA318963E045B9620BA33324F2826638540ADFF006AB97A883C203E6E212E67821B233C8E4EAC58BD7BBF84866A95CAFDD203A5D184EC4398BBD497E96971E05A2201CD558A2D3CC6135757F165BE167792EC964B5744FA20B42F07767BAC461D6BA2E17BC0679CC9C30112618C1B23B995B65F58238E844D7B020650809C061556DE7A66794A72FE9C0E2837358970D3A5A3843E813D9C202D9820BFA889619A2AB7BC542DEA50435F51F36453B61A4A58092B0E5227E0E7CB5753333DE2580AB2CC4BB588CE7056910115D1CD05F499654654790B2D00957DA009407BBFEA17A1F06CF8E741ABAECA9560416B753BF0FE8197D5077F657695C61835478CCA56774A3D91A22825E8FF4861688ADCDD7262A742166D58831249892A107BA4A4F73406556849D87E49B8FE1637C0B0144B483B45239BEDC5E1B5148A4D97E3CD49BF2463783066D8A288C4282ADBDDB65D05C9037966B267542A4D798C8D90F020283C963364B41A4B63C8299B7B886D8347FA901903B3066CB3078C6776201B1FB95499551AB0BDBB92298A1B2005CEC6C0D0D4C41C800AF4BAA9F118431ECC38C338CAEE6F8A11D955B582100056691372102EDD2B46FB830AC529081B90E16F0AEB1A8A6461B4E1A22282AE2A012313784182268140FF1F0AEFCD96493F25098645B9C40A0DF702FF7652E8F1184DEA510720A002F29B458236F3FF5469BB3C5DD11C158A64A33793C6C5314CC778CE97BC7FC504147AB67BC4B12F1333CBF15CE6188522F54ACCEB011EBA62AFAD11ECC8030ADBA9A43945DF9E1A16BE05D158536F1B00882771AACF2330486576A5B39A9C7909F223976CA7862611F1825BA1345CEFE6B14FC5917B93086DAFBB0A4E292AAB687CF49A0FA30B04EE686EA5821DBCAAE7A792BFB487B656BADE7853E86DC4C05E7A741624388DC7FF61501848AC4375B2C9D937F76714C3593C23EC34559F27FA22715435A131CFAAFF8C5A51F145427C44895C006C71A59E35B55CC7C6568D58C43E4AB56F593E32BC7F485512BCA2D4F653332E3B19CD71704DA017F768F7C440086049D5FD39D67B8CEA701CF8A7B33E3810EE8A213BE84BD19534FA7572AABD01AF974C65F81A4BE0793C3F36E4C72A088324CC2B1A168E1B4C6D6AED45860C59BC2700CB241F08435ABA92BA02609B97CC8C120A51C3226B83DE45503A7560AAB797EC45EE09343FE6CB311F0D33E3547841ED0D05E287E3FCE050F5164F2E2D3BC6C", + "2DE1004769769E2AC03C6312D6B4C46918244F4033DB8C7AA85230ADCC6B1C3671C307BF7ED895FCD77E15B156962CBC421A36CA202B3C55186FFB51CAA274CB30CDB4E16DFF9C285FAB8CBB47B9446B1239E71AAD424FDA1699AE277B26D2B4404C005A438E0343C246E8104D66A9E6424DBCBC88BEE549020716C9EA2D85EB519C61248C80230005915779658531BE1D89AE10FCAF2D688C169BCFE1676D748C549FD72414461711658A4948768992198CB15DF8F0A1CC947C03B5826F98743B99129D085373621A861424C81A92865B2FBC639FA8D30133A2A1B0D76173DC70C7CBBA718413C5029CF34C452B01B884191A9F6BCD7EE766DCB46196717099C374CD2AB1A4DAACD1E09583018C7787CFEF72A196779AC383179CE8405F00780B2B9411393F3E8B37D3AAAF8C0B61D37989AF331DFFB18D76F159399019749035FAA0034DA6AC878BB070553F841938241852F9C35F794020ECB80FEE947E20B7AB1FE4553E7A2FE2094FD6B282EE5B56AFEA93E938899D10A8C82A6871777B51961F84A4ADBD873E25106C5B69362A8C2631643C7A7C9B4F53A6707955FA79A2ABD6CDD5C33CE124B9BC55491916610F73ABD2801EB31A1559D0132BA44810F3C565761ACA565CAD94AC2C36BF363B9641C9AEB2736CC7EC49D1FAB5805131E49CA6DF331CC7CB91D4E2603C2610573181D838110F68AB5DA84B78743118CC409DF3B13E38BB1C691DFE51018DA64EB0B02128795768953011F05B72B59C25C21D433A6092A86CFA9529287AB7D44512C6C929B758359673A896BBB8D70203097267B8A9A22642161CC050A5522BFC0B7ED47188EAA5108F311D8E940C1F104763F111A1965984E0BFD0B2CF824B4F80676DC63B6DA0F41C108273BEF76A749499803893197A5960806CB51391185B5078E251F219701F285A6482A142412F9CAB5F65EBCA31885EB22228304607FD26AA45C61EF2087B75627C44BA8E6F7A50090A2C19D864D0C1564E18BCB4C89FFD974C5EB562BAC38ECD66689738C3FD5832A58B091255C14A21ACCFD62080EC051AB587A0F00D4F50158BA411A956C7F0167D8D2B55A09354A29A32D573C5C1770C40E085F32945FFEA21F3B4982869C7C26B2B3B6A49F6A944DB10126D998A709A5924722FDEC5CC8C054DA5746546E99A0D6025FE524CAB4B45BEEA588EA5B4EF1317FF528B91B587DD05B4A4241C48712DD4017298E1276025452BC94DFBE7C837A1480841518ACB74ACEAAA90638795976F882A67EC027A8CCA6F84C78D11046FC8FB8F442497108C4EAEA00AE5EBAC7F36709F406351535BF76A532A0468A40084FE0695C8A32F20636462D320C512CDAA0A318134CE9A72AC971114D14A4BA9B8533417274C59580AE083E5FCAAAA711C2A5B3AEC160FF65860735C6D76E298A92CAE256A152B79564394789DA8484C5A7E65F060D1C0C9B4020B8CAC66F16197A782A0A9F013ABFC7FC1E52458614C87F02F24179450776659C13269A390171372E196622A870DADF125320434587C1FF3D80966F06197B2283FB4A89537BDC62192078AB717A77C3B910D6D5C86D4689C89A9A6CBD87429EB96E469462F4934BD289F62301D1132159E6554D830433E9378B6B9AF56E7591FEB8D80C63E91A7281A15C7DCD156D55967FEC57B00B99C5ED171318298CF06CF32C1645DC10DA6C71CBB761B43F501744740C82829EAD216FD99BBB2D6A30A960BC3E6AB6901765BAAA8B97B8CEEE283EC9B82CC6484FB016D439354B37A14342B6E019B6B8106C5D4001C1957338B400D41D56A3B927F4D86928AEA684362C715A3B47AA36AA1C33747B64453F11C9065BB042973B905AD6D858FE7889DC4CC50B17AA6D2054586CBAF9FF258B946832D42C98349223FB3657B3B6A963608DAE210A8F4907E1A94A724B29568B2EBE3429E0B85955A8E0B824C4966C69EA39B29549D21CA33B4DBA247409724DB9145A576572CBDC13A968E263DC3689CF7A43EADAB01E4682EC2022E09A3BC058B7FA038804BD207938000EA318963E045B9620BA33324F2826638540ADFF006AB97A883C203E6E212E67821B233C8E4EAC58BD7BBF84866A95CAFDD203A5D184EC4398BBD497E96971E05A2201CD558A2D3CC6135757F165BE167792EC964B5744FA20B42F07767BAC461D6BA2E17BC0679CC9C30112618C1B23B995B65F58238E844D7B020650809C061556DE7A66794A72FE9C0E2837358970D3A5A3843E813D9C202D9820BFA889619A2AB7BC542DEA50435F51F36453B61A4A58092B0E5227E0E7CB5753333DE2580AB2CC4BB588CE7056910115D1CD05F499654654790B2D00957DA009407BBFEA17A1F06CF8E741ABAECA9560416B753BF0FE8197D5077F657695C61835478CCA56774A3D91A22825E8FF4861688ADCDD7262A742166D58831249892A107BA4A4F73406556849D87E49B8FE1637C0B0144B483B45239BEDC5E1B5148A4D97E3CD49BF2463783066D8A288C4282ADBDDB65D05C9037966B267542A4D798C8D90F020283C963364B41A4B63C8299B7B886D8347FA901903B3066CB3078C6776201B1FB95499551AB0BDBB92298A1B2005CEC6C0D0D4C41C800AF4BAA9F118431ECC38C338CAEE6F8A11D955B582100056691372102EDD2B46FB830AC529081B90E16F0AEB1A8A6461B4E1A22282AE2A012313784182268140FF1F0AEFCD96493F25098645B9C40A0DF702FF7652E8F1184DEA510720A002F29B458236F3FF5469BB3C5DD11C158A64A33793C6C5314CC778CE97BC7FC504147AB67BC4B12F1333CBF15CE6188522F54ACCEB011EBA62AFAD11ECC8030ADBA9A43945DF9E1A16BE05D158536F1B00882771AACF2330486576A5B39A9C7909F223976CA7862611F1825BA1345CEFE6B14FC5917B93086DAFBB0A4E292AAB687CF49A0FA30B04EE686EA5821DBCAAE7A792BFB487B656BADE7853E86DC4C05E7A741624388DC7FF61501848AC4375B2C9D937F76714C3593C23EC34559F27FA22715435A131CFAAFF8C5A51F145427C44895C006C71A59E35B55CC7C6568D58C43E4AB56F593E32BC7F485512BCA2D4F653332E3B19CD71704DA017F768F7C440086049D5FD39D67B8CEA701CF8A7B33E3810EE8A213BE84BD19534FA7572AABD01AF974C65F81A4BE0793C3F36E4C72A088324CC2B1A168E1B4C6D6AED45860C59BC2700CB241F08435ABA92BA02609B97CC8C120A51C3226B83DE45503A7560AAB797EC45EE09343FE6CB311F0D33E3547841ED0D05E287E3FCE050F5164F2E2D3BC6CFD877A8C94D335F49037D8747B51FD7201CB246CB7D62D893DD8EDD16933B17659F631BA2FDAE1A68A77AE066C4186960506823D2D1B8383041178A568A3F8D0" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "631D57398086D55F1D9E2173F46E16B78F0390D24D586C58F08CF2A74F69C30941DD2D8B1CC8C5A1F7E9155F19EF800D5283B852A83BF590A874014628CD4832", + "BD797B63B11B6058BABEC60C095773A1910E0D505BAFE29AB639B20B4B8C120B21BC3C0DE2930A6142AE43E6AB5339042FE15B396917157BA114B639B8712990810018453E63F1CDF6C524C189B85AD3863F2046F9B15A8F569ACCF1AE19A057B14846B2083BEED4BD5A9025A032A1DF46042D935754EC8DC933907CE5B911053EC9B563F68572D2B7354EF0625FF94639937B5A8809EF4238550BACA7EAA4A9520B50F5BA1463399B65101CD89EC3F9062C07B34E898636035C1C87A3C6C3884E94B6F923A53D3CCDB86CA7F9B85BFCC247DE2504796A1DDCA1C59D8CBFBD83C0ABE531E97252718AC8D2297D59B01830186BC2918E9C818BF851CB976224FFA4C132B00BF5D12696A714A970616D2AC467F7BDCB59C7DE84062F15C08A562923F6C26C4340905B947F3BCDDC8314FEB711C97B8D0B19CC49584F1F9C29EA52B8C5DA2B6405B841328A9B8C98263B19F8279ECFF35A68541D4FC2C930197F3AA6652E70CC102C7236C33AC976B629297B23DBC79C771D710A6E493261EAB13BD78990A790AF526A5BE7B18FD2365EAC287DA51A643EA27F17DB531DCC1827F6B729A508B4274DE2AC4E64A8C89D0AA1F5458075981496D79B40F188A68281BFCAA3C2E2B97EB1227B93C19671BCA9B0C8DCD25C0A23ABE4F87037623EC85C3CC09632CB76A46C8766F328742965C05C138888B0387CE36049565093486AD53809A2120D48596C116597A7A13468766E95C73AA5CCBA06A190BB0373BB92769CB3518A2980055A07B48C84AE48C2D4DC41C483201692BD76507767D5682525A921F36ABEB97AA217BE02CA9049710058D5336D128435442EC0328BEF5581E89497481142093A15A7088DFEA61EB43613FF3A5CE7570C2D4A1DB0E803A0D09CE9A0BD6E269CC43C9D4CB83A88B43E845521CE217BE03B34C1EB621B858604F1B941C7C5A5384CCC286996A0A7A504C17FA2C8BEE47E40748507586392D72347B6AD19322264633614E762D706A115533F6F32656F3597D1236CFC0BA04BC32088F1889A7902E864BBECD62FD6245F5F32CB30B8151AD822D19C76442168309970B01A547D31BB89B2C684F04214D1409739BDA69B70D026C4BDEB932BAB2C36B85F754AC11B26B40A128602F3C2ADA17C2C9026EC8526D5E5345163B180528334CC7FCB63CD7992ADA895A395D6B7124186CE6418954855521C7177CBB1D95870D908689869B0F0D03E5AF099FFB91A47CB6A5F473FE6355A8B8A3195E0ABD87A83C4E0CCEC905941B0444217227BE93BDE218E7E817397E544CA502F4880C0D77A45CF70606363AADFD7148C663C97B49BCBA5B3295460E30C39E14A866A63923B32556D5A4C5A103EF9160DE526BFFB193A6A228BBD8666F5F67A775C2FC0209D67C344B543535CE66820734041D2462DF9850DB89AE443A3AB5891B259310B3AC39CF4407820820C6B599D5371E65B38ED480957FA70B2642C30818760FAA1A0E743DF569AB84019C4A73692DC9E2E624C86A617F8424C80A3B04C4BB434CBA572FA89E5C0658DF6B920683EB75248AE98006572B639742A364498F258823FC75EEB6ABB3A3CA31E901948979537088669463A386A8334643B3DB7489801674B41E81578D994E34FBF57E0D5052ECCB8E165A56CE8F7C596EF03BCDE63C35E", + "C9118E1D51B0988218035C4CFAB1C229A4C546B154AFA03BF0E2984A9B607D7B2AE3869610864BB91225A5AB3B10F22B21A0644FB06F4E319A5ED1A191634F49B9CE8C0507E1B0712A54B919366438C54466721250448E56D5053E095861D35DB5CBB01D765F3120B223890F44F722BF66545DC68FB37CAE6B5341204116CB496D31D3155984AD8156260D23C85561A9306A7A8ED5AA9A0163DAD86FBFF65FCDF22C85012AEFB219C85944EF771677031591D7A3A426614B50411AE3B047300DA0062D3E4792FC39C0E20A94EFFB3752661D5F0B37AD26A1CF610AA540C6542439E53B8E7E3CB92F58C609AA9CF99162001A03E7410C2384987DE6A333AA7401F671D6D1156777BCC3730CB1117E01386FA72C07634774BD53391F629C0256ABA8623D73671954548CE47A72A7776CC2DCC3C2A4916FF93F07769A7FEAA543B037901A3CB32751EF3529815792D85AC1E37294A86155AD6A058BE0A1EC269AE241C107AA51681B79BCC69EE6B00D467C18D45544D3D5429743B5F1F987307038485B09EFB307036531D88111F81B2F7BCAB9BCBC98913580B30170E7846CBEB88DCB2AA3DEC87295D311B000904C47BD6E9821563520CBF6510405A908F58D56B7B0B210342ECBBA26A8875145BFED5A8DECFBA151AC7DE77A30A0B5CDE691C59418AB6A7BA3C8782EF61CA11DFB03A70526A8F313A6F197757A640826C1C22C48F7E1213C4A7AD60037B5020F315A8ACFB021A3814B02B53CF4C34683BCC6A6CC80B2A98A19A6732EBB2E044A23E924516D14519564C0D768A9D63269BE8AB4B9AC19E410709D79ABCC58070544389C75A7ACEA2755F15BE7693B10E0203E034B56D3C8DE722D2AF2747AC30EE2FA9DF153731FE7CA3F17881FB2A29BF6096E70A2BDBC241CB2756854029C499B495127D1FC4B09A9A78A21983861053D174BEEF9A2E8612FA3405440E1BE5E8B9340277F38BC376FC771EC523D573AB3C5A208C74A1E2D772BD3B45050C01119D859604C9A1848A73A67CB4C457E631B834CE91DF6D34255E66054009EBF21CA951CA670811EA3A6CDD008CACB78308D27218ADA2268CA76283286AC17AA73EC2ACACA472C72870417AC8FEB9273199DCF962757D911F137A5B2F8437FD43575AC69FD618017962F79C9C265272DEDB262DEF79F73F73CB0577BA767B0711AA376E5A63C49838B343F5CBB06D0E3A8B1445F11FA1FEE8B7309413DFEE5BE971C8745383C0E1A1B5F7364B4D8869A51B790A379240A4D011A4027255A8F8C4655F98F63188E2D3A6A0D962D1E14397A65030528789A6C7FD37964DDA59B2C93822C7B2EFA288E77A3C9027C298A5193CCD07AB9D73112B77D5E68BADB806B8819318D2A85713A7AD4272370ABB2AD124342A505E408CE5F13263BF20FEA470E84463AA781A1A41870C56C9C0CD2721BB86C06427680A86925106EC391AD33597C5A25AA4961AC7AA6CDE5B157B26883B808CC10B6B7EE20267B406649521ECF973769A983C4EB32D06996E0271CBF4CCEF2C07B5E0C6708CC908D210B7F20361E094393B1B31A744190118F84487A225B24B2F9A50473C01A9CC4FDA2C433F9A7DF0C333CC33932C476B8639404CC9DB66238BD797B63B11B6058BABEC60C095773A1910E0D505BAFE29AB639B20B4B8C120B21BC3C0DE2930A6142AE43E6AB5339042FE15B396917157BA114B639B8712990810018453E63F1CDF6C524C189B85AD3863F2046F9B15A8F569ACCF1AE19A057B14846B2083BEED4BD5A9025A032A1DF46042D935754EC8DC933907CE5B911053EC9B563F68572D2B7354EF0625FF94639937B5A8809EF4238550BACA7EAA4A9520B50F5BA1463399B65101CD89EC3F9062C07B34E898636035C1C87A3C6C3884E94B6F923A53D3CCDB86CA7F9B85BFCC247DE2504796A1DDCA1C59D8CBFBD83C0ABE531E97252718AC8D2297D59B01830186BC2918E9C818BF851CB976224FFA4C132B00BF5D12696A714A970616D2AC467F7BDCB59C7DE84062F15C08A562923F6C26C4340905B947F3BCDDC8314FEB711C97B8D0B19CC49584F1F9C29EA52B8C5DA2B6405B841328A9B8C98263B19F8279ECFF35A68541D4FC2C930197F3AA6652E70CC102C7236C33AC976B629297B23DBC79C771D710A6E493261EAB13BD78990A790AF526A5BE7B18FD2365EAC287DA51A643EA27F17DB531DCC1827F6B729A508B4274DE2AC4E64A8C89D0AA1F5458075981496D79B40F188A68281BFCAA3C2E2B97EB1227B93C19671BCA9B0C8DCD25C0A23ABE4F87037623EC85C3CC09632CB76A46C8766F328742965C05C138888B0387CE36049565093486AD53809A2120D48596C116597A7A13468766E95C73AA5CCBA06A190BB0373BB92769CB3518A2980055A07B48C84AE48C2D4DC41C483201692BD76507767D5682525A921F36ABEB97AA217BE02CA9049710058D5336D128435442EC0328BEF5581E89497481142093A15A7088DFEA61EB43613FF3A5CE7570C2D4A1DB0E803A0D09CE9A0BD6E269CC43C9D4CB83A88B43E845521CE217BE03B34C1EB621B858604F1B941C7C5A5384CCC286996A0A7A504C17FA2C8BEE47E40748507586392D72347B6AD19322264633614E762D706A115533F6F32656F3597D1236CFC0BA04BC32088F1889A7902E864BBECD62FD6245F5F32CB30B8151AD822D19C76442168309970B01A547D31BB89B2C684F04214D1409739BDA69B70D026C4BDEB932BAB2C36B85F754AC11B26B40A128602F3C2ADA17C2C9026EC8526D5E5345163B180528334CC7FCB63CD7992ADA895A395D6B7124186CE6418954855521C7177CBB1D95870D908689869B0F0D03E5AF099FFB91A47CB6A5F473FE6355A8B8A3195E0ABD87A83C4E0CCEC905941B0444217227BE93BDE218E7E817397E544CA502F4880C0D77A45CF70606363AADFD7148C663C97B49BCBA5B3295460E30C39E14A866A63923B32556D5A4C5A103EF9160DE526BFFB193A6A228BBD8666F5F67A775C2FC0209D67C344B543535CE66820734041D2462DF9850DB89AE443A3AB5891B259310B3AC39CF4407820820C6B599D5371E65B38ED480957FA70B2642C30818760FAA1A0E743DF569AB84019C4A73692DC9E2E624C86A617F8424C80A3B04C4BB434CBA572FA89E5C0658DF6B920683EB75248AE98006572B639742A364498F258823FC75EEB6ABB3A3CA31E901948979537088669463A386A8334643B3DB7489801674B41E81578D994E34FBF57E0D5052ECCB8E165A56CE8F7C596EF03BCDE63C35E3E1D2325662A1341606CBA9E873AA7C17A5E8AD155CF2BB8CC79921DEE28BC1741DD2D8B1CC8C5A1F7E9155F19EF800D5283B852A83BF590A874014628CD4832" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "F13DEA91F234BC45FABEB82F6D5CD6C7A1F8C9102A0E9AEA90F16E98283B3D4CC4D62EC083507AC0523EBF0B9BDE3B1BFEA833C5FD66451FFD6EE26DF40E83BA", + "F18BCD6F83AD4F75CBE34115B3C36A75E52848A18636C28370F42837AAA40F38B3805C01D4076DB6389D755C2D734A4A12B500A53B7E3EFC952BEC8F7FE509A0C4793DCAA5F69956E560C45D80AD3A1090AA4ACB48450A62001B44B313C2B599F8D27D59139559C325E521AE3DA18C48AC92098036AE014293BC4E32C4C235686C7C528AEE0B5D027B3DD63511FE236FDFD2463617B08FB21DBD778183203F33C512E413695B000582044F6F49AD4581572CA76A4B40BE0720AF09C7C75E39045002BB81E47A2DD30F7DF26D30D85F8355751CA4283CE05700F5C11A2C8BA39891B9616D5FF3B85382A452F57859B8C29ED38D2D1B676D41989ED10DEEC077E5BA871929A36B51595185525536B797DC81E9309D85BB1EE442AE3E5511D068276112CA80C4718E4446947B2BDFB71872A3600EE2351A6C7EB968A932AA6FEE78B6A93C42386772E548047944AE3E2199C51BC162A1AC1C96393F4586FBF7A43C28345E5B48DE666134C9628D075CFF03BD96987B23809DF9070E0DAA9C83166D7F774D75903ADF40892B2092F5E9371D720AAE95072DE6994E99C51129AC6C1628FA204B17CA317A74B0027B4872B8B094AC6486A1712D0C4C3C112AA8703D14E9CC0D8192349C3E76B119D352333275B40DEBC9EBB00267D6792DCB24D6389E515C1D7F232013D6B59A061C25B79C7BC84C471BA566A11247194E021025EFCB6B84094ECC5A62C499AC54CA1A04CA1A3746A109E86448E667EC9C3E322761565CC3756CC351F9C3A2CC63A7B81E7FFB9ED2C0735003A58760BE0D63896A98A1576B81522614DFB226579314FD88AFE7CA9704E4B410D13125E35AA2C478B6A6B4888082E9127ECEEC8A93000B0AC46EAE9154A7E347589267E2CA9476796EE73A1F2C80C6377300109CC42A09C809B0A841214892F67BB626B17E986B0B12AFC49B1CC4018019036FF2EA085A20C7FD027FBEC68DD327B0E842BB7E0A69F14C99EE974C882270C244AC1B2594B9BC61DB5A3B3D366CD88B8A0A436DB386A0C3996A777869622A03F401A997645AEAC954A2B749183C6F5D987468A72FAE6685C1A273E856260F2918C6D0525666A021CC8C7BD18EF8939339CA4633D224E5FB3C4711C890685F0C5733EE92539690B957B0280A2515E77686CB899B7272A26B37A33A92B6BC6008272A38730B2A06446DCD707D5E140BFBCCC39679ABFF7624A970BDD945518894945B305FDB709A8EC147FA9599D34719959AB00A132B215C1D712B5005555B05BB7F66253B705315512A05B8D591600C8DBC19B871B3794CC13CE260060D77CB60CA2CCF7543A8E270F5A48DD86015FE3A9A8C2CB8474C2CD27B04112CBF1E60675739263C050015C4C198B87A6D494FD44816BF64AB849831B2C88A257037A6024C01F96497D0297D2CC74FB0CC487AB2FF81B2B6EA04CBE00F164B67FF5247179C42A94B0C2489074EE89FD74151E4F99CDF24808C6453F1886BAEDC26D649B7F7782AF660A829D7B423D067C2344568023854A6963D4074F7E404F1416E78E96526158398512387D02339C57AFC9C2740624B47345972249675424A39892A0FF4C2DCBCC80B8046D0921BB62C65AD2397C0CC5D775967E4BBD727B318F1CD37987FF7E9C966E7F37FBB5CB8AB943804196060F7A1CF00", + "6AB50A4B017ABDC2A191C4C4E09490D9241E200B145EF0C81C170B6BBC82CEEA8F90025937D65720B20F8F93999D273575117AAAC6A95527CFA475CEC524BD7F987735F168AE97C26112605CF6A5B16336C860AF45ABBAA499956973BE5E1BA6AC1A1E61ACA807543C4921405D7B0BF3493C927104137C6B962C9B7FD846B21779014B4FD9E4751EE63A80F2AA8CD729A3E64F277CB68263623AA5AB60A48695CC032AC014D35673AAF0831804855DB83DFF209B7AC86552A80FC4ECB155545E360C956063BF6F0A942D5A1696FA136E18C8A63C983B0CAB4B09C808E14D774408D06A18DE41A9F39C1CF7D545CF5B3FFE49A8A21214048271D58BC846629B011C50F74C8074945CD70046A69A9B6073C2B1976B28C058F37B16E4147E998077F3900E2F58733C38CAC1B20F5A0789E09551DEE572E138B3B2B41326E7B5BF7A70E4B55025F2246753098E9508DEF460D824A884F6C91504BF4BAA5A0DD0B65E139827F5B995974F1AE8BD14BB97D7190B7801A4D01B9AE441158AB4239F79910051B514315677A89B75B24F57E6219E8371F9A57573D1AB82103B022C098A7B740E6A96C6CA1B89162AE6731922E969F1047325B612454683782C2A3AD27EE5728000E2131676CCCC293D70751335C17474A5B90BF536D8FB2D5690B98DBCB86BF840CD5272A8E10B71069FAE34872676C15512CE87926E4481C4CE4CBA6FD981883A255C2B78036C1EA6C6AB6FB7601624C2F47872D69A3634A9B24BE187A1F491B2380BE4D9676E74C7314718D148A9D29A3D0E80CB4D8818B5C4BDF2D4BA11F28B19569239785574B38927B95D80C412D92B4E0D3B95A8B81B5A93A3A2D94B1EF600C6439D8CC132847B7A868A519D29A65975B87871C95338C24DD4527EFB9AD55AAB7B8B1CB09B0E52E2C917E51BA4B699BE0648A677AB9A343471B957A322C5B996C793A55787B1AF277C9A9389419B6227A96334E333BE2A93C46A2732821C955F18A2A93589756ACC4D826C79EB8965497B0B812EBCC0AF39383CF54180CCF75F3A842323C45E271A8E910C89DDA18CD7CB4738172A041CCF7DDABF3C08CF1FE3A4D254628BB949AB660D2BFC2FDA9A3BA9EAB6F592088E65385B6BC253A6435FA8B4D3EC22A96892516A0B619990B16C1EBBC13D16439DA7010CF213857AD12DC237ABCDB135988501516532A7FC75A1C6754B345D8DF488BDB3239D1A9AD0F74EB57866F908CF68513EA3837C62063B89B5BB49967C8AE808C6E50086FCC8A0C24E37B3A713483BE0E813E9421FA1290691016D31E72696545283F66ECC3531A9179241576B4CA36F2A8812986515F99185C4C959BC8335EAC5A485723B3A004088603BF18C879972168AB391E86215119B2727CABA86DC4CB831B6134B6C9D404B72D056D1955948EAAC19B14FE15BA74B3B067CBABC00E739A98553A2C8BDD35A5EB9CABC9C497A0392007AE419D3407D598140F1325D3D6469F0283BABFBB2D8BC4C3C0369574759F872B31A12125E2BAB902BB6862880DEA97DA7A49AC10151BED8B064B3110B3C4872129F6D75A01BE215A94670E19473723261E37872770342EF02AD59F62D753C38AC31868694A3427429BA8BA1C7A660F18BCD6F83AD4F75CBE34115B3C36A75E52848A18636C28370F42837AAA40F38B3805C01D4076DB6389D755C2D734A4A12B500A53B7E3EFC952BEC8F7FE509A0C4793DCAA5F69956E560C45D80AD3A1090AA4ACB48450A62001B44B313C2B599F8D27D59139559C325E521AE3DA18C48AC92098036AE014293BC4E32C4C235686C7C528AEE0B5D027B3DD63511FE236FDFD2463617B08FB21DBD778183203F33C512E413695B000582044F6F49AD4581572CA76A4B40BE0720AF09C7C75E39045002BB81E47A2DD30F7DF26D30D85F8355751CA4283CE05700F5C11A2C8BA39891B9616D5FF3B85382A452F57859B8C29ED38D2D1B676D41989ED10DEEC077E5BA871929A36B51595185525536B797DC81E9309D85BB1EE442AE3E5511D068276112CA80C4718E4446947B2BDFB71872A3600EE2351A6C7EB968A932AA6FEE78B6A93C42386772E548047944AE3E2199C51BC162A1AC1C96393F4586FBF7A43C28345E5B48DE666134C9628D075CFF03BD96987B23809DF9070E0DAA9C83166D7F774D75903ADF40892B2092F5E9371D720AAE95072DE6994E99C51129AC6C1628FA204B17CA317A74B0027B4872B8B094AC6486A1712D0C4C3C112AA8703D14E9CC0D8192349C3E76B119D352333275B40DEBC9EBB00267D6792DCB24D6389E515C1D7F232013D6B59A061C25B79C7BC84C471BA566A11247194E021025EFCB6B84094ECC5A62C499AC54CA1A04CA1A3746A109E86448E667EC9C3E322761565CC3756CC351F9C3A2CC63A7B81E7FFB9ED2C0735003A58760BE0D63896A98A1576B81522614DFB226579314FD88AFE7CA9704E4B410D13125E35AA2C478B6A6B4888082E9127ECEEC8A93000B0AC46EAE9154A7E347589267E2CA9476796EE73A1F2C80C6377300109CC42A09C809B0A841214892F67BB626B17E986B0B12AFC49B1CC4018019036FF2EA085A20C7FD027FBEC68DD327B0E842BB7E0A69F14C99EE974C882270C244AC1B2594B9BC61DB5A3B3D366CD88B8A0A436DB386A0C3996A777869622A03F401A997645AEAC954A2B749183C6F5D987468A72FAE6685C1A273E856260F2918C6D0525666A021CC8C7BD18EF8939339CA4633D224E5FB3C4711C890685F0C5733EE92539690B957B0280A2515E77686CB899B7272A26B37A33A92B6BC6008272A38730B2A06446DCD707D5E140BFBCCC39679ABFF7624A970BDD945518894945B305FDB709A8EC147FA9599D34719959AB00A132B215C1D712B5005555B05BB7F66253B705315512A05B8D591600C8DBC19B871B3794CC13CE260060D77CB60CA2CCF7543A8E270F5A48DD86015FE3A9A8C2CB8474C2CD27B04112CBF1E60675739263C050015C4C198B87A6D494FD44816BF64AB849831B2C88A257037A6024C01F96497D0297D2CC74FB0CC487AB2FF81B2B6EA04CBE00F164B67FF5247179C42A94B0C2489074EE89FD74151E4F99CDF24808C6453F1886BAEDC26D649B7F7782AF660A829D7B423D067C2344568023854A6963D4074F7E404F1416E78E96526158398512387D02339C57AFC9C2740624B47345972249675424A39892A0FF4C2DCBCC80B8046D0921BB62C65AD2397C0CC5D775967E4BBD727B318F1CD37987FF7E9C966E7F37FBB5CB8AB943804196060F7A1CF0096D32D7AAA8D8DB6180EC2037B1428D67DF5810D5C98ADB84F0BB563AC4CF823C4D62EC083507AC0523EBF0B9BDE3B1BFEA833C5FD66451FFD6EE26DF40E83BA" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "71E0FD80B462AFFFBE1EC0C5993063D586FC5B733522145776E51CDED9A0C44B3C4836CF160D936179B75F4173FA6921F052452DEF3418A8B0138D47C429B71E", + "29A219518A85107742AE300E69F90B1F006C0F868FC84749A60295BF9648DA2CBE8C23C2EB980B0968CDA2309885B5843EAA6B4CF3A3C8D52D68EC72705B34120A3A2394C289F903D04049CA832EC3B5A7D4AA0730B704A04A3BBD250DE18C9F6F416BA18730F35B3DFBB48A4D77C03C653B16B20C3065828DE942AB8A01C7268E07C97A928241F6E78DB3B36384313531F6C3BFD62A9EF93D989C0467A4A111947EC9D40D2581C09538BDF9D422C3FA0BC50B1EB2EB74FCA92E71178C612B596E0B5CCBE8923B342E8B6B5D9E09B60350BD926942BFE1457979771FA4010A2385E84030FE1B0E1F9C5C26A8ABD376A3E5FB4BAE77392D4C42C4E500A9963DE2A268E7D31AECFB3A17F95F96072D3C8458008CBE76E752533BC653224B0E4A1564754AA966098E877286506C3DA13A7B752806DA33382C7385A2A40F8B509CC44A60B4CD36DB0F20A6235917A14EB2295FA18E50E69F2751CAF4B783ED0C8D600C473E725AF852A90DDC53D8C988BD221BEA2B7895016A7BF94F45506CBF357070F740D628AB587097D1B36601FB14EA27440BD237A6A227FE477CC82A3411ECCD80D46DDF05B52128590F3B4520D2599146B64BABC5353436AA29BB3D5A8829848FBF84223515289E78C9E3F82E81131ACB3997C24A548C3009FA8C2765A37340183705300C34715A4DA3BE83E124854025EF6AA7A5590972688211E14676E2A04D394C09D8AB9A570FF61CCCAEA19BBC150B7F46C6E3BC7CAC6B5D655C6F0F6A4481317A74AC2838E510A318582DF8AD33F7870CE87E478778FE441E8F052DC6324988EC7610F654AA0A1AE14499E833C7F363B47FAC6B11038D65B331D5E6B48EC3788252CCAB4A74E764A963281AD9753680032975F79AC231A786D07451CC8D32D9AF39D4049EFB8958DA42CCE696421C3AE085334592464347C68F60C4CAC5ADA55C8C00C1433BA08233319FB05B829863A5037904642A336FCA0F743B8CECE3A3488B28FFE89E43EA18BBC6337D9615C69009EB9B0FA8E8BFE2B48AA8EAAD55A8777EC620959A90A8F70BE016021E6476351A3C6D4204157B7468CA2E095A19BAD000B7F45B122ABFA9CB26D7125671B950F1D627D5B61BDCF68E7B7980A3168BF9286E8103B1E9D8C69E239C2BB5545809A1CCC15C476A72AC87BEA1C41FC63C4A0F491E91B234DD78C8181C3D247ACE317A0CECA2934FA69BE05373A53174C8C2B9DCDC29C1507435018A7ABBBF4129265AB25A7491257DA18CA224453FD581A68B384F7AC77473436A42659718044A2912B3156EF1E185F1083604989C2DF848D12229D3C93831DBA1A8B49EA53A44B0534F61D978B9C000414B68BE37270393B29579A23FF3003AB0AA35710F339354D3D8830BB15B9D08A61762270C8B3B78B8BEE5C7339973BCA0A1241F965EBEBBB07E2CBA7D50BD5B309C4E6A40CFB0A757F47DEF3148E3B7C44F337589BC1A9DC91A882CAB0ABC82DD1062FBDA64B8BC7A8004BD5E02CCD849144DD2A3FDA52D5F94C58E47680A94671908C382A7463B615997B2B59B891182F3B10B1670059A8715E1B7A2E369FA351C9934926B44164D42732A10383974168246A01BC913483797BE8259FE1C683B403A950F8F74EF6EAC1507DA6B3EA569E2DCF837E8370F229B824EEE73A791BCCDCF", + "C335B70FB26C7364CDFE873150C33FF9C72719E06139E548F87888C7008E159898938350B85A61A69C0C14D68648011502760C6CD65BDF070B69918A0249927708A49D8B0394F4700AFCC33A70230E57AD59C5B99EA35373D83E29DC8DAB3154FEA5A5757858F2F055405115F23B8B9AB7603C896F3D8B816B923A3294CB519528AFB620C975C0E4E2C58450C871C32AFEFBC83524CDE5B3078171B27746A63DE36A12F613B737A45CE357B7F70B04F1A3A1A9CF2B413D2FFA09471426969B8970E311258851EFE41D366618D6C93DD6D22DC54179BF8C4014C2B7E9AB8AEC28932EE588CDD8A75C1ACC32DB70E3174DE41A884C0282A565AB82348D90ACCBEDB354F00C5B2061070F34113AB3C8806C547789047E3AB6A69057A83AC6C3FCB6599CCB58216D275C556973C5EB45C63876677324931EC76AA4EB62F2935CB5C385D62B93B3A4ACD5C955C7778F6DA52DC4767D89DCC572A994B7626173B41518B54F4A34CD586A83A3F33ABD752215B8AF918CBE562174B0B8945A070F16E6B860C93407014E00665B8D96BB2E70939FD3B9B5AA19AF67241831572E130A35C912EF1566944BA270DCB33446523F53CC5F6BCE851C4B63ABC592865A0878C020B201E577C45B5462B90938ACCC1AB391705ED01FFF059E80BA10749961EA97C7DB736CA8D96148C03B93062F8686C519F47850ABBCFF5452F596595EF2563971B155261EAA17282BBC20A26694E96654A0B3820D0C205A463DDD88A1C25B5604F125E11A92CFB24291E330A08B34E1A240BD8B625281CAC3C4B326E3BD770B627F536F8440B276BA644884CB153C1330098F7727A2587AB3987B99167346B4E325B3DB65361756B18731DC8C60B8308E614B6B48144AB005229AE13730010351786AA8907505D49069822D268153C77CCC5BDACB33745253782EC7A310337101A39A3C006676D88A1E398B3A2F31CA67498F2694313E86A7863C9E02E1B8171A86A357A9A2A5B90D016E3E8044F4522BCA0664D5D98A060250E778198D479A2D1B45B9232C5A0A089B546377574835A84EB7B77B345778F3AC1C1A94831F08815E892669A4CAE2D48FCAD9B02F2897439288FFAA7D2EF4944E099B443415BFC84F1953287473590383C8DFA4937905612B114FC50A96305277582C552E3A501163BF1C638A51334980362AF87486C4645733905BC92BAE48E697F3B7BAB4778AC154229A434553923C1806CC592170871461046762576ABF8B70C1351368350B4A1E31A949A06F29426B4DB8010F267F4D506F8410CE67A153A8082D7A699DCAA1557D0C51DB8A96156238B82B9FC3C47E8A954F1E27C74CB612F42066EF512CF862C4C9BB23B3C296F534A52D222BAE729E34745D57A7CF4FB3358D18C6873218FDB97B650577F2D630A0AB7F713146299B1AEB634CD1484338B7C7519658B0B72DF158B177437F65F4AD0E9A1009978BC5D38739578F4A16271FEA6030682A958010399788BE39615F8A14D8EAAC82554C0E9C3568C7759FAB42BEB7746B5B2097DB66105A88D75A47D8A87EC249C33E121DE7E5A1AE67101BF530962CC3D1C4CC2C264616514BA82B67E8857DC3381757C176E6DABC6C7224597290AB047B29A219518A85107742AE300E69F90B1F006C0F868FC84749A60295BF9648DA2CBE8C23C2EB980B0968CDA2309885B5843EAA6B4CF3A3C8D52D68EC72705B34120A3A2394C289F903D04049CA832EC3B5A7D4AA0730B704A04A3BBD250DE18C9F6F416BA18730F35B3DFBB48A4D77C03C653B16B20C3065828DE942AB8A01C7268E07C97A928241F6E78DB3B36384313531F6C3BFD62A9EF93D989C0467A4A111947EC9D40D2581C09538BDF9D422C3FA0BC50B1EB2EB74FCA92E71178C612B596E0B5CCBE8923B342E8B6B5D9E09B60350BD926942BFE1457979771FA4010A2385E84030FE1B0E1F9C5C26A8ABD376A3E5FB4BAE77392D4C42C4E500A9963DE2A268E7D31AECFB3A17F95F96072D3C8458008CBE76E752533BC653224B0E4A1564754AA966098E877286506C3DA13A7B752806DA33382C7385A2A40F8B509CC44A60B4CD36DB0F20A6235917A14EB2295FA18E50E69F2751CAF4B783ED0C8D600C473E725AF852A90DDC53D8C988BD221BEA2B7895016A7BF94F45506CBF357070F740D628AB587097D1B36601FB14EA27440BD237A6A227FE477CC82A3411ECCD80D46DDF05B52128590F3B4520D2599146B64BABC5353436AA29BB3D5A8829848FBF84223515289E78C9E3F82E81131ACB3997C24A548C3009FA8C2765A37340183705300C34715A4DA3BE83E124854025EF6AA7A5590972688211E14676E2A04D394C09D8AB9A570FF61CCCAEA19BBC150B7F46C6E3BC7CAC6B5D655C6F0F6A4481317A74AC2838E510A318582DF8AD33F7870CE87E478778FE441E8F052DC6324988EC7610F654AA0A1AE14499E833C7F363B47FAC6B11038D65B331D5E6B48EC3788252CCAB4A74E764A963281AD9753680032975F79AC231A786D07451CC8D32D9AF39D4049EFB8958DA42CCE696421C3AE085334592464347C68F60C4CAC5ADA55C8C00C1433BA08233319FB05B829863A5037904642A336FCA0F743B8CECE3A3488B28FFE89E43EA18BBC6337D9615C69009EB9B0FA8E8BFE2B48AA8EAAD55A8777EC620959A90A8F70BE016021E6476351A3C6D4204157B7468CA2E095A19BAD000B7F45B122ABFA9CB26D7125671B950F1D627D5B61BDCF68E7B7980A3168BF9286E8103B1E9D8C69E239C2BB5545809A1CCC15C476A72AC87BEA1C41FC63C4A0F491E91B234DD78C8181C3D247ACE317A0CECA2934FA69BE05373A53174C8C2B9DCDC29C1507435018A7ABBBF4129265AB25A7491257DA18CA224453FD581A68B384F7AC77473436A42659718044A2912B3156EF1E185F1083604989C2DF848D12229D3C93831DBA1A8B49EA53A44B0534F61D978B9C000414B68BE37270393B29579A23FF3003AB0AA35710F339354D3D8830BB15B9D08A61762270C8B3B78B8BEE5C7339973BCA0A1241F965EBEBBB07E2CBA7D50BD5B309C4E6A40CFB0A757F47DEF3148E3B7C44F337589BC1A9DC91A882CAB0ABC82DD1062FBDA64B8BC7A8004BD5E02CCD849144DD2A3FDA52D5F94C58E47680A94671908C382A7463B615997B2B59B891182F3B10B1670059A8715E1B7A2E369FA351C9934926B44164D42732A10383974168246A01BC913483797BE8259FE1C683B403A950F8F74EF6EAC1507DA6B3EA569E2DCF837E8370F229B824EEE73A791BCCDCFCB3A075EE16957EE5AA40435D11F1BF5697B102A066A0ABBADF6AE87FFBD55D73C4836CF160D936179B75F4173FA6921F052452DEF3418A8B0138D47C429B71E" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "6034BF02515427CC2A4AA74ECAC46B032DE00890BF257FFB4B88233DD9BDAC21062A06DEFE9602F9E304536E306430D3516604704ABD496712BD99544D0AD07D", + "08A19FBED58B7361726489AF7EA1C56C118A2BB4155275967A00723BBA20C0E7082CD132372436EF09CAA78C4ADD73A1CBD817F84133AED43BF561506337A19C49B8C9D3BDC191C68A15C64DAC9BD5A40FEB094A0A369EC5B95367439FF1103EA7034311F2456BE9589E07252DCB7EDA73A1B6703630F73EB244C9F9034267714391F65914C924EEE3582EA942D8847B7E686415035D7B64182E5A7616723AC23C30473301F1E1A87D529A8759521B357A54558277992248F2044F23C53779C673B8CCC9C278332B4AB7FCA59F163026EB8746E978FEC4C61D952497664CB6065EA091B3B976B021D67DF248B0C0BA9556B32249C0A63EE41EFCC91679103A39F895186AA76B4764325975DD2AB2188147CBA70CAA2C6C9A08329AA39000A1ABA68AA61DA3386F209F1C4C815245009F7BA641A5477FEA4B8821BC9D54424B9711D1829D798A3A128C6C2CF521D9480B9663127F445608B4474DD180F9E542A282891F17BD6EF2718D52AC0C4CAD097C8706F4617D1901E0FB3C34F0CF966790F1C62E1CB71D11F098C0A8AE3F8A5EFC54A0788A6280E37D5478C7B336B2939182D3A7036E620F3272666099965B392B7B998EFC01AD6BE22DDC3B372EFC4936A298A502913841B17D554AB7D714C2487F6B35C3BCC387023B0057A40DCCF5A3D15544F9A920D1A7C17A644EFA6B8F865A35C7FB81C3B8B6EA963ED06B39C8628FCC24197C43A0710656D6E275FEA8A4D83CBFBE173466836CE6050410F30D9299041609BBAE4A27A25B53D1C0503F42AC69147B1C37563FA0CC98990556A573189A684496A694C215CD8066DBD7C1AD0C486A6B5A0D782F003648AAFB2B8423C3DE2B2402F391479B02AAF61DEC0AC8CF7BB99643311910BC3AD5374AF3413DE179AE320E905A562A572E6EC78F8CF2635D93A3AB15135956171E585148E5988D7431DE1A9A6F3B63CD892E9AD25EF522CBED8ACD39426A402A2E922A8A61DB4FF2F4CAE5F1513F08765B32844C863F3E63ABC50BCA9A127D3CB0B32E22A969A85C64F6277AD466A6628E4452CCAAFC57CB727FACA226DBF66E8D213DBE8028BF72183CB7742A9A53CADB6AD4931510A161A8688169287DCAEA082C45C53CC96FD5E326C41B85DC12BCCCD5553AA0033CA4C02B7007DB5081BC3A9C83C599DA23A6F69956EC66C9C1830AA5567D867750B5C4176293A51EFA2A551C58F04340FB3043E0C4311217AF7FAB293CA27C4E544542F46E4236B5D18CAD0BB453C0F828D6022718793C80C181EAAC2F4774A83845B9173148DD668DCCA656A8C26B53E12DE6649C000D35E5A7AAE4F39A90E7B95DD487534BCCA3975B6A168171C36988C94104B47E3942B2E5C47F3E70CD06712881031D84945DA30A21B3A315FA06A2A0014403FCA16ADC2982468CBE1930B396CA4EAC4BA8E750E91C40C654B2C7F2CB3EAB25F49A4994EB14AB816587033C6EF65C97FA17030A87A074979BC355B46C216AF878B2BC8AC2B1B3EB176CBB85A6A8D790BAC1B9B8F368E77CC9DEEC64F7F19B39A0A8B924A323197F2D276370C6949B734EA9370DADC4022FE18D59B1AEEA3949EA0581D8867CD303BC27AA1B8E325C0E4058D6C5453366CB7ED9C1367AEE618A51BB694A3DC712E9E13643B59335B6B5DC5795CBCF44C381681322", + "33895C98D5646CF9328ABA3C11C110B5FC970A26C9926850A65C851FA59C52C10687D5C770C2A96B836B95D75654628F1D417690F11A28752A227C87C4555DF520C207D2A5ED519216865FBC2BB2B395409402387E0369ECB58BBD8A4FA7EB096ED146A67303482284B7D83D458C2B6D523FEF16573B7879D5440298CA182FB31502BB9109132FB1E6C4D10A1E4A486AEF36393A635F7CEB28C3BB4780A9B7E1637ECC44842BB22C670A1DBE2C0DD154C0E0F9818589C5AEAA2DE5829503BC062BD31F63E75EDD3303E94B7B7E526694B1AA5E98098FE704EE7A24AF62859090C244192C6C077AECA24848222FB041C8E9E3B1EC370C31AAA922698ABAB390363621C5FC8891305D3892438F245EC34C482A243540A2A5B4F3A3FE2B90254511B73AB46F9C8FAE1596367667F9295EECFB7FA9B289EB5BAC03E39B80EB3891B91280B7B02EB4CB364A3BFAC701363965E2C68C9CCC72A686A1EDCA1476B89022737A1FA036AC10134C4A20C75425F9E67F8EC6A0FF467E33801FBF759EA7CBC43EDA55F5E330312259BC3C0B25A296058AA233696AC24122D8B33E613B17C219AF8C53004034204210BE34C7428CE38711848914A7015271B6FA75CDEEFCC06AA18EDC83A078C1BECDE9096483915575A5CADACD4FD54F808412E0AC39B4493115BBC27D44427AA122CD149FE9F5A51B90AC29745B871748DCC6A75124AF490710205A589F8C79BA27B98EB3C358FA9FA6D613850AAB39F2080C74AECDDC84B68A1182F858FE6900032C6E65FA398FFB6DC5224CAD37B61C9000DEC0B36F1A91A76BA6F620CDBCA112005DB0382372899567BAF449C8F1AF6F4841EB114FFDC2859710BC4AB565738B762274C19C9616D6709E07A471C513648D875E7C13961FF36850971C2911139BD232D8874AC5C066C8A68D938841E012B887E910A976947DA9092476078019042FA939824156E1F4561F353E197CBCA9D83E99EC9635D70E7D0087B1E395176B487A565325F37CAA0655AC8307B87C2D02984217C3927380A5C02B4F36937FDEDBC5F5722569CC15F863C0E68060A692A171BB544CB68FB1EC573A55AB539C70F549063D652132DB224E020E7D5335BF5C6F3E4797E162BB6212CF88B279BEDB0B8F99588852A86969A86F522A0BA00F98E6246142C9D94CB891C8A9E5463171F18D24C941624B3827C67F3EF467E7646C3A519E96B8B24585CD2EDC68A7524BB98731882375A18210B6A502A055A45973CEF8B5C00A2C95F9A044F4F3155C68BC7D13BE15251AB2F2C4746769B1EA00A2268B72FC17202035020C8A5BC9558E1C088AD37A58765EF7F16DA40911AA82286AF22869A020A235681A283EB906C839AC9D6BB854FE6A00E0286309601FC6592CC7E99B85555227D67FD8E170F72AB1425051327A4268EC192EE6CD3D17C619762C35407522479328590C5972B7E2979C20135703F4BFB6F7359DF7CFA7618BDBD0CBE6DB72FCA522CC89B8DEF6154CA60E220918B83A1A90553302D96FF819C0B8191A88E3451612C997B6927BD20573045C880664CE454190DC5739D4532FD488A5F745D571C5D598772712A3AB285F00FB3E8210B043F461A3F41CE58B36AE9B8E651CCC08A19FBED58B7361726489AF7EA1C56C118A2BB4155275967A00723BBA20C0E7082CD132372436EF09CAA78C4ADD73A1CBD817F84133AED43BF561506337A19C49B8C9D3BDC191C68A15C64DAC9BD5A40FEB094A0A369EC5B95367439FF1103EA7034311F2456BE9589E07252DCB7EDA73A1B6703630F73EB244C9F9034267714391F65914C924EEE3582EA942D8847B7E686415035D7B64182E5A7616723AC23C30473301F1E1A87D529A8759521B357A54558277992248F2044F23C53779C673B8CCC9C278332B4AB7FCA59F163026EB8746E978FEC4C61D952497664CB6065EA091B3B976B021D67DF248B0C0BA9556B32249C0A63EE41EFCC91679103A39F895186AA76B4764325975DD2AB2188147CBA70CAA2C6C9A08329AA39000A1ABA68AA61DA3386F209F1C4C815245009F7BA641A5477FEA4B8821BC9D54424B9711D1829D798A3A128C6C2CF521D9480B9663127F445608B4474DD180F9E542A282891F17BD6EF2718D52AC0C4CAD097C8706F4617D1901E0FB3C34F0CF966790F1C62E1CB71D11F098C0A8AE3F8A5EFC54A0788A6280E37D5478C7B336B2939182D3A7036E620F3272666099965B392B7B998EFC01AD6BE22DDC3B372EFC4936A298A502913841B17D554AB7D714C2487F6B35C3BCC387023B0057A40DCCF5A3D15544F9A920D1A7C17A644EFA6B8F865A35C7FB81C3B8B6EA963ED06B39C8628FCC24197C43A0710656D6E275FEA8A4D83CBFBE173466836CE6050410F30D9299041609BBAE4A27A25B53D1C0503F42AC69147B1C37563FA0CC98990556A573189A684496A694C215CD8066DBD7C1AD0C486A6B5A0D782F003648AAFB2B8423C3DE2B2402F391479B02AAF61DEC0AC8CF7BB99643311910BC3AD5374AF3413DE179AE320E905A562A572E6EC78F8CF2635D93A3AB15135956171E585148E5988D7431DE1A9A6F3B63CD892E9AD25EF522CBED8ACD39426A402A2E922A8A61DB4FF2F4CAE5F1513F08765B32844C863F3E63ABC50BCA9A127D3CB0B32E22A969A85C64F6277AD466A6628E4452CCAAFC57CB727FACA226DBF66E8D213DBE8028BF72183CB7742A9A53CADB6AD4931510A161A8688169287DCAEA082C45C53CC96FD5E326C41B85DC12BCCCD5553AA0033CA4C02B7007DB5081BC3A9C83C599DA23A6F69956EC66C9C1830AA5567D867750B5C4176293A51EFA2A551C58F04340FB3043E0C4311217AF7FAB293CA27C4E544542F46E4236B5D18CAD0BB453C0F828D6022718793C80C181EAAC2F4774A83845B9173148DD668DCCA656A8C26B53E12DE6649C000D35E5A7AAE4F39A90E7B95DD487534BCCA3975B6A168171C36988C94104B47E3942B2E5C47F3E70CD06712881031D84945DA30A21B3A315FA06A2A0014403FCA16ADC2982468CBE1930B396CA4EAC4BA8E750E91C40C654B2C7F2CB3EAB25F49A4994EB14AB816587033C6EF65C97FA17030A87A074979BC355B46C216AF878B2BC8AC2B1B3EB176CBB85A6A8D790BAC1B9B8F368E77CC9DEEC64F7F19B39A0A8B924A323197F2D276370C6949B734EA9370DADC4022FE18D59B1AEEA3949EA0581D8867CD303BC27AA1B8E325C0E4058D6C5453366CB7ED9C1367AEE618A51BB694A3DC712E9E13643B59335B6B5DC5795CBCF44C3816813224BB73822FE54FA91EFBED54E4EB94EACA07645CC57304D1B17B7E98818BB23B3062A06DEFE9602F9E304536E306430D3516604704ABD496712BD99544D0AD07D" + ); + yield return new + ( + MLKemAlgorithm.MLKem768, + "FD3A62757B683A4755380E42E915CCF2D31A74979BC143A453A8F4570F1BDA062CFE75E5E15327C71B5313ECDF48399CCB106102D37431722043C8A32F569B68", + "4CA22FC2745AB5A1B51D36A99E6C0AA6B9851A49B2BB6688A6C107A4E02A2AA612DE156BCFCC4C5D2C3862C5295E2B0280104FE7D8BCA7AB3AC8210AA3D64CED435F9083AFA142A7C072007E8454DB2339474625EB03AE8F9A2F4F5215FA8534146CC512503C3F33A744898C68DB0882E05E08656C897B313DD713C81C26D38B300F4628C7C7AF551280C5BA65F7B310CDC279622117AFE16C66686C4B825BA1E331E1B25FCF878F07F9B809607B1C918E18308232EC086F7581D03921D806781C5819D198931CAC74202B66022ABFD1641FC6B9827634A0093A96C6B4B9EBB13D7F13B5C0354588163B05EAB9FCD17DEEB9C06FD176603BC1FA34B34EDA908361169A95C48125CE131B1FB6F6C53CDB2BB1568571A3B25875C21AC274B78C795D95C01D99A0F6C740415519FE9871F0A781FAB79540F05A95800512C644359566CF029C41B5C5DC082605A2096F403C47E344C0C99635C882CE116B70DC111D1688E6D43333D3111EB96CF1E103146B7E7DBB3BC83B53EE976192A872AEE21E5D5A7D9EB4AC644C177898414917244BB80F88359CD5FA26F45C7FF8D2BA1DA114D53C4057C821DEF0AA81099B4580B6C3EB839A9820DFCA6E94800E9DF565C42A30CBE5B10D24311CC736790212F8DC0E3C5348AD402BFA0A7106292C16467C97CB54002BB3F5EC889799C53D2CBC97074DF3AC8163BA940DB07698E5ACBB7A4C74D53D2A046DF3895C5312729DB939AFC93730142DAD533E34E59211866E8F5A8C16133EA8FBAB89355FA5148F62401C03217B8FE37984DB7347F6B12344BCD95A3163EC9FB1E6B15AA4312D6B6F67E0417CC64C60CA7D9906541AF81FE4F66DBA4123C34B29C53616A1C80D074A086D585E119739A61823EECB3F5572A3D0269134CC682F535F7D1349364109E63345623521D01C97CDF53D8ACB0AECD659D8671E31669586E8486E1B23284C61A3C1ADEC8235CDDBCEA9EA5786592B99DB8A8E104F47D60EC4489F26D744547A8EEA30A40C52C820C91120C07BC3C6112929884BE2BC8BF127B05690E5D0583FB7644C594A0F9511D678547089801F43B553E32C1804448107B9B9A8227776531EE587D41B31E9C04B1DD3B47DD259288299A6A42771D8707D493655559B406A4EA302367E249E2067B5A52C0B4D50426BFA8840C3653D34A74617B6155CAE1784A45E356351A72535242803F984F36A876E227DA3EC7B165095C1F954907B71BD5238464385B9053C2DE953FDBA4B924AB54A452F2530024A2AC7198CAD628B7EB8B18FAED975C59B29A7C982DE419814CB4C69B8009D6894CDC995EFC86A8B190BD591B28CE469875B0A040AA77EB391D9D64307F189F9630D37914CDEEA9958AA4B6A0B3C2E0162E091BEF89766D27283EFB592C06C1AE4E02136A4200F4A02F7661854A753B9FC0A03328C84B953C6D826E28ABFEEE8C77DCA98258A6ED8912CC1EA94645BA753EB5A44D043CEF621F4344E7302CEFF09314079B7624502BFA4C6CA6416B1808E53081549478211988FDEC39388D49D2855413D91AE581C47116C304A1959DCCBB3B8BA1A873CAD94195E653B9B85E628B743AEC592833A44A1B940483164CB50FBCCA3C4029929249D5B3054255C7BB7BE5DE283E42A2EB1F8F12B6961ACB5BFA4178F3EB3238814", + "D0195AEED8CC671582059C090BD67D2BA81D914616CBC055EC604E834BC84EC8A50309817A438EE46912E1C7515AB79B8671C105B74F3652C9ED1C224987A60CC710FEE49E9B567E9D75BFAA095BF413CB57880E01E43610A76C387A37B6C60AEC879E922B36CBE61A643716C188CFBC4A5FE1538ABF58919F635A91B09C3456770A977C01D2ADF5E76BE608B834EC2928042D8320867A3130C0A066A1188C9E87B81160529EDA26C9E311C7402F0635620E181D7273A1861A0BC0C85AC8032A62EC96ADE72007873C185B1A0D49CDF6CBBFCD264F07353BFD30339C0C1988BA91F25178AF4A88BCC069B8FC3190B7A315B49394D034C6A1BF46D55389B1CEEA82B834421BD259501AD3C453C1B9522906EB649839A680C7616E8C321196F1C4EA9629E5028185EB4BC33CBFB96807BD4BCE64B72EA6AC69CC8093A201C92D8930B331BD9E1A4DBA47AC8B785996F00D81316868B496C4B37D86E2BA185656A4032C57A632E6C5C1CF46474E4A4FF098914459679D65B01B1667ABD541BA731242D98ABEE7751C4A99A9E86ADB56BBFF9432DF4287DCB95FC2572CF8690BBA3A91805BAC0DE34248F8BB8AB33A739743B58C310DFC7064D910F9AB4FE3965836BC61BEBBA27216A23C39BD7384BCD4D2A806B5950D71AF45B100ACA66474D25E21205BD2638081FB53F019A5DC49C9FB64B306D53D488A5BFDE30A732B825586C45D611DCD98162D58C63E968BF81834CF83C3F463A67BF548EDD001FB621694F17DBE847791B7252E842C730C32222A92216A261F5A365749279F6C0324A2B85447732E59A64362BBECD400FBF84F3CBC1BF3D0835CC04ED00418D9F2BF48E35DB98C5AEEC4002453505A2A13D93B80D2FC7A06C1CD9FC005100B9E647843688422CB357E1C5C1F47443D977510BE2C004743175B8541B405A9E9E8BFE480B48F377E01671F1D21AC37348CA2A31C5C4855CB22558226AA609A88DC790F79B404E81477CE0277C4682C42E7BAB51A68D3EA945DE36D12777121C58DCB9643519423E4002CE8D100FDFC31FCC9A33D4C6292ECA3AF6378B8F56D55F05AFB6485C79780374B2B3F026938A6A87351A6068C58B7EB83539A5AFE3449D0E0C80CE4B93973C84FA64514A030834399B774AC8E9A99D0007FD87766A1AB031B2782FA27139FC08ABB37A82A59BCD75C89C800ABA88574A69604464A7BA1B208BC14017FA22E30C758EDDC7F67501E6DA8740F9B18A4A08CAFA021FFC0B293DAB8EC0369D5194F30B449AC248105BB3B4288B8ADEB584F70159D2A26D5AB500568C948E1B66958163D755326078DC7E916DF342ECEC257AE0354CCB16D6AF2524F65B6883C4665B4304C40CE9D6358A5A35B6536853C4800EDD81BD4D06C5E616C069402F864969F1247D52407766C3870D21B0C014825D853F8D12EC5073678628F3FFAA5CDB715F5E6C257B0B31E83494AAB8075E5B19886B725674AB0586E72C3CE0377C62925036CC7C9277B187AF28DEFBBB2C0960F4F623EE9D56073F1CE4B55C9D0CBC20576A004A136297A0A7D1AA3D0C5051F2CAECDB40B8BE4C5F81A9AE55A3C4A66AEE555A231E55A68A8B997C53A77855A57F09EC1A79E1E48658477C84CA22FC2745AB5A1B51D36A99E6C0AA6B9851A49B2BB6688A6C107A4E02A2AA612DE156BCFCC4C5D2C3862C5295E2B0280104FE7D8BCA7AB3AC8210AA3D64CED435F9083AFA142A7C072007E8454DB2339474625EB03AE8F9A2F4F5215FA8534146CC512503C3F33A744898C68DB0882E05E08656C897B313DD713C81C26D38B300F4628C7C7AF551280C5BA65F7B310CDC279622117AFE16C66686C4B825BA1E331E1B25FCF878F07F9B809607B1C918E18308232EC086F7581D03921D806781C5819D198931CAC74202B66022ABFD1641FC6B9827634A0093A96C6B4B9EBB13D7F13B5C0354588163B05EAB9FCD17DEEB9C06FD176603BC1FA34B34EDA908361169A95C48125CE131B1FB6F6C53CDB2BB1568571A3B25875C21AC274B78C795D95C01D99A0F6C740415519FE9871F0A781FAB79540F05A95800512C644359566CF029C41B5C5DC082605A2096F403C47E344C0C99635C882CE116B70DC111D1688E6D43333D3111EB96CF1E103146B7E7DBB3BC83B53EE976192A872AEE21E5D5A7D9EB4AC644C177898414917244BB80F88359CD5FA26F45C7FF8D2BA1DA114D53C4057C821DEF0AA81099B4580B6C3EB839A9820DFCA6E94800E9DF565C42A30CBE5B10D24311CC736790212F8DC0E3C5348AD402BFA0A7106292C16467C97CB54002BB3F5EC889799C53D2CBC97074DF3AC8163BA940DB07698E5ACBB7A4C74D53D2A046DF3895C5312729DB939AFC93730142DAD533E34E59211866E8F5A8C16133EA8FBAB89355FA5148F62401C03217B8FE37984DB7347F6B12344BCD95A3163EC9FB1E6B15AA4312D6B6F67E0417CC64C60CA7D9906541AF81FE4F66DBA4123C34B29C53616A1C80D074A086D585E119739A61823EECB3F5572A3D0269134CC682F535F7D1349364109E63345623521D01C97CDF53D8ACB0AECD659D8671E31669586E8486E1B23284C61A3C1ADEC8235CDDBCEA9EA5786592B99DB8A8E104F47D60EC4489F26D744547A8EEA30A40C52C820C91120C07BC3C6112929884BE2BC8BF127B05690E5D0583FB7644C594A0F9511D678547089801F43B553E32C1804448107B9B9A8227776531EE587D41B31E9C04B1DD3B47DD259288299A6A42771D8707D493655559B406A4EA302367E249E2067B5A52C0B4D50426BFA8840C3653D34A74617B6155CAE1784A45E356351A72535242803F984F36A876E227DA3EC7B165095C1F954907B71BD5238464385B9053C2DE953FDBA4B924AB54A452F2530024A2AC7198CAD628B7EB8B18FAED975C59B29A7C982DE419814CB4C69B8009D6894CDC995EFC86A8B190BD591B28CE469875B0A040AA77EB391D9D64307F189F9630D37914CDEEA9958AA4B6A0B3C2E0162E091BEF89766D27283EFB592C06C1AE4E02136A4200F4A02F7661854A753B9FC0A03328C84B953C6D826E28ABFEEE8C77DCA98258A6ED8912CC1EA94645BA753EB5A44D043CEF621F4344E7302CEFF09314079B7624502BFA4C6CA6416B1808E53081549478211988FDEC39388D49D2855413D91AE581C47116C304A1959DCCBB3B8BA1A873CAD94195E653B9B85E628B743AEC592833A44A1B940483164CB50FBCCA3C4029929249D5B3054255C7BB7BE5DE283E42A2EB1F8F12B6961ACB5BFA4178F3EB32388141E0A27B82EBDE9A53C506D70E0512182378F345B816C84AA6B7224914BC9DECB2CFE75E5E15327C71B5313ECDF48399CCB106102D37431722043C8A32F569B68" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "EBD6260BBFA0C542CD1C857C318BA68153832A60F81DE839E71284CCC919BB71600FDD18126AC926D3A745172186BEB557CE6F0D7911A5C9EE387689C799E912", + "8859395F916E37E747BC9A5798764BD7C7A6B2071A7D5797A33816CC941EEB77A62049CA1E3A20A6012198D0903CD5CA9D813A994C639EE1952AA70CCBF78AE1FB104232102C987069E7583C73C427C8812F467F0C7A27F4799343471285BCAA939A38243007BB1C62ACDB42A8E85F7F63CA74F31ACBC6BDCF949FAFFC6C3DF4A9B6603CF95563A26921D056B8CA0A8CF8A649143728A9E3AF24AA3787663480EC2FD7A485F90300B672B9718B8A881AB606456893A105CE518C61202069E4924A5A6CE0508B54A37E591915A0544B67BBC4E0F0225D3A7F3BA48F92CC91D7802485E3BC0A408A3C123A069518C8D304D47B96D9AB80FEB50322F2887AC733097A06F1327F727399ECF17F0E2B76BF852E4B2464FBB8424D4629F8644B5F787A16FA5D24D295E0CA707AF6417EB4782CD8337215322C82C645002E12EB57008054F3528F1906260F692D5985ADCFE45BB59CC2143CC986D5975773150718C7CDEA20F4D8BB70584597B0C67E6C0A7A221DBB4C98A99296E9A458800022350C3086949E50784E8CAC90AB901583B45253472B752213892888DD8C6937C856B829C5EB904FA51BACAD81B2273062CEF29EF3FA76E1B56E1BD9142E27C360384C46C687A340BA78750230423393EC245DF58A3077247E6383E3D3AAEE14090A8BAF3E6912699954FA50AAD5E158809355A8E9C7AFE49497E7ABA193275ED1C0B1A5A31C28B5EEC20C38681F4EE049778BAEADF6586863B5EFE35E1349CE6199A58EBA7EB333163F441006A05E39D3BDEB8568F6797F6E724D9358004DE76A843CADB3C939F4961A3EF9A13530B85A7A9C7D23372615BDF827C2D9E57A2AB867E2CB77F7C5023D64BA3DA96C2A1AB55B891835C10B6A848FAB88B311E434BF28766973BFC4B00702F07CD8D35985EB0ADBBA21F0D79C6070361F9212EC5A5EDC0C606E17CB82F1B36F8025C682752E3307EA60347E1644AAA2C0D6F79015516EE729AA44CA64209078DD3A05B8D24760A265CE630E7875178127268053912B2405B7E63F5082A10832A922D2973C9AB0BFF1323B443C66F8338296C77715883FDAC2C373043A878722CA01A701215A7A8ED0BBBF67E95299F70E4E7B897AE45FDA1543373C83CAF08CFF8C4D9E1B2601D773AE3956333454806446C7D63ABD32B9347719848C873DA9989D845884A9A7562326D2109AE06496EB790B2139C6337C8667CBBAF3040AD73C4F2A7A2DEF3B1260174BFD4106092B4C1215A4D52425633880B396721FD0ADA23A991BE1A3E1B7ACF6E3A6A0B23A5FA5C2C40A5D9B252E0E3C8E923063EF2643BA655A95C32518F3BACDB612764889C7E71C006A389E5B80C55A1C93771D009177A6F5BC1D304F8095A672276D64B78D2816AA49080988568593F337A13B5128ABAFF0D70A6330631B96864005459F8B2824FC5DF7408E4B8A2B09628E4059CBAEC95CC984CD5DB8BAF584BD7695487BD220A49307B05A87D06713254900D26B6E384B455A8C2A41A9ADED866E5235960990B19DF6AF36458B95575341B782C0DCB3DCA940A207189AB672BED83720B65ED6B47DD335898F3C55C7CCB6CA03A556932AC6AA15F0A40CBBA14C66948390F8054D33970FEC82F8F370193A2F15EA8CBB9ABD97A31F10085AE1AC5E80712F277A5D6B7127B04798CEC91FE2B0B1858A0E904236007951D184503AB4665FE72B835216E13C8DB81A68818583D293B1CEE09F80705A1FE29C4BA89563E01B313450598409927779626A874E7103F34C758D204F609CC8C85A1FF94187D8A6783B2B206AA9821A1197F223AE770572157069F0E221C7365F72300CCD798746544FD2D989BF10C71647106386B88F999E26727ADBC52E92323F724552E810C1ADFB8CDFA132DD79507CA017D4B0B81118C758CA49F20871C54161E49C7E1E8A482EE53FAB584DB1E3258744A8B4664B7C06AF752B949D681B37B6C57F9C32B0F49A839476F4122989A761D9E3236EB3B63C0CA395A9391B5B1A8BEA76CFD7A267E7574AD938C918364330C1D7F45CAE5A8327C892C075B2D0546C8C1B391B55A4EE013E0F600BA5043C242B1735EB5449494F9E9BBB2EE7C741DACC97C08AD4ACBC2A6B40C36847547A4FF29854248484CB9CC17D98941F544441F0B674898B21873785FC204829B3A8074BE8113160D0CB0AEEEE9B7795B6659669BD3311A722DDA728AC095933A8", + "CE109720FA07BE01AC762187DD00BA90418D9F567832300D98A27C7A294FAFA267822AAAFED4463200662BFABA61EBBBA77B4D4FB628BC15AB1C458707787A9A7CAE5984A3E141B2A9106F2C101278379E81F218CD89A8E7A62D6886281B5925F5F0C39642A54DD391F2E0357369202CD9839FF0A6DB547E832A0EAE4B32468C109CFA543F8C7A61D69D8D170EACBA1439628B6093A1B5051471B3C8B229A8D6AA4A5D51255726035F8B1518A0A647CB1F1BB88E9D522ABD02BFF375552084039F3A0CE4740A690917636A2CFE32BBC4F339529ACDD1B28E1987B764E7A4B1C3C782225C1C30CE91551642657DF378A63CB56A1C471D955B33C23203CC2B95644787E313B87162B8716BB3D2053E70969A50B5175D010DF1482F0628BD58320C62502AFDE3200F01169288B3A57925932BC7DD31CC26480B98BCB438CA319D038939038A6E69CA1193C56843367B13396E859FE08169EF8925740754F8226D1310ABE54400B9B24127FA46208AC875C3C1685B9CA5496672966A3E681260E30CC529041C38C9E5E07610BC237EA8AB5C9873714C22E77A092AEC4860FB4543DB394F161AE456B3BEC89622532DAFAC16CF059E66D38C3BD24568277E83782CCDBB2067C15418B8AAB5F41F581CB7EFA7BA114317AF346959411DA2F44D65C264AFE028285B7865C879ACF9280F6C60A3B71752B142E39C9BDA400E7A46170789CAA8F296EC3594A0B3C50644764BE6A18B4057B4B2764735CE41DC13C551AD9D421205633A7D3A916CFABA3FF5390A55998ED3C2D0C9376B09A7C66B2AECC52EFB551263710F590524E9977B1D8749C659CF4CAA195A31B7309401CB209C15C00A47CC8AC8997DCD47C6CDF13E156814650568C276CDF3C4CF6F3417307B420F6C694BA2021BD82D242A7325842F1AF4991BE4333853A45DF31B379604584B45CE5A4E127BCDB01977A301808BD83408DB8E69E1B7B875BB5EF86EDA606870A81E71362686791A954603122B736FD1AC6A247B1D966194A955C444B92A2BB4C1CB7B5AE3C79DF81EB031B7CDBC0359F04782E08FA1E654091AABB8C89F7F8043B28C4BE0681754A7B255A0CFC7342B431A0CC6AA24A88A43B0EC5860651D6E252E3D314BEAD1807A0A137234B8FC0A52E7FA870D936B42B23EF0B76224EA461A661ACCF5B615545B56AC23CE6A579E5841B8CB69E7798F9E7A4CC51CC688692B2710C6E1751AB8628DFAAA211D4B1D002BAD7E241E1259588DF7457B8293230C0C61EA1812B7375D23A6E4A80B872624EA0C7FB2841E4B572EED9BA182EB8B4617666C172E504109E317B23A0B839C4B6E530A05F8846A6A914DFFDA14A2C555D23C1EA45379C270B2023785C927132C8BBA7AA05A1361B34AF1CDEF186F5D3B5FC022A2DC2B3845A0B972E52636267E212C884957B885D6C9B50903200863B45716863924F3C5CC382A9FD7410E2C27BD80549DB8E439F81966EE418A55E5C2DC1A90215507382A976C649CF9061612A43D14B227F918ABD10AB0D06C285F1574E6157F95598FD86453A12320CB8CA9B7B408A4A83B872C9180C9BD5F786F4F94B2F806AE5A8B55A8470469F7A21EEA9972143D872897F86C50998B2AB83B9AA6554B2764CFA2F04C9BB2100B7092C56CBC293BC78DA66598EC4FEF95C31FD69AE74407E9A655CC012F3007A422A0BAD01C564D8355207128E1FCA59C9AB7F0298EAD2301633AC590F0545162B744B7C01C98AB2E05B92289044FDB42619099A6E373F9E871C4665526DA69F067C643F88F779B2D6D30BEE00470E695A4EEE221E0622E11A30E4FDACEFBB9120CABC298EB2E4B3A93E2D09EB88444F50458245BA2CFA247C77A451DB9842397442D34B6D6AC3D4E40BD04E910E0338FE4586F0779CAB721C713D9B19AB696A224AE3645AF8BC5BE819848DB80B133418F79617F0D994689F847BD8B768E94999FCA867621402CDB575C25A3D9F647BCF4614CD7ABFBAA1CF3B9C732D30603D8B101644E620C18A08711151A6AEB69BD0EAC7961F42A4B649257912835F9BBC4079EC7C7C5CBB2B0895C3F075A969F84C179396470B18EA32397F04C63E4F89F6F14CA23F503D207AE91E891FDE8ADEA7418C5B70B2DA2B226D06E8CCC7C090CB2D7B8A1F16885F0CB3694972D0C14839DBBCE8859395F916E37E747BC9A5798764BD7C7A6B2071A7D5797A33816CC941EEB77A62049CA1E3A20A6012198D0903CD5CA9D813A994C639EE1952AA70CCBF78AE1FB104232102C987069E7583C73C427C8812F467F0C7A27F4799343471285BCAA939A38243007BB1C62ACDB42A8E85F7F63CA74F31ACBC6BDCF949FAFFC6C3DF4A9B6603CF95563A26921D056B8CA0A8CF8A649143728A9E3AF24AA3787663480EC2FD7A485F90300B672B9718B8A881AB606456893A105CE518C61202069E4924A5A6CE0508B54A37E591915A0544B67BBC4E0F0225D3A7F3BA48F92CC91D7802485E3BC0A408A3C123A069518C8D304D47B96D9AB80FEB50322F2887AC733097A06F1327F727399ECF17F0E2B76BF852E4B2464FBB8424D4629F8644B5F787A16FA5D24D295E0CA707AF6417EB4782CD8337215322C82C645002E12EB57008054F3528F1906260F692D5985ADCFE45BB59CC2143CC986D5975773150718C7CDEA20F4D8BB70584597B0C67E6C0A7A221DBB4C98A99296E9A458800022350C3086949E50784E8CAC90AB901583B45253472B752213892888DD8C6937C856B829C5EB904FA51BACAD81B2273062CEF29EF3FA76E1B56E1BD9142E27C360384C46C687A340BA78750230423393EC245DF58A3077247E6383E3D3AAEE14090A8BAF3E6912699954FA50AAD5E158809355A8E9C7AFE49497E7ABA193275ED1C0B1A5A31C28B5EEC20C38681F4EE049778BAEADF6586863B5EFE35E1349CE6199A58EBA7EB333163F441006A05E39D3BDEB8568F6797F6E724D9358004DE76A843CADB3C939F4961A3EF9A13530B85A7A9C7D23372615BDF827C2D9E57A2AB867E2CB77F7C5023D64BA3DA96C2A1AB55B891835C10B6A848FAB88B311E434BF28766973BFC4B00702F07CD8D35985EB0ADBBA21F0D79C6070361F9212EC5A5EDC0C606E17CB82F1B36F8025C682752E3307EA60347E1644AAA2C0D6F79015516EE729AA44CA64209078DD3A05B8D24760A265CE630E7875178127268053912B2405B7E63F5082A10832A922D2973C9AB0BFF1323B443C66F8338296C77715883FDAC2C373043A878722CA01A701215A7A8ED0BBBF67E95299F70E4E7B897AE45FDA1543373C83CAF08CFF8C4D9E1B2601D773AE3956333454806446C7D63ABD32B9347719848C873DA9989D845884A9A7562326D2109AE06496EB790B2139C6337C8667CBBAF3040AD73C4F2A7A2DEF3B1260174BFD4106092B4C1215A4D52425633880B396721FD0ADA23A991BE1A3E1B7ACF6E3A6A0B23A5FA5C2C40A5D9B252E0E3C8E923063EF2643BA655A95C32518F3BACDB612764889C7E71C006A389E5B80C55A1C93771D009177A6F5BC1D304F8095A672276D64B78D2816AA49080988568593F337A13B5128ABAFF0D70A6330631B96864005459F8B2824FC5DF7408E4B8A2B09628E4059CBAEC95CC984CD5DB8BAF584BD7695487BD220A49307B05A87D06713254900D26B6E384B455A8C2A41A9ADED866E5235960990B19DF6AF36458B95575341B782C0DCB3DCA940A207189AB672BED83720B65ED6B47DD335898F3C55C7CCB6CA03A556932AC6AA15F0A40CBBA14C66948390F8054D33970FEC82F8F370193A2F15EA8CBB9ABD97A31F10085AE1AC5E80712F277A5D6B7127B04798CEC91FE2B0B1858A0E904236007951D184503AB4665FE72B835216E13C8DB81A68818583D293B1CEE09F80705A1FE29C4BA89563E01B313450598409927779626A874E7103F34C758D204F609CC8C85A1FF94187D8A6783B2B206AA9821A1197F223AE770572157069F0E221C7365F72300CCD798746544FD2D989BF10C71647106386B88F999E26727ADBC52E92323F724552E810C1ADFB8CDFA132DD79507CA017D4B0B81118C758CA49F20871C54161E49C7E1E8A482EE53FAB584DB1E3258744A8B4664B7C06AF752B949D681B37B6C57F9C32B0F49A839476F4122989A761D9E3236EB3B63C0CA395A9391B5B1A8BEA76CFD7A267E7574AD938C918364330C1D7F45CAE5A8327C892C075B2D0546C8C1B391B55A4EE013E0F600BA5043C242B1735EB5449494F9E9BBB2EE7C741DACC97C08AD4ACBC2A6B40C36847547A4FF29854248484CB9CC17D98941F544441F0B674898B21873785FC204829B3A8074BE8113160D0CB0AEEEE9B7795B6659669BD3311A722DDA728AC095933A8B130FE1F45233005F73159381C4C8B10F8536837D1931B6D40C9FA53D4118391600FDD18126AC926D3A745172186BEB557CE6F0D7911A5C9EE387689C799E912" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "E8AFD845036AB72B2DA4A7F200BD75B0C360AC607400526B824074F1D836F44F00B70B6BD2EF4B24E7CEE9BE756538C211259BBDF2C0FEF31BAB344E8E9FFA17", + "78B88EE379CDF8A2360847C93B3A63AA499203F3797049BC642848E807C40766CC1D18340C5C6E26A325C3A4B3B4DCA35E26BC574511C860BB8D935ECBF69BBB0B73C2DA0CD5885CBF285885C5A7A8913C0A51CC6765A8E67837BA1C17AFB9842E469629791647CBB278B5B916B3BE94706F02939635F012097B76E9D33A3CF53E502329B0E6890B681FF7EBB027355A4A738970782FF17385D6C01D91D422FB9191E373256A26C6E6C586AF10C53BF3605936B35295987F01BD4782BB70F140092749CF0864D9B46B48974EA33C7512F1991EA3318C917F8030CBA61198B1EC779B9A2C00B90A4C0757F5E373F80C10F8F985CFE4C79A43BE90A691DCD36CA9D5AD73657A41EB255B89420A350ECA7263A63A23F3E2624CFA5ADD4828473814B7E5497DB938A87A1888966BB9D7CB9CA972D74975A5AB51204B6F8CB6C738906091EA003DB18A4B41BB2F38C9C9801DD9932760DAC0CBA6CBD3F13955BA8898A46CAEA84F239C8019326ADC2A5DEA03A868C56877E4B2A3019DE921A7743468A9186778292F468714DC7905BFE326DE32A068F05C9EEA819C95BF1D611BA02954EFE7B4E07990BB795973F39F053292F98A80BB5930072ABFAD1772C02C309469B6EFC726C0E088DDC6729E580C38323D7DE221FAA2BD52B0A5DFA936FD293E00B7C22879054E4B957C275B850B25C004444387A627D85803D2C51EB2AE468C286D7B476732A73C192BB0243163E34217C3320AA83894D8A4C2522FCB343340125E503B723D1C0A9CAB88D5EBC90A18A75D0C6B6FA421D3EA3F2D5743CAA8356D99AA1B0AA6210B456B7AC6185576F41B995C123503B6082057CB1C0993A4966E128326E1B7C736DA09C86609C1C74C967985C2B1C16CC707EF044FCD624A780335981275729B1D18F94BA6F78BEA9063D596316C1A0365EC58A2AA92160310CB527500E980019796CFF04087F265388C58967A8450A780C8D3BE71A17CDFF51C339944E0A92A2532A61564163E45831DF1425A172946E677C1C904B4DA4E1F41CEC30B130F594644B51CBE34AA3CABA2D8B612DABCAEB74C47A600CF57B0977C00CDBBB207E00591FCF11F0C3831BDA38FD43312C052435B5053CE03653C0A9C7ED237636BCE189076BF1C5077917DF161559146C6BCA860C6E6CDD1E44B335B045683C0BA522BE523C3D3372E9A340BC0539056CA98C1570652B723014530584796482A5526C9860C5133AB431728CA818EAC4DB58A43EF970FE2400AD1D5A01E2178E79B193B014913FC9437E534C595C3B84848C4BC6546E8946BD66638C45F22B5CF73AA790B01A0F02947E6E904FC3146DB4B46B0648875C362AFD079770626D3786836E2910E4394E0772964BC67AD32A10B9067A2A62271070B371C0EEC8705A3C2AEB132CF4F41906FE31D602CB4BB5A0614F1979DF0BE6363BF06558A0BCB83A2E26F2B59B2C2650944391369367D40A60FE0451C9A041E5BD08E7B17532FDC2439345B6088C4EF0ACB737017F54A3C04640A9E644053F06F6397920BF960D2A71AE336987079206F6A722AAA48A0F718F736A8761C35E0D8404F478A7A973DCF774420349FBA08D0598527523058AE2141636116252B370685A6F263CF96C7BD6F7B845DC03BAE7A36DE0951ACAA3478EA7BC953B059CAC3E8B1234BE1359CA33AEB99400D16CCC3672726D03AB5A65361D482F740B94284360A8C03FA76457199256333A8E3971DDD87CE30BA9E039240F568A0C88912E9738E6D2B4A1C8617EED16322103343AB4C7A0364AD56CC5646806EF2941FACC850496C94DC19C7388EBC1A343C835783C9A26102CDE5D02502782BB3B4320DE06432A31AA83145D720B077657D6B7A8B50021DE77697771092E98612D2C50B12A398F8A32444C48B8430733FA2C7C34B00EE448E0AB40C25D4B76DF6C63DB78CA8D0C74625375C4A299DA82E27A400BEDC9C8C99CE46D60DA309104F182C09CA6B2A21C07676A21509CF63B96746084B4605BCAD5588684B42FE6912E60721AB8A5684D7CDCBAC5AA5D1826A90BFEB6237309465F8251F54310F9E10A9AF998B5D3236EAC265E4040164389D5BCC1FE45BC23B0614CD585EDF8367C74967BD90B5461541EDE2B6659704C438CC8A8A21E604A9A4D8357ABC64DD361330152ECE93B611C2F41FAFBA719B6329BCE996FE43C82F2E7E78C15154DE72B10766043BE217", + "C8C33E422A3816146B242C194CA5BC1089198FB4C6472868F99A50291527C5E76E95067B8F7C5A97EB457D8C5BD383B907D395083955BD0A1E18D97C07E9B7F33305718290B072C4CF2BA74C482C49870DB5AB3677855818D16252C3403AC120213188A7C47D3B974445758AF82980A0DB32C71845B8EA337D7941650A03C4D6419AD78A371036CC90B4A3720934431018260418ECCED1E82F4CB31AA31A0399010D70CA81A3A70D8A0420872583F84CA98FB1554C0485FE437FEC099C8556CD56205E47585117D819EC206D2EA64D9D5728B6656665E13ED0025BA0719FA8B74F9738B7D281A233D93A0DE4A5F29403EE6716697969A3A19E9FB4CC9A3788481A23B2A7CAF6ECB87E655BC825135868598426128A71715B98230F02B1ABF2C515520DE0733A90526F00581B851931A9D9CE91F28F791B330AB98DE235BC3BE063FA1AC071871CA24A0F2604C4C331AD13D03EB8C3157C4A300F1AA543D57E47272F5FB84226BCBDD934CEF3E05AE65837ED244D1F667A7FC4552FA71B74134BF69099D8C078714BAA4D6ABE6DA43AA12B5CD158487DE7BC77748FFB33545C4B8DFAD00CF0342EB6634B037251BBF677A31C4E8702C7DFA6596C1B2092F11C09CC2B1D51C1290276CCE0360966699BDA82FCCA7C02C9352C708DFCA891902978F943856B7965F8B1BDD6463C2580A1E676157DA0A200E881C5DC154A4611A7CB6E3BF271B2E81501754777687D5C712E350C4B3DCB77FCE291DE37240F1B1550628570A63CB9298855E8C3791226B3C61837D8C625D99D8D18CCEF77C7D1490F82D9388DA355C2A151D4AC01B4654A7AF8BAFD857A4974A3BE581CB5AA45A23055D3C0671D8312CF3B1CD0D706F6B569083B47247597972C2C048A25C9833165831E0398023DF786D573BC57CCB21646AC9D88030F454B30BBC6E08B6AF4435448D761EA50B2D1223B3F191D24C54C0114978A50B53F41382A266C68B65A871B08C1902F5B7696751A0F0E889B66036750E641CAB99A127937AE643494FA2AF7BCC7F0C8BAFC3A0803990ECF7A7A15423D03F5023F2C04A0C972A641439BE5038178764EB44ED886CEE977BD06FA0F6739758AC53F4BD624DA4893C468CCE390AD22D3A6DE151447594937AC4A3F84597464A6A678005A62B61AB8623AA59289B9C6C748584172289B33377C0AAEC6B85799127374675615A9823EE4624A20A99B134B08501157804395465DD3E95C6309738920235ADA42D044BC0448CB0F86877E200D7D469D57DA7B10504BE0EC77B4371526FC8542E21582295B8428A7B231BBCBA60424DB863AD370A889B46FB940B3F420D28971FD03B5ACE084E083577D289412D2C63764226AD97934E3AA2C4693ED984439106DB775895A4A6DBDD11767EA76E368B83F00A9645873B093887C3197C133431DC7C72F675AB55864F4BAB726F595CA1C5B40B7689F9C10D970B40C9259F67A6AED5916E5069821B8553D276172AC5F7A714652F0362193142AF25F76AB258DE409D7F5CCC0D0A4BAA067004D15B7045282998CC73201C5221BB34A59DE564262237F422001A84A6AF276B8E06B0B339CC25BB83D9923A55B441FAE797ABCD7A76250CE0516820EA9B8E704904B0723D2D610773503418C6F72940F4155188C3753D7CB8B9F007156ACC3FF0B55C442633C6C80629B4A5FD956189B0B3A650E8034C1C0A7753B5287855971BDE4AA8F1702E2A81C21AB3B7783C91EF76B9153B48FB7713B77C161832A88385FDE1A1030A6AC389CB1B81812BE28C1940A4AA897C42A5570ABE6A2321425353004474C36DBE950492AAB3FD64430E75268873DBDA0A1CAC199991664BAC22DBB554FB7C15F54A22ED8F7A51B463E24A27397C18AAA8538B6B0CCFC482C426954B205532BA674EC3230AD8C7000A79DB9374956C364D170ACF6679598D173B6271539061824A51CA379632945921EF31598F21340DBB77B779D082A18A7481094743FA2647F44DB3F0A6474C9058BA0A269E2A0A558877BC0EC6B04871695FAC20E330280EC266E83585420B3B2F2B55A09AB189B4DCCF413AB6CCE6BF1B741CBC28A5435C02A3BD84B98C689C79867A94924342207268BB30D719173B2C149A5DC2428AC4B76A75D4A487747B6B108C28CCBF3778EF357533295C3889578B88EE379CDF8A2360847C93B3A63AA499203F3797049BC642848E807C40766CC1D18340C5C6E26A325C3A4B3B4DCA35E26BC574511C860BB8D935ECBF69BBB0B73C2DA0CD5885CBF285885C5A7A8913C0A51CC6765A8E67837BA1C17AFB9842E469629791647CBB278B5B916B3BE94706F02939635F012097B76E9D33A3CF53E502329B0E6890B681FF7EBB027355A4A738970782FF17385D6C01D91D422FB9191E373256A26C6E6C586AF10C53BF3605936B35295987F01BD4782BB70F140092749CF0864D9B46B48974EA33C7512F1991EA3318C917F8030CBA61198B1EC779B9A2C00B90A4C0757F5E373F80C10F8F985CFE4C79A43BE90A691DCD36CA9D5AD73657A41EB255B89420A350ECA7263A63A23F3E2624CFA5ADD4828473814B7E5497DB938A87A1888966BB9D7CB9CA972D74975A5AB51204B6F8CB6C738906091EA003DB18A4B41BB2F38C9C9801DD9932760DAC0CBA6CBD3F13955BA8898A46CAEA84F239C8019326ADC2A5DEA03A868C56877E4B2A3019DE921A7743468A9186778292F468714DC7905BFE326DE32A068F05C9EEA819C95BF1D611BA02954EFE7B4E07990BB795973F39F053292F98A80BB5930072ABFAD1772C02C309469B6EFC726C0E088DDC6729E580C38323D7DE221FAA2BD52B0A5DFA936FD293E00B7C22879054E4B957C275B850B25C004444387A627D85803D2C51EB2AE468C286D7B476732A73C192BB0243163E34217C3320AA83894D8A4C2522FCB343340125E503B723D1C0A9CAB88D5EBC90A18A75D0C6B6FA421D3EA3F2D5743CAA8356D99AA1B0AA6210B456B7AC6185576F41B995C123503B6082057CB1C0993A4966E128326E1B7C736DA09C86609C1C74C967985C2B1C16CC707EF044FCD624A780335981275729B1D18F94BA6F78BEA9063D596316C1A0365EC58A2AA92160310CB527500E980019796CFF04087F265388C58967A8450A780C8D3BE71A17CDFF51C339944E0A92A2532A61564163E45831DF1425A172946E677C1C904B4DA4E1F41CEC30B130F594644B51CBE34AA3CABA2D8B612DABCAEB74C47A600CF57B0977C00CDBBB207E00591FCF11F0C3831BDA38FD43312C052435B5053CE03653C0A9C7ED237636BCE189076BF1C5077917DF161559146C6BCA860C6E6CDD1E44B335B045683C0BA522BE523C3D3372E9A340BC0539056CA98C1570652B723014530584796482A5526C9860C5133AB431728CA818EAC4DB58A43EF970FE2400AD1D5A01E2178E79B193B014913FC9437E534C595C3B84848C4BC6546E8946BD66638C45F22B5CF73AA790B01A0F02947E6E904FC3146DB4B46B0648875C362AFD079770626D3786836E2910E4394E0772964BC67AD32A10B9067A2A62271070B371C0EEC8705A3C2AEB132CF4F41906FE31D602CB4BB5A0614F1979DF0BE6363BF06558A0BCB83A2E26F2B59B2C2650944391369367D40A60FE0451C9A041E5BD08E7B17532FDC2439345B6088C4EF0ACB737017F54A3C04640A9E644053F06F6397920BF960D2A71AE336987079206F6A722AAA48A0F718F736A8761C35E0D8404F478A7A973DCF774420349FBA08D0598527523058AE2141636116252B370685A6F263CF96C7BD6F7B845DC03BAE7A36DE0951ACAA3478EA7BC953B059CAC3E8B1234BE1359CA33AEB99400D16CCC3672726D03AB5A65361D482F740B94284360A8C03FA76457199256333A8E3971DDD87CE30BA9E039240F568A0C88912E9738E6D2B4A1C8617EED16322103343AB4C7A0364AD56CC5646806EF2941FACC850496C94DC19C7388EBC1A343C835783C9A26102CDE5D02502782BB3B4320DE06432A31AA83145D720B077657D6B7A8B50021DE77697771092E98612D2C50B12A398F8A32444C48B8430733FA2C7C34B00EE448E0AB40C25D4B76DF6C63DB78CA8D0C74625375C4A299DA82E27A400BEDC9C8C99CE46D60DA309104F182C09CA6B2A21C07676A21509CF63B96746084B4605BCAD5588684B42FE6912E60721AB8A5684D7CDCBAC5AA5D1826A90BFEB6237309465F8251F54310F9E10A9AF998B5D3236EAC265E4040164389D5BCC1FE45BC23B0614CD585EDF8367C74967BD90B5461541EDE2B6659704C438CC8A8A21E604A9A4D8357ABC64DD361330152ECE93B611C2F41FAFBA719B6329BCE996FE43C82F2E7E78C15154DE72B10766043BE217FA91A9C70F17C8D9EFBC24AF32FB0C822334B365646136DD82DC9171C212546000B70B6BD2EF4B24E7CEE9BE756538C211259BBDF2C0FEF31BAB344E8E9FFA17" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "BB45E6A05C79FAB39099B8B61917F230D245389D0F086F55635E97099F2D18A3923D3D0939AC084FA80DB64EF6222CEB788759E86C0AE3F84E204C65C8A2C047", + "6CF7AE05118C0D99737AA38457435B07B2CD33D001A7B1B6EFF72CBE18771176BF03E528F6DB5208AB7C3305B07E6009A24239DCC46EA265A670F78D4ACB21A218932A9A2FF464AAC95BCB03F30F5A7BADF213562657A3DB98532039AF1CD870AD022DA9034A2AA092D2646493E2234A984957944E1C5B3BBD859F818834B10956F1B743EEE9166513B700A00FBE9327DF6B3B6F7910919BA67FE61699874710651A3CB57E33C680C0AB4FB3512567F45AFE6653690463CC875464DA2CB2804513E9420D9C2ED24437DA3085E2C5593712389E523E89BAC771B589FA398FEEC2984AB48ED9DB38752C52E3A66B35D755AB83C57653CD3ED9A301487ECB5C57793C83D59776742529EC11903E612B45D268F07419F1E8735F106257A1832AEBC70C361AF01532DFB1A460A013C55688D94546B3CA9340A937BF0B3FCFB0C7A4C8124D5669BD3295A18639315B184040C8B6C2BEEA932A8E803B7B7654E0044621F4CB2E1C48D5C90136457E7C023AB0DB8D3D159F396486C92309231431E7338944A0696AC0273DE4B1B5E688893A5FB96C06AF234D828AB141C0B69B5AC0DD6C6968B8BF92DC6A20D23DE1A88AB76487D56A4F60CA3D6BA1AAFF784D93756CFC373E6E42CC5EC62677269434D04FB947A5CB34053B715688E4125C316DA8017E08F8C255BC29F256B04F17710CB54AC0F531641588A0213E2A2742FC78B7F4644419A8507673861A2ABB8BDAB973A3B7C1C87224269D8D032263B7AF72C028AA1A6BF261355CE75998E167EC518511E0037CE843989C65291734E6A39E4137185A4267919AC173D87669685C61F397C046BFBBE101E37B30F08CC081010079E0A58EC649E41CB7BA6377A490BD85CA92CA2B55DA6628CF2C7E54C05FC278425E4C3509B51EE3429939B9A7C5B2643343BBF6E60B36E7CE41693CD16B6D035014BDBB682FB92D1504AE4F2144E2B52FC6086FC076829CC427BA9490767564B6B70156F5A809F7B1D234B91F656031D50A440B1CE7981C694146F3D023D8C80550D07E3AF568F0E2ACFAA2023095BBECA0C361CA2BD0D79FD97386460C1312A337D6F7CAEB47B078A73A039026605463D25B54DE3461AABB6668986F33168AF92B7810557F00F389444B7C9788C6DE31321F604D28D8A2F325890AB5915B48C4A7EB06D0842836673AE46A1103630189C064D2A5B38C48115DC4858802003FB13194369C42CC9B03433B9A510EE5792536A53F832838B27BA7BF5A2AAB508328CA98E7BA97FF1A49F0079016E586C9B8CE971A49433790BC8C90188697EB4199D5087200E7A67DB72ECA65357EA9679527B6834B2F7256BE64899D3DC6395786A90E2A725A56AA1A3A8F47E05E882AA86B170D453403EA40232EE87EB0A1AC74092006A18444291E1C0B659DA34A6224AA897273EBD07058125902306C7E1A7A0BDA71A6F8A9194B5B670865C5FB6625D1A54C24C5E5838488E3301D581987C27795083BC9EBC535588086445814F794955349967494A3305E8915B289579D391A17C2A32387BC48CE89A8F7D9200FE5A392088452B3CDDA94BAF4B08C000CCA63068B62CC8C7AA9087CB33B62F37952513B063B3E4A4B71BC96836E428D75E3655AF80F5518CEC5EB360863A4B8370AC8F75239A96FD825CEC0E0CFFAB942C3FA9DD337B74A5C5AB1D844C5DA94CBE10D38E6690AA57C10C20E7DE7B089F533FCAA09E55A1183104D350C68FFB411E03703376103D1967AC8B4072DA21CDDA98E24DBC4905B13CB618FA21251F957644F7B3CB1A6001E63B25139102EA150490A52C6BA1037DA889946897B08BF8CC9B1C60BB5C020566786499A76CCFA785FE8B06034A843869574CAA248ED3A98FD73908F37AF365721A984143E269CC933350E9CA57D9341A19B5355E0193BF22BECDC235AFCC4ED8BA867A9C547B8C5BC31B82F87C1B7E5962DECBB79F412377352B8A336884845F6C1175B04BC6D38670F802706302626953C0D3750BDB8BBEFAC6CD8F0424C36C869213F6869C266BB0A8EA9244F968482DA56F2896FF2F1A9517C022E5281E5D41AF6A781414555BFA0271CCB056C79BF1DC277D3F245FB4C4C27368DBB9828E184422477586246063F9A01E4EAA88810409C9C7ABA5B36746294FA7A0B577CA2503517883B96A72A8F014B6C58738E94F2089227DBB1FCE2E613B9400A0F8532DC225710D6CC92BBC2", + "390A967ACA9577985C7E775B44257C5A3842A391315308CFF0537DF5702581F3CAD22A8691510A74D1AB8EE41943B38057C092A64B65E5F24E93A931F236232A71311E662608B1C8730C31C61C2251FC77F5771EB581A131B9218F387F1A3584146C8ED664A6C93A0CBFA2753089AE0DE5823E583145E6AF97EC842F725A89DA297D61CD8758219A40C07D32A68898CAC41787B30B55DCE29F5DA491C4302DD7609B2EB8AD80708B7DA21FE4C75703E743D3ACA53B4864769BB6A148AB6AA11ED7DC20EFF41D75C16629B99F01FAB88B381B716C26657334739006079676A57117E56A9F5171056891623A9B45C5008FA1E54684E592CEEB959571A2CEBB3555633B0DBA37FB660566EC038B6748A1CA90C55417999A28952147F36974FD2C1986EB8044024CB188859E48B884B937B44C255637058FCB69C579B68C7737DFE7A40ED5BAE25000B43C5AB2625B03646259F46240E23F19D918300B91FCF9296E804639A120ED84084D617BDD88B15DB8545C9C45A3C76C31A051F652979A0A44075121BC2C54E933BEB0DB142D35CD84E92D5CEC25A8471D16616D80761C177608BE5C7BA68729A4931E7947CB18A67BC39766464267BDF431FD3C887B74AA5B7679BED5875239B088876668E758FE581680D96B57CAA73E3173425C31CDE2C66A81C5C0620D601827765B18266C5188E779CC449C1E22A38DCC76A5009D73449D915B1235A06909023C786B9FFA9711F294CDA815B8DEC5C14501B1FEBB6ED27A7CF5436FB612005A193223F9B28D74C6ABC12A3478382A905082DA67C4F7270A174728F9253A615D85FA0222AC27B95A83E4C368901498D3AA08E688C73C87A266694A8222085319226F46662F344C1F282747D544CEF0BDEC33B67D4255E4AB9415D90CEC3CC044D92757075D01B25AE5CB1842E00CA73003619C151DB2A2DA050240FAB7D3D049CB3499B27809B2297C0CE23F488822E457016C57C3FC489F8DCB2538249876C8B8AE511D801431FC613F129BC86A990ED2545861557C995B65925251A0668C3A81368847BE74414FD1473981AB8795A91EB81697390627CA88A9C2D1CDFDC41E14C0B0E9D37FD9A1A13D308290338C28B4C87EF85F94563E3A91403A5B33701AABCB9242D960A6C02060E72B734FB001653685F3141485CB8DFA573B0DE2829D7C60E16782F6887835827645384125323ED44A012780B746A89AEC2412838243DB12A5A61CC2E79C36FDF2113DD6C6F0CC75E99246BEAA9C0DE5C1F744BBE18C643E6433BCA9226BF1342F2989C8D78E38740F5C992D996668506533C29C8CCCCC04FE8C821172C6B2F8AAAFA8985FC33EE90354B62A5F4C436377832F91681490A5429B259F54543A07B1986B8149F11BBDF889A7F0073890B00B9AB4584097B5BCF5B25525CE89D30B2F46675422AD51CA6DF1100FCC274CE1C49EAE3AB9368CCF8BE0062C7B3C3CF63B6EAAB1AF2161E6D6767FC48C876150B01A0AFE4304AC3531B482C51980967864C6B53CB1410C7B11B9296D656012F19E245266ABF07D06690594498502A681348B98B283B8A8BA47B1E989B49AC9CE76799130638117BC02BB5C172104326B15D6D54F30B7CBB4DC6464D6AFAA467933EB5A52C65D4C3324987776953B11D3F2531479465BD6658CC42C62A856BC10243748BDC0D61285287E13AA05EB7215883A9AB72BC6BFE737DD0527DD899B335BBA1940206C9C8497963EF1AA854F2B20B3C450D7DB2F4C9C08B8E158D08A62A22B5C9058800B4C4455954F41E8C56F96BDD17CA309B2070DC82B3ED98F8C04887CD2933773AC536A2CA0E50FE9D573AB839FFF595743F2C2A23A55D990C07BE3C5929B2203CC2D6D30B985A621B15B9152807594F0A8EA782CA54A53D871167D1BA25CF36C29B117C14A1A98302B115ABCE58A15FB04368364CC6AF50038F804BE0C50D1379F6DA21A676951C9E493E84C012BF64E562C04A8D47B0401840EA55543EA80EB19C5AF6658AA8BC0B93BB7A3E014B5D41D2DB7613C93466A303C25B83CD5D0AE2684B977E1B18B33704D51A7E5077B1D59211C223A283A1595ABA39B2BB131FB1C812124BA1A65BBE13C79129A4C8B47B2CC0E5F18A5C8541F468BC528A42737759452D715A5F2A6C3FCC1BB20B869FC9F14E678BBD0C56CF7AE05118C0D99737AA38457435B07B2CD33D001A7B1B6EFF72CBE18771176BF03E528F6DB5208AB7C3305B07E6009A24239DCC46EA265A670F78D4ACB21A218932A9A2FF464AAC95BCB03F30F5A7BADF213562657A3DB98532039AF1CD870AD022DA9034A2AA092D2646493E2234A984957944E1C5B3BBD859F818834B10956F1B743EEE9166513B700A00FBE9327DF6B3B6F7910919BA67FE61699874710651A3CB57E33C680C0AB4FB3512567F45AFE6653690463CC875464DA2CB2804513E9420D9C2ED24437DA3085E2C5593712389E523E89BAC771B589FA398FEEC2984AB48ED9DB38752C52E3A66B35D755AB83C57653CD3ED9A301487ECB5C57793C83D59776742529EC11903E612B45D268F07419F1E8735F106257A1832AEBC70C361AF01532DFB1A460A013C55688D94546B3CA9340A937BF0B3FCFB0C7A4C8124D5669BD3295A18639315B184040C8B6C2BEEA932A8E803B7B7654E0044621F4CB2E1C48D5C90136457E7C023AB0DB8D3D159F396486C92309231431E7338944A0696AC0273DE4B1B5E688893A5FB96C06AF234D828AB141C0B69B5AC0DD6C6968B8BF92DC6A20D23DE1A88AB76487D56A4F60CA3D6BA1AAFF784D93756CFC373E6E42CC5EC62677269434D04FB947A5CB34053B715688E4125C316DA8017E08F8C255BC29F256B04F17710CB54AC0F531641588A0213E2A2742FC78B7F4644419A8507673861A2ABB8BDAB973A3B7C1C87224269D8D032263B7AF72C028AA1A6BF261355CE75998E167EC518511E0037CE843989C65291734E6A39E4137185A4267919AC173D87669685C61F397C046BFBBE101E37B30F08CC081010079E0A58EC649E41CB7BA6377A490BD85CA92CA2B55DA6628CF2C7E54C05FC278425E4C3509B51EE3429939B9A7C5B2643343BBF6E60B36E7CE41693CD16B6D035014BDBB682FB92D1504AE4F2144E2B52FC6086FC076829CC427BA9490767564B6B70156F5A809F7B1D234B91F656031D50A440B1CE7981C694146F3D023D8C80550D07E3AF568F0E2ACFAA2023095BBECA0C361CA2BD0D79FD97386460C1312A337D6F7CAEB47B078A73A039026605463D25B54DE3461AABB6668986F33168AF92B7810557F00F389444B7C9788C6DE31321F604D28D8A2F325890AB5915B48C4A7EB06D0842836673AE46A1103630189C064D2A5B38C48115DC4858802003FB13194369C42CC9B03433B9A510EE5792536A53F832838B27BA7BF5A2AAB508328CA98E7BA97FF1A49F0079016E586C9B8CE971A49433790BC8C90188697EB4199D5087200E7A67DB72ECA65357EA9679527B6834B2F7256BE64899D3DC6395786A90E2A725A56AA1A3A8F47E05E882AA86B170D453403EA40232EE87EB0A1AC74092006A18444291E1C0B659DA34A6224AA897273EBD07058125902306C7E1A7A0BDA71A6F8A9194B5B670865C5FB6625D1A54C24C5E5838488E3301D581987C27795083BC9EBC535588086445814F794955349967494A3305E8915B289579D391A17C2A32387BC48CE89A8F7D9200FE5A392088452B3CDDA94BAF4B08C000CCA63068B62CC8C7AA9087CB33B62F37952513B063B3E4A4B71BC96836E428D75E3655AF80F5518CEC5EB360863A4B8370AC8F75239A96FD825CEC0E0CFFAB942C3FA9DD337B74A5C5AB1D844C5DA94CBE10D38E6690AA57C10C20E7DE7B089F533FCAA09E55A1183104D350C68FFB411E03703376103D1967AC8B4072DA21CDDA98E24DBC4905B13CB618FA21251F957644F7B3CB1A6001E63B25139102EA150490A52C6BA1037DA889946897B08BF8CC9B1C60BB5C020566786499A76CCFA785FE8B06034A843869574CAA248ED3A98FD73908F37AF365721A984143E269CC933350E9CA57D9341A19B5355E0193BF22BECDC235AFCC4ED8BA867A9C547B8C5BC31B82F87C1B7E5962DECBB79F412377352B8A336884845F6C1175B04BC6D38670F802706302626953C0D3750BDB8BBEFAC6CD8F0424C36C869213F6869C266BB0A8EA9244F968482DA56F2896FF2F1A9517C022E5281E5D41AF6A781414555BFA0271CCB056C79BF1DC277D3F245FB4C4C27368DBB9828E184422477586246063F9A01E4EAA88810409C9C7ABA5B36746294FA7A0B577CA2503517883B96A72A8F014B6C58738E94F2089227DBB1FCE2E613B9400A0F8532DC225710D6CC92BBC26722FE3E80CE22AC852CE4BBCF346A3CCC1685BD14F5DB3A081BF7EFDF34E222923D3D0939AC084FA80DB64EF6222CEB788759E86C0AE3F84E204C65C8A2C047" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "0A45C90756550DC7EAD5D608CDBE54952568217C6AA444D3AB1EEC9F7A208255EF3ED2282C1F2A60FE72FCBC2A51E885A00AAC76E4EECDDC6DF52780B60B3AE6", + "F602105F361278EB5B3EA01F680851D420B507BCAAB3F9649D896BBB889B454BABDB5BC692774A13222B87D0A56EFB175467424DE65D86D42B37085260225CA37807BAA06E3E1945B09A247CC00912BC6945A29F5F21B44806B97EB20C63705BC323B796D68D2BC663280B102584B21556067E498D527AA96062913FE023F524714BD4988971BFED027C4A8ABA12FB2F3F48AABA077FB3060B18C291BB841CE4D35CC43BA471A6BDE5B40322189D640C5FD03A769712B73484B9964CB8BE8086FB36A371113C05619DC740BDFC0541114690C0BBBDDBCC5DF0931D8B625B82A41ECFE96F8CBB7B2647C506015657EC7ABC21C302EC34F6E437F5C8BC0AD43D718003E3F75838888279700D7F488DDCF235985057DB52975B998AA2C73FBC31B5ECE80BC38269549844A7D3687FE7257226BD33FA1B4B6864EBB38038E0986F2757CB1A0A76D27C45FB15F05680F90A25DFF046DDFC8D2376587B581AF0C8A14319425A097946FCBC018A183FD9BBF8221CC2B159797C49975233914437529C86927627A9298A92B854080C103CF4CD9AD1B84C2946AAC32633FA3559C73FAF470329DA64819A80EAD853802692A75C92F24711C8E55F5042AAB7C48173B7328CAB3D5D3618F326186AD5A649F2C361F5463CAA0180CC1558956865E455F713991489129096410BA50472541C06E8B9C34CB5E3D314B30CC9F4B647A26978DEC48C6285CF7E30735328AB9EC66A8598AEFDA708BAAB306D13707FB3A825429BF8728AD1FB3198F446B0E8B934E9846DBB9B4E61935396362137C6BF11783BDC782AF5AE42B4A04FD3A30FF7C55C234A1C5B8881F1197927AB22A3449BD158336B51A08069449286E586C92A33CB1A87248856BD66936C62B12CFAC957C65125613B750DA49C7405B8EAC1ACE69B1DB865C6CA36ACDCC90AE6E288CBE35FD33851E7E7291037429CC46B39C268A46B247F5365F6030BEFAA496AB7BFE0D3155BD6346A76353388B5410A579C93743C3A546FA93F0880A21779CCA1E2974AC452B6C5746733CA438A25BCF5CD55BC7F8EF9672E11B056316111BC400508AD1BDB092343082A12239D5478E240B7C322CC87E21899A7B1FD9B0D9FAB8C59389E3D37CCF8E43C4DD216E98CCD3E8A50D5D90913A2BB51538D28F37496302BA8AA0545F6AD4D396D00337D44B03FB13958FE41B1F1640A58C60EF4442792E36A5BD76EAA77BC46FA6EBC100DBF432DD408A5C2CA63A908B12D0C8A04310230D7287D6B859F7A6224483ECFE969D5AA4286122562E10E016996F2D374BA3C214948886FB53F74412BE0F51770F06E42326E0D8017D6590E7581BF26128B905702EE4051A1B970B5BAB234C6503CEC3286F30C35C31DF8512DD87C992E394AFA04A37445A300FA8D6F2A3817D8B369C4A1FB9A57AC1A08FE958916522723051EE2D4256F24838D648A9EC921F6A9456090711576A5FF511FB94A031B248236423F66424F06835DDF0408BD5A4BF7B589413BBB6C5BAC1EB7AFF61854CF121903A161B0FB6F68D844EF9A515E38BD54F76992F06E5EEBBF773624C7D61C6218B19ADC4ECA72104B9A52D0A8A5AADB0953B440A545913C5B51504B42DB3BBB941CCBDE350E4A59BA71BB7932851D95C54862E9161F7A8CD36BBAA6FA66F5E07ACE071D558CB4743B3CE74B9479540EB69627589BCB5C87533A34734A2A16E3548EDE487B48B22DE3CAB9E58B43AB78A4CFF67E17BB7E5A368D24E01E7A90548451A67427802A623C8C3B759D52245953AEEB7132DB711819930DFD428531F78A9AF8C4F7407B8BC33A0DA9CC3A195ABED660E408C1C0903D66FB887AE58B90699A15B2A7066CA99F50A1E73B2FBD939B735AB14AD78B0278BD27729AAAA5BA031509827A570257008E4091B108484FD5755FD21073F5995974647DC4BEA23769FC382D7928BF128162D09A4665578D14069DF5968655971217D21B3D2341CBA169D6960A29B2634C47973E5C9B0C8659078B984AACA4DF662FA35553C3C05CF1854D0425993DDB58C00AC98B956A9D2BBA5F72CD242491EDF756D8174D79469A61101E1FA0CFBBCB8FD31A55DEB8842E13C8EF5799A603CFD7609E9B826EDE3AB4AC38320AA7333C8469A3605C97518D3B320AD1E4B81864514B716FD9F86E0CD763016383D8E093D05ADE27FF896BA959F1EE3C28D2E7AD65A938ED12168D52CD921B6F0F", + "042B94917A50366ACF55D82C607B4AB42434A1A433024A11AD256A13830E991AAE6E996DCBE9CA31D56B39DC47D098129796602C4BA073225A89F78FDD58ACEF803D3B0BA649266A10F622812ABC2F607DA0C069CD732BEC99AD55A70448420366E8568E0448C9A8A3384B6088BA17276A14321BC3163C718E86644A066C229428839CAFE23A4F8E510FB37A5F818006600001B1BB14941C92A0CBB5790B37A38A933C178F36E9AEAAC5969E1B27E54B2B3F7A026BB018ED84B4D9D59F20EA09E4E8BE90E77E247C4202E13236103BEA018F7DCC49069B093AD75F15D7806A328B124C9E0D7400DF60496C55381EB76B5C953BFCD208AA58240BBC9F512A4DBBF76A191C88F4D13C9E252C6ABC1F1D24CCBBA13BDB574B1A0B07EB9914175860AC731A32F6507E33558E216D25324F73663290D5326BA7A30F292B21A70AA32559CF39C4D97A0696047BD8F4A250BCBE1E06795A5B37636B852CAB2D4ED80CE67627C7C00866442A46645C2A6019242CC429058D51ACCE126909AFA3785B6717F2F9708744C91356514CBC1D9BF9284BD7353D2AA471F2C5D33C3CB7980A50D75A8EC04473629F14F9A51885BC4F3681DE0813D35B80983184EA7536D62066EFA46155985A32B451363038CCE2773EF74BB6903E4817AAFFBCA580E1A6CAB8B2BBA1B478C621964AC3B744767AB23A96E4BA7A17CA850B02C9E3BF2E4482782C5CF0C273DED8B5F1718AED83550EAA705CA885FBF2656839C4C4A485F4002C6AFC37E4CA4BE2A7449499290E083F053A832E2C4FEDD0331961C915D8CE49883053A6004828CE0B86154A7B6B0EC40A978A10BC32319A0B21CD9B212738CA9BFC64F1ACA0AD1A4791DCA94818307A013A6A81AE06701D412725A0F7CEC791AF2B0BA4F2D60FCC6570C89BA330239E2E55469E488364AB4604E390A3942990FC7843D829CC887EE3F7C621211CD5367A59A052E1AC0EE6F574769230C97C560F128C75D1061DF844F5328006AC5B6FF13D0CBCCECC95A65293A40F8B733B9C54DE710832D21A1B8BAB76161ADF18082564BEE02629C62B802E0258017A795878A5627B9EEBE47AB955AF204727D2806B9F267B085CC283688BD97A3F34919875889BF44A27A9308D9EC93452B8B8CE2557D929AC2B7545D949C95D965B90100F2414787DA4B62743617D673280A24CB607242DB53ECF0880ABD87F4F9759F7E34C7CE6C6D2E349DFAC0EC268ADE374164A11A11026AE8B36BB236C5B3A7A610C26BC7D755FFFFC3E6E29CBE3108F1A2BCE543B44CBEA4E3A239F0B288BCA443A3C61B55AF27B89E22ED8ACAD0B2B53CBF13C0E053D2C7C2BA5D0CBAE01773F4260D729BBD7038AE49999B21045E9AABA7CF66109F815A47C481A2C824E35394067C11C592DFE128CC7037035733969E693C29AA8CCD451A1C89DDA976912F99FCA88882345CEEBE81E2F49BB8A8B92B5692AF5025875A024182CC03BC49147D9A5ED493175F96473A76332787598046988891482B4C7284756B4AC674368AE1B51ABAA9B69EB86993BC1C25DDA7789466DB515A405014E6CDA19F11B06AA7C541C6167F74676C2465AA49C940CB5AA35F41D3C964A212956562B0040D464DD9CAA042986CDF016A1D82702539FE630241E15B7AE200843745291A5C784672696F2853BF2A7D443CF0E148497974E774986C092CA71AA3E5C96430971C51FE649DC8B5EAA1ABD30E03DD9C9A08AE0B5A3E320A3B6CFD5715AFB3A19A85AC56270BF6C304CF6B01D7EE13D7FC8C24FE894CE72A67642A69DFB90F50397A4440D8C94A3EBE24041D38684B2208D69B87C159BC8CAA23268133247387BF151F26C0426C429DF191D46EA03347C68503025ECB592AAFBA345A692DCEBB95D9C414799201236CE51A895D2C00C396A9359D39F1C842D8DE47C65E5BBF5D57DD66900819445F45994499728B72A5FD554CFD483B6278CAA4D61AB82E7AC7E9527EF7B6C89D9948E2322C513045AB747F9C73960FC2AB8E290FC7A86F78489769763601C2D5F734E6E2AAEA987AAF330404EC720DC27735D9498893978767208CB90366E02431A5151C405077A988AFE883228F64DBE190378C356813CB4B0EA524CF94B9315B852B68E82C216C16738B9E77E9AA165F0C785E76C5EBC18AA57227F725B59F602105F361278EB5B3EA01F680851D420B507BCAAB3F9649D896BBB889B454BABDB5BC692774A13222B87D0A56EFB175467424DE65D86D42B37085260225CA37807BAA06E3E1945B09A247CC00912BC6945A29F5F21B44806B97EB20C63705BC323B796D68D2BC663280B102584B21556067E498D527AA96062913FE023F524714BD4988971BFED027C4A8ABA12FB2F3F48AABA077FB3060B18C291BB841CE4D35CC43BA471A6BDE5B40322189D640C5FD03A769712B73484B9964CB8BE8086FB36A371113C05619DC740BDFC0541114690C0BBBDDBCC5DF0931D8B625B82A41ECFE96F8CBB7B2647C506015657EC7ABC21C302EC34F6E437F5C8BC0AD43D718003E3F75838888279700D7F488DDCF235985057DB52975B998AA2C73FBC31B5ECE80BC38269549844A7D3687FE7257226BD33FA1B4B6864EBB38038E0986F2757CB1A0A76D27C45FB15F05680F90A25DFF046DDFC8D2376587B581AF0C8A14319425A097946FCBC018A183FD9BBF8221CC2B159797C49975233914437529C86927627A9298A92B854080C103CF4CD9AD1B84C2946AAC32633FA3559C73FAF470329DA64819A80EAD853802692A75C92F24711C8E55F5042AAB7C48173B7328CAB3D5D3618F326186AD5A649F2C361F5463CAA0180CC1558956865E455F713991489129096410BA50472541C06E8B9C34CB5E3D314B30CC9F4B647A26978DEC48C6285CF7E30735328AB9EC66A8598AEFDA708BAAB306D13707FB3A825429BF8728AD1FB3198F446B0E8B934E9846DBB9B4E61935396362137C6BF11783BDC782AF5AE42B4A04FD3A30FF7C55C234A1C5B8881F1197927AB22A3449BD158336B51A08069449286E586C92A33CB1A87248856BD66936C62B12CFAC957C65125613B750DA49C7405B8EAC1ACE69B1DB865C6CA36ACDCC90AE6E288CBE35FD33851E7E7291037429CC46B39C268A46B247F5365F6030BEFAA496AB7BFE0D3155BD6346A76353388B5410A579C93743C3A546FA93F0880A21779CCA1E2974AC452B6C5746733CA438A25BCF5CD55BC7F8EF9672E11B056316111BC400508AD1BDB092343082A12239D5478E240B7C322CC87E21899A7B1FD9B0D9FAB8C59389E3D37CCF8E43C4DD216E98CCD3E8A50D5D90913A2BB51538D28F37496302BA8AA0545F6AD4D396D00337D44B03FB13958FE41B1F1640A58C60EF4442792E36A5BD76EAA77BC46FA6EBC100DBF432DD408A5C2CA63A908B12D0C8A04310230D7287D6B859F7A6224483ECFE969D5AA4286122562E10E016996F2D374BA3C214948886FB53F74412BE0F51770F06E42326E0D8017D6590E7581BF26128B905702EE4051A1B970B5BAB234C6503CEC3286F30C35C31DF8512DD87C992E394AFA04A37445A300FA8D6F2A3817D8B369C4A1FB9A57AC1A08FE958916522723051EE2D4256F24838D648A9EC921F6A9456090711576A5FF511FB94A031B248236423F66424F06835DDF0408BD5A4BF7B589413BBB6C5BAC1EB7AFF61854CF121903A161B0FB6F68D844EF9A515E38BD54F76992F06E5EEBBF773624C7D61C6218B19ADC4ECA72104B9A52D0A8A5AADB0953B440A545913C5B51504B42DB3BBB941CCBDE350E4A59BA71BB7932851D95C54862E9161F7A8CD36BBAA6FA66F5E07ACE071D558CB4743B3CE74B9479540EB69627589BCB5C87533A34734A2A16E3548EDE487B48B22DE3CAB9E58B43AB78A4CFF67E17BB7E5A368D24E01E7A90548451A67427802A623C8C3B759D52245953AEEB7132DB711819930DFD428531F78A9AF8C4F7407B8BC33A0DA9CC3A195ABED660E408C1C0903D66FB887AE58B90699A15B2A7066CA99F50A1E73B2FBD939B735AB14AD78B0278BD27729AAAA5BA031509827A570257008E4091B108484FD5755FD21073F5995974647DC4BEA23769FC382D7928BF128162D09A4665578D14069DF5968655971217D21B3D2341CBA169D6960A29B2634C47973E5C9B0C8659078B984AACA4DF662FA35553C3C05CF1854D0425993DDB58C00AC98B956A9D2BBA5F72CD242491EDF756D8174D79469A61101E1FA0CFBBCB8FD31A55DEB8842E13C8EF5799A603CFD7609E9B826EDE3AB4AC38320AA7333C8469A3605C97518D3B320AD1E4B81864514B716FD9F86E0CD763016383D8E093D05ADE27FF896BA959F1EE3C28D2E7AD65A938ED12168D52CD921B6F0FD1FB915975884704D6B21A7A5C6144130D5B06AD3A5E6B7CFEF486B9B5D1209CEF3ED2282C1F2A60FE72FCBC2A51E885A00AAC76E4EECDDC6DF52780B60B3AE6" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "AEFC8873C0813CBDFACA93A56A0B5F0A0D2E440D432D48BD10F99A87BC50D6B9A10ADABA73D62FD5234D8F33A0371EA2697D66A3D5BDD789B6FB4AF056600A8A", + "887768757528A0602511C595206A111ECCAF9CCA7C9286A8C271C87297077F8658CFBC8DB7EC8410245B9A8CA629F10F774079D8C210179CC2C75B0F5F771C5514C4CE62C2E372056991414A250D7AA17616E616E8E9AD6A037F00430BA5F744371023216844C1B7B64C9766A2716F33030866F4613B066DB48C52C07256674309CC963D0833B5F8261DE58526D380040781963B4B0BF082A99B57958BC8AED4119243D68CC34677D4F1A2B6E89B47ABA4BEB5BC18C93C9F44AB86C4B135B5C221433C1B4A5A03D8397F051BF806181D552F3349105CE68A07924920286F6A858225755B181C282063113D38CC85F1ABE52CB75E6762ACE33F9CF1BFB8351E675B6BA2D3423CF49E4ED6BBF781858646624BBA564C48462FC2853EE854652B282DB5236BD26F7E7B0D89737668313711A3BD258268FC7BAF7D3C530AF028954AC4B0636C5B4B141E990C2F8680FAA4A1D9DBAB24107D9BDA94D264A9E41CC80BAB49307A8FC5A08185B48C34A6ACDCA155FC80C728D40CE4784B63907895F76E56879C23E9506EA56342F7BB2AD978D9707BC1E21A9D8030C4EA0E507AB5120CBF5C951E78CB94FF7B1919A930906174E18C03CD810DAFC9869B5CCAAD43B92C723AEA415939283474A68D90574E169BB6F04343927436C3F99B510A808D960B210BC69088060B02644C64C6C25439644A1BF3A46FA1F81EFD63B4D5E1B783642F5C2187D5F34D80A46F14A8794E4C55B823BCDD092C5677CCA7D6AC6567325661CE918919FA903D1993298A632ECECB8BF1C8B679F968D0F027A28703FA8C6D3AE8A5DEC39A0E77AE97C91DCC722AED623DADB517F8EBAEC7B1313C6474F776787BF65BC2251695C76A3F363AB4F9C4A24376940A68A1C68663C73A5EF066BB4BA4F72B2AD1760D634636FF9C79EF37A8F6DC4E14E50FC7E5CF86B267BDB5CC318C7182A1591FD00B2A50390D9290C216C08AF57F7A2B48F22A4B55794832AC75A0A4CC807081D5F04F64778EDA71259C36CA81B6AA563695974592E256922A46854F0C98399C9570D3806321C56F6A9DCDB1A559F9A84B8B3A60595D827C4AA7F3B85E0851E844BD40B7B6BC16A5BE507D2B283EADC77BFCAB3C1868C438E66442F2758E1B7B6A657E0174BFAE88CDFF315721D9C25E4B4C324B4923FC10BC49926C7B1E98BB7132C0BB2E447957C2686F76AA83202B8C667EE4796BB3670CBD828C48C40E5E23C38345145DB203B6C87AF94A2D78835E392A6379579327F22BAA24617F454D374903C8DB9B9DF1C8B5787F224CB9EE87C62ABC0C9373CB1B6000CEDA4E237958B5EB9C6CF4C65C6412F145AAFF6A2A62C6C39CAB643DC2C702A05ABBECC073E92A435A37B6E10885F80AC68974742009A2499AA98830FDF57B94A36C1827BAE3002327B273DEA8969A09010A40111F74408BB690B5F47346254B02B9A486E246BA698D3E46011D472180D503B60B637CA2011247BCE460829AD14D8AA96AAA78AB7ACA01E1CA838E392A8F149A5E7ACEEE21BE9F74725982BAB490CB416161BCE64FA9AB55C2676B2E3091EF7ACDEEE12EBC820AC2B84D1CB2488F1530C61B8BB1471BD98CB5EB178E00636BA01080F573504E5AB315403AE7412B3586C255D85BF21A0AE058755740CCBAF86B44C48F4F7043CC32AF4B812A99473D008CB85C383BB1965523E2AB9902B6DD006055557242EA88B24889BC4805C0F2AE0B8BB0B81776F631CA518C4E5118171D54ABE2586DDB514B1479A5EA69C99A4C7030B51B14C84B3EE06A142B4DA209AE47E6BCC4899444A2BDFA5B2E1616A333A458266666A0513A08CC9E8A1123C83B874843A441FA1B98F414C93037CC971466728C44CC9EDB242D71D044DC928004DB6EE2AB6A3A658190498CAEDC2A6B5CB67513866C89862BF4A61573361143B4C350705DCA77F729A7D3833C698199C8F78DC3EC37DFDA1CA374507136649D21B207C53F88F71BC49B90D72AB9D44B96F66C1D13973CE7C42EC654292CD0407E695E28245DA2B18A09A7243FA596DF3B0E49038AE88CBE9821155DA5CE41949B5EA8AE5FD597C3241B0DD3798CF8CF5619561736B7F03150CA64153D26785BB2475B4905C486889CB49167C657410B42303C57872AC4324BA10125B3D202680DBC9517624802E58AC40107A8F8EEDD5C0790DB4E7EA8A940E7EF6687556373C00710DCA5A5412C423E1A06", + "8882A2D4927ACF7C41910880FE141FF43C2211D46370967B13186C27296D75BABDEC747926190B8C65CB16EB3E2DDACCA573B42944BF3442390044420F727BC66C507690105FFB3C94477A3D256CEBE311E12838A0B054D398C6DC36AFC8B1CE33A3163082A9DD7B21A0584FC42C4182217DAF7C02C2B8B58E8BA38CE46F16D28F6B299D906B8723B39AD8E22B6475A3C7A7B8CD292125399DEE44A1A03BBEBF508C03B3AD19DB8D963CC88175277408AF5A8642447B76BB3341110C1FEAE6173E2730C6E982D6EB4DC9CC03655027492135062B85EA4BC898A7495A7028B8250B5480B896953588716F07EB1BF4001FBAD1B6910754A1E2CAE6A1716BEAA253D5615BC18FD148706F96106078613F67ACBCABB92417A272B60F408530E53A708726A4AD32C0BABBA9FAB72879045074013FB7E26086D735792C611EC9129CC84404B551E9714AFEBB4B25A8C6A255B0DAC0C505DB3E976096371B40A93897D7F9568844BA5A177F6CC763C744319E84462B8A9D6BD7BFB28922595A35F1965011860E9865AEB3CC350BB461CE057B7EB3870E53108E2C1CAD8B151DD148FF2B1F6973367C48CC0A386BF17633308A47874001F0125E50898F0D0017335AA2164A98AF2C0635E241E6899E138B6760EC76B98627CFF2A3A7422B714907F0FA55FA5B8C3D0416C705181DA1AB04020CEC794EFBD531D199506FA24376970DFE8CCFA0A3ADCCAC4490705238C02833101C60990CA9F41EFBA71DE3521BBA2B39CC148C5CA40DC257621A87A53CF43121E7B6AD210DA72BC19DE4BB0DB5B8ED308B5D475B1D10C0FC9B11B6F52DFAD9B948F2542DA2C8FC8678F9518C2A51CB035779E932197C7656E14AB8C142CDCF74C233C535E7F85E80738B738622E2080AD05004C9F4AA1A48B7DDDABCE0B7102796A557B22300F6B5C3E57C91203DB1988C7C228CFFAAA00D2B77D13C304E31808C2422D8634AB45739368721D255812387BAD50B3AD2466D033565F7E533D6C129E29634ABD65E27C7A58DF00612D1937E222E16322FE65B94E8566E4CDABAD2C41EB42B6F10213AC729C45A65258FE22A814C2F53524036E4B727D46403D470CF33AA97F84917712E0AA855EA2C09CE98238B48089376A065341E93B31C4600A51E6653F00004A455658862A20B0879DB00250BB63131376F8807472C2A3994E498A5573EF105A7F49BBA1449C3A7F196A6A196B5C56C033699D0A934593C72C5A68AD1BA363E7896ECC78B5E27817892CD9E0C34C799BDC23360EBE044EAD39A72503FADEB2F9BA4C87C3904B6C90BAD300637F4BD3CF147D6B14C09588665850059FC639AA269AD4C6D19C72D669821AF8727DB73A132E522A609143D8B2ED0F760D8224826BCB259B309385A9309A4323CB70D2112A1FCEC000B4A270A95A7702CB595502711B8C5747A830343C59F891DEE825E63AB08BE6B6F8095AC4CB21CBF113B64E2CB48F7898AB2B8CE206A2F9947F41B1AA1D367C804C0E19C7989FC88AC27835E67920FE39694D14DB1414EF6305FCA68616046A8BBC1BE641A438F2980454129DC789AB6D1631AE78EB65B7A233C663FA19E34622D48C8ADE56A3846D18F3FFA6CB7821B1132366682AD8DD52B7F77836867AC0A58BBE714233EAB079B27297098A5787942DA34B66544B59E637ED7E713F20C7EC6F807022706C6D476D0720E55D49E9F51AE21126DC97A81AFC507C81614291815AE17B228AB3A2DE959222730FACC2C6DCA3647F392007106A046398058A79736BDD66A990ED1CA7491555C62C9C97B386ECC44A5D6639EDA0952772CEB6147CEB6471CC170F3B505F3E8CA5CF91FD7F4CDB9383F5EB8A9ECB51AAA424B34FB023A01B300D99BFE93C6C0143123E01EF088AD360627EFE1272CB999122C123BDB7C99602CE8F2A1E2748A94ECAB7B9A7168ACB331FCAE20678555FB3C716B35528921EE210D6B586EA1BA1936F661F566CDBE031A36490A9E04C63B1674544AC3EA686EF7E575A6047ABDA71937083607BB6E8F028B4B5150A0B5130BB66D4E4B8DABF6140C7B3CBABB804502C896B22149D49D758A074A8A31C886A38ED1A002A517BAD9BA73C1189C546E3F17011958A3FED7A9156037EE3C79DE68799C2062522127A105B7BB81895314302B136F3567AC115313887768757528A0602511C595206A111ECCAF9CCA7C9286A8C271C87297077F8658CFBC8DB7EC8410245B9A8CA629F10F774079D8C210179CC2C75B0F5F771C5514C4CE62C2E372056991414A250D7AA17616E616E8E9AD6A037F00430BA5F744371023216844C1B7B64C9766A2716F33030866F4613B066DB48C52C07256674309CC963D0833B5F8261DE58526D380040781963B4B0BF082A99B57958BC8AED4119243D68CC34677D4F1A2B6E89B47ABA4BEB5BC18C93C9F44AB86C4B135B5C221433C1B4A5A03D8397F051BF806181D552F3349105CE68A07924920286F6A858225755B181C282063113D38CC85F1ABE52CB75E6762ACE33F9CF1BFB8351E675B6BA2D3423CF49E4ED6BBF781858646624BBA564C48462FC2853EE854652B282DB5236BD26F7E7B0D89737668313711A3BD258268FC7BAF7D3C530AF028954AC4B0636C5B4B141E990C2F8680FAA4A1D9DBAB24107D9BDA94D264A9E41CC80BAB49307A8FC5A08185B48C34A6ACDCA155FC80C728D40CE4784B63907895F76E56879C23E9506EA56342F7BB2AD978D9707BC1E21A9D8030C4EA0E507AB5120CBF5C951E78CB94FF7B1919A930906174E18C03CD810DAFC9869B5CCAAD43B92C723AEA415939283474A68D90574E169BB6F04343927436C3F99B510A808D960B210BC69088060B02644C64C6C25439644A1BF3A46FA1F81EFD63B4D5E1B783642F5C2187D5F34D80A46F14A8794E4C55B823BCDD092C5677CCA7D6AC6567325661CE918919FA903D1993298A632ECECB8BF1C8B679F968D0F027A28703FA8C6D3AE8A5DEC39A0E77AE97C91DCC722AED623DADB517F8EBAEC7B1313C6474F776787BF65BC2251695C76A3F363AB4F9C4A24376940A68A1C68663C73A5EF066BB4BA4F72B2AD1760D634636FF9C79EF37A8F6DC4E14E50FC7E5CF86B267BDB5CC318C7182A1591FD00B2A50390D9290C216C08AF57F7A2B48F22A4B55794832AC75A0A4CC807081D5F04F64778EDA71259C36CA81B6AA563695974592E256922A46854F0C98399C9570D3806321C56F6A9DCDB1A559F9A84B8B3A60595D827C4AA7F3B85E0851E844BD40B7B6BC16A5BE507D2B283EADC77BFCAB3C1868C438E66442F2758E1B7B6A657E0174BFAE88CDFF315721D9C25E4B4C324B4923FC10BC49926C7B1E98BB7132C0BB2E447957C2686F76AA83202B8C667EE4796BB3670CBD828C48C40E5E23C38345145DB203B6C87AF94A2D78835E392A6379579327F22BAA24617F454D374903C8DB9B9DF1C8B5787F224CB9EE87C62ABC0C9373CB1B6000CEDA4E237958B5EB9C6CF4C65C6412F145AAFF6A2A62C6C39CAB643DC2C702A05ABBECC073E92A435A37B6E10885F80AC68974742009A2499AA98830FDF57B94A36C1827BAE3002327B273DEA8969A09010A40111F74408BB690B5F47346254B02B9A486E246BA698D3E46011D472180D503B60B637CA2011247BCE460829AD14D8AA96AAA78AB7ACA01E1CA838E392A8F149A5E7ACEEE21BE9F74725982BAB490CB416161BCE64FA9AB55C2676B2E3091EF7ACDEEE12EBC820AC2B84D1CB2488F1530C61B8BB1471BD98CB5EB178E00636BA01080F573504E5AB315403AE7412B3586C255D85BF21A0AE058755740CCBAF86B44C48F4F7043CC32AF4B812A99473D008CB85C383BB1965523E2AB9902B6DD006055557242EA88B24889BC4805C0F2AE0B8BB0B81776F631CA518C4E5118171D54ABE2586DDB514B1479A5EA69C99A4C7030B51B14C84B3EE06A142B4DA209AE47E6BCC4899444A2BDFA5B2E1616A333A458266666A0513A08CC9E8A1123C83B874843A441FA1B98F414C93037CC971466728C44CC9EDB242D71D044DC928004DB6EE2AB6A3A658190498CAEDC2A6B5CB67513866C89862BF4A61573361143B4C350705DCA77F729A7D3833C698199C8F78DC3EC37DFDA1CA374507136649D21B207C53F88F71BC49B90D72AB9D44B96F66C1D13973CE7C42EC654292CD0407E695E28245DA2B18A09A7243FA596DF3B0E49038AE88CBE9821155DA5CE41949B5EA8AE5FD597C3241B0DD3798CF8CF5619561736B7F03150CA64153D26785BB2475B4905C486889CB49167C657410B42303C57872AC4324BA10125B3D202680DBC9517624802E58AC40107A8F8EEDD5C0790DB4E7EA8A940E7EF6687556373C00710DCA5A5412C423E1A0634D72386DEA33E648A108B6CD50AE30855F2797B4ECF6F0FF0FC9C6BFACD97A1A10ADABA73D62FD5234D8F33A0371EA2697D66A3D5BDD789B6FB4AF056600A8A" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "11DC979904555A3E4B9BB27A9A7C7033D00B2BC3259281F91D679D5725C10C355D70EA10939FC39F99181D05B1F6126CCF93BADCABCA69FBED2B38C7F5F35768", + "0A09C57C0C8A66393974C542D4C3B7D1FB2440EB307A312ACDB2CD08C49C01F240E44986FAC2C5F64988FB76932A8C99D6859856F0682BBA26BE3B4617221BF44459BA3BBAE6527AAC511F2CECAF29A146BD69A6CC543934D1CC2F6BA88F5A6F858AB5F44A4BF8F1384A39393B9B81CF509747D35D68AA6AFC272942109ACEF84BD85300DF841553768239422A3EAC39C1C0093B113C0B9029319B06962A3AA4A1428D534E7AC450CDE444069A132BFA733E267A84E17A88B064A5A26A9C904AD66A3C5BFC0405EC1DBB6A482CD0BCCC0449E7C24A9FC1010A5B59D6682BC98CC86F634A59545A9D083546716801F61108E3CEF6FB1038F66DCF71B6F5959A4DACC0DCA7105B175712AA4AC64C071FEB53BF2A819E644659E0C4EFB33197129245F20C1D3451DA842AA0BC7F8359764A843896B1916DA53BD5FA518D5823CE27C1109CC412270BB28C1819D53EFCB30541386D5BB15B7A0355F421858E627EEED2627A0798B4BA2FAC08455BA938E9E498ACAC3EE7E44DD9C28914EBA7F0111CDFD2331DB348F7AAAF92D64EF617A52C697DD0C582033340BF5AAE94BC7CDFC369C550319FA3CEA4D29DCD48BA5EC5CCFC0A76CA14B1B54B878063BA914937EF09A702DA8111187BBE657BD0939043B0977AB6264917BC53E534E70C449F1A642DB1A35AA00273107FB620CB84E96CA48924A466BDD608A88A855F7C65AE1CB22413C551996655E80C2383619D964B2B94885EACD77AB43022D962C18E953AD158BEB333395128A5D9D3BEA0E71225791722A9AD2D8943CB43B443B675CB53CBD8173FCFA0996859CC0097818F6B5D25705659FBADBCD1096F04A775D92EF2E28D83612AD9A3785F7C0EF835BF1BC38F80F48C05F2750EC61883D85F5522AA5F9C227345A3E89404E4480460693C55EB04F79B8580D6AA4D4A177097C3BCDB041325A47CCC53EFF54145897C7371A58D69704CF44E329856C597709C322676D981AE078948CA65D813619D8AA7C3038F1DF965A845506437CA35930DFBAC30095A79A985BBCF48101FC890DD0082D1C72BF401704FA66CEF3ACEC7911FCF1C47EF2161FB381C72B9AA4FA1CC4941B3C34A725B1523922C346D820B5942525364752935A350C8ACD8B2793D93834BA55E0C9301902417CA4780359BA663F0B176BB6C12548F53C66C40814070837A85F1985E1610C075732FE355A59714401C610A76B7DCD96F2E558BA7E5066DAB760D634E9D41784357A14E2CAAA0409E0A76C59B177911A831048C563E58AC2BB24D261C86222588B30C511E3B9387601BA938AC874311F04394BD59564DC652FF6A5D0919337F23C872F964F7E80EE28A02EDC98ED19ABADFACC1E1435430CA4A7BF374A22903744691FD6A08CBB148B086B04FC95A700B83F897B5C7C1BCD6CC470A996A445125DAACB4D6AC6B926754EC0A3BECC4016A116D75949853609ACA1B1CF9F81A37556202E8A26F480F0CE595BFE15F4899A1A0D578CD4317C757A9047C4FEAD85AA5534AFB00859A4775642955505434B4A94845C217B99CC9AD8983B98789FAA8B58D546BEDE1955F86C66737A4C863A48DB5B0CB1B240BE7C6AA22BF4257720E950E37B174C826A006E40258C74F27003BD07310779959AABB29C793014D476774BB026DAC9D49261132321AA5538C5199B4AF53B4C6A8A70D647A5F99ADF2D0093836C798FA6D71903A7ED0CE1BC33138581853976DDBC0188EC8A280DB154D91705931446C32585E5C16A9780071301D4347AC9AC5C59D396D69205D4E99118D417D2A2C36FF7C4C61285800016460E9934DA87BEEB13CD7E591A873633A315C9068BF17D00E150CAFD2E15D9591622D56C22EC93F8AC14387766A69DA487103BBF50781A641A50E68BAB7C24F6311316FE3AA6877AABFB0A5303490534777B0269113E73990E9CAAD4881FB7A9BB34634CB195EF7D35831BC105193784FD514C6101DC863B3B6657251A26DC2C0502E4450F21BAB451588C1390F12C8CE2836C484773B8C361C345C1810CB22DE990301176D05292521C1117FC90A66802A4572B369EC98822850CA730E4B94507CC4938952560D8BB55576110C09A1D0E0C0F2E071198462F6A26A48A288B83915328CA218E636C960BE186CBA71846BA859BA6C48BEFF532A236750CB3E9709246BC5D4784811B945CE6C0A0E26F9975F77E0849532CCFEE7B190D8", + "8281152CA8B6A0F9640F1A801247854DE90FCE26A0C7715FA330C4387943651C7F1DD48E05DC07E0633603DA88FABC2262967F283C39ECA25BDC652296D852EC351E85C6B5AE18C8C1CC44E7862A50F96B924B05749638E3C5335DE235D6441E42FC771BC5300DA7BF54D50173232FD9366CA7E36E84F41240B1571C7A28B9B05DFE0571DBFA9A7E712548318A3B0B8EE2E37069FA955314962FA76260037FEE90CB975248A64C81970AA22D1C1C4510481D75CD647243E05C46EE6992A292766D70997786CFCFA74B1C558E424C7B3D70A6BEB5AD56A99664986E4905A5F982A8C3D18089A2B8C9F434932774FC1169A7E39214026629936BE7D3C3D6595F0C4C09333B5AB9EA6B4F8808B6A7333BA0922AF762DCB774194C67EAB6B6817AA8C48A655B5ACD9AD7A9FD67BF44FBB22AF15B03D8A8BB89B7D80900373C0EED54570607086E02818B8AA752B87EBD4840F1F142AFFB7110CC67AE41043F1B45AA4951F9A2760DF5222EDC1C3EDB4BB041ABCA2516BD80510A0390A761378535700D3A72BDB1A60BC66D12C41823B505583774A0EA33BE283CBB4CA5334528591639C0A1066EE05089F29CC205479F627384E066E7B0A41669506A9256C9DA2FA6651C7E499CB59C8AFB22AB928ABE02BAC48E039997736A1B669305B7C56F13AF597135E1C557B64C8F0B08B3E494B79CAAA2D212A330B87A28213F0BEA05F65129929B772870154BE02000AD4819586E5A8B0F80E16ECEC83B841A7E2CD759B72B9D2CC48D4A23798BEC7CDDA3AC3F1CCFB545C4DC919C139A8EA867CAB58C71E7ACCBAF28A802E86B8E49BC26ABACF1740754A75CADB826F8814C6AB2BB24E71D71C5944CF16090641F98208764AB9FFAFC8BE9AC34709A3472AC2A94E95132784C33F404B37C4E89DCBEA795AB52E9CB30241DB8CB28B4C35F2AE67E94311D1FA7C2900584198334667CAF54F85CE547B796EC2A805B67FFACCEC5380911AB7ECA812275401CDD8367D869402DEC88FA373BCEB937430918D8CB59BD0A776B3C107CC5AE9E9B143301132D856402755FA0A99B52B9238D91266C628BA7062D84017908C4728A6734F476B3FF364BB86A8517D6BD3095945F686E273B045CA70A77C18FAEA12E7EB6568E307C324666FD9549D9B853FE7875ADA77FEB59857C1ACB2C3B3DAED52C8B259881F96B6144B652B6C19BDC5CBD11846E5A875C2157CD65BE8390C5AA730D2F1A99D09BA3CCDC942FAB5EB4592D8F6A66466284191B4E5D1121A9F99DF806C8C60B440810923473AD3EFAA00FAC2BD07380F5795C56FB315C20BBD70C1F9D4B442A40CACAC2816AB097E74410B2484DFFFA6C2E2673020BC30832A0A93A23BBB27EE86BCE81DC14ECF59BCCE91C6E2602D63619BF582222C3A37D96B6EEE33BCE5876F0C859427154B9E7586DC470E1104254950ED6377D137920C6362B21681CC3274084FC18553B5838228EC285C8C8A4C0E2177A7981ABF951C771E64241B5325625A1614C26D5564040867078DA031113A7FAC01BE92BC244FB241C5B44EAD147AF606F5A152D8F461F04D829A9A2C78BC654FE0CC08594459EB4404A24BBA253334567AD2A115C60D64754C5519F52831030C17CA2A9FCE4BACDB95AD9014FB451526B2C3941F72B88C738C61C064E24000066C5827B08B6CCA6AD958C00ED06D73274D26C66A1B667B722C9FE75CEFDEC9ED03B77F4E67594FC9AF024BD5905245669B7E9066CC8A1A1B7A51337C0BC1B7A9E33E0BB16337E73F5484038059D167B9B6138ECF9BDF83A8A692A6B58A470E5706AFF93CD361CCCAF504AFF53579A55244E14C7FC2C0841E1168DB43F2911AA43A68D32231A6B22A74A5A825AB369CBA5C77A926764A08B6EE8BFE90012754761B60B5103889246CB4C9B87A0CF2B902EF381092CB24F97B6C1BC0D3B859BD93B91B7220F658189D877A8214459D0B8771699C374ACC7101CA791DA2502B094A546B8CCE65C54E03B6B436DDED94F57313A1C45BF520A24B7B98861EC06906414D89C4459C5C8CCD7B00424C6B1676BAFC90CFBD63B55E4C0659B880427432535BDB2D153B374B1A1D27F89CA00DA874BB9F879BF9060E1488DA4DB9DECF035EF919327E4B463733EB3518C7A073BF378A6C5CA07F7C402A0A24F04D963C5BA420A09C57C0C8A66393974C542D4C3B7D1FB2440EB307A312ACDB2CD08C49C01F240E44986FAC2C5F64988FB76932A8C99D6859856F0682BBA26BE3B4617221BF44459BA3BBAE6527AAC511F2CECAF29A146BD69A6CC543934D1CC2F6BA88F5A6F858AB5F44A4BF8F1384A39393B9B81CF509747D35D68AA6AFC272942109ACEF84BD85300DF841553768239422A3EAC39C1C0093B113C0B9029319B06962A3AA4A1428D534E7AC450CDE444069A132BFA733E267A84E17A88B064A5A26A9C904AD66A3C5BFC0405EC1DBB6A482CD0BCCC0449E7C24A9FC1010A5B59D6682BC98CC86F634A59545A9D083546716801F61108E3CEF6FB1038F66DCF71B6F5959A4DACC0DCA7105B175712AA4AC64C071FEB53BF2A819E644659E0C4EFB33197129245F20C1D3451DA842AA0BC7F8359764A843896B1916DA53BD5FA518D5823CE27C1109CC412270BB28C1819D53EFCB30541386D5BB15B7A0355F421858E627EEED2627A0798B4BA2FAC08455BA938E9E498ACAC3EE7E44DD9C28914EBA7F0111CDFD2331DB348F7AAAF92D64EF617A52C697DD0C582033340BF5AAE94BC7CDFC369C550319FA3CEA4D29DCD48BA5EC5CCFC0A76CA14B1B54B878063BA914937EF09A702DA8111187BBE657BD0939043B0977AB6264917BC53E534E70C449F1A642DB1A35AA00273107FB620CB84E96CA48924A466BDD608A88A855F7C65AE1CB22413C551996655E80C2383619D964B2B94885EACD77AB43022D962C18E953AD158BEB333395128A5D9D3BEA0E71225791722A9AD2D8943CB43B443B675CB53CBD8173FCFA0996859CC0097818F6B5D25705659FBADBCD1096F04A775D92EF2E28D83612AD9A3785F7C0EF835BF1BC38F80F48C05F2750EC61883D85F5522AA5F9C227345A3E89404E4480460693C55EB04F79B8580D6AA4D4A177097C3BCDB041325A47CCC53EFF54145897C7371A58D69704CF44E329856C597709C322676D981AE078948CA65D813619D8AA7C3038F1DF965A845506437CA35930DFBAC30095A79A985BBCF48101FC890DD0082D1C72BF401704FA66CEF3ACEC7911FCF1C47EF2161FB381C72B9AA4FA1CC4941B3C34A725B1523922C346D820B5942525364752935A350C8ACD8B2793D93834BA55E0C9301902417CA4780359BA663F0B176BB6C12548F53C66C40814070837A85F1985E1610C075732FE355A59714401C610A76B7DCD96F2E558BA7E5066DAB760D634E9D41784357A14E2CAAA0409E0A76C59B177911A831048C563E58AC2BB24D261C86222588B30C511E3B9387601BA938AC874311F04394BD59564DC652FF6A5D0919337F23C872F964F7E80EE28A02EDC98ED19ABADFACC1E1435430CA4A7BF374A22903744691FD6A08CBB148B086B04FC95A700B83F897B5C7C1BCD6CC470A996A445125DAACB4D6AC6B926754EC0A3BECC4016A116D75949853609ACA1B1CF9F81A37556202E8A26F480F0CE595BFE15F4899A1A0D578CD4317C757A9047C4FEAD85AA5534AFB00859A4775642955505434B4A94845C217B99CC9AD8983B98789FAA8B58D546BEDE1955F86C66737A4C863A48DB5B0CB1B240BE7C6AA22BF4257720E950E37B174C826A006E40258C74F27003BD07310779959AABB29C793014D476774BB026DAC9D49261132321AA5538C5199B4AF53B4C6A8A70D647A5F99ADF2D0093836C798FA6D71903A7ED0CE1BC33138581853976DDBC0188EC8A280DB154D91705931446C32585E5C16A9780071301D4347AC9AC5C59D396D69205D4E99118D417D2A2C36FF7C4C61285800016460E9934DA87BEEB13CD7E591A873633A315C9068BF17D00E150CAFD2E15D9591622D56C22EC93F8AC14387766A69DA487103BBF50781A641A50E68BAB7C24F6311316FE3AA6877AABFB0A5303490534777B0269113E73990E9CAAD4881FB7A9BB34634CB195EF7D35831BC105193784FD514C6101DC863B3B6657251A26DC2C0502E4450F21BAB451588C1390F12C8CE2836C484773B8C361C345C1810CB22DE990301176D05292521C1117FC90A66802A4572B369EC98822850CA730E4B94507CC4938952560D8BB55576110C09A1D0E0C0F2E071198462F6A26A48A288B83915328CA218E636C960BE186CBA71846BA859BA6C48BEFF532A236750CB3E9709246BC5D4784811B945CE6C0A0E26F9975F77E0849532CCFEE7B190D89148E3DE50578E5EE3C4B351CD84EA999D906EB7CE9E5EDF56095DD3611128E65D70EA10939FC39F99181D05B1F6126CCF93BADCABCA69FBED2B38C7F5F35768" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "A16470ACE83FC78AE8D78D8E8E6E24562F924A7C2AAD99CE1CD2505A2AAB7626A7AC74D64D41FE1A10E48A449986CE3D8562736B19FE15153ABDEEE659D76F72", + "6EBA14D47657033C06BC3560176966CBC01FF415CB6A689D4B0430B4B541A9B70C0908B16E75660BA37DD1880F864227926A7224B43A7867A5ADEB51D7931BF1F8946F51277375C43BD63C4C081851E65ACA74A4F6445EE8158338560BFA3335CE54363BC80B5AF87C6097CFF02C646B9C96693438CF1255163C4114398A239C7DAAFC59E48534DA3C615D2BC26ADB733979551AA6951FE2B1DB20176779097C006F98218BDA686E13514ED438086822AE53C471CE429AF5469D75215E1529314905B064E204C9C177AB034FAC46566A98B1C3D95749108CDADB45976103E557B12EA29034AA6C9BF93E9F037EB2EB3B496C40765B6FF9DC58E1425B6086AE8246A94F844A9AE471F30A52F50444323C020F6A74E0787BAB1AC29C2B7F21D335CA286BDA349CD91258673A35D3AB62A3AA0E9DC083E7C76478BC956BEAB25E959B715C539FC02D8AD091E3F43D907B484ABC628679227B078F62987C19CAC108A98EE566751F6A4AA679B0C0273742D910C2F65DD476831897CBF88B1F1B79207EE3401C42CEFDF097461695CE3B3BA903CABEDC387E19784568BD5F234910B3A864F40D7CBA425A344900E4781DBA9A0838487923B2F751AA878256FFD9186ACB226F49054B4732D301AD143A9CF5561C3ED0A834738B92AB974E89CC17461DFDC4BAF6A11E65145E9294CC55C1249A46711A852E4EF140A9564574B4B8D1483E3203A6CE8545BFD6BE317252FF3CC344EA9E5C936AD861B293A3A7ADD6CD999134A07C1430CCBD24A5389552AB9D393C39062B8EB7AD7B18A65AF13FDE426C06E1C01EF5A0F9264477697C601280469CB437C47A44706460F3C7D9F05CB7160F6BAC8937F32BC19A610C883C602765F1041977FB904648951C267287B8AD655A784F76A8AB1C49A0C92CB6E75D162353896AB2742C17142B4692380DC6B00A679B21044378A13436DC342E3D88ACDDB7450CFA6BF6E38EA4DA66EE321500AD2FC3D85CE319A07DC3AAFB2563507580D287B03E704D7A842648A55775E020F28107F3059CB62AB6658A2F51BA2476B68DFC7C8AD5F7C767A1C8470245CFD8777658830A4A4D4C26C66552ACC5B3BD92E83C736AC5524570355452FC6C2196C0C900C47926DA33BBCC8EA14978C6B4021129B6C5825FE3893BB3F2951CA60E81EA244DE9832AC800BE427B20BBCB84598B24978ECAF951561836EC172740BC881CD0972CBCCBEAC84A0592AD469A5673A5A5919A406C2591E82315779759D3A67C9B7C005AD9678FD58558566B1CF5406CE1630690CF5FB79FBFAC56A9DA94A73B64A32AC9E4805F0C402107E68768B7034D488B10B587E396C86227BBA5882CDB8445845603BA87CAC253751EF7043A1530CAE89A73603299024124C389F92A894D2A2D7F01267BE754F34015325760A6A18C4184639CE11ECA4086B1EA6330C1C65C57A0E284069C82B54B151D001213899A2BD939B7A3E409E0E24C01B097DE470DF8D0A9C89519FE3180FA3A83119943034209103854794BCB4CD565F08C06A2881225967AAC8148DD61171C6159F9AA6B539C41DAE5C38F255FB76093BB6B4BAFC690F3DCB41C623888D534BAA3B91B4B347D7350818C2C4209825EFB3DB269179905A3D26C944530070167A2A94518C6B8A8FAD095271279F438C6C7A4BEAAA42943306D70942F0CC97F9B010D95E29FDE851B5C0C0507785629CCA9B5E994E05691600A9B293529AA33159AA7C57BB38AB1DC8E3B5185415B9534AB544B3450037295CA077AAED2B77977B7CFF1C2AD5B6ED2249D073C611ADC2275F7814053764762AF6B11CA02B034F0266E1AA04B403B2E15597EEF804587381B6DC19C4CAABD6B2A62616906607A0CCC8C9004A443FEECB9E8E218E84B1C25F97B5886C6F2EB112519335354ACC403961B59309118AA27C16B81AAA7165CC3B20A8E502652372A7D39482F7664825AD6ADA8DA60B9780EEC345925B29E356714C05BCB335A0E4F4A5DAB4526344A7905E7CD5E23919F910A81785E532C93A32932F95C6DBFB7C7DA514BD0146040023BC0F652D5487E57266937BA83BF36A34DE43576F62FB251960F2AAE6E8C7F94BCB45B99C2436731764C4201856E4426BEF275A270D0AAA6E98DC429838390CB6EE19A692567CF2C8770E50411D1A765EA671E90BE7CE784978D8402FBE9156B23E5CB488173EDC0B1A2761F7E7EF75AE5C5", + "B5323D19064D5E2492EB09A909A5215724444E1584712C10EE6611477A43DF6B1A6F31929166C250D960CE452B0486816DC629E1029A3FEB625721533C842638B98AFE89CA4EBC45CA73714AEB84FD7B4DACC82DCC76734B3C645E8AAD5A9A714CA934592C80030A77E939748B838B073A530A09C5A654A5C4F4A2DB307F70A96FC3EB915F01034E60B4F7650286FC06E69AB2BCA2AE9BDA699CA27A10381661C22D639A8C18494FA0D40388660DFBDA1CB44486EF338B35313709D3CED0F2BBCE0A28FAA26AFF43C21B38CF5D0947E781B27E12825AA594C1C69DAB34C563FBCA006A623A85A6A2296D0AB9CC36AA0899408919D93118B22EEB59BDFA4524CA13862B61C01AF10E89F29DD15679C86261AEA6920466B1E09012F30368CF761694EBCED58640D4E96A1FC2334B300FEBA1557A3C7B569B1CC3A30FE53633B4F95AD7D0CF78FA15EE06C03C586AE6F93545269FA58A7B42624012326440D860D695BA098845E018190BD1B43344B2D54871AB50C3AF0CBA93160DD13BC3F63C3B0B37131FA5C25AF130C17988DE274C3802001FA2B7323A73C2D01A1D253653C84F9F31C277F5CBA3537DFD2CB9ED430AC0463D7C1AC814FA45C25792F74797CE0463A73CBFEC2534F43224CA00B143EB0789516427DC4084BCA50503852DEC69C4E04E67896AB6149876E6692678991A6523CB5A026566682D0C11A3DC0E142601DC1182F15B0770A064DCB473B85B2D5E77097DC4AEB7328A5FC0A7050B7B51CB4F607567ACA0153EC694CE7219B818518B26AE401982F0E1B526990A7BD1553F4AABC7488026DB5B2E02431ABC6DF4AA7A3FF01CA3C85B30C2462E25832700C45F09563F969FE7E3CADA285C3D7B27080A591CFC142D37C24FB89C16836871B918F6D03427072D46F9604F0425C3220524AA7717C12AE57761A87B980A2CB378AC9026E15C90842868B239857308F775C6D4E90CFEFA96882B617878B54B831278A111C1480A7BD74ECA3B7695323D780236799BB0D367A2F380BF21D0CC9474615DE1737F91968640C5AD2A8101851255D00E1336227392CA0F69B4FD1617ED1B0B59D17CF8E7572AE239BF630658A60FFC54BA42F0C0C3A05F756444017815CFD2BEBFE6860C7CB4023091C577A834A1310F3B069ACCA76B8AB326011900C526B5FC6DF2212D52BCBE03F73133297C4DD26E0C0826CEEA76F376538A3530BB3830329002004981C6812592A3693CD28B1EF630815AC23395864E490E57E876895BB6689A1D3D1BAC49D9381FE71BEE181E478907A694B4DB35586D22A2BD51A90DD3B7F2F29F0D51305499167A217395FC3FD54208FF62C33804B17F5C6DD3655DD4724BAD2C315CBC0121D84E5B28B07F1A2FA9FA9640EA103A8072D2D6613144A72E6B371974A272060C3A19A2F412485CA94623FC1E7B4437EEC496F1D0C8DBF5BAF56AA16139B3D83AAE7FEB4A707B8D3727CEFB999EBFA353DAFC788AB614D7B56F86AB788D1924B5896AFA7431A315B4A0584DC5577CEB62629F665CD4C7283C571F91D58611680A302838D7017095C0A7E81627D631C911FB38760B1C754596D0A9AA9F861C22CA684AC06D1B950ED4B03FC0A37C87F22D20EB00D6245F71595C6BE817B4248DB5D9A4877BA2F7FA1642B45087114CF4A597A68CB006E11869B222F61A8066901BF56B42A157279037A81CD39BD5DAC4BA87632A450043022102299A92779FA2204A28B0538C62183F0A5D969127D84737AC0A6EA40491E7F3693A86CEABF7C586A92EA9265358D2650A1C0530D7B43C688C967AB3B7EBACAEFCBC1AE07112542F7FE13875156724E7BB766A44A6968D1D8ABDC1376BD597CFFFEA7384B9022D470051605EC75C496A146E3C301CA6EC05EC4A2810A04098AC564A3109C463C4D57BA8FE559C4019490F692210DB121DE43929D46B0DD978960AA668D04D8DB5741760859C7B7256987138BC2AB2FAA58EA5025BA515FBE47EE70807BA308D0E2AB777E30DAB31797548CB27D3CD93512CCABCC210D88FF4C90F3C7C38E643314E7280BEE861D640B8C82C5C633A083BBA6BB41856638C2517E3621E321949B4AE32F017171B6D6B7182A01CBB7C06A061F82EFC602CC1D0826AC78B6F052C552AACBF4BBAD171AE3BCBAEB339CDCC4A9A3013206EBA14D47657033C06BC3560176966CBC01FF415CB6A689D4B0430B4B541A9B70C0908B16E75660BA37DD1880F864227926A7224B43A7867A5ADEB51D7931BF1F8946F51277375C43BD63C4C081851E65ACA74A4F6445EE8158338560BFA3335CE54363BC80B5AF87C6097CFF02C646B9C96693438CF1255163C4114398A239C7DAAFC59E48534DA3C615D2BC26ADB733979551AA6951FE2B1DB20176779097C006F98218BDA686E13514ED438086822AE53C471CE429AF5469D75215E1529314905B064E204C9C177AB034FAC46566A98B1C3D95749108CDADB45976103E557B12EA29034AA6C9BF93E9F037EB2EB3B496C40765B6FF9DC58E1425B6086AE8246A94F844A9AE471F30A52F50444323C020F6A74E0787BAB1AC29C2B7F21D335CA286BDA349CD91258673A35D3AB62A3AA0E9DC083E7C76478BC956BEAB25E959B715C539FC02D8AD091E3F43D907B484ABC628679227B078F62987C19CAC108A98EE566751F6A4AA679B0C0273742D910C2F65DD476831897CBF88B1F1B79207EE3401C42CEFDF097461695CE3B3BA903CABEDC387E19784568BD5F234910B3A864F40D7CBA425A344900E4781DBA9A0838487923B2F751AA878256FFD9186ACB226F49054B4732D301AD143A9CF5561C3ED0A834738B92AB974E89CC17461DFDC4BAF6A11E65145E9294CC55C1249A46711A852E4EF140A9564574B4B8D1483E3203A6CE8545BFD6BE317252FF3CC344EA9E5C936AD861B293A3A7ADD6CD999134A07C1430CCBD24A5389552AB9D393C39062B8EB7AD7B18A65AF13FDE426C06E1C01EF5A0F9264477697C601280469CB437C47A44706460F3C7D9F05CB7160F6BAC8937F32BC19A610C883C602765F1041977FB904648951C267287B8AD655A784F76A8AB1C49A0C92CB6E75D162353896AB2742C17142B4692380DC6B00A679B21044378A13436DC342E3D88ACDDB7450CFA6BF6E38EA4DA66EE321500AD2FC3D85CE319A07DC3AAFB2563507580D287B03E704D7A842648A55775E020F28107F3059CB62AB6658A2F51BA2476B68DFC7C8AD5F7C767A1C8470245CFD8777658830A4A4D4C26C66552ACC5B3BD92E83C736AC5524570355452FC6C2196C0C900C47926DA33BBCC8EA14978C6B4021129B6C5825FE3893BB3F2951CA60E81EA244DE9832AC800BE427B20BBCB84598B24978ECAF951561836EC172740BC881CD0972CBCCBEAC84A0592AD469A5673A5A5919A406C2591E82315779759D3A67C9B7C005AD9678FD58558566B1CF5406CE1630690CF5FB79FBFAC56A9DA94A73B64A32AC9E4805F0C402107E68768B7034D488B10B587E396C86227BBA5882CDB8445845603BA87CAC253751EF7043A1530CAE89A73603299024124C389F92A894D2A2D7F01267BE754F34015325760A6A18C4184639CE11ECA4086B1EA6330C1C65C57A0E284069C82B54B151D001213899A2BD939B7A3E409E0E24C01B097DE470DF8D0A9C89519FE3180FA3A83119943034209103854794BCB4CD565F08C06A2881225967AAC8148DD61171C6159F9AA6B539C41DAE5C38F255FB76093BB6B4BAFC690F3DCB41C623888D534BAA3B91B4B347D7350818C2C4209825EFB3DB269179905A3D26C944530070167A2A94518C6B8A8FAD095271279F438C6C7A4BEAAA42943306D70942F0CC97F9B010D95E29FDE851B5C0C0507785629CCA9B5E994E05691600A9B293529AA33159AA7C57BB38AB1DC8E3B5185415B9534AB544B3450037295CA077AAED2B77977B7CFF1C2AD5B6ED2249D073C611ADC2275F7814053764762AF6B11CA02B034F0266E1AA04B403B2E15597EEF804587381B6DC19C4CAABD6B2A62616906607A0CCC8C9004A443FEECB9E8E218E84B1C25F97B5886C6F2EB112519335354ACC403961B59309118AA27C16B81AAA7165CC3B20A8E502652372A7D39482F7664825AD6ADA8DA60B9780EEC345925B29E356714C05BCB335A0E4F4A5DAB4526344A7905E7CD5E23919F910A81785E532C93A32932F95C6DBFB7C7DA514BD0146040023BC0F652D5487E57266937BA83BF36A34DE43576F62FB251960F2AAE6E8C7F94BCB45B99C2436731764C4201856E4426BEF275A270D0AAA6E98DC429838390CB6EE19A692567CF2C8770E50411D1A765EA671E90BE7CE784978D8402FBE9156B23E5CB488173EDC0B1A2761F7E7EF75AE5C50B0512399CB6735EADAB41261B37BD495B6C1D594DEF2A40DD2E3F428AA7BBC5A7AC74D64D41FE1A10E48A449986CE3D8562736B19FE15153ABDEEE659D76F72" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "1E232A9F6E1BEC736BCD8269EBB1F91194B10AF29FAA456A8894D4E333600223E527422A8164BDA28DD896337F05F2A44EFF846DED7F92614EAC032BBE794C02", + "65208CC8928E467AA519071ED539C98FC583FD5132F01B52B8462705B80BEF10A778D7010C32C134457A4709251E97509A293540DB66DBF7C520EC075D3A8F575618A071C62D009187B520BE0B900DC902E9F3036507306ADA228987BD7D5025EB35882D808C78E19FF2973469B08F64670A216AB2ECC62EBC5A65B316809A65A4A4307EC2B54358E5AD26D00C4F77C4B1664C16E94550E9A3CDD4290672BEBCA081C378447B6B6A61E1B88B9BC89D0B33739ABFE8AA1897969A4DC94BD68C7A97C94B3E462D79B61221A0CFD493895D544EFC40BB3D2C7C214141A6B04931DB17FB029350975864337D97834C4EC98A80D69BC1554F37B87C53147D9FA411E7024F90A5544CD74320B932A80AC556946A196B3843B4639265700CD7969F4186EF34BA367267B8BA367D703DE118597399A539AC7A090B3126477FA47BC57358A40653C2C4E918E1F80011440BE24A622982AB852747B37A8259297FE83C9058D499C4826831845F1656587899C63D54C96E4C200D4B7F2D9C4B3C0ABE8FC8B31ABC33044729C1339D87A564A4C92DB54A05E556630D0029FBC88213B7412C7BBAED557C7D0387DCB9467E826800A34D565C76AAB10BA8017BC37C1D92CABA8543B3ABD4A38C0C8CA309A8A7C313981742D82B3BE3608DB3DA5491B22B0270A9A4D3341E7436DE8665D89B3995B454F4DB01043C1B2CC864272417DCA796DEEA932F060C3F406BBDD56009C68E7F94A37BA824C5B60FD622729DB31E0D60CE42D726A14751447B16129C496160A756B775945B1A66F56BAC80C5A67937227C80BD0A21FB9019E3C5CDED95C0D737BF2DF352F0A569D5D9953508BC4A897BB697C6C3726A1991C3C35C785FF156DD0B13060924A5D002CF1C5237E9193D51ACF057B5D8C15572DB81A5206A15416164E61EBBC65A9E863C9D99B921A023B8C0C7C162CAA8334F560909155A930A627F44FA3E702062887582D9826B8EB88F0956A16DBA051A210D7D9BA896856992068E8948C14C90B697824AE9C5B45ADB4604D54B2B931E6AFBB814676D17034CB6C68B854780832C72C361A5B7063DB333B728049C119BCB4E6CA6576773D55873855A37CBA0AE9D36778D5B33B1AC4E3FE490A4BC03754B07CD84C1E0C11D846200E2A6B37A44AECD24699C2B1B8E613EFA33179CF6A84900AA9CB9BAD06CC8A9D620A3B64E4ADC5BA6FB84EFD42F6F88C786E036352B751EA3BFB503A8C4438820966E03F93EFB91A8BCA7A595BCA4C695338F81C3D379A769049FBFEC704D87BFA09236E5EA3DD36A8C22B19F9D1687FB713D800C40BFB0CA0E99493D61490F8B28B17593020895525502CAAB314A98689976AD2A3A2D929A1E82D13B3E69C71CF516D59461C74930E71C17A691CA10119C6DDB3F17607ACD03BB7D1764DA49C1EC915331088C4A7B6C9594B2400C735A5304C5F5515C0CBA84FAA433C93D502CC09F0BB399815BEC79318E18141235552DD8B827D33E06461F554678F4E6CB50598A5014570BB22E11F67B10092107D2000FC793706159C7DC1B1F489DC2100DCD56493B1A80B0A92029194E38D131AE8726A85655F8B5471EF49E821A4CB2A48C8E8A126FCB96FB005BDAD7C68956AE7F8C82D65C98D822765E224065ECC64823A65CB880B8956D38D437D9106A75577224A80775C3741B6B6523085137104C272B397577AC3CF0A60A91426BB6641A720927602F29F2856DF1977A686C33F44B3907501333000DD302C0BBAD98FB91B407533F327606585EC7759C9C3269422070244C6135FBAD58D1703A2A6B112B82EBB1A1DA38207D173AE3450AE3A2BA20E556DB1182BAD09C38256CB8673028C555E869A7215358DD645414E98B9AE9C6911C5D1A52439ACC17147381C7476AA4C8AFAE8BA73557A06CB494C0930CF6C01033712F15385B96652443493668122C2948A970C35127F1A0619C5EBD21CAE145548444BAB340924BF45EE45B4AEEA1897B9899227641CF64228853AA1698C4FC95443C42B53FB96BEC2C8EA9826F9FB6565C56BBB33C8274B06E6805CD027B48D6B24E96C63E43384EAA538246D126101A4E6A9BA60B4A19DF38CAF6962F18A31A8F800856886FCC1A4937B5B003BC7E3E290B4703A3E4708F4BF25CD4F28580D15FA2F65389C884E8402C364A1C1F563CDD57657A916C37EBCC8EEC27164069301FA3E54AA51A87E8EE1E202CA2", + "BF9214EAFC4E2F29285F14B8FC990DFE04821169C001A02D4BB967F5F033286B06E63815BAE0584EB95AF86AB254B004197B684893A46467BA631C0B18714366F32216F585EC3B1CCA22B1D4BB0B92E9B42D5529391C949862BDA867395626499E796B8B643605600F7FBC98CB2C60769A7772FC765E0B4A5C22C6EDA3456F87CC095A7F9000272E8555EB91A7CE74A5E6E28620A48CD6AB66CB446276ACACC5844D3445B7CC937A7D21304F349E8F46BE95B75D0D876C12941C4308305C01BEDBFCABBB5C8849106D2ACC797C36BA5C0065B05033C509CE2F7988E763A5555C5C7BE00F3AB55535F76DE415017A3B022D2C6897548A7BE634B613A5FD373DE416562513AFB2A00B5C507402BC8842A59945211B47C1BA83DBA7F2F950A9F614CA8156047A0178CB3D9EE82F4B374470C62721538313D4370AB8AC50B4AD1CF20E65A55437231AA5E7CBF750B41FAA487E786782937B973B63B526AC32BACCC29C44D0B5A8FCE877723B9E90F559BB1225F7067A4FC8CC49174FC591C044C10B6D82BA8F54A60ACB057C3B8258A30BB5746D8E94502FCC9192C37EA57A77F0F447094AA504C9A005AB9A6A2C361CC163E650826DD801A03558B9C06E7D11ADFA2A8A10158E6795505119BD34D21CB4F064B73BB84D1910C458610ED16AFBC3CA43DB62B3546D0FA782A874C7FC32ABD43A99161712F7703A3253911D4425244B792F603985B3A27619544B16315019B3A39A097C32C9FC094FF5657E2859738F6AB3F3F35EF768614A1017728C1BD57347B2C99689A11B245BC468A79347E50D59F65CAC65377A6A17B5A409D8EA9AA0C828742C03157662323C9ED3B1965A3811953A6131671B81628633E0A27A89A6E3027204829CA089817EBA8388F163284015AAE41C37D9CBA347B33C890592B482EC47B7274A6C8594701149B830658B1AE31B3C9229A981BD44405405A15791529F1FD866A6D7AACF08664FE8865B409BF4433511507145C565BD36894D347593A9C6531416A5CC07445344C95347F0A3C272F385B0432E208C768505A86A9C09E24C74DC04B81FA00BC91591CA100C5C2374453307BF217766A5919523B4D4F13EF953C94C26148F0C500C88962B4CAF5946A587C9A296F674D74C521BF16E2021ADA73B43868C1DBD5708A3570FC5FBA868EC382AC5BCB46A542160990FC66B08730C533C1437E5C8B7EBC23FCB8167FB28ABB990D0755AAC09C527943AF65A9AE85400F596C5A6FA1C756BC71FF4899E67095337C17768A2DD3765A6C4674C8582A8D7AEC0BC422CE99358300491F47D86C54A89B94A371473DC8B73674329A6334B09250CEFC7CE4E289E2691448F65BAA46B0D05E70A83F7009FC9CAE3699ADEA0C591F111537B85E7429C08709298702BCDBA52C462B95E8199ADFBCA4575166C24AA0128A6D38569947AA8F7541098A0C765580509B3C797702CCAE29A1167BDAD5A94105453F0CA991F2A1BEE4204403581F05B9BF38A23D479B8A635AAAFACB642D0AD604A86EDAA238CC61E83B441964CB13D22CCF95AA6A5D8BB38C1C17A38BE336AC01C6193101ABB3903B9D3FBA28B272BC2476518FA9E7AE329CA370581C656A873A10D231C65E1C20589B4D8209F7582824F2305050A9AE69840012C70D6B90CD3231995201203F1AC85F1086A644E94955FC2C60EF5E36CAEE1A6BA904885D13B35882675F1581F29ABA8952F72433C4A552C4EE9ACF2F62A2CD37E3A04043EE8041D1A5ABB7084252329E49B0F1E90132BD35FEB1B5078BB4A14C1032C06A1C745330F31A732A84C04100469350227C915156556FBEA10547275E160B4CA226809C7BDA7CA9E3DB182179B02A7911D4C730905579682BA454A98ABD9106E7F48582D2299F1DAA4A2C82C77D16BE34A3C84BCB391E5C571D7BE286981C567CA74296DB020217C378AF8141460A681B44B8C51BC02319ACCE74A6AF8E56FEA33601C984413A4656E33999AAB14BA821E10E097DE6C917EEAAD28D18C28FB9A4591AF6A22130D377E1E6B07BD0C44C0D8ABA6291C01BA95545230DF161511A899E2FBB069D3C9EB19993694CDC31150CEEBCDA8B61DAD2549862B40FA8614F207034F6821D1773D8ED0B9ECCB9473579731B8A667B66A392ABE6A4A6B0ADBB0DBBB32D3B293EBAB1665208CC8928E467AA519071ED539C98FC583FD5132F01B52B8462705B80BEF10A778D7010C32C134457A4709251E97509A293540DB66DBF7C520EC075D3A8F575618A071C62D009187B520BE0B900DC902E9F3036507306ADA228987BD7D5025EB35882D808C78E19FF2973469B08F64670A216AB2ECC62EBC5A65B316809A65A4A4307EC2B54358E5AD26D00C4F77C4B1664C16E94550E9A3CDD4290672BEBCA081C378447B6B6A61E1B88B9BC89D0B33739ABFE8AA1897969A4DC94BD68C7A97C94B3E462D79B61221A0CFD493895D544EFC40BB3D2C7C214141A6B04931DB17FB029350975864337D97834C4EC98A80D69BC1554F37B87C53147D9FA411E7024F90A5544CD74320B932A80AC556946A196B3843B4639265700CD7969F4186EF34BA367267B8BA367D703DE118597399A539AC7A090B3126477FA47BC57358A40653C2C4E918E1F80011440BE24A622982AB852747B37A8259297FE83C9058D499C4826831845F1656587899C63D54C96E4C200D4B7F2D9C4B3C0ABE8FC8B31ABC33044729C1339D87A564A4C92DB54A05E556630D0029FBC88213B7412C7BBAED557C7D0387DCB9467E826800A34D565C76AAB10BA8017BC37C1D92CABA8543B3ABD4A38C0C8CA309A8A7C313981742D82B3BE3608DB3DA5491B22B0270A9A4D3341E7436DE8665D89B3995B454F4DB01043C1B2CC864272417DCA796DEEA932F060C3F406BBDD56009C68E7F94A37BA824C5B60FD622729DB31E0D60CE42D726A14751447B16129C496160A756B775945B1A66F56BAC80C5A67937227C80BD0A21FB9019E3C5CDED95C0D737BF2DF352F0A569D5D9953508BC4A897BB697C6C3726A1991C3C35C785FF156DD0B13060924A5D002CF1C5237E9193D51ACF057B5D8C15572DB81A5206A15416164E61EBBC65A9E863C9D99B921A023B8C0C7C162CAA8334F560909155A930A627F44FA3E702062887582D9826B8EB88F0956A16DBA051A210D7D9BA896856992068E8948C14C90B697824AE9C5B45ADB4604D54B2B931E6AFBB814676D17034CB6C68B854780832C72C361A5B7063DB333B728049C119BCB4E6CA6576773D55873855A37CBA0AE9D36778D5B33B1AC4E3FE490A4BC03754B07CD84C1E0C11D846200E2A6B37A44AECD24699C2B1B8E613EFA33179CF6A84900AA9CB9BAD06CC8A9D620A3B64E4ADC5BA6FB84EFD42F6F88C786E036352B751EA3BFB503A8C4438820966E03F93EFB91A8BCA7A595BCA4C695338F81C3D379A769049FBFEC704D87BFA09236E5EA3DD36A8C22B19F9D1687FB713D800C40BFB0CA0E99493D61490F8B28B17593020895525502CAAB314A98689976AD2A3A2D929A1E82D13B3E69C71CF516D59461C74930E71C17A691CA10119C6DDB3F17607ACD03BB7D1764DA49C1EC915331088C4A7B6C9594B2400C735A5304C5F5515C0CBA84FAA433C93D502CC09F0BB399815BEC79318E18141235552DD8B827D33E06461F554678F4E6CB50598A5014570BB22E11F67B10092107D2000FC793706159C7DC1B1F489DC2100DCD56493B1A80B0A92029194E38D131AE8726A85655F8B5471EF49E821A4CB2A48C8E8A126FCB96FB005BDAD7C68956AE7F8C82D65C98D822765E224065ECC64823A65CB880B8956D38D437D9106A75577224A80775C3741B6B6523085137104C272B397577AC3CF0A60A91426BB6641A720927602F29F2856DF1977A686C33F44B3907501333000DD302C0BBAD98FB91B407533F327606585EC7759C9C3269422070244C6135FBAD58D1703A2A6B112B82EBB1A1DA38207D173AE3450AE3A2BA20E556DB1182BAD09C38256CB8673028C555E869A7215358DD645414E98B9AE9C6911C5D1A52439ACC17147381C7476AA4C8AFAE8BA73557A06CB494C0930CF6C01033712F15385B96652443493668122C2948A970C35127F1A0619C5EBD21CAE145548444BAB340924BF45EE45B4AEEA1897B9899227641CF64228853AA1698C4FC95443C42B53FB96BEC2C8EA9826F9FB6565C56BBB33C8274B06E6805CD027B48D6B24E96C63E43384EAA538246D126101A4E6A9BA60B4A19DF38CAF6962F18A31A8F800856886FCC1A4937B5B003BC7E3E290B4703A3E4708F4BF25CD4F28580D15FA2F65389C884E8402C364A1C1F563CDD57657A916C37EBCC8EEC27164069301FA3E54AA51A87E8EE1E202CA2A97D647496ACB1EC6BCD4D0C4D4029B1A5FC371DD7C259E78B98556F85CDF380E527422A8164BDA28DD896337F05F2A44EFF846DED7F92614EAC032BBE794C02" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "EBEF97C3C1C0F61E2CDFA21FAAC0F026B498DFB17E46027D48F76128F2777E4B359C39184AFE550C25FCA0CE5A68C90090160962EAE2272408E1C116CC1B1BCC", + "2CE6CB70CB51C3251D8FF857F097BA5AE9015A66C8A2390A113B74D6C7CA465611CAE9A98F1A4ED5ACC2EA56269F8009907C9E95D66BD0D71FD7B004C1E1575224BACA332EB273C517164C4AA92AC1272AD4C70961FB3D90A16CCDE304343A50D469B80EAC04B0C44BE72787C161B229C260B469B43C905E7D2B3F409ABF563A23D9C3013BD20B398298900C9404390AD178711B7923F877C5D2343616F70D87802834A11F260CC6E3727EA4AB26E35CA46D5C533A65624B07A35473A83DAA3C8AE3BAE0F58FB4B6B20639C344D63EA784515A6854CED80A034619814A83D7F7A3BA8476007C6685FB1975D71ACF08C16514694F125C37099F5F5CB81E48833A94A6987B3336D5B7C658A4C09094C2018D661B044A153731A4B2CA9A2433A1AB70AB9DBF917FBAA53BD422CC3A8750E5332A1BECC7B8F2CAED406B47011E559911902085DF98897FB4C4DA807FA6E07F075845F65475C1DCA2B4135C9F97A79E9C3A0C61197BA95280D900386A1AD51424D733C7EDF4B61329B010946C15F32161C5224570033604ABDF385371E10BE1641B035891DDE58773AC9463C143FDE71B5D283090754092790CB0008941B591275C4AFF7A85CECA451BA3CB25A7003EC97B71651F7F273D1DDB6DCF985A362BC6EAA7670F88CE4D47C5296915AC32165EE410F7D645DB586EA64A3258B979FFDA10B2AA12B48C3C023B12B985680998161F18763DD4C4BEC95D4DF59A9DC963648740F1B4BCF021B8F83B83FF284DE982A466044C812A48390234F6E19D41F6BB34246BB20784C0247FB83995F49253479BB321647BEB4177BDA91A2A32758E939635154433A706F52CA88C309A6852CA7B2880859985CEA712AB8113E2A483AB59351BB3C0468139C912836120288C5C808F0C7469E36C964CCDC2348662420C578AB1DBB388C3A343AF62754CD60D7471B040B3137547B363450C3E8C423499C60B17744BBC433C052DF0F0169F3225DFA5BC39B68402B28D713C83C4AAAE2769A423245E54C8853F5A60EE788929786FB6381E4A9A84385BC5931454E671296045AD4ADA959187459F227426EB12A91484B3DC99BDFBA8BA4985295292EE0930E1F09F36D9B6F9DAB63A67BAD9077645AA5FBF3C7882A2248F6526DBF12AE295525A501446DCCA26949F83DAAD54F774E8F171A951A5BEC8BEF228992DE87053BB24CEC3979522845E7C823B40BCF5C47E0D803FB3479F6EE059B4289A9CF19A51FA743704041437442E99236B9557DB121358F753FA344E337A300906559080CE84E7625C64135C5A7812EC20DE6B186070104BF2B96CC7CBC9C5AD2455CD1EA580079915179421A3594688A3BE7C6CB402C26FA60C216C5918547A47D0A45C88C1BECB00CBA8E09D23AC30D916642DC8A86EE63D169388D6F22165EBA3BD753233393FAAFBAE87162367071E95B9C55CA06877852F9FF54597755278171914BC6CDB088BAFB75AF0AB640F75592D5CB6F2A10D362C3568C18EC6DC5B2056A7D9D080FED442FBC6C753A068D3777608025131A08DE3022EA991ADD6E534A26673B7774631F745E58B7ECDE5B2A2520945E63BA612213AB1CD0ED65DADE4B663B7CBD093C47328A9DCDB38E61155B47151081152FA043167F20614BC3F456019F241603D7773F698AF57835EBD4B6B5E81217BB93C826A8B3DA62662E2197CBC5D005421404351E7AC2013CC39AEF76986E61B086A47CD4AAD985108E7E4CADF1AAAD75757A265BAE7DA38D65BCBFA7AAD60D688AD916D92DB4D85B54EF9E92F2BE4B91E720147220C651A8AAB6C1487B87FFF0BB0D14060491A5E19C3484964AEF7F6182D99CA8403A69F41B5561A14A4C18176137BFBD2148C13A0CF327A8FEB7DBE48239E290AEFD1A217593C1EFCCF753113567246EF0BBB717AAE7B3B6B6DA1B8A9523AE466401A1A2A424BA6A6301A1585365EAA32DFE72937259E6E701AD506BB98A26BB4011DECB179E758A9B4C8C29452839315878066814B99C7657093C7C4699B8C58B3434EFCDC1F815263F21998340CA170347EC3F2523DF61D26026774C42A413B0888D35BDB91A8AC36791F9295FB3B8DA4609A9944402DD510F6AA068C7A26C338443FBBBAEBDC00EA423CF836CEEC54396C4B39C7617B3F085D2E21662186B1720ACA3AA2959954A606D7B8C7C306F0F15629E705DCB5FABB9EBA0EE0368AE42CDD9BD13649", + "05B8A5DF18975817131DA0B2C13B196E435F22B11ECD340BC0058A0B4658B8D51506097ED28A940F846254730956A51F572216A876053DE382E3F453B6AC4A3F7A948316C0A9F55A538C594F04404E2804C5C7C9F215C1CF857E95366EB3017F46E191EFD29B2124755957223ECC0851850661020CAD122DFC747A3B79834CD96944D10D464076069C4A8119A94F26251C7A4BD4D7A74890BA618478C860A8B4013CC565047615C273E8A7D8947285B259BBF75BACF11238135F7ED99CE86A46C6609EC7F82031F3B8A800B752E00104155EB4405350911C44C4BC6644458BDBAA1E401125C1AFE681B4D531821CAC54BF41539216BFE653BB99896F8C2A693E3084558435B23A3B9779BB8131C59040202B35468CF8844D617E765746E7A28275FA01E26544AD681CE776B2EFC31CDA1BC5B45207ED02C678C466E2CCA7F3AC3248920FE87754AC78A0193AAB96685BB865AD6E233DD7F62FD6F8021D286141A25B5DA10287456784D55BB1F69A143866D5D61157A53B21EC516E8771DD65C7A8398CD6C348196B1452306DA404985EE636D123BCF18575A87A64D003C1666827F871CD42326EB449A481E2B976C2C38347717966982DC1244E62CDA1EB5624B7A776519AAE2268FF9A034A31886C98124825A8046958681B40700736CD3A8EFEEA6E20B0A551D7321BB6CB36F41631E82559F31E50646E09B11A70907DECA692B045874483B67665AE7EC64A5E42789C92BA14830D36DBC9644785F940A7AA1A2A57376A6594A6CE81AD4D3A40B5528DA03C638530148FF015CE1762665BB64C584886803432817318C26BE12451609CBBA4FC94E3C8CB64C8018B10443DC40BBD098692F38C6D08075656A51A59CAEE0C1C21284251770E00039528F99DEC18684DD59E03899289A39610BA486AB636AAA11B6943B3ACD33341C9650D20A5B99CB6A8123E16A06147BC5E6E293A07C262C5F1153FB65C55047A0D266E570B5954643E334094E58BB3DA548C99B0CA52825B25043B315865EA30CA1100A28B421F8D5B61A76366AF907B951561B91C36FBAC6C519A74E2E38AD62B9EDC9482D170421B7517FDC676128065E3021040396C0CB7509416B98BAB07001397CABC172C6B3B3E839B86806079F1ABE12B9C010CB9778B5467765D5E1576E4517E0B0165250116CE9CBB7A8526A4906E67FA3EDA0799A3DA2A145868FAC45102CA7FB78210DF548A33E846F88C5BE8518440523857EA1E5B8C960697BBE2336389B730C0A0379119B064BAC09AA07FD989254E974769C5380C3331F299C5A61A0107C8CFDF928723D8C50E6928DC867B25F5C29A8529501A615DE892AA694D5C9529562AADE3C51062A19B1B28C7F6582EA429657A3012F5CACED450B0AA8C5968AB042F2823BF1A01D8BA3B4FE22932E9450EB129365A2DB58A2687622ACF877813F517CA06BC0F8C2971AA8987E54344D8810973BCF3B4C0655BAC74642DDC7A051E59C8049C40E79304D83074861543AE080CCB30BBA8068D06B8C2508C799B0653CAD5821C4239E47A00284C7CC68297E9C4813A0650A49B540692B0CFA84AFBC2559C0927F47B6F12DA6C00A878D1351FB678BF7071CB70B8B7471A069631562B5BB98FF32784B61B29A02181B405B590A6FF92812DDB16A5C7521F05245C2289658BAE59B5668E667AD6C18C362BB6DBD94366E31E37525C03526F3D229D5E649645D33BD246CA9AE19DFAC812A9858E5A5C513166A7288B3BEC15B6E4B33D06622AEAF5A436762D74A66895E777D661562A83CDA9E86D03466DEB131276FB48FFE8A490684DE6E82D275B50585B754DD252E2D07F1C18BAD78B55CAE315FFE43DFE53B130826BA1A2A5A68809F776017D4730D32A5EFA80CEFAFB78655861531AAABFC8250633655626432ED5364E635C92D54A12A6A9E71B4722492D60DA981B794C3F968411AB1665E9683B66C36E346D5EB8301AE37B484677AB0C8B8500CD9038513D1786FFC6453039415288A44D625992A21E5DA8CF90C893B7C1BAB65C37CB7891F3E867F9C52EF16197A7F13AF0047B2F7891A5F840B32952C943274D54C37D8860D05B72F6DA031A65B2085AAFD00641FF9582027C0CCEC6B266C72D0FF59E222438F8916E06CB6A04D345F3D008C811A16B02A1B765A524976A2CE6CB70CB51C3251D8FF857F097BA5AE9015A66C8A2390A113B74D6C7CA465611CAE9A98F1A4ED5ACC2EA56269F8009907C9E95D66BD0D71FD7B004C1E1575224BACA332EB273C517164C4AA92AC1272AD4C70961FB3D90A16CCDE304343A50D469B80EAC04B0C44BE72787C161B229C260B469B43C905E7D2B3F409ABF563A23D9C3013BD20B398298900C9404390AD178711B7923F877C5D2343616F70D87802834A11F260CC6E3727EA4AB26E35CA46D5C533A65624B07A35473A83DAA3C8AE3BAE0F58FB4B6B20639C344D63EA784515A6854CED80A034619814A83D7F7A3BA8476007C6685FB1975D71ACF08C16514694F125C37099F5F5CB81E48833A94A6987B3336D5B7C658A4C09094C2018D661B044A153731A4B2CA9A2433A1AB70AB9DBF917FBAA53BD422CC3A8750E5332A1BECC7B8F2CAED406B47011E559911902085DF98897FB4C4DA807FA6E07F075845F65475C1DCA2B4135C9F97A79E9C3A0C61197BA95280D900386A1AD51424D733C7EDF4B61329B010946C15F32161C5224570033604ABDF385371E10BE1641B035891DDE58773AC9463C143FDE71B5D283090754092790CB0008941B591275C4AFF7A85CECA451BA3CB25A7003EC97B71651F7F273D1DDB6DCF985A362BC6EAA7670F88CE4D47C5296915AC32165EE410F7D645DB586EA64A3258B979FFDA10B2AA12B48C3C023B12B985680998161F18763DD4C4BEC95D4DF59A9DC963648740F1B4BCF021B8F83B83FF284DE982A466044C812A48390234F6E19D41F6BB34246BB20784C0247FB83995F49253479BB321647BEB4177BDA91A2A32758E939635154433A706F52CA88C309A6852CA7B2880859985CEA712AB8113E2A483AB59351BB3C0468139C912836120288C5C808F0C7469E36C964CCDC2348662420C578AB1DBB388C3A343AF62754CD60D7471B040B3137547B363450C3E8C423499C60B17744BBC433C052DF0F0169F3225DFA5BC39B68402B28D713C83C4AAAE2769A423245E54C8853F5A60EE788929786FB6381E4A9A84385BC5931454E671296045AD4ADA959187459F227426EB12A91484B3DC99BDFBA8BA4985295292EE0930E1F09F36D9B6F9DAB63A67BAD9077645AA5FBF3C7882A2248F6526DBF12AE295525A501446DCCA26949F83DAAD54F774E8F171A951A5BEC8BEF228992DE87053BB24CEC3979522845E7C823B40BCF5C47E0D803FB3479F6EE059B4289A9CF19A51FA743704041437442E99236B9557DB121358F753FA344E337A300906559080CE84E7625C64135C5A7812EC20DE6B186070104BF2B96CC7CBC9C5AD2455CD1EA580079915179421A3594688A3BE7C6CB402C26FA60C216C5918547A47D0A45C88C1BECB00CBA8E09D23AC30D916642DC8A86EE63D169388D6F22165EBA3BD753233393FAAFBAE87162367071E95B9C55CA06877852F9FF54597755278171914BC6CDB088BAFB75AF0AB640F75592D5CB6F2A10D362C3568C18EC6DC5B2056A7D9D080FED442FBC6C753A068D3777608025131A08DE3022EA991ADD6E534A26673B7774631F745E58B7ECDE5B2A2520945E63BA612213AB1CD0ED65DADE4B663B7CBD093C47328A9DCDB38E61155B47151081152FA043167F20614BC3F456019F241603D7773F698AF57835EBD4B6B5E81217BB93C826A8B3DA62662E2197CBC5D005421404351E7AC2013CC39AEF76986E61B086A47CD4AAD985108E7E4CADF1AAAD75757A265BAE7DA38D65BCBFA7AAD60D688AD916D92DB4D85B54EF9E92F2BE4B91E720147220C651A8AAB6C1487B87FFF0BB0D14060491A5E19C3484964AEF7F6182D99CA8403A69F41B5561A14A4C18176137BFBD2148C13A0CF327A8FEB7DBE48239E290AEFD1A217593C1EFCCF753113567246EF0BBB717AAE7B3B6B6DA1B8A9523AE466401A1A2A424BA6A6301A1585365EAA32DFE72937259E6E701AD506BB98A26BB4011DECB179E758A9B4C8C29452839315878066814B99C7657093C7C4699B8C58B3434EFCDC1F815263F21998340CA170347EC3F2523DF61D26026774C42A413B0888D35BDB91A8AC36791F9295FB3B8DA4609A9944402DD510F6AA068C7A26C338443FBBBAEBDC00EA423CF836CEEC54396C4B39C7617B3F085D2E21662186B1720ACA3AA2959954A606D7B8C7C306F0F15629E705DCB5FABB9EBA0EE0368AE42CDD9BD13649CE740C439CFA78D529DFEFA90F554665BE47E1091CA97159F12A8ED0309AA64F359C39184AFE550C25FCA0CE5A68C90090160962EAE2272408E1C116CC1B1BCC" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "4E98A2022F166D848D6BF1851ECFB9117E7F1B275050FBA71215D35ACD643B2352B1D970496D5AE84B730C310CAF32778BE41719579F222808EC6F8AFEB8F79A", + "FBEA685961B0D3B9BD40F6BDF2185EA447961FA5B262BB997D6562ADF85D985033D7C8984E3AA4FEA8030964139C43C216A8CF7B7A108F55928C8C089A31A191B13DFD958FA2C5B2EAD6BD284C4FAE774914E2BDB1C6101C728EA3870F77C68330CBA82D55556AAC76F2C761341A268145B8FFC10729C551F0CC1E61852546935B78EAA7D5D04637F227B16643C27B0F5D3218CA6A02BAFC4EBEA5A56CF121357C6C2C56C58FE6585B7684CE9A6085F225A7573AF7206FCEA0495B331B4012CDB52A3F2EF75D15FB472077B606F0534A88CA2D809B4CE7955E7A5BD7160592B855F021A589B000BECCBA8F01AA3C1987FB6250C0D78E8494C4CDDBA82AF07464945820C31CEF4AC99F19366205C3299C9BC62CBB70C68732DC1897987EB951AF28997D99F37E5DEA1AAB917ED33A87C4D88517051413619BE66A6A6A07CBE265B6EE8A0184B6C3913C7CB5467FA29AB6A57663397218A304B10A7110CCCC625882AB5DA54212A6707030C7FD62B618E97A90712F1B20AD42850D4697AEEC9828E3473BCA48CCFE4BB5F6C2C1DA6A81E6A9003D00CA5923BD4B550F9F1521C547A5313830AFD45264D04FD23ABC58CABB60C08F74255EF0B1A3E0788CA60A1A9820A4ED45B37A2BC1EBAAAD7BB9C7C7FAA56525662ED4983FA17F253327414956A8070430640E967A32FCCAC43A9242D9846EE7A60CF7C5AA7B128B4B4644B6177B1A2C653116173CE5052C71CB124C4551D2C2763793485686EFA881F82B87C327C45530148A9B9BFA50A047BB0DCFD9A7554909BF3C1545740D7E3A31BD974EFA494ED98AC76D6A84F7981F09347FBF8A617AA52C02291768398A0FBC839858531EC35C80FB9F9E8824D14B07774570C7D05B8F0505BA086E6FD59B0CE1B039E897E8A9AE81F8C854CBAABF1165FCC129FD080F4F8058F82C0B5E1B47B0AB686E570782557C2668C33357B29B9187C9C42C4089613F2CA9C60B94085412EFB4CA543186B4E42C3D03B576DA6C5085057A610067D147C327B5F923B47735CF22F648079A8EB82032AF2C1336AAA60DB06452C808E22324C1B023D3987299F6BD03D94E36C31E4F022F10568C739A248C552C5430971F49CCC0D91D8E5564B5959E90B9274ACC5C94495BF183B03222CDED755A9480258F95CC1D065609E525FA26B0E62BA4491B034FC03291370223B221F0624FB76737DAC258210B79CF70A00A9C2E3DEC1E91ACB5C1042B9FC1B387F784E4C40950913C007CA24D25A21097AA78075ACE1225842C1CFCEBA3A41AA4E92C2119B6C8B8F69058D368C26B7A7C09C426C3A446045285F59C8543BB89A264A6B67A213C8893ECA0D55586C060ADC448CC91D9A1E5A678F4D734F4AAAFACC622E7265BCCE4C090D597DFA0A443D7504015691383575020724A34C5B6D82F39E53DC71362B8DA248EC82C957C37FC3CB4C8A7CB86E6440AE8A3C19B18293A0DC4E83944E0B2C9C819DDB1A10175A8E58920E109A7EDE7B91EBB005DB4424E678A17234F9212BFDBC9B2271C03A6F387E6D1938CEC555D69CC85135710AC4DAC72A29520A55CAA15C129B717C785D178A165D242E6377FC2158F16BC6BCB73B8D41490333156CAC79FFC673CB84C08B18B45A02626E3A7BA82A533597C60702A680641A372431A5521516AF67E5B51A2CDEA5A8CB579F2598FE239AB7FD2CA140518AD8CB76D0B81531673889699F9D36E9A855929A6A153FA49665C3CB6C999C663A20EB642A3A635CF4029C93545AF566A5536080F609B6CA32F54627276E80391BC5EEF132D40B104E65A700E515C5F762063BA5B908890B02024C9521D257520B2DC3AD59A5902C6864C301FF02720A640BA2EA3773D29C2B0F39560F12DBC203AB57A01E58964D359988E9A96F746793C533A89540BD2A3773FE604FC5C8DFCA2BCEE607AAC34AFCC585D0AB490FE591AA7030D4C68B53EC3245661432FC09970A1512C10B13AB54FB3BA1C07C549660C5BFA06229C92AED33288DAF59C5D9442F5A5BC4FB70307E909CB398FAF90898C76362C3AB30BE743B32B7B8B01B54B9681DBFC938237BF35F31EFE778487C12D428A34CFEC66AAF14EE5A6365B5C5CDF1743181A7BC50786A47AA9E8F089D9CC8E3C729086F09C2E5A3B49E048E78333F9FA64D0858C4BDB3331A24349CE762723BDF3A6F77126F79CC16A7A48CF746223C21227A5F7CF53B0E8C30B", + "CCBAB46E731819714C4B064FA237C3A1E7CEC633963C14C6944CC00D9B48FD309C90D47CBB4090B94317D5736A45A208E6D8303BD48C2F6294312A031F94A2294745BD17628DC3CB1067C0CE28A39522B5AA1999DF26BE6FB467F42BA08510503EC949D68432BDB078B1694379B91376132CCCB7180AF3A113C4792F9C6461393C36347F57932A47FCB070A928D0F1A3338B7689543612B324E0563484500CE1D5042560A10558CEFCD62FD48C698502812EE465004CAE0B208085C89F18138FB18C6455A38067679EE8C88737A675750906064407091501F2219FC753A314673579B845C5C974CF697F38C14BB4F58C8A748C5B280FA4430AB61873A5EB4878126B0910AB3191B90BA980FBC32278E04FBAFA3479A12BF02C6C5DE65B0EA44E792BB9E287B80450548863A78CC4A3A8F74BCFAA4EA9E1A5A8008FF8C0BCE8365C57903E1EA167AF86CFFE0692202AC93E2C072F849A1815C9A51319E7A10B8EA999C7BAC131E5AB5A11789FCBC420DC776252136E7645C123A1114918983BC16938C473658F205034905C0595CC4128A7139792C585629A52E209AF988477B504FC5BB386B4BDCDCBC4625ABE7042057BD996A4A92CAD555EC6D96E38028F3313B7CB835A1BD2BC392543D4B514B42333003CC1E1B25F53703A699C6BF2EA9C18315C11E586DAB505E516A6D9A0743E8C1912DB868F5201D8C8CE7F55BF1EF467845CAE79C662D1E0B8A517C0BD518386B35FF9753DD5464995E30FE03984B120B07170838FE6CFFA67AC67CBAF288046FB35C7B044B0B655B32D2914F6E8C09596ABA32534C949B4E455A7DE3660384A35620069B3B32A8106B5CAEB13D3D2CC14113F612B76A8196FAD924B42183A6C6A99199C6A4AE590FABAA62C4650A4E88ECC44775B0016CBD301FC43B2122A486FACB09B01A3F1E8B1EDBCBD26F764677BA88B7BA30F306AF64767DCF91350F461DD0CCCFF03673F4B3807159DC80B493188C1ACB00AC3CBCCB19A9DF5F83BA880331DB598B16260F7A41846BACD91F8065B7A163FA841BDD752ED813DB5B0615D870578823378EB0FD3AAB433B57705435CE4318CB828826DB41874601ED4299CCDB26EAFE09529592FBC5B9E78F2BFF632C4D6259AF72833A21B38DBB4C04A60717C440B126CBA8360B1A089A0EDB387A421A5A32BC9FD56B2E20B4E63456039110B86546E19D2620C44911A594E640059E72CCB655A3D57FB70799578E5646E37A856686284D45CA07321BE1AD94D778937EEFA94C354028300AF613553F3560A1AFCC1F94CC28942578DE667A91779A1FB5E5D8067D4C98AE03080EB8956B4E770D5DB322CF202EBF5646F51A3184B0CB6E3991147AEC5F6972E9A376E651FBF82114EF6817B88CCBB182DE239323DD7712A927A82BC351DD0A5610093019731A5347B0F9A4130AC212E79BFF4D14A2D69A5AE5C1AF03C4A86FB7DF936505838268FD349E6265356A9AA5A42BCD6B1177D1B1FB401705BA6B7B04747479CC448DC391E4C2409565BDFB3C514B87BAB0A9E365497D8D163FCB834C46345129803E0D9B54309CD837AAD17847A06653C0F35A3F332C16217315AC224A45B58AEC78B8B897E77B3228F6124BDF18F21B71DFF69BF14E30B85B20B8EFC4F2130690B281075C90B3BC10DD550648589670BB99DDC38AF96DA9D40F583DDD91C2C356A9FC85F6B116CB5E7639D67460BC943700B821503D05631947AF58A53AA58D5668FF055C3C4455281D84274E17E8E320606126A1AA1074BE002BFA2C1C2B48BE5A537908248B10A7D826229C99C4F4A87A403E794C035AD103BAB2F5564FD1961C4CA587E0724B0B46E0A678FD0397259C89BD6845E935820C0E064938364E659A8BD0B78587B029AC0A32531B039E6C9D8059D2B1ABE592B6ED2CA2800D73E8237BCA76232AB1115DB36A1FC2BA014A694A484C9B41CA295861CA4A573B6859574A1743BCA28DBFA4838B8018153BA4CF01803645D0628C6421A7576E889CA282DDD7C0ADE75A0A135A4EF6B584DD3575899A8020AC798469C7A5BA1AFC361359265DA160B3C13120B3741183C48D31C4986D40147121B63487F1935BE2206C175289F789B0ED590673211551D72CDAC459A79682E0DB849B129C42D0C220D19371FB2647AF168AA7B584B1020FBEA685961B0D3B9BD40F6BDF2185EA447961FA5B262BB997D6562ADF85D985033D7C8984E3AA4FEA8030964139C43C216A8CF7B7A108F55928C8C089A31A191B13DFD958FA2C5B2EAD6BD284C4FAE774914E2BDB1C6101C728EA3870F77C68330CBA82D55556AAC76F2C761341A268145B8FFC10729C551F0CC1E61852546935B78EAA7D5D04637F227B16643C27B0F5D3218CA6A02BAFC4EBEA5A56CF121357C6C2C56C58FE6585B7684CE9A6085F225A7573AF7206FCEA0495B331B4012CDB52A3F2EF75D15FB472077B606F0534A88CA2D809B4CE7955E7A5BD7160592B855F021A589B000BECCBA8F01AA3C1987FB6250C0D78E8494C4CDDBA82AF07464945820C31CEF4AC99F19366205C3299C9BC62CBB70C68732DC1897987EB951AF28997D99F37E5DEA1AAB917ED33A87C4D88517051413619BE66A6A6A07CBE265B6EE8A0184B6C3913C7CB5467FA29AB6A57663397218A304B10A7110CCCC625882AB5DA54212A6707030C7FD62B618E97A90712F1B20AD42850D4697AEEC9828E3473BCA48CCFE4BB5F6C2C1DA6A81E6A9003D00CA5923BD4B550F9F1521C547A5313830AFD45264D04FD23ABC58CABB60C08F74255EF0B1A3E0788CA60A1A9820A4ED45B37A2BC1EBAAAD7BB9C7C7FAA56525662ED4983FA17F253327414956A8070430640E967A32FCCAC43A9242D9846EE7A60CF7C5AA7B128B4B4644B6177B1A2C653116173CE5052C71CB124C4551D2C2763793485686EFA881F82B87C327C45530148A9B9BFA50A047BB0DCFD9A7554909BF3C1545740D7E3A31BD974EFA494ED98AC76D6A84F7981F09347FBF8A617AA52C02291768398A0FBC839858531EC35C80FB9F9E8824D14B07774570C7D05B8F0505BA086E6FD59B0CE1B039E897E8A9AE81F8C854CBAABF1165FCC129FD080F4F8058F82C0B5E1B47B0AB686E570782557C2668C33357B29B9187C9C42C4089613F2CA9C60B94085412EFB4CA543186B4E42C3D03B576DA6C5085057A610067D147C327B5F923B47735CF22F648079A8EB82032AF2C1336AAA60DB06452C808E22324C1B023D3987299F6BD03D94E36C31E4F022F10568C739A248C552C5430971F49CCC0D91D8E5564B5959E90B9274ACC5C94495BF183B03222CDED755A9480258F95CC1D065609E525FA26B0E62BA4491B034FC03291370223B221F0624FB76737DAC258210B79CF70A00A9C2E3DEC1E91ACB5C1042B9FC1B387F784E4C40950913C007CA24D25A21097AA78075ACE1225842C1CFCEBA3A41AA4E92C2119B6C8B8F69058D368C26B7A7C09C426C3A446045285F59C8543BB89A264A6B67A213C8893ECA0D55586C060ADC448CC91D9A1E5A678F4D734F4AAAFACC622E7265BCCE4C090D597DFA0A443D7504015691383575020724A34C5B6D82F39E53DC71362B8DA248EC82C957C37FC3CB4C8A7CB86E6440AE8A3C19B18293A0DC4E83944E0B2C9C819DDB1A10175A8E58920E109A7EDE7B91EBB005DB4424E678A17234F9212BFDBC9B2271C03A6F387E6D1938CEC555D69CC85135710AC4DAC72A29520A55CAA15C129B717C785D178A165D242E6377FC2158F16BC6BCB73B8D41490333156CAC79FFC673CB84C08B18B45A02626E3A7BA82A533597C60702A680641A372431A5521516AF67E5B51A2CDEA5A8CB579F2598FE239AB7FD2CA140518AD8CB76D0B81531673889699F9D36E9A855929A6A153FA49665C3CB6C999C663A20EB642A3A635CF4029C93545AF566A5536080F609B6CA32F54627276E80391BC5EEF132D40B104E65A700E515C5F762063BA5B908890B02024C9521D257520B2DC3AD59A5902C6864C301FF02720A640BA2EA3773D29C2B0F39560F12DBC203AB57A01E58964D359988E9A96F746793C533A89540BD2A3773FE604FC5C8DFCA2BCEE607AAC34AFCC585D0AB490FE591AA7030D4C68B53EC3245661432FC09970A1512C10B13AB54FB3BA1C07C549660C5BFA06229C92AED33288DAF59C5D9442F5A5BC4FB70307E909CB398FAF90898C76362C3AB30BE743B32B7B8B01B54B9681DBFC938237BF35F31EFE778487C12D428A34CFEC66AAF14EE5A6365B5C5CDF1743181A7BC50786A47AA9E8F089D9CC8E3C729086F09C2E5A3B49E048E78333F9FA64D0858C4BDB3331A24349CE762723BDF3A6F77126F79CC16A7A48CF746223C21227A5F7CF53B0E8C30B5AF7B60E6CAC0F3E6CC9BCDB707FABA9C3A9C51F4A0096FB371EA34913E2F0CC52B1D970496D5AE84B730C310CAF32778BE41719579F222808EC6F8AFEB8F79A" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "A29DFBB1BD2A782C99302200EBCD056A463DE1939CD3D1240584B736A34DA8257E3D54DDC2CD09DE682ABA1664799BB5598942E5C1A89AF67BBD7FC609E05654", + "4D16AEF4E20DEA770B07C36F82C77D23E16659F85EABE65603E53CBE3BB622B64FA4FB9902C6681537ACD151BBD0B69EFDF38C911722269550633620B3881FC1B673BFE7C0D958A24045A2E35596FDC319292988E88471152C7D39D58156B388EAC55DCF98BA10D9428135BBFF04C59F096212C17DB2CA27F607B37E41CC679B47EF648602B36076470C28828CFD560FC0D1788FC57860B3449D8A03DAF76581802D1F7769D89954C9A817807A2E496461E9CA2BF0F96E05772CAA3CBAA808AE73E3A105EA69A97CBDA06C35252817F7067F79848E9C3ACC84943070B30CFBF4BA54787B1BDA450BB05CD20571B295331AB1C17C8A99EA178A730716DBC49AD1A17CB5C7A965C30AB4102E1356A2E29A98E729598DB8907914AF86CC91A567A718E94502C82F75867C73A73EEEF99332F47283753FED944ABEF36006FB1B802495F89741C073270775B0DD612BAAD8C9D526CE36F90A2ED035B731A00A17B087B690A90019E1011456D00B04707750902089A11C6F29422FB52144B55E97F98ED765924B87718269BEE41C276E1C4655C18C51AC5C3DCCACF253B22AD75139677255AA1D182C65058562D0E684494A7D2DC6311DBAB6C931C98E1376E91A4221E129C2F12A20C491D8E17392F9951F526CEE94B416112B7C7B0B37F03EC58BB70609BCADD3C8366323BD48C57B491479CAB0CE2979CB8414A8D74E978968EDF53D13BCA653F42D31889FAEDBC5AEDB5B4F9C7C42425128FB1C91C49DD2AC7A64951FF38AC85986AFD77362FD778C15B58467D56DE473B79B8C1CDC5C2D63C763733B59E16C4244A4B44D281E544A005659C00EE17401AA57FF14B38A7476E455978F1015F3385BCC4956EE93748A0712074587AC4043B9982B89CCA03C63728C16086A2978A7366F95EB0CB02C1AD09AB95331C6D8DC6F8CF820A91B6D0F392A58CA1F11117B42A50869D781EA2B4811E175306059C60A9ECD12809CD553F6C51E47D62A68DC35EA71790D3BCBCD40B5116105066AA5316227AD1335DE3425FC627A70A0A4BFC4799BE3897E57779606763A69494445AEA93970E15B2E10858905C460E3E441D2D4BAF1C59C9FD04D5B44CFBF9970B04562231AC3785C6BC46B3BB9F51E7B107996F703B06043A3BCAAE735C1AF6A753AC8BBAC457057F794C355817B713290326E80754F4A4529B8253DFF763FE5F09D4234A9BD01BA0DC7C1A1ACCF6BBC4F5E1B5FFE566D779B7024E4187B488860F1BF2BF5B49817C7B4F07359B0C3C2809B487A61A213C3780C7742F7AA847C1492E7B31423B2772089A502655108C19FF3226EFA64CC1469420352C506268D82C327CB444408471FCB54DB415391404BE2F30EFF287D9FF13B636666E45564C95098B356339A955EB82313FF544AB1BBAD9E327237A9AB51648C9671B0A2677C7162A0E87C3901E2BAD4EC8B34C864DB329CF0087DA6D5003FC19217B7375D455EB91052C90392BC177A2BB21028D9A275F2920546696BBB9075826AF46A2357184AB42769B62B0B320B848B35003AB1A88710176764AD4E433C00ECC3C7616112FC9402E505488C8325C72EFFC3169D3C83F621C750CA4320E36FEF44CF57E979DEF5CD7B49C56791A5A1B530E992116C2A456D2737078439F5499639C8315D977FD7E0ACBF701CA9E85E301410966769B4B59E3DA1CAB1C844681A350C68760B5627074B3477A8C1BDE452114878A4B36832E82F9069C53E95639682AB7A94B16B253B42E4091844220375A1A3D421F310A55FA2A2EBC0CD65A224C27BB320173D40B59525F789ED4839F6FC2831555AF0F03FA1372ACBE0AB9B5B858EDBB579D1CA2CD529C49BB67FD30654D902957C3B563107E3D135AB64A821563353A48217436977A5472C88C6A8A30B4B2C4A92F62EA3C1910151A472E7AD81B2042A416629BBBCF4B7C64C739E9E54C612E41BAC517164B8258A1497B7C85E2FD28C714C224F5C1A9BEA8DBBA17A45735592F8CA7992975821A7D4B680D68A6A724AC439F8687BB4B59D549A73D4796DE10B21EB0F99395D4E809268C1AFF7E4110178C210D1A6759969338C21D7F85B846939BC599B6F99CC50B333DB805DAA0C49A219B15263BE09E6406FF66618E74A9D632B69717BE25656CCA251839C0A5A376AB416A57C933E0C2C464F86168D72476ADBF85AD10583F2FBCB0A2017ED8BB87797995EEAD8089EC7A2", + "DFC76145C694C069B088192383A811B848A897CAAEADD9950E731AF85219C151AFDD386317A03C78805F2AE9992B9243A1C674BDE2B0CD1CBF256B60D7C5C3726758974325710C3D0ACA7FA0E05A4F612A2E1A3399D6331B09A0D1E709300A25D3644724041B0568B08D356A268C6413D431F175A002857476D85BB8B00ECDE824A277A39729A60F87B4D4D518C6992D2B51B22DC4A1D4295B18D43F4A4A50FC886693F00F34A8BD03D4A1841A207BD65221252A16C5C713DC01378A1F8B4272D071844CD9B2DD0A98D5FA628FF1CF42FC4FE5E327801360094218609C3C83263D3259700A91C8E646A54DC63DDEC913C7E653B6C4ABC0D565EF584BE1021D7B2C4CBA66115DC46644FB5C4139C528D763D9DC3D90BB84131983D938C946D83B9BE61BC2EB14FB106A0F490BC8F6C9DAD4A328532CD8CC22626BADA8D94D690B6682FB4D31DB81DF5B2DC50C49CAEB9E43CCAE963918C0940525C5878F31B1C87B1FAD4B4336FAB326120AAC5835DAC99A76E8AAFE98B9C5E9BAA1AA5FA9E7AFF86640F46803447885A1862DAEF74957D7B3C2E044CEF3210A9B8B036586E0B4052C946636A26E9E0A064C7666B364654BA1BD962459CCC91E38D93CCB2BABF2C22972C2536B319A7F25017DF0208ADC518DCA07009DAD91A146C4793CB7A64600C4574FE919CBA3C2AB4CA33C9770D4E027E0CA8D7EE68DBAB98F1597C345432417FA19CB53282B7799CA6B56BC411BBFCA04621543FD300CEAC04FF8D2604F281FF516CF35D07F605B2A623B4EF8940D963670F6B54799A3091A907FA3C927498128505019496AA14A4C9BC9F804DA85C4D2295D4440BDBF9083B206CFE535832CC04150BC5C2F552DC8070437E3C33E103D5D6417A9329A83835A2E91C927278AB0CA5AFB1C440697B8C756192CE3B61FD2A11E3621408A99A82CC58C5A4F95C70F8AF50FD3109E56317A5E398719E8CD8CB7C9A1782236157934ECA45D90555C5A4228D0859B17BDB7812551A407C72C381EE12C8D300549978EB9915FC1B7CC881C3C06276F524078827144BA79B0E5F8AC26E774FB647A25209D319AC1448040D28B0E2A8631489283F47521BB564D057202D230766329C050E87D743376F9DA439E260044F248CCF6049FE65349FC5C56101EF5E97091D12618FBBDE46897C1964593D42FC301BA2C0220A4575040D54645C9272D76B7308ABA9AE348968162BECAA4EF937F5FDB74C6F84ACC287CD8259D8B3C7E344B2F90C2A5D73274DAF32ACD570522B3CF6FD3589D0013AC3A9EB69AA6A2E726EB758E2E505EAE51613BD56E3A06C44699BE1626456F7B0DEF1B7A62D6BFC1851E1B750BC224AF339C594849673443B1E8282BCF9BB6AD830C3F292219BAB11A3B20DFD0C10E4309C41CC4B692C2FB556C2D421926C98A84368561E01097C6C3FE0430F04B656EE7A2F233C3CF90238D32BE5F4A198F20A4892853E344B9E6C59819E798FF9634B3F236BD4C062EFB6F70419067A08FE63C33B1584932223A3790C76E6CBD64493275567B93DC9A09693BDA3A58269959B7A14ADCE535B6199B56D617C5375459DB602DE8B89BC59D5E1835724A4A421431CD11465E866E6B3660FDC386060614951C09EED1630C6752E40C963DFA1D94A1525F779DB942AEC4DA44A457275787931B0AB1B750915D74597902519C91258B26C0E8C1BEF5F281B06871E945C1836ACA7920216294414CE07784AB792FF94B3A0811906055AF860F74B4A6BD2A72C135C91F79A11ED138867ACDE172B86F41965CC9CB22A63CB9F60A846A58C1087D0F3AC1473A9FDC44A71AA194869B1017147E2EE7B44AA2241B848C0EB95C80569540983187A19ABBE346C92A659CC2429945299A018B269C87B3D290EA823D8C1BA06F8A8FCAC3829058140B92C482D9801C189C89E1111B351C1F499F66B889DE8403D0BC1DD5012C9FBAA4FAF06BF6270F6171CE3C627A57BB6379CC8559983D259C971CE97FE78A6CA418B97CABA98BF24D7CB542ABD5AD337588D7C6C8F733B86A689EFB212DDB2BCABA764D451427EA0C4E13680985E12ADCF7BBC517A0D67A99C3E62156B3840AC79CD091ADD3174472A3A1E286175A422A1E359CBEAAAAE56603A11338D1364B93D665CDABAA09075C9EB73D99436CF678CD33767E4D16AEF4E20DEA770B07C36F82C77D23E16659F85EABE65603E53CBE3BB622B64FA4FB9902C6681537ACD151BBD0B69EFDF38C911722269550633620B3881FC1B673BFE7C0D958A24045A2E35596FDC319292988E88471152C7D39D58156B388EAC55DCF98BA10D9428135BBFF04C59F096212C17DB2CA27F607B37E41CC679B47EF648602B36076470C28828CFD560FC0D1788FC57860B3449D8A03DAF76581802D1F7769D89954C9A817807A2E496461E9CA2BF0F96E05772CAA3CBAA808AE73E3A105EA69A97CBDA06C35252817F7067F79848E9C3ACC84943070B30CFBF4BA54787B1BDA450BB05CD20571B295331AB1C17C8A99EA178A730716DBC49AD1A17CB5C7A965C30AB4102E1356A2E29A98E729598DB8907914AF86CC91A567A718E94502C82F75867C73A73EEEF99332F47283753FED944ABEF36006FB1B802495F89741C073270775B0DD612BAAD8C9D526CE36F90A2ED035B731A00A17B087B690A90019E1011456D00B04707750902089A11C6F29422FB52144B55E97F98ED765924B87718269BEE41C276E1C4655C18C51AC5C3DCCACF253B22AD75139677255AA1D182C65058562D0E684494A7D2DC6311DBAB6C931C98E1376E91A4221E129C2F12A20C491D8E17392F9951F526CEE94B416112B7C7B0B37F03EC58BB70609BCADD3C8366323BD48C57B491479CAB0CE2979CB8414A8D74E978968EDF53D13BCA653F42D31889FAEDBC5AEDB5B4F9C7C42425128FB1C91C49DD2AC7A64951FF38AC85986AFD77362FD778C15B58467D56DE473B79B8C1CDC5C2D63C763733B59E16C4244A4B44D281E544A005659C00EE17401AA57FF14B38A7476E455978F1015F3385BCC4956EE93748A0712074587AC4043B9982B89CCA03C63728C16086A2978A7366F95EB0CB02C1AD09AB95331C6D8DC6F8CF820A91B6D0F392A58CA1F11117B42A50869D781EA2B4811E175306059C60A9ECD12809CD553F6C51E47D62A68DC35EA71790D3BCBCD40B5116105066AA5316227AD1335DE3425FC627A70A0A4BFC4799BE3897E57779606763A69494445AEA93970E15B2E10858905C460E3E441D2D4BAF1C59C9FD04D5B44CFBF9970B04562231AC3785C6BC46B3BB9F51E7B107996F703B06043A3BCAAE735C1AF6A753AC8BBAC457057F794C355817B713290326E80754F4A4529B8253DFF763FE5F09D4234A9BD01BA0DC7C1A1ACCF6BBC4F5E1B5FFE566D779B7024E4187B488860F1BF2BF5B49817C7B4F07359B0C3C2809B487A61A213C3780C7742F7AA847C1492E7B31423B2772089A502655108C19FF3226EFA64CC1469420352C506268D82C327CB444408471FCB54DB415391404BE2F30EFF287D9FF13B636666E45564C95098B356339A955EB82313FF544AB1BBAD9E327237A9AB51648C9671B0A2677C7162A0E87C3901E2BAD4EC8B34C864DB329CF0087DA6D5003FC19217B7375D455EB91052C90392BC177A2BB21028D9A275F2920546696BBB9075826AF46A2357184AB42769B62B0B320B848B35003AB1A88710176764AD4E433C00ECC3C7616112FC9402E505488C8325C72EFFC3169D3C83F621C750CA4320E36FEF44CF57E979DEF5CD7B49C56791A5A1B530E992116C2A456D2737078439F5499639C8315D977FD7E0ACBF701CA9E85E301410966769B4B59E3DA1CAB1C844681A350C68760B5627074B3477A8C1BDE452114878A4B36832E82F9069C53E95639682AB7A94B16B253B42E4091844220375A1A3D421F310A55FA2A2EBC0CD65A224C27BB320173D40B59525F789ED4839F6FC2831555AF0F03FA1372ACBE0AB9B5B858EDBB579D1CA2CD529C49BB67FD30654D902957C3B563107E3D135AB64A821563353A48217436977A5472C88C6A8A30B4B2C4A92F62EA3C1910151A472E7AD81B2042A416629BBBCF4B7C64C739E9E54C612E41BAC517164B8258A1497B7C85E2FD28C714C224F5C1A9BEA8DBBA17A45735592F8CA7992975821A7D4B680D68A6A724AC439F8687BB4B59D549A73D4796DE10B21EB0F99395D4E809268C1AFF7E4110178C210D1A6759969338C21D7F85B846939BC599B6F99CC50B333DB805DAA0C49A219B15263BE09E6406FF66618E74A9D632B69717BE25656CCA251839C0A5A376AB416A57C933E0C2C464F86168D72476ADBF85AD10583F2FBCB0A2017ED8BB87797995EEAD8089EC7A257489778A6C55BF9AB90BE5934E39F80FA5DFBFAEE68AEFA4AD35CF089419A1D7E3D54DDC2CD09DE682ABA1664799BB5598942E5C1A89AF67BBD7FC609E05654" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "1B26145DACAAB8A2FD647B3FC3D38C0BB9A931991D914DBC0A218005E4FC7F8B244D18259188E7B7FC90FD67BB1F37BAC3D2E3D86393C0334CA6E59461B533FB", + "C7515D50FA12D072289F386862306FC5163299137F3511C2B73742CBA7902054212FE2CB76F953F8DB6CF7D0B80E9CC38C79C63A19AB0ED452FE1821409C5CDB15590854560B750332293BE729CCA791405EE5AE805B7F3B548DE9B22AB15427984844C4DC76C516911A64BA491899B7B4910DB65436642D8C4A54E7DC00CA8B8BB4F07365AC9C32E0B28FD40D0AB1A649401942ACA49F011EBEFB9471E6A73E879006590EDE38097D661F7A2048EEC05B2E6B218F77C9729B3EE4A4850FBAC1567152EF134B163B86A45144314C64D4E9B0DCC6850BE61F7D428E1499970A06269AC38848A97E960B110C4765AF1722F6A92CBB9149EC270F048783C9A9CCCF1A5385B100290A5263B61FBB8968BF1298AEFA80910B061800B14A64426CC95013AACFDA931B2EB2BA5D96B1F251CC1F255DE49C1FFF903BF1076BEAB88C42159BDC7A0B4C490A36E6B8C59CB2222C3A5691B5B9E732D0A70297D782386736A54C401D663FC49030EDB3B8B8B1A207F7C0F73C60207A0A623C66DB8B5CA778924F09B5EAF8B207295CE960970C9C791D515EF5D88483265315330F93559DF5E8B4303232067849A556263AF12758506496033972765463E54EEFA06626A42A42E9680BD03AB168A753E993679CABA0A81059A98771A8B0BE23A7C5B897DD9790B787924E369109A346BB55C7A0FB65CE3695936A6675FA0021554F40265858C46B24985B00F19B0E9048968080B59526CFE97C19FA5AC1E3234EB256A1E9B4D63644C406BC4787B23C13239AD7BCF6B590B19133B8CBA879C367C2194E4B2B681C683842454180A805C8E461F6D137D3E44D154B521FF06F1DB5A7E3357223A5A3D6548473AC4EC5AC1977ACCB1B24483596504C0BB4F8337431C5018647520EF92312845FC904CF6D928D2C7216DB5220997CBCBDE11F4EAC088987364D842A3357291E033BC951C769425284F3BCBC80C6DF0CD06DB1247CB682D9987811554C57F9A6BBC198F0D241407585FB99600E458724B060ABA073A963C5BC36A00C8C34D8C69950BB4118809A9E7555EBB9B8A506667A7A86CB561E02E7787E10795B552C86C6CF4D4CC9C4119BB685C6871A21C9C3CAAE972E64200FBC57682EEBB868B187B29B156331450099A882F823AEBC58F6A48720DC0B5DB4B1B13C66E152C7113A445CFC15E7F9B4623C83A2226943E04836F465ACA4757D3A97ADE62A15743C4039C82768A9181753F2A24EF8E090B876C9B5318B276AB398985CB197C111FC8AEFE284949146F4491B563B167F7396C3B40069774012F11E2C501551F9BA7368163FFC5D955B2B6C087AAE506536243BDEBA9FFBDA68F57CCE5B47398902B29DA02D6D80251DE77280B6755A04B322713985F211EE8A99C9E3403BA8B1A23A18F500130B65BB668146C609BB089B30FE415C8C166B5C159762FBC7729AAA39A7A1B4D3C191CBC3A940702DD712CEA69CBD54593E599754E912B24132366B20DF4934727BAA4DB57650B330E06A76BA5ABE127179525941234639482C0F09401428E246BFD20515976537E4C3AC82A5D37686AA9B643C9A36C701006411899634B70DE0B8DDAB9ECDE9BF56BC56B8803F8B5747672515714A12C1D37DCB6203BBB893B3AC811C28CE64EC15936C9A7040A5C2D11A8C5116B158A6D3317761295E4E2413A803323B0695E3BB8DDF4661F47334C8188DF63446651305D6A1BD254791E8F9258C413FE7129AC9476EADB61433271B81570F5188416E68C65527BCE3346BFCE7145B056745830068EC8C1E09CB09B9C9526904A557954E41B9072B25125C81F0A1BB969B87033286F0E1CB22E4B6B546AF91ECB4D989499869C84D6740A90685A4D883F9FC6D27EA7453354606E06FD9F328F510C41183C9B2BB6A353C55B8EC6E53E11CEDE3BED42827B7D7AADFD9B343E83F51A93546820C6D14C735488853F5233DDA533BCCC66C9CC6F99BA22702251B3A0E31595FC3331396315E5E33401BE95EDDC9C9E64CBCCD2CBE7A4C81A80632E69C7EDD3C91D4B9BFC979A4D6E14B54D75C7ED71ADDF71A659CB14E7630B97C6B5E07C63291B9F8417269A87E5E520E9437563455C6C0FA556801229B0806F565509D3B25B7520693D82659490C2E09C87BD191F66030C14BB380F42A8F0BC3491768C7A12C99F548715506A0CFBF4470E8AB18855B9B59E9DB20E5036243080C4E4CB4B80A", + "BC8C45974482592C1FA09A5125C017C117987F1433144972CA94B1B4C6CAA71312FDC5572629830A7C9A084362BE24CBF070274FA38A2795147E7679F4BC25D258456C8C2B19E192546C72ED778805B4B13FF5404B65CC9BF32D5CD678C572C979226549498C86F44A1EBAB2B152487792B918960073D73A82D2C1E4522AB37B5E82F4B4B5D9BE8AAC3BC9A028C9A7B693AB851F3350CB55A1928B360E4446BC46B61C558C79805222E856B88708DD1A3243C34FC8CA768E55C43F1BB2E574C5A9D42DAD3688C7940FDFD507AD8290C3F30F438B08470741779808842BAB07A80B8BF7858F825DF9C2191B36B05300CDE927B79E148D591646BBC22AE3C04FC03C533FD37216037E317A85D1BB7A93115E75BCCB79D6035DA7543B01CB51D75C439623775716F21829EB317122012E73298694F20996F9813FE59136C984084536CC655FF6D555844CAC264694F1C97B3C00CBC5D15AA51393E86C7FCA8132A53361C03C24A64C8CAF3A5D03319DC03403E73A4B792A1CFDE27D7C03216A54919D4C04CE19575C643AA167418264B94620389AB31C8105472938C7F909BA57B0B551850A6794866F86AC39492DFB620DC6D37D15F44527D511346C09B63B433B3124C78A0474B4590A65114395361BEB825418551A989F9E123BAF3C339BC13B4450C1C6A3BF79EBA4499978D4E04CF5FA6D82CCBDAC11B611B9CB0823B9127885B036C7FAFB8C9C9305086C6BE4A2B0F7C4833C2ACFC5A48B5E957416B744350BC9595A07C80CBD7E5BB0FAC5CFEC727A7F2075E5013710FB77F7E7A3906CB2A0B546BBDA2F69A1B2F89622DB046BC09612BBC7258183A0B770800DF5CFEBE0728DF898BDDA9F39266784318BC6F50899E31908930E6D965D5F7898051993AA529082CB30CBA42E11135345E6A5369CAA38891396814742B1073DACCFCEC42928AA8E1A663B63A479C0C2192A9AB2821A935262AC53865E46EBC4D3E43733B379B7933F91C4807F898521816726F991FF285D5B830FAB9228FC2996B238626497934D14238B894991AB6B3C84ACD844C8F2785841E8A9BDA41929315663E1605D45C75270AE7511342BEC8920516A8FC642B089C313D189D9CC3A970B812B93BBCE132FD669B2476C92F6E351BB707F74803EB7582B0E034F35B81FB768B6827BCAE377775A3179CAF70A045220C6E9308228501EE127431093CBE27ED1205E08F2219B5CCBDD0C8228AB6D7B3A44D56490E2246B974922755810CE6B62FD1A8507A48B73B9B8112C5C0F3B84B1FB7553A63330688DFDB067B03604CE38B402732BCCC254DC02995AE356F7DC3F61683C57C018ABDC5EDE59A465666F59C25BF3516DF4E42603FA95EE87B711B073EE38AB460A3F6E20A5A727A791C5674EDA82A78C85BD90C4C33461130902CC43BBA0D573944313D59C78DAAACF47E93368D99C696165E3854B02371A077116B1836D952C69E4D66598CC99E22C808E1992C117A5EEC305B1AC4D36C45AD49AA2BBB0350AEB0CF4C15065652773B106C456AF19FA3BFD09C4AD78A8E3A954B386CE9466A501DA0593566B42B3AA9E295B0FD3319008354E28AD49057414562A26E51E4768C9CDB8C09A165F327050BF822CE9E1BD1122383FE840FD8646320B8A39B741628C3DF9CB75D1D16AD7ACCE7798A4267331454ACD21373C3B715201A7C9B15C315EFA8E7DF35F42634F6C2C5E6F87405613647242AAF6D17F6B1112D56C13E16C589E73A2216A0C536B09FC672DE59A8158163764539C69E9664C58C8DB79963EB8C07C594D43B5791653734AA94DA1019B2D409E80119C2928044CAB4A0D520D5E5972DE5CC234CBC5C10C2D7EA08DF7C75F2799A104207D2FFBA30B732F99377A269389F7786D82683809395CDC7C6366430A2AB03C8CD19E8CAACE8EA2CA9997956E19A25460046574411086248DB28A71AA2119E72A5F727CB093CCBA46ADDA9C79EEDC7825A04BEDEC50C0313DEAB397B4B103D1653A66CA3CD3EC74C2989110D2984D36631DE407CF51C67D9568E2788A426C2854FB5CF569C5050312B89C04D4DA22748C9F10B883E4D3A2DE0A1CF00496C7B2BBB442826FB1B5B878380ED81CFEC3880ADC17B9558BC3195F9245641DA67B009A8C2EC46165936786608344D40901660A0B6A67146639C7515D50FA12D072289F386862306FC5163299137F3511C2B73742CBA7902054212FE2CB76F953F8DB6CF7D0B80E9CC38C79C63A19AB0ED452FE1821409C5CDB15590854560B750332293BE729CCA791405EE5AE805B7F3B548DE9B22AB15427984844C4DC76C516911A64BA491899B7B4910DB65436642D8C4A54E7DC00CA8B8BB4F07365AC9C32E0B28FD40D0AB1A649401942ACA49F011EBEFB9471E6A73E879006590EDE38097D661F7A2048EEC05B2E6B218F77C9729B3EE4A4850FBAC1567152EF134B163B86A45144314C64D4E9B0DCC6850BE61F7D428E1499970A06269AC38848A97E960B110C4765AF1722F6A92CBB9149EC270F048783C9A9CCCF1A5385B100290A5263B61FBB8968BF1298AEFA80910B061800B14A64426CC95013AACFDA931B2EB2BA5D96B1F251CC1F255DE49C1FFF903BF1076BEAB88C42159BDC7A0B4C490A36E6B8C59CB2222C3A5691B5B9E732D0A70297D782386736A54C401D663FC49030EDB3B8B8B1A207F7C0F73C60207A0A623C66DB8B5CA778924F09B5EAF8B207295CE960970C9C791D515EF5D88483265315330F93559DF5E8B4303232067849A556263AF12758506496033972765463E54EEFA06626A42A42E9680BD03AB168A753E993679CABA0A81059A98771A8B0BE23A7C5B897DD9790B787924E369109A346BB55C7A0FB65CE3695936A6675FA0021554F40265858C46B24985B00F19B0E9048968080B59526CFE97C19FA5AC1E3234EB256A1E9B4D63644C406BC4787B23C13239AD7BCF6B590B19133B8CBA879C367C2194E4B2B681C683842454180A805C8E461F6D137D3E44D154B521FF06F1DB5A7E3357223A5A3D6548473AC4EC5AC1977ACCB1B24483596504C0BB4F8337431C5018647520EF92312845FC904CF6D928D2C7216DB5220997CBCBDE11F4EAC088987364D842A3357291E033BC951C769425284F3BCBC80C6DF0CD06DB1247CB682D9987811554C57F9A6BBC198F0D241407585FB99600E458724B060ABA073A963C5BC36A00C8C34D8C69950BB4118809A9E7555EBB9B8A506667A7A86CB561E02E7787E10795B552C86C6CF4D4CC9C4119BB685C6871A21C9C3CAAE972E64200FBC57682EEBB868B187B29B156331450099A882F823AEBC58F6A48720DC0B5DB4B1B13C66E152C7113A445CFC15E7F9B4623C83A2226943E04836F465ACA4757D3A97ADE62A15743C4039C82768A9181753F2A24EF8E090B876C9B5318B276AB398985CB197C111FC8AEFE284949146F4491B563B167F7396C3B40069774012F11E2C501551F9BA7368163FFC5D955B2B6C087AAE506536243BDEBA9FFBDA68F57CCE5B47398902B29DA02D6D80251DE77280B6755A04B322713985F211EE8A99C9E3403BA8B1A23A18F500130B65BB668146C609BB089B30FE415C8C166B5C159762FBC7729AAA39A7A1B4D3C191CBC3A940702DD712CEA69CBD54593E599754E912B24132366B20DF4934727BAA4DB57650B330E06A76BA5ABE127179525941234639482C0F09401428E246BFD20515976537E4C3AC82A5D37686AA9B643C9A36C701006411899634B70DE0B8DDAB9ECDE9BF56BC56B8803F8B5747672515714A12C1D37DCB6203BBB893B3AC811C28CE64EC15936C9A7040A5C2D11A8C5116B158A6D3317761295E4E2413A803323B0695E3BB8DDF4661F47334C8188DF63446651305D6A1BD254791E8F9258C413FE7129AC9476EADB61433271B81570F5188416E68C65527BCE3346BFCE7145B056745830068EC8C1E09CB09B9C9526904A557954E41B9072B25125C81F0A1BB969B87033286F0E1CB22E4B6B546AF91ECB4D989499869C84D6740A90685A4D883F9FC6D27EA7453354606E06FD9F328F510C41183C9B2BB6A353C55B8EC6E53E11CEDE3BED42827B7D7AADFD9B343E83F51A93546820C6D14C735488853F5233DDA533BCCC66C9CC6F99BA22702251B3A0E31595FC3331396315E5E33401BE95EDDC9C9E64CBCCD2CBE7A4C81A80632E69C7EDD3C91D4B9BFC979A4D6E14B54D75C7ED71ADDF71A659CB14E7630B97C6B5E07C63291B9F8417269A87E5E520E9437563455C6C0FA556801229B0806F565509D3B25B7520693D82659490C2E09C87BD191F66030C14BB380F42A8F0BC3491768C7A12C99F548715506A0CFBF4470E8AB18855B9B59E9DB20E5036243080C4E4CB4B80A4968C9BD195E5AE749FC460A24EB6301F75634DC39DD18F01C1241EF7F230C4D244D18259188E7B7FC90FD67BB1F37BAC3D2E3D86393C0334CA6E59461B533FB" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "920059B543F49FD2DE066B3881B1C8D29FA2ABB407145549F4151CCBF108676AAB7E6DF32388274BBEB48B3A37C1F28AC119891D75E56500F37D3D6B405D8669", + "86D222E8F62742720C95350BDB82874A33BCB8A9A6F0B12E2A3089FDBA7526A566B351617F0C5F1611989AB49B246B18E3D28093679E4E0A00C7967980B302F679BBA2425D1CA4C83E088F2A44BDCA760210D3097CD7583264663661BE8CE927E5911E4706408AFA58C4DC9F9ED5856CAAB7DDB9B2FB39477BA48D50FB6A16F90DFF933CA14CBF0C74A01A501036E47477EC9B43B23C594AB5236A386D31BA69739067D389B7D2310A3451F400A0D65BC318E16F4C2925BB0624936BC0A9665F0D21A106586A3A103C6B55734926BED1E7333697256C770F58104FFD94234346B637E7122306CAE6EC8D2CC89D26CA7D6BDB62E5413143DC9E61E87D4914457D67717FA206774C5CA00CA2A3FB65B75CA32FD7AC8A41505597117D7B7FBFFC4E107B5385B09288AC7003815FB95677EA6A9708D24493981CDCE2826CC70820C930F31754B38BC0CC60A45F86511A7761C3BCB50A44BA450797EDA3B873D927D4C92C0FFB0F28910D6E95A1F42AC106D5A046E45202B4623FF1BEEA076BF321C7BE2C0ED0D723443696C9DA5952128FF83A41302714204487FDAC3262B04491DBBA70922F3D9086E205284BE047D2B61E4073B87E2ACB36E11E91E46BFF443CE8EB1C1FA71B6DD0378C9AC1694B4F2B2A4071075BD0B0871F3C7425B950F22405974CB843CCA540A74DF5108B04D638522C50C374146A336253096EB2B40879E99472E916859543B9199A124B5216887FDB75BAE131C02C0BC31A034191F1216F5960AEB1AEAC2335AE198881712159B20E7E343976256842EA9CDC7284B3205A074148B48815AE826F102082E1013BD271781C80C5D50B753C94A8953667941B88E0BB463F11A30E7784549392EC6C624FE0B4F3E06365361C84C4AEBD18559D2535D267A0B6F08F865764F2021B62504AF0845A2917B20AA51DC2F7644BD417A5C1A8C58786BD7C1870B64849E50EDEA0B9F86C58233A75A55BB1B7D03D4EF464936B828055A5F06270ABBB19E6B36441A4B25F7A82EC3B1DA6725568B8B98B7A819D763E60EC5F04DB2D79B409BBD170ECFC3A8771356BC71F9C042ABCA45C6BB56ABA654EB50866B515668DC1C63EA8B88A816D35939CEE464A3011BBE7E5C326AB84C1E14892F755A329B063014E0B4607E62967AE6BCB1C9102942810DFA557E5479F5870C4D44023C8E5BAD7EC6ADB5B6C8858932749707ABBB81D01880CD1704F19217D6348CE4472F7229164FA2003B243AFFBAAF3EB2707886EF4980820F779A5117FC026C679C2B83539115D4AAA7593B6D14A5468541B44D77CDD96AFA40A2F59F0B08DAA59D72A31ED740ECBDA2166E65376DA16EF342C10CC79A8699D85A12082F8CBF8B73F5735B3A65C19A20B72EAD860D502255A24AA9251AA926750269A045346579070B98E8AA7DA79A4613655F787A1B7F1C7AB144A6A56474ED94BD1333CE9402CB2E7C8EA965CAB168DF71519483026D364BBFBA6441266B90C578B6760143CBC1DB2C834AC9C34DFE0BA52C84147826EAAD1BB5A0BAA01DBA5B2C7B804E21E6F8C87EB143C4F44A3BD79260BF736A1A82E38C7748D241EC114C1DAE6141B6994617774E2B41D8B397EA0264607E03570DA46B6FA4D03C100FD366B33C0659D40C9892B2258D5A0B85A33DFC391707B1A47E6783BA7127E124C1A920BA4A25AC6B727E6771339A892C1D8C2E9CABB8A8527BC3605F57A4D4E7979E3ECACD311A6EDE5A910877ED6AB31CAD8A3B9B7B1FC4174ED1162C3B5B05BA6AC585C38A3910E334128FB4C40E9B476A860B4F13124829A0332A73625C16F46DC3626691026C2AF0D2A5D469151B8F79044494FA843BA10E369890C8556768CCB349681FB42EBC16F4A2C74FA074C487C7FD0F680119A5198009ACF8478ACF900900758150352A14208776260B4A19B13319504CC56261738D5CAC0B3561088AC4091383D9CBABAFF23249462A897C37B1639A6ACB590FF067C1CD9902E748D9408305C4BA029CBCEB1E7672AAB3CA0B45080736E96ABB81A956F40767D0D0C0BBF453C8D873EEE41A5F5F81769AA9016FABE3E99A92311868FE72A1F062081F65C08096ECB1B880AF5B92CF0788FF3CC1AEC3CC639AE0E83C162480AF08048969C190D0B2C7B8B601BC16676D56E4A6775530AC1C98C950A30A69B39ABE281C8F9F321B2F62E74ECD92136C2D2928670B6F2E70D21D4EF270824", + "FAFC70BF1C5755007915DC3D0C0B29D6440061024FA4DBBF76B85263D448922780E1F864C5151EE0FC164691287F9172B5393C7B60A8192C8F61B93472239E4AE54CA6848B6E984096D33F09552B9629850FC08A7E681722B7385E8B2B75F8A85393C81F3A7FA5BC913F3C059CDC5B65356FC4D048CCC96247D0A3FC083F82BAC34A022B00403E09117B9B58A1D1EB494B318E90445718B3468CB41B5B41351FD84C66D5BA7CD70348954ED0008257D3B3D8929EDD3B9AD31C234462B16E440E04339F80B8A3CEB96E8278BB6A944676B8CB596421A7D8931468C1D803B4ECB51335D88AA7C3700AD5345EE853D9A4172ADC8573943FDCC04C88219935C585C89A72906B5E3B8B780D634D19C5974AB5BF8C68AB61EC449D7B7C76C30EA86C33DB01AB418405B6F891942AAD863637CA9B6F6873265E19B0CB77BC0D028D15F69BEB92602415A2BFD5A762165686999CFE03597767801E5716A87192A9DA74E8B5BFCAB16204C60D70D514C1072198739A04CA405DC926CFC0975D251947930BA44B7152407DA43AA023A181EDCA7A1360984BAB7AE844A8D9C1733CE1C0ED90770C29328C951D5782C1C90B096E48C65039008982539F6563D7886525763CA4167667E840A7E6AA6F10C3638C6113FC620104C66D70CAB02A205C1449C8E185DAF961C457C291E41CF483B6DAD299CD330455A8640BA01C6DBB9B37E801ACD32D98DBA82BA8906B37C1712C87D3C91A213A69A04885C32A0BB849601AC44756A14DD19BC308E45BE6C89C3E39274614943CF668569AC2AD11AC7AC43D06E776E7E78838E878F0931D9934949A593E61228A172A4D05B45EBF10CFED552CD4B76AF151A8CA017E87638309B0073DC1C790C27E6466331671851DA5655AABB41D94109DAB3E74E848E048CF9F1823D0473ABA782EFF568C2E3A0BE7E11FE5B6ABE9B3BE78369A5E71C05FB7014EC0062A95A9648195FA29795CA3CF8FA2B835A5C77ED47419966921D167699080133852B1724D04144E012BBC84D294B8DC3E6B358C08500459F44752C8A368060C610476BCC553AB5B44B741293FBBAAC6E3A638970FD0277F77931F93E45D226161AD1291660C725EB6B8A6926EC8AA74CBCB8AD1B64B7C1512A4E81143E78977AB2B9AE320A8F4637C707C85408424D519DCD425B38B268F9AB7CD48944CC27FA3566857427E71B4808F5182735646DD923B84C87E1BFAB3B6EB69D9A33CDC205C0F7B1370331D74383B5F712AA1B72F7E707BAEA885C503409FD54615ACA94A48CB752B5108974D71D4BF9F9B0843E8409A448A6449838EB449EF852C8D1ABC93822FF6FC059CC2A06736387E060542DBBB2C63022D02873AD6B1A1BC7B1D9A24614934365779EBB60565547415340679CC230919773B1241872329A202085A601EC854365C6B566FB658670AB13DE0CA8D561CA9D7843E10A052A0415BF73BB2097B3EA07B7BC55A03451CC3D0A3AE5BCF4EC53254F0C2FA2B31437478FE4300999104816B98BD97AE9727AFE2E1B241FA8ECC16064BF013FEE1B24B327AFAC7506A28934FC9C24969A2A6EC6F44FA53E864B59D34014AC0AD952024F89C3082BB977E907304616E7CFBBC153A5B53127E04C13C5E7C152171AE9C21BD36522975DCA35A8B943666379FC1572E171A65985FE3552DEAA6645A81CEBEAC703776C2ADF9673E9B8BB76A36B1008494299B21C0B5BA940CAF02821741179152CDFE9B3CC0375F91AB83FBBA0ABC9C4FC07B8341298F8AD05D3071C7069169A5574FE86743940015602AA48581CA3FB1243DE611EF5C5CFB356930CB10D8740CB3FB5236C528D42B2C2ED15DE2BCC5A77B738C833C6828594D0AAF86D93FF99011D89AA9F19816852A7A8D188A711ABFC5C761CE36663EE16FB69A65186BA62DA742854113FBD9AD54396291B219F199869995798A7BBDD788419A7ABEA78C13B2A8454180298DE15ABDE8C340207F105C35986B12CC5432D6502AA72B5EBAA37E88534A829192A3229E14A95E70D89FA9E14611818C5802197E23A8AA85B77B8B0C71E0630FB06E1A0560B3340077DC3F7F7052D0BBACA1E5ACAB89293E9B8943D758AB67026A55A7195C73BA696191F7AFD49C1F6A8C99984B94FE3788073B920BE195A3A8591EDAAD188CC8FA7C814CD59786D222E8F62742720C95350BDB82874A33BCB8A9A6F0B12E2A3089FDBA7526A566B351617F0C5F1611989AB49B246B18E3D28093679E4E0A00C7967980B302F679BBA2425D1CA4C83E088F2A44BDCA760210D3097CD7583264663661BE8CE927E5911E4706408AFA58C4DC9F9ED5856CAAB7DDB9B2FB39477BA48D50FB6A16F90DFF933CA14CBF0C74A01A501036E47477EC9B43B23C594AB5236A386D31BA69739067D389B7D2310A3451F400A0D65BC318E16F4C2925BB0624936BC0A9665F0D21A106586A3A103C6B55734926BED1E7333697256C770F58104FFD94234346B637E7122306CAE6EC8D2CC89D26CA7D6BDB62E5413143DC9E61E87D4914457D67717FA206774C5CA00CA2A3FB65B75CA32FD7AC8A41505597117D7B7FBFFC4E107B5385B09288AC7003815FB95677EA6A9708D24493981CDCE2826CC70820C930F31754B38BC0CC60A45F86511A7761C3BCB50A44BA450797EDA3B873D927D4C92C0FFB0F28910D6E95A1F42AC106D5A046E45202B4623FF1BEEA076BF321C7BE2C0ED0D723443696C9DA5952128FF83A41302714204487FDAC3262B04491DBBA70922F3D9086E205284BE047D2B61E4073B87E2ACB36E11E91E46BFF443CE8EB1C1FA71B6DD0378C9AC1694B4F2B2A4071075BD0B0871F3C7425B950F22405974CB843CCA540A74DF5108B04D638522C50C374146A336253096EB2B40879E99472E916859543B9199A124B5216887FDB75BAE131C02C0BC31A034191F1216F5960AEB1AEAC2335AE198881712159B20E7E343976256842EA9CDC7284B3205A074148B48815AE826F102082E1013BD271781C80C5D50B753C94A8953667941B88E0BB463F11A30E7784549392EC6C624FE0B4F3E06365361C84C4AEBD18559D2535D267A0B6F08F865764F2021B62504AF0845A2917B20AA51DC2F7644BD417A5C1A8C58786BD7C1870B64849E50EDEA0B9F86C58233A75A55BB1B7D03D4EF464936B828055A5F06270ABBB19E6B36441A4B25F7A82EC3B1DA6725568B8B98B7A819D763E60EC5F04DB2D79B409BBD170ECFC3A8771356BC71F9C042ABCA45C6BB56ABA654EB50866B515668DC1C63EA8B88A816D35939CEE464A3011BBE7E5C326AB84C1E14892F755A329B063014E0B4607E62967AE6BCB1C9102942810DFA557E5479F5870C4D44023C8E5BAD7EC6ADB5B6C8858932749707ABBB81D01880CD1704F19217D6348CE4472F7229164FA2003B243AFFBAAF3EB2707886EF4980820F779A5117FC026C679C2B83539115D4AAA7593B6D14A5468541B44D77CDD96AFA40A2F59F0B08DAA59D72A31ED740ECBDA2166E65376DA16EF342C10CC79A8699D85A12082F8CBF8B73F5735B3A65C19A20B72EAD860D502255A24AA9251AA926750269A045346579070B98E8AA7DA79A4613655F787A1B7F1C7AB144A6A56474ED94BD1333CE9402CB2E7C8EA965CAB168DF71519483026D364BBFBA6441266B90C578B6760143CBC1DB2C834AC9C34DFE0BA52C84147826EAAD1BB5A0BAA01DBA5B2C7B804E21E6F8C87EB143C4F44A3BD79260BF736A1A82E38C7748D241EC114C1DAE6141B6994617774E2B41D8B397EA0264607E03570DA46B6FA4D03C100FD366B33C0659D40C9892B2258D5A0B85A33DFC391707B1A47E6783BA7127E124C1A920BA4A25AC6B727E6771339A892C1D8C2E9CABB8A8527BC3605F57A4D4E7979E3ECACD311A6EDE5A910877ED6AB31CAD8A3B9B7B1FC4174ED1162C3B5B05BA6AC585C38A3910E334128FB4C40E9B476A860B4F13124829A0332A73625C16F46DC3626691026C2AF0D2A5D469151B8F79044494FA843BA10E369890C8556768CCB349681FB42EBC16F4A2C74FA074C487C7FD0F680119A5198009ACF8478ACF900900758150352A14208776260B4A19B13319504CC56261738D5CAC0B3561088AC4091383D9CBABAFF23249462A897C37B1639A6ACB590FF067C1CD9902E748D9408305C4BA029CBCEB1E7672AAB3CA0B45080736E96ABB81A956F40767D0D0C0BBF453C8D873EEE41A5F5F81769AA9016FABE3E99A92311868FE72A1F062081F65C08096ECB1B880AF5B92CF0788FF3CC1AEC3CC639AE0E83C162480AF08048969C190D0B2C7B8B601BC16676D56E4A6775530AC1C98C950A30A69B39ABE281C8F9F321B2F62E74ECD92136C2D2928670B6F2E70D21D4EF270824CE3234330BC78E05ACA1CFAADF9FD8D7DBFA5D52679529DAF4AAB8D428B71E11AB7E6DF32388274BBEB48B3A37C1F28AC119891D75E56500F37D3D6B405D8669" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "FD33DC89AEC88774D219CA1BB6FFB85AEAF0E7C7DAD4EC7E948882FA4B01EEEE6846325992089351444178C13B6B1139F596F2454E73D0308C6F914119CBB54A", + "3864305A592A3FEC4510096C2975747E31245CE797B2268522A74027F4BDEFA213FBFA8521005D196A8EC12908CCE53CD1EACCB1480E851409FFB41F685385582B3ABD79B9C8D44135D48859D215D7125C42D260B518903043C951075A07FACB77240BEABA348404C35D2013F0718735E08D983B003C013E49022E77A35F0833793A2C9B3AB3BF0ECABE5B05C886B1A4F77C6BE043CC1127C29BE12A8A2B9E571A491C5191C8DA42F0F2C649F05F8DF98031B8BE1A6C9868B4CBA2AC72767AB28E4422BE466C20115D65D5CB64CAAF77B316E0582632BC0519BC59AA5257F55395D64817982464CF0302E74480B038766CE57BF1406AA1893883D55D9B8821D02CBFB1D2789262A78709319096B8782C37BA6AAB833326CF7B75B594807B2697C07631567ABBD091994226CC01F8A02C27A08E456EAB58B20065BD26A1B03DC7136387AD6CD113E8A0C77BDB766F91208E9554BD2C6085380084652AF4FB9F5581A5901210E35889EDC5BE5090A2729558B877C9754A435582673E4C35E46359305595B844B4EA4443C4C282A2F09D74EC83C6AB72D0190C8C46508081959A990B99E1071DAB85A4449BEA3B8872597C700672C0CC850CD644E9B6CD7FB3AC2CBBAC67BB5B3200C4DECC849C793914D53B96A14C7DB865C1742F199038658019E6313D9738A634AC136FF2677DBB936C69678111C484B22443F1B3A1F56198CB9817590A8E961AD66B215E746C8AB381FD961D496A7E393A029A123845A03A54D121E2CC5FDE743251C810A04B6E2E19633AA448E78697AAE86184C9708112C5989CAFB753B4BC8AB5AE5764E669363140906DF832F589C884E80D83186DB0D31C56A85DD2177A71F123DE614E5E9A5E8776C7A7ACA482E96B58E26A1FAB5982D8B59EA261FBAA3346C52C708AA375498E611A55D2B3B66DD18C6F9814A3560411398FCDD72D75A42555A77E2A44A346E6C2F1D57FC270B4FAF73B3ECC4BE8D0BA69D199E746417024A0F2414BE9FB446F7709CC2ACD9C939091C279E121107457A805239B7D7B8DE7C3BB0A457277A21703BA0A44E45B216889A524282AAB7CA2F49BAC7561AFE666442165589B3F2D4632BADC4CBD569C37F50F1847A6FD9316F583349119B9CF4005CA8449EE3A7D388B93730065D28B767CAC3E24E17B942B925D481599016BE6A386944830257230A6C6C9F536336B453BE8692F18138028C9841C08C425668372F1C245014B2AD6B8B53A259201BBDFF53866222A26C59FEA94CFA605A9768924B667B1EE35A79FC4540ED88CDAD60C65F6CC136846E85A7742A184B1744B41FBAC641526F11553D30491E34757C36C9038674B95560B6E65C7F473A0E812607E2AA5EFA159AADC1815C890BF07A3B5A71F43AC182BA43196A30C415491F2B6576F166164E63DA271BEFBE2065BDB8E2131006524B31E6829807088B6B893C4AB82CDC91690DB122D4005BF48ABB7FC53831B9D2B1CC295B25A70459AFAA18BE3B89D118594BB694093FC96C056B97648B1BE7A7094702133D7C59CB609FD1C22551A04B659CD4780B1BD4B88AF3446FE0A8B399C6FB45B7AE3724E3E37039641A7CBF71097770426803735E3CDD1B44E0AA5A301F495AC1277F05BA8AD276918A72A70E25444FCB22DC10A348608673A3E7697A9BE9728389944B3E818655BC209B6A859C33DA34652EE62859B0379DCAB1EC01743D3B23856271BE33A9DF9A53F24009D2AC24655E77E1CD49A1D5B99294343EA9B1C90C58A3EC69C10F2C8C2431A55D0B50338C8C0384D2581062E02840B9104344B159A0976219A4CD83C40839BA6BB13379FCBB529869C74D43AC1969FC47476D9F23769160207908D3763730FC6617263894F06D041743E54E78299698A2AE2540777C50CB01663E758C6750361053F9832B634119BDBC95E5A3385F1B6AE24BAA842330638E5AB0DC275AE2B2643A517692BAC3FA97EE4756AF87A56015682DEB4C236499B246201A341BC2D410D7DE972D44486E507205C722B3652667A1C51EC9CAF216592ACD9868BF6444A5B0FB15919938CCA416375671C372060529497C5F4057817B44F0DD9BB8CE36C8647B338306F680C536D1B3DE8613BB37673DB052D2A22853AA55698FC5994494FB7C4118A76BCD7589BC5951FB67AA19DB96406FCC3535804947DB39FD223C6A0D60E5536FEDFD6E888B259C08B49D631F4E7", + "E690AD1205052D8C98FD35C61741259BD3C331D3A5C134A8CB4A37CC491F9A92949CA5075304C9534095EB40BF483A6F73CA3F56C119A8049B65940A41A8BCDDA0B82ABBBD0C390382B4AAB7995D841C14E4A31886280D324B76E3E5BB3E69379975B21924B40153505CF0B435641E428723BD9190CBF68CD4C4456837835C585BEA0BB0704B4482E098F329C6E03C6A317B97778C960B841B52F112772B4C7F079C94D520AC359406028FA573AFF321165E116E88F9CDF4133335E6C6D4DBCA5A42CF3BEBBCC9B955AD7BCA4709573F800C7D88AAFF973FD09978D07001628A5210B5377B36718B546748A98E83E9572A535B5524C907289B106481CC870394C334DC9A52E9416C867C5C1EDAC22856A1A22CA210ABC991E6484CEB3DE4A8512A6315E281049F8A0766C705E758256A0954270563994A4B79A4B76C578DE30ABECF2622B95A8B1628A83F2917CE2054F9BA37C9B69F6131C7A03470C6E8533F380F29D212AC582E0C39B5BFE04A94E40FE1CC178676077F28316B57CAD55446CBD15B77D94F04ACAB87A94FA8E3A48D47C336D8C75CD08BC282804C82A0CFC22BABD4027C6BADE6D0C9C5EA6BAE1961FA3B9D61C9B5F9968F8643536E610092E47DE9F924771947697B496C5748F8789F21B5B571E5B4A7338259238B773206FFA3B0178ACCB1507A91A370B1071B6D7230EB734365F9B80B570A41193BA3157AAEF43AAD1954D1929D37D6890363B3968564B33407E1067C62BC27759AC7130BBFED533AF633A9DE2525CE5A9E166B98A6A6B0DBA4CDE5950128D8A09EC7A997D63C0B632DB3E212808A8D1F0C80AB6706F43BCC02E04FB74A3439395E6B70220D3BBE45A1A320E963782406B9629FAD2A4017140C57949372C8937C8196993A7A3904357DE516854431BF96439835631D333FC62CA3BD22C595804FF1789CE7C1705BEBB528704CA64B74F736C93105C115459772A7C8CFE194B2A15E4F1194B419539CB156DAA1854E441A90F2B4AB62B27BB3907620782F2BAB298516A8B56D3D832DF6DCCA084A0170164A409749D8C49F4842533327CCD1B47C0CA78A65ACBD1A8C087528CECD4BCB1B54A128A26613658C3FC554CF4C12FC440CAF1AB11F49777E63510E75596A00A931253D15441B5F7B10816797ED209968964398A882004665730859F8A66A95862DFF44557777B4EFA6C322EC3679DABAC800AADA0A310138462C814A1BF29FA68048B1C447CB2C22E79A526CFC167C5268B314C2D438105FACA78F1B7EE518228643757C739FA7FA1D87CB7F3FD1002F77712D85062010AB8F97AC13E66C8B0589FD23791BFBB0A1917E00285D444A67A2734CE7778D68277B0B300C72F8146C7ACFA865033DD4CB083BB6D74551D84B591827A28171216C969C7710A44C4C317AB737C80322263B3FD11BBDA789AD1DD2A9EE20B5F6781F48682C74F7A7825150FFD651AC44C2AEE5A139EB0FAA42706AA1BB0449288DF3B9E3C16ACCC25A8136A2CE18069AFBC464DC4F9CE8946D5B7F9897C99D310DF50567DF989396B8A56BF43312E978813208B55AA2133BC051C02407A6BA9A45C6FC0093DAF354973A88C635202A0073857CC786F5942989AA7F98629EF336C389C13BA6BA28F69E0CA11D842139034B5B5CBAAA4413A216231EF9B40A5EFBC2E4AA6752976846F73FC5587F1C04A64FCBC0A73A6A3FB573CD03A5032C7F1EEBA76AC9AA28B2047D598E1B4A9A9D12A15207AAD531CECD1CAB5155483E4389ACE89010A81A236B6A6841C63FDC4AB8F211C6328A26691B606B9E97137A3F62C4859A63CF63BE1395AAE2C34B72F30D4E22498F4B85A4CA6C8BA1590F95C415518C7EB562372340283B84F1874A75391B28F4962E6051BE32AB719710BDE938C0880F41AAB65D18BDBCD8852530274B9A1DEE714DBA92A9376BC403909D15E820D554A958BBB98945B1F3F2B9D5AA6E3C95755BC976B4E286B47A0BA7570AF68163371BAECFD77F80A004F0EA8E6FA39E48E3BFF3E83FBAF46EA7440253F2684ADC4B1C0AAE203555D2753C93B1B82875CEF12743A1E4C6BF259D9DF1B5EAFB2366166E33052DEEFB19E37920CAF7668B958ACD5386B3E20254641870491648F4959887BBACC834A1BA1DA0E75CB55A7C4449AA3AF06707B6275E44A53864305A592A3FEC4510096C2975747E31245CE797B2268522A74027F4BDEFA213FBFA8521005D196A8EC12908CCE53CD1EACCB1480E851409FFB41F685385582B3ABD79B9C8D44135D48859D215D7125C42D260B518903043C951075A07FACB77240BEABA348404C35D2013F0718735E08D983B003C013E49022E77A35F0833793A2C9B3AB3BF0ECABE5B05C886B1A4F77C6BE043CC1127C29BE12A8A2B9E571A491C5191C8DA42F0F2C649F05F8DF98031B8BE1A6C9868B4CBA2AC72767AB28E4422BE466C20115D65D5CB64CAAF77B316E0582632BC0519BC59AA5257F55395D64817982464CF0302E74480B038766CE57BF1406AA1893883D55D9B8821D02CBFB1D2789262A78709319096B8782C37BA6AAB833326CF7B75B594807B2697C07631567ABBD091994226CC01F8A02C27A08E456EAB58B20065BD26A1B03DC7136387AD6CD113E8A0C77BDB766F91208E9554BD2C6085380084652AF4FB9F5581A5901210E35889EDC5BE5090A2729558B877C9754A435582673E4C35E46359305595B844B4EA4443C4C282A2F09D74EC83C6AB72D0190C8C46508081959A990B99E1071DAB85A4449BEA3B8872597C700672C0CC850CD644E9B6CD7FB3AC2CBBAC67BB5B3200C4DECC849C793914D53B96A14C7DB865C1742F199038658019E6313D9738A634AC136FF2677DBB936C69678111C484B22443F1B3A1F56198CB9817590A8E961AD66B215E746C8AB381FD961D496A7E393A029A123845A03A54D121E2CC5FDE743251C810A04B6E2E19633AA448E78697AAE86184C9708112C5989CAFB753B4BC8AB5AE5764E669363140906DF832F589C884E80D83186DB0D31C56A85DD2177A71F123DE614E5E9A5E8776C7A7ACA482E96B58E26A1FAB5982D8B59EA261FBAA3346C52C708AA375498E611A55D2B3B66DD18C6F9814A3560411398FCDD72D75A42555A77E2A44A346E6C2F1D57FC270B4FAF73B3ECC4BE8D0BA69D199E746417024A0F2414BE9FB446F7709CC2ACD9C939091C279E121107457A805239B7D7B8DE7C3BB0A457277A21703BA0A44E45B216889A524282AAB7CA2F49BAC7561AFE666442165589B3F2D4632BADC4CBD569C37F50F1847A6FD9316F583349119B9CF4005CA8449EE3A7D388B93730065D28B767CAC3E24E17B942B925D481599016BE6A386944830257230A6C6C9F536336B453BE8692F18138028C9841C08C425668372F1C245014B2AD6B8B53A259201BBDFF53866222A26C59FEA94CFA605A9768924B667B1EE35A79FC4540ED88CDAD60C65F6CC136846E85A7742A184B1744B41FBAC641526F11553D30491E34757C36C9038674B95560B6E65C7F473A0E812607E2AA5EFA159AADC1815C890BF07A3B5A71F43AC182BA43196A30C415491F2B6576F166164E63DA271BEFBE2065BDB8E2131006524B31E6829807088B6B893C4AB82CDC91690DB122D4005BF48ABB7FC53831B9D2B1CC295B25A70459AFAA18BE3B89D118594BB694093FC96C056B97648B1BE7A7094702133D7C59CB609FD1C22551A04B659CD4780B1BD4B88AF3446FE0A8B399C6FB45B7AE3724E3E37039641A7CBF71097770426803735E3CDD1B44E0AA5A301F495AC1277F05BA8AD276918A72A70E25444FCB22DC10A348608673A3E7697A9BE9728389944B3E818655BC209B6A859C33DA34652EE62859B0379DCAB1EC01743D3B23856271BE33A9DF9A53F24009D2AC24655E77E1CD49A1D5B99294343EA9B1C90C58A3EC69C10F2C8C2431A55D0B50338C8C0384D2581062E02840B9104344B159A0976219A4CD83C40839BA6BB13379FCBB529869C74D43AC1969FC47476D9F23769160207908D3763730FC6617263894F06D041743E54E78299698A2AE2540777C50CB01663E758C6750361053F9832B634119BDBC95E5A3385F1B6AE24BAA842330638E5AB0DC275AE2B2643A517692BAC3FA97EE4756AF87A56015682DEB4C236499B246201A341BC2D410D7DE972D44486E507205C722B3652667A1C51EC9CAF216592ACD9868BF6444A5B0FB15919938CCA416375671C372060529497C5F4057817B44F0DD9BB8CE36C8647B338306F680C536D1B3DE8613BB37673DB052D2A22853AA55698FC5994494FB7C4118A76BCD7589BC5951FB67AA19DB96406FCC3535804947DB39FD223C6A0D60E5536FEDFD6E888B259C08B49D631F4E7D6CD87A3FC689B64FA42685BF539A1899A10E025B55C3BA822E44CD5C81C43646846325992089351444178C13B6B1139F596F2454E73D0308C6F914119CBB54A" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "63B035F32BBA7B03DF80DF9F75E731C19D11B925C1EA7AE3E1CFAECC9D5E2734C942846A8563A41C2D666753168A3EF62BDF55A2FAC8CCE81ABA57CFD6A86946", + "CB948031F739E5203437E08F51A51B36D256D217C2838B0F265036D2D8905CE2C119273B610164662169070C01230C2B53CA8110F20339528D39F80B552C3A1B97224D410A45C69EDFF177077BA13BE85F018087742B9F81778B879768CCB5C193B827FCFB5FAC703416284B2F899FAAB8BFEF19A4925C28C1DB78DA1B0EF8229D8D0C87E082A50FCB143F914147395CC7C785DCC3C106FB5027EA19D5CA2CEC367B2AF8B24447874507BCFA450BA6F177C8C0910181CFBEE7A27909A9F9D943F88960EAB1A06F00B2158A67590A61D379381B40AA45992C72B18788AAA27B425EDF65228626A13218665E136C26484493F941F682C7E0C54D8E27A8F5A578C339435DC7C19379C9B7D74E3E246C91CC4484B4C7AB21BBB246C7614169833C52DCF20859CACB4902780A31A776B63E8AE62783333F0992C037BB48FC6059F28B4FE533874393B8127508DEC7A82C1A76DA94235B6875EB722759995C4713009C2213A5CC520EE88FC585B2F65A87C0610559FB01B819AD614928F00163008AAF08C5BBD2A0A7B23C1E00A37BFC695F078768D1F25E5E1B15E6F414EF5942B80AD0F6FA221E39C9FAF43ADA781BE24CBC32CB67D7F80417D433ADEA21F3401A2186BCE3244F85D1CB8F4B3DE70B5F256CBB316909D8F0A4E8B36DCC500C7DD52E70423B6FA419043B8BC912C6F532CEEC1954D7B254A909AFAB317E28C811863748BCC716B734B2C283C1B9B75ECD0457E9895CA6AA1AE427500E19A8174433A48C7B4C34AAABF3B6475C7C058994DF8C124D094685C15BA3BBBB79483E6FE96D1B050E42702AA104CB7AF984CD3063A2A9706215C5F102C47FE4C8D9089919C44C920738E29A0301F7294790B528320BD1C931553B448F9017F8C6493111A0111BC032394266AB495B6B24CC34379B140B36BCBF7127C404D803BBB5A054C3A45DDB265B75413AD9CAA53CAA9C50AB4802232F90911AE90C1F541DE25B6082214AADFC70B7B523A88C6AFDB26DAD38C97102C228006BE9988FB52377D10B429F53ADCFDA1D5FF5462D190B4FF9350DF18F14F17577F08142684F7CF815797B08296A6EC3750E4ECB1C88EBB0A0DA13DCC3BD0572A7C4C6915FF2562A5C021DD00A95F7AF97AC7066AC39A68B92B2294637214BA00A840FA74F59373AEC0C4BF718C038CC981196A053E0B585E2CE89D900879C69E92382D7EC175B1437680601D59884101C3E751A5BA61289749A1D6F6584416AC0CC896C8C476BA1ECCA58DC5E820037BC3B4FC4AA9687C9B49815B13860A836E50299441C6E76C7FD7676CBF004676CA575998EF37707D6A6007748334A1812504A0F7D239B997181AAA7232DC57D03C5197A3C1E1BB51B525CA50D890330BA74E23A729DE4622C368F2D5B74D6DC20D4402DC2958C14328B572570FBF3C4558494C252571BD6683F353D1F555EABB8BA69A80C9B148454C78E5AD40365082DCCF064E515A00448CE4826441C7C2EF97003114ACE871512CDE0697E62262DE59BCD7157049C311F3115628664B42876212B8496E4CA0C872D1D3B0C2A6752BF3241CB7664B5FA59382B6B5298750B79CC9A36CF41D56903F0C236A4B357939EF6BCB193D60C14985945672952DCA8DEFB41323467C81618E2BB5D573BC1A7C62C18F09B149566357C9802F9528E9C92E4F13BA6353D378C3FBD8C354D2622F3C41997A5C7D8C4B93CDB5C0B033D2D01B53510695842171D447302D49A86D9818D79B0598B9AF6062FA377B6B5761CFED081999AA26FF48890187D29D31D76B79FB2B9A7098B616FC7C542851F4D13CFBBC1743C8B75A308BE484224E6C29CC88640DAB6AB754A2A74992CCDBA1CAAD443D250C37D5B29066355DED76F32071690D69EEEEC2ED17ABD6EDAB10CE23E9B705AE359331F18042A1835E4250F72DB561923AF0A7B8D41A15E1869912568653412970DB48D80F53FD90514105B393D57A059B4621BCC1B46C919246C21248C7F815A2EC112C978646FA6CBA87E27444E83190130A12DDC57745679D3FC1C1F8B5A02848A120C03567AA75631232F02B064EB1FEE126C817ACC5A44A378D5A842C84132546721C24BC2D13C28F7961B200DE987CB5F2B283DC0CCD90A4AD6793BF06B84B4F91662CA08D2161FAD1B586C434AB3B05BAEB14AC4A8C5F1B5AF1C634E4E7C27A809C6A97DA27BDADC9C61247C2D78223DF2CB405707CE", + "5CA5B97968042A26AFD752C9592920D80BBD10EA10AA95B51C91C666FB4FF4634DF07073F12B8952AA57BFA0A709978C18D96106153D1C8B6B06ECCF3D5918ADDC8E91627F1CE8B4FEDC854CD750CA7B8384C0B3E5E3B737447090A1B8B341AB228A4C52C43A5613805C6A431D63938F5C568E010EF53190E438C249242D4AD16F2222B82018175E614CD7632132C021FBE8747351967308649363BFE15362B6E27E40783764D31C92354E43B828EE0B9DC5ACAFBB7829E52B794C02BC6615423310A8B895625B0AAD1442290EE3B852FB5728463887C6589205947EA9625215ABC5ACB0EA6908405088F94B6FEAE953FA972BF651228EC01DF73949BC47B5456C8BC574330AD40AE9DC3ADE82020DD70A5487462DD6497B065B470A828102CD8178324C68B790295C962232B445CEBC412C61F512435C80470A083013A61F16961F8CAD33B6984AFB6183A5A3F1041094674A36FA698433A8C65C4F4F0CCF413A571FC115DCC13352084607B92976977FC219B975E89D08C66524974FCC5692F28BBABE2C2A4B161CBA401858610C9D950D0946641AA54BA9506D98C82C6F88B6155A2E82132ADFF58C21586CBC75BCA6EB2628F96E59B1AD3981B4637C30CDE5B9C97BA201C3789D750A059B10CC52376A16CB481563D52B59BE36138C4B8564575871120793AC26AD37C7F4D67DEC465249DA00D9B5089A72C7D0634D63CB6CA2D38049903FB213C53AAA7CA18B69BD6BAAE31345666497F4079C2ADB91D5E211E7011C46B7435B1047347BBDD49C4E0F2C90CDC6B3EE6AC2226868CA5C851CABCDDE13109F761FBED51240B876086586900A071B3207A081B1107B71DDE09910F58B5053A7E8C7C035B7577EE400FABA27523B82C5D06268240B10F68C9144928718C74BE2B9AAA192A5FB14E510452CA83A31C1474F9235D7995310E3850B470D0F52BB16F46073452F9A41814D0000E6652CD9F08D9555540C6BC629E74AFE96AB26203B1AC4389D683788D68A2F91A836B68181145A3F661FFB34A97080CEE3C38D74B3BAFAEACEC0FBCC3010C317AB29E8D6A296153E2F039BA9E033EB2C132B40BD9BB65D293B88D21290DBB19482641E3B9A6F6E048F31B92578D035283C9C795884A7CB9C2A04A65CD85607F75ECAFC6168C4885D521B4039BA30EB9BFEC0602D42707B73C211ECAC5FD95BA5420BE207BACE86172470A61373BC6BF2ABDED5563C4CB4EB71C83C0851177575DEB6054C8A2CB4F70C5A957A4E6B5BBE9B72D3296A6B8C6EE2E9BBC404B463E8C6C4C7680F84A5A76A1913CCBF71944CBB6210338578E108928711B5B92A0D29E01C37E2BD86D740E41311AD71B3EF5667081A26913057BFC8C04B03C3C2A02EDFB3B07874170A19C6682276E8AB4EEC7B9B6CF05398F9690F72424952C65CFA16F5749DB9B73B3DF532305C653AC5945E4739EAD3CC167B3CA5DA2B3B42B51ABB1D2C9980393A7856926CFEE867945BC97CB88256864181A04A7733CB9D16CA12BABC3295973129B4B9753B3F42C20B26BFACAA0A0B27BF79918222F895E68A83B531ABD183296466AE2316BFB3ABB6112AC48411A5B9A5226E4AAC22B0490DFB1CC3206C312514847BB0417B3A08B85D60787E45463FC283A121295562D0378FA75CA45174D788CAEF59AA4C629973E2B6FB069B5AC373406CBD85675539470B111C0C654947D7E1CBB62067710C0EE434692394278F05CA421AA05A52C77558CA98199AE2E93771A91C5F4B350A9151B1268F87EC997FCB09F4325C9BB8CE869B59724BC6B6905755F873435C63AC50B0F570243DDA64DC3588DFD090BA4A521AF08D9543C217762BA89722853185E18399CDB42856445EED69012AFAB4F7EA55038B2AAE26CFDE4ABB829279FC5A311199C14908482288CBCF519065A74EDADB035AC0064643C1C89829F6A9589DEA5C19B82811A086CA76A688CA5655A47C2B55AF0CE9129AC9A8503872EAF920E01BAF9D0681E8D58F5787C41C08663D725400681865B2CA1DB474D591599C6C2D925A8109E63A88E095A05C6EB44897652CB00376061C07857945B7ED07B1DF363A5F2581BC416678138C488B6BF2FB74C6800C216AAF02971FAF18978549624B356F2086C15391C949367DEBC8C32E64CDFAA116903007CC284D5D9BCBCB948031F739E5203437E08F51A51B36D256D217C2838B0F265036D2D8905CE2C119273B610164662169070C01230C2B53CA8110F20339528D39F80B552C3A1B97224D410A45C69EDFF177077BA13BE85F018087742B9F81778B879768CCB5C193B827FCFB5FAC703416284B2F899FAAB8BFEF19A4925C28C1DB78DA1B0EF8229D8D0C87E082A50FCB143F914147395CC7C785DCC3C106FB5027EA19D5CA2CEC367B2AF8B24447874507BCFA450BA6F177C8C0910181CFBEE7A27909A9F9D943F88960EAB1A06F00B2158A67590A61D379381B40AA45992C72B18788AAA27B425EDF65228626A13218665E136C26484493F941F682C7E0C54D8E27A8F5A578C339435DC7C19379C9B7D74E3E246C91CC4484B4C7AB21BBB246C7614169833C52DCF20859CACB4902780A31A776B63E8AE62783333F0992C037BB48FC6059F28B4FE533874393B8127508DEC7A82C1A76DA94235B6875EB722759995C4713009C2213A5CC520EE88FC585B2F65A87C0610559FB01B819AD614928F00163008AAF08C5BBD2A0A7B23C1E00A37BFC695F078768D1F25E5E1B15E6F414EF5942B80AD0F6FA221E39C9FAF43ADA781BE24CBC32CB67D7F80417D433ADEA21F3401A2186BCE3244F85D1CB8F4B3DE70B5F256CBB316909D8F0A4E8B36DCC500C7DD52E70423B6FA419043B8BC912C6F532CEEC1954D7B254A909AFAB317E28C811863748BCC716B734B2C283C1B9B75ECD0457E9895CA6AA1AE427500E19A8174433A48C7B4C34AAABF3B6475C7C058994DF8C124D094685C15BA3BBBB79483E6FE96D1B050E42702AA104CB7AF984CD3063A2A9706215C5F102C47FE4C8D9089919C44C920738E29A0301F7294790B528320BD1C931553B448F9017F8C6493111A0111BC032394266AB495B6B24CC34379B140B36BCBF7127C404D803BBB5A054C3A45DDB265B75413AD9CAA53CAA9C50AB4802232F90911AE90C1F541DE25B6082214AADFC70B7B523A88C6AFDB26DAD38C97102C228006BE9988FB52377D10B429F53ADCFDA1D5FF5462D190B4FF9350DF18F14F17577F08142684F7CF815797B08296A6EC3750E4ECB1C88EBB0A0DA13DCC3BD0572A7C4C6915FF2562A5C021DD00A95F7AF97AC7066AC39A68B92B2294637214BA00A840FA74F59373AEC0C4BF718C038CC981196A053E0B585E2CE89D900879C69E92382D7EC175B1437680601D59884101C3E751A5BA61289749A1D6F6584416AC0CC896C8C476BA1ECCA58DC5E820037BC3B4FC4AA9687C9B49815B13860A836E50299441C6E76C7FD7676CBF004676CA575998EF37707D6A6007748334A1812504A0F7D239B997181AAA7232DC57D03C5197A3C1E1BB51B525CA50D890330BA74E23A729DE4622C368F2D5B74D6DC20D4402DC2958C14328B572570FBF3C4558494C252571BD6683F353D1F555EABB8BA69A80C9B148454C78E5AD40365082DCCF064E515A00448CE4826441C7C2EF97003114ACE871512CDE0697E62262DE59BCD7157049C311F3115628664B42876212B8496E4CA0C872D1D3B0C2A6752BF3241CB7664B5FA59382B6B5298750B79CC9A36CF41D56903F0C236A4B357939EF6BCB193D60C14985945672952DCA8DEFB41323467C81618E2BB5D573BC1A7C62C18F09B149566357C9802F9528E9C92E4F13BA6353D378C3FBD8C354D2622F3C41997A5C7D8C4B93CDB5C0B033D2D01B53510695842171D447302D49A86D9818D79B0598B9AF6062FA377B6B5761CFED081999AA26FF48890187D29D31D76B79FB2B9A7098B616FC7C542851F4D13CFBBC1743C8B75A308BE484224E6C29CC88640DAB6AB754A2A74992CCDBA1CAAD443D250C37D5B29066355DED76F32071690D69EEEEC2ED17ABD6EDAB10CE23E9B705AE359331F18042A1835E4250F72DB561923AF0A7B8D41A15E1869912568653412970DB48D80F53FD90514105B393D57A059B4621BCC1B46C919246C21248C7F815A2EC112C978646FA6CBA87E27444E83190130A12DDC57745679D3FC1C1F8B5A02848A120C03567AA75631232F02B064EB1FEE126C817ACC5A44A378D5A842C84132546721C24BC2D13C28F7961B200DE987CB5F2B283DC0CCD90A4AD6793BF06B84B4F91662CA08D2161FAD1B586C434AB3B05BAEB14AC4A8C5F1B5AF1C634E4E7C27A809C6A97DA27BDADC9C61247C2D78223DF2CB405707CE9B7B4C274E7EA8E6CD809CE04CBCFE7AE2819CF54D17112A53DD790D30CBC912C942846A8563A41C2D666753168A3EF62BDF55A2FAC8CCE81ABA57CFD6A86946" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "2099CF585476FC3A3D96811F628042BF5ACE4DD83533629A575C2AF9C89C51E8EA0332BC7444E0E1E84DB4873221A7811FDEF6AA2609985256449D3457E487F1", + "D3D89FCD677A508625AC0874599672D730CE62C4A4D59ABB53F7089644C690C351EBB8001B36A7B00C3866E0774741CF2C1181817621577B6D52B598814674A9DABFC8AA54A3516711696A72654817B4150F5337985803A346432857249EC01877796B9F7C9EC6D1CD3FC39B9527750D692248858EF1B41C550751D1CA70CD423B8172061FA3658178A5A9B163EE58767BD8B5216C38B9E0B21A6C6434E971D156AE6B2143A1E270F556814D57991F41814405521A07852C49C1DDA16416E7507B943FB0492C9091810D3090B6322AAB04A35F7653D89136B7D55F797B31DFEBA5A0C01053FBB10E36743A5B6DCBB16FF01ACDBEC29CDBA1947E6CB8F783B60447C4727B6E8EA9662E03066D5620309240958AA85080299A035F9D447ED7F70E01939F98BB2E79EB08A93760529728864BC70B595ED6CA545C818BEF2C1BE48C64491423C4038FC265BE0C4760D4602A5BA187D93B8360E7B979716020016B1B13A4CEC9919AB2251F602D70713411322A3B2CC4B25BCF65787A0D881B68749AFE33BF4C51C4B256B964B038E5A80291F3360A758AB8F36122845C4965B9FD4C557FEC96F5436909986534963E0D43116038A4199009335417D1C44DD021C0E6759B0B47355920B54BBA71FBE335FC18CE9B6914DAB69ACBF312B415A2C620A6A3600437B333F50A7F7FE21FFF2C6098315DB5703F9878BE0F11B4DE952E8DB70A2C700F6EC598FCA2CBA4E635935C13F23932EFE4CB8ED34256641EDEF534DB951E96FB9DFF4C177E0A9CC71A448087AE0B88C619C78762F7C915671DB13212E03C3234A2844BB738ECB6034EA608472518B9E21B60AB8F3D0B73217191594700E2E131B726185FD846FD235586BA6D64A76E3F02A56BB5CA8C3B68FEC4C418E233E1B1396A63A5EFE6B55A9CB34547C2D8EC5ADFAC977C72714C63B6DE9962AD7B6766E82350B531E59C9FB3F53B7D4C74EDE30E9BEB67EF1A5660EB7BBA97476A32BC7989853BF72DF42AA9ED79AF3C52943B80397882CF78FB077D5131C927A21065568F3AA18C8B7D94F1A95FB0824F74883345CCCCD354C4215F1BFC6AD8A26B8DBC2FDC8A046983CA007196E793286F295A98F98CC402C2F8C4B493CC7008E00E12B27DEEC2596CE01D79F32133B9384434164E65C843984945F609E7877C4BDA02667592424758465B641BC16636904FFF2CB4FA249A3425BECA5841B77A785A8424C4A39DB09CC61C20B2EC6139A01B2BB527A12A7C9DAAC236BBC53971E7CC1538395F104B46D6929B02547492B39B6250EC27153EA3BB5A74548F82AF1FF36CBC2A90C44A204E9353B9B846421762BE7621F7D907C74482767C2330FA2FECA8149BE75C94A3A2D63C1B57539C4BCA4B2841AB58E1A663E594B0D3CB870905F77C035053A85B4557F8500EB31BAD6DE37D50915E143914702409679971CA2ABA66BC71DFF0B4ACB484D8042D12991A48675BD3F324E7F8633170360AEBCAD8C271BE49BC7A537691E1129357BCEFEBAC459B35D28B16F98188B93B37E647B69DFC865AC5513FE11DFC430E4F6980C9D8C8CE8663445784FA8630E31CB1EBE188BF8370507A8150B5C7DCCC6073A623467ABF6C1649B50787AF1730CBC48680650B40D32978C05AB246BFFB81552945B599139297BAC8494013C3BC6BE74CAA557597A038AD65B918312953821972CC67AADED086F69C9F5CF43D1B67CE1D33B3AC356179784E9287B18B65A25C6200A9E495FD625957C1C6B8CC138AE052C6E31D205888158A1FAD111E44E390951066C16717A7793D897C4D0A5959C2B500774B715031116D62939A3C4AF815CBB3B74CAF62311C73908173242B19C4A33BB050E839A3C670B5E56B1D390B13089E71B6006C1AB2522B186217CF2C6204B2C8487B0752EC3144BE237BB9764B79BB3B9A5195E7A511264A16B6D6AAA9F289656CC2CF70AC6D74C79D739D61A26836A5CBB484667879A0490CAAE504B3D631CFD053463FB529251125E2C7550B165D6449BF2FB166F2C474133781097CB37FD8822B604D6C7226C2C123AFC35B93A402C28C594F4517FA275BD3DC634931148D9C3BAB5A6F4C4B33C6373D34AC98C901AA48BCC273D73C60F3727FAAC6410C692DF7CAD3E29D134793D314518C71A03AD86C35E739E5E24976152B16CB5B59F860992DC67B982C666FE170BE8E3AD863830B8CBC26AF14C76DC133", + "6B661ABB9229534CCD645C86CC4A663EF62251D871AF3564B97A2BFBE87D7A8B0440A059FEA26EEA9B3BEB5C405C6B086CEC80FB953CD158C4FEE3013753819C7C2924F230FDD3852FD91537A209C2A36818D17073186069887A7B59428670009B49B52A23CAB5258B8848867639B236E687A64868EBD081E9212953B0173C8117C845AB83C7612AE8C7FB25AE8FB27C39C042D0E9A52BC75F19A76C3E0734D2B263D43B1107706CB4CC33E7A4B45F566009BC31E12B3400A4B55D36A267179C9105A8C6D077F0B82D282374BB2191735BBB8F674B606CBBB0975149DB5AA3AC91FB2BC4A89457F7F4A841A223866145FE6A451E0CC878B2AA1D67B97E32631E981011B1A188B54623B6183AC465733A2110DA30C381C0B235AAFE6C9FD5A0CA12194BF4006ED6BC59B2F612A19420A9D196A36003C7898169831AEBD68910C60823F4C6A100414A4603CEDA9CAB5929E739B81489B2C7D39E08B590699702563917AEBB75F572284F352AF1D2BE6CB58AE29A068E9B180DF14BD285437549BE03A9108D09BB75B5274506CBE8382406551236E6967FF66770F65BA1645AF7801409C80E7C51803E579B78FCC3A5D4A9BDDBB7A022228E682280115969122C44E352CE029D27BA29D363556F209014F772DA871B093291506A5AE2801731482A8C7B37D55564A84508E668C1AA9B1FCD9BB7F1666A12F6063C61B3186A6F81901AB85190B55664F52421AAA85833071056E14413B348BEB7C4923900B93CC863B17B4B063C46B425F2741884BC0032D16B6FAA3BC6D8CD5FA6CDEB38C6D9200F90216B412650302CAB09E2240A929B87639999C9663836B582FAC46E64873C0CB218D635EBB7188518C599EB0762F875BED0810A7114DDAC9A77B26C0FA03440D6692E8A64A38B6DC50B11F4E67FCC2861241A2B502756FED20790996113BB78B55CA1D1E57138373758D084A8D90343A85A900C43B8F5B7E55C2058ACB5DA8543B1D506B07277B2904854434CF0B86063F470D7961F4E570F6F902C95B3990F3B1603D295F58C5424E6A285C1808DCC40E3E851EB2635C7EB9A2CAA33AFCC589AFA8188481E3823724AF21B995B32D2432F9B6CAC1CB52463185F941112BC4B0A804135B99156E32A8D2A9383149187BDF65DE02237C2771B61F2B9DB7556B6E628428419116437AD899E12B4721CF5878D725634728EAD9A672FAB2286B0CEDA650E23E165D05A3EBF42141EBB6F0B9B598681A05014C3A8050A13D080A0D4C592DA58C94C8A4AB6039BE5ABC4F04E568087886C54F79977AE9A159531644D3358055110F0CC4EC90919DC60212D7998E592461CB70BED17BAFBB365A9C3228714CC0F761D47C93DD0A26DBAF02654174D4E1C300A538A89730E9F2747F2F421E336C9B62A89AD938923A3AB2A47C57C3B6472948EF2F59AFCDB8537055B43F80F01037F6B55C9F9CB31D3A864365175A9CC29ED4B5A5F9AAC261A190B82ACAEF36C70B23ABF66237AF34EF5542B983736FA7117AB650C30FB4D5F51BD0FA522487581DB828E8249469DEB2F81B97A9E925F4BA69C5E4681E29BB38D1ABDE1583F456BB60ACA548A5560B42A9FAA66B3ACA1032343C18435C964299608B7722F319522632FF30877941187145C0C242919FBD458EFD8380879742B1B10DE43ADF9E9A744677C6C942D896040D38C80F4D305560C9BCE4A00BE8394040C5508CA5C09543325709B269BA67507BBDD64667EBC4AB8655A9C735FEEC51CA966B20C5C0DF3D13D2A559D55E2BD6B2740BD3510A5DB46088B4F4EA49E45365B084139986B080F0B26FD47CD0C3A589959433072888D6279B4FA296A761D2692252331A7B8F7B3B239ACB9885DD8BCC1BAD76A025733F0BACDACC50EC8E7238B2B5BA8D04D699297B9C9658B0063D372270FF5AAC2020CDC52460B65CC2F3C9C7A814DB7179041F46ECE8523DC21AA6B3032F354275E27521EB276D8699476746D5C96C25DB4615CB02618842ED7983DBBDCABB4101EA2316761999A62905C1852A6CF7CAD5FE21D9389AE02D12D4672C668B8231F502E5E6C1349D942E169069C6963CAD084A717C7CD2C7D57245AF17101F7146CB6E12DFDF2401355AC098A044776B7F2583968B4A8FE74BB9706803F0B57CA46A524A0A02461167B936F761577D3D89FCD677A508625AC0874599672D730CE62C4A4D59ABB53F7089644C690C351EBB8001B36A7B00C3866E0774741CF2C1181817621577B6D52B598814674A9DABFC8AA54A3516711696A72654817B4150F5337985803A346432857249EC01877796B9F7C9EC6D1CD3FC39B9527750D692248858EF1B41C550751D1CA70CD423B8172061FA3658178A5A9B163EE58767BD8B5216C38B9E0B21A6C6434E971D156AE6B2143A1E270F556814D57991F41814405521A07852C49C1DDA16416E7507B943FB0492C9091810D3090B6322AAB04A35F7653D89136B7D55F797B31DFEBA5A0C01053FBB10E36743A5B6DCBB16FF01ACDBEC29CDBA1947E6CB8F783B60447C4727B6E8EA9662E03066D5620309240958AA85080299A035F9D447ED7F70E01939F98BB2E79EB08A93760529728864BC70B595ED6CA545C818BEF2C1BE48C64491423C4038FC265BE0C4760D4602A5BA187D93B8360E7B979716020016B1B13A4CEC9919AB2251F602D70713411322A3B2CC4B25BCF65787A0D881B68749AFE33BF4C51C4B256B964B038E5A80291F3360A758AB8F36122845C4965B9FD4C557FEC96F5436909986534963E0D43116038A4199009335417D1C44DD021C0E6759B0B47355920B54BBA71FBE335FC18CE9B6914DAB69ACBF312B415A2C620A6A3600437B333F50A7F7FE21FFF2C6098315DB5703F9878BE0F11B4DE952E8DB70A2C700F6EC598FCA2CBA4E635935C13F23932EFE4CB8ED34256641EDEF534DB951E96FB9DFF4C177E0A9CC71A448087AE0B88C619C78762F7C915671DB13212E03C3234A2844BB738ECB6034EA608472518B9E21B60AB8F3D0B73217191594700E2E131B726185FD846FD235586BA6D64A76E3F02A56BB5CA8C3B68FEC4C418E233E1B1396A63A5EFE6B55A9CB34547C2D8EC5ADFAC977C72714C63B6DE9962AD7B6766E82350B531E59C9FB3F53B7D4C74EDE30E9BEB67EF1A5660EB7BBA97476A32BC7989853BF72DF42AA9ED79AF3C52943B80397882CF78FB077D5131C927A21065568F3AA18C8B7D94F1A95FB0824F74883345CCCCD354C4215F1BFC6AD8A26B8DBC2FDC8A046983CA007196E793286F295A98F98CC402C2F8C4B493CC7008E00E12B27DEEC2596CE01D79F32133B9384434164E65C843984945F609E7877C4BDA02667592424758465B641BC16636904FFF2CB4FA249A3425BECA5841B77A785A8424C4A39DB09CC61C20B2EC6139A01B2BB527A12A7C9DAAC236BBC53971E7CC1538395F104B46D6929B02547492B39B6250EC27153EA3BB5A74548F82AF1FF36CBC2A90C44A204E9353B9B846421762BE7621F7D907C74482767C2330FA2FECA8149BE75C94A3A2D63C1B57539C4BCA4B2841AB58E1A663E594B0D3CB870905F77C035053A85B4557F8500EB31BAD6DE37D50915E143914702409679971CA2ABA66BC71DFF0B4ACB484D8042D12991A48675BD3F324E7F8633170360AEBCAD8C271BE49BC7A537691E1129357BCEFEBAC459B35D28B16F98188B93B37E647B69DFC865AC5513FE11DFC430E4F6980C9D8C8CE8663445784FA8630E31CB1EBE188BF8370507A8150B5C7DCCC6073A623467ABF6C1649B50787AF1730CBC48680650B40D32978C05AB246BFFB81552945B599139297BAC8494013C3BC6BE74CAA557597A038AD65B918312953821972CC67AADED086F69C9F5CF43D1B67CE1D33B3AC356179784E9287B18B65A25C6200A9E495FD625957C1C6B8CC138AE052C6E31D205888158A1FAD111E44E390951066C16717A7793D897C4D0A5959C2B500774B715031116D62939A3C4AF815CBB3B74CAF62311C73908173242B19C4A33BB050E839A3C670B5E56B1D390B13089E71B6006C1AB2522B186217CF2C6204B2C8487B0752EC3144BE237BB9764B79BB3B9A5195E7A511264A16B6D6AAA9F289656CC2CF70AC6D74C79D739D61A26836A5CBB484667879A0490CAAE504B3D631CFD053463FB529251125E2C7550B165D6449BF2FB166F2C474133781097CB37FD8822B604D6C7226C2C123AFC35B93A402C28C594F4517FA275BD3DC634931148D9C3BAB5A6F4C4B33C6373D34AC98C901AA48BCC273D73C60F3727FAAC6410C692DF7CAD3E29D134793D314518C71A03AD86C35E739E5E24976152B16CB5B59F860992DC67B982C666FE170BE8E3AD863830B8CBC26AF14C76DC1335AC099397D349D4905CD9081AE58EF16328056E2C00D4388B6CD5384B293226EEA0332BC7444E0E1E84DB4873221A7811FDEF6AA2609985256449D3457E487F1" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "920CD04F4025CF0E9F7AAF57A072044BBDB019DEBF962C944556272B2CD97D8C5DEB0C8D7F930CA124AB843003C42115EF6556C1380D9F9F994FE24CC6F4BA24", + "9118055AECB6A9E302E3149655F93B58B4C96717694FDB6033D53644748F2DC288FFC2CE00C74F537079C398AC83177F35038770C7946C77260B81B53874B0C9385CE4ABA2F0562BB457774C1C063020B5C90682D5722686D4A6BDB70670414E092C8D949B6D28AC65EFCB8DAD674A72C658B8D50AA5F23A0D83CF14A8B9EB697CA2C96F48063025FB1CA05593C2ACAA68DA7FE472CFEC139EA3BA3F673612907B12B049B76A086F28D87826E82662327E85989C7A04A4F4F3B80E374BE97B98AF205A0698AF8A4528680514366921094849E697783BA1739BCA3C3960CF96B32E59229C8F867FAAA841320C030443797D8B9A9680B87966BA59E0B76076CAE6E5712155304D6B39CA36C757A69F7C41719C1044BFE683AEF0A6C314C34E96B16E38B895F1011E6C4F992CB67BE31E7E6B8F51566876CC71BB8A3F35D722835794E3C87E163CB6AA46B60205BE9CE7978DC7A88A723FDB3921F48A6D439784C3E10195D62FC183ACD785613FE213242B10CC37047D5414F0BB1DA6726716E964B7B2486DECBC127032888820C3E47C96FA2AD269B2B480B330816B1CA50C1589613CA292A2326BDDD627D721CF3035025361495A589696298C8BF90A0915AAD0E52C988A41548365DC743BF5B29FCCC5292DBBA64FEC43C4AC5B9484B7513CA31CB470B2E07BA7A5095B7906BDD46D8BB4C660317AFC903C95C549ED7868450355B69AAE3CB414AA002B91AC777B1B8C18F6771F396AB8F9003FF2564D740825D327DDF971E3B938C8B38BFBD856D3610FE2B01A2E2BAA3B46AAFDB3501C033B845B2545D6BE406008EB489E0C6A1E3FC179EEE02F593A9242B42D23D0001E042AEDE15103231E6DA090F4BB799E8682E488A1D9E5159CA7CFDA2669A7D805E262CDBB9A835CE442955076C1164ACFB5237CD9B4AD011155679578651D6A286D65EC07D0603CA5B2715A998E148C5B223086DB0765344A58DF2987B2A35F7C592B68D70413840CF844A23691BEE947B3C86AC275945D9481A70C14A164E20AFC1B2D373B5692847E0C12A84F99CAF4CB703430840617C0EB69B4653200DA2A66E2B733F0DC11D554506FF3B655BCB4CFC22CCC99B31DA9C77B888FBAA43D1513B229E7CF423C1611A42A30BC974773BA0AD0489F873D66AC3426F3290E11B3FB863BF7623F151514910BA322B8BBDDBB9DBE09AFB497933FA092AB1AA6E6BACAF7D47F28910087063E4B993016C7618EF29017A52898E63D23D66638E65ADC49680DD1C31565B929CB54F5AC7749FACB3675AA028B04A0F4A00B91BB753A96A2777CA6866DA75079EAB7456FEC74BFAB2777E8B630563B7F5B2788775D6D733373D27FEDC3566A1B6196F11E75D6B2412599E30733C4CB7009F7B7DA1359CC196193F817420C9AF89C91CC097F730BC7478C1FCDBA3BA6F095D7D1B99166B0DB92B71E451301C41057EA82A6CA1A613A425639BADA7435211731F484961E985992B199BEAB3535277FCA16A9ED0391B0277CE812355867395BF49597499266B2A05841BD7FC8BC3AF7A84BC11C1F9C2D267676FDEA2190C14B14036787B41564F4896890160D64BD50751B5431BFE156ACE9D222F3688D66583B9FD837DBB87147271D9B025B900C9136804A6F2C36F910630E769CDC1A4FF4B0044DCB45E725ADE26B9719269F49C43DD4A96A43EA86D6A91AAAA123350552AC512D2C6A37C04BACF4E27C89A49CA0A1BB106903DEA4882771A3A48C1F40256348C1B8E0F5844442C63E0BA6A17555218325B24B196BD52443D23B4D82BCBF243DE32BAF1880B9E1410A1F803B82D407301C12ED5764EB284CC1185B64D00151CB12B95C6248A92C04F47D3C22336455685EFC4441B67D63465408C90EC3E04C71B565D8D32C3D88411321C0D72A9C1361BFCE78CAC0602FA93484AC17415EB39AFF8B6A8BB0CCAC59AD7E59C6CB2656F4C5499DC76236C37799871CE6C03EFD659CE43655BDEB90D0896ED0052B857A5EED0B11886070AB32990B343B0A081B517C0714866D53CB482EDCBFA053CCCC070967F3C10304B30C80C659D2438BC95C471C7336D6C86BC595B0F89025A646619AC533E727B93BA353B28C5C74984BA0A690082391F40F63098D63BCCE87FB61340C9DDBE708B436771798BDD30314622B52F473C8FCCE991E48ABF56753BC19EBB31445317F5BA3136A2653D43B28ECA455F4680E", + "2CBC31DEE3B466838EB0969AC5EC0F3760AF448BA588F78190246CF5E20331E15C047BC9B34690009DCC58FA410967A587369E99F05BB066A603361F1CF17A9262219A206231E8027B05C7DB550A7F9BBD90CAAC863934C69222EFE9C5E71C970756C028EA249E81628FE925719141A2C0A9F1C9CFD09C0503CC0DE9D861C5D668FD661AFB6375F5124F1E2312C990999825CA1862373E567B25F8B1784131F607D0AC1926346A4D6992C6CD268D0AE5169DC5AD33E82202C91B643A0ACB334B2C362252746A23679D90386178DA3EFEC9463C5C627C5B5DEF98A601871D97C64810516F17FB266402CD574A3C4BA6492E9987E89A7C8E4342AF00A4F64CC5773716BA45B6BBB6AF3769467C40CDD2F32A4CAB0200879C658780602B91AD399287F37817082CA686C314327BBCEA46F815629A332128D37CDE78CE6B1A1E9C1B83581ABB7F7B5332252D5C030D5E965F15D52A605400ABB96F1FE3759C8201C45C7B69C35B0381464B10573D7A7FA5643222AC1A9F3737D81445F00B7221A80254FCB742A1A504C19E35498519A66D1F6470B699998D61AF3ECBA96FB598D70511A680AEFE589530417EA88B49ECC190D62530FC209F5028569570A749C798D1B78AD990942D8A208B554826CBB287B3CC9EB255ADDB9A8F10B140F161BFE3123D32914780A20CE26F6A9912A50968FF9710F4E5118C151E1C86657256956DA414D4FB68F1DA378D9083E1A3537D10432F46AA9BC0CB4FC8A03BE06242B5C78DC7984FD7B577E7A2CF01A6668B09A3BA363DA594507B3A01CA48E7645220618286D8BBE1B6AAA2F22C52161A5D05480E51BB3F5095DCC85590A7CD8A19B74D9B3BFB3755119CAEA5A26BFF9CC436F7BEEE3914B1C827641468AED1B128A292C885A03323AB3A2C0A792413DB5605D2FBAC1305074C8981D919BE97B0690F59528628A200F8CFAA60C55A245297C1A6004518A6F6311174C9A42A8C8C908A98574AC7907744546A77361C487531ACB9544FC91DEB3B5A18AC6F26CB3CD4E63CEA36C478A50373A9A0C6A07CDC936D2543800975CB9E02A63B763297E727C7132CCBC11E78E23D7A8745C5C361196437D47A287E6641C81B8A4460716FC868248666005B5340E94477EA6185219171C53E651554D42C9B410AC29A601A416BC564657079E77FBF853B72B2C332E384AF210E33E4084F29AD5061068C7621F1008823F646F7A62EA22114F5D29C38216B311424A593CA1DC537FDC59DD7B6CB6C17480478B6A2AA6A6DA645702429BAC043D40304DA374CB2FA532BF5B545F61126FB3174E8C48707554FA5529A0B00495A236F81CF646A4055D7A833FA995A8325B07084CAF98DAEF8A566F591CA347EDAA84F64B519D7B671A94327E1D77AB3036C3EEA3FCAFC50E5BB9BF8497F356B5FA0C448E90356455B4EA9B44AC0FC5B16E961E3033D7A244043FA9A73E8BEC8C53B75C0C64F10BAE052CE42E08EA8C0599C049097613EEA9B2FDFE73529D765EA4285FDD77E8F2447ABFC62563814B47B58754261F7DA7054FA0A2FC00F90B226A6813CDD6875D1482BC5DA357D432C4C56CF6D3BB1E0AC96FEF784257A994C3C662B026EDA3A92A7376A711C25C03A07427A70FE63244755BC3E872988D4805EBC2F2B0B7444FA9D38E20F96918B82E644767A4FF4BB378FF2C17E01894F0C0C59B48B5642938A109A9D600236EC51FAA47425B433E185791A98B62C899A44043270C29302A3C40C43B2AC7B6BF0735D4D798945588733B792ECE7B019A9917A53C08D933BF228672AD9B87EA729E9A959F8825577C35616C06349441B60109F734B485CA62E08017BF9F455356AC49AC36C00618F9C7AB40C58049DEB92BFD85A390481AFE526A8024A345655F7CC0B19A812C48B41AAE09216D18ACA9652C814084991015C9059C68BA5EAD90707B49F9FF40C9C0460F4F350A3966CC2007EA6705FC33B22A7A78DADDB76684A507683B864705A00BA11382142B37BB9FB473AC3466BF84A81673B21CF8C6171607A4EDB34F466CC6A9C430CD8AFAE2B3AD1144EFC754A0823A38265CA3869989C60BD83729C31CBCB33D970EFF2C6A79664D9736C5E9762DDD9BDCDF54D4961B881B35355298A42A3753AA5227E3865B2E6832097A6EDB923BAC597B170766625419118055AECB6A9E302E3149655F93B58B4C96717694FDB6033D53644748F2DC288FFC2CE00C74F537079C398AC83177F35038770C7946C77260B81B53874B0C9385CE4ABA2F0562BB457774C1C063020B5C90682D5722686D4A6BDB70670414E092C8D949B6D28AC65EFCB8DAD674A72C658B8D50AA5F23A0D83CF14A8B9EB697CA2C96F48063025FB1CA05593C2ACAA68DA7FE472CFEC139EA3BA3F673612907B12B049B76A086F28D87826E82662327E85989C7A04A4F4F3B80E374BE97B98AF205A0698AF8A4528680514366921094849E697783BA1739BCA3C3960CF96B32E59229C8F867FAAA841320C030443797D8B9A9680B87966BA59E0B76076CAE6E5712155304D6B39CA36C757A69F7C41719C1044BFE683AEF0A6C314C34E96B16E38B895F1011E6C4F992CB67BE31E7E6B8F51566876CC71BB8A3F35D722835794E3C87E163CB6AA46B60205BE9CE7978DC7A88A723FDB3921F48A6D439784C3E10195D62FC183ACD785613FE213242B10CC37047D5414F0BB1DA6726716E964B7B2486DECBC127032888820C3E47C96FA2AD269B2B480B330816B1CA50C1589613CA292A2326BDDD627D721CF3035025361495A589696298C8BF90A0915AAD0E52C988A41548365DC743BF5B29FCCC5292DBBA64FEC43C4AC5B9484B7513CA31CB470B2E07BA7A5095B7906BDD46D8BB4C660317AFC903C95C549ED7868450355B69AAE3CB414AA002B91AC777B1B8C18F6771F396AB8F9003FF2564D740825D327DDF971E3B938C8B38BFBD856D3610FE2B01A2E2BAA3B46AAFDB3501C033B845B2545D6BE406008EB489E0C6A1E3FC179EEE02F593A9242B42D23D0001E042AEDE15103231E6DA090F4BB799E8682E488A1D9E5159CA7CFDA2669A7D805E262CDBB9A835CE442955076C1164ACFB5237CD9B4AD011155679578651D6A286D65EC07D0603CA5B2715A998E148C5B223086DB0765344A58DF2987B2A35F7C592B68D70413840CF844A23691BEE947B3C86AC275945D9481A70C14A164E20AFC1B2D373B5692847E0C12A84F99CAF4CB703430840617C0EB69B4653200DA2A66E2B733F0DC11D554506FF3B655BCB4CFC22CCC99B31DA9C77B888FBAA43D1513B229E7CF423C1611A42A30BC974773BA0AD0489F873D66AC3426F3290E11B3FB863BF7623F151514910BA322B8BBDDBB9DBE09AFB497933FA092AB1AA6E6BACAF7D47F28910087063E4B993016C7618EF29017A52898E63D23D66638E65ADC49680DD1C31565B929CB54F5AC7749FACB3675AA028B04A0F4A00B91BB753A96A2777CA6866DA75079EAB7456FEC74BFAB2777E8B630563B7F5B2788775D6D733373D27FEDC3566A1B6196F11E75D6B2412599E30733C4CB7009F7B7DA1359CC196193F817420C9AF89C91CC097F730BC7478C1FCDBA3BA6F095D7D1B99166B0DB92B71E451301C41057EA82A6CA1A613A425639BADA7435211731F484961E985992B199BEAB3535277FCA16A9ED0391B0277CE812355867395BF49597499266B2A05841BD7FC8BC3AF7A84BC11C1F9C2D267676FDEA2190C14B14036787B41564F4896890160D64BD50751B5431BFE156ACE9D222F3688D66583B9FD837DBB87147271D9B025B900C9136804A6F2C36F910630E769CDC1A4FF4B0044DCB45E725ADE26B9719269F49C43DD4A96A43EA86D6A91AAAA123350552AC512D2C6A37C04BACF4E27C89A49CA0A1BB106903DEA4882771A3A48C1F40256348C1B8E0F5844442C63E0BA6A17555218325B24B196BD52443D23B4D82BCBF243DE32BAF1880B9E1410A1F803B82D407301C12ED5764EB284CC1185B64D00151CB12B95C6248A92C04F47D3C22336455685EFC4441B67D63465408C90EC3E04C71B565D8D32C3D88411321C0D72A9C1361BFCE78CAC0602FA93484AC17415EB39AFF8B6A8BB0CCAC59AD7E59C6CB2656F4C5499DC76236C37799871CE6C03EFD659CE43655BDEB90D0896ED0052B857A5EED0B11886070AB32990B343B0A081B517C0714866D53CB482EDCBFA053CCCC070967F3C10304B30C80C659D2438BC95C471C7336D6C86BC595B0F89025A646619AC533E727B93BA353B28C5C74984BA0A690082391F40F63098D63BCCE87FB61340C9DDBE708B436771798BDD30314622B52F473C8FCCE991E48ABF56753BC19EBB31445317F5BA3136A2653D43B28ECA455F4680E55EADA9ED627C30ECBB54CFA6DB63067F680FF08E79BDB35AC1AA46CC2BC6CA95DEB0C8D7F930CA124AB843003C42115EF6556C1380D9F9F994FE24CC6F4BA24" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "3B5CF90BAF7956304482F83F13A2DD111AF36115260FA48F5D38D53F038916FE4728B88C1D4BA3F987FEF5393CCF6C57091A90D6F1ABF6F4E817575373DE2F3A", + "F2071C9F0140D01BCA4A95A52CB877A1D762A4B4465A4829D70B4C1B6B2FAFA7773535C6595B60E1956F7A8823DADA0A58C8B48DC99BF3CCAC7533AF12E5B502100539A9ABE329A83D9B1935953DC5182BD7A6B5640766F1EA52916ABD10C09424039CDAF00CFF943EF06892CB07665A836827135419230137983219D14ACAA04108A31A50848E4522CEED1AC6929461EAA7AB2C30C19DAA97E8F48D9F035E93E7752B1C95344C9233048BD15719696C10A3F9244CD75EE5B23D73A309F2F59861265648849424212C4879BA1E6CBCDA9A44FF288C8E5B8C28E0A30FB967CDA6B69832449804A2A208B9FEC92C06DB74466C6AC6F6A4FF4AB6EDFA842763B2903CA0CF512F2AF608FA99620E178BB723728648B58376B526029D61B1C5B4CCC09D9CCF9A40B296E476AB707C1CB00F91B08A3332753F2280D7623685C4C0FA3747EAEA598784B442E4876A5095A15730B6ACB2D6B2074B236B43D705085C796BF8581AC47F2DD84550DB74E464A22302A050D4CDC1424244811885B71D988BCD6BB66D0C32A341268319444BBBC4CD98909816AA392349AFCC85B41AF631BABA84C31AA291A1123900B4DA088F42495F60508CFABC097338CE74A971C69408541ACA9E54607853034EAC3365BC8B3C2A71E78A40806C5906077B76344D6A3177822619A0375131EB2E4B7ACE62ABC6B1938B415840F57A44F9B9896EE09A6976654D587B498054466897FA94290AC9A659FB382FC859CCC5B980F1C343545B64987AD22393EB57B67F845B3B13C0D38681731C5CAF043D846B10BBABA766B87D69EC6382D4A1B75CB077DC6174FB58C2DC9AE8C19FB712CA2D2878C7CBBBC5B61CC38AA6D9434C51384DDDD686CF0087207956AF86383FF3CEAB42B8364A20ECF99C32A73E0BA1332FDB1D5BA84FC829BE1D4664471331A1F00F8B7A29B1A8876F4B6D1A5211660A9F72613F2BBC7CAC6404FD881012943C889B2557096BA2C23D3A62751691B3BE0BBF46993BDB2077FFE4AA0792BCC782114CE9B884FACC85D1C21BE53729D2326C55373801CC9CC07014A8AD99F05436A02F2A6689221934CFF4BB59972D97D92A37249ACA461C3FBBC7D6656983206E5D204135693F247A827973016BFA814E073EBB8C0881C72274F64586946B829B01258B3A377686C2F51DE86267EE34429A5780367C47AF45C28F697B8443859CB0632EB610E227AECE3681AF324855708E54F88A3B6A9C74F4C6E10B8047F70A2E92620D801015D81AD9E8B67FAC031190C9CBF98C8CF9B7E693B342C18969C4B3EC000AB7371366FA13B4D4CBCA3032849AB90661BA47070DF33874EDFC25D5F801418459541C65102942008B9FE8A18409F9A7719705CF3053090B97B7061351F44C501587661370D82619E7B21FD1714C72AA36A3B400E4B558EE78482D45911D575380AA443BCB35BCDC7BD52077D45B27D3458128943D0528242DC5689AB80144D79AB1D26354E5947F500E59203FB3A5B34CFB6DD47A632367570612A219EA286D770576366AB83384482873AF1C2D0A64AF931BBF3C021CB93849D0A75049B59CEB0B4F54F209DA9C49C3E084525463DDE0CEDB9A549D793D66C73780FCA831CB5662B34611A5C837EA9168A2066CEB38F6F166EBD787C397344D57169E6344F0614A57465233934103F5C973084D0B3462BD5392D1D28497B05D00280453BA847BB9A733AB81EDFC94A904595EF9CED5165371BBC88732A12B11795154945363A6AD9788004A21AD6589CA4B7AE8D9AC24D6A282CA04D9CA8C681B9699175CCA13B9097C364BAC4A1E5308085305DBA519FCB16BF977102DF45753474A87942FDA4084CC8425CEE2343C777AF3537963E349A7EBBA556BB2E4C1BC2CD1221DF7038555780B549E6C7143BCE062D3B69D0398027F861F47C8490B0990D110A188EA296C8560D6E6BF96A48010227D63C41B3A09168F389C10F23266136EC9C1640F1CAB116B051DF0A609FCCF7B40477615920BF92D04149528532BAC6A597CEA224E0705A7CC6D3317CC74B307666B71A2C20772F7C1F1693B12633462552E7FF06821465F4D267511649D836B3B22674374C1C66A836CA56AA3757190546149E39050F29436A8843C0AC7534732A711BBA4B3E6A24F9712A7306FDD3B1D796486FB137D2F59EE894C1898343A7682318EE793F845099258574E759AA503910E508482B7", + "295A393A07B26B9304705BA52D1564C6A51C6CD9BD7525A87BF37EB240A44B7A08A4F0B151E978B0111FE1B87C3559CACF845EFD68148A991D6CB0A8147024C9E341F4DC2F43A45976B93A92581A1F9187C1C56562610B2DE68A36B3B8E790BE1246A70DA62DA4B7201F651A87E18A70B6BA86989469863BAE622A4C1838A8BC77CEF58CD7C0BCDD376A6C32B7A33456882C5D9A440D052C4796424681EC4B2353A3CA58560AFC237B82025C4335826C785793AAC61826B0BAB9A8EA53B57C00A145A9AD19B844624ABEB9194604A62C879C0F47AE6E00455F17288D7AA1094159064893791B745456A1D7D1355F5CADC7A32497076CFDC3B6CB3B7530DC1D4297BC3074453855C9E80521B1B31FBF65467A63204DE7BB1F26A71C3110F0953D6B5CA665E46ECE201A8C241A5841970BA406332C7AB31226C69B1C49099D14E98D0D494109270B8676A16CA83B920C261F2B75ACB8255A07118B996F1CA3A78949C47963822BD97FCD75B5EFC8CF1FA3CC90621E9EDC0336A18551D36D9E454B60043440E651A21AB65EF39E22A6252E6884417A66DE899975A005E3FABE849C764E26B9E2B79D4FD358931C9E1626231BD71808703CBD099247F39B8AF5817041A7B0AA0C0624C9D4E01A64942C0180ADF2C86BA36751A8D7BE14BC2F142377688B19845238120C79F6673C185A7AF2263C1E2A80E8A8AB41AA263EF34F4D4ACADF4A70B370CF13832FAD208244230D5E112108B55FCD939824490DA649BB1282355680960283B46E0B15C3614F2A42778DDB54AC4CA9C17B636EA88C29D1B244F516E66C60AD2956ADD824E79A1F46A879BC14B81D788B388041732B36A607869F04AD1507C79795C5ECA02DE2313A5BCA1B8942A5D6B83706A9696A208F786ABF3F9681556A5EE2C79A09686634F04542027EFB67351AB7BEF7C67210927969C943CC17316D69230221436C2B8D83B74940661400B896DA3C61F5690FDB7A035F446B1A20C891B9BE40F5BA1E994A4EF389E1273B05A400AB8BB1A4279F2EFA5C6761B2796A15354926868343DA1280B819174315067EE70F18E54C3D5156EF0447C90089549BBC1A183F2A1B35EE58074692941A4422772C9069F81F45A6B270A176CC36C3E7407EB4112B3749596C128817169C0D24C1FDC904DEB625F537705FC8BDE01360D92270883791AA492C24F27CD305C9B67606261426C2694B7C03B9F38BB0692015068B9AFEB603CD0ACADCD23FBF33BC0C38AC60334B5E80B71407BC9E037149BA27585C2FF77021207A85EBBA5B5B8301C260BD7E9B9F58A7B6DE15A4CDD29DB9E8C28712602B842C8BCB4C122A54907C448C6199EDBB195A3B8BFDC5716F03C34188727D111909B5C19C27CF475AB7FDF40024C878A7DB3D6B1509A496048A403D252807397918FCD3A6AE0BC1C499694EB50EABD8AA6A935B61FC91169C44D4FA37A57A882E4280BC4725D245B3FC770A39D5A508A16D65EC0013054FE56090E3C048AD5C0FA7C805B3D820579AC40E015570E55076389DD1F16642E30934BB15E7403DDF6A03BF082EBC2731665CCDDE683497C5A6AC239199B88D1B01C8963657C626B6D4BA545D707A88632120694FE303BE49583598DA19EF228590A5271C442A3E9B39B3068D51A382871CAF9C65BA7F77CC8D95767DDAB70C83BB2FA0904B8A0BFEB6B07A8556B489591F395DA65581636890EB8737C9C96D7511C297E7ACD3BCC98C5315F97B553A71465D1B2652F9969DA1AC5FA50BB79BA1353A2EDFD584ACE8A4F6976166741FD8C4781E4B281A1B0E02EB2DF29204C908BA3FB25996F13054C84432C64220781DF550AAA3A0C9990B978C4068E36B8501303964567D780473D83C3DC4355315A7120CF2AC70BA764333A43362C703A9B0037224306A1D6889146E9691171512B728ADE8C14FD62CAE2A749A3A0B6D33D1942068177D05709F9BC98A58B2B2933DBB4355125302F92C2C4B290A76B00F1DB39B6AC41EF550805BA758D8063D74599769280C75D6C517E961C03AA9ABB63CF907090F2829CBAC539CF82189489AFB56C59A6957CBA74762468F73534F765171355C1B64F5B3990950D28819CFD741C914BC8D78A1CC7496FBCBC32084A54C3B7589BABB64B349DE59CE9073046A822BE77173EE297E46C10EF2071C9F0140D01BCA4A95A52CB877A1D762A4B4465A4829D70B4C1B6B2FAFA7773535C6595B60E1956F7A8823DADA0A58C8B48DC99BF3CCAC7533AF12E5B502100539A9ABE329A83D9B1935953DC5182BD7A6B5640766F1EA52916ABD10C09424039CDAF00CFF943EF06892CB07665A836827135419230137983219D14ACAA04108A31A50848E4522CEED1AC6929461EAA7AB2C30C19DAA97E8F48D9F035E93E7752B1C95344C9233048BD15719696C10A3F9244CD75EE5B23D73A309F2F59861265648849424212C4879BA1E6CBCDA9A44FF288C8E5B8C28E0A30FB967CDA6B69832449804A2A208B9FEC92C06DB74466C6AC6F6A4FF4AB6EDFA842763B2903CA0CF512F2AF608FA99620E178BB723728648B58376B526029D61B1C5B4CCC09D9CCF9A40B296E476AB707C1CB00F91B08A3332753F2280D7623685C4C0FA3747EAEA598784B442E4876A5095A15730B6ACB2D6B2074B236B43D705085C796BF8581AC47F2DD84550DB74E464A22302A050D4CDC1424244811885B71D988BCD6BB66D0C32A341268319444BBBC4CD98909816AA392349AFCC85B41AF631BABA84C31AA291A1123900B4DA088F42495F60508CFABC097338CE74A971C69408541ACA9E54607853034EAC3365BC8B3C2A71E78A40806C5906077B76344D6A3177822619A0375131EB2E4B7ACE62ABC6B1938B415840F57A44F9B9896EE09A6976654D587B498054466897FA94290AC9A659FB382FC859CCC5B980F1C343545B64987AD22393EB57B67F845B3B13C0D38681731C5CAF043D846B10BBABA766B87D69EC6382D4A1B75CB077DC6174FB58C2DC9AE8C19FB712CA2D2878C7CBBBC5B61CC38AA6D9434C51384DDDD686CF0087207956AF86383FF3CEAB42B8364A20ECF99C32A73E0BA1332FDB1D5BA84FC829BE1D4664471331A1F00F8B7A29B1A8876F4B6D1A5211660A9F72613F2BBC7CAC6404FD881012943C889B2557096BA2C23D3A62751691B3BE0BBF46993BDB2077FFE4AA0792BCC782114CE9B884FACC85D1C21BE53729D2326C55373801CC9CC07014A8AD99F05436A02F2A6689221934CFF4BB59972D97D92A37249ACA461C3FBBC7D6656983206E5D204135693F247A827973016BFA814E073EBB8C0881C72274F64586946B829B01258B3A377686C2F51DE86267EE34429A5780367C47AF45C28F697B8443859CB0632EB610E227AECE3681AF324855708E54F88A3B6A9C74F4C6E10B8047F70A2E92620D801015D81AD9E8B67FAC031190C9CBF98C8CF9B7E693B342C18969C4B3EC000AB7371366FA13B4D4CBCA3032849AB90661BA47070DF33874EDFC25D5F801418459541C65102942008B9FE8A18409F9A7719705CF3053090B97B7061351F44C501587661370D82619E7B21FD1714C72AA36A3B400E4B558EE78482D45911D575380AA443BCB35BCDC7BD52077D45B27D3458128943D0528242DC5689AB80144D79AB1D26354E5947F500E59203FB3A5B34CFB6DD47A632367570612A219EA286D770576366AB83384482873AF1C2D0A64AF931BBF3C021CB93849D0A75049B59CEB0B4F54F209DA9C49C3E084525463DDE0CEDB9A549D793D66C73780FCA831CB5662B34611A5C837EA9168A2066CEB38F6F166EBD787C397344D57169E6344F0614A57465233934103F5C973084D0B3462BD5392D1D28497B05D00280453BA847BB9A733AB81EDFC94A904595EF9CED5165371BBC88732A12B11795154945363A6AD9788004A21AD6589CA4B7AE8D9AC24D6A282CA04D9CA8C681B9699175CCA13B9097C364BAC4A1E5308085305DBA519FCB16BF977102DF45753474A87942FDA4084CC8425CEE2343C777AF3537963E349A7EBBA556BB2E4C1BC2CD1221DF7038555780B549E6C7143BCE062D3B69D0398027F861F47C8490B0990D110A188EA296C8560D6E6BF96A48010227D63C41B3A09168F389C10F23266136EC9C1640F1CAB116B051DF0A609FCCF7B40477615920BF92D04149528532BAC6A597CEA224E0705A7CC6D3317CC74B307666B71A2C20772F7C1F1693B12633462552E7FF06821465F4D267511649D836B3B22674374C1C66A836CA56AA3757190546149E39050F29436A8843C0AC7534732A711BBA4B3E6A24F9712A7306FDD3B1D796486FB137D2F59EE894C1898343A7682318EE793F845099258574E759AA503910E508482B7DBC04D81D8DB7F52B220838BC2980514E1E4999EACC7273383C3797E0F5257924728B88C1D4BA3F987FEF5393CCF6C57091A90D6F1ABF6F4E817575373DE2F3A" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "BD81A2BAB4B099E15C6689399297EE6206352F39E510DC3EFB2CE2CCC03F6EF207B9AA3E4014927CA81E3876592130A657BE0ADB1F198B68C0E3CF472D42FF94", + "A6229798E0C19A59AF41347F0772B3248A566F33AD3362AC3DF35165927D03F3BD6381ADD7864BF0FA687AE5924B193428472494FA9DAEC8413B40ABAE8433756323D86A20DA821A1F1B9AE33422EA527BF08CAA1C46C621849952F9B9E8657A4CC0ADF9FBAA0BE42AE992B13041A289957721D0C56EB026FD7C6BE9A027DA0A6ACEB3076FFB3D9ABC46F0E207E74B17DBE717A77436D4FA150DEC933F527FACE476CE0B0337D437F9856E2F3845A24B337860477F732AC17446075CBEFA88583F538C67F6ACA17ACE7940659F803BCBE37C85A3CA7FDBB749BA4296381708BC5003259F5E834EE262BAABD0584D6A87B6747D969A9D1A235272CA81DF9BCA743A0BE0564552E561AF5074539279DA1801956358F43109C267C7014813AC09887FD302BA83B68D2A537C048B9F06C0E3712F62F789DFA3AD42959BA5A5529E3AA509F6850B987D91CC1DDF140A2EE15D8674937FC5142959BC5682A63DB62CC28056F4E3451936C7602721558B21FA282848E766F6857E319B8EAF3B18910518A7B246CDC2B938776B005575B0FA00649349BF7BCFA9990F773B2373A77A1E41AE8C8C035329630FA45B8F18CBE05B1A7CE29FB3FC497E2189E0925709160ACB2B27F02AC2690801FE70395E17795F03B621960DD38C19CBA67D7D1294FF072E1FD721458804080BC1931B0D472793F34786AE514205C92E5C7C59FA863DB4943AD837971D670C5F002E5C3557681A95E2298E5561CFC1984DDBCAA5B5A490BE0601CE60A0D1E108ACD10961254E8D253EA246A5597C37AFB2552982306A010569D834523737F40AB28BCB5EB9F123B64406B508199CE95D41D4970842B3EC1A8E1B07022A9BCFC3A17FE83C741BB730387243CE61A50391579315B588D702C2D67DCBB06B7D9AC19D54805C897F822A31D998BED081A15C65AFA2E0B1DA33A42E52AC57A903905A522F8022299A967E837DA17CAF8CE4590C1B0620AB055F026559847D8AE1BF9182A6798ABE9D2CA37D7CC183380F3DA4537893B0244928FC80A407D04ECCD997D1B121DCC2AF4AB04E953AB6C1579C46E49FAA1709DFC2BD71EA6EBA355BB004A941E663F25CBEB1A75A869006CE2C3D5058AA72C4086AC88BF142AD08C622CD70705643AAC79620D0C56E241984FCF9C75CB71C57F8637AB041FCAB05B250772DB52652756F84A10809164A2CB30057B61C6EB9BB4E11BC9961C4E4160BA97993B7C570A301CBD7F865BA200863120C1925204F41C25AF30D52840F2866B172B04354A51427901BE3BB69432221016C19424B51C82559E3291A8CDB2FA83305D1288840F1B072354DB2FA0C1D074778EC916B78B6664517ED47965DE799AC2396009C5E44643934A5B84D776D3403096A85BEA49CC499F0061B2ABDC8AB7002125F4F2674DECA2DA0E43C62F9A035806B7A2B38D60B5D63E5A627B4132C2350FAD7ABFE3317337C77F0B00A8862CB3AB3812ED634884679F4E526AF00B63C049B1630B2B7D68264A24524498C55C7B5D0F845E33C873EE77B56A3277AC487053B2D8C6B9FECBB9BA181414C314B16974849A87733B96BF3F9826C924858BB4CE6285EDC776F89C88BE341BCC7299D3CDC026366059D8564B5B864F970A8C3E631BB0AB42E018FC4D603F1E09D48234BE1393B76BA58A892CC0DF968216C62FC629325E22916499378278955675427534AFEFC48F2752AB1B7CD06403689182E3FD41EF3017561692722591AE234CC3C6624B1D35E56B0A05146AE8A944BD22C0B62A9788B1B01244335F69A998A39CC03EA415FD2A7E16243A1160EA41ACBFCC67B28E6513591066C744138B15E0EE16B82B5CB2495243D4913B534C8DBE7765D4012DBD441F62A2156BC002AC162FE320CD022085506BEDD17B278B52BDDDBAF1AD55FF2168A6DF114D57055C30273207AC61B149D1E18AE12A8A6F3FBB7A4A97F5060A2D077585F78A19B29B9467C73AF4CB8A7E6A7CBB8A5E7493FFB5632C4871DC30BBA174B96F59A6C9F309E86C5173C6CC51ADAB919E577D5107615C4646F37BC398C859B3A5028D95C7CD9A158A27D90E7B6642C84DC639DF8C8ADD96A9BA34C4C0769CF350BB1E71A7BBC8624F289AF5C6312A1E71617AB0716D396EA0A21E63CCC136958AA7081972C7FDCBA8E947053C4D3170C419B42DF2FCA29D23A9FC824A0642938D4DEA798B5C966FF4FE777CDAF8C1B", + "B389BA13631CE9C086D18C8BCD584D26B15A319B5BC68C65A2051DBF8A4E18942511E2C1E5B1BCE7859A21F9038862522E2A82902A4F79B02F817CC9CCC14C01839FA2B52E10045D5204B6E3040E0443CFCCD49BD3005F6E00396C2800F3E3237E545FBD315FAA004424432B789AA1E8429C50227D7E931913461E3829468BFA526BFCC1BBA7626B761724457111A88A68114941A3695B185EC277369FF85A0B8A6D11822346B92DAB7114D406221BBA7D0A049C39F99AACB7962958CE2EAC0D6638B4B3A0A18890481F645219435C4C38B47E593D7B739BBC53C8475CB98FF51FFCC5588E4771CC3A0F56068096E23A78924C2AF4654CDB8B0EF5CADD0608AA2B00E8E00985497C5D24034D599B20042EFCA28B5EE1BAB36388BAF81BBDAA535624887BB16647540A24409BF3B859C048317BC0B8D5F9CCDBC04FCA083E35AB8393EBC01D1C57F232AE82FA604808A19B650B66D3049F678DCBEC232E2B5375591863C695FA693BB6F837C5728C368441503A8B8EB96A4D361A512457B27BC841E48EC77A58FE2B5033B0216B80BD8F92285F852289F2746E0A8669F34DF1B59768F2A6088189BD94BCD2419146C1770AF202FFF342E419B046BB3982B9A5524A7F36A5748543745C296CC4D6C1D44C2CFA7CA813039251D52FCE48B89E48066CB20914C94F97E608FAA6B32EAA3A6078170EBA836067C1403792C8D7B015327FF991C4C3107C26F7C5A7EAA0F1441DC2762947321BA05333EBF44BB9B6997D80C28C95B48AF05C5681B1212C0BFEE12B98433EACC8952EF2C0545C0FB647B39073818A4ABAB4800FC36C8BD6E5C3F827C9E6C9C05AC992546295A1BBC0C190A274470FFD53B730A50AC2B1341AE0301752415B6A7550014BD8209DD918BD63737A1F19C77005035E415852AC8B7D8470BC1A6419823845B83F51D4B3A6E583F9F8B0CB073BD1B001A0323A5FC0823F71A325BB6A0F24805467A63A22AE577A02AA52A01DA76E567AC0A6B253CED43863D798E1147FA78AAAFF7C60A3A8473B68408FEC1B68E841904BCF5B0BC9197301B029C43E8CAF42C5A024E2BD1615BFB8C8B462E196BDEA2FEB09250C71291AF1BE1B09BB01493F1D742844C679A70153F62591406247143798E184767771B245B0AFDCE1817406CF115C560A402002404D80917DA57C8312CC99FCCA5474BB79A521C1FBDA2E28840232184B8493AA12A50B9A4BAE3B541221904D227524EA684401436E8B771982603775A47B1D4657B4B854774206BD5A9A8C678D1626824A0C5EEEB3849F326E276229A4043C836204359C3C77D570FC2934E3D57D6839C409F769CBFAB02962577FC233E50B6D72884E4566C063007CDE8113D72B43B4108F7018ACBC319011B83A6698325EF2C4E2747D20F7C65D4820D52B7532214E0A9333297B3C2D58251830CC47A157EB49A0135197BA41B1BF2364EE6A077EBB153BB2AB40AB9BD8C53BF30129947381F2306441B1BF4C316F62C01DEAB34CBFD65F381B6EB2146DB97B3EFB3B2F6C7C8818F21D9BB01CF13C0DFBB504D6B556C7223D01957BE80186A879614E46437C0328752C8B5CBB0F96F228B485C6E543038BF13B853975A9D87F91DC0E230390B5884C4B1040EC3364834BA606C00DD0C20AF0C9A587C118C81A91B6E2A046198BF9B04B49B35728D677A91BBB3290C29FA01E89ACC3C67AB746ABAD4ED25E4E407B12BC27F0765A9E925DF6C155BF6C299DD10EBB6921FDD17B624672D441C71073102B27523DE3A089435F9E711A1F35C208AB709483CECF5C015D269430E5B154F29FF545264400124DBC7EC16CB054A97051B97B9DE41B8D100D0EE2CA6DDB23A7632CC43C2C25766ABEC4B57E92C3CCD6156440773FD72DA2A18B2FB5B2B5239889CA0E8AD819A4CC13E3D04ECF49485C9BB2EE6830D8BB9880CB3150A46592A05650965636C48921F27DD02AC255C575D5336B07552626A3BC4D589716671A3790C91D609675422BA91292385569C75C3623315303E4B2CB763FDA238A2EAC56FF4B3952E82B93CC9FEAB293A2E28518A663E6588259030E0351CD17E1B632077D2C23A7E6FA6F72A3BF0C8228DDF36F993B4B4B352ADC82C2A3B19F3E94100C7470E2F4B6C0149A816A4CC143AEFE612FF0F09C75A13882EA8CE95365A6229798E0C19A59AF41347F0772B3248A566F33AD3362AC3DF35165927D03F3BD6381ADD7864BF0FA687AE5924B193428472494FA9DAEC8413B40ABAE8433756323D86A20DA821A1F1B9AE33422EA527BF08CAA1C46C621849952F9B9E8657A4CC0ADF9FBAA0BE42AE992B13041A289957721D0C56EB026FD7C6BE9A027DA0A6ACEB3076FFB3D9ABC46F0E207E74B17DBE717A77436D4FA150DEC933F527FACE476CE0B0337D437F9856E2F3845A24B337860477F732AC17446075CBEFA88583F538C67F6ACA17ACE7940659F803BCBE37C85A3CA7FDBB749BA4296381708BC5003259F5E834EE262BAABD0584D6A87B6747D969A9D1A235272CA81DF9BCA743A0BE0564552E561AF5074539279DA1801956358F43109C267C7014813AC09887FD302BA83B68D2A537C048B9F06C0E3712F62F789DFA3AD42959BA5A5529E3AA509F6850B987D91CC1DDF140A2EE15D8674937FC5142959BC5682A63DB62CC28056F4E3451936C7602721558B21FA282848E766F6857E319B8EAF3B18910518A7B246CDC2B938776B005575B0FA00649349BF7BCFA9990F773B2373A77A1E41AE8C8C035329630FA45B8F18CBE05B1A7CE29FB3FC497E2189E0925709160ACB2B27F02AC2690801FE70395E17795F03B621960DD38C19CBA67D7D1294FF072E1FD721458804080BC1931B0D472793F34786AE514205C92E5C7C59FA863DB4943AD837971D670C5F002E5C3557681A95E2298E5561CFC1984DDBCAA5B5A490BE0601CE60A0D1E108ACD10961254E8D253EA246A5597C37AFB2552982306A010569D834523737F40AB28BCB5EB9F123B64406B508199CE95D41D4970842B3EC1A8E1B07022A9BCFC3A17FE83C741BB730387243CE61A50391579315B588D702C2D67DCBB06B7D9AC19D54805C897F822A31D998BED081A15C65AFA2E0B1DA33A42E52AC57A903905A522F8022299A967E837DA17CAF8CE4590C1B0620AB055F026559847D8AE1BF9182A6798ABE9D2CA37D7CC183380F3DA4537893B0244928FC80A407D04ECCD997D1B121DCC2AF4AB04E953AB6C1579C46E49FAA1709DFC2BD71EA6EBA355BB004A941E663F25CBEB1A75A869006CE2C3D5058AA72C4086AC88BF142AD08C622CD70705643AAC79620D0C56E241984FCF9C75CB71C57F8637AB041FCAB05B250772DB52652756F84A10809164A2CB30057B61C6EB9BB4E11BC9961C4E4160BA97993B7C570A301CBD7F865BA200863120C1925204F41C25AF30D52840F2866B172B04354A51427901BE3BB69432221016C19424B51C82559E3291A8CDB2FA83305D1288840F1B072354DB2FA0C1D074778EC916B78B6664517ED47965DE799AC2396009C5E44643934A5B84D776D3403096A85BEA49CC499F0061B2ABDC8AB7002125F4F2674DECA2DA0E43C62F9A035806B7A2B38D60B5D63E5A627B4132C2350FAD7ABFE3317337C77F0B00A8862CB3AB3812ED634884679F4E526AF00B63C049B1630B2B7D68264A24524498C55C7B5D0F845E33C873EE77B56A3277AC487053B2D8C6B9FECBB9BA181414C314B16974849A87733B96BF3F9826C924858BB4CE6285EDC776F89C88BE341BCC7299D3CDC026366059D8564B5B864F970A8C3E631BB0AB42E018FC4D603F1E09D48234BE1393B76BA58A892CC0DF968216C62FC629325E22916499378278955675427534AFEFC48F2752AB1B7CD06403689182E3FD41EF3017561692722591AE234CC3C6624B1D35E56B0A05146AE8A944BD22C0B62A9788B1B01244335F69A998A39CC03EA415FD2A7E16243A1160EA41ACBFCC67B28E6513591066C744138B15E0EE16B82B5CB2495243D4913B534C8DBE7765D4012DBD441F62A2156BC002AC162FE320CD022085506BEDD17B278B52BDDDBAF1AD55FF2168A6DF114D57055C30273207AC61B149D1E18AE12A8A6F3FBB7A4A97F5060A2D077585F78A19B29B9467C73AF4CB8A7E6A7CBB8A5E7493FFB5632C4871DC30BBA174B96F59A6C9F309E86C5173C6CC51ADAB919E577D5107615C4646F37BC398C859B3A5028D95C7CD9A158A27D90E7B6642C84DC639DF8C8ADD96A9BA34C4C0769CF350BB1E71A7BBC8624F289AF5C6312A1E71617AB0716D396EA0A21E63CCC136958AA7081972C7FDCBA8E947053C4D3170C419B42DF2FCA29D23A9FC824A0642938D4DEA798B5C966FF4FE777CDAF8C1B3776CF087363C9E8DACDC3FA2157289BE2810E784F0E5900ECBABCFF8E7C016F07B9AA3E4014927CA81E3876592130A657BE0ADB1F198B68C0E3CF472D42FF94" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "068238E9AA7926BB9A9BB97091660EE5F81192A3E9EF6E00F694ADDD78C3AF02BF1F026EB1B0E362D210EC6FA841271025D3F79454519208F0EA998DDBF8CB86", + "5611B13D4B6BF1E36B048086611133DEF6CB5D733F86E88942B33E579A547CC08510A528E626A403144328E6BF2B829744A321DA6241999B41BD87A77004B874B22327BB66C53715F7EC1996D298691A68A920CDEB0808D763991F37BBCC7A962BC235AF210359250DC496309ECC66E7350F0EA0365419324C2B2C934CB992F1AE0B444979A69E2D262B7B4C7A1F6395C88C60035A2F8EB3C086442307E984844607D7299A5F63BF9A181EE3E14301898F50A8671B38BC53F9007E289718F4217AEC842DF8843745130911403AC8067167895EA39EF7852ECD6149DBF0C9F144AE3D4B1ACD2C8A5B0208DD348089B898585B9F5AD27AC4C8088F8620C539924E8A463A923A59BC0C38E2635BD35B5FE029134C3FC811237B4B0BA181CA413619A5B01A21596EB0D6B526796C36490E0D86765A5C8350D03968CC57A5D07D0AD09C0399BE777271EBFB426A98076ED169DF6035C9B251A2E1BC5E31447134A07E2BBF0115635FA05BF8C25C888906EE005675372538E5103D8B4C43439896D0238BD94FB4016C8721965BDC4485E7509F63A15FB65532E8CABD4405572370FA7844F388721E6A91FF83345A6C0D126321EBB272FD784EF8CB580FA1C2F67039EB65389D822E03B067FE069F49FBA16CE73EA88B5FAAA96530B27BC5483F1F245BFCD80D3A7A4E377B795344A0E82609E5C4C29CB245D8F6A112452CFF192B1B310A33A72CE86B91CA1BB6384A7F39D360F2164E8BB340C03B0020F53CDC178BC09C9196A2C4767A0C82A20DA4A5AC8AC67C48294D69D4C1899BA3C328BB4A733D3F46152011264F259189E71E30B909CFAA7264879A62E2B1EDB065641BCC99E9890275AF9113A3704BA719286516DB110629280D5124837878ECC52BAA066EEEC4C21F007F3D7101DEB0AC78F35F3A88012CA90EB0965A8CB6081D639725BA5489297086D8B7A8C835FF5C07E0518DCB6BBF1EB46D232A22D6E550CBD5BE45D0759F8C98A3312A921209A5932806F0B136F37CC14A9F9F51C3F18805EC43834D33AFD6158ECF680AA75A0C41121C4E9969305359E51B9CFDF16A5AE097C0919593824D6264BC00C53D847CC33851B254C94956E321CDC33086D8742F30599B284B95D8CDA85C7B4AC97DAA02566C8C189E26A47C240C21C53FFA2AAE3E405FD4F840DC3BAC25B3BDC3229A54AAB7885734E7E35ED8E544E1227CAF92174B21177319C9E5F6C04FCAA136E063B628A6418B49EE4B441EF411483ACF7D44C96EF46A85BA3A2D5B740CAC5F3673A4A2039F3F36AE39630086B07395C658C962C8CC885B04C156B8DAAD96B93D7D3CCAA404BE8B75191C584AD321268F3511AE30806E599DA218537B230F631745A41B59738B9F71D6B850B2BF7AA62BD87179493B5A977C2529618B65F58BA182404F720134F00F9478298BF30833CC167655870B96B4979B94754B60B57BA74DFA8CCDFAC65341C47DB36210246EC5F1C300742381A12069F04A060457A1A596DBB1AF5ADA683D18223AD28DD267AB4679479CFBACFCA7162419844056BAFA1B115BE18796101A536789D7B8AE72114C74597CF7A2373C9608878C14EEF22AA9C336ACC27D3FD7072DEC5288EAACD8D8592A9910E6107AE9C25832DA9932A95157C55F6C7418BB21030F00187B3C1AC221484D421C0A8C80EFD11DF130B76473C8337240FE818C3F01863F3663DAB699D6211185353879045BA5F572677B58B658B21D5B0CF8250485B288FD63832FB37F733556423249827836A24686520C8795C6444F960B28C49E54D776FD1B80241945D8158407AC3272AC25466ACE681BA971982B7647BE5CFB02B2858F1B0023224328AD77B0A1954209468F58D88AF98652181682E8D6BDFA7167074A969386B532C28264956AC031201D0A61FD857CA85BA803B329FC532981C321B920B8E87267B5359BF9CA0BAF746B94981D54E92591F848E8BC0692C585D2F79D9990C0E4E030DD4265A7E946200B397DA61F9607A22E48157B6261DDAB835C171C9B57688AB52D6E31866D22833AF425E55634E0733F5464B38F68303A4003AB374F4EA8B3AC34449B7A2218028360C1CD642370E429BFCAB7BE93B949EDA56C66881E3CDC59CBF9BA79BB9D3BE8951AE095A96B9A18041DFB842973273218B30982736D5A597BA0015575416A851A6ABC1550A269343E65E0C5946F328CB3AEACBD87EB6D8BF2", + "D174AFB1F07902EB8BBB3414C5D3131A28C8435C7DA1179EEF9B6A1EFA380DC77218F46A0407248D422E3CC8ACD56C4918996CFEE59F8A1046B46456229B3198725C5C23C245B047DD4135A075509827377E4782B8D5BFCF204D8ECA2E8A633D91B804CE8CCF2BC658A9FABC43A6B08C9613342117C45ABAAD5790D52191D9BBB3E1FA3897D13D9005C14B959918748C19731DA0CB65CFD552AEB78E4F663CDA22050A197BBB394A29E4A13E146F8DDCCD36E47A826537D6DA0E58A8A3CAC3BB605216DDD93D30A0CDCF92C7960B2F54AA0AC942B36E5996DCA19D6119568559ADC0912072B42706D11FC8D8B540F765634C1DB4EBC1B856C241AB66B0A22EAEBB734758C5D4824CDAF3A6C473AC80D7581C5B89D8D7A26096B7DAE9CA664920ED6AC7011ACAB6B5000D7671B0B778A133172B03BA9A30B6615A3D217572CC82138744B30B7A48BCD7A3F9F8BCFB943318C641D8AB2EB93C02A6327AB2888A6C4485272A8A65DCA333602E9DB35671A70F6A8C8B90542B51227F1E83596E206605E028C4D5B1BC1CBFB67282A5380423E95787D4593BF4A12568455F24AA1968B51108801E8ACA8B18690E92B0C35385176C4F93A02009EC601F1985F5DA145A4720A8F2BA47D89F9A443F09A77ECDF44393D260292718902C9DFB0AB3B5242009234D70D46DDFA90FB2402A3384C94A620FF9986D5AAA5E354403A08A1A3FAB4BD1DC7E5FBB500F64921DEB60FF1A52FFC741EEE78BBB421AAAF1747D620D5F082D1CD9229F307DC959B98D3B0FE2D827FD0857931B5F786845979883923404285AAE4C9A313C1C915E528AE1850B53D00570F006BD135E3B4178DC7675DCF1989AAC7BABC567E00C803CC0CACC447F6320089D34A28AF446BE1CB5A434B7BD661E0D5B75FD4BBBF1D43B57741433E3A854208B9A9C9206EC932C3809A931CD961983F2C8499D20C6EF724CEBA89FA0A5C8BA2CCB441AC91E82C1DD3BBECDE5079CB322C15CA4135B4A9C73C1D1B34DB372AF9BDA1800B3779D51C56D02226CCA8E6B9C0AFBE7B6D49C6205660451725871F602F75C19E86B1BE69493ED404D170311ADC8C9E2901CAAD188F3387BC8A70D7FCC23E5F915A534138712412C61624638388C69C94A45A24B041CA459AB14B887A2CB84C65022304CAD20C55F72D460E438AB0BA338DF17713B858F8FA38C0BFAA769272970130DB1D60E117B59BFB6AD3B004BDAE07A0AF102DE5606CD5925A6741C3DD2846EE96454E8A57477471237127AE4133403666BB0400EE1528BF528B2FA391606947873A63D3082681C90EC1B5793554767076299B1401ED59A1A257F3127A2F3841D10F3C9172BC291832223E7BDD1501D5D41C04B6B9DE5EA5C7025406296A199168730218AA7470E43C1A7C6E65542737A4155AD279C037DA21B2527241138BEE3959C7A18777E3B7B425047577A56052B7B5F95993E642ED99634AE3314C815155C91B5C6E09CA324C8D5496ECE56578AA302CD2CB99E9905BB4AC68FCA6658913B4AC40AF3B308224357E7E144F3607D16B57F899C724EA15561F83905EA594F924931711DB02C7A813C8D8E553231915FA677B0A348983D4851279ABAD8D3548EE805F46890956260704016DA6B23E1974E4C674D570B4E5E88B924920EB9878830C61BF0097293668F46E851704771A4875170673EAC3341274B0CAD949234475B2F40428670578A47898D025B4B54AE9AF5A756D3C35B590E4A34ADEF000814D59893F88F280B3FAA228CF0ABCC6066068D636924D455B649AAD1E32450C72EC686CE5B91CC9202496F073F6056450EA757AF4465988125CCF0B2FC0877A9836B54952039114F6952AF17D800C2390F1BC2C62447C6F80A3683858A192693E7F30332177F5579BEBB854901D11937399C12825F25CA18FAE60AB2964A89EB2099FA579DC04577C3304F5B4DD4B43EE1D4A31A5809DE807E4D16AA20B5A6D0FC93AB4330F2758A774341798C3E79632540C2C9CE5C461519C874E5AB113482133263A3D32A4E1BA3DC49C76C8B3D742558CD9C3CE982753F65CDC1935C99B89F160741E3FA1771B2C7F38BCE3D57A26E433E7378A19CE66D7380A2707C72F55A08A7419E2A986BE5262F1398978C6B2470B67C911AAC2BD5846A389F02CAAEB301201A70A65611B13D4B6BF1E36B048086611133DEF6CB5D733F86E88942B33E579A547CC08510A528E626A403144328E6BF2B829744A321DA6241999B41BD87A77004B874B22327BB66C53715F7EC1996D298691A68A920CDEB0808D763991F37BBCC7A962BC235AF210359250DC496309ECC66E7350F0EA0365419324C2B2C934CB992F1AE0B444979A69E2D262B7B4C7A1F6395C88C60035A2F8EB3C086442307E984844607D7299A5F63BF9A181EE3E14301898F50A8671B38BC53F9007E289718F4217AEC842DF8843745130911403AC8067167895EA39EF7852ECD6149DBF0C9F144AE3D4B1ACD2C8A5B0208DD348089B898585B9F5AD27AC4C8088F8620C539924E8A463A923A59BC0C38E2635BD35B5FE029134C3FC811237B4B0BA181CA413619A5B01A21596EB0D6B526796C36490E0D86765A5C8350D03968CC57A5D07D0AD09C0399BE777271EBFB426A98076ED169DF6035C9B251A2E1BC5E31447134A07E2BBF0115635FA05BF8C25C888906EE005675372538E5103D8B4C43439896D0238BD94FB4016C8721965BDC4485E7509F63A15FB65532E8CABD4405572370FA7844F388721E6A91FF83345A6C0D126321EBB272FD784EF8CB580FA1C2F67039EB65389D822E03B067FE069F49FBA16CE73EA88B5FAAA96530B27BC5483F1F245BFCD80D3A7A4E377B795344A0E82609E5C4C29CB245D8F6A112452CFF192B1B310A33A72CE86B91CA1BB6384A7F39D360F2164E8BB340C03B0020F53CDC178BC09C9196A2C4767A0C82A20DA4A5AC8AC67C48294D69D4C1899BA3C328BB4A733D3F46152011264F259189E71E30B909CFAA7264879A62E2B1EDB065641BCC99E9890275AF9113A3704BA719286516DB110629280D5124837878ECC52BAA066EEEC4C21F007F3D7101DEB0AC78F35F3A88012CA90EB0965A8CB6081D639725BA5489297086D8B7A8C835FF5C07E0518DCB6BBF1EB46D232A22D6E550CBD5BE45D0759F8C98A3312A921209A5932806F0B136F37CC14A9F9F51C3F18805EC43834D33AFD6158ECF680AA75A0C41121C4E9969305359E51B9CFDF16A5AE097C0919593824D6264BC00C53D847CC33851B254C94956E321CDC33086D8742F30599B284B95D8CDA85C7B4AC97DAA02566C8C189E26A47C240C21C53FFA2AAE3E405FD4F840DC3BAC25B3BDC3229A54AAB7885734E7E35ED8E544E1227CAF92174B21177319C9E5F6C04FCAA136E063B628A6418B49EE4B441EF411483ACF7D44C96EF46A85BA3A2D5B740CAC5F3673A4A2039F3F36AE39630086B07395C658C962C8CC885B04C156B8DAAD96B93D7D3CCAA404BE8B75191C584AD321268F3511AE30806E599DA218537B230F631745A41B59738B9F71D6B850B2BF7AA62BD87179493B5A977C2529618B65F58BA182404F720134F00F9478298BF30833CC167655870B96B4979B94754B60B57BA74DFA8CCDFAC65341C47DB36210246EC5F1C300742381A12069F04A060457A1A596DBB1AF5ADA683D18223AD28DD267AB4679479CFBACFCA7162419844056BAFA1B115BE18796101A536789D7B8AE72114C74597CF7A2373C9608878C14EEF22AA9C336ACC27D3FD7072DEC5288EAACD8D8592A9910E6107AE9C25832DA9932A95157C55F6C7418BB21030F00187B3C1AC221484D421C0A8C80EFD11DF130B76473C8337240FE818C3F01863F3663DAB699D6211185353879045BA5F572677B58B658B21D5B0CF8250485B288FD63832FB37F733556423249827836A24686520C8795C6444F960B28C49E54D776FD1B80241945D8158407AC3272AC25466ACE681BA971982B7647BE5CFB02B2858F1B0023224328AD77B0A1954209468F58D88AF98652181682E8D6BDFA7167074A969386B532C28264956AC031201D0A61FD857CA85BA803B329FC532981C321B920B8E87267B5359BF9CA0BAF746B94981D54E92591F848E8BC0692C585D2F79D9990C0E4E030DD4265A7E946200B397DA61F9607A22E48157B6261DDAB835C171C9B57688AB52D6E31866D22833AF425E55634E0733F5464B38F68303A4003AB374F4EA8B3AC34449B7A2218028360C1CD642370E429BFCAB7BE93B949EDA56C66881E3CDC59CBF9BA79BB9D3BE8951AE095A96B9A18041DFB842973273218B30982736D5A597BA0015575416A851A6ABC1550A269343E65E0C5946F328CB3AEACBD87EB6D8BF20D9B9B2C4006DA49A608EBCD81CAAD324E8CAEC0AC3974A54278A60F53C18588BF1F026EB1B0E362D210EC6FA841271025D3F79454519208F0EA998DDBF8CB86" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "AED60297778AE47064D6FF0500D7BC2F9EDF4F78A3B3DBBDFB20CAA6EA2D5A726F04B758B52CCB2D472EBC07A214A743FE31D8949D9EDB652EB7C442B72B9E21", + "98481CD37A32F9A74E11B390CB51BC7C48B643234E617A9C17683C2987B1AF30A4EEE73029A67C49EC8853C81B0DD1B5399171D6A5B026275AF8542255583F36869751608B67B19E86181AE306040D573D0556534A8C390F84A14BF36B2FC3877A3362E869C70194492EA409DB43AD762A5BB5297700E838CD81A02211318FDA13231538A82B98BFBC2300205E7A7351DCF3A3660C9943204202F1CA3DE22BD78C2BF6C861B3257C66B95216EA6BA60A7949748CECD430FA426E79F0945B824D90E964F2514C9A75C251546B26D12E8A4116620B16540AADD37A48D2BA29455585A76A9A2EB02C1919ACBCE03FD56043CC17AD4060646AA065DFFB08AD3624D6C31A25DC99B9951B1C484DA39430A6C1BE0CD8A3385A2FE6A602F15370966392A57C7F97817BAE4832B51907EF937C1BD6030E072F680A0D81D7949EF025D52C3CB9115A6B65B42101852D2C7BBCE56C0EA9B9EA4283F524263BB6CBF710476BC235F3164DFAAAAD5C3200308581D6584B02A5555069CB9715C6EF9238DF381598941589C06BD613A7DC45513A198432705B17B278826415204B5D0675C9C75B68792942831859028AA54EBB111A038557416FBE6AAF91B18CC4F6092C0BB26C902F32E81AF94B101733A572BB14BAC3CC7EB6333C662647A49F3318B531C9C5F5A0A924B501250218196BA66E6C9717190A6F94A76AAAB478C69EFD3C4760E694C234563EFB2BB9743BAA466B3CC54017F8A482428D8F1BC094B9AC2369557E0CC2712C1877F718BA712FBE76CA1BE3C01D6C44D435192113A5C362C18BA10AADA28B7B98564022163542C35FCC6EB59B0A7C3621B94471CCF691CE363EB0F486DEB91D3DA11E2C031D2C331C32E88D42E6BF8FF3C025EA44732B1A0A2B49803A4969DA9F868398B5E88F1C92745A8CB9D64C65187104DA24B3D1C3A9571C75868117AB5ACE698B50E329B30F3245CE02B032802D7695CCF9778BC0B622100C35AF184DDAEC743628AB053405C115937BBA2D383293D4E93E7726AA70C89DCBAC6ADCC32DF0F6CDD88CB8F1C9513B230928052843DC9388BA593154621D4B6F2C042D1762B9E28B6B605AAA2267A441F775720C7D5DD96900EB5C326CA4AF452A637717D41558BF59475AC34069B87B2A2086CB34945EB21A5E79CA47B18ADB7043CC7482BCB52CFCB6C44719962E045ABAF88BC6DB92B09219AAE7C74453B86D576AFA1571E86B1BBF28B4C3D82ABEEA9FBB3B8836A97DEF5B0141794A9036B205C87D3812753DE74C071C3C3F6B1A59AA19552C2F42342FECE63CA27997A9B98F220C20F8F47C5E3021E9295983C757E24088D5D5197F5C912087C35D0A114D26647E2CBB1C16A0AF9C471F90720CBC118C0AA2D4A0638F3B02C33849FBA0A94542492260005F959AE3907B27F2A7F2602CDAA2109654078C2A90379A5E9D49894B007E6F854AE93520BA142B32660A7FDCAB877B2E0C68756B1324D3B9A606B4291C15B5429060833BB6575CA0E5C7689A4A131E26166E984A9CB06AC91A9991F978D5F6310AA91A1F4B14BB802B4C008CDB70ABB8068AF3C40DB979884FB61767C260B6B72B3A6BBA2ED2968B83689EC80D387ABAE88C184CE166DC0A2D096ACC36DA5F925430FB048BC1FA4246B8C0FD103745376A4BF858A3310A7E611B29F830F9C5C57166AA0FB3AAD45B6C55110562ECC50625384DEC579E5B37303C8C115801FD0617BC5133E0A3A1A1BA5B1CF51D87009CD5F617A0B1AC9970722784407624451DD8725BF4874321936B0C333892CD2E3097517604A1657B24220558AA766EE44314C780A2D5BB271A7E8A8149C08C8F65B3A293431748CC03E0F3B1C985096CA181FD41C50C775C667CB67B75CB91F972E5AA6CECBC0175676A18971E2A0B682EF16D66D87815F8B662AC427F2B4B48DA88E407495154322F1943F331B0F7B1A04E9712BAE9B672440FA4729253D09473BBB023B91281357C88679C1897AF4F096CE3A38F9C88A3AB847E15371E6C8B590DA6899ED640462BB440883CCE06CADC8CA113676296DC5BD1FC57CF829216CB3E32F5C9DE384189C5688D164A4E480A0424973A476170C63CBDB094AF629570C35EF97C341DE3279DDA717FF823EB0A34AE153E07427949AB07B015A1CF32C531D952F139A8453464F7360F68B04EDBCD136DFBF32AE6F93BDF366E855FD0422FF874F2B65947791E", + "B2039FFF7802F49A794AD71F49106E42C3B338C964BCD7695CA2C358841CDF8B1D402058E12178A3F6023FF9C80FA3C45A058E3DF44F81841AAAEB2019FC4AA625120833936C026731261C7E4550E715BFBA18C5685058F681175190B49517A69650787DA88EB06B6797787253656AD1B922218AA1C1C8006A66CD907642C0839131A36EBECC7F8E4BA96DB49DB6611D16A368F2000072860D7DC79CCD4B342F983593732DE6E133FC521E325869CC4A94E3F41E03724918B01485729F5E5BC451422639A0328E740EEAF49526752CF2C83AAEB87B36D65824184C3E1329D382491F07A85A80242DC3B99D91C60F7C07C61899AAF5342B5B274B3433A316BEF3AB290A8830BDC88FC0F3C535412B1EC78997B6004AC20C8ECC37BA0C67CCE6420958C5A2594970D2BF514134F69435005B351BA09BD7793688E5522AE274EA53BCF7028DC6961BF9ACB935A80282886C66EC426A707A8045B05B284A25C636E01C47E8958453F40B492B6F106C6EF267A66AB0CC4317192CC2C88F45CAD41352E2835F3A26868B2843E4F16E6975AA4C3357503A70E2615BA9B14A272040C7354FE4946A3543030781CAC0DA548D2C47440C4923FA4E6197B70AA8B62E0A74CA20C6FAA987EB420E5B3C1B34CAC49F790B155A5AB7BA08627647DEC928F01309690BB065033D35B0897BC5C77B33CCDBFAC20764796FA59DD721BC4891A30687CD348670A5D596AAD7AF6B1884DD33AB8569B3A132772DE4B862C9472E010922E691320A9F11450114628A00155FFA880F90AA1185891E0B04B51DF51880D09B289473A15B4A45EA74950885E2021B7444205C2C7D691C02BD34110CD1CAF7089F02A5044076583EC013A0D427A1A799040297ED6CC37FA52F0FD76B5A87012DD9248CF892E822C40340AA541108415CC74159C83A7A1F2E809138745778997D89D11ADCB375246701A98B3AE0CC0E75A1C6E12A514BF65220B9CD4A25BB12E54EBCA815B6037F1E000A10478755375021D52535681877BA5AAC34693FBA7968C35F8AC265F93233F445166EBC8CC5F7C7D19AA457B37F41B3A60C793A15208F92A4A54B0922100A01D8F2BA11B08F3EA3792CC9CE989269D774645638206D4C9733267B054B5C998254B7B3AAD29452F8E3710D0274147643A7E83E9C6897EBF85C0464AEEBD2059A95637E8173DEC125436597167BC7AF78125F428C9FCC3A250A5C9E1CC527E98FBFF44355CB3A75E49DF7D68829760152D1C37A265F62A361719CBD4C459C41402D0943A362B1CAAEE5A1D72837FA6183F33818E4105BB5172F9583B0A4618EEF41AA8AFC73B26B4D6718B1966083F25332DA28BA9CE3B4A3A02264661BD7A9B927F60CBEB540EED7A2D658CD1CE3613BF14E8A128EB3009E6089C8A33BBBBB44B66786C694C785C29B6D309451F78C526B67577CE01B31166DFF4320B04C37877298E9A63D0124291ED630AA7AAC94A078EE2A99A125513961A20E0881FFB6439F371BF068956C320889BC5796528B5BAB5BC78832CDE75263354D04D26BFDE5C94E02AE3E63B8CA1C41650A55FD565D6461871B07CE859C78BC6648A93B1586E793889C9271A954DD0A6B31C2A16B92CE350753E1B6357B14C49A8589C82242073C4E276AC1F290880DB87B12C27911B909817A8DC2EC06F347A0144A065C5A6784135CEB6A473A1A11DA66CF5EAA690F8675032818401B001891CC8D320F33C094FB812CFA94524DCC2F6099AEDD59BE56782DD6097D127CBE4E1B2035377DB7723D6F8968EA2413DA2A04705BB233F03879FBC6ED70A4BED67C9B47569A959BA18ABFB6C45452BC9A6DD957B2F28DCA3A8675424E0402650400CB8722B81E1149A5D55A724B0170B00F8A61AB641C8833CC61E1E5A76855B071E5B8797102CB339E6566B058237167A86490192E5D592BC85AA1D3734117B51B0B3B9259DB8E82DB15A504B0BFD5858C0C2B5D59202C004000C2BAD21593C755B87A421856F02200723CCACA17A8809D64D95139EC55EFC795C276B9FE47B4280C67DF685F806243178BB4B7462CB03A5AF46398EDB1C61D2671410AA3843B9D48ECC136BC7AA5DCA9F6B87268A38D59A0BCA9A7602D8CB4706731F5F3B0657796BF3C3DC1266D54714929DB3ECB684C9C132F025914539629A324A098481CD37A32F9A74E11B390CB51BC7C48B643234E617A9C17683C2987B1AF30A4EEE73029A67C49EC8853C81B0DD1B5399171D6A5B026275AF8542255583F36869751608B67B19E86181AE306040D573D0556534A8C390F84A14BF36B2FC3877A3362E869C70194492EA409DB43AD762A5BB5297700E838CD81A02211318FDA13231538A82B98BFBC2300205E7A7351DCF3A3660C9943204202F1CA3DE22BD78C2BF6C861B3257C66B95216EA6BA60A7949748CECD430FA426E79F0945B824D90E964F2514C9A75C251546B26D12E8A4116620B16540AADD37A48D2BA29455585A76A9A2EB02C1919ACBCE03FD56043CC17AD4060646AA065DFFB08AD3624D6C31A25DC99B9951B1C484DA39430A6C1BE0CD8A3385A2FE6A602F15370966392A57C7F97817BAE4832B51907EF937C1BD6030E072F680A0D81D7949EF025D52C3CB9115A6B65B42101852D2C7BBCE56C0EA9B9EA4283F524263BB6CBF710476BC235F3164DFAAAAD5C3200308581D6584B02A5555069CB9715C6EF9238DF381598941589C06BD613A7DC45513A198432705B17B278826415204B5D0675C9C75B68792942831859028AA54EBB111A038557416FBE6AAF91B18CC4F6092C0BB26C902F32E81AF94B101733A572BB14BAC3CC7EB6333C662647A49F3318B531C9C5F5A0A924B501250218196BA66E6C9717190A6F94A76AAAB478C69EFD3C4760E694C234563EFB2BB9743BAA466B3CC54017F8A482428D8F1BC094B9AC2369557E0CC2712C1877F718BA712FBE76CA1BE3C01D6C44D435192113A5C362C18BA10AADA28B7B98564022163542C35FCC6EB59B0A7C3621B94471CCF691CE363EB0F486DEB91D3DA11E2C031D2C331C32E88D42E6BF8FF3C025EA44732B1A0A2B49803A4969DA9F868398B5E88F1C92745A8CB9D64C65187104DA24B3D1C3A9571C75868117AB5ACE698B50E329B30F3245CE02B032802D7695CCF9778BC0B622100C35AF184DDAEC743628AB053405C115937BBA2D383293D4E93E7726AA70C89DCBAC6ADCC32DF0F6CDD88CB8F1C9513B230928052843DC9388BA593154621D4B6F2C042D1762B9E28B6B605AAA2267A441F775720C7D5DD96900EB5C326CA4AF452A637717D41558BF59475AC34069B87B2A2086CB34945EB21A5E79CA47B18ADB7043CC7482BCB52CFCB6C44719962E045ABAF88BC6DB92B09219AAE7C74453B86D576AFA1571E86B1BBF28B4C3D82ABEEA9FBB3B8836A97DEF5B0141794A9036B205C87D3812753DE74C071C3C3F6B1A59AA19552C2F42342FECE63CA27997A9B98F220C20F8F47C5E3021E9295983C757E24088D5D5197F5C912087C35D0A114D26647E2CBB1C16A0AF9C471F90720CBC118C0AA2D4A0638F3B02C33849FBA0A94542492260005F959AE3907B27F2A7F2602CDAA2109654078C2A90379A5E9D49894B007E6F854AE93520BA142B32660A7FDCAB877B2E0C68756B1324D3B9A606B4291C15B5429060833BB6575CA0E5C7689A4A131E26166E984A9CB06AC91A9991F978D5F6310AA91A1F4B14BB802B4C008CDB70ABB8068AF3C40DB979884FB61767C260B6B72B3A6BBA2ED2968B83689EC80D387ABAE88C184CE166DC0A2D096ACC36DA5F925430FB048BC1FA4246B8C0FD103745376A4BF858A3310A7E611B29F830F9C5C57166AA0FB3AAD45B6C55110562ECC50625384DEC579E5B37303C8C115801FD0617BC5133E0A3A1A1BA5B1CF51D87009CD5F617A0B1AC9970722784407624451DD8725BF4874321936B0C333892CD2E3097517604A1657B24220558AA766EE44314C780A2D5BB271A7E8A8149C08C8F65B3A293431748CC03E0F3B1C985096CA181FD41C50C775C667CB67B75CB91F972E5AA6CECBC0175676A18971E2A0B682EF16D66D87815F8B662AC427F2B4B48DA88E407495154322F1943F331B0F7B1A04E9712BAE9B672440FA4729253D09473BBB023B91281357C88679C1897AF4F096CE3A38F9C88A3AB847E15371E6C8B590DA6899ED640462BB440883CCE06CADC8CA113676296DC5BD1FC57CF829216CB3E32F5C9DE384189C5688D164A4E480A0424973A476170C63CBDB094AF629570C35EF97C341DE3279DDA717FF823EB0A34AE153E07427949AB07B015A1CF32C531D952F139A8453464F7360F68B04EDBCD136DFBF32AE6F93BDF366E855FD0422FF874F2B65947791ED43084F92B2B0B485987B6F0ABBC825E85FC66DB25478D52D1C387AB92FADC4B6F04B758B52CCB2D472EBC07A214A743FE31D8949D9EDB652EB7C442B72B9E21" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "ABB31CC188F3B1147252EC5E36C5E328A3EE1FE7FE283F79AC948130A77FF3100ABAF6E7ECC4040E4C55EA78864C341B808ACCBA04C5DFA29A09868C02FD695C", + "664A6EDC9B4647C3C5BAFC25A1553BD1E717BD06BB66F177E5D8C67029574D30685E2BBA08C44B181135F934754AF0298D378405369B7DA47C7EC7505E6704E3A00E2608025A40A0061091F5B3B45ED622CAC377B624AFC8560AC63CC2E5E92CC35365DA676176B061A3AB9DF8045C920B82D7CB2D867B5F8280AAC43C3425565DFA43BA7BC062FF82083B7C614976BAD46A80FEF316CEDB2D47E59E3CA48DF5D176DD2BC279515F6D705CE1725CCB51B5FA17357CECBDD590449805239A42CADB028905C6BAD4210E7AA662FA2B2C7D795F305B1A2C950646787677517BD771CD88C138C6310343D1CDFC24ABEEFB14256BCB18555F11F5CB10596A06890F438A6A3F65A4512A967EEB7C51619C15776ED9289F367224F6784296979E4619CB25C1AE6A09A90FA745BE2179C75198B38242A5553A4D9C37D97528CF3389FA935514B63371E60C85F28E2F1B67B0025C6FCB0FD6A80C419B3BC3551864CCBF38861DE71224C7191710DBC40F495BD6F88009A0255B328361777F73C07177826C72922CA33873E4E99F9D75BE3564BDE6494675969B9C505C333874D5E121F9CB82409C6B9EFC6B1A89A74204767B097A737079C868AA42F0CC17B4315B27C9A9F040259846737BA32FB991287CA3B385B9641704DB87BEB5F17D5933C1BC69A83AAA97B106741B8C1F98B56A513A36D818AD0F477C17C3C485F23D721533730A66EC854AB3B7693FC29313EBA703280BAD29C7FB9B68050AC2709A1C9C8A115E9AC918091106EC009DE86483A3607326874651B7FD3C8966875E6A04956927A8304C9CB317B8BFD16443E947AD380C481C227BBB22B2330CA5C502F572808090BE5D746FD7C28FF7DC6BC98A343DA60A1F4C2548E48F16D95A6D2955E6C250EA41391F6B2EC6180959039635B6A1187552AA539D56D64AD06031D5218B1960629DBBC3FC3530CEDA508B6C0D7887C58602601E43A8A9A74E5EC557A79C6F3CB733A2E49BBA186AC3EA7A62491354666098D6CBA3867D7EEAA10355BAEC52BAC59B5831C1B468B96DB79A943B38B99FBA77A1218CE16165C1334FFAB84EEFCC8B893A505D167EADB5090D90A261F030C8E82AFD6B98247672DFB0369F145BF30453240766F7890E2353AB8E9550A0E19A3F958701B42F5D844942671D69AA40FEC84CC93124C2745AE2F62994D01B1AB3C58D107ACC87A4DFF91E34088CB9B766DBC78C28B925AB4AC03107916CF03DFFE9094F69B2B596AA6661581D003521A5947657410E6069C1470115E7A1CDA20A89F98A71121FA0979D5DE94DFD37A31D5B6B47A17EE79AC415817299352E2021350A3B2C0D43CEF42C6696F24157D4A2E938B89F755296687460A7543AE31A09393595923AED4A49DBCB457923A7F41137C366BC6AF50A92337EF974A3262A5CA9B6A95D4943CF1C20DD7CABAD8599DC227617A4C30C19928494C02612BD25CA2060767D974673F0B6B1DEF2291F0C50434A4E3018557845CD5C401DBB97C11C71BC8521953DA67537698B0638CF1B607EC6115FC2D082AD787395F09513F05E44632D95A81C9AA38DEFF3914C137B667A0529D308A1F20468B942DEAAADDC9268FEF08C9D802DE9EA62E68A0C53417E6292C2D2D058410B10A7068545479B57C4209D3AC6EB0984078BCEF748BD503C9D47C6389B916635A891A1E70E88E3B7E61B57402A3B72E15DED603CA98C719B85862AA51AC1A8639D311356D49BE688C09707B667A05B8CAA8E392016F7F6A8859ACCF4B69AB4EB140C5506ADF80A8D485D6AE7C8DC72811C7C9C08573481B25770F615920861B8F0C8FF61B340DBC500602E9BD400A93108B6E158FB23BCF7851B73C5A87710B624CB2665865F5AA88738D9A602A33C86E65090AC29F9D6513D6B8485FA5CC9CC16BDD9A684B67430A2565651282AA21829C9CB82A301380B2C9B148DCE49B4E8C73846E52A8607136FEC79C37676E66620D9CB7974F91B1553403DACC228DA791C86140198224242B8B5B32F5192ACDF423E08D06B47B4B6A2484CF2160B83D8BAB0F60CB0D0751DC85BA4CC221A052528B796348B495FF190DB69257E686D031B0ED39B0239939550897BFD0265B37B3E2AF859D3959EF8711D2DB0A9335C5686A70D2A11C41D15C8D40A85F460915142BCB668C9DA40C911EF05AA34A3514F3B67ECF15B0B71016296A1D1911EEB23A53E63C47FCED6F4", + "C093800071AFD9A1686F5A536228CB02DBA8323216948B6F31F1B42BB98B171405D64C6CE8B80DF69647A2E377B6338E7A84BBC05B9D1934C5E0C124BB972F9B50411A22105034A9DA304B442C1BE1986C0D4ABDB4FC92CEC1C3C5530927A7A9B8151CBB227EB2B6144FA77D621118FA9A3ABD02A251C23EF6813E5D70C31F089636E90CD4A97965CCAF2AF505CB9328FA1138AFD174FF3A3DCACB1252C5CD3EC1CD438271B0D87F9306A7A94746BF409AF58C31876242F54983A2BC8E680A1972D4149E38AB2D68397F7432F5882559405522D8A070D2558C216641877AAB6ACAEAC38DDCD94D733A4F302766F2A3174D40712684AF170B95FB305C959BB631D50B48F2775D6632EB4C2BA2FA7E0033645695B4D0011AB48525EEF5B0E4E1B95DBB505CF05A8E4A9A1A9033E42096B7C221C7625AF8B19FBA9AB27929B4192018F987BCC9D143D8795D651C0D29F06E71B45869A27EEA595B7E786B9BB4BCF3B051D27BC8C353187E4C590524025B552E3E597A74A09266524FD15C880B18AA3A7985BB7141D2ECBA23591B9484600186916A44B3B54A641D58250AB507217C7480A16AC4A39D67202855610EB8CC080577876BC2C9B33818A20C86D7E7BC65770D61F72198E47B6A38212CF6C83BDA9182710E5523A7E1E9894045410E657DAD399F15A17BC38A7CCEE98525BC8241812896263823A59E110B8D978BC4ECA4B10741B6B023B555141FEC549CB56489188B89F62B63DC4BCF468143EDD7027E77738785273F909B46E4C91D130A9E707BA56959EE244ECB76BB5DCB549F0AAF983526C576B71A0A01C937BECF89087C797576A6A416383337A995AB3460E08283CD8B93E2651E923C5CF5865E464B6000DD442838AD85E81185B7050E52955AC6C377B2CCDA9B0037A3B3B480B4FDE7CFA41B3FDB0B1383E47BDADAC230A44CE649CAF0B103A49B8037EA8BB01132131B1CBD0428AFA2B531991715019A06218C1DEAC25B19AD83E9057BFB1ACB8134B2FC05D94A7F5F117B2C6AB904C657FB15471875AA29212A75C9044A7674F98427E8672E03C649B770317D2A8B989BA8E279544F5892B95B711BEBC83E03BD3D295394E118E7E434FA3750838B66CF40C5BAB67384B9176F0A33A1920A257196D590B3DCB346F4E26E01496DD0FC0BABA5A62F4420C69365CFC723B2324F7A19905B48350AA1910F476C67686C211C2388C084186A5421CB432635AB33F26C86C7B7FE20216123A788FAA7F9D2782039A236669D4DC21C2AFB6197D0C04FF7C8B5EA3B52E5307845BCDADBB2A9C093ABF40DE53A1D1071CB523C05A9F53A6112991BE22EF91246164A2C753C0BC6180213D0615242B92D0C76CB039C13E9C79B812399055F5E7A0CDB8120A9ACA140218F455A9CDA494D9BAB0840704D68132343C49984526747394DF7B7CFDD97A825D55E6135C1EA0235F29B0B36C849C390477C97BC43106B7AB88E53101A308A17EEA81B4E7A3C6ED453179513B6702A194B6DD68C0E7D1409C3D86742C1826DCB5CBE9A162723ADB35175DE555C3F448F31D1BCA18964F1D13BF696510861886C5A7D26F2CA3861459E770C6EB3C61CE1B1F7CA0ED2716FFBB414D6E41567D7C4536C13FB2381A4B575ACE10923B819964AAB720A1DA7FC97C482A196D70CDA17C605F008E91B421823C3B7C00F819345EF1C6749D81BF6F5C4EF04CB80470E0E816887514B203C9ADF66BCE4764FF5050B69D224CE5A2A15F8568317A2BB9257C20B738B65AD2CF24140405E5F196F860C7C1B911C095183063300DFA58C4074C750FB8AD5A13D35B3091D0B2601244A6DEC902D24A0D5C70C99490285621718C97055D21578BC9305459BBCB63E70406E5E1AC375778E9D300B888072AC67A31DFC6D647530A8EA60816045F86C2B6C333B3D7920899C315EE7A183206425E96B5A1443FA1608C3F8771AE2A0FDF0AD4AF494009BA7156A9C70A73180DB1F409339CA1C72753B0D3F89C04D4177D0F822C559A144294F4C75BEFA8B5F5364410CB1009AEA92242CC18DA761CDA9023401646767B8A502BBC3647009237833473B84FC30D39379656A51B525A1FAE078941CC42C9C24E80A3C9DC94DEB129EB84C29022556FAC59E8B529124A84258677BCA7BCAC936399968057F75176F3CC3664A6EDC9B4647C3C5BAFC25A1553BD1E717BD06BB66F177E5D8C67029574D30685E2BBA08C44B181135F934754AF0298D378405369B7DA47C7EC7505E6704E3A00E2608025A40A0061091F5B3B45ED622CAC377B624AFC8560AC63CC2E5E92CC35365DA676176B061A3AB9DF8045C920B82D7CB2D867B5F8280AAC43C3425565DFA43BA7BC062FF82083B7C614976BAD46A80FEF316CEDB2D47E59E3CA48DF5D176DD2BC279515F6D705CE1725CCB51B5FA17357CECBDD590449805239A42CADB028905C6BAD4210E7AA662FA2B2C7D795F305B1A2C950646787677517BD771CD88C138C6310343D1CDFC24ABEEFB14256BCB18555F11F5CB10596A06890F438A6A3F65A4512A967EEB7C51619C15776ED9289F367224F6784296979E4619CB25C1AE6A09A90FA745BE2179C75198B38242A5553A4D9C37D97528CF3389FA935514B63371E60C85F28E2F1B67B0025C6FCB0FD6A80C419B3BC3551864CCBF38861DE71224C7191710DBC40F495BD6F88009A0255B328361777F73C07177826C72922CA33873E4E99F9D75BE3564BDE6494675969B9C505C333874D5E121F9CB82409C6B9EFC6B1A89A74204767B097A737079C868AA42F0CC17B4315B27C9A9F040259846737BA32FB991287CA3B385B9641704DB87BEB5F17D5933C1BC69A83AAA97B106741B8C1F98B56A513A36D818AD0F477C17C3C485F23D721533730A66EC854AB3B7693FC29313EBA703280BAD29C7FB9B68050AC2709A1C9C8A115E9AC918091106EC009DE86483A3607326874651B7FD3C8966875E6A04956927A8304C9CB317B8BFD16443E947AD380C481C227BBB22B2330CA5C502F572808090BE5D746FD7C28FF7DC6BC98A343DA60A1F4C2548E48F16D95A6D2955E6C250EA41391F6B2EC6180959039635B6A1187552AA539D56D64AD06031D5218B1960629DBBC3FC3530CEDA508B6C0D7887C58602601E43A8A9A74E5EC557A79C6F3CB733A2E49BBA186AC3EA7A62491354666098D6CBA3867D7EEAA10355BAEC52BAC59B5831C1B468B96DB79A943B38B99FBA77A1218CE16165C1334FFAB84EEFCC8B893A505D167EADB5090D90A261F030C8E82AFD6B98247672DFB0369F145BF30453240766F7890E2353AB8E9550A0E19A3F958701B42F5D844942671D69AA40FEC84CC93124C2745AE2F62994D01B1AB3C58D107ACC87A4DFF91E34088CB9B766DBC78C28B925AB4AC03107916CF03DFFE9094F69B2B596AA6661581D003521A5947657410E6069C1470115E7A1CDA20A89F98A71121FA0979D5DE94DFD37A31D5B6B47A17EE79AC415817299352E2021350A3B2C0D43CEF42C6696F24157D4A2E938B89F755296687460A7543AE31A09393595923AED4A49DBCB457923A7F41137C366BC6AF50A92337EF974A3262A5CA9B6A95D4943CF1C20DD7CABAD8599DC227617A4C30C19928494C02612BD25CA2060767D974673F0B6B1DEF2291F0C50434A4E3018557845CD5C401DBB97C11C71BC8521953DA67537698B0638CF1B607EC6115FC2D082AD787395F09513F05E44632D95A81C9AA38DEFF3914C137B667A0529D308A1F20468B942DEAAADDC9268FEF08C9D802DE9EA62E68A0C53417E6292C2D2D058410B10A7068545479B57C4209D3AC6EB0984078BCEF748BD503C9D47C6389B916635A891A1E70E88E3B7E61B57402A3B72E15DED603CA98C719B85862AA51AC1A8639D311356D49BE688C09707B667A05B8CAA8E392016F7F6A8859ACCF4B69AB4EB140C5506ADF80A8D485D6AE7C8DC72811C7C9C08573481B25770F615920861B8F0C8FF61B340DBC500602E9BD400A93108B6E158FB23BCF7851B73C5A87710B624CB2665865F5AA88738D9A602A33C86E65090AC29F9D6513D6B8485FA5CC9CC16BDD9A684B67430A2565651282AA21829C9CB82A301380B2C9B148DCE49B4E8C73846E52A8607136FEC79C37676E66620D9CB7974F91B1553403DACC228DA791C86140198224242B8B5B32F5192ACDF423E08D06B47B4B6A2484CF2160B83D8BAB0F60CB0D0751DC85BA4CC221A052528B796348B495FF190DB69257E686D031B0ED39B0239939550897BFD0265B37B3E2AF859D3959EF8711D2DB0A9335C5686A70D2A11C41D15C8D40A85F460915142BCB668C9DA40C911EF05AA34A3514F3B67ECF15B0B71016296A1D1911EEB23A53E63C47FCED6F4BAAF4119B26B063826145BD6F4FFE671176A65BFFDCDD5343BD80F76351CAD040ABAF6E7ECC4040E4C55EA78864C341B808ACCBA04C5DFA29A09868C02FD695C" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "0D63F93A37672C314582D7F69D6C7C1A7FB13538E0B38512B0A8394867714DCC40F84C79E0463EF69B766B6646442844846B9F262FBEB65ADDD980755EC8A7B0", + "6691424DC07B49D5419E9B667ED57A63602654F897A6326CBE336DDF6685226016CDC680C495C71CB48C697B3CE5A04074B51AF15970227077C7A7BE282761297A61E97593621C04EAA117EF5AA09EE30A4A782CB85927D9B7B259AB1CBE7989FDF11A595635E375170043C56C33111DCAA8642CA8EFDA597ADB39D0E771335422CE20B8A55BCF2CB57074E939E9BBBA6D329122435CB91B240180B62E2AC78DD37AEF561AF90BCD94D31B5770426DFB175CCA3061153752EC61C2987C20A83A3DB0496EA8C90E6BC176D3152AA4805039582AF64C39985DEF162192093171B14BB86A81E9FCAC13E48C4C6490A71AA356B41D3A62C2660A130833B2E877C710F2611456621E5BA34254153A011D436738BED4C7F2943FEEEB78265B245BC9880944149A0A73D8B174BBC91D26631D328832961674656C6E8E2767D7895A80E5925E73440849A199653530216641571D53080AC9BB1A229C9CF78880C56429ED643584692A09B43AE9A69141A82541FB3B4E894CB7D298812709D33A0AF6D3A8E16B7AB51C71EE691961253BDC11642AD40666A00CAFE368FAFB582BF4617C41227EC3087FC93D6F824FAF59853848AB0F22920AB8C3C2D10A7496726D742A5D87A76400C0DEFA6453497789DC219F32A4DD5B0ED619412CC5229C92414053C18B4A08C4255753AA8BA9B0C6F23CBF935C96CB13841B2780F024984E60C48D6A42A43181BF59AFA5284294298AF9E20CD0BA58B8BB522A5B2FA5813C0FA2C5D75A947D3407A1967709F3208B6436B2550E65DC0E21D0B916713694A1B015C7A6EF91670F123014D5274640B2316C5A1011259CEC5176844BA4A7170BB1C24406AEA367A4FC6719DCC07F77315930A3A0C30B33AA9942343904CBEACC7E9A6444832DFAC8BB006C2E7F9A4BACA73DF50B558F839500BD1291E668B99C7E9F8681E48B52FDF097ABFB61F125CA25D3543DF9B4B5F3943445263BFC447188B5B7139422E2CDEC7B035DEA1CF6629749CB96B1E7C0A8E3B3DF491F58DC17BE79A82F2150055862FF939FEA13967F383361D20082127DE9D86E3A6550A6819325D72D5F0208BCB254082B524B935710143364201446BACBF169C62ADCB6960AA5E2072342AA173904598FF214B05669EFAB639C41300119A6E2B0AE2F13C481F492E3A735085CB35FBC86FC17B028B6227BB154F368739C71302FAB59918A2A476B23786C8E88B913F7394BE7174B99712296D035E1E9AF4C79662EB58960A876AE97023B763A2E2C3E969327BBAB7E2C33288ED25820005642F59D3A68BEB43563740098232A4252B5CE3976AE62858F55E59472483A2BCCC2BBD4537F3194A4D9CDA7E50DF3C05C752045E727B32E01B9C0E92818A7C75113A5CDE82CE40512508CBE719CB09025712B6CAC74CA60562480B0009B19076F5A94B74950551E001B9774619205B0907793B374BE261263F5E15F17BA8B28AABE4FEC4261F0040A4CA1262A97E1F5C645B6C14001439B9541EFA032AC74B549D151832A6158AC82D6E85831D636AB833F02B534481B06F57017CCB9CB547686CE756487821DF0075834233E9433522510B30A19CB9D0C3F714A7891A972E0F508F1740376FA6271A3357604B03628AF541BB116B398795C63E8FC0FD88A4F330A385E699BEB1032F7578DC1B26C352234559B088DDAB4E3499AD0E3CFB716C120139EF9D683FF471D57730AEA0CA7CB673AF8A769A5A9B1BCF6145BE28A4C87C652859CE4B952EE7C6C22D5C918127D4519187CB240BB3C45A21C8DAF3183D5A2AC8C440B8D7016C755BB75D51DB74BBF50EB8ACEB44AF5721E4FE4834CD16529486B38D4C6977665D4945C21AB57382272B558C9F8F68A6021AA806C0522576D1C7673A0375663D28556A194DF6449CC959124C11C199AAAABC1B53D224FCE6954CA930698A28095A6270B738B8BE3C5CED54D6C51A7554B9E0591AD3D987EFD4313A0CAB97CB6749FD2815B5A8785203364569996D2C798F73D14F02AC95624D0C8CA51F4C829814A89AB156DF8A0D5F60102209FC7AB880372B93B54694D69AB0A4482EC78220CABBF8F39849385B2F1A00FBC47046821A831298D0B605A030503499C8620D83DC010A6A097AF7A20501CA5CF0293121D6C98093565077286597686E8827EB41359EB82906E68C54B08ECAA79F7E76C91486E5B252DAF4DD7E78F0E345B5DC5CBA8", + "00FA8E62594FBE2BBDC21CBF4EC7BFD1BC75CC98A3D61A54E2F7CA3B459B5CB75B866999275A254A77394E53465822348B80A6B66C0B8593C670835FA38B42267A858F51CFC68141A193C50FF26509D61B0D63C002736D6B39ADAED85D330660C3216DC2650BB3B21570C27BADC9B9B02062E58B333367630EC47E597A1C3F3803C8D973003A559E1909CDCA3554F6808B48634695702F9645298A53DD39AC4BDC391DE7034D5BA898720024C47C1D25C6B93AA085115E70EA4D70B90325484383A699DDF640A8169E4D746DE8C3541227967D641130A94B062599A2FBC88822B8B4B73A5FE923A80B52F9D510624519D83BCD67C03C482C1243427F21AB321154ADCFA709DC2B7297927E3F2CA39398781A61920342143E1B2767C0CC54F20A27337C15B708A4FBA5FEF3C2ACB44CF856437E5941CEC995C2022CB3D5C8EABA1DB299A8EE90C8B010CDC595C582F31442809EECF3B37E8B00FA023DEC5C92E1E685A77850445C714FE21D12F285F18CB141A028E55163DA5155195CA10BF0BA1A359DD8EB96AEEAB9E9466B46021095616858702CD2743A3FB86EAFCB0165C4B5201058FBBB1CFBB66387E207E0009677C60F1A08354BB5A39D7218100C69F2F6059AC714B4C70B99F34BFC721C369B46DDBCCBE8D1CFF6E48666DB161D071D48B6BEF3157267A82347918241C8742ED8B8C299B815998C8CE8CA92F52A69A7A125546898A8CF0D53AE8107449C07ADAF502DCEF1837D610BA826CDABD10FE0F6BA1FE6C350B5B35D52C9CD01663554A4E1D15CDDD11F5380C899D031EAC7989A705BFD6554FEBC5436079C78F41E156504E6DC95905C70E2B55AC0BC990E663B91899580B74815E7C23D984AA0198845EC103D01937159798C19A71AD80DC5930759CB8F15C84510E0192BC8238E5863F44BB453254467D31FE85ABFEE73C2F9765481A97A02E8B23AB8B1EBC88A0FA06F0EECA2FC2A8786E763E0473705EC0E9A1B062879A98715AF6413A72F873ADBB59D20739747FB80C35982DB2622FBEC50FA066EB3A4616AFB0A79C63C58A677288BB396F17A5C99C0B191713DBB9D8E0940239AA7A9D364291C46C9735401C0903AC680E099297399ACD9744A56389AEEA8279A327FB19ACD92F333D4D0450D4460624C7033479E6B79178A3537A0AB4DA7D67A7CB576AF21B0725A91F577C9F6504910E67816260E1E983ECEF2BD5E318BFC854400F46288171D32BA8E4D504DF6855BBA346B44CA7FCFD03FFEF24C4FC475863AA5D4C42E8CC16ACD973BB46C3A26F2732CFA4AC2C0AD67DA4399786249B66FBE59368892861B522CBCFA6238428C5F75A9253788259530EA32A27FBA1FEB167022552EA8886282885B7D3221344618B06B784BBB1BCA1472107206EA10885CECB86749A68489B234A5425449A6D96C1F68521269F1783A91C4B88006500CA0DD708F14B2528B255F78389BB6F50CEA026DA214324E90C902CB8522C601A4F70505233465E8B6D31BBC32161B1A3B49773C37080A88C0185F1D843704B83082E46628BA1C53A1C251B17FCB217EA8D4B0308BA2C64C1B061B1B83620DCD836CD864A73C526FD6907A8EE77E1AB5A5138322082A43EE6B48430717D26594A20B5AE1DA19715ACEC9D4B7540B792D823481C99A9EF16E570CC42D4553F3931B3F2747A56A46CF0B84502119AFD73809276C9BD71E20D5279FA35BBF84AC98183DFC674BBCC5025665BDBF9B34E762523E5B22FD5326152A9843024BFE6C3BE4E582967BBE814C26F3F48053601D4596171F78A850F79733986B2AC7B12AEA55A0188141D030ACDB71C69C9253E6AB83B5C1F40389963556003AA03B3674C1179A4948593149C7CC464C75244659D587B78C0272E55A52B86BD37610BD650888BC36C8763E28E92DDC77BCB0E10A1D928028815620572A3DD360386993B4AC908C3BA95582090AC957CF64057CCB8401A49A768750C91741920058C904CF8B0993898ABF9872013AB4818560B2D91207E7D92EDD650B338632FC04AA93F25845B90C3EDAC6C9699FDF40BED4771A9F0B3B93D912A5BB3738FA3BE2E85825A8B4D7F1C3C1A34FB8B55E61EB7F18DBAE66898833770F61877C70876E124497DACB23CB414C61779A15E128B4537C712A70565413AFE335A0C540B848016691424DC07B49D5419E9B667ED57A63602654F897A6326CBE336DDF6685226016CDC680C495C71CB48C697B3CE5A04074B51AF15970227077C7A7BE282761297A61E97593621C04EAA117EF5AA09EE30A4A782CB85927D9B7B259AB1CBE7989FDF11A595635E375170043C56C33111DCAA8642CA8EFDA597ADB39D0E771335422CE20B8A55BCF2CB57074E939E9BBBA6D329122435CB91B240180B62E2AC78DD37AEF561AF90BCD94D31B5770426DFB175CCA3061153752EC61C2987C20A83A3DB0496EA8C90E6BC176D3152AA4805039582AF64C39985DEF162192093171B14BB86A81E9FCAC13E48C4C6490A71AA356B41D3A62C2660A130833B2E877C710F2611456621E5BA34254153A011D436738BED4C7F2943FEEEB78265B245BC9880944149A0A73D8B174BBC91D26631D328832961674656C6E8E2767D7895A80E5925E73440849A199653530216641571D53080AC9BB1A229C9CF78880C56429ED643584692A09B43AE9A69141A82541FB3B4E894CB7D298812709D33A0AF6D3A8E16B7AB51C71EE691961253BDC11642AD40666A00CAFE368FAFB582BF4617C41227EC3087FC93D6F824FAF59853848AB0F22920AB8C3C2D10A7496726D742A5D87A76400C0DEFA6453497789DC219F32A4DD5B0ED619412CC5229C92414053C18B4A08C4255753AA8BA9B0C6F23CBF935C96CB13841B2780F024984E60C48D6A42A43181BF59AFA5284294298AF9E20CD0BA58B8BB522A5B2FA5813C0FA2C5D75A947D3407A1967709F3208B6436B2550E65DC0E21D0B916713694A1B015C7A6EF91670F123014D5274640B2316C5A1011259CEC5176844BA4A7170BB1C24406AEA367A4FC6719DCC07F77315930A3A0C30B33AA9942343904CBEACC7E9A6444832DFAC8BB006C2E7F9A4BACA73DF50B558F839500BD1291E668B99C7E9F8681E48B52FDF097ABFB61F125CA25D3543DF9B4B5F3943445263BFC447188B5B7139422E2CDEC7B035DEA1CF6629749CB96B1E7C0A8E3B3DF491F58DC17BE79A82F2150055862FF939FEA13967F383361D20082127DE9D86E3A6550A6819325D72D5F0208BCB254082B524B935710143364201446BACBF169C62ADCB6960AA5E2072342AA173904598FF214B05669EFAB639C41300119A6E2B0AE2F13C481F492E3A735085CB35FBC86FC17B028B6227BB154F368739C71302FAB59918A2A476B23786C8E88B913F7394BE7174B99712296D035E1E9AF4C79662EB58960A876AE97023B763A2E2C3E969327BBAB7E2C33288ED25820005642F59D3A68BEB43563740098232A4252B5CE3976AE62858F55E59472483A2BCCC2BBD4537F3194A4D9CDA7E50DF3C05C752045E727B32E01B9C0E92818A7C75113A5CDE82CE40512508CBE719CB09025712B6CAC74CA60562480B0009B19076F5A94B74950551E001B9774619205B0907793B374BE261263F5E15F17BA8B28AABE4FEC4261F0040A4CA1262A97E1F5C645B6C14001439B9541EFA032AC74B549D151832A6158AC82D6E85831D636AB833F02B534481B06F57017CCB9CB547686CE756487821DF0075834233E9433522510B30A19CB9D0C3F714A7891A972E0F508F1740376FA6271A3357604B03628AF541BB116B398795C63E8FC0FD88A4F330A385E699BEB1032F7578DC1B26C352234559B088DDAB4E3499AD0E3CFB716C120139EF9D683FF471D57730AEA0CA7CB673AF8A769A5A9B1BCF6145BE28A4C87C652859CE4B952EE7C6C22D5C918127D4519187CB240BB3C45A21C8DAF3183D5A2AC8C440B8D7016C755BB75D51DB74BBF50EB8ACEB44AF5721E4FE4834CD16529486B38D4C6977665D4945C21AB57382272B558C9F8F68A6021AA806C0522576D1C7673A0375663D28556A194DF6449CC959124C11C199AAAABC1B53D224FCE6954CA930698A28095A6270B738B8BE3C5CED54D6C51A7554B9E0591AD3D987EFD4313A0CAB97CB6749FD2815B5A8785203364569996D2C798F73D14F02AC95624D0C8CA51F4C829814A89AB156DF8A0D5F60102209FC7AB880372B93B54694D69AB0A4482EC78220CABBF8F39849385B2F1A00FBC47046821A831298D0B605A030503499C8620D83DC010A6A097AF7A20501CA5CF0293121D6C98093565077286597686E8827EB41359EB82906E68C54B08ECAA79F7E76C91486E5B252DAF4DD7E78F0E345B5DC5CBA8FD1AC04A4DA9F003A6915ADFCB6E489902C23839A00DB3726001F09624E435C940F84C79E0463EF69B766B6646442844846B9F262FBEB65ADDD980755EC8A7B0" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "41A3FA743B8AEB29BF21996C1449C631815D297872A80DA5F2A97D0FB1E76C58219F84FEF373E7EA91FCC6838A57A9708DEF52ADB6A709C5A2EEE822747D2585", + "848C3A88783DF0A82AE0BC9679AC85DBC60E90A1BCAB784DF42B1C20A29A30269DD0F4C7873AB9DB1271C5158264B28C5616B7CBF92AFCB83FA40B8C461A5A62198F80F5AF00FC304EC693553748A0A82DF43B96A73131FF59A7BBFA05AE5A9714115B4648CC11E4A0A23625C338BFB7604FA5836A7EB05332578179AA25BBB022F94C326CE52525B23B148995F39C575309398DF25161428479C0322E54A5AC699D151148CBC86A2B5C9514BBC235305B52284A4868944364BF8FA119746190057C17380ACC5C509FCBD1B84E610909951ABDDA1676CC62F3E45AA9E841F4FC41C3CBC83B541AD0102949D017C57963E1F094F39BCB8FE3B5714221D7F977637943EC51526CF01BD30344B5E247DD1498ABEB25A505551F832616E12E343674D81059DFF22EAC24CF921A33CD11C911FA590151B88FBB08F56A905C4610060A14316B29703826C5995141A2BFA04896BCD641C0FA1CFAFB245129488F01421C611C4360C96333A45CA59400C1CB94C85F0F162BD2A11BFA4783AEF2721D9B0A08A7451738CE3E057993D8399B90B25CD14B23216164FC31F4A39E43E62E772ACCE28AA28A19604D5607734B475CE5928EB98BC79A0ACC5C976AA6A421C4895E88C669231D1C1B8924F643E51CCF312982023A4E2879365312CF9EA862BC4C926F523DDA22A80F075CCB49294CD43DF50238E73C7FCD9692BB432E77EB6CA260CCC50C3AEFF43995BA7DBE25507CE7956AA266DBE477F30BAF7A0B3174D7C2391B08AC997761CC4A069549AC9178FDA481B434241E21CEA4178A9F4030C71C5D93459273F27DBFAA88F428B3CBB1C4F94209B49BB950C27BE37C25F4A523C616995D56C7EEC4222C7519EA4661ACC5C0B441CEFE61425F441843D162F6B0B3B7DB9D37934524D7C753BC66B5451518B5297672B4683A8E84FB6FBC46528D8618FB2B6E780211AEB8108929B0896A6E714AC0E07C2DDF66BB1682B794DB3A1FD8CC027A59EC605DEA106937852CB22C7D10014B36F6016C795F540B79B282A2E43433AFE1A039512A5B711D34BC74F9FA2B69F74EA02325946C3C1CBBC915B96E85BA1AFBBC7060B29006A537FC0AB648D17DF5993ED8CB24A143CFA9215D4CB7185F66674D2404A3F682C400635AA65BB0C4538D886434706488D01600AA9230245EE7303936FA04D656297212B6C0F4479498AE78BA1911D1A179E20BBCE28CA0E001FA3524477CB181968B03934E20809958E556DDCB742D7A817ACC64CC4950C1438FE7144DD9A499AB6B5469D0C1443CA03E19BBFA57A3E6F5C962C0915F3C97B1584DF8767ACFD21AB4E8A69B82A2017857A0490A87692B057994F5527354114BDB1806E08CC7DF876BEBFA9FB955B5FEDA192F190890911D8D6C5F15036FD43C3C4B09112C08B690FB7509F994870B35E5DB3281CC2020E3B6D532798BC6C01874265F0284330ACEE94B1A88F353ADAC6004734EA18039D5329EF185AB655A363FA85771F6CBDD963185E97B84134D4945A38E5A89B289735AEBAD7C3CC55E51675B8621D6B385DB636EFC630068698C6E701C9BCB2975A46FA48B9D2908CA86162626C26EAF588018D5C2ECA92C1F468BCE98A82BFC16336900AECAA720BBCFC920BA584B5F987C3ED9E55FC3768BF6D78D385C0DA3A649D60C82D8C784A45C2949858D5B5133C2A23143A1B7535898E3582F0D945D13493690D8884C377A6145A772C710D7E02D65B9134BA130EC320873341D0536721782722ECBCF288311F86CA2A0298753F78E6AE5300CD30D4C61A8095C06361C7A19D84B53B47F24BCCD598197AD0036157164D1BAB96A348511851C97E77103531C2E617E8B049D3D57570B9951CFD83D3691C57218AF498A5E7CCA948A2542EEF48038FC88512A9F836560E4A36C6B974528572D32428E0C71A35185472B66578BB6A316A043EFCB1BA9B4A375233325A235DCC24F6C68839DE2C6B46279F99215DE82AC40CB1310696504DBC88B598F161B0FD1F6374C590B89A44E7C3532D739708114AA634567A030B503E1A58DF81F4D5057F5990C6AF64B98B89A39818F5ED48B4E70BA5331666B46A78FAC2157D174300677F191B834956695B83154A85D32C1C10343B78A8A32EA023C34E00F70805C10394EB8749C40CB56F3793FF9D14E287B323DC7CD5E8B10AB2173AC13B3F316CC551C4CF5629CB7725FB79FFD1FF1FF0347", + "FB82C889A42F580A49459BA4A855B93EF529AC787F2DC68374D4C9DA1100C9E3BBFBC60E2DDBC59BF77808C69177737EE59685EF6B41318C7CE2933DA466A5DDD82489B14286937A22A7864F4A049FD31643F7CD67389B1B9C64C1135861207E34B237DC30058D1754EF0533606674305BCAE6C737E6585BBAB9B1CA49B36995ACA37549CABB630363C322636AA4063FE1F50EB7FCA6226AC6A0D0116DFB3491DB9C291B14FB4A4F55E19383B03206964492D1968218B94D37B9B73A355CE73C779C3DEA2C0EFF802560ACC86D7052A4634AC401128285529DD008F013C0E1FB44578249307399D088B0DF79679516CFA126B8E3397CBBB97139A3144C52A2CF103C68081CC4B8812D9A08EBC0577972AB60360767D4C8B032831F7869519A190B04984E22A2F6B590A2A035B79A82D8780BAEC5A82B985E545AC17B57A2AB24AF80B801A85A55A9C149B39B51AD873A85D23A00C105CEC7B5D5A894F87B5E7AC21F79D529F3367284B70EB00781E8EA4EAACA5C32E7B7E876BAB694A81AE90797A0877FD363503B468E01C3208B4B8A754914410E9BBA2EF6B75326DA77C2A7A287E27515C9C8F4942DB88A93189869E613A8DF5B966A245038243BCD01820D2007EDF046F9343177258CE282CB87D79F176AB753BAB4E18914D714A8C447192CB3AA85666C2B6779B7E986A21089ACC36A70A13529032D00E902E4FB7682C3351B71201F3086C4311D4A440A31287EF8BB1AB7F36D9546B04F61A67917AA1A1568A2A0337109A7A9E01DF09A2DF8A390F9DA6520C1611E946F0DF03D3F67AB9FF2308178BD300013274957BB541E718375EC280611F2B696148098069B90FC6A34C074963C7D245199E0B5279D555EF4FA438F178A7E84BA4DA895DD57BA0B3CC565711D613944A52836597B41449394D2441ABB489776C566CFB93CDD703CC4610E511B18F6E73E69EA3D74356168900B239CB897EC1609D118C4E814D0A34FA123596395865A7A2610983D03207C98CC8ACE445280E2A80DB917234C9CB8FB2469C466DE9687D4D3514565AD72B54CD9BBB3B02C0C12D4710DF7418841C13023B7BCC67936643BDAA5B4A43A757B7B625ABB01268C2995F399D6DB9F599C8CBBA94E152A6C9E02368B7ACAA915BC5C6A4BA8F5A52D6AA2CC3A4A117649C196CC3F924F89115B818B099EB109461289DB90717CC7C56D48035D1A4BF2F0BCCC4CC0E055BA765791E03B1D1622B5883718AE886CEBE9B97EF13DBB1C5866988FD7811E5C693A718141A7E98986C820CB5264AD3C22E14CACB300457E3A926129701DC6945F1B3F28712A9B830507D50D959444AF48106A17B99C4607ED389333D003EF7440832459D5826A95429BE6122F5ADA2A36755F066C5F5A63AFEFAA36C4C17795C68BFC0A91D8459EBCC7BC24E1354E56863A65333600B5F24834A8B3670BDC837ED977C4D18BF5A76252270D87D796F75C69DFA814B84AC1888A58BF3268A347611AD0C851D426D656468C627ABF335401F7906C5872983AB6DAC3362520BEEAB1CF1D90C798C881D7F908EE8530365060D97C2E1B704C589488DCB60B1622BDC74304DA05958E6468A6565A58600EA6E8CA78A39A73B87BADFA337031184BE559FE42B321C42452B94B6E57321794BF574407A2953799079D0BACBEA1DA141C723066F3BC8839446C33095518A109FAA70FE0011542AC07FB0CB0AB3F5E05B6412967DD1C376EFA6BABFB499C2665973AACA0A5A70436AA707810D8F508AF2914312257A374B40C8962C8E4267276CB3513BA96675CA86860A1F72F4F11530C07B41EF89BCC92CB9FA564C5283D8D1989E40A4AA87022DEC24367D1B6A4DA7CB995108FA1462226961A255857B2264009A74F66344F34408FE609654073382869805B26656B21DC6039E0831F79244F6F173985FBBD8E33CD987617701948A7132879AB69FF5324D35A59D8E275FB6AC3FD55271A3A9A60FAA8AFA75798E68851A2A65A3028EB55CA57000C3559CEF03872A2D7A3378B4808D7AD2DE01BCC1797E1283C87548D6BC8A13348A5BF5359D28C8F578A35A52ACF8D2A3C6AE0A55EC1A11A8382252A19BC464F4DB2CB696B1C5B98774A194EFE89813A950AFF05099353371420A226C971027BCDBDE3A745C25D9E49C8D022CE3A538C848C3A88783DF0A82AE0BC9679AC85DBC60E90A1BCAB784DF42B1C20A29A30269DD0F4C7873AB9DB1271C5158264B28C5616B7CBF92AFCB83FA40B8C461A5A62198F80F5AF00FC304EC693553748A0A82DF43B96A73131FF59A7BBFA05AE5A9714115B4648CC11E4A0A23625C338BFB7604FA5836A7EB05332578179AA25BBB022F94C326CE52525B23B148995F39C575309398DF25161428479C0322E54A5AC699D151148CBC86A2B5C9514BBC235305B52284A4868944364BF8FA119746190057C17380ACC5C509FCBD1B84E610909951ABDDA1676CC62F3E45AA9E841F4FC41C3CBC83B541AD0102949D017C57963E1F094F39BCB8FE3B5714221D7F977637943EC51526CF01BD30344B5E247DD1498ABEB25A505551F832616E12E343674D81059DFF22EAC24CF921A33CD11C911FA590151B88FBB08F56A905C4610060A14316B29703826C5995141A2BFA04896BCD641C0FA1CFAFB245129488F01421C611C4360C96333A45CA59400C1CB94C85F0F162BD2A11BFA4783AEF2721D9B0A08A7451738CE3E057993D8399B90B25CD14B23216164FC31F4A39E43E62E772ACCE28AA28A19604D5607734B475CE5928EB98BC79A0ACC5C976AA6A421C4895E88C669231D1C1B8924F643E51CCF312982023A4E2879365312CF9EA862BC4C926F523DDA22A80F075CCB49294CD43DF50238E73C7FCD9692BB432E77EB6CA260CCC50C3AEFF43995BA7DBE25507CE7956AA266DBE477F30BAF7A0B3174D7C2391B08AC997761CC4A069549AC9178FDA481B434241E21CEA4178A9F4030C71C5D93459273F27DBFAA88F428B3CBB1C4F94209B49BB950C27BE37C25F4A523C616995D56C7EEC4222C7519EA4661ACC5C0B441CEFE61425F441843D162F6B0B3B7DB9D37934524D7C753BC66B5451518B5297672B4683A8E84FB6FBC46528D8618FB2B6E780211AEB8108929B0896A6E714AC0E07C2DDF66BB1682B794DB3A1FD8CC027A59EC605DEA106937852CB22C7D10014B36F6016C795F540B79B282A2E43433AFE1A039512A5B711D34BC74F9FA2B69F74EA02325946C3C1CBBC915B96E85BA1AFBBC7060B29006A537FC0AB648D17DF5993ED8CB24A143CFA9215D4CB7185F66674D2404A3F682C400635AA65BB0C4538D886434706488D01600AA9230245EE7303936FA04D656297212B6C0F4479498AE78BA1911D1A179E20BBCE28CA0E001FA3524477CB181968B03934E20809958E556DDCB742D7A817ACC64CC4950C1438FE7144DD9A499AB6B5469D0C1443CA03E19BBFA57A3E6F5C962C0915F3C97B1584DF8767ACFD21AB4E8A69B82A2017857A0490A87692B057994F5527354114BDB1806E08CC7DF876BEBFA9FB955B5FEDA192F190890911D8D6C5F15036FD43C3C4B09112C08B690FB7509F994870B35E5DB3281CC2020E3B6D532798BC6C01874265F0284330ACEE94B1A88F353ADAC6004734EA18039D5329EF185AB655A363FA85771F6CBDD963185E97B84134D4945A38E5A89B289735AEBAD7C3CC55E51675B8621D6B385DB636EFC630068698C6E701C9BCB2975A46FA48B9D2908CA86162626C26EAF588018D5C2ECA92C1F468BCE98A82BFC16336900AECAA720BBCFC920BA584B5F987C3ED9E55FC3768BF6D78D385C0DA3A649D60C82D8C784A45C2949858D5B5133C2A23143A1B7535898E3582F0D945D13493690D8884C377A6145A772C710D7E02D65B9134BA130EC320873341D0536721782722ECBCF288311F86CA2A0298753F78E6AE5300CD30D4C61A8095C06361C7A19D84B53B47F24BCCD598197AD0036157164D1BAB96A348511851C97E77103531C2E617E8B049D3D57570B9951CFD83D3691C57218AF498A5E7CCA948A2542EEF48038FC88512A9F836560E4A36C6B974528572D32428E0C71A35185472B66578BB6A316A043EFCB1BA9B4A375233325A235DCC24F6C68839DE2C6B46279F99215DE82AC40CB1310696504DBC88B598F161B0FD1F6374C590B89A44E7C3532D739708114AA634567A030B503E1A58DF81F4D5057F5990C6AF64B98B89A39818F5ED48B4E70BA5331666B46A78FAC2157D174300677F191B834956695B83154A85D32C1C10343B78A8A32EA023C34E00F70805C10394EB8749C40CB56F3793FF9D14E287B323DC7CD5E8B10AB2173AC13B3F316CC551C4CF5629CB7725FB79FFD1FF1FF034722DAE6A75688BD9C1E7F50A40E002CE2E10B19A9C469EACAADA696F2D56111BA219F84FEF373E7EA91FCC6838A57A9708DEF52ADB6A709C5A2EEE822747D2585" + ); + yield return new + ( + MLKemAlgorithm.MLKem1024, + "E81D3AC5B001861ED765F7960E63EC311D97110F2135E97ABEFD7A6664165B930D79C9327545DC957BC15C193974585740E58BB95BB52AB24FAF0B8C9601DF34", + "BBC8AECB6B29CD13CFCF6C3B12593E8440722A330E54B7B9284BBAF746C79B188E836A317341A5B82CBEC8EA6AA8094DA4C1C999A031783817A5551A3D6730FD47BB9BD79DDA7A6B754B731A6678BEE06FA827CFFC603A960562925681B6C82A92CA8762841F80965EA71773C59A79F92913E75529F8DCBED9A9344B1A10A6C29C96C2B8AC1CC6E5A4A9BA4792727B030929375D17168DDCAEC729A134A268C4A005F6040E148ACD7D7B1662461C99766060666249139E6EFB9FF547B7FAC149DB1AB7B09C9A6686B47E683C64D0AA4420CDCE20B6B76A8087EB19A326B89F37CB5486BCE5533E5B996E1DF305040B7A49534A7C4C046E3B9BB26470E99018C9FA4F0E1919A5074CA030C541A514B40151B4EACA03D5CA8E2B8FCF3377A7FAB7876313A3A423523313C6D16487607A65B47E3107AE8136C4E4308860DB1499CAAA77957429A52F9388212D7B1A5ABB0F144811A9B20319E75EEE515B084532F92C1EDEA51056FC7BA313ABAA591503FC28325774BD3AC644C3001B05A15AB583C8E80D394338112488BFA13EACB199C0B86D4FB515A68B6911730E27D96FAFB823EFD0C497FBA5F1A46391F1B74C2C9262934A1D38630B183A32C5350E26212DF067F6A1BA9FE53F3DC17BAC0C5D5D6A7F9BF21E1E9433DB35986A1836550C6A42C206A1988608D29C68FA6053F5168B64641080077A255F34744A06ACC37D1AB00F098F3953C7A659620B7C7DC320AF40E889CD3407FA297818B01F5B03C8C49159668ACC1C5611014A671CA48525540E81972D06C4966433806A50BD2FD0B0F0F185722ACE9A01CE9DA6831C61023AB56E02A718E1788D179854D27521E4E18DEF091396A5226AA95D2D89007435AF73E232E77A6FA5A506C93B4C98682C67DB28CD8B25887740F58686FAA696F6072FB75300D5F05044E06DE7734F2E01CB8FCA19787381E870BB5C282C5DD9A4568428E4CB82DD5579DD931BD68A56B794220AA538DF667E9DCA25191C93E2E90F39F233AD9CBEC0341A95F0B1DE7C7BB2DB2530502DFDD59A04520CE3CA282BB93543977E4B6B38BD50C872A5AE2D289AB512966EAAAF83450B6C3C2A49B15EFC8671030B3CACB49A6A243FCEAA428691CB3CF429BD34BAF4D9CD80264D3DF827F7DA738A15CC55D2699E45645F32B56398C89728AEB523C7E58ABD8D588197067E8B8A9B144288B442606D889B91C500C36B4629595A3388485812850B204C46AC3194A4A1A412B9B6645DFEC1130FE491E9E6192CA43AF27032C261426B67AD18D17ECB4BBB54C48E212B682C55AF35EA9C4EDCACB1D4A08CC14BABA81E5C723AC821786C037D8E142DB5B259E2655FB7E084D80443D1F166B634B023D97BE6753287B2358BD44EAD2578A9E5636DD96B5FA667A1A6889CAC04A1A552F336549FCA1512880A392781211494F1B47E708713E1EBA5F7767A61F97D8329417440400F835A5D38144E481AA7A2C9B8BCB3F32120BAEA5CAFD67078474EE417BEBD3832D2A2A6C1B1714971790C390824D86C321A9E2C2A5433C0AC31176DB80C5A7643862976B8379CB3AC71A64B46AD30026B836B8C884289F2D5C55E73A281A52573473247258824D496201C23D46A7897BB528C5C2F31101B61D695F112BC17F36BD8265928475955446CBAA1A7919B4BA448C8E80A3D5BA96F5A45966CC03E4FA2BD7913A75C881D4DAC62A2A83E525A36AB21B272EA2A957680B1FA8673A36D9E54B65A39A85C83BAED4937F0E651C11468AAE97F6589B6ED675D1B696C2251BDBD462A7F70AF44F810BA594C0AA7796FE85DDA54C8BEFAAA79D5A6BA591BFB129B6AE0A25E646A69B7A98D5BBDF8B140FAFC011BB265E175600A83397AB3187EB1ADDF9816952C0B13D73A0B3C9567B57F26818060A0B6A6006612634ED433189D4304E8C77420F14E98E984C1F3591AB15DD6107572955E8D73707AF7C1DA79B1D6F1058A801ABF26B5E39033B56119934CB8BFEC3107C0BA2038C78172593AD04A0DF4A3F8729C303317158766E9389A64A4C05C45858CC6116BF564C962843D3B1F6EF9A3625B8850421F98F2A9A4303F791C4C6C2C91E48B36A2D7BC54458455838C080CCE9EB8C774145490755C9AB6B74E638E7295AFEAFA8A1217979AC43181218D7BA6A8B921A205CCBB128B22FAA3A209A9221DC13F6FEA2AF48A9BA9219FC2F7BB064E325BA800BE2F", + "32F876A30283DAB3A558367981D0868C750A11601D11EC9282D2AA656614ED160A7F66104AEB2123E93233126809D7B7CD3A7F93796FEEC746D3C94815D97F2C26381737969F9B6B68FBB7B20CA4F886A23A0108283CC034300C70E82A59578DBC7645E2380626B028BEE39FC5EB11C3C01EA6422B990A255C64B4E423BD5703A4D579855799390F352FF3A5BC9EDC6EABFC91FEE499A9CB87ED847BDFA82304114466309C38208422D01659B82424297C7007C0E7E821E0BCBBE7810D5E798056C658B8DC8C983BA30E355954BB8FECA0969CA4AC1FA076C0583DDC95B026BCBFE2CAA443BA784623CB089A1508DA54D10C1A321343856562665000FA0C3234C9A1E5650C6B7B8301E21922E19E35D1B8001515EBB0138E87723996A84569C9D296B8F543CD241B2CF99A64666078B59B7832653E380AAC47872117CCAEC390CB3A39AF55DA9E93131FCBC52E206549E237B8478CB76C47A4F13C895E56CC67852598A23052520CD9A5693B305C50794EDA21BE450288D54049BF9BABF689869BB19847404497225D69B1CCC5E38EDC8253B501CFE49B83E16689DAE391DBA018252005C3157F13D86E0BCCA9848328A017BC8DA714CAA0282EB78341512B7E56B360118EFFB323149040750C0805E883F0715091CA8065CA761AC441272AC058B12DAC5645181ABCAAA46B1453924E285012F6C6B2C025F801C50366442EECB2884C899D50B4D224CC131C2D28367C155A132E62A76B92C5B090B56BCB91D30663E01B671952B7D2A2BA6A0848CB60C531542F6B42210829BFD448A60CE87BF98BC066646BA9091557015F3E34B8D2634C83F1C7943660865811F0984CDF01CAF3A510A30CAA46EC33C9E53118C88B786A919F491210E6BDC1567D55247ED4B50D9EA938E6160BA08AAC4DB61093894E74541156C1695559073A240332E07F3B45374C5545D832459EB5CD57E3B307D0BE6B51958F907DDDB0816FE8792AA2225185519991230D1CCF6B43CA7D9298E1061A58431820A9BCB9EA8F51413155C154B4BBCD933015BA86CACF0CC283F40E77167EC7807A217873A233A0AEC1064E03B4AE255D00F53DC4D2911F2C4AB663088592C6DF0A792107465C7954760891271308E027533064461B7733DE143FCBFC07FFB62EB1BC755CD5B6F98B7E4F3A905B069B01116B46A80ED57780EA147AD6D06BD75AA5BFDA8F444AB5B66648B63C06B24A9719161E9E6907F2E41F7BFA862C70B9D057502ED2BC2AA5C09876282EDC5A5912419A7480D7A00C9F4061919C44BD33A1A6260E5297113E63B6F813606135A040A02A3047B59D3AAED5108C0215C8DFFB24E4FA172C453841287BA7A146162C38E6D505697162101667C56B027FE7B562E199FC6039A51A5332631E3B66C2D4816B61CAC3D98BA2415C7B03203D719675D7012B785343E9C42DB5D88CFF385B6F8909BA346AC59782107B4D2586C83B25CB2A24A422B23FF63C915C19A66D7C8BB09C2B7CD5757D53A0E2045E427927CDE022D5808BC6D92AB85C7355DC10BA12B45674BD7BBA909787425C6AB3DFB7C4C3EC49F666CDBE8C2F51300F91D9A8F665A45F6B8500F7CFD98C57CC9366B4211130D27CB15217D111BCC1124B461A825EAC4573D3B1A34A1BF2FB93422263E6548F9986865696453C209F08452D633C8C74332D27BC4DA2A39A90301D59B99D0CFBB81AE921AFD30EC23385534426AA2610F4FB741BB450907A1DA9836642F822387757331700EE887BB0C2589A222E89AA2EF9C965D5D4B9F4BC3911D3186F3551D4331EB1DBA52B15963EA91C453174D3983268D40CC173B0DA555DE1B18139490D0478BA00C44975511DB43B2BA526629B38C2650025E863A6628C417DB8B3F0710A0CEC2EC936359261A4D887A8C1702DF83545334A2821250E5BCB9A6C7A322605B1B30B5AFB23228A13A14658BCF7746FCE3BC641A3201F66B6FF92724B1390384008D323B4947724EEC8A8EEC0C8BBEC9F8EA58426A784B79BB754392C3A79CE9937587179388541C73AAC3649F60FE92B320A68461E97A82FF781A361CE0CF9CE900793C4A0A7CEF05264E8C959953C39B4568A1A632E816B3FEAA919856B89CC05A266A5768B716EBB0989028D8512A46EA820B603882BE84632045D1C572158549028F82EBBC8AECB6B29CD13CFCF6C3B12593E8440722A330E54B7B9284BBAF746C79B188E836A317341A5B82CBEC8EA6AA8094DA4C1C999A031783817A5551A3D6730FD47BB9BD79DDA7A6B754B731A6678BEE06FA827CFFC603A960562925681B6C82A92CA8762841F80965EA71773C59A79F92913E75529F8DCBED9A9344B1A10A6C29C96C2B8AC1CC6E5A4A9BA4792727B030929375D17168DDCAEC729A134A268C4A005F6040E148ACD7D7B1662461C99766060666249139E6EFB9FF547B7FAC149DB1AB7B09C9A6686B47E683C64D0AA4420CDCE20B6B76A8087EB19A326B89F37CB5486BCE5533E5B996E1DF305040B7A49534A7C4C046E3B9BB26470E99018C9FA4F0E1919A5074CA030C541A514B40151B4EACA03D5CA8E2B8FCF3377A7FAB7876313A3A423523313C6D16487607A65B47E3107AE8136C4E4308860DB1499CAAA77957429A52F9388212D7B1A5ABB0F144811A9B20319E75EEE515B084532F92C1EDEA51056FC7BA313ABAA591503FC28325774BD3AC644C3001B05A15AB583C8E80D394338112488BFA13EACB199C0B86D4FB515A68B6911730E27D96FAFB823EFD0C497FBA5F1A46391F1B74C2C9262934A1D38630B183A32C5350E26212DF067F6A1BA9FE53F3DC17BAC0C5D5D6A7F9BF21E1E9433DB35986A1836550C6A42C206A1988608D29C68FA6053F5168B64641080077A255F34744A06ACC37D1AB00F098F3953C7A659620B7C7DC320AF40E889CD3407FA297818B01F5B03C8C49159668ACC1C5611014A671CA48525540E81972D06C4966433806A50BD2FD0B0F0F185722ACE9A01CE9DA6831C61023AB56E02A718E1788D179854D27521E4E18DEF091396A5226AA95D2D89007435AF73E232E77A6FA5A506C93B4C98682C67DB28CD8B25887740F58686FAA696F6072FB75300D5F05044E06DE7734F2E01CB8FCA19787381E870BB5C282C5DD9A4568428E4CB82DD5579DD931BD68A56B794220AA538DF667E9DCA25191C93E2E90F39F233AD9CBEC0341A95F0B1DE7C7BB2DB2530502DFDD59A04520CE3CA282BB93543977E4B6B38BD50C872A5AE2D289AB512966EAAAF83450B6C3C2A49B15EFC8671030B3CACB49A6A243FCEAA428691CB3CF429BD34BAF4D9CD80264D3DF827F7DA738A15CC55D2699E45645F32B56398C89728AEB523C7E58ABD8D588197067E8B8A9B144288B442606D889B91C500C36B4629595A3388485812850B204C46AC3194A4A1A412B9B6645DFEC1130FE491E9E6192CA43AF27032C261426B67AD18D17ECB4BBB54C48E212B682C55AF35EA9C4EDCACB1D4A08CC14BABA81E5C723AC821786C037D8E142DB5B259E2655FB7E084D80443D1F166B634B023D97BE6753287B2358BD44EAD2578A9E5636DD96B5FA667A1A6889CAC04A1A552F336549FCA1512880A392781211494F1B47E708713E1EBA5F7767A61F97D8329417440400F835A5D38144E481AA7A2C9B8BCB3F32120BAEA5CAFD67078474EE417BEBD3832D2A2A6C1B1714971790C390824D86C321A9E2C2A5433C0AC31176DB80C5A7643862976B8379CB3AC71A64B46AD30026B836B8C884289F2D5C55E73A281A52573473247258824D496201C23D46A7897BB528C5C2F31101B61D695F112BC17F36BD8265928475955446CBAA1A7919B4BA448C8E80A3D5BA96F5A45966CC03E4FA2BD7913A75C881D4DAC62A2A83E525A36AB21B272EA2A957680B1FA8673A36D9E54B65A39A85C83BAED4937F0E651C11468AAE97F6589B6ED675D1B696C2251BDBD462A7F70AF44F810BA594C0AA7796FE85DDA54C8BEFAAA79D5A6BA591BFB129B6AE0A25E646A69B7A98D5BBDF8B140FAFC011BB265E175600A83397AB3187EB1ADDF9816952C0B13D73A0B3C9567B57F26818060A0B6A6006612634ED433189D4304E8C77420F14E98E984C1F3591AB15DD6107572955E8D73707AF7C1DA79B1D6F1058A801ABF26B5E39033B56119934CB8BFEC3107C0BA2038C78172593AD04A0DF4A3F8729C303317158766E9389A64A4C05C45858CC6116BF564C962843D3B1F6EF9A3625B8850421F98F2A9A4303F791C4C6C2C91E48B36A2D7BC54458455838C080CCE9EB8C774145490755C9AB6B74E638E7295AFEAFA8A1217979AC43181218D7BA6A8B921A205CCBB128B22FAA3A209A9221DC13F6FEA2AF48A9BA9219FC2F7BB064E325BA800BE2FA774D27B8A7B72200A560150C5B9CD86F35FD766B0C93A49108F2416599CF2360D79C9327545DC957BC15C193974585740E58BB95BB52AB24FAF0B8C9601DF34" + ); + } + } + + + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.cs new file mode 100644 index 00000000000000..4b2bc52cef58e1 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/MLKemTests.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.RemoteExecutor; +using Microsoft.DotNet.XUnitExtensions; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public static partial class MLKemTests + { + public static bool IsNotSupported => !MLKem.IsSupported; + + [Fact] + public static void IsSupported_AgreesWithPlatform() + { + Assert.Equal(PlatformSupportsMLKem(), MLKem.IsSupported); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void IsSupported_InitializesCrypto() + { + if (!MLKem.IsSupported) + { + throw new SkipTestException("Algorithm is not supported on current platform."); + } + + // This ensures that ML-KEM is the first cryptographic algorithm touched in the process, which kicks off + // the initialization of the crypto layer on some platforms. Running in a remote executor ensures no other + // test has pre-initialized anything. + RemoteExecutor.Invoke(static () => + { + return MLKem.IsSupported ? RemoteExecutor.SuccessExitCode : 0; + }).Dispose(); + } + + private static bool PlatformSupportsMLKem() + { + if (PlatformDetection.IsOpenSslSupported && PlatformDetection.OpenSslVersion >= new Version(3, 5)) + { + return true; + } + + return false; + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/OpenSslNamedKeys.Helpers.cs b/src/libraries/Common/tests/System/Security/Cryptography/OpenSslNamedKeys.Helpers.cs new file mode 100644 index 00000000000000..59d68eb26e2738 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/OpenSslNamedKeys.Helpers.cs @@ -0,0 +1,67 @@ +// 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.Security.Cryptography; +using System.Text; + +namespace Test.Cryptography +{ + // See System.Security.Cryptography/tests/osslplugins/README.md for instructions on how to setup for TPM tests. + public static class OpenSslNamedKeysHelpers + { + private const string EnvVarPrefix = "DOTNET_CRYPTOGRAPHY_TESTS_"; + + private const string EngineEnvVarPrefix = EnvVarPrefix + "ENGINE_"; + private const string TestEngineEnabledEnvVarName = EngineEnvVarPrefix + "ENABLE"; + + private const string TpmEnvVarPrefix = EnvVarPrefix + "TPM_"; + private const string TpmEcDsaKeyHandleEnvVarName = TpmEnvVarPrefix + "ECDSA_KEY_HANDLE"; + private const string TpmEcDhKeyHandleEnvVarName = TpmEnvVarPrefix + "ECDH_KEY_HANDLE"; + private const string TpmRsaKeyHandleEnvVarName = TpmEnvVarPrefix + "RSA_KEY_HANDLE"; + + public const string NonExistingEngineName = "dntestnonexisting"; + public const string NonExistingEngineOrProviderKeyName = "nonexisting"; + + public const string TestEngineName = "dntest"; + public const string TestEngineKeyId = "first"; + public const string TpmTssEngineName = "tpm2tss"; + + public const string Tpm2ProviderName = "tpm2"; + + public static string TpmEcDsaKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmEcDsaKeyHandleEnvVarName); + public static string TpmEcDsaKeyHandleUri { get; } = GetHandleKeyUri(TpmEcDsaKeyHandle); + + private static string TpmEcDhKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmEcDhKeyHandleEnvVarName); + public static string TpmEcDhKeyHandleUri { get; } = GetHandleKeyUri(TpmEcDhKeyHandle); + + private static string TpmRsaKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmRsaKeyHandleEnvVarName); + public static string TpmRsaKeyHandleUri { get; } = GetHandleKeyUri(TpmRsaKeyHandle); + + public static bool ShouldRunEngineTests { get; } = PlatformDetection.OpenSslPresentOnSystem && StringToBool(Environment.GetEnvironmentVariable(TestEngineEnabledEnvVarName)); + + public static bool ProvidersSupported { get; } = PlatformDetection.IsOpenSsl3; + public static bool ProvidersNotSupported => !ProvidersSupported; + public static bool ShouldRunProviderEcDsaTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmEcDsaKeyHandleUri); + public static bool ShouldRunProviderEcDhTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmEcDhKeyHandleUri); + public static bool ShouldRunProviderRsaTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmRsaKeyHandleUri); + public static bool ShouldRunAnyProviderTests => ShouldRunProviderEcDsaTests || ShouldRunProviderEcDhTests || ShouldRunProviderRsaTests; + + public static bool ShouldRunTpmTssTests => ShouldRunEngineTests && !string.IsNullOrEmpty(TpmEcDsaKeyHandle); + + public static readonly string AnyProviderKeyUri = TpmEcDsaKeyHandleUri ?? TpmEcDhKeyHandleUri ?? TpmRsaKeyHandleUri ?? "test"; + + private static bool StringToBool(string? value) + => "true".Equals(value, StringComparison.OrdinalIgnoreCase) || value == "1"; + + private static string GetHandleKeyUri(string handle) + => string.IsNullOrEmpty(handle) ? null : $"handle:{handle}"; + + public static IEnumerable RSASignaturePaddingValues() + { + yield return new object[] { RSASignaturePadding.Pkcs1 }; + yield return new object[] { RSASignaturePadding.Pss }; + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/TestData.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/TestData.cs index 20fb1159cd966b..9f61d37f4f7697 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/TestData.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/TestData.cs @@ -2698,6 +2698,37 @@ internal static DSAParameters GetDSA1024Params() VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiAwq18UD2DCufaMGTsz4JOQ 1vRqLI4hMLsIUQNyYgzbcgIhAJsB3qgv5WGyshlav98MPORcdCmYfkIvUCal0oPX Wesb +-----END CERTIFICATE-----"; + + public const string RsaNoParametersCertificate = @" +-----BEGIN CERTIFICATE----- +MIIE4jCCAsygAwIBAgIEMTI0NjALBgkqhkiG9w0BAQUwgZgxCzAJBgNVBAYTAlVT +MQswCQYDVQQIDAJOWTEbMBkGA1UECgwSUVogSW5kdXN0cmllcywgTExDMRswGQYD +VQQLDBJRWiBJbmR1c3RyaWVzLCBMTEMxGTAXBgNVBAMMEHF6aW5kdXN0cmllcy5j +b20xJzAlBgkqhkiG9w0BCQEWGHN1cHBvcnRAcXppbmR1c3RyaWVzLmNvbTAeFw0x +NjA0MDYyMTAwMDBaFw0xNzA0MDcyMTAwMDBaMIGtMQswCQYDVQQGDAJDWjEXMBUG +A1UECAwOQ3plY2ggUmVwdWJsaWMxDTALBgNVBAcMBEJybm8xGTAXBgNVBAoMEHNt +c3RpY2tldCBzLnIuby4xGTAXBgNVBAsMEHNtc3RpY2tldCBzLnIuby4xHjAcBgNV +BAMMFXBva2xhZG5hLnNtc3RpY2tldC5jejEgMB4GCSqGSIb3DQEJAQwRaW5mb0Bz +bXN0aWNrZXQuY3owggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIBCgKCAQEAsDh05CAX +Wp29GTbjk3gzeCCe/1t7V3aNTwbtzkUtLZnbS9tge/+Iaqsz10IOWk3SndLhPIfa +KUvX/pnkq5CXIVyTTyRoFpyYrDfNoRmZ/3uTmMG50urk0Rg/+e4f2k32BfFTfB0W +3V169+QQ6Xvvuoyh62cppfi1msgFJ6WGmEF1r73Q6tK1vxfuA9wJfMWTl4Sg8nEf +9NXsTc9VAwGKRJbmTUN1b0xsqFvlFbxvaxPGwxNM29lXWlez5KEsh0sfUyTGQuTB +tu5JMC57TGvL0/TwgwrtOxQL5+N4lJAWnUQ+z3XXL694eSsuKlgw2yasO2ZwWnyz +eap2vnN/CifUgwIDAQABoyMwITAfBgNVHSMEGDAWgBSQplC3hNS56l/yBYQTeEXo +qXVUXDALBgkqhkiG9w0BAQUDggIBAHMNLagyKZYla3gR0KOhxiUWuFG2gU7uB2v+ +zeqmIh6XxG4/39r6SJgUIimZ2aVQjYLa/fgrn5FRXhDqMumLJ3rWp8GB05evmdWl +WMQrb6E39jsFXuCzev6mCjiHxzGC2I7SRvFmnCj5fvOF81V5dLjU2PnCNqPym9Aw +XbEHVXTxpM9okSeq/EoeuTA5NHl/EySwYiGoexz0Ia51M5cw5W5go2Abmtqs4bbz +7OFeZKP9fd1p+C/ZnekgKq+3SJ9qbEiJxoPir3rG2N0mw7iI5pwvbCixY9irZh5o +Lrc5RvH4hdpygNSm4MYEuBykEW0tizkcVanGCUmGdjxM22Y9XdPgKitS04rVk/2U +C1Gszv9KvtmQ2P3/HWWWiOQgljc3SFqBltt6TqJTGCtLEbWRw6V+sw3SALoafvLg +tIsyWUsjM5LunRkUQ+HIsmKo42943TmgUvgRuuo0nsEFI5TS7Jh0iC/2gQEt7XGh +wzOTZ0HzM3oNnTphlXFLBwL9MUgWKbhu5Fg486dDMeQmZmhztW/+F/uHHYFisk+1 +tmr2prSh5i4fD71t4p+EGJJQxM4wCiXRLzggIVGUAIrzynxO2vjYiMQxAUH3tdsX +JI6fq+e/mFZOE2XQmYu3/hQEw8/2F6usF1lyvwMZt2TgQZF1/g8gFVQUY2mGLM1z +Wry5FNNo -----END CERTIFICATE-----"; public const string EcDhCertificate = @" diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs index 59c0b9a29d3932..781646e7f74cbd 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs @@ -20,6 +20,7 @@ public static partial class PlatformDetection public static bool IsUbuntu => IsDistroAndVersion("ubuntu"); public static bool IsUbuntu2004 => IsDistroAndVersion("ubuntu", 20, 4); public static bool IsUbuntu24 => IsDistroAndVersion("ubuntu", 24); + public static bool IsUbuntu24OrHigher => IsDistroAndVersionOrHigher("ubuntu", 24); public static bool IsDebian => IsDistroAndVersion("debian"); public static bool IsAlpine => IsDistroAndVersion("alpine"); public static bool IsRaspbian10 => IsDistroAndVersion("raspbian", 10); diff --git a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj index 51fc1add6ef9fd..1e21633bf88afe 100644 --- a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj +++ b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj @@ -1,14 +1,11 @@ + $(NetCoreAppMinimum);$(NetFrameworkCurrent) true false - - $(NetCoreAppMinimum);$(NetFrameworkMinimum) + + + + + + + + diff --git a/src/libraries/Microsoft.Bcl.AsyncInterfaces/tests/Microsoft.Bcl.AsyncInterfaces.Tests.csproj b/src/libraries/Microsoft.Bcl.AsyncInterfaces/tests/Microsoft.Bcl.AsyncInterfaces.Tests.csproj index cef1a73b4db037..40ee38968f04f1 100644 --- a/src/libraries/Microsoft.Bcl.AsyncInterfaces/tests/Microsoft.Bcl.AsyncInterfaces.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.AsyncInterfaces/tests/Microsoft.Bcl.AsyncInterfaces.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetFrameworkCurrent);$(NetCoreAppCurrent) diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.Forwards.cs b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.Forwards.cs index 198e623ef8709d..0c637b3c9b60c3 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.Forwards.cs +++ b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.Forwards.cs @@ -11,3 +11,7 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.Pkcs12LoadLimitExceededException))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.X509Certificates.X509CertificateLoader))] #endif +#if NET10_0_OR_GREATER +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.MLKem))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Cryptography.MLKemAlgorithm))] +#endif diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj index 973f529be3106f..d967161f0e6323 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj +++ b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj @@ -5,6 +5,7 @@ true true Provides support for some cryptographic primitives for .NET Framework and .NET Standard. + $(NoWarn);SYSLIB5006 @@ -12,7 +13,9 @@ true true - true + + true + true @@ -320,6 +323,21 @@ Link="Common\System\Security\Cryptography\KeySizeHelpers.cs" /> + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/Resources/Strings.resx b/src/libraries/Microsoft.Bcl.Cryptography/src/Resources/Strings.resx index 0a9c247f690c41..875f7cf780a710 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Bcl.Cryptography/src/Resources/Strings.resx @@ -60,12 +60,27 @@ Error occurred during a cryptographic operation. + + Destination must be exactly {0} bytes. + Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. Value was invalid. + + The specified ciphertext is not the correct length for the ML-KEM algorithm. + + + The specified decapsulation key is not the correct length for the ML-KEM algorithm. + + + The specified encapsulation key is not the correct length for the ML-KEM algorithm. + + + The specified private seed is not the correct length for the ML-KEM algorithm. + {0} ('{1}') must be a non-negative and non-zero value. @@ -108,6 +123,9 @@ Key is not a valid public or private key. + + One or more provided buffers overlap. + The certificate data cannot be read with the provided password, the password may be incorrect. diff --git a/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj b/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj index 1c47527480b27a..b26efaf7baf0c4 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj @@ -1,8 +1,12 @@ + + $(NetFrameworkCurrent);$(NetCoreAppCurrent) true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + true + $(NoWarn);SYSLIB5006 + @@ -18,6 +22,16 @@ Link="CommonTest\System\Security\Cryptography\PlatformSupport.cs" /> + + + + + + + + + + - - - + + diff --git a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj index b7458269bedff7..fa0b196ac08bc0 100644 --- a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj @@ -1,7 +1,7 @@ - $(NetFrameworkMinimum);$(NetCoreAppCurrent) + $(NetFrameworkCurrent);$(NetCoreAppCurrent) true @@ -32,14 +32,8 @@ - - - - System\Runtime\CompilerServices\RuntimeHelpers.cs - - - - + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj b/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj index 8f2abec46041a7..121dbe660463d4 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj @@ -1,7 +1,7 @@ - $(NetFrameworkMinimum);$(NetCoreAppCurrent) + $(NetFrameworkCurrent);$(NetCoreAppCurrent) diff --git a/src/libraries/Microsoft.Bcl.TimeProvider/tests/Microsoft.Bcl.TimeProvider.Tests.csproj b/src/libraries/Microsoft.Bcl.TimeProvider/tests/Microsoft.Bcl.TimeProvider.Tests.csproj index 9fceaa62f33396..5deea1415e71cf 100644 --- a/src/libraries/Microsoft.Bcl.TimeProvider/tests/Microsoft.Bcl.TimeProvider.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.TimeProvider/tests/Microsoft.Bcl.TimeProvider.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) $(DefineConstants);TESTEXTENSIONS diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/Microsoft.Extensions.Caching.Memory.Tests.csproj b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/Microsoft.Extensions.Caching.Memory.Tests.csproj index 1d602a71c1616b..00a56d03755ada 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/Microsoft.Extensions.Caching.Memory.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/Microsoft.Extensions.Caching.Memory.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj index c19f91354cba5a..8a406566c1aeec 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj @@ -1,6 +1,7 @@ + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true $(NoWarn);SYSLIB1100,SYSLIB1101 @@ -67,4 +68,5 @@ + diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/UnitTests/Microsoft.Extensions.Configuration.Binder.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/UnitTests/Microsoft.Extensions.Configuration.Binder.Tests.csproj index fc859a6f71bbec..209a2b10695a85 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/UnitTests/Microsoft.Extensions.Configuration.Binder.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/UnitTests/Microsoft.Extensions.Configuration.Binder.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.CommandLine/tests/Microsoft.Extensions.Configuration.CommandLine.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.CommandLine/tests/Microsoft.Extensions.Configuration.CommandLine.Tests.csproj index 18b0c90b1e0add..91d6b800969a08 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.CommandLine/tests/Microsoft.Extensions.Configuration.CommandLine.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.CommandLine/tests/Microsoft.Extensions.Configuration.CommandLine.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.csproj index 588b801f1c35d7..a6d935e1e74029 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/tests/Microsoft.Extensions.Configuration.FileExtensions.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/tests/Microsoft.Extensions.Configuration.FileExtensions.Tests.csproj index 9ae3029a16c23a..e5f6fba991eb2f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/tests/Microsoft.Extensions.Configuration.FileExtensions.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/tests/Microsoft.Extensions.Configuration.FileExtensions.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.Ini/tests/Microsoft.Extensions.Configuration.Ini.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Ini/tests/Microsoft.Extensions.Configuration.Ini.Tests.csproj index e452a5fb4511a1..28d3dcb8efe1fa 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Ini/tests/Microsoft.Extensions.Configuration.Ini.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Ini/tests/Microsoft.Extensions.Configuration.Ini.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/tests/Microsoft.Extensions.Configuration.Json.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Json/tests/Microsoft.Extensions.Configuration.Json.Tests.csproj index 8e7d876b203f26..eef49b47827a3e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/tests/Microsoft.Extensions.Configuration.Json.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/tests/Microsoft.Extensions.Configuration.Json.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/Microsoft.Extensions.Configuration.UserSecrets.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/Microsoft.Extensions.Configuration.UserSecrets.Tests.csproj index 0964f7795af269..bbe96b61add21f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/Microsoft.Extensions.Configuration.UserSecrets.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/Microsoft.Extensions.Configuration.UserSecrets.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj index 9f6c4b7a6d6a5c..901790b59a547e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true false diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj index 2be8ba76966f0d..dd6c95c44f311a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/Microsoft.Extensions.Configuration.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration/tests/Microsoft.Extensions.Configuration.Tests.csproj index 2d38ecef11273b..245d86dec45e69 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/Microsoft.Extensions.Configuration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/Microsoft.Extensions.Configuration.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index ee7daad0be7eb1..7cee6ebd40ad18 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -13,6 +13,84 @@ public abstract partial class KeyedDependencyInjectionSpecificationTests { protected abstract IServiceProvider CreateServiceProvider(IServiceCollection collection); + [Fact] + public void CombinationalRegistration() + { + Service service1 = new(); + Service service2 = new(); + Service keyedService1 = new(); + Service keyedService2 = new(); + Service anykeyService1 = new(); + Service anykeyService2 = new(); + Service nullkeyService1 = new(); + Service nullkeyService2 = new(); + + ServiceCollection serviceCollection = new(); + serviceCollection.AddSingleton(service1); + serviceCollection.AddSingleton(service2); + serviceCollection.AddKeyedSingleton(null, nullkeyService1); + serviceCollection.AddKeyedSingleton(null, nullkeyService2); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey, anykeyService1); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey, anykeyService2); + serviceCollection.AddKeyedSingleton("keyedService", keyedService1); + serviceCollection.AddKeyedSingleton("keyedService", keyedService2); + + IServiceProvider provider = CreateServiceProvider(serviceCollection); + + /* + * Table for what results are included: + * + * Query | Keyed? | Unkeyed? | AnyKey? | null key? + * ------------------------------------------------------------------- + * GetServices(Type) | no | yes | no | yes + * GetService(Type) | no | yes | no | yes + * + * GetKeyedServices(null) | no | yes | no | yes + * GetKeyedService(null) | no | yes | no | yes + * + * GetKeyedServices(AnyKey) | yes | no | no | no + * GetKeyedService(AnyKey) | throw | throw | throw | throw + * + * GetKeyedServices(key) | yes | no | no | no + * GetKeyedService(key) | yes | no | yes | no + * + * Summary: + * - A null key is the same as unkeyed. This allows the KeyServices APIs to support both keyed and unkeyed. + * - AnyKey is a special case of Keyed. + * - AnyKey registrations are not returned with GetKeyedServices(AnyKey) and GetKeyedService(AnyKey) always throws. + * - For IEnumerable, the ordering of the results are in registration order. + * - For a singleton resolve, the last match wins. + */ + + // Unkeyed (which is really keyed by Type). + Assert.Equal( + new[] { service1, service2, nullkeyService1, nullkeyService2 }, + provider.GetServices()); + + Assert.Equal(nullkeyService2, provider.GetService()); + + // Null key. + Assert.Equal( + new[] { service1, service2, nullkeyService1, nullkeyService2 }, + provider.GetKeyedServices(null)); + + Assert.Equal(nullkeyService2, provider.GetKeyedService(null)); + + // AnyKey. + Assert.Equal( + new[] { keyedService1, keyedService2 }, + provider.GetKeyedServices(KeyedService.AnyKey)); + + Assert.Throws(() => provider.GetKeyedService(KeyedService.AnyKey)); + + // Keyed. + Assert.Equal( + new[] { keyedService1, keyedService2 }, + provider.GetKeyedServices("keyedService")); + + Assert.Equal(keyedService2, provider.GetKeyedService("keyedService")); + } + [Fact] public void ResolveKeyedService() { @@ -158,10 +236,75 @@ public void ResolveKeyedServicesAnyKeyWithAnyKeyRegistration() _ = provider.GetKeyedService("something-else"); _ = provider.GetKeyedService("something-else-again"); - // Return all services registered with a non null key, but not the one "created" with KeyedService.AnyKey + // Return all services registered with a non null key, but not the one "created" with KeyedService.AnyKey, + // nor the KeyedService.AnyKey registration var allServices = provider.GetKeyedServices(KeyedService.AnyKey).ToList(); - Assert.Equal(5, allServices.Count); - Assert.Equal(new[] { service1, service2, service3, service4 }, allServices.Skip(1)); + Assert.Equal(4, allServices.Count); + Assert.Equal(new[] { service1, service2, service3, service4 }, allServices); + + var someKeyedServices = provider.GetKeyedServices("service").ToList(); + Assert.Equal(new[] { service2, service3, service4 }, someKeyedServices); + + var unkeyedServices = provider.GetServices().ToList(); + Assert.Equal(new[] { service5, service6 }, unkeyedServices); + } + + [Fact] + public void ResolveKeyedServicesAnyKeyConsistency() + { + var serviceCollection = new ServiceCollection(); + var service = new Service("first-service"); + serviceCollection.AddKeyedSingleton("first-service", service); + + var provider1 = CreateServiceProvider(serviceCollection); + Assert.Throws(() => provider1.GetKeyedService(KeyedService.AnyKey)); + // We don't return KeyedService.AnyKey registration when listing services + Assert.Equal(new[] { service }, provider1.GetKeyedServices(KeyedService.AnyKey)); + + var provider2 = CreateServiceProvider(serviceCollection); + Assert.Equal(new[] { service }, provider2.GetKeyedServices(KeyedService.AnyKey)); + Assert.Throws(() => provider2.GetKeyedService(KeyedService.AnyKey)); + } + + [Fact] + public void ResolveKeyedServicesAnyKeyConsistencyWithAnyKeyRegistration() + { + var serviceCollection = new ServiceCollection(); + var service = new Service("first-service"); + var any = new Service("any"); + serviceCollection.AddKeyedSingleton("first-service", service); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey, (sp, key) => any); + + var provider1 = CreateServiceProvider(serviceCollection); + Assert.Equal(new[] { service }, provider1.GetKeyedServices(KeyedService.AnyKey)); + + // Check twice in different order to check caching + var provider2 = CreateServiceProvider(serviceCollection); + Assert.Equal(new[] { service }, provider2.GetKeyedServices(KeyedService.AnyKey)); + Assert.Same(any, provider2.GetKeyedService(new object())); + + Assert.Throws(() => provider2.GetKeyedService(KeyedService.AnyKey)); + } + + [Fact] + public void ResolveKeyedServicesAnyKeyOrdering() + { + var serviceCollection = new ServiceCollection(); + var service1 = new Service(); + var service2 = new Service(); + var service3 = new Service(); + + serviceCollection.AddKeyedSingleton("A-service", service1); + serviceCollection.AddKeyedSingleton("B-service", service2); + serviceCollection.AddKeyedSingleton("A-service", service3); + + var provider = CreateServiceProvider(serviceCollection); + + // The order should be in registration order, and not grouped by key for example. + // Although this isn't necessarily a requirement, it is the current behavior. + Assert.Equal( + new[] { service1, service2, service3 }, + provider.GetKeyedServices(KeyedService.AnyKey)); } [Fact] @@ -250,7 +393,7 @@ public void ResolveKeyedServicesSingletonInstanceWithAnyKey() var provider = CreateServiceProvider(serviceCollection); var services = provider.GetKeyedServices>("some-key").ToList(); - Assert.Equal(new[] { service1, service2 }, services); + Assert.Equal(new[] { service2 }, services); } [Fact] @@ -504,6 +647,9 @@ public void ResolveKeyedSingletonFromScopeServiceProvider() Assert.Null(scopeA.ServiceProvider.GetService()); Assert.Null(scopeB.ServiceProvider.GetService()); + Assert.Throws(() => scopeA.ServiceProvider.GetKeyedService(KeyedService.AnyKey)); + Assert.Throws(() => scopeB.ServiceProvider.GetKeyedService(KeyedService.AnyKey)); + var serviceA1 = scopeA.ServiceProvider.GetKeyedService("key"); var serviceA2 = scopeA.ServiceProvider.GetKeyedService("key"); @@ -528,6 +674,9 @@ public void ResolveKeyedScopedFromScopeServiceProvider() Assert.Null(scopeA.ServiceProvider.GetService()); Assert.Null(scopeB.ServiceProvider.GetService()); + Assert.Throws(() => scopeA.ServiceProvider.GetKeyedService(KeyedService.AnyKey)); + Assert.Throws(() => scopeB.ServiceProvider.GetKeyedService(KeyedService.AnyKey)); + var serviceA1 = scopeA.ServiceProvider.GetKeyedService("key"); var serviceA2 = scopeA.ServiceProvider.GetKeyedService("key"); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx index e6f57dcbb5a1ee..2eb2adba7e0060 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx @@ -192,4 +192,7 @@ The type of the key used for lookup doesn't match the type in the constructor parameter with the ServiceKey attribute. + + KeyedService.AnyKey cannot be used to resolve a single service. + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index aec3f2c6745420..68c89a386e7c18 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -282,11 +282,13 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica CallSiteResultCacheLocation cacheLocation = CallSiteResultCacheLocation.Root; ServiceCallSite[] callSites; + var isAnyKeyLookup = serviceIdentifier.ServiceKey == KeyedService.AnyKey; + // If item type is not generic we can safely use descriptor cache // Special case for KeyedService.AnyKey, we don't want to check the cache because a KeyedService.AnyKey registration // will "hide" all the other service registration if (!itemType.IsConstructedGenericType && - !KeyedService.AnyKey.Equals(cacheKey.ServiceKey) && + !isAnyKeyLookup && _descriptorLookup.TryGetValue(cacheKey, out ServiceDescriptorCacheItem descriptors)) { callSites = new ServiceCallSite[descriptors.Count]; @@ -317,9 +319,12 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica int slot = 0; for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (KeysMatch(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) + if (KeysMatch(cacheKey.ServiceKey, _descriptors[i].ServiceKey)) { - if (TryCreateExact(_descriptors[i], cacheKey, callSiteChain, slot) is { } callSite) + // Special case for AnyKey: we don't want to add in cache a mapping AnyKey -> specific type, + // so we need to ask creation with the original identity of the descriptor + var registrationKey = isAnyKeyLookup ? ServiceIdentifier.FromDescriptor(_descriptors[i]) : cacheKey; + if (TryCreateExact(_descriptors[i], registrationKey, callSiteChain, slot) is { } callSite) { AddCallSite(callSite, i); } @@ -327,9 +332,12 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica } for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (KeysMatch(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) + if (KeysMatch(cacheKey.ServiceKey, _descriptors[i].ServiceKey)) { - if (TryCreateOpenGeneric(_descriptors[i], cacheKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) + // Special case for AnyKey: we don't want to add in cache a mapping AnyKey -> specific type, + // so we need to ask creation with the original identity of the descriptor + var registrationKey = isAnyKeyLookup ? ServiceIdentifier.FromDescriptor(_descriptors[i]) : cacheKey; + if (TryCreateOpenGeneric(_descriptors[i], registrationKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) { AddCallSite(callSite, i); } @@ -354,12 +362,38 @@ void AddCallSite(ServiceCallSite callSite, int index) ResultCache resultCache = (cacheLocation == CallSiteResultCacheLocation.Scope || cacheLocation == CallSiteResultCacheLocation.Root) ? new ResultCache(cacheLocation, callSiteKey) : new ResultCache(CallSiteResultCacheLocation.None, callSiteKey); - return _callSiteCache[callSiteKey] = new IEnumerableCallSite(resultCache, itemType, callSites); + return _callSiteCache[callSiteKey] = new IEnumerableCallSite(resultCache, itemType, callSites, serviceIdentifier.ServiceKey); } finally { callSiteChain.Remove(serviceIdentifier); } + + static bool KeysMatch(object? lookupKey, object? descriptorKey) + { + if (lookupKey == null && descriptorKey == null) + { + // Both are non keyed services + return true; + } + + if (lookupKey != null && descriptorKey != null) + { + // Both are keyed services + + // We don't want to return AnyKey registration, so ignore it + if (descriptorKey.Equals(KeyedService.AnyKey)) + return false; + + // Check if both keys are equal, or if the lookup key + // should matches all keys (except AnyKey) + return lookupKey.Equals(descriptorKey) + || lookupKey.Equals(KeyedService.AnyKey); + } + + // One is a keyed service, one is not + return false; + } } private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResultCacheLocation locationA, CallSiteResultCacheLocation locationB) @@ -381,7 +415,7 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult var lifetime = new ResultCache(descriptor.Lifetime, serviceIdentifier, slot); if (descriptor.HasImplementationInstance()) { - callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.GetImplementationInstance()); + callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.GetImplementationInstance(), descriptor.ServiceKey); } else if (!descriptor.IsKeyedService && descriptor.ImplementationFactory != null) { @@ -399,7 +433,6 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult { throw new InvalidOperationException(SR.InvalidServiceDescriptor); } - callSite.Key = descriptor.ServiceKey; return _callSiteCache[callSiteKey] = callSite; } @@ -478,7 +511,7 @@ private ConstructorCallSite CreateConstructorCallSite( ParameterInfo[] parameters = constructor.GetParameters(); if (parameters.Length == 0) { - return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, constructor); + return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, constructor, serviceIdentifier.ServiceKey); } parameterCallSites = CreateArgumentCallSites( @@ -488,7 +521,7 @@ private ConstructorCallSite CreateConstructorCallSite( parameters, throwIfCallSiteNotFound: true)!; - return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, constructor, parameterCallSites); + return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, constructor, parameterCallSites, serviceIdentifier.ServiceKey); } Array.Sort(constructors, @@ -552,7 +585,7 @@ private ConstructorCallSite CreateConstructorCallSite( else { Debug.Assert(parameterCallSites != null); - return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, bestConstructor, parameterCallSites); + return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, bestConstructor, parameterCallSites, serviceIdentifier.ServiceKey); } } finally @@ -693,24 +726,6 @@ internal bool IsService(ServiceIdentifier serviceIdentifier) serviceType == typeof(IServiceProviderIsKeyedService); } - /// - /// Returns true if both keys are null or equals, or if key1 is KeyedService.AnyKey and key2 is not null - /// - private static bool KeysMatch(object? key1, object? key2) - { - if (key1 == null && key2 == null) - return true; - - if (key1 != null && key2 != null) - { - return key1.Equals(key2) - || key1.Equals(KeyedService.AnyKey) - || key2.Equals(KeyedService.AnyKey); - } - - return false; - } - private struct ServiceDescriptorCacheItem { [DisallowNull] diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs index 66984648134553..979db8cffcf907 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs @@ -10,7 +10,7 @@ internal sealed class ConstantCallSite : ServiceCallSite private readonly Type _serviceType; internal object? DefaultValue => Value; - public ConstantCallSite(Type serviceType, object? defaultValue) : base(ResultCache.None(serviceType)) + public ConstantCallSite(Type serviceType, object? defaultValue, object? serviceKey = null) : base(ResultCache.None(serviceType), serviceKey) { _serviceType = serviceType ?? throw new ArgumentNullException(nameof(serviceType)); if (defaultValue != null && !serviceType.IsInstanceOfType(defaultValue)) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs index 1dbd77cb451714..7fdb8a2a8fbd6f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstructorCallSite.cs @@ -11,11 +11,11 @@ internal sealed class ConstructorCallSite : ServiceCallSite internal ConstructorInfo ConstructorInfo { get; } internal ServiceCallSite[] ParameterCallSites { get; } - public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo) : this(cache, serviceType, constructorInfo, Array.Empty()) + public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, object? serviceKey) : this(cache, serviceType, constructorInfo, Array.Empty(), serviceKey) { } - public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites) : base(cache) + public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites, object? serviceKey) : base(cache, serviceKey) { if (!serviceType.IsAssignableFrom(constructorInfo.DeclaringType)) { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs index e7fea17a46cb94..00cd766e17b287 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs @@ -9,13 +9,13 @@ internal sealed class FactoryCallSite : ServiceCallSite { public Func Factory { get; } - public FactoryCallSite(ResultCache cache, Type serviceType, Func factory) : base(cache) + public FactoryCallSite(ResultCache cache, Type serviceType, Func factory) : base(cache, null) { Factory = factory; ServiceType = serviceType; } - public FactoryCallSite(ResultCache cache, Type serviceType, object serviceKey, Func factory) : base(cache) + public FactoryCallSite(ResultCache cache, Type serviceType, object serviceKey, Func factory) : base(cache, serviceKey) { Factory = sp => factory(sp, serviceKey); ServiceType = serviceType; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/IEnumerableCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/IEnumerableCallSite.cs index 75657584fd75f7..5547555bcc012b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/IEnumerableCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/IEnumerableCallSite.cs @@ -13,7 +13,7 @@ internal sealed class IEnumerableCallSite : ServiceCallSite internal Type ItemType { get; } internal ServiceCallSite[] ServiceCallSites { get; } - public IEnumerableCallSite(ResultCache cache, Type itemType, ServiceCallSite[] serviceCallSites) : base(cache) + public IEnumerableCallSite(ResultCache cache, Type itemType, ServiceCallSite[] serviceCallSites, object? serviceKey = null) : base(cache, serviceKey) { Debug.Assert(!ServiceProvider.VerifyAotCompatibility || !itemType.IsValueType, "If VerifyAotCompatibility=true, an IEnumerableCallSite should not be created with a ValueType."); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs index e3ff3baa818594..df6a412399f86c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs @@ -10,9 +10,10 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup /// internal abstract class ServiceCallSite { - protected ServiceCallSite(ResultCache cache) + protected ServiceCallSite(ResultCache cache, object? key) { Cache = cache; + Key = key; } public abstract Type ServiceType { get; } @@ -20,7 +21,7 @@ protected ServiceCallSite(ResultCache cache) public abstract CallSiteKind Kind { get; } public ResultCache Cache { get; } public object? Value { get; set; } - public object? Key { get; set; } + public object? Key { get; } public bool CaptureDisposable => ImplementationType == null || diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderCallSite.cs index 6271473505c29f..6185513029d113 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderCallSite.cs @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { internal sealed class ServiceProviderCallSite : ServiceCallSite { - public ServiceProviderCallSite() : base(ResultCache.None(typeof(IServiceProvider))) + public ServiceProviderCallSite() : base(ResultCache.None(typeof(IServiceProvider)), null) { } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs index ffacbf9bbc0521..cf9bedf8341d78 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ThrowHelper.cs @@ -15,5 +15,12 @@ internal static void ThrowObjectDisposedException() { throw new ObjectDisposedException(nameof(IServiceProvider)); } + + [DoesNotReturn] + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void ThrowInvalidOperationException_KeyedServiceAnyKeyUsedToResolveService() + { + throw new InvalidOperationException(SR.Format(SR.KeyedServiceAnyKeyUsedToResolveService, nameof(IServiceProvider), nameof(IServiceScopeFactory))); + } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index d3177c229e31ec..bb05be370d8303 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -108,11 +108,24 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv /// The type of the service to get. /// The key of the service to get. /// The keyed service. + /// The value is used for + /// when is not an enumerable based on . + /// public object? GetKeyedService(Type serviceType, object? serviceKey) => GetKeyedService(serviceType, serviceKey, Root); internal object? GetKeyedService(Type serviceType, object? serviceKey, ServiceProviderEngineScope serviceProviderEngineScope) - => GetService(new ServiceIdentifier(serviceKey, serviceType), serviceProviderEngineScope); + { + if (serviceKey == KeyedService.AnyKey) + { + if (!serviceType.IsGenericType || serviceType.GetGenericTypeDefinition() != typeof(IEnumerable<>)) + { + ThrowHelper.ThrowInvalidOperationException_KeyedServiceAnyKeyUsedToResolveService(); + } + } + + return GetService(new ServiceIdentifier(serviceKey, serviceType), serviceProviderEngineScope); + } /// /// Gets the service object of the specified type. @@ -120,9 +133,21 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv /// The type of the service to get. /// The key of the service to get. /// The keyed service. - /// The service wasn't found. + /// The service wasn't found or the value is used + /// for when is not an enumerable based on . + /// public object GetRequiredKeyedService(Type serviceType, object? serviceKey) - => GetRequiredKeyedService(serviceType, serviceKey, Root); + { + if (serviceKey == KeyedService.AnyKey) + { + if (!serviceType.IsGenericType || serviceType.GetGenericTypeDefinition() != typeof(IEnumerable<>)) + { + ThrowHelper.ThrowInvalidOperationException_KeyedServiceAnyKeyUsedToResolveService(); + } + } + + return GetRequiredKeyedService(serviceType, serviceKey, Root); + } internal object GetRequiredKeyedService(Type serviceType, object? serviceKey, ServiceProviderEngineScope serviceProviderEngineScope) { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/CollectibleAssembly/CollectibleAssembly.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/CollectibleAssembly/CollectibleAssembly.csproj index 82159cece28227..7eaa265d0a9340 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/CollectibleAssembly/CollectibleAssembly.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/CollectibleAssembly/CollectibleAssembly.csproj @@ -1,6 +1,7 @@ + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true @@ -8,4 +9,5 @@ + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj index a9dab8c3709fe0..64fb6f86521bb5 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true $(NoWarn);CS8002 diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs index 26b410e7f59d71..dea27de90fbedc 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs @@ -17,6 +17,11 @@ internal static ServiceCallSite GetCallSite(this CallSiteFactory callSiteFactory { return callSiteFactory.GetCallSite(ServiceIdentifier.FromServiceType(type), callSiteChain); } + + internal static ServiceCallSite GetKeyedCallSite(this CallSiteFactory callSiteFactory, Type type, object? serviceKey, CallSiteChain callSiteChain) + { + return callSiteFactory.GetCallSite(new ServiceIdentifier(serviceKey, type), callSiteChain); + } } public class CallSiteTests @@ -300,6 +305,61 @@ public void CallSiteFactoryResolvesIEnumerableOfOpenGenericServiceAfterResolving Assert.Equal(typeof(FakeOpenGenericService), implementationTypes[1]); } + [Fact] + public void ServiceCallSite_ShouldHaveKey_WhenResolvingKeyedService() + { + // Arrange + IServiceCollection services = new ServiceCollection(); + + services.Add(ServiceDescriptor.Transient(typeof(SomeService), typeof(SomeService))); + services.Add(ServiceDescriptor.KeyedTransient(typeof(SomeService), "someKey", typeof(SomeOtherService))); + + using var serviceProvider = services.BuildServiceProvider(); + + // Act + var callSite = serviceProvider.CallSiteFactory.GetKeyedCallSite(typeof(SomeService), "someKey", new CallSiteChain()); + + // Assert + Assert.NotNull(callSite.Key); + } + + [Fact] + public void ServiceCallSite_ShouldHaveKey_WhenResolvingKeyedClosedImplementationOfOpenGenericService() + { + // Arrange + IServiceCollection services = new ServiceCollection(); + + services.Add(ServiceDescriptor.Transient(typeof(IGenericService<>), typeof(UnkeyedGenericService<>))); + services.Add(ServiceDescriptor.KeyedTransient(typeof(IGenericService<>), "someKey", typeof(PrimaryKeyedGenericService<>))); + + using var serviceProvider = services.BuildServiceProvider(); + + // Act + var callSite = serviceProvider.CallSiteFactory.GetKeyedCallSite(typeof(IGenericService), "someKey", new CallSiteChain()); + + // Assert + Assert.NotNull(callSite.Key); + } + + [Fact] + public void ServiceCallSite_ShouldHaveKey_WhenResolvingKeyedIEnumerableOfClosedImplementationOfOpenGenericService() + { + // Arrange + IServiceCollection services = new ServiceCollection(); + + services.Add(ServiceDescriptor.Transient(typeof(IGenericService<>), typeof(UnkeyedGenericService<>))); + services.Add(ServiceDescriptor.KeyedTransient(typeof(IGenericService<>), "someKey", typeof(PrimaryKeyedGenericService<>))); + services.Add(ServiceDescriptor.KeyedTransient(typeof(IGenericService<>), "someKey", typeof(SecondaryKeyedGenericService<>))); + + using var serviceProvider = services.BuildServiceProvider(); + + // Act + var callSite = serviceProvider.CallSiteFactory.GetKeyedCallSite(typeof(IEnumerable>), "someKey", new CallSiteChain()); + + // Assert + Assert.NotNull(callSite.Key); + } + private class FakeIntService : IFakeOpenGenericService { public int Value => 0; @@ -395,6 +455,18 @@ public void Dispose() } } + private interface IGenericService; + + private class UnkeyedGenericService : IGenericService; + + private class PrimaryKeyedGenericService : IGenericService; + + private class SecondaryKeyedGenericService : IGenericService; + + private class SomeService; + + private class SomeOtherService : SomeService; + private static object Invoke(ServiceCallSite callSite, ServiceProviderEngineScope scope) { return CallSiteRuntimeResolver.Instance.Resolve(callSite, scope); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj index 067508506a82fe..f69b18b3388114 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true @@ -27,8 +27,4 @@ - - - - diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/tests/JsonAssetions.cs b/src/libraries/Microsoft.Extensions.DependencyModel/tests/JsonAssetions.cs index 80527195b3de05..b0413835daa5dc 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/tests/JsonAssetions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/tests/JsonAssetions.cs @@ -16,20 +16,20 @@ public static class JsonAssertionExtensions { public static JsonAssertions Should(this JToken jToken) { - return new JsonAssertions(jToken); + return new JsonAssertions(jToken, AssertionChain.GetOrCreate()); } } public class JsonAssertions: ReferenceTypeAssertions { - public JsonAssertions(JToken token) : base(token) { } + public JsonAssertions(JToken token, AssertionChain assertionChain) : base(token, assertionChain) { } protected override string Identifier => nameof(JToken); public AndWhichConstraint HaveProperty(string expected) { var token = Subject[expected]; - Execute.Assertion + CurrentAssertionChain .ForCondition(token != null) .FailWith("Expected {0} to have property '{1}'", Subject, expected); @@ -39,7 +39,7 @@ public AndWhichConstraint HaveProperty(string expected) public AndConstraint NotHaveProperty(string expected) { var token = Subject[expected]; - Execute.Assertion + CurrentAssertionChain .ForCondition(token == null) .FailWith("Expected {0} to have property '{1}'", Subject, expected); diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj index 70fd9e556fb285..9f3b18f347fc7c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true $(DefaultItemExcludes);nonentrypointassembly\* @@ -12,7 +12,7 @@ - + @@ -21,4 +21,5 @@ + diff --git a/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/tests/Microsoft.Extensions.Diagnostics.Abstractions.Tests.csproj b/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/tests/Microsoft.Extensions.Diagnostics.Abstractions.Tests.csproj index b3043a4481a1db..c59795b670cbef 100644 --- a/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/tests/Microsoft.Extensions.Diagnostics.Abstractions.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/tests/Microsoft.Extensions.Diagnostics.Abstractions.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Diagnostics/tests/Microsoft.Extensions.Diagnostics.Tests.csproj b/src/libraries/Microsoft.Extensions.Diagnostics/tests/Microsoft.Extensions.Diagnostics.Tests.csproj index cf79a3f5dca619..98e83a8815cac6 100644 --- a/src/libraries/Microsoft.Extensions.Diagnostics/tests/Microsoft.Extensions.Diagnostics.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Diagnostics/tests/Microsoft.Extensions.Diagnostics.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/Microsoft.Extensions.FileProviders.Composite.Tests.csproj b/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/Microsoft.Extensions.FileProviders.Composite.Tests.csproj index 6e5719a7b31e59..62f8c046761841 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/Microsoft.Extensions.FileProviders.Composite.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/Microsoft.Extensions.FileProviders.Composite.Tests.csproj @@ -1,8 +1,8 @@ + $(NetCoreAppCurrent);$(NetFrameworkCurrent) Microsoft.Extensions.FileProviders.Composite - $(NetCoreAppCurrent);$(NetFrameworkMinimum) true diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj index 44db55e3dc61cc..d7751305a7f187 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj @@ -1,8 +1,8 @@ + $(NetCoreAppCurrent);$(NetFrameworkCurrent) Microsoft.Extensions.FileProviders.Physical - $(NetCoreAppCurrent);$(NetFrameworkMinimum) true false true diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj index 18043e2391cb01..73712b52c7fc1c 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromArgument/ApplicationNameSetFromArgument.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromArgument/ApplicationNameSetFromArgument.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromArgument/ApplicationNameSetFromArgument.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromArgument/ApplicationNameSetFromArgument.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderInvalidSignature/CreateHostBuilderInvalidSignature.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderInvalidSignature/CreateHostBuilderInvalidSignature.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderInvalidSignature/CreateHostBuilderInvalidSignature.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderInvalidSignature/CreateHostBuilderInvalidSignature.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderPatternTestSite/CreateHostBuilderPatternTestSite.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderPatternTestSite/CreateHostBuilderPatternTestSite.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderPatternTestSite/CreateHostBuilderPatternTestSite.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateHostBuilderPatternTestSite/CreateHostBuilderPatternTestSite.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderPatternTestSite/CreateWebHostBuilderPatternTestSite.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderPatternTestSite/CreateWebHostBuilderPatternTestSite.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderPatternTestSite/CreateWebHostBuilderPatternTestSite.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/CreateWebHostBuilderPatternTestSite/CreateWebHostBuilderPatternTestSite.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj index adc356d86a80f5..0379f3b1629f53 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj @@ -1,6 +1,7 @@ + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) enable @@ -35,4 +36,5 @@ + diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/MockHostTypes/MockHostTypes.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/MockHostTypes/MockHostTypes.csproj index 2c9f3a71fc5ee1..47187cb5275f8e 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/MockHostTypes/MockHostTypes.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/MockHostTypes/MockHostTypes.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPattern/NoSpecialEntryPointPattern.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPattern/NoSpecialEntryPointPattern.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPattern/NoSpecialEntryPointPattern.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPattern/NoSpecialEntryPointPattern.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternBuildsThenThrows/NoSpecialEntryPointPatternBuildsThenThrows.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternBuildsThenThrows/NoSpecialEntryPointPatternBuildsThenThrows.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternBuildsThenThrows/NoSpecialEntryPointPatternBuildsThenThrows.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternBuildsThenThrows/NoSpecialEntryPointPatternBuildsThenThrows.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternExits/NoSpecialEntryPointPatternExits.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternExits/NoSpecialEntryPointPatternExits.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternExits/NoSpecialEntryPointPatternExits.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternExits/NoSpecialEntryPointPatternExits.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternHangs/NoSpecialEntryPointPatternHangs.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternHangs/NoSpecialEntryPointPatternHangs.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternHangs/NoSpecialEntryPointPatternHangs.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternHangs/NoSpecialEntryPointPatternHangs.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternMainNoArgs/NoSpecialEntryPointPatternMainNoArgs.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternMainNoArgs/NoSpecialEntryPointPatternMainNoArgs.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternMainNoArgs/NoSpecialEntryPointPatternMainNoArgs.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternMainNoArgs/NoSpecialEntryPointPatternMainNoArgs.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternThrows/NoSpecialEntryPointPatternThrows.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternThrows/NoSpecialEntryPointPatternThrows.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternThrows/NoSpecialEntryPointPatternThrows.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/NoSpecialEntryPointPatternThrows/NoSpecialEntryPointPatternThrows.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatements/TopLevelStatements.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatements/TopLevelStatements.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatements/TopLevelStatements.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatements/TopLevelStatements.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj index 1d8d76f900ada1..fcc7214c0b5f54 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj index 4f2edef0f83b71..6deee14667ec89 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj @@ -2,7 +2,7 @@ - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) true true true diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs b/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs index 153bd31d4bc51e..18f295a3599d99 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs @@ -338,6 +338,10 @@ private static async Task ForeachService( { exceptions.AddRange(task.Exception.InnerExceptions); // Log exception from async method. } + else if (task.IsCanceled) + { + exceptions.Add(new TaskCanceledException(task)); + } } else { diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Common/ApplicationType.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Common/ApplicationType.cs index ec190cb32eaf13..b92d3e7f70029e 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Common/ApplicationType.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Common/ApplicationType.cs @@ -11,7 +11,7 @@ public enum ApplicationType Portable, /// - /// All dlls are published with the app for x-copy deploy. Net462 requires this because ASP.NET Core is not in the GAC. + /// All dlls are published with the app for x-copy deploy. .NET Framework requires this because ASP.NET Core is not in the GAC. /// Standalone } diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/ApplicationDeployer.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/ApplicationDeployer.cs index 34c5832beedabb..6a96659f406835 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/ApplicationDeployer.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/ApplicationDeployer.cs @@ -61,7 +61,7 @@ private void ValidateParameters() private RuntimeFlavor GetRuntimeFlavor(string tfm) { - if (tfm.ToLowerInvariant() == "net462") + if (tfm.ToLowerInvariant().StartsWith("net4")) { return RuntimeFlavor.Clr; } diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs index 0ef58a0d95924d..c156755831371c 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs @@ -85,7 +85,7 @@ protected async Task StartSelfHostAsync() // Run from the pre-built bin/{config}/{tfm} directory. Version version = Environment.Version; var targetFramework = DeploymentParameters.TargetFramework - ?? (DeploymentParameters.RuntimeFlavor == RuntimeFlavor.Clr ? "net462" : $"net{version.Major}.{version.Minor}"); + ?? (DeploymentParameters.RuntimeFlavor == RuntimeFlavor.Clr ? "net481" : $"net{version.Major}.{version.Minor}"); workingDirectory = Path.Combine(DeploymentParameters.ApplicationPath, "bin", DeploymentParameters.Configuration, targetFramework); // CurrentDirectory will point to bin/{config}/{tfm}, but the config and static files aren't copied, point to the app base instead. DeploymentParameters.EnvironmentVariables["DOTNET_CONTENTROOT"] = DeploymentParameters.ApplicationPath; diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/Microsoft.Extensions.Hosting.Functional.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/Microsoft.Extensions.Hosting.Functional.Tests.csproj index 83bb46beb4470f..f195afdccd0be6 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/Microsoft.Extensions.Hosting.Functional.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/Microsoft.Extensions.Hosting.Functional.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/TestApp/Microsoft.Extensions.Hosting.TestApp.csproj b/src/libraries/Microsoft.Extensions.Hosting/tests/TestApp/Microsoft.Extensions.Hosting.TestApp.csproj index 5fc20549478653..e0769454ab8368 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/TestApp/Microsoft.Extensions.Hosting.TestApp.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/TestApp/Microsoft.Extensions.Hosting.TestApp.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true Exe diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs index d5e03ebab1d08e..cd54f9f468ebd6 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs @@ -1453,6 +1453,23 @@ public async Task HostedServiceFactoryExceptionGetsLogged() Assert.Equal("HostedServiceStartupFaulted", events[0].EventId.Name); } + [Fact] + public async Task HostConcurrentCancelledStartAsyncAbortsStart() + { + using CancellationTokenSource cancellationTokenSource = new(); + StartAsyncCancelledService service = new(cancellationTokenSource); + + using IHost host = CreateBuilder() + .ConfigureServices((hostContext, services) => + { + services.Configure(o => o.ServicesStartConcurrently = true); + services.AddHostedService(sp => service); + }) + .Build(); + + await Assert.ThrowsAsync(() => host.StartAsync(cancellationTokenSource.Token)); + } + /// /// Tests that when a BackgroundService is canceled when stopping the host, /// no error is logged. @@ -1698,6 +1715,17 @@ private class BackgroundServiceDoesNotCallBase : BackgroundService public override Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; } + private class StartAsyncCancelledService(CancellationTokenSource cancellationTokenSource) : IHostedService + { + public Task StartAsync(CancellationToken cancellationToken) + { + cancellationTokenSource.Cancel(); + return Task.FromCanceled(cancellationToken); + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } + private class SlowStartService : IHostedService { public async Task StartAsync(CancellationToken cancellationToken) diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj index 962f3f02fca83b..ea7f4fcbce05a0 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetFrameworkCurrent) true true true diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Microsoft.Extensions.Http.Tests.csproj b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Microsoft.Extensions.Http.Tests.csproj index b1a3e853dc5cbc..d704d7564ab177 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Microsoft.Extensions.Http.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Microsoft.Extensions.Http.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj index 7d7c040d33111c..85dae0238c9c34 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true true diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj index cc24d8f4a83ea0..4d0b74af30617e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/Microsoft.Extensions.Logging.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging/tests/Common/Microsoft.Extensions.Logging.Tests.csproj index 6586026447c58a..eb64f40c2a38ed 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/Microsoft.Extensions.Logging.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/Microsoft.Extensions.Logging.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj index 49e334b679eebb..e72c80ccd383b2 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj index e5f19ac31e2698..b8e359047706c9 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj @@ -1,7 +1,7 @@ enable - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) $(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS;ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER $(InterceptorsPreviewNamespaces);Microsoft.Extensions.Configuration.Binder.SourceGeneration true diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/UnitTests/Microsoft.Extensions.Options.ConfigurationExtensions.UnitTests.csproj b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/UnitTests/Microsoft.Extensions.Options.ConfigurationExtensions.UnitTests.csproj index 512e0018a400c0..cc7229212c29b4 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/UnitTests/Microsoft.Extensions.Options.ConfigurationExtensions.UnitTests.csproj +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/UnitTests/Microsoft.Extensions.Options.ConfigurationExtensions.UnitTests.csproj @@ -2,7 +2,7 @@ enable - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs index d12b13d8c3ed9c..bb27ee8fa4e9e0 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -681,15 +681,23 @@ private void GenModelValidationMethod( if (_symbolHolder.UnconditionalSuppressMessageAttributeSymbol is not null) { // We disable the warning on `new ValidationContext(object)` usage as we use it in a safe way that not require executing the reflection code. - // This is done by initializing the DisplayName in the context which is the part trigger reflection if it is not initialized. + // This is done by initializing the DisplayName in the context which is the part trigger reflection if it is not initialized. For + // projects targeting .NET 10 and above, we can avoid the suppression since we use the new trim-safe constructor. + OutLn("#if !NET10_0_OR_GREATER"); OutLn($"[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage(\"Trimming\", \"IL2026:RequiresUnreferencedCode\","); OutLn($" Justification = \"The created ValidationContext object is used in a way that never call reflection\")]"); + OutLn("#endif"); } OutLn($"public {(makeStatic ? "static " : string.Empty)}global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, {modelToValidate.Name} options)"); OutOpenBrace(); OutLn($"global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null;"); + OutLn("#if NET10_0_OR_GREATER"); + OutLn($"string displayName = string.IsNullOrEmpty(name) ? \"{modelToValidate.SimpleName}.Validate\" : $\"{{name}}.Validate\";"); + OutLn($"var context = new {StaticValidationContextType}(options, displayName, null, null);"); + OutLn("#else"); OutLn($"var context = new {StaticValidationContextType}(options);"); + OutLn("#endif"); int capacity = modelToValidate.MembersToValidate.Count == 0 ? 0 : modelToValidate.MembersToValidate.Max(static vm => vm.ValidationAttributes.Count); if (capacity > 0) diff --git a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/Microsoft.Extensions.Options.Tests.csproj b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/Microsoft.Extensions.Options.Tests.csproj index b6fe16d15b9957..7d492c8ac7319f 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/Microsoft.Extensions.Options.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/Microsoft.Extensions.Options.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/DataAnnotationAttributesWithParams.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/DataAnnotationAttributesWithParams.g.cs index c51c551222f42f..8e18bef64a48d8 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/DataAnnotationAttributesWithParams.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/DataAnnotationAttributesWithParams.g.cs @@ -13,12 +13,19 @@ partial class MyOptionsValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.MyOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MyOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netcore.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netcore.g.cs index b36fff7e49060b..802ef32bd9b4e4 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netcore.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netcore.g.cs @@ -13,12 +13,19 @@ partial struct MyOptionsValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::HelloWorld.MyOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MyOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netfx.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netfx.g.cs index 1fa2f9c2e25770..ad678ad8d7783b 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netfx.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/EmitterWithCustomValidator.netfx.g.cs @@ -16,7 +16,12 @@ partial struct MyOptionsValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::HelloWorld.MyOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MyOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang10.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang10.g.cs index 789d299cf93c5a..e4845565934345 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang10.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang10.g.cs @@ -13,12 +13,19 @@ partial class OptionsUsingGeneratedAttributesValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValidationTest.OptionsUsingGeneratedAttributes options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "OptionsUsingGeneratedAttributes.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang11.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang11.g.cs index 60d511f2e83561..1bde049b333977 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang11.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netcore.lang11.g.cs @@ -13,12 +13,19 @@ partial class OptionsUsingGeneratedAttributesValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValidationTest.OptionsUsingGeneratedAttributes options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "OptionsUsingGeneratedAttributes.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang10.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang10.g.cs index 9c20532b17631d..e311788a74170e 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang10.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang10.g.cs @@ -16,7 +16,12 @@ partial class OptionsUsingGeneratedAttributesValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValidationTest.OptionsUsingGeneratedAttributes options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "OptionsUsingGeneratedAttributes.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang11.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang11.g.cs index c563c65e821903..68bd65a6d611ab 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang11.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/GeneratedAttributesTest.netfx.lang11.g.cs @@ -16,7 +16,12 @@ partial class OptionsUsingGeneratedAttributesValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValidationTest.OptionsUsingGeneratedAttributes options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "OptionsUsingGeneratedAttributes.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netcore.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netcore.g.cs index 00e0de4d51f4d0..4c68f556588b21 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netcore.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netcore.g.cs @@ -14,12 +14,19 @@ internal sealed partial class __EndPointsOptionsValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.EndPointsOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "EndPointsOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -58,12 +65,19 @@ internal sealed partial class __RedisClientOptionsValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.RedisClientOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RedisClientOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -107,12 +121,19 @@ partial class RedisNamedClientOptions /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.RedisNamedClientOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RedisNamedClientOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netfx.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netfx.g.cs index c7a038cc2d6cf6..2dcec625981c81 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netfx.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/OptionsExtendingSystemClassTest.netfx.g.cs @@ -17,7 +17,12 @@ internal sealed partial class __EndPointsOptionsValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.EndPointsOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "EndPointsOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -59,7 +64,12 @@ internal sealed partial class __RedisClientOptionsValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.RedisClientOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RedisClientOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -106,7 +116,12 @@ partial class RedisNamedClientOptions public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.RedisNamedClientOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RedisNamedClientOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netcore.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netcore.g.cs index 1cd942fab0f1bb..eae660b0cf1eca 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netcore.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netcore.g.cs @@ -13,12 +13,19 @@ partial class MyOptionsValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.MyOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MyOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netfx.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netfx.g.cs index 603680a9ec732c..acd7d2a1bae147 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netfx.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netfx.g.cs @@ -16,7 +16,12 @@ partial class MyOptionsValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Test.MyOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MyOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj index f3a5f33b4a2b45..38b388d44c6e8b 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) $(MicrosoftCodeAnalysisVersion_4_4) true diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs index 8e230835246dcd..cdd8e18117d400 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs @@ -12,12 +12,19 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ThirdModelNoNamespace options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -42,12 +49,19 @@ partial class FirstValidatorNoNamespace /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FirstModelNoNamespace options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModelNoNamespace.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -82,12 +96,19 @@ partial class SecondValidatorNoNamespace /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SecondModelNoNamespace options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModelNoNamespace.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -114,12 +135,19 @@ partial class FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::CustomAttr.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -157,12 +185,19 @@ internal sealed partial class __SecondModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -191,12 +226,19 @@ internal sealed partial class __ThirdModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -223,12 +265,19 @@ partial struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif if (options.P1 is not null) { @@ -377,12 +426,19 @@ partial struct SecondValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -410,12 +466,19 @@ partial struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FileScopedNamespace.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -443,12 +506,19 @@ partial struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FunnyStrings.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -476,12 +546,19 @@ internal sealed partial class __SecondModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -509,12 +586,19 @@ partial class FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -547,12 +631,19 @@ partial struct MultiValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -579,12 +670,19 @@ partial struct MultiValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -613,12 +711,19 @@ internal sealed partial class __ThirdModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -648,12 +753,19 @@ partial record struct FifthValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -686,12 +798,19 @@ partial struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -735,12 +854,19 @@ partial struct FourthValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -773,12 +899,19 @@ partial struct SecondValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -812,12 +945,19 @@ partial struct ThirdValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -847,12 +987,19 @@ partial class FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RandomMembers.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -881,12 +1028,19 @@ internal sealed partial class __ThirdModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -914,12 +1068,19 @@ partial record struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -959,12 +1120,19 @@ partial record struct SecondValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -992,12 +1160,19 @@ partial record class ThirdValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -1026,12 +1201,19 @@ internal sealed partial class __SecondModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1064,12 +1246,19 @@ internal sealed partial class __ThirdModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -1097,12 +1286,19 @@ partial class FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1165,12 +1361,19 @@ internal sealed partial class __SecondModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1201,12 +1404,19 @@ partial struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1252,12 +1462,19 @@ partial class SelfValidateOptions /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.SelfValidateOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SelfValidateOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif context.MemberName = "Validate"; context.DisplayName = string.IsNullOrEmpty(name) ? "SelfValidateOptions.Validate" : $"{name}.Validate"; @@ -1279,12 +1496,19 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1312,12 +1536,19 @@ internal sealed partial class __RequiredAttributeModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RequiredAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1345,12 +1576,19 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.TypeWithoutOptionsValidator options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1392,12 +1630,19 @@ partial class AttributePropertyModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.AttributePropertyModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "AttributePropertyModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1434,12 +1679,19 @@ partial class ComplexModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.ComplexModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ComplexModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif if (options.ComplexVal is not null) { @@ -1466,12 +1718,19 @@ partial class CustomTypeCustomValidationAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomTypeCustomValidationAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1498,12 +1757,19 @@ partial class CustomValidationAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomValidationAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1530,12 +1796,19 @@ partial class DataTypeAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DataTypeAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "DataTypeAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1562,12 +1835,19 @@ partial class DerivedModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DerivedModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "DerivedModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1614,12 +1894,19 @@ partial class EmailAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.EmailAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "EmailAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1646,12 +1933,19 @@ partial class LeafModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.LeafModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "LeafModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1698,12 +1992,19 @@ partial class MultipleAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.MultipleAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MultipleAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -1761,12 +2062,19 @@ partial class OptionsUsingRangeWithTimeSpanValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.OptionsUsingRangeWithTimeSpan options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "OptionsUsingRangeWithTimeSpan.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1823,12 +2131,19 @@ partial class RangeAttributeModelDateValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDate options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelDate.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1855,12 +2170,19 @@ partial class RangeAttributeModelDoubleValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1887,12 +2209,19 @@ partial class RangeAttributeModelIntValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelInt options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelInt.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1919,12 +2248,19 @@ partial class RegularExpressionAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RegularExpressionAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1951,12 +2287,19 @@ partial class RequiredAttributeModelValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RequiredAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1984,12 +2327,19 @@ internal sealed partial class __SecondModelValidator__ /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -2017,12 +2367,19 @@ partial struct FirstValidator /// The options instance. /// Validation result. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + #if !NET10_0_OR_GREATER [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] + #endif public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs index e193e6fc7ea3ad..f3e298c495eda9 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -15,7 +15,12 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ThirdModelNoNamespace options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -43,7 +48,12 @@ partial class FirstValidatorNoNamespace public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FirstModelNoNamespace options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModelNoNamespace.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -81,7 +91,12 @@ partial class SecondValidatorNoNamespace public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SecondModelNoNamespace options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModelNoNamespace.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -111,7 +126,12 @@ partial class FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::CustomAttr.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -152,7 +172,12 @@ internal sealed partial class __SecondModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -184,7 +209,12 @@ internal sealed partial class __ThirdModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -214,7 +244,12 @@ partial struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif if (options.P1 is not null) { @@ -366,7 +401,12 @@ partial struct SecondValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -397,7 +437,12 @@ partial struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FileScopedNamespace.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -428,7 +473,12 @@ partial struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FunnyStrings.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -459,7 +509,12 @@ internal sealed partial class __SecondModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -490,7 +545,12 @@ partial class FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -526,7 +586,12 @@ partial struct MultiValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -556,7 +621,12 @@ partial struct MultiValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -588,7 +658,12 @@ internal sealed partial class __ThirdModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -621,7 +696,12 @@ partial record struct FifthValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -657,7 +737,12 @@ partial struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -704,7 +789,12 @@ partial struct FourthValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -740,7 +830,12 @@ partial struct SecondValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -777,7 +872,12 @@ partial struct ThirdValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -810,7 +910,12 @@ partial class FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RandomMembers.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -842,7 +947,12 @@ internal sealed partial class __ThirdModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -873,7 +983,12 @@ partial record struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -916,7 +1031,12 @@ partial record struct SecondValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -947,7 +1067,12 @@ partial record class ThirdValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -979,7 +1104,12 @@ internal sealed partial class __SecondModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1015,7 +1145,12 @@ internal sealed partial class __ThirdModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.ThirdModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ThirdModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -1046,7 +1181,12 @@ partial class FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1112,7 +1252,12 @@ internal sealed partial class __SecondModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1146,7 +1291,12 @@ partial struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1195,7 +1345,12 @@ partial class SelfValidateOptions public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.SelfValidateOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SelfValidateOptions.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif context.MemberName = "Validate"; context.DisplayName = string.IsNullOrEmpty(name) ? "SelfValidateOptions.Validate" : $"{name}.Validate"; @@ -1220,7 +1375,12 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1251,7 +1411,12 @@ internal sealed partial class __RequiredAttributeModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RequiredAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1282,7 +1447,12 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.TypeWithoutOptionsValidator options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1327,7 +1497,12 @@ partial class AttributePropertyModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.AttributePropertyModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "AttributePropertyModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1367,7 +1542,12 @@ partial class ComplexModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.ComplexModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "ComplexModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif if (options.ComplexVal is not null) { @@ -1397,7 +1577,12 @@ partial class CustomTypeCustomValidationAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomTypeCustomValidationAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1427,7 +1612,12 @@ partial class CustomValidationAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomValidationAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1457,7 +1647,12 @@ partial class DataTypeAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DataTypeAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "DataTypeAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1487,7 +1682,12 @@ partial class DerivedModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DerivedModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "DerivedModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1537,7 +1737,12 @@ partial class EmailAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.EmailAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "EmailAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1567,7 +1772,12 @@ partial class LeafModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.LeafModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "LeafModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1617,7 +1827,12 @@ partial class MultipleAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.MultipleAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "MultipleAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -1678,7 +1893,12 @@ partial class OptionsUsingRangeWithTimeSpanValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.OptionsUsingRangeWithTimeSpan options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "OptionsUsingRangeWithTimeSpan.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1738,7 +1958,12 @@ partial class RangeAttributeModelDateValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDate options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelDate.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1768,7 +1993,12 @@ partial class RangeAttributeModelDoubleValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1798,7 +2028,12 @@ partial class RangeAttributeModelIntValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelInt options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RangeAttributeModelInt.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1828,7 +2063,12 @@ partial class RegularExpressionAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RegularExpressionAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1858,7 +2098,12 @@ partial class RequiredAttributeModelValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "RequiredAttributeModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(1); @@ -1889,7 +2134,12 @@ internal sealed partial class __SecondModelValidator__ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.SecondModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "SecondModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); @@ -1920,7 +2170,12 @@ partial struct FirstValidator public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.FirstModel options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; + #if NET10_0_OR_GREATER + string displayName = string.IsNullOrEmpty(name) ? "FirstModel.Validate" : $"{name}.Validate"; + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options, displayName, null, null); + #else var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + #endif var validationResults = new global::System.Collections.Generic.List(); var validationAttributes = new global::System.Collections.Generic.List(2); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj index e38c31f71704a8..7f2cd358d95991 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) $(MicrosoftCodeAnalysisVersion_4_4) true diff --git a/src/libraries/Microsoft.Extensions.Primitives/tests/Microsoft.Extensions.Primitives.Tests.csproj b/src/libraries/Microsoft.Extensions.Primitives/tests/Microsoft.Extensions.Primitives.Tests.csproj index 00a7482013c099..449de04ed83fed 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/tests/Microsoft.Extensions.Primitives.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Primitives/tests/Microsoft.Extensions.Primitives.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj b/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj index 83c45050ded286..688a009eb8691f 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj +++ b/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj @@ -1,7 +1,7 @@ - true $(NetCoreAppCurrent);$(NetFrameworkCurrent) + true 1 diff --git a/src/libraries/Microsoft.Win32.Registry.AccessControl/tests/Microsoft.Win32.Registry.AccessControl.Tests.csproj b/src/libraries/Microsoft.Win32.Registry.AccessControl/tests/Microsoft.Win32.Registry.AccessControl.Tests.csproj index 76442c6fb1f7c9..edb1d8dc0c177a 100644 --- a/src/libraries/Microsoft.Win32.Registry.AccessControl/tests/Microsoft.Win32.Registry.AccessControl.Tests.csproj +++ b/src/libraries/Microsoft.Win32.Registry.AccessControl/tests/Microsoft.Win32.Registry.AccessControl.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) diff --git a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj index 049bcbb6157a29..b853f5a2c9b655 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) true true diff --git a/src/libraries/System.CodeDom/tests/System.CodeDom.Tests.csproj b/src/libraries/System.CodeDom/tests/System.CodeDom.Tests.csproj index ac519acf967e49..4db5a506b11789 100644 --- a/src/libraries/System.CodeDom/tests/System.CodeDom.Tests.csproj +++ b/src/libraries/System.CodeDom/tests/System.CodeDom.Tests.csproj @@ -1,7 +1,7 @@ + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) diff --git a/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj b/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj index 3d80be9e7906be..2fd15add61a640 100644 --- a/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj +++ b/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) $(NoWarn);0436 true true @@ -102,7 +102,6 @@ - diff --git a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs index c9e82b8cece0c7..0fb7a5f5ef2876 100644 --- a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs +++ b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs @@ -341,12 +341,13 @@ public void Validate(object? value, string name) { } } public sealed partial class ValidationContext : System.IServiceProvider { - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public ValidationContext(object instance) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public ValidationContext(object instance, System.Collections.Generic.IDictionary? items) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public ValidationContext(object instance, System.IServiceProvider? serviceProvider, System.Collections.Generic.IDictionary? items) { } + public ValidationContext(object instance, string displayName, System.IServiceProvider? serviceProvider, System.Collections.Generic.IDictionary? items) { } public string DisplayName { get { throw null; } set { } } public System.Collections.Generic.IDictionary Items { get { throw null; } } public string? MemberName { get { throw null; } set { } } @@ -381,16 +382,16 @@ public ValidationResult(string? errorMessage, System.Collections.Generic.IEnumer } public static partial class Validator { - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection? validationResults) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection? validationResults, bool validateAllProperties) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of validationContext.ObjectType cannot be statically discovered.")] public static bool TryValidateProperty(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection? validationResults) { throw null; } public static bool TryValidateValue(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection? validationResults, System.Collections.Generic.IEnumerable validationAttributes) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public static void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered and the Type's properties can be trimmed.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided.")] public static void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, bool validateAllProperties) { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of validationContext.ObjectType cannot be statically discovered.")] public static void ValidateProperty(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationContext.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationContext.cs index 8a19ea0b27ebe3..75ef95a7cd6416 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationContext.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationContext.cs @@ -27,7 +27,7 @@ public sealed class ValidationContext // Also we use this ability in Validator.CreateValidationContext()?? : IServiceProvider { - internal const string InstanceTypeNotStaticallyDiscovered = "The Type of instance cannot be statically discovered and the Type's properties can be trimmed."; + internal const string InstanceTypeNotStaticallyDiscovered = "Constructing a ValidationContext without a display name is not trim-safe because it uses reflection to discover the type of the instance being validated in order to resolve the DisplayNameAttribute when a display name is not provided."; #region Member Fields @@ -98,6 +98,43 @@ public ValidationContext(object instance, IServiceProvider? serviceProvider, IDi ObjectInstance = instance; } + /// + /// Construct a for a given object instance with + /// a , an optional , + /// and an optional property bag of . + /// + /// The object instance being validated. It cannot be null. + /// The display name associated with the object instance. + /// + /// Optional to use when is called. + /// If it is null, will always return null. + /// + /// + /// Optional set of key/value pairs to make available to consumers via . + /// If null, an empty dictionary will be created. If not null, the set of key/value pairs will be copied into a + /// new dictionary, preventing consumers from modifying the original dictionary. + /// + /// When is null + /// + /// This constructor is trim-safe because it does not use reflection to resolve + /// the Type of the to support setting the DisplayName. + /// + public ValidationContext(object instance, string displayName, IServiceProvider? serviceProvider, IDictionary? items) + { + ArgumentException.ThrowIfNullOrEmpty(displayName); + ArgumentNullException.ThrowIfNull(instance); + + if (serviceProvider != null) + { + IServiceProvider localServiceProvider = serviceProvider; + InitializeServiceProvider(localServiceProvider.GetService); + } + + _items = items != null ? new Dictionary(items) : new Dictionary(); + ObjectInstance = instance; + DisplayName = displayName; + } + #endregion #region Properties @@ -178,7 +215,7 @@ public string DisplayName /// Looks up the display name using the DisplayAttribute attached to the respective type or property. /// /// A display-friendly name of the member represented by the . - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctors are marked with RequiresUnreferencedCode.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Constructors that trigger this codepath are marked with RequiresUnreferencedCode. Constructor that takes the display name as an argument is trim-safe.")] private string? GetDisplayName() { string? displayName = null; diff --git a/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/ValidationContextTests.cs b/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/ValidationContextTests.cs index a18321ac1c2d9e..c877e0bd1c93ce 100644 --- a/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/ValidationContextTests.cs +++ b/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/ValidationContextTests.cs @@ -41,6 +41,18 @@ public static void Constructor_creates_new_instance_for_three_arg_constructor() new ValidationContext(testDataAnnotationsDerived, serviceProvider, items); } + [Fact] + public static void Constructor_creates_new_instance_for_four_arg_constructor() + { + var testDataAnnotationsDerived = new TestClass(); + var displayName = "testDisplayName"; + new ValidationContext(testDataAnnotationsDerived, displayName, null, null); + var items = new Dictionary(); + new ValidationContext(testDataAnnotationsDerived, displayName, null, items); + var serviceProvider = new TestServiceProvider(); + new ValidationContext(testDataAnnotationsDerived, displayName, serviceProvider, items); + } + [Fact] public static void ObjectInstance_and_ObjectType_return_same_instance_and_type_as_passed() { @@ -88,6 +100,23 @@ public static void Can_get_and_set_DisplayName_to_existent_and_non_existent_memb Assert.Equal("NonExistentDisplayName", validationContext.DisplayName); } + [Fact] + public static void Can_set_DisplayName_via_constructor() + { + var displayName = "testDisplayName"; + var testDataAnnotationsDerived = new TestClass(); + var validationContext = new ValidationContext(testDataAnnotationsDerived, displayName, null, null); + Assert.Equal(displayName, validationContext.DisplayName); + } + + [Fact] + public static void Setting_DisplayName_to_null_or_empty_via_constructor_throws() + { + var testDataAnnotationsDerived = new TestClass(); + AssertExtensions.Throws("displayName", () => new ValidationContext(testDataAnnotationsDerived, null, null, null)); + AssertExtensions.Throws("displayName", () => new ValidationContext(testDataAnnotationsDerived, string.Empty, null, null)); + } + [Fact] public static void Setting_DisplayName_to_null_or_empty_throws() { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs index c4f6f4161a03f4..2eb67b204463eb 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs @@ -26,7 +26,7 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { if (value is string strValue) { - string text = strValue.Trim(); + ReadOnlySpan text = strValue.AsSpan().Trim(); if (text.Length == 0) { return null; @@ -35,24 +35,19 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( // Parse 2 integer values. culture ??= CultureInfo.CurrentCulture; - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(sep); - int[] values = new int[tokens.Length]; - TypeConverter intConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); - for (int i = 0; i < values.Length; i++) + string sep = culture.TextInfo.ListSeparator; + Span ranges = stackalloc Range[3]; + int rangesCount = text.Split(ranges, sep); + if (rangesCount != 2) { - // Note: ConvertFromString will raise exception if value cannot be converted. - values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i])!; + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text.ToString(), $"x{sep} y")); } - if (values.Length == 2) - { - return new Point(values[0], values[1]); - } - else - { - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text, "x, y")); - } + TypeConverter converter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); + int x = (int)converter.ConvertFromString(context, culture, strValue[ranges[0]])!; + int y = (int)converter.ConvertFromString(context, culture, strValue[ranges[1]])!; + + return new Point(x, y); } return base.ConvertFrom(context, culture, value); @@ -68,20 +63,18 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { culture ??= CultureInfo.CurrentCulture; - string sep = culture.TextInfo.ListSeparator + " "; + string sep = culture.TextInfo.ListSeparator; TypeConverter intConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); // Note: ConvertFromString will raise exception if value cannot be converted. - var args = new string?[] - { - intConverter.ConvertToString(context, culture, pt.X), - intConverter.ConvertToString(context, culture, pt.Y) - }; - return string.Join(sep, args); + string? x = intConverter.ConvertToString(context, culture, pt.X); + string? y = intConverter.ConvertToString(context, culture, pt.Y); + + return $"{x}{sep} {y}"; } else if (destinationType == typeof(InstanceDescriptor)) { - ConstructorInfo? ctor = typeof(Point).GetConstructor(new Type[] { typeof(int), typeof(int) }); + ConstructorInfo? ctor = typeof(Point).GetConstructor([typeof(int), typeof(int)]); if (ctor != null) { return new InstanceDescriptor(ctor, new object[] { pt.X, pt.Y }); @@ -109,7 +102,7 @@ public override object CreateInstance(ITypeDescriptorContext? context, IDictiona public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true; - private static readonly string[] s_propertySort = { "X", "Y" }; + private static readonly string[] s_propertySort = ["X", "Y"]; [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext? context, object? value, Attribute[]? attributes) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs index da85f29784b6b2..a4f1b489e43ec7 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs @@ -26,7 +26,7 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { if (value is string strValue) { - string text = strValue.Trim(); + ReadOnlySpan text = strValue.AsSpan().Trim(); if (text.Length == 0) { return null; @@ -35,22 +35,21 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( // Parse 4 integer values. culture ??= CultureInfo.CurrentCulture; - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(sep); - int[] values = new int[tokens.Length]; - TypeConverter intConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); - for (int i = 0; i < values.Length; i++) + string sep = culture.TextInfo.ListSeparator; + Span ranges = stackalloc Range[5]; + int rangesCount = text.Split(ranges, sep); + if (rangesCount != 4) { - // Note: ConvertFromString will raise exception if value cannot be converted. - values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i])!; + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text.ToString(), $"x{sep} y{sep} width{sep} height")); } - if (values.Length != 4) - { - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text, "x, y, width, height")); - } + TypeConverter converter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); + int x = (int)converter.ConvertFromString(context, culture, strValue[ranges[0]])!; + int y = (int)converter.ConvertFromString(context, culture, strValue[ranges[1]])!; + int width = (int)converter.ConvertFromString(context, culture, strValue[ranges[2]])!; + int height = (int)converter.ConvertFromString(context, culture, strValue[ranges[3]])!; - return new Rectangle(values[0], values[1], values[2], values[3]); + return new Rectangle(x, y, width, height); } return base.ConvertFrom(context, culture, value); @@ -66,23 +65,21 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { culture ??= CultureInfo.CurrentCulture; - string sep = culture.TextInfo.ListSeparator + " "; + string sep = culture.TextInfo.ListSeparator; TypeConverter intConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); // Note: ConvertToString will raise exception if value cannot be converted. - var args = new string?[] - { - intConverter.ConvertToString(context, culture, rect.X), - intConverter.ConvertToString(context, culture, rect.Y), - intConverter.ConvertToString(context, culture, rect.Width), - intConverter.ConvertToString(context, culture, rect.Height) - }; - return string.Join(sep, args); + string? x = intConverter.ConvertToString(context, culture, rect.X); + string? y = intConverter.ConvertToString(context, culture, rect.Y); + string? width = intConverter.ConvertToString(context, culture, rect.Width); + string? height = intConverter.ConvertToString(context, culture, rect.Height); + + return $"{x}{sep} {y}{sep} {width}{sep} {height}"; } else if (destinationType == typeof(InstanceDescriptor)) { - ConstructorInfo? ctor = typeof(Rectangle).GetConstructor(new Type[] { - typeof(int), typeof(int), typeof(int), typeof(int)}); + ConstructorInfo? ctor = typeof(Rectangle).GetConstructor( + [typeof(int), typeof(int), typeof(int), typeof(int)]); if (ctor != null) { @@ -115,7 +112,7 @@ public override object CreateInstance(ITypeDescriptorContext? context, IDictiona public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true; - private static readonly string[] s_propertySort = { "X", "Y", "Width", "Height" }; + private static readonly string[] s_propertySort = ["X", "Y", "Width", "Height"]; [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext? context, object? value, Attribute[]? attributes) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs index a718bc85d9e923..24b8cec971c98e 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs @@ -26,7 +26,7 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { if (value is string strValue) { - string text = strValue.Trim(); + ReadOnlySpan text = strValue.AsSpan().Trim(); if (text.Length == 0) { return null; @@ -35,22 +35,19 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( // Parse 2 integer values. culture ??= CultureInfo.CurrentCulture; - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(sep); - int[] values = new int[tokens.Length]; - TypeConverter intConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); - for (int i = 0; i < values.Length; i++) + string sep = culture.TextInfo.ListSeparator; + Span ranges = stackalloc Range[3]; + int rangesCount = text.Split(ranges, sep); + if (rangesCount != 2) { - // Note: ConvertFromString will raise exception if value cannot be converted. - values[i] = (int)intConverter.ConvertFromString(context, culture, tokens[i])!; + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text.ToString(), $"Width{sep} Height")); } - if (values.Length != 2) - { - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text, "Width,Height")); - } + TypeConverter converter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); + int width = (int)converter.ConvertFromString(context, culture, strValue[ranges[0]])!; + int height = (int)converter.ConvertFromString(context, culture, strValue[ranges[1]])!; - return new Size(values[0], values[1]); + return new Size(width, height); } return base.ConvertFrom(context, culture, value); @@ -66,20 +63,18 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { culture ??= CultureInfo.CurrentCulture; - string sep = culture.TextInfo.ListSeparator + " "; + string sep = culture.TextInfo.ListSeparator; TypeConverter intConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(int)); // Note: ConvertToString will raise exception if value cannot be converted. - var args = new string?[] - { - intConverter.ConvertToString(context, culture, size.Width), - intConverter.ConvertToString(context, culture, size.Height) - }; - return string.Join(sep, args); + string? width = intConverter.ConvertToString(context, culture, size.Width); + string? height = intConverter.ConvertToString(context, culture, size.Height); + + return $"{width}{sep} {height}"; } else if (destinationType == typeof(InstanceDescriptor)) { - ConstructorInfo? ctor = typeof(Size).GetConstructor(new Type[] { typeof(int), typeof(int) }); + ConstructorInfo? ctor = typeof(Size).GetConstructor([typeof(int), typeof(int)]); if (ctor != null) { return new InstanceDescriptor(ctor, new object[] { size.Width, size.Height }); @@ -107,7 +102,7 @@ public override object CreateInstance(ITypeDescriptorContext? context, IDictiona public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true; - private static readonly string[] s_propertySort = { "Width", "Height" }; + private static readonly string[] s_propertySort = ["Width", "Height"]; [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext? context, object value, Attribute[]? attributes) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs index c825178a24b3fb..27e9935194bf95 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs @@ -26,7 +26,7 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { if (value is string strValue) { - string text = strValue.Trim(); + ReadOnlySpan text = strValue.AsSpan().Trim(); if (text.Length == 0) { return null; @@ -35,21 +35,19 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( // Parse 2 integer values. culture ??= CultureInfo.CurrentCulture; - char sep = culture.TextInfo.ListSeparator[0]; - string[] tokens = text.Split(sep); - float[] values = new float[tokens.Length]; - TypeConverter floatConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(float)); - for (int i = 0; i < values.Length; i++) + string sep = culture.TextInfo.ListSeparator; + Span ranges = stackalloc Range[3]; + int rangesCount = text.Split(ranges, sep); + if (rangesCount != 2) { - values[i] = (float)floatConverter.ConvertFromString(context, culture, tokens[i])!; + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text.ToString(), $"Width{sep} Height")); } - if (values.Length != 2) - { - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text, "Width,Height")); - } + TypeConverter converter = TypeDescriptor.GetConverterTrimUnsafe(typeof(float)); + float width = (float)converter.ConvertFromString(context, culture, strValue[ranges[0]])!; + float height = (float)converter.ConvertFromString(context, culture, strValue[ranges[1]])!; - return new SizeF(values[0], values[1]); + return new SizeF(width, height); } return base.ConvertFrom(context, culture, value); @@ -65,18 +63,16 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen( { culture ??= CultureInfo.CurrentCulture; - string sep = culture.TextInfo.ListSeparator + " "; + string sep = culture.TextInfo.ListSeparator; TypeConverter floatConverter = TypeDescriptor.GetConverterTrimUnsafe(typeof(float)); - var args = new string?[] - { - floatConverter.ConvertToString(context, culture, size.Width), - floatConverter.ConvertToString(context, culture, size.Height) - }; - return string.Join(sep, args); + string? width = floatConverter.ConvertToString(context, culture, size.Width); + string? height = floatConverter.ConvertToString(context, culture, size.Height); + + return $"{width}{sep} {height}"; } else if (destinationType == typeof(InstanceDescriptor)) { - ConstructorInfo? ctor = typeof(SizeF).GetConstructor(new Type[] { typeof(float), typeof(float) }); + ConstructorInfo? ctor = typeof(SizeF).GetConstructor([typeof(float), typeof(float)]); if (ctor != null) { return new InstanceDescriptor(ctor, new object[] { size.Width, size.Height }); @@ -104,7 +100,7 @@ public override object CreateInstance(ITypeDescriptorContext? context, IDictiona public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true; - private static readonly string[] s_propertySort = { "Width", "Height" }; + private static readonly string[] s_propertySort = ["Width", "Height"]; [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext? context, object value, Attribute[]? attributes) diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/PointConverterTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/PointConverterTests.cs index 90b7c95ecce985..b0a8d19167e8f2 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/PointConverterTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/PointConverterTests.cs @@ -80,18 +80,17 @@ public void CanConvertToFalse(Type type) } public static IEnumerable PointData => - new[] - { - new object[] {0, 0}, - new object[] {1, 1}, - new object[] {-1, 1}, - new object[] {1, -1}, - new object[] {-1, -1}, - new object[] {int.MaxValue, int.MaxValue}, - new object[] {int.MinValue, int.MaxValue}, - new object[] {int.MaxValue, int.MinValue}, - new object[] {int.MinValue, int.MinValue}, - }; + [ + [0, 1], + [1, 0], + [-1, 1], + [1, -1], + [-1, -2], + [int.MaxValue, int.MaxValue - 1], + [int.MinValue, int.MaxValue], + [int.MaxValue, int.MinValue], + [int.MinValue, int.MinValue + 1], + ]; [Theory] [MemberData(nameof(PointData))] @@ -102,7 +101,9 @@ public void ConvertFrom(int x, int y) [Theory] [InlineData("1")] + [InlineData("*1")] [InlineData("1, 1, 1")] + [InlineData("*1, 1, 1")] public void ConvertFrom_ArgumentException(string value) { ConvertFromThrowsArgumentExceptionForString(value); @@ -114,6 +115,14 @@ public void ConvertFrom_Invalid() ConvertFromThrowsFormatInnerExceptionForString("*1, 1"); } + [Theory] + [InlineData("")] + [InlineData(" \t ")] + public void ConvertFrom_WhiteSpace(string value) + { + Assert.Null(Converter.ConvertFromString(value)); + } + public static IEnumerable ConvertFrom_NotSupportedData => new[] { @@ -153,7 +162,7 @@ public void ConvertTo_NotSupportedException(Type type) public void ConvertTo_NullCulture() { string listSep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; - Assert.Equal($"1{listSep} 1", Converter.ConvertTo(null, null, new Point(1, 1), typeof(string))); + Assert.Equal($"1{listSep} 2", Converter.ConvertTo(null, null, new Point(1, 2), typeof(string))); } [Fact] @@ -172,31 +181,31 @@ public void CreateInstance_CaseSensitive() [Fact] public void GetProperties() { - var pt = new Point(1, 1); - var props = Converter.GetProperties(new Point(1, 1)); + var pt = new Point(1, 2); + var props = Converter.GetProperties(new Point(3, 4)); Assert.Equal(2, props.Count); Assert.Equal(1, props["X"].GetValue(pt)); - Assert.Equal(1, props["Y"].GetValue(pt)); + Assert.Equal(2, props["Y"].GetValue(pt)); - props = Converter.GetProperties(null, new Point(1, 1)); + props = Converter.GetProperties(null, new Point(3, 4)); Assert.Equal(2, props.Count); Assert.Equal(1, props["X"].GetValue(pt)); - Assert.Equal(1, props["Y"].GetValue(pt)); + Assert.Equal(2, props["Y"].GetValue(pt)); - props = Converter.GetProperties(null, new Point(1, 1), null); + props = Converter.GetProperties(null, new Point(3, 4), null); Assert.Equal(3, props.Count); Assert.Equal(1, props["X"].GetValue(pt)); - Assert.Equal(1, props["Y"].GetValue(pt)); + Assert.Equal(2, props["Y"].GetValue(pt)); Assert.Equal((object)false, props["IsEmpty"].GetValue(pt)); - props = Converter.GetProperties(null, new Point(1, 1), new Attribute[0]); + props = Converter.GetProperties(null, new Point(3, 4), new Attribute[0]); Assert.Equal(3, props.Count); Assert.Equal(1, props["X"].GetValue(pt)); - Assert.Equal(1, props["Y"].GetValue(pt)); + Assert.Equal(2, props["Y"].GetValue(pt)); Assert.Equal((object)false, props["IsEmpty"].GetValue(pt)); // Pick an attribute that cannot be applied to properties to make sure everything gets filtered - props = Converter.GetProperties(null, new Point(1, 1), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); + props = Converter.GetProperties(null, new Point(3, 4), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); Assert.Equal(0, props.Count); } @@ -218,7 +227,7 @@ public void ConvertFromInvariantString_ArgumentException() [Fact] public void ConvertFromInvariantString_FormatException() { - ConvertFromInvariantStringThrowsFormatInnerException("hello"); + ConvertFromInvariantStringThrowsFormatInnerException("hello, hello"); } [Theory] @@ -241,7 +250,8 @@ public void ConvertFromString_ArgumentException() [Fact] public void ConvertFromString_FormatException() { - ConvertFromStringThrowsFormatInnerException("hello"); + var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; + ConvertFromStringThrowsFormatInnerException($"hello{sep} hello"); } [Theory] diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/RectangleConverterTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/RectangleConverterTests.cs index 4c939f8a61228f..2a7c9a7b26e984 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/RectangleConverterTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/RectangleConverterTests.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Drawing; using System.Globalization; -using System.Linq; using Xunit; namespace System.ComponentModel.TypeConverterTests @@ -21,19 +20,19 @@ public class RectangleConverterTests : StringTypeConverterTestBase protected override IEnumerable>> CreateInstancePairs { get { - yield return Tuple.Create(new Rectangle(10, 10, 20, 30), new Dictionary + yield return Tuple.Create(new Rectangle(10, 20, 30, 40), new Dictionary { ["X"] = 10, - ["Y"] = 10, - ["Width"] = 20, - ["Height"] = 30, + ["Y"] = 20, + ["Width"] = 30, + ["Height"] = 40, }); - yield return Tuple.Create(new Rectangle(-10, -10, 20, 30), new Dictionary + yield return Tuple.Create(new Rectangle(-10, -20, -30, -40), new Dictionary { ["X"] = -10, - ["Y"] = -10, - ["Width"] = 20, - ["Height"] = 30, + ["Y"] = -20, + ["Width"] = -30, + ["Height"] = -40, }); } } @@ -83,18 +82,16 @@ public void CanConvertToFalse(Type type) } public static IEnumerable RectangleData => - new[] - { - new object[] {0, 0, 0, 0}, - new object[] {1, 1, 1, 1}, - new object[] {-1, 1, 1, 1}, - new object[] {1, -1, 1, 1}, - new object[] {-1, -1, 1, 1}, - new object[] {int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue}, - new object[] {int.MinValue, int.MaxValue, int.MaxValue, int.MaxValue}, - new object[] {int.MaxValue, int.MinValue, int.MaxValue, int.MaxValue}, - new object[] {int.MinValue, int.MinValue, int.MaxValue, int.MaxValue}, - }; + [ + [0, 1, 2, 3], + [1, 0, 3, 4], + [-1, -2, 0, -4], + [-2, -3, -4, 0], + [int.MaxValue, int.MaxValue - 1, int.MinValue + 1, int.MinValue], + [int.MinValue, int.MaxValue, int.MaxValue - 1, int.MinValue + 1], + [int.MinValue + 1, int.MinValue, int.MaxValue, int.MaxValue - 1], + [int.MaxValue - 1, int.MinValue + 1, int.MinValue, int.MaxValue], + ]; [Theory] [MemberData(nameof(RectangleData))] @@ -105,7 +102,9 @@ public void ConvertFrom(int x, int y, int width, int height) [Theory] [InlineData("10, 10")] + [InlineData("*10, 10")] [InlineData("1, 1, 1, 1, 1")] + [InlineData("*1, 1, 1, 1, 1")] public void ConvertFrom_ArgumentException(string value) { ConvertFromThrowsArgumentExceptionForString(value); @@ -117,6 +116,14 @@ public void ConvertFrom_Invalid() ConvertFromThrowsFormatInnerExceptionForString("*1, 1, 1, 1"); } + [Theory] + [InlineData("")] + [InlineData(" \t ")] + public void ConvertFrom_WhiteSpace(string value) + { + Assert.Null(Converter.ConvertFromString(value)); + } + public static IEnumerable ConvertFrom_NotSupportedData => new[] { @@ -162,7 +169,7 @@ public void CreateInstance_CaseSensitive() Converter.CreateInstance(null, new Dictionary { ["x"] = -10, - ["Y"] = -10, + ["Y"] = -20, ["Width"] = 20, ["Height"] = 30, }); @@ -172,7 +179,7 @@ public void CreateInstance_CaseSensitive() [Fact] public void TestGetProperties() { - var rect = new Rectangle(10, 10, 20, 30); + var rect = new Rectangle(10, 20, 30, 40); var propsColl = Converter.GetProperties(rect); Assert.Equal(4, propsColl.Count); Assert.Equal(rect.X, propsColl["X"].GetValue(rect)); @@ -180,7 +187,7 @@ public void TestGetProperties() Assert.Equal(rect.Width, propsColl["Width"].GetValue(rect)); Assert.Equal(rect.Height, propsColl["Height"].GetValue(rect)); - rect = new Rectangle(-10, -10, 20, 30); + rect = new Rectangle(-10, -20, -30, -40); propsColl = Converter.GetProperties(null, rect); Assert.Equal(4, propsColl.Count); Assert.Equal(rect.X, propsColl["X"].GetValue(rect)); @@ -188,7 +195,7 @@ public void TestGetProperties() Assert.Equal(rect.Width, propsColl["Width"].GetValue(rect)); Assert.Equal(rect.Height, propsColl["Height"].GetValue(rect)); - rect = new Rectangle(10, 10, 20, 30); + rect = new Rectangle(10, 20, 30, 40); propsColl = Converter.GetProperties(null, rect, null); Assert.Equal(11, propsColl.Count); Assert.Equal(rect.X, propsColl["X"].GetValue(rect)); @@ -203,10 +210,9 @@ public void TestGetProperties() Assert.Equal(rect.Right, propsColl["Right"].GetValue(rect)); Assert.Equal(rect.Location, propsColl["Location"].GetValue(rect)); Assert.Equal(rect.Size, propsColl["Size"].GetValue(rect)); - Assert.Equal(rect.IsEmpty, propsColl["IsEmpty"].GetValue(rect)); // Pick an attribute that cannot be applied to properties to make sure everything gets filtered - propsColl = Converter.GetProperties(null, new Rectangle(10, 10, 20, 30), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); + propsColl = Converter.GetProperties(null, new Rectangle(10, 20, 30, 40), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); Assert.Equal(0, propsColl.Count); } @@ -230,7 +236,7 @@ public void ConvertFromInvariantString_ArgumentException() [Fact] public void ConvertFromInvariantString_FormatException() { - ConvertFromInvariantStringThrowsFormatInnerException("hello"); + ConvertFromInvariantStringThrowsFormatInnerException("hello, hello, hello, hello"); } [Theory] @@ -256,7 +262,8 @@ public void ConvertFromString_ArgumentException() [Fact] public void ConvertFromString_FormatException() { - ConvertFromStringThrowsFormatInnerException("hello"); + var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; + ConvertFromStringThrowsFormatInnerException($"hello{sep} hello{sep} hello{sep} hello"); } [Theory] diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeConverterTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeConverterTests.cs index 478e29c86f801e..9ab4c78db51a08 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeConverterTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeConverterTests.cs @@ -80,18 +80,17 @@ public void CanConvertToFalse(Type type) } public static IEnumerable SizeData => - new[] - { - new object[] {0, 0}, - new object[] {1, 1}, - new object[] {-1, 1}, - new object[] {1, -1}, - new object[] {-1, -1}, - new object[] {int.MaxValue, int.MaxValue}, - new object[] {int.MinValue, int.MaxValue}, - new object[] {int.MaxValue, int.MinValue}, - new object[] {int.MinValue, int.MinValue}, - }; + [ + [0, 1], + [1, 0], + [-1, 1], + [1, -1], + [-1, -2], + [int.MaxValue, int.MaxValue - 1], + [int.MinValue, int.MaxValue], + [int.MaxValue, int.MinValue], + [int.MinValue, int.MinValue + 1], + ]; [Theory] [MemberData(nameof(SizeData))] @@ -102,7 +101,9 @@ public void ConvertFrom(int width, int height) [Theory] [InlineData("1")] - [InlineData("1, 1, 1")] + [InlineData("*1")] + [InlineData("1, 2, 3")] + [InlineData("*1, 2, 3")] public void ConvertFrom_ArgumentException(string value) { ConvertFromThrowsArgumentExceptionForString(value); @@ -114,6 +115,14 @@ public void ConvertFrom_Invalid() ConvertFromThrowsFormatInnerExceptionForString("*1, 1"); } + [Theory] + [InlineData("")] + [InlineData(" \t ")] + public void ConvertFrom_WhiteSpace(string value) + { + Assert.Null(Converter.ConvertFromString(value)); + } + public static IEnumerable ConvertFrom_NotSupportedData => new[] { @@ -153,7 +162,7 @@ public void ConvertTo_NotSupportedException(Type type) public void ConvertTo_NullCulture() { string listSep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; - Assert.Equal($"1{listSep} 1", Converter.ConvertTo(null, null, new Size(1, 1), typeof(string))); + Assert.Equal($"1{listSep} 2", Converter.ConvertTo(null, null, new Size(1, 2), typeof(string))); } [Fact] @@ -172,31 +181,31 @@ public void CreateInstance_CaseSensitive() [Fact] public void GetProperties() { - var pt = new Size(1, 1); - var props = Converter.GetProperties(new Size(1, 1)); + var pt = new Size(1, 2); + var props = Converter.GetProperties(new Size(3, 4)); Assert.Equal(2, props.Count); Assert.Equal(1, props["Width"].GetValue(pt)); - Assert.Equal(1, props["Height"].GetValue(pt)); + Assert.Equal(2, props["Height"].GetValue(pt)); - props = Converter.GetProperties(null, new Size(1, 1)); + props = Converter.GetProperties(null, new Size(3, 4)); Assert.Equal(2, props.Count); Assert.Equal(1, props["Width"].GetValue(pt)); - Assert.Equal(1, props["Height"].GetValue(pt)); + Assert.Equal(2, props["Height"].GetValue(pt)); - props = Converter.GetProperties(null, new Size(1, 1), null); + props = Converter.GetProperties(null, new Size(3, 4), null); Assert.Equal(3, props.Count); Assert.Equal(1, props["Width"].GetValue(pt)); - Assert.Equal(1, props["Height"].GetValue(pt)); + Assert.Equal(2, props["Height"].GetValue(pt)); Assert.Equal((object)false, props["IsEmpty"].GetValue(pt)); - props = Converter.GetProperties(null, new Size(1, 1), new Attribute[0]); + props = Converter.GetProperties(null, new Size(3, 4), new Attribute[0]); Assert.Equal(3, props.Count); Assert.Equal(1, props["Width"].GetValue(pt)); - Assert.Equal(1, props["Height"].GetValue(pt)); + Assert.Equal(2, props["Height"].GetValue(pt)); Assert.Equal((object)false, props["IsEmpty"].GetValue(pt)); // Pick an attribute that cannot be applied to properties to make sure everything gets filtered - props = Converter.GetProperties(null, new Size(1, 1), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); + props = Converter.GetProperties(null, new Size(3, 4), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); Assert.Equal(0, props.Count); } @@ -218,7 +227,7 @@ public void ConvertFromInvariantString_ArgumentException() [Fact] public void ConvertFromInvariantString_FormatException() { - ConvertFromInvariantStringThrowsFormatInnerException("hello"); + ConvertFromInvariantStringThrowsFormatInnerException("hello, hello"); } [Theory] @@ -241,7 +250,8 @@ public void ConvertFromString_ArgumentException() [Fact] public void ConvertFromString_FormatException() { - ConvertFromStringThrowsFormatInnerException("hello"); + var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; + ConvertFromStringThrowsFormatInnerException($"hello{sep} hello"); } [Theory] diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeFConverterTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeFConverterTests.cs index 6d19fedaf5b1d8..a57ee25ed91771 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeFConverterTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Drawing/SizeFConverterTests.cs @@ -80,18 +80,19 @@ public void CanConvertToFalse(Type type) } public static IEnumerable SizeFData => - new[] - { - new object[] {0, 0}, - new object[] {1, 1}, - new object[] {-1, 1}, - new object[] {1, -1}, - new object[] {-1, -1}, - new object[] {float.MaxValue, float.MaxValue}, - new object[] {float.MinValue, float.MaxValue}, - new object[] {float.MaxValue, float.MinValue}, - new object[] {float.MinValue, float.MinValue}, - }; + [ + [0, 1], + [1, 0], + [-1, 1], + [1, -1], + [-1, -2], + [float.MaxValue, float.MaxValue / 2], + [float.MinValue, float.MaxValue], + [float.MaxValue, float.MinValue], + [float.MinValue, float.MinValue / 2], + [float.Epsilon, -float.Epsilon * 2], + [-float.Epsilon, float.Epsilon * 2], + ]; [Theory] [MemberData(nameof(SizeFData))] @@ -102,7 +103,9 @@ public void ConvertFrom(float width, float height) [Theory] [InlineData("1")] + [InlineData("*1")] [InlineData("1, 1, 1")] + [InlineData("*1, 1, 1")] public void ConvertFrom_ArgumentException(string value) { ConvertFromThrowsArgumentExceptionForString(value); @@ -114,6 +117,14 @@ public void ConvertFrom_Invalid() ConvertFromThrowsFormatInnerExceptionForString("*1, 1"); } + [Theory] + [InlineData("")] + [InlineData(" \t ")] + public void ConvertFrom_WhiteSpace(string value) + { + Assert.Null(Converter.ConvertFromString(value)); + } + public static IEnumerable ConvertFrom_NotSupportedData => new[] { @@ -153,7 +164,7 @@ public void ConvertTo_NotSupportedException(Type type) public void ConvertTo_NullCulture() { string listSep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; - Assert.Equal($"1{listSep} 1", Converter.ConvertTo(null, null, new SizeF(1, 1), typeof(string))); + Assert.Equal($"1{listSep} 2", Converter.ConvertTo(null, null, new SizeF(1, 2), typeof(string))); } [Fact] @@ -170,31 +181,31 @@ public void CreateInstance_CaseSensitive() [Fact] public void GetProperties() { - var pt = new SizeF(1, 1); - var props = Converter.GetProperties(new SizeF(1, 1)); + var pt = new SizeF(1, 2); + var props = Converter.GetProperties(new SizeF(3, 4)); Assert.Equal(2, props.Count); Assert.Equal(1f, props["Width"].GetValue(pt)); - Assert.Equal(1f, props["Height"].GetValue(pt)); + Assert.Equal(2f, props["Height"].GetValue(pt)); - props = Converter.GetProperties(null, new SizeF(1, 1)); + props = Converter.GetProperties(null, new SizeF(3, 4)); Assert.Equal(2, props.Count); Assert.Equal(1f, props["Width"].GetValue(pt)); - Assert.Equal(1f, props["Height"].GetValue(pt)); + Assert.Equal(2f, props["Height"].GetValue(pt)); - props = Converter.GetProperties(null, new SizeF(1, 1), null); + props = Converter.GetProperties(null, new SizeF(3, 4), null); Assert.Equal(3, props.Count); Assert.Equal(1f, props["Width"].GetValue(pt)); - Assert.Equal(1f, props["Height"].GetValue(pt)); + Assert.Equal(2f, props["Height"].GetValue(pt)); Assert.Equal((object)false, props["IsEmpty"].GetValue(pt)); - props = Converter.GetProperties(null, new SizeF(1, 1), new Attribute[0]); + props = Converter.GetProperties(null, new SizeF(3, 4), new Attribute[0]); Assert.Equal(3, props.Count); Assert.Equal(1f, props["Width"].GetValue(pt)); - Assert.Equal(1f, props["Height"].GetValue(pt)); + Assert.Equal(2f, props["Height"].GetValue(pt)); Assert.Equal((object)false, props["IsEmpty"].GetValue(pt)); // Pick an attribute that cannot be applied to properties to make sure everything gets filtered - props = Converter.GetProperties(null, new SizeF(1, 1), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); + props = Converter.GetProperties(null, new SizeF(3, 4), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); Assert.Equal(0, props.Count); } @@ -216,7 +227,7 @@ public void ConvertFromInvariantString_ArgumentException() [Fact] public void ConvertFromInvariantString_FormatException() { - ConvertFromInvariantStringThrowsFormatInnerException("hello"); + ConvertFromInvariantStringThrowsFormatInnerException("hello, hello"); } [Theory] @@ -239,7 +250,8 @@ public void ConvertFromString_ArgumentException() [Fact] public void ConvertFromString_FormatException() { - ConvertFromStringThrowsFormatInnerException("hello"); + var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; + ConvertFromStringThrowsFormatInnerException($"hello{sep} hello"); } [Theory] diff --git a/src/libraries/System.Composition.AttributedModel/tests/System.Composition.AttributeModel.Tests.csproj b/src/libraries/System.Composition.AttributedModel/tests/System.Composition.AttributeModel.Tests.csproj index 8aef684e2caf5f..f633d1d7fbfc19 100644 --- a/src/libraries/System.Composition.AttributedModel/tests/System.Composition.AttributeModel.Tests.csproj +++ b/src/libraries/System.Composition.AttributedModel/tests/System.Composition.AttributeModel.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Composition.Convention/tests/System.Composition.Convention.Tests.csproj b/src/libraries/System.Composition.Convention/tests/System.Composition.Convention.Tests.csproj index 841657bbb9c0c6..456c33a001fa4c 100644 --- a/src/libraries/System.Composition.Convention/tests/System.Composition.Convention.Tests.csproj +++ b/src/libraries/System.Composition.Convention/tests/System.Composition.Convention.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Composition.Hosting/tests/System.Composition.Hosting.Tests.csproj b/src/libraries/System.Composition.Hosting/tests/System.Composition.Hosting.Tests.csproj index 8e6cdee5158b70..74b5160fae29a2 100644 --- a/src/libraries/System.Composition.Hosting/tests/System.Composition.Hosting.Tests.csproj +++ b/src/libraries/System.Composition.Hosting/tests/System.Composition.Hosting.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Composition.Runtime/tests/System.Composition.Runtime.Tests.csproj b/src/libraries/System.Composition.Runtime/tests/System.Composition.Runtime.Tests.csproj index 5439d9d781d20e..82de86ddb7ed97 100644 --- a/src/libraries/System.Composition.Runtime/tests/System.Composition.Runtime.Tests.csproj +++ b/src/libraries/System.Composition.Runtime/tests/System.Composition.Runtime.Tests.csproj @@ -1,7 +1,9 @@ + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) + @@ -10,10 +12,9 @@ + - - - + \ No newline at end of file diff --git a/src/libraries/System.Composition.TypedParts/tests/System.Composition.TypedParts.Tests.csproj b/src/libraries/System.Composition.TypedParts/tests/System.Composition.TypedParts.Tests.csproj index 2e6b8d57979fad..80dfd5cd250a64 100644 --- a/src/libraries/System.Composition.TypedParts/tests/System.Composition.TypedParts.Tests.csproj +++ b/src/libraries/System.Composition.TypedParts/tests/System.Composition.TypedParts.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true @@ -14,7 +14,6 @@ - diff --git a/src/libraries/System.Composition/tests/Microsoft.Composition.Demos.ExtendedCollectionImports/Microsoft.Composition.Demos.ExtendedCollectionImports.csproj b/src/libraries/System.Composition/tests/Microsoft.Composition.Demos.ExtendedCollectionImports/Microsoft.Composition.Demos.ExtendedCollectionImports.csproj index 8456d2bdc904d2..e35ae952285f1e 100644 --- a/src/libraries/System.Composition/tests/Microsoft.Composition.Demos.ExtendedCollectionImports/Microsoft.Composition.Demos.ExtendedCollectionImports.csproj +++ b/src/libraries/System.Composition/tests/Microsoft.Composition.Demos.ExtendedCollectionImports/Microsoft.Composition.Demos.ExtendedCollectionImports.csproj @@ -1,6 +1,6 @@ - netstandard2.0;$(NetFrameworkMinimum) + netstandard2.0;$(NetFrameworkCurrent) diff --git a/src/libraries/System.Composition/tests/System.Composition.Tests.csproj b/src/libraries/System.Composition/tests/System.Composition.Tests.csproj index f9242fd5e2f45d..c15bf8613b019c 100644 --- a/src/libraries/System.Composition/tests/System.Composition.Tests.csproj +++ b/src/libraries/System.Composition/tests/System.Composition.Tests.csproj @@ -1,7 +1,7 @@ + $(NetCoreAppCurrent);$(NetFrameworkCurrent) System.Composition.Lightweight.UnitTests - $(NetCoreAppCurrent);$(NetFrameworkMinimum) diff --git a/src/libraries/System.Composition/tests/TestLibrary/TestLibrary.csproj b/src/libraries/System.Composition/tests/TestLibrary/TestLibrary.csproj index 3045d462256d42..b4f126e1a15462 100644 --- a/src/libraries/System.Composition/tests/TestLibrary/TestLibrary.csproj +++ b/src/libraries/System.Composition/tests/TestLibrary/TestLibrary.csproj @@ -1,6 +1,6 @@ - netstandard2.0;$(NetFrameworkMinimum) + netstandard2.0;$(NetFrameworkCurrent) diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj index a4582dbd3584d8..df0132b384c1da 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj @@ -1,7 +1,7 @@  true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true $(DefineConstants);LEGACY_GETRESOURCESTRING_USER diff --git a/src/libraries/System.Data.Odbc/tests/System.Data.Odbc.Tests.csproj b/src/libraries/System.Data.Odbc/tests/System.Data.Odbc.Tests.csproj index 46d4e355a1800f..7c5017ed50d650 100644 --- a/src/libraries/System.Data.Odbc/tests/System.Data.Odbc.Tests.csproj +++ b/src/libraries/System.Data.Odbc/tests/System.Data.Odbc.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetFrameworkCurrent) diff --git a/src/libraries/System.Data.OleDb/tests/System.Data.OleDb.Tests.csproj b/src/libraries/System.Data.OleDb/tests/System.Data.OleDb.Tests.csproj index 6f72486a944fbd..d163d0d2f83c60 100644 --- a/src/libraries/System.Data.OleDb/tests/System.Data.OleDb.Tests.csproj +++ b/src/libraries/System.Data.OleDb/tests/System.Data.OleDb.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) diff --git a/src/libraries/System.Diagnostics.EventLog/tests/System.Diagnostics.EventLog.Tests.csproj b/src/libraries/System.Diagnostics.EventLog/tests/System.Diagnostics.EventLog.Tests.csproj index 3ce9ebf7bfb92e..66b09a1a8ff65e 100644 --- a/src/libraries/System.Diagnostics.EventLog/tests/System.Diagnostics.EventLog.Tests.csproj +++ b/src/libraries/System.Diagnostics.EventLog/tests/System.Diagnostics.EventLog.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) true diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj index fb902be8219173..6942d5bb687eb7 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj @@ -1,7 +1,7 @@ + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) true - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index 39ad5dc6576f85..c383cabe4aae9a 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -2267,6 +2267,7 @@ public void TestLongProcessIsWorking() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/52852", TestPlatforms.MacCatalyst)] [ActiveIssue("https://github.com/dotnet/runtime/issues/53095", TestPlatforms.Android)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/29383", TestPlatforms.OSX)] public void LongProcessNamesAreSupported() { string sleepPath; diff --git a/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs b/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs index 3559adc9703731..c46574061b7f0a 100644 --- a/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs +++ b/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs @@ -663,27 +663,27 @@ public partial class SecurityPackageContextConnectionInformation { internal SecurityPackageContextConnectionInformation() { } #if NET10_0_OR_GREATER - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.Authentication.CipherAlgorithmType AlgorithmIdentifier { get { throw null; } } #if NET10_0_OR_GREATER - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public int CipherStrength { get { throw null; } } #if NET10_0_OR_GREATER - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public int ExchangeStrength { get { throw null; } } #if NET10_0_OR_GREATER - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.Authentication.HashAlgorithmType Hash { get { throw null; } } #if NET10_0_OR_GREATER - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public int HashStrength { get { throw null; } } #if NET10_0_OR_GREATER - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public int KeyExchangeAlgorithm { get { throw null; } } public System.DirectoryServices.Protocols.SecurityProtocol Protocol { get { throw null; } } diff --git a/src/libraries/System.Formats.Asn1/tests/System.Formats.Asn1.Tests.csproj b/src/libraries/System.Formats.Asn1/tests/System.Formats.Asn1.Tests.csproj index 3626af0c77d1a5..fec46d5554a8b5 100644 --- a/src/libraries/System.Formats.Asn1/tests/System.Formats.Asn1.Tests.csproj +++ b/src/libraries/System.Formats.Asn1/tests/System.Formats.Asn1.Tests.csproj @@ -1,7 +1,7 @@  + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs index 16fccd99cc1c5f..040378d33b4fc5 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs @@ -25,9 +25,9 @@ private protected ArrayRecord(ArrayInfo arrayInfo) } /// - /// When overridden in a derived class, gets a buffer of integers that represent the number of elements in every dimension. + /// When overridden in a derived class, gets a buffer of integers that represent the number of elements in each dimension. /// - /// A buffer of integers that represent the number of elements in every dimension. + /// A buffer of integers that represent the number of elements in each dimension. public abstract ReadOnlySpan Lengths { get; } /// @@ -65,9 +65,8 @@ internal bool IsJagged /// An array filled with the data provided in the serialized records. /// does not match the data from the payload. /// - /// Check the total length of the array by using property before calling this method, - /// as an attacker could have sent you a small payload that will require to allocate a very large array - /// and potentially cause and Denial of Service. + /// Before calling this method, check the total length of the array by using the property. + /// An attacker could have sent a small payload that requires allocation of a very large array, which could cause and denial of service. /// [RequiresDynamicCode("The code for an array of the specified type might not be available.")] public Array GetArray(Type expectedArrayType, bool allowNulls = true) diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleObjectRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleObjectRecord.cs index 2c402af7c35ab0..3010b2930494ae 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleObjectRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleObjectRecord.cs @@ -10,7 +10,7 @@ namespace System.Formats.Nrbf; /// -/// Represents a single dimensional array of . +/// Represents a single-dimensional array of . /// /// /// ArraySingleObject records are described in [MS-NRBF] 2.4.3.2. diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleStringRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleStringRecord.cs index 38884aadc54693..b276fc8955c5f7 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleStringRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySingleStringRecord.cs @@ -10,7 +10,7 @@ namespace System.Formats.Nrbf; /// -/// Represents a single dimensional array of . +/// Represents a single-dimensional array of . /// /// /// ArraySingleString records are described in [MS-NRBF] 2.4.3.4. diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassRecord.cs index 1d61bee3b23709..4453584117a798 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassRecord.cs @@ -43,7 +43,7 @@ private protected ClassRecord(ClassInfo classInfo, MemberTypeInfo memberTypeInfo /// Checks if the member with the given name was present in the payload. /// /// The name of the member. - /// if it was present, otherwise . + /// if the member was present, otherwise . /// /// It's recommended to use this method when dealing with payload that might contain /// different versions of the same type. diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs index dd5ee0e5bdf2c7..64b2c2425c9569 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassTypeInfo.cs @@ -9,7 +9,7 @@ namespace System.Formats.Nrbf; /// -/// Identifies a class by its name and library id. +/// Identifies a class by its name and library ID. /// /// /// ClassTypeInfo structures are described in [MS-NRBF] 2.1.1.8. diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs index 192fe80c6f5681..d3fbe95aded07a 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs @@ -18,7 +18,7 @@ namespace System.Formats.Nrbf; /// /// /// NrbfDecoder is an implementation of an NRBF reader, but its behaviors don't strictly follow BinaryFormatter's implementation. -/// Thus the output of NrbfDecoder shouldn't be used to determine whether a call to BinaryFormatter would be safe. +/// You shouldn't use the output of NrbfDecoder to determine whether a call to BinaryFormatter would be safe. /// public static class NrbfDecoder { diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/PayloadOptions.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/PayloadOptions.cs index 213eb0d77577f1..779c5dd817174d 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/PayloadOptions.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/PayloadOptions.cs @@ -27,12 +27,14 @@ public PayloadOptions() { } /// /// /// Example: - /// TypeName: "Namespace.TypeName`1[[Namespace.GenericArgName" - /// LibraryName: "AssemblyName]]" - /// Is combined into "Namespace.TypeName`1[[Namespace.GenericArgName, AssemblyName]]" /// + /// TypeName: "Namespace.TypeName`1[[Namespace.GenericArgName" + /// LibraryName: "AssemblyName]]" /// - /// Setting this to can render susceptible to Denial of Service + /// Is combined into "Namespace.TypeName`1[[Namespace.GenericArgName, AssemblyName]]" + /// + /// + /// Setting this property to can render susceptible to denial of service /// attacks when parsing or handling malicious input. /// /// diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs index 74359693604651..67c8bb590feddb 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs @@ -35,9 +35,9 @@ private protected SZArrayRecord(ArrayInfo arrayInfo) : base(arrayInfo) /// /// An array filled with the data provided in the serialized records. /// - /// Check the total length of the array by using property before calling this method, - /// as an attacker could have sent you a small payload that will require to allocate a very large array - /// and potentially cause and Denial of Service. + /// Before calling this method, check the total length of the array by using the property. + /// An attacker could have sent you a small payload that requires allocation of a very large array + /// that could cause and denial of service. /// public abstract T?[] GetArray(bool allowNulls = true); diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs index fa7d2eda86ca60..30830cd84eab04 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs @@ -11,10 +11,8 @@ namespace System.Formats.Nrbf; /// Abstract class that represents the serialization record. /// /// -/// /// Every instance returned to the end user can be either , /// a , or an . -/// /// [DebuggerDisplay("{RecordType}, {Id}")] public abstract class SerializationRecord @@ -40,8 +38,8 @@ internal SerializationRecord() // others can't derive from this type /// /// The name of the serialized type. /// - /// Since the provided type name may originate from untrusted input, - /// it should not be utilized for type loading, as it could potentially load a malicious type. + /// Since the provided type name might originate from untrusted input, + /// don't use it for type loading, as it could potentially load a malicious type. /// public abstract TypeName TypeName { get; } @@ -154,7 +152,7 @@ private static bool Matches(Type type, TypeName typeName) /// /// Gets the primitive, string, or null record value. /// For reference records, it returns the referenced record. - /// For other records, it returns the records themselves. + /// For other records, it returns the record itself. /// /// /// Overrides of this method should take care not to allow diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs index fac6966f6abd49..969380a08694d0 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs @@ -14,10 +14,10 @@ namespace System.Formats.Nrbf; /// -/// The ID of . +/// Represents the ID of . /// /// -/// It can be used the detect cycles in decoded records. +/// This struct can be used to detect cycles in decoded records. /// [DebuggerDisplay("{_id}")] public readonly struct SerializationRecordId : IEquatable diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordType.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordType.cs index 1fc1236a94b402..46f5bc380acfc4 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordType.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordType.cs @@ -7,7 +7,7 @@ namespace System.Formats.Nrbf; /// Specifies record types. /// /// -/// SerializationRecordType enumeration is described in [MS-NRBF] 2.1.2.1. +/// The RecordTypeEnumeration enumeration is described in [MS-NRBF] 2.1.2.1. /// public enum SerializationRecordType { @@ -20,7 +20,7 @@ public enum SerializationRecordType /// ClassWithId, /// - /// A system class information without type info. + /// System class information without type info. /// /// Not supported by design. SystemClassWithMembers, diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializedStreamHeaderRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializedStreamHeaderRecord.cs index b21ff8ca23732b..bf35b09b301240 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializedStreamHeaderRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializedStreamHeaderRecord.cs @@ -9,7 +9,7 @@ namespace System.Formats.Nrbf; /// -/// Represents the NRBF header, it must be the first record in NRBF payload. +/// Represents the NRBF header. It must be the first record in NRBF payload. /// /// /// SerializedStreamHeader records are described in [MS-NRBF] 2.6.1. diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SystemClassWithMembersAndTypesRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SystemClassWithMembersAndTypesRecord.cs index 0c5193cd92272a..0ce423ef128ce2 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SystemClassWithMembersAndTypesRecord.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SystemClassWithMembersAndTypesRecord.cs @@ -11,7 +11,7 @@ namespace System.Formats.Nrbf; /// Class information with type info. /// /// -/// SystemClassWithMembersAndType records are described in [MS-NRBF] 2.3.2.3. +/// SystemClassWithMembersAndType records are described in [MS-NRBF] 2.3.2.3. /// internal sealed class SystemClassWithMembersAndTypesRecord : ClassRecord { diff --git a/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj b/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj index c31537bb983ef1..f524d00464ed91 100644 --- a/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj +++ b/src/libraries/System.Formats.Nrbf/tests/System.Formats.Nrbf.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs index cb65c0e6d163e0..428f098625fd04 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs @@ -145,6 +145,78 @@ public void Verify_Checksum_SymbolicLink_LongLink(TarEntryFormat format) => public void Verify_Checksum_SymbolicLink_LongLink_LongPath(TarEntryFormat format) => Verify_Checksum_Internal(format, TarEntryType.SymbolicLink, longPath: true, longLink: true); + [Fact] + public void Verify_Size_RegularFile_Empty() + { + using MemoryStream archiveStream = new(); + string entryName = "entry.txt"; + using (TarWriter archive = new(archiveStream, TarEntryFormat.V7, leaveOpen: true)) + { + V7TarEntry e = new(TarEntryType.V7RegularFile, entryName) + { + DataStream = new MemoryStream(0) + }; + archive.WriteEntry(e); + } + + int sizeLocation = 100 + // Name + 8 + // Mode + 8 + // Uid + 8; // Gid + int sizeLength = 12; + + archiveStream.Position = 0; + byte[] actual = archiveStream.GetBuffer()[sizeLocation..(sizeLocation + sizeLength)]; + + byte[] expected = [0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0]; + AssertExtensions.SequenceEqual(expected, actual); + + archiveStream.Position = 0; + using TarReader reader = new(archiveStream); + + TarEntry? actualEntry = reader.GetNextEntry(); + Assert.NotNull(actualEntry); + Assert.Equal(0, actualEntry.Length); + Assert.Null(actualEntry.DataStream); // No stream created when size field's value is 0 + } + + [Fact] + public void Verify_Compatibility_RegularFile_EmptyFile_NoSizeStored() + { + // Filling archiveStream contents without depending on the Tar implementation. + // The contents of the archiveStream are equivalent to creating the archive using TarWriter with this code: + + // // using MemoryStream archiveStream = new(); + // // string entryName = "entry.txt"; + // // using (TarWriter archive = new(archiveStream, TarEntryFormat.V7, leaveOpen: true)) + // // { + // // V7TarEntry e = new(TarEntryType.V7RegularFile, entryName) + // // { + // // DataStream = new MemoryStream(0) + // // }; + // // archive.WriteEntry(e); + // // } + using MemoryStream archiveStream = new(Convert.FromBase64String("ZW50cnkudHh0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA2NDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADE0NzMwMzQ0MjQwADA1MTM2AAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); + + int sizeLocation = 100 + // Name + 8 + // Mode + 8 + // Uid + 8; // Gid + + // Fill the size field with 12 zeros as we used to before the bug fix + byte[] replacement = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + archiveStream.Seek(sizeLocation, SeekOrigin.Begin); + archiveStream.Write(replacement); + + archiveStream.Position = 0; + using TarReader reader = new(archiveStream); + + TarEntry? actualEntry = reader.GetNextEntry(); // Should succeed to read the entry with a malformed size field value + Assert.NotNull(actualEntry); + Assert.Equal(0, actualEntry.Length); // Should succeed to detect the size field's value as zero + Assert.Null(actualEntry.DataStream); // No stream created when size field's value is 0 + } + private void Verify_Checksum_Internal(TarEntryFormat format, TarEntryType entryType, bool longPath, bool longLink) { using MemoryStream archive = new MemoryStream(); @@ -351,20 +423,5 @@ private int GetChecksumForFormatSpecificFields(TarEntry entry, TarEntryFormat fo // Gnu BlockDevice: 623 + 1004 + 686 + 1142 = 3455 return checksum; } - - [Fact] - void Verify_Size_RegularFile_Empty() - { - using MemoryStream emptyData = new(0); - using MemoryStream output = new(); - using TarWriter archive = new(output, TarEntryFormat.Pax); - PaxTarEntry te = new(TarEntryType.RegularFile, "zero_size") - { DataStream = emptyData }; - archive.WriteEntry(te); - var sizeBuffer = output.GetBuffer()[1148..(1148 + 12)]; - // we expect ocal zeros - byte[] expected = [0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0]; - Assert.True(sizeBuffer.SequenceEqual(expected)); - } } } diff --git a/src/libraries/System.IO.Hashing/tests/System.IO.Hashing.Tests.csproj b/src/libraries/System.IO.Hashing/tests/System.IO.Hashing.Tests.csproj index 961ac1ef63c3ab..d4ed8b81f7ea42 100644 --- a/src/libraries/System.IO.Hashing/tests/System.IO.Hashing.Tests.csproj +++ b/src/libraries/System.IO.Hashing/tests/System.IO.Hashing.Tests.csproj @@ -1,8 +1,10 @@ + true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) + @@ -20,10 +22,9 @@ CommonTest\System\IO\PositionValueStream.cs + - - - + diff --git a/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj b/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj index d41bfd533ed850..cfc579ab228bdf 100644 --- a/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj +++ b/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/System.IO.Ports/tests/System.IO.Ports.Tests.csproj b/src/libraries/System.IO.Ports/tests/System.IO.Ports.Tests.csproj index a84a74343b0ae4..fe3aac50f3a9f3 100644 --- a/src/libraries/System.IO.Ports/tests/System.IO.Ports.Tests.csproj +++ b/src/libraries/System.IO.Ports/tests/System.IO.Ports.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-freebsd;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-freebsd;$(NetFrameworkCurrent) diff --git a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Shuffle.cs b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Shuffle.cs index e2d5d89a59eb98..5eb9867d27685b 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Shuffle.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Shuffle.cs @@ -18,7 +18,7 @@ public static partial class AsyncEnumerable /// The type of the elements of . /// A sequence of values to shuffle. /// A sequence whose elements correspond to those of the input sequence in randomized order. - /// Randomization is performed using a non-cryptographically-secure random number generator. + /// Randomization is performed using a non-cryptographically secure random number generator. public static IAsyncEnumerable Shuffle( this IAsyncEnumerable source) { diff --git a/src/libraries/System.Linq.AsyncEnumerable/tests/System.Linq.AsyncEnumerable.Tests.csproj b/src/libraries/System.Linq.AsyncEnumerable/tests/System.Linq.AsyncEnumerable.Tests.csproj index 4b045a52e3dab3..d5acc5d6b5c450 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/tests/System.Linq.AsyncEnumerable.Tests.csproj +++ b/src/libraries/System.Linq.AsyncEnumerable/tests/System.Linq.AsyncEnumerable.Tests.csproj @@ -1,7 +1,7 @@  - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) $(NoWarn);CS1998 diff --git a/src/libraries/System.Memory.Data/tests/System.Memory.Data.Tests.csproj b/src/libraries/System.Memory.Data/tests/System.Memory.Data.Tests.csproj index 1236c354f983f4..d13a3eba33cc00 100644 --- a/src/libraries/System.Memory.Data/tests/System.Memory.Data.Tests.csproj +++ b/src/libraries/System.Memory.Data/tests/System.Memory.Data.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index 5fef7122c9ea67..9f42d49b21621c 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -518,6 +518,7 @@ public static void Sort(this System.Span keys, Sy private object _dummy; private int _dummyPrimitive; public readonly System.Range Current { get { throw null; } } + public readonly System.ReadOnlySpan Source { get { throw null; } } public System.MemoryExtensions.SpanSplitEnumerator GetEnumerator() { throw null; } public bool MoveNext() { throw null; } } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.netstandard.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.netstandard.cs index 7b58aa41a40860..b69e47a3a25a70 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.netstandard.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.netstandard.cs @@ -18,7 +18,7 @@ private static Task PatchAsync(this HttpClient client, stri private static Task PatchAsync(this HttpClient client, Uri? requestUri, HttpContent content, CancellationToken cancellationToken) { - // HttpClient.PatchAsync is not available in .NET standard and NET462 + // HttpClient.PatchAsync is not available in .NET Standard 2.0 and .NET Framework HttpRequestMessage request = new HttpRequestMessage(HttpPatch, requestUri) { Content = content }; return client.SendAsync(request, cancellationToken); } diff --git a/src/libraries/System.Net.Http.Json/tests/UnitTests/System.Net.Http.Json.Unit.Tests.csproj b/src/libraries/System.Net.Http.Json/tests/UnitTests/System.Net.Http.Json.Unit.Tests.csproj index ddfaa0f52cecbf..98bb17b5e47b9d 100644 --- a/src/libraries/System.Net.Http.Json/tests/UnitTests/System.Net.Http.Json.Unit.Tests.csproj +++ b/src/libraries/System.Net.Http.Json/tests/UnitTests/System.Net.Http.Json.Unit.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj b/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj index 9e4f19ec066f65..3a60326bfb5614 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj @@ -64,8 +64,6 @@ System.Net.Http.WinHttpHandler Link="Common\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs" /> - - + + + + + diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 1363b6aa04a7f2..8409513d55a3b3 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -391,8 +391,6 @@ Link="Common\System\Net\HttpKnownHeaderNames.cs" /> - - EnableStreamingResponse = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); private static readonly HttpRequestOptionsKey> FetchOptions = new HttpRequestOptionsKey>("WebAssemblyFetchOptions"); + [FeatureSwitchDefinition("System.Net.Http.WasmEnableStreamingResponse")] + internal static bool FeatureEnableStreamingResponse { get; } = AppContextConfigHelper.GetBooleanConfig("System.Net.Http.WasmEnableStreamingResponse", "DOTNET_WASM_ENABLE_STREAMING_RESPONSE", defaultValue: true); + internal readonly JSObject _jsController; private readonly CancellationTokenRegistration _abortRegistration; private readonly string[] _optionNames; @@ -143,7 +147,7 @@ internal sealed class BrowserHttpController : IDisposable private readonly string uri; private readonly CancellationToken _cancellationToken; private readonly HttpRequestMessage _request; - private bool _isDisposed; + internal bool _isDisposed; public BrowserHttpController(HttpRequestMessage request, bool? allowAutoRedirect, CancellationToken cancellationToken) { @@ -314,10 +318,14 @@ private HttpResponseMessage ConvertResponse() responseMessage.SetReasonPhraseWithoutValidation(responseType); } - bool streamingResponseEnabled = false; - if (BrowserHttpInterop.SupportsStreamingResponse()) + bool streamingResponseEnabled = FeatureEnableStreamingResponse; + if (_request.Options.TryGetValue(EnableStreamingResponse, out var reqStreamingResponseEnabled)) + { + streamingResponseEnabled = reqStreamingResponseEnabled; + } + if (streamingResponseEnabled && !BrowserHttpInterop.SupportsStreamingResponse()) { - _request.Options.TryGetValue(EnableStreamingResponse, out streamingResponseEnabled); + throw new PlatformNotSupportedException("Streaming response is not supported in this browser."); } responseMessage.Content = streamingResponseEnabled @@ -361,10 +369,10 @@ public void Dispose() internal sealed class BrowserHttpWriteStream : Stream { private readonly BrowserHttpController _controller; // we don't own it, we don't dispose it from here + public BrowserHttpWriteStream(BrowserHttpController controller) { ArgumentNullException.ThrowIfNull(controller); - _controller = controller; } @@ -392,7 +400,7 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati public override bool CanRead => false; public override bool CanSeek => false; - public override bool CanWrite => true; + public override bool CanWrite => !_controller._isDisposed; protected override void Dispose(bool disposing) { @@ -506,7 +514,7 @@ protected override void Dispose(bool disposing) internal sealed class BrowserHttpReadStream : Stream { - private BrowserHttpController _controller; // we own the object and have to dispose it + private readonly BrowserHttpController _controller; // we own the object and have to dispose it public BrowserHttpReadStream(BrowserHttpController controller) { @@ -540,7 +548,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel return ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); } - public override bool CanRead => true; + public override bool CanRead => !_controller._isDisposed; public override bool CanSeek => false; public override bool CanWrite => false; @@ -582,4 +590,24 @@ public override void Write(byte[] buffer, int offset, int count) } #endregion } + + internal static class AppContextConfigHelper + { + internal static bool GetBooleanConfig(string switchName, string envVariable, bool defaultValue = false) + { + string? str = Environment.GetEnvironmentVariable(envVariable); + if (str != null) + { + if (str == "1" || str.Equals("true", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (str == "0" || str.Equals("false", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + } + return AppContext.TryGetSwitch(switchName, out bool value) ? value : defaultValue; + } + } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpInterop.cs index 92f3024df33161..517a23060c0164 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpInterop.cs @@ -11,11 +11,26 @@ namespace System.Net.Http { internal static partial class BrowserHttpInterop { + private static bool? _SupportsStreamingRequest; + private static bool? _SupportsStreamingResponse; + + public static bool SupportsStreamingRequest() + { + _SupportsStreamingRequest ??= SupportsStreamingRequestImpl(); + return _SupportsStreamingRequest.Value; + } + + public static bool SupportsStreamingResponse() + { + _SupportsStreamingResponse ??= SupportsStreamingResponseImpl(); + return _SupportsStreamingResponse.Value; + } + [JSImport("INTERNAL.http_wasm_supports_streaming_request")] - public static partial bool SupportsStreamingRequest(); + public static partial bool SupportsStreamingRequestImpl(); [JSImport("INTERNAL.http_wasm_supports_streaming_response")] - public static partial bool SupportsStreamingResponse(); + public static partial bool SupportsStreamingResponseImpl(); [JSImport("INTERNAL.http_wasm_create_controller")] public static partial JSObject CreateController(); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs index 606c64aaaf5f44..f38b3df12bb5f4 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs @@ -97,7 +97,7 @@ private async ValueTask SendAsyncCore(HttpRequestMessage re // Since we are reusing the request message instance on redirects, clear any existing headers // Do so before writing DiagnosticListener events as instrumentations use those to inject headers - if (request.WasRedirected() && _propagatorFields is HeaderDescriptor[] fields) + if (request.WasPropagatorStateInjectedByDiagnosticsHandler() && _propagatorFields is HeaderDescriptor[] fields) { foreach (HeaderDescriptor field in fields) { @@ -355,6 +355,7 @@ key is not null && request.Headers.TryAddWithoutValidation(descriptor, value); } }); + request.MarkPropagatorStateInjectedByDiagnosticsHandler(); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpRequestMessage.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpRequestMessage.cs index 691db4059a2481..dffd8a3ed2cebb 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpRequestMessage.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpRequestMessage.cs @@ -17,7 +17,7 @@ public class HttpRequestMessage : IDisposable private const int MessageNotYetSent = 0; private const int MessageAlreadySent = 1; - private const int MessageIsRedirect = 2; + private const int PropagatorStateInjectedByDiagnosticsHandler = 2; private const int MessageDisposed = 4; // Track whether the message has been sent. @@ -172,9 +172,9 @@ public override string ToString() internal bool WasSentByHttpClient() => (_sendStatus & MessageAlreadySent) != 0; - internal void MarkAsRedirected() => _sendStatus |= MessageIsRedirect; + internal void MarkPropagatorStateInjectedByDiagnosticsHandler() => _sendStatus |= PropagatorStateInjectedByDiagnosticsHandler; - internal bool WasRedirected() => (_sendStatus & MessageIsRedirect) != 0; + internal bool WasPropagatorStateInjectedByDiagnosticsHandler() => (_sendStatus & PropagatorStateInjectedByDiagnosticsHandler) != 0; private bool Disposed { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs index fee5a120f8e2e4..c6e98a0527080a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs @@ -28,7 +28,6 @@ internal sealed partial class HttpConnectionPool : IDisposable public const int DefaultHttpPort = 80; public const int DefaultHttpsPort = 443; - private static readonly bool s_isWindows7Or2008R2 = GetIsWindows7Or2008R2(); private static readonly List s_http3ApplicationProtocols = new List() { SslApplicationProtocol.Http3 }; private static readonly List s_http2ApplicationProtocols = new List() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; private static readonly List s_http2OnlyApplicationProtocols = new List() { SslApplicationProtocol.Http2 }; @@ -277,20 +276,6 @@ private static SslClientAuthenticationOptions ConstructSslOptions(HttpConnection // Set TargetHost for SNI sslOptions.TargetHost = sslHostName; - // Windows 7 and Windows 2008 R2 support TLS 1.1 and 1.2, but for legacy reasons by default those protocols - // are not enabled when a developer elects to use the system default. However, in .NET Core 2.0 and earlier, - // HttpClientHandler would enable them, due to being a wrapper for WinHTTP, which enabled them. Both for - // compatibility and because we prefer those higher protocols whenever possible, SocketsHttpHandler also - // pretends they're part of the default when running on Win7/2008R2. - if (s_isWindows7Or2008R2 && sslOptions.EnabledSslProtocols == SslProtocols.None) - { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(poolManager, $"Win7OrWin2K8R2 platform, Changing default TLS protocols to {SecurityProtocol.DefaultSecurityProtocols}"); - } - sslOptions.EnabledSslProtocols = SecurityProtocol.DefaultSecurityProtocols; - } - return sslOptions; } @@ -1026,19 +1011,6 @@ public bool CleanCacheAndDisposeIfUnused() return false; } - /// Gets whether we're running on Windows 7 or Windows 2008 R2. - private static bool GetIsWindows7Or2008R2() - { - OperatingSystem os = Environment.OSVersion; - if (os.Platform == PlatformID.Win32NT) - { - // Both Windows 7 and Windows 2008 R2 report version 6.1. - Version v = os.Version; - return v.Major == 6 && v.Minor == 1; - } - return false; - } - // For diagnostic purposes public override string ToString() => $"{nameof(HttpConnectionPool)} " + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs index a1256da552f63f..76c2641bc50f9a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs @@ -79,8 +79,6 @@ internal override async ValueTask SendAsync(HttpRequestMess } } - request.MarkAsRedirected(); - // Issue the redirected request. response = await _redirectInnerHandler.SendAsync(request, async, cancellationToken).ConfigureAwait(false); } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs index 29a03a52d1ab30..5b8dbf0d6e4779 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs @@ -1506,8 +1506,82 @@ await GetFactoryForVersion(useVersion).CreateClientAndServerAsync( Assert.Equal(activitySourceCreatesActivity.HasValue, madeASamplingDecision); Assert.Equal(diagnosticListenerActivityEnabled.HasValue, listenerCallbackWasCalled); - }, UseVersion.ToString(), TestAsync.ToString(), parameters).DisposeAsync(); - } + }, UseVersion.ToString(), TestAsync.ToString(), parameters).DisposeAsync(); + } + + private sealed class SendMultipleTimesHandler : DelegatingHandler + { + private readonly Activity[] _parentActivities; + + public SendMultipleTimesHandler(HttpMessageHandler innerHandler, params Activity[] parentActivities) : base(innerHandler) + { + Assert.NotEmpty(parentActivities); + _parentActivities = parentActivities; + } + + protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) + => SendAsync(request, testAsync: false, cancellationToken).Result; + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + => await SendAsync(request, testAsync: true, cancellationToken); + + private async ValueTask SendAsync(HttpRequestMessage request, bool testAsync, CancellationToken cancellationToken) + { + HttpResponseMessage response = null; + foreach (Activity parent in _parentActivities) + { + parent.Start(); + Assert.Equal(ActivityIdFormat.W3C, parent.IdFormat); + response = testAsync ? await base.SendAsync(request, cancellationToken) : base.Send(request, cancellationToken); + parent.Stop(); + if (parent != _parentActivities.Last()) + { + response.Dispose(); // only keep the last response + } + } + return response; + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task SendAsync_ReuseRequestInHandler_ResetsHeadersForEachReuse() + { + Activity parent0 = new Activity("parent0"); + Activity parent1 = new Activity("parent1") { TraceStateString = "wow=1" }; + Activity parent2 = new Activity("parent2") { TraceStateString = "wow=2" }; + + const string FirstTraceParent = "00-F"; + const string FirstTraceState = "first"; + + await GetFactoryForVersion(UseVersion).CreateServerAsync(async (server, uri) => + { + SendMultipleTimesHandler handler = new SendMultipleTimesHandler(CreateSocketsHttpHandler(allowAllCertificates: true), parent0, parent1, parent2); + using HttpClient client = new HttpClient(handler); + HttpRequestMessage request = CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true); + + request.Headers.Add("traceparent", FirstTraceParent); + request.Headers.Add("tracestate", FirstTraceState); + + Task clientTask = TestAsync ? client.SendAsync(request) : Task.Run(() => client.Send(request)); + + HttpRequestData requestData = await server.AcceptConnectionSendResponseAndCloseAsync(statusCode: HttpStatusCode.InternalServerError); + + // On the first send DiagnosticsHandler should keep user-supplied headers. + string traceparent = GetHeaderValue(requestData, "traceparent"); + string tracestate = GetHeaderValue(requestData, "tracestate"); + Assert.Equal(FirstTraceParent, traceparent); + Assert.Equal(FirstTraceState, tracestate); + + requestData = await server.AcceptConnectionSendResponseAndCloseAsync(statusCode: HttpStatusCode.InternalServerError); + + // Headers should be overridden on each subsequent send. + AssertHeadersAreInjected(requestData, parent1); + requestData = await server.AcceptConnectionSendResponseAndCloseAsync(statusCode: HttpStatusCode.OK); + AssertHeadersAreInjected(requestData, parent2); + + await clientTask; + }); + } private static T GetProperty(object obj, string propertyName) { diff --git a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj index 4483fe2bf0e479..c71216b138fa4b 100755 --- a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj @@ -35,8 +35,6 @@ Link="ProductionCode\Common\System\Net\Logging\NetEventSource.Common.cs" /> - - diff --git a/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj b/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj index 888f2e47541314..03708443b2ea80 100644 --- a/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj +++ b/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj @@ -120,8 +120,6 @@ Link="Common\System\Net\Logging\NetEventSource.Common.cs" /> - - host, ReadOnlySpan domain) + { + if (!host.EndsWith(domain, StringComparison.Ordinal)) + { + return false; + } + + // The last character of the 'host' that is not included in the domain + int idxOfSeparator = host.Length - domain.Length - 1; + if (idxOfSeparator < 0) + { + // 'host' and 'domain' are equal + Debug.Assert(idxOfSeparator == -1); + return true; + } + + return host[idxOfSeparator] is '.' // The last character of 'host' that is not included in 'domain' is a "." + && domain.Contains('.') // In case of single-label domains, there should be an exact match. + && !IPAddress.IsValid(host); // If host is an IP address, there should be an exact match. } // According to spec we must assume default values for attributes but still @@ -319,31 +354,24 @@ private static bool IsDomainEqualToHost(string domain, string host) // We also check the validity of all attributes based on the version and variant (read RFC) // // To work properly this function must be called after cookie construction with - // default (response) URI AND setDefault == true - // - // Afterwards, the function can be called many times with other URIs and - // setDefault == false to check whether this cookie matches given uri - internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDomain, string localDomain, bool setDefault, bool shouldThrow) + // default (response) URI. + internal void VerifyAndSetDefaults(CookieVariant variant, Uri uri) { string host = uri.Host; int port = uri.Port; string path = uri.AbsolutePath; - bool valid = true; - if (setDefault) + // Set Variant. If version is zero => reset cookie to Version0 style + if (Version == 0) { - // Set Variant. If version is zero => reset cookie to Version0 style - if (Version == 0) - { - variant = CookieVariant.Plain; - } - else if (Version == 1 && variant == CookieVariant.Unknown) - { - // Since we don't expose Variant to an app, set it to Default - variant = CookieVariant.Default; - } - m_cookieVariant = variant; + variant = CookieVariant.Plain; + } + else if (Version == 1 && variant == CookieVariant.Unknown) + { + // Since we don't expose Variant to an app, set it to Default + variant = CookieVariant.Default; } + m_cookieVariant = variant; // Check the name if (string.IsNullOrEmpty(m_name) || @@ -352,149 +380,49 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma m_name.EndsWith(' ') || m_name.AsSpan().ContainsAny(s_reservedToNameChars)) { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, "Name", m_name ?? "")); - } - return false; + throw new CookieException(SR.Format(SR.net_cookie_attribute, "Name", m_name ?? "")); } // Check the value if (m_value == null || (!(m_value.Length > 2 && m_value.StartsWith('\"') && m_value.EndsWith('\"')) && m_value.AsSpan().ContainsAny(';', ','))) { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, "Value", m_value ?? "")); - } - return false; + throw new CookieException(SR.Format(SR.net_cookie_attribute, "Value", m_value ?? "")); } // Check Comment syntax if (Comment != null && !(Comment.Length > 2 && Comment.StartsWith('\"') && Comment.EndsWith('\"')) && (Comment.AsSpan().ContainsAny(';', ','))) { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.CommentAttributeName, Comment)); - } - return false; + throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.CommentAttributeName, Comment)); } // Check Path syntax if (Path != null && !(Path.Length > 2 && Path.StartsWith('\"') && Path.EndsWith('\"')) && (Path.AsSpan().ContainsAny(';', ','))) { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PathAttributeName, Path)); - } - return false; + throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PathAttributeName, Path)); } // Check/set domain // // If domain is implicit => assume a) uri is valid, b) just set domain to uri hostname. - if (setDefault && m_domain_implicit) + if (m_domain_implicit) { - m_domain = host; + SetDomainAndKey(host); } else { - if (!m_domain_implicit) - { - // Forwarding note: If Uri.Host is of IP address form then the only supported case - // is for IMPLICIT domain property of a cookie. - // The code below (explicit cookie.Domain value) will try to parse Uri.Host IP string - // as a fqdn and reject the cookie. - - // Aliasing since we might need the KeyValue (but not the original one). - string domain = m_domain; - - // Syntax check for Domain charset plus empty string. - if (!DomainCharsTest(domain)) - { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.DomainAttributeName, domain ?? "")); - } - return false; - } + Debug.Assert(m_domainKey is not null); - // Domain must start with '.' if set explicitly. - if (domain[0] != '.') - { - domain = '.' + domain; - } - - int host_dot = host.IndexOf('.'); - - // First quick check is for pushing a cookie into the local domain. - if (isLocalDomain && string.Equals(localDomain, domain, StringComparison.OrdinalIgnoreCase)) - { - valid = true; - } - else if (domain.IndexOf('.', 1, domain.Length - 2) == -1) - { - // A single label domain is valid only if the domain is exactly the same as the host specified in the URI. - if (!IsDomainEqualToHost(domain, host)) - { - valid = false; - } - } - else if (variant == CookieVariant.Plain) - { - // We distinguish between Version0 cookie and other versions on domain issue. - // According to Version0 spec a domain must be just a substring of the hostname. - - if (!IsDomainEqualToHost(domain, host)) - { - if (host.Length <= domain.Length || - (string.Compare(host, host.Length - domain.Length, domain, 0, domain.Length, StringComparison.OrdinalIgnoreCase) != 0)) - { - valid = false; - } - } - } - else if (host_dot == -1 || - domain.Length != host.Length - host_dot || - (string.Compare(host, host_dot, domain, 0, domain.Length, StringComparison.OrdinalIgnoreCase) != 0)) - { - // Starting from the first dot, the host must match the domain. - // - // For null hosts, the host must match the domain exactly. - if (!IsDomainEqualToHost(domain, host)) - { - valid = false; - } - } - - if (valid) - { - m_domainKey = domain.ToLowerInvariant(); - } - } - else + if (!IsValidDomainName(m_domainKey) || !HostMatchesDomain(host, m_domainKey)) { - // For implicitly set domain AND at the set_default == false time - // we simply need to match uri.Host against m_domain. - if (!string.Equals(host, m_domain, StringComparison.OrdinalIgnoreCase)) - { - valid = false; - } - } - if (!valid) - { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.DomainAttributeName, m_domain)); - } - return false; + throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.DomainAttributeName, m_domain)); } } // Check/Set Path - if (setDefault && m_path_implicit) + if (m_path_implicit) { // This code assumes that the URI path is always valid and contains at least one '/'. switch (m_cookieVariant) @@ -532,7 +460,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma } // Set the default port if Port attribute was present but had no value. - if (setDefault && (m_port_implicit == false && m_port.Length == 0)) + if (m_port_implicit == false && m_port.Length == 0) { m_port_list = new int[1] { port }; } @@ -540,7 +468,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma if (m_port_implicit == false) { // Port must match against the one from the uri. - valid = false; + bool valid = false; foreach (int p in m_port_list!) { if (p == port) @@ -551,21 +479,16 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma } if (!valid) { - if (shouldThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, m_port)); - } - return false; + throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, m_port)); } } - return true; } // Very primitive test to make sure that the name does not have illegal characters // as per RFC 952 (relaxed on first char could be a digit and string can have '_'). - private static bool DomainCharsTest(string name) => - !string.IsNullOrEmpty(name) && - !name.AsSpan().ContainsAnyExcept(s_domainChars); + private static bool IsValidDomainName(ReadOnlySpan name) => + !name.IsEmpty && + !name.ContainsAnyExcept(s_domainChars); [AllowNull] public string Port @@ -676,7 +599,7 @@ internal string DomainKey { get { - return m_domain_implicit ? Domain : m_domainKey; + return m_domain_implicit ? Domain : m_domainKey!; } } @@ -713,7 +636,7 @@ public override int GetHashCode() StringComparer.OrdinalIgnoreCase.GetHashCode(Name), StringComparer.Ordinal.GetHashCode(Value), StringComparer.Ordinal.GetHashCode(Path), - StringComparer.OrdinalIgnoreCase.GetHashCode(Domain), + StringComparer.OrdinalIgnoreCase.GetHashCode(DomainKey), Version); } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs b/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs index cd1d96b571c7d2..c61076fe894908 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs @@ -4,7 +4,6 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Net.NetworkInformation; using System.Text; // Relevant cookie specs: @@ -28,30 +27,7 @@ // // Cookies without an explicit Domain attribute will only match a potential uri that matches the original // uri from where the cookie came from. -// -// For explicit Domain attribute in the cookie, the following rules apply: -// -// Version=0 (Netscape, RFC6265) allows the Domain attribute of the cookie to match any tail substring -// of the host uri. -// -// Version=1 related cookie specs only allows the Domain attribute to match the host uri based on a -// more restricted set of rules. -// -// According to RFC2109/RFC2965, the cookie will be rejected for matching if: -// * The value for the Domain attribute contains no embedded dots or does not start with a dot. -// * The value for the request-host does not domain-match the Domain attribute. -// " The request-host is a FQDN (not IP address) and has the form HD, where D is the value of the Domain -// attribute, and H is a string that contains one or more dots. -// -// Examples: -// * A cookie from request-host y.x.foo.com for Domain=.foo.com would be rejected, because H is y.x -// and contains a dot. -// -// * A cookie from request-host x.foo.com for Domain=.foo.com would be accepted. -// -// * A cookie with Domain=.com or Domain=.com., will always be rejected, because there is no embedded dot. -// -// * A cookie with Domain=ajax.com will be rejected because the value for Domain does not begin with a dot. +// For explicit Domain attribute in the cookie, see the rules defined in Cookie.HostMatchesDomain(). namespace System.Net { @@ -94,7 +70,6 @@ public class CookieContainer public const int DefaultPerDomainCookieLimit = 20; public const int DefaultCookieLengthLimit = 4096; - private static readonly string s_fqdnMyDomain = CreateFqdnMyDomain(); private static readonly HeaderVariantInfo[] s_headerInfo = { new HeaderVariantInfo(HttpKnownHeaderNames.SetCookie, CookieVariant.Rfc2109), new HeaderVariantInfo(HttpKnownHeaderNames.SetCookie2, CookieVariant.Rfc2965) @@ -105,7 +80,9 @@ public class CookieContainer private int m_maxCookies = DefaultCookieLimit; // Do not rename (binary serialization) private int m_maxCookiesPerDomain = DefaultPerDomainCookieLimit; // Do not rename (binary serialization) private int m_count; // Do not rename (binary serialization) - private readonly string m_fqdnMyDomain = s_fqdnMyDomain; // Do not rename (binary serialization) +#pragma warning disable CA1823 // Avoid unused private fields + private readonly string m_fqdnMyDomain = string.Empty; +#pragma warning restore CA1823 // Avoid unused private fields public CookieContainer() { @@ -128,14 +105,6 @@ public CookieContainer(int capacity, int perDomainCapacity, int maxCookieSize) : m_maxCookieSize = maxCookieSize; } - private static string CreateFqdnMyDomain() - { - string domain = HostInformation.DomainName; - return domain != null && domain.Length > 1 ? - '.' + domain : - string.Empty; - } - // NOTE: after shrinking the capacity, Count can become greater than Capacity. public int Capacity { @@ -252,24 +221,20 @@ public void Add(Cookie cookie) // We don't know cookie verification status, so re-create the cookie and verify it. Cookie new_cookie = cookie.Clone(); - new_cookie.VerifySetDefaults(new_cookie.Variant, uri, IsLocalDomain(uri.Host), m_fqdnMyDomain, true, true); + new_cookie.VerifyAndSetDefaults(new_cookie.Variant, uri); - Add(new_cookie, true); + InternalAdd(new_cookie); } // This method is called *only* when cookie verification is done, so unlike with public // Add(Cookie cookie) the cookie is in a reasonable condition. - internal void Add(Cookie cookie, bool throwOnError) + internal void InternalAdd(Cookie cookie) { PathList? pathList; if (cookie.Value.Length > m_maxCookieSize) { - if (throwOnError) - { - throw new CookieException(SR.Format(SR.net_cookie_size, cookie, m_maxCookieSize)); - } - return; + throw new CookieException(SR.Format(SR.net_cookie_size, cookie, m_maxCookieSize)); } try @@ -340,10 +305,7 @@ internal void Add(Cookie cookie, bool throwOnError) } catch (Exception e) { - if (throwOnError) - { - throw new CookieException(SR.net_container_add_cookie, e); - } + throw new CookieException(SR.net_container_add_cookie, e); } } @@ -580,85 +542,15 @@ public void Add(CookieCollection cookies) } } - // This will try (if needed) get the full domain name of the host given the Uri. - // NEVER call this function from internal methods with 'fqdnRemote' == null. - // Since this method counts security issue for DNS and hence will slow - // the performance. - internal bool IsLocalDomain(string host) - { - int dot = host.IndexOf('.'); - if (dot == -1) - { - // No choice but to treat it as a host on the local domain. - // This also covers 'localhost' and 'loopback'. - return true; - } - - // Quick test for typical cases: loopback addresses for IPv4 and IPv6. - if ((host == "127.0.0.1") || (host == "::1") || (host == "0:0:0:0:0:0:0:1")) - { - return true; - } - - // Test domain membership. - if (string.Compare(m_fqdnMyDomain, 0, host, dot, m_fqdnMyDomain.Length, StringComparison.OrdinalIgnoreCase) == 0) - { - return true; - } - - // Test for "127.###.###.###" without using regex. - ReadOnlySpan hostSpan = host; - Span ipParts = stackalloc Range[5]; - ipParts = ipParts.Slice(0, hostSpan.Split(ipParts, '.')); - if (ipParts.Length == 4 && hostSpan[ipParts[0]] is "127") - { - int i; - for (i = 1; i < ipParts.Length; i++) - { - ReadOnlySpan part = hostSpan[ipParts[i]]; - switch (part.Length) - { - case 3: - if (!char.IsAsciiDigit(part[2])) - { - break; - } - goto case 2; - - case 2: - if (!char.IsAsciiDigit(part[1])) - { - break; - } - goto case 1; - - case 1: - if (!char.IsAsciiDigit(part[0])) - { - break; - } - continue; - } - break; - } - if (i == 4) - { - return true; - } - } - - return false; - } - public void Add(Uri uri, Cookie cookie) { ArgumentNullException.ThrowIfNull(uri); ArgumentNullException.ThrowIfNull(cookie); Cookie new_cookie = cookie.Clone(); - new_cookie.VerifySetDefaults(new_cookie.Variant, uri, IsLocalDomain(uri.Host), m_fqdnMyDomain, true, true); + new_cookie.VerifyAndSetDefaults(new_cookie.Variant, uri); - Add(new_cookie, true); + InternalAdd(new_cookie); } public void Add(Uri uri, CookieCollection cookies) @@ -666,18 +558,17 @@ public void Add(Uri uri, CookieCollection cookies) ArgumentNullException.ThrowIfNull(uri); ArgumentNullException.ThrowIfNull(cookies); - bool isLocalDomain = IsLocalDomain(uri.Host); foreach (Cookie c in cookies) { Cookie new_cookie = c.Clone(); - new_cookie.VerifySetDefaults(new_cookie.Variant, uri, isLocalDomain, m_fqdnMyDomain, true, true); - Add(new_cookie, true); + new_cookie.VerifyAndSetDefaults(new_cookie.Variant, uri); + InternalAdd(new_cookie); } } - internal CookieCollection CookieCutter(Uri uri, string? headerName, string setCookieHeader, bool isThrow) + internal CookieCollection CookieCutter(Uri uri, string? headerName, string setCookieHeader) { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"uri:{uri} headerName:{headerName} setCookieHeader:{setCookieHeader} isThrow:{isThrow}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"uri:{uri} headerName:{headerName} setCookieHeader:{setCookieHeader}"); CookieCollection cookies = new CookieCollection(); CookieVariant variant = CookieVariant.Unknown; @@ -696,7 +587,6 @@ internal CookieCollection CookieCutter(Uri uri, string? headerName, string setCo } } - bool isLocalDomain = IsLocalDomain(uri.Host); try { CookieParser parser = new CookieParser(setCookieHeader); @@ -717,20 +607,12 @@ internal CookieCollection CookieCutter(Uri uri, string? headerName, string setCo // Parser marks invalid cookies this way if (string.IsNullOrEmpty(cookie.Name)) { - if (isThrow) - { - throw new CookieException(SR.net_cookie_format); - } - // Otherwise, ignore (reject) cookie - continue; + throw new CookieException(SR.net_cookie_format); } // This will set the default values from the response URI // AND will check for cookie validity - if (!cookie.VerifySetDefaults(variant, uri, isLocalDomain, m_fqdnMyDomain, true, isThrow)) - { - continue; - } + cookie.VerifyAndSetDefaults(variant, uri); // If many same cookies arrive we collapse them into just one, hence setting // parameter isStrict = true below cookies.InternalAdd(cookie, true); @@ -742,16 +624,13 @@ internal CookieCollection CookieCutter(Uri uri, string? headerName, string setCo } catch (Exception e) { - if (isThrow) - { - throw new CookieException(SR.Format(SR.net_cookie_parse_header, uri.AbsoluteUri), e); - } + throw new CookieException(SR.Format(SR.net_cookie_parse_header, uri.AbsoluteUri), e); } int cookiesCount = cookies.Count; for (int i = 0; i < cookiesCount; i++) { - Add((Cookie)cookies[i], isThrow); + InternalAdd((Cookie)cookies[i]); } return cookies; @@ -801,74 +680,33 @@ public CookieCollection GetAllCookies() int port = uri.Port; CookieCollection? cookies = null; - var domainAttributeMatchAnyCookieVariant = new System.Collections.Generic.List(); - System.Collections.Generic.List? domainAttributeMatchOnlyCookieVariantPlain = null; - - string fqdnRemote = uri.Host; - - // Add initial candidates to match Domain attribute of possible cookies. - // For these Domains, cookie can have any CookieVariant enum value. - domainAttributeMatchAnyCookieVariant.Add(fqdnRemote); - domainAttributeMatchAnyCookieVariant.Add("." + fqdnRemote); - - int dot = fqdnRemote.IndexOf('.'); - if (dot == -1) + List matchingDomainKeys = [uri.Host]; + ReadOnlySpan host = uri.Host; + int lastDot = host.LastIndexOf('.'); + while (lastDot > 0) { - // DNS.resolve may return short names even for other inet domains ;-( - // We _don't_ know what the exact domain is, so try also grab short hostname cookies. - // Grab long name from the local domain - if (!string.IsNullOrEmpty(m_fqdnMyDomain)) + int dot = host[..lastDot].LastIndexOf('.'); + if (dot > 0) { - domainAttributeMatchAnyCookieVariant.Add(fqdnRemote + m_fqdnMyDomain); - // Grab the local domain itself - domainAttributeMatchAnyCookieVariant.Add(m_fqdnMyDomain); + string match = host[(dot + 1)..].ToString(); + matchingDomainKeys.Add(match); } - } - else - { - // Grab the host domain - domainAttributeMatchAnyCookieVariant.Add(fqdnRemote.Substring(dot)); - - // The following block is only for compatibility with Version0 spec. - // Still, we'll add only Plain-Variant cookies if found under below keys - if (fqdnRemote.Length > 2) - { - // We ignore the '.' at the end on the name - int last = fqdnRemote.LastIndexOf('.', fqdnRemote.Length - 2); - // AND keys with <2 dots inside. - if (last > 0) - { - last = fqdnRemote.LastIndexOf('.', last - 1); - } - if (last != -1) - { - while ((dot < last) && (dot = fqdnRemote.IndexOf('.', dot + 1)) != -1) - { - // These candidates can only match CookieVariant.Plain cookies. - domainAttributeMatchOnlyCookieVariantPlain ??= new System.Collections.Generic.List(); - domainAttributeMatchOnlyCookieVariantPlain.Add(fqdnRemote.Substring(dot)); - } - } - } - } - BuildCookieCollectionFromDomainMatches(uri, isSecure, port, ref cookies, domainAttributeMatchAnyCookieVariant, false); - if (domainAttributeMatchOnlyCookieVariantPlain != null) - { - BuildCookieCollectionFromDomainMatches(uri, isSecure, port, ref cookies, domainAttributeMatchOnlyCookieVariantPlain, true); + lastDot = dot; } + BuildCookieCollectionFromDomainMatches(uri, isSecure, port, ref cookies, matchingDomainKeys); return cookies; } - private void BuildCookieCollectionFromDomainMatches(Uri uri, bool isSecure, int port, ref CookieCollection? cookies, System.Collections.Generic.List domainAttribute, bool matchOnlyPlainCookie) + private void BuildCookieCollectionFromDomainMatches(Uri uri, bool isSecure, int port, ref CookieCollection? cookies, List matchingDomainKeys) { - for (int i = 0; i < domainAttribute.Count; i++) + for (int i = 0; i < matchingDomainKeys.Count; i++) { PathList pathList; lock (m_domainTable.SyncRoot) { - pathList = (PathList)m_domainTable[domainAttribute[i]]!; + pathList = (PathList)m_domainTable[matchingDomainKeys[i]]!; if (pathList == null) { continue; @@ -886,7 +724,7 @@ private void BuildCookieCollectionFromDomainMatches(Uri uri, bool isSecure, int { CookieCollection cc = (CookieCollection)list.GetByIndex(e)!; cc.TimeStamp(CookieCollection.Stamp.Set); - MergeUpdateCollections(ref cookies, cc, port, isSecure, matchOnlyPlainCookie); + MergeUpdateCollections(ref cookies, uri.Host, cc, port, isSecure); } } } @@ -896,7 +734,7 @@ private void BuildCookieCollectionFromDomainMatches(Uri uri, bool isSecure, int { lock (m_domainTable.SyncRoot) { - m_domainTable.Remove(domainAttribute[i]); + m_domainTable.Remove(matchingDomainKeys[i]); } } } @@ -922,7 +760,7 @@ private static bool PathMatch(string requestPath, string cookiePath) requestPath[cookiePath.Length] == '/'; } - private void MergeUpdateCollections(ref CookieCollection? destination, CookieCollection source, int port, bool isSecure, bool isPlainOnly) + private void MergeUpdateCollections(ref CookieCollection? destination, string host, CookieCollection source, int port, bool isSecure) { lock (source) { @@ -942,13 +780,7 @@ private void MergeUpdateCollections(ref CookieCollection? destination, CookieCol } else { - // Add only if port does match to this request URI - // or was not present in the original response. - if (isPlainOnly && cookie.Variant != CookieVariant.Plain) - { - ; // Don't add - } - else if (cookie.PortList != null) + if (cookie.PortList != null) { foreach (int p in cookie.PortList) { @@ -971,6 +803,12 @@ private void MergeUpdateCollections(ref CookieCollection? destination, CookieCol to_add = false; } + // For implicit domains exact match is needed + if (cookie.DomainImplicit && !string.Equals(host, cookie.Domain, StringComparison.OrdinalIgnoreCase)) + { + to_add = false; + } + if (to_add) { // In 'source' are already ordered. @@ -1025,7 +863,7 @@ public void SetCookies(Uri uri, string cookieHeader) ArgumentNullException.ThrowIfNull(uri); ArgumentNullException.ThrowIfNull(cookieHeader); - CookieCutter(uri, null, cookieHeader, true); // Will throw on error + CookieCutter(uri, null, cookieHeader); // Will throw on error } } diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs index 11fa3ba37026ee..6a31011d3ca77a 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs @@ -294,6 +294,8 @@ public static void Equals_Compare_Success() Cookie c14 = new Cookie("name", "value", "path", "domain") { Version = 5 }; Cookie c15 = new Cookie("name", "value", "path", "domain") { Version = 100 }; + Cookie c9dot = new Cookie("name", "value", "path", ".domain"); + Assert.False(c2.Equals(null)); Assert.False(c2.Equals("")); @@ -329,6 +331,9 @@ public static void Equals_Compare_Success() Assert.NotEqual(c13, c15); Assert.Equal(c13.GetHashCode(), c14.GetHashCode()); Assert.NotEqual(c13.GetHashCode(), c15.GetHashCode()); + + Assert.Equal(c9, c9dot); + Assert.Equal(c9.GetHashCode(), c9dot.GetHashCode()); } [Fact] diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest/CookieContainerTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest/CookieContainerTest.cs index 9f5333c1c3d73e..bd3bb3fcacf123 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest/CookieContainerTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest/CookieContainerTest.cs @@ -93,39 +93,6 @@ public void GetCookies_AddCookieVersion0WithExplicitDomain_CookieReturnedForDoma Assert.Equal(1, cookies.Count); } - [Fact] - public void GetCookies_AddCookieVersion1WithExplicitDomain_CookieReturnedForDomainAndOneLevelSubDomain() - { - const string SchemePrefix = "http://"; - const string OriginalDomain = "contoso.com"; - const string OriginalDomainWithLeadingDot = "." + OriginalDomain; - - var container = new CookieContainer(); - var cookie1 = new Cookie(CookieName1, CookieValue1) { Domain = OriginalDomainWithLeadingDot, Version = 1 }; - container.Add(new Uri(SchemePrefix + OriginalDomain), cookie1); - - var uri = new Uri(SchemePrefix + OriginalDomain); - var cookies = container.GetCookies(uri); - Assert.Equal(1, cookies.Count); - Assert.Equal(OriginalDomainWithLeadingDot, cookies[CookieName1].Domain); - - uri = new Uri(SchemePrefix + "www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(1, cookies.Count); - - uri = new Uri(SchemePrefix + "x.www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(0, cookies.Count); - - uri = new Uri(SchemePrefix + "y.x.www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(0, cookies.Count); - - uri = new Uri(SchemePrefix + "z.y.x.www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(0, cookies.Count); - } - [Fact] public void GetAllCookies_Empty_ReturnsEmptyCollection() { diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs index 06ee2c214ee858..050024fd0a0592 100644 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs +++ b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs @@ -467,39 +467,6 @@ public void GetCookies_AddCookieVersion0WithExplicitDomain_CookieReturnedForDoma Assert.Equal(1, cookies.Count); } - [Fact] - public void GetCookies_AddCookieVersion1WithExplicitDomain_CookieReturnedForDomainAndOneLevelSubDomain() - { - const string SchemePrefix = "http://"; - const string OriginalDomain = "contoso.com"; - const string OriginalDomainWithLeadingDot = "." + OriginalDomain; - - var container = new CookieContainer(); - var cookie1 = new Cookie(CookieName1, CookieValue1) { Domain = OriginalDomainWithLeadingDot, Version = 1 }; - container.Add(new Uri(SchemePrefix + OriginalDomain), cookie1); - - var uri = new Uri(SchemePrefix + OriginalDomain); - CookieCollection cookies = container.GetCookies(uri); - Assert.Equal(1, cookies.Count); - Assert.Equal(OriginalDomainWithLeadingDot, cookies[CookieName1].Domain); - - uri = new Uri(SchemePrefix + "www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(1, cookies.Count); - - uri = new Uri(SchemePrefix + "x.www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(0, cookies.Count); - - uri = new Uri(SchemePrefix + "y.x.www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(0, cookies.Count); - - uri = new Uri(SchemePrefix + "z.y.x.www." + OriginalDomain); - cookies = container.GetCookies(uri); - Assert.Equal(0, cookies.Count); - } - [Fact] public void Ctor_Capacity_Success() { @@ -590,13 +557,20 @@ public void Add_SameCookieDifferentVairants_OverridesOlderVariant() { Uri uri = new Uri("http://domain.com"); + Cookie c0 = new Cookie("name1", "value", "", "domain.com"); Cookie c1 = new Cookie("name1", "value", "", ".domain.com"); // Variant = Plain Cookie c2 = new Cookie("name1", "value", "", ".domain.com") { Port = "\"80\"" }; // Variant = RFC2965 (should override) Cookie c3 = new Cookie("name1", "value", "", ".domain.com") { Port = "\"80, 90\"" }; // Variant = RFC2965 (should override) Cookie c4 = new Cookie("name1", "value", "", ".domain.com") { Version = 1 }; // Variant = RFC2109 (should be rejected) CookieContainer cc = new CookieContainer(); + + cc.Add(c0); + Assert.Equal("domain.com", cc.GetCookies(uri)[0].Domain); + cc.Add(c1); + Assert.Equal(1, cc.Count); + Assert.Equal(".domain.com", cc.GetCookies(uri)[0].Domain); // Adding a newer variant should override an older one cc.Add(c2); @@ -614,6 +588,24 @@ public void Add_SameCookieDifferentVairants_OverridesOlderVariant() Assert.Equal(1, cc.Count); } + [Fact] + public static void Add_SetCookies_SameCookieDifferentVairants_OverridesOlderVariant() + { + Uri uri = new Uri("http://domain.com"); + CookieContainer cc = new(); + Cookie a = new() + { + Domain = "domain.com", + Name = "lol", + Value = "0" + }; + cc.Add(uri, a); + cc.SetCookies(uri, "lol=42"); + + Assert.Equal(1, cc.Count); + Assert.Equal("42", cc.GetCookies(uri).Single().Value); + } + [Fact] public void Add_Cookie_Invalid() { @@ -781,10 +773,10 @@ private void VerifyGetCookies(CookieContainer cc1, Uri uri, Cookie[] expected) for (int i = 0; i < expected.Length; i++) { - Cookie c1 = expected[i]; Cookie c2 = cc2[i]; - Assert.Equal(c1.Name, c2.Name); // Primitive check for equality - Assert.Equal(c1.Value, c2.Value); + Cookie c1 = expected.Single(c => c.Name == c2.Name); + + Assert.Equal(c1.Value, c2.Value); // Primitive check for equality } } @@ -983,5 +975,100 @@ public void GetCookies_PathMatchingFollowsRfc6265(bool useDefaultPath, string[] CookieCollection collection = container.GetCookies(requestUri); Assert.Equal(expectedMatches, collection.Count); } + + [Fact] + public void Add_ImplicitDomainOfIPv6Hostname_Success() + { + CookieContainer container = new CookieContainer(); + Cookie cookie = new Cookie("lol", "haha"); + Uri uri = new Uri("https://[::FFFF:192.168.0.1]/test"); + container.Add(uri, cookie); + Assert.Equal(uri.Host, container.GetCookies(uri).Single().Domain); + } + + public static TheoryData DomainMatching_WhenMatches_Success_Data = new TheoryData() + { + { "https://q", "q" }, + { "https://localhost/", "localhost" }, + { "https://test.com", "test.com" }, + { "https://test.COM", "tEsT.com" }, + { "https://test.com", ".test.com" }, + { "https://yay.test.com", "yay.test.com" }, + { "https://yay.test.com", ".yay.test.com" }, + { "https://yay.test.com", ".test.com" }, + { "https://42.aaaa.bbb.cc.d.test.com", "d.test.com" }, + { "https://yay.test.com/foo/bar", "test.com" }, + { "https://127.0.1.1", "127.0.1.1" }, + { "https://42.42.100.100", "42.42.100.100" }, + }; + + [Theory] + [MemberData(nameof(DomainMatching_WhenMatches_Success_Data))] + public void DomainMatching_WhenMatches_Success(string uriString, string domain) + { + CookieContainer container = new CookieContainer(); + Cookie cookie = new Cookie("lol", "haha") + { + Domain = domain + }; + + Uri uri = new Uri(uriString); + container.Add(uri, cookie); + Assert.Equal(1, container.Count); + + CookieCollection collection = container.GetCookies(uri); + Assert.Equal(1, collection.Count); + } + + [Fact] + public void DomainMatching_ExplicitDomain_MatchesMultiple() + { + CookieContainer container = new CookieContainer(); + Cookie a = new Cookie("a", "aa", null, "a.com"); + Cookie b = new Cookie("b", "bb", null, "b.a.com"); + Cookie c = new Cookie("c", "cc", null, "c.b.a.com"); + + container.Add(new Uri("http://a.com"), a); + container.Add(new Uri("http://b.a.com"), b); + container.Add(new Uri("http://c.b.a.com"), c); + + CookieCollection matches = container.GetCookies(new Uri("http://c.b.a.com")); + Assert.Equal(3, matches.Count); + } + + public static TheoryData DomainMatching_WhenDoesNotMatch_ThrowsCookieException_Data = new TheoryData() + { + { "https://test.com", "test.co" }, // Domain is not a suffix + { "https://test.com", "x.test.com" }, // Domain is not a suffix (extra chars at start) + { "https://test.com", "ttest.com" }, // Suffix but not separated by dot + { "https://test.com", "test.com." }, // Trailing dot + { "https://test.com", "..test.com" }, // 2 leading dots + { "https://foo.test.com", "yay.test.com" }, // subdomain mismatch + { "https://42.42.100.100", "41.42.100.100" }, // different IP + + // Single label domain without a full match. + { "https://test.com", ".com" }, + { "https://test.com", "com" }, + + // If Host is an IP address, it should be equal to the domain. + // See https://issues.chromium.org/issues/40126142 and the last condition in + // https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3 + { "https://1.2.3.4", ".2.3.4" } + }; + + + [Theory] + [MemberData(nameof(DomainMatching_WhenDoesNotMatch_ThrowsCookieException_Data))] + public void DomainMatching_WhenDoesNotMatch_ThrowsCookieException(string uriString, string domain) + { + CookieContainer container = new CookieContainer(); + Cookie cookie = new Cookie("lol", "haha") + { + Domain = domain + }; + + Uri uri = new Uri(uriString); + Assert.Throws(() => container.Add(uri, cookie)); + } } } diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/HostInformation.cs b/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/HostInformation.cs deleted file mode 100644 index 277b450b24158d..00000000000000 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/HostInformation.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.NetworkInformation -{ - internal static class HostInformation - { - public static string DomainName - { - get - { - return "contoso.com"; - } - } - } -} diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/System.Net.Primitives.UnitTests.Tests.csproj b/src/libraries/System.Net.Primitives/tests/UnitTests/System.Net.Primitives.UnitTests.Tests.csproj index 1d9db5b2762863..133bf304cde91a 100644 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/System.Net.Primitives.UnitTests.Tests.csproj +++ b/src/libraries/System.Net.Primitives/tests/UnitTests/System.Net.Primitives.UnitTests.Tests.csproj @@ -1,4 +1,4 @@ - + true $(NoWarn);169;649 @@ -28,6 +28,10 @@ Link="ProductionCode\System\Net\Sockets\SocketError.cs" /> + + - - - - diff --git a/src/libraries/System.Net.Security/ref/System.Net.Security.cs b/src/libraries/System.Net.Security/ref/System.Net.Security.cs index 986a492e479212..ca8aa52a2dbf62 100644 --- a/src/libraries/System.Net.Security/ref/System.Net.Security.cs +++ b/src/libraries/System.Net.Security/ref/System.Net.Security.cs @@ -251,22 +251,22 @@ public partial class SslStream : System.Net.Security.AuthenticatedStream public override bool CanTimeout { get { throw null; } } public override bool CanWrite { get { throw null; } } public virtual bool CheckCertRevocationStatus { get { throw null; } } - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual System.Security.Authentication.CipherAlgorithmType CipherAlgorithm { get { throw null; } } - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual int CipherStrength { get { throw null; } } - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual System.Security.Authentication.HashAlgorithmType HashAlgorithm { get { throw null; } } - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual int HashStrength { get { throw null; } } public override bool IsAuthenticated { get { throw null; } } public override bool IsEncrypted { get { throw null; } } public override bool IsMutuallyAuthenticated { get { throw null; } } public override bool IsServer { get { throw null; } } public override bool IsSigned { get { throw null; } } - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual System.Security.Authentication.ExchangeAlgorithmType KeyExchangeAlgorithm { get { throw null; } } - [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead.", DiagnosticId = "SYSLIB0058", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual int KeyExchangeStrength { get { throw null; } } public override long Length { get { throw null; } } public virtual System.Security.Cryptography.X509Certificates.X509Certificate? LocalCertificate { get { throw null; } } diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index ecf71f7c0f5c97..50a09e13eba7b1 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -98,8 +98,6 @@ - diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslClientAuthenticationOptions.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslClientAuthenticationOptions.cs index 8ecde73420971e..5e7ccf90c0e714 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslClientAuthenticationOptions.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslClientAuthenticationOptions.cs @@ -12,7 +12,7 @@ public class SslClientAuthenticationOptions { private EncryptionPolicy _encryptionPolicy = EncryptionPolicy.RequireEncryption; private X509RevocationMode _checkCertificateRevocation = X509RevocationMode.NoCheck; - private SslProtocols _enabledSslProtocols = SecurityProtocol.SystemDefaultSecurityProtocols; + private SslProtocols _enabledSslProtocols = SslProtocols.None; private bool _allowRenegotiation = true; private bool _allowTlsResume = true; diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslServerAuthenticationOptions.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslServerAuthenticationOptions.cs index cc580f588db99f..cc082eaa04f7e6 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslServerAuthenticationOptions.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslServerAuthenticationOptions.cs @@ -10,7 +10,7 @@ namespace System.Net.Security public class SslServerAuthenticationOptions { private X509RevocationMode _checkCertificateRevocation = X509RevocationMode.NoCheck; - private SslProtocols _enabledSslProtocols = SecurityProtocol.SystemDefaultSecurityProtocols; + private SslProtocols _enabledSslProtocols = SslProtocols.None; private EncryptionPolicy _encryptionPolicy = EncryptionPolicy.RequireEncryption; private bool _allowRenegotiation; private bool _allowTlsResume = true; diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs index 96dae15afd7488..bcf2a5bf88d61f 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs @@ -228,14 +228,14 @@ public SslStream(Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificat // public virtual IAsyncResult BeginAuthenticateAsClient(string targetHost, AsyncCallback? asyncCallback, object? asyncState) { - return BeginAuthenticateAsClient(targetHost, null, SecurityProtocol.SystemDefaultSecurityProtocols, false, + return BeginAuthenticateAsClient(targetHost, null, SslProtocols.None, false, asyncCallback, asyncState); } public virtual IAsyncResult BeginAuthenticateAsClient(string targetHost, X509CertificateCollection? clientCertificates, bool checkCertificateRevocation, AsyncCallback? asyncCallback, object? asyncState) { - return BeginAuthenticateAsClient(targetHost, clientCertificates, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation, asyncCallback, asyncState); + return BeginAuthenticateAsClient(targetHost, clientCertificates, SslProtocols.None, checkCertificateRevocation, asyncCallback, asyncState); } public virtual IAsyncResult BeginAuthenticateAsClient(string targetHost, X509CertificateCollection? clientCertificates, @@ -265,7 +265,7 @@ internal IAsyncResult BeginAuthenticateAsClient(SslClientAuthenticationOptions s public virtual IAsyncResult BeginAuthenticateAsServer(X509Certificate serverCertificate, AsyncCallback? asyncCallback, object? asyncState) { - return BeginAuthenticateAsServer(serverCertificate, false, SecurityProtocol.SystemDefaultSecurityProtocols, false, + return BeginAuthenticateAsServer(serverCertificate, false, SslProtocols.None, false, asyncCallback, asyncState); } @@ -273,7 +273,7 @@ public virtual IAsyncResult BeginAuthenticateAsServer(X509Certificate serverCert public virtual IAsyncResult BeginAuthenticateAsServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, AsyncCallback? asyncCallback, object? asyncState) { - return BeginAuthenticateAsServer(serverCertificate, clientCertificateRequired, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation, asyncCallback, asyncState); + return BeginAuthenticateAsServer(serverCertificate, clientCertificateRequired, SslProtocols.None, checkCertificateRevocation, asyncCallback, asyncState); } public virtual IAsyncResult BeginAuthenticateAsServer(X509Certificate serverCertificate, bool clientCertificateRequired, @@ -307,12 +307,12 @@ private IAsyncResult BeginAuthenticateAsServer(SslServerAuthenticationOptions ss #region Synchronous methods public virtual void AuthenticateAsClient(string targetHost) { - AuthenticateAsClient(targetHost, null, SecurityProtocol.SystemDefaultSecurityProtocols, false); + AuthenticateAsClient(targetHost, null, SslProtocols.None, false); } public virtual void AuthenticateAsClient(string targetHost, X509CertificateCollection? clientCertificates, bool checkCertificateRevocation) { - AuthenticateAsClient(targetHost, clientCertificates, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation); + AuthenticateAsClient(targetHost, clientCertificates, SslProtocols.None, checkCertificateRevocation); } public virtual void AuthenticateAsClient(string targetHost, X509CertificateCollection? clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) @@ -341,12 +341,12 @@ public void AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthent public virtual void AuthenticateAsServer(X509Certificate serverCertificate) { - AuthenticateAsServer(serverCertificate, false, SecurityProtocol.SystemDefaultSecurityProtocols, false); + AuthenticateAsServer(serverCertificate, false, SslProtocols.None, false); } public virtual void AuthenticateAsServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation) { - AuthenticateAsServer(serverCertificate, clientCertificateRequired, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation); + AuthenticateAsServer(serverCertificate, clientCertificateRequired, SslProtocols.None, checkCertificateRevocation); } public virtual void AuthenticateAsServer(X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) @@ -375,7 +375,7 @@ public void AuthenticateAsServer(SslServerAuthenticationOptions sslServerAuthent #region Task-based async public methods public virtual Task AuthenticateAsClientAsync(string targetHost) => AuthenticateAsClientAsync(targetHost, null, false); - public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection? clientCertificates, bool checkCertificateRevocation) => AuthenticateAsClientAsync(targetHost, clientCertificates, SecurityProtocol.SystemDefaultSecurityProtocols, checkCertificateRevocation); + public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection? clientCertificates, bool checkCertificateRevocation) => AuthenticateAsClientAsync(targetHost, clientCertificates, SslProtocols.None, checkCertificateRevocation); public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection? clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) { @@ -401,7 +401,7 @@ public Task AuthenticateAsClientAsync(SslClientAuthenticationOptions sslClientAu } public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate) => - AuthenticateAsServerAsync(serverCertificate, false, SecurityProtocol.SystemDefaultSecurityProtocols, false); + AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.None, false); public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs index 02458d637796cd..4c9c1c8aea9952 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs @@ -353,10 +353,11 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(Ss secureCredential.dwSessionLifespan = -1; } + Interop.Crypt32.CERT_CONTEXT* certificateHandle; if (certificate != null) { secureCredential.cCreds = 1; - Interop.Crypt32.CERT_CONTEXT* certificateHandle = (Interop.Crypt32.CERT_CONTEXT*)certificate.Handle; + certificateHandle = (Interop.Crypt32.CERT_CONTEXT*)certificate.Handle; secureCredential.paCred = &certificateHandle; } @@ -434,19 +435,21 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials( credential.dwSessionLifespan = -1; } + Interop.Crypt32.CERT_CONTEXT* certificateHandle; if (certificate != null) { credential.cCreds = 1; - Interop.Crypt32.CERT_CONTEXT* certificateHandle = (Interop.Crypt32.CERT_CONTEXT*)certificate.Handle; + certificateHandle = (Interop.Crypt32.CERT_CONTEXT*)certificate.Handle; credential.paCred = &certificateHandle; } if (NetEventSource.Log.IsEnabled()) NetEventSource.Info($"flags=({flags}), ProtocolFlags=({protocolFlags}), EncryptionPolicy={policy}"); + Interop.SspiCli.TLS_PARAMETERS tlsParameters; if (protocolFlags != 0) { // If we were asked to do specific protocol we need to fill TLS_PARAMETERS. - Interop.SspiCli.TLS_PARAMETERS tlsParameters = default; + tlsParameters = default; tlsParameters.grbitDisabledProtocols = (uint)protocolFlags ^ uint.MaxValue; credential.cTlsParameters = 1; diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamDisposeTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamDisposeTest.cs index de7aa502933b02..0eacfb274cb62f 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamDisposeTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamDisposeTest.cs @@ -102,5 +102,57 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout( await Assert.ThrowsAnyAsync(() => client.ReadAsync(readBuffer, cts.Token).AsTask()); } } + + [Fact] + [OuterLoop("Computationally expensive")] + public async Task Dispose_ParallelWithHandshake_ThrowsODE() + { + using CancellationTokenSource cts = new CancellationTokenSource(); + cts.CancelAfter(TestConfiguration.PassingTestTimeout); + + await Parallel.ForEachAsync(System.Linq.Enumerable.Range(0, 10000), cts.Token, async (i, token) => + { + (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + using (client) + using (server) + using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate()) + using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate()) + { + SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() + { + TargetHost = Guid.NewGuid().ToString("N"), + RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true, + }; + + SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions() + { + ServerCertificate = serverCertificate, + }; + + var clientTask = Task.Run(() => client.AuthenticateAsClientAsync(clientOptions, cts.Token)); + var serverTask = Task.Run(() => server.AuthenticateAsServerAsync(serverOptions, cts.Token)); + + // Dispose the instances while the handshake is in progress. + client.Dispose(); + server.Dispose(); + + await ValidateExceptionAsync(clientTask); + await ValidateExceptionAsync(serverTask); + } + }); + + static async Task ValidateExceptionAsync(Task task) + { + try + { + await task; + } + // either we disposed the stream, or the other side does and we get unexpected EOF + catch (Exception ex) when (ex is ObjectDisposedException or IOException) + { + return; + } + } + } } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs index 07c92297fda148..38da62537c6401 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs @@ -604,93 +604,6 @@ private static CipherSuitesPolicy BuildPolicy(params TlsCipherSuite[] cipherSuit return new CipherSuitesPolicy(cipherSuites); } - private static async Task WaitForSecureConnection(SslStream client, SslClientAuthenticationOptions clientOptions, SslStream server, SslServerAuthenticationOptions serverOptions) - { - Task serverTask = null; - Task clientTask = null; - - // check if failed synchronously - try - { - serverTask = server.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); - clientTask = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); - } - catch (Exception e) - { - client.Close(); - server.Close(); - - if (!(e is AuthenticationException || e is Win32Exception)) - { - throw; - } - - if (serverTask != null) - { - // i.e. for server we used DEFAULT options but for client we chose not supported cipher suite - // this will cause client to fail synchronously while server awaits connection - try - { - // since we broke connection the server should finish - await serverTask; - } - catch (AuthenticationException) { } - catch (Win32Exception) { } - catch (IOException) { } - } - - return e; - } - - // Since we got here it means client and server have at least 1 choice - // of cipher suite - // Now we expect both sides to fail or both to succeed - - Exception failure = null; - Task task = null; - - try - { - task = await Task.WhenAny(serverTask, clientTask).WaitAsync(TestConfiguration.PassingTestTimeout); - await task; - } - catch (Exception e) when (e is AuthenticationException || e is Win32Exception) - { - failure = e; - // avoid client waiting for server's response - if (task == serverTask) - { - server.Close(); - } - else - { - client.Close(); - } - } - - try - { - // Now wait for the other task to finish. - task = (task == serverTask ? clientTask : serverTask); - await task.WaitAsync(TestConfiguration.PassingTestTimeout); - - // Fail if server has failed but client has succeeded - Assert.Null(failure); - } - catch (Exception e) when (e is AuthenticationException || e is Win32Exception || e is IOException) - { - // Fail if server has succeeded but client has failed - Assert.NotNull(failure); - - if (e.GetType() != typeof(IOException)) - { - failure = new AggregateException(new Exception[] { failure, e }); - } - } - - return failure; - } - private static NegotiatedParams ConnectAndGetNegotiatedParams(ConnectionParams serverParams, ConnectionParams clientParams) { (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); @@ -714,7 +627,7 @@ private static NegotiatedParams ConnectAndGetNegotiatedParams(ConnectionParams s clientOptions.TargetHost = "test"; clientOptions.RemoteCertificateValidationCallback = delegate { return true; }; - Exception failure = WaitForSecureConnection(client, clientOptions, server, serverOptions).WaitAsync(TestConfiguration.PassingTestTimeoutMilliseconds).GetAwaiter().GetResult(); + Exception failure = TestHelper.WaitForSecureConnection(client, clientOptions, server, serverOptions).WaitAsync(TestConfiguration.PassingTestTimeoutMilliseconds).GetAwaiter().GetResult(); if (failure == null) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamOpenSslNamedKeysTests.manual.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamOpenSslNamedKeysTests.manual.cs new file mode 100644 index 00000000000000..4f844044c92222 --- /dev/null +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamOpenSslNamedKeysTests.manual.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using Test.Cryptography; +using Xunit; + +namespace System.Net.Security.Tests +{ + // See System.Security.Cryptography/tests/osslplugins/README.md for instructions on how to setup for TPM tests. + public class SslStreamOpenSslNamedKeys + { + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderEcDsaTests))] + public static async Task Provider_TPM2SslStream_ServerCertIsTpmEcDsa() + { + using X509Certificate2 serverCert = CreateSelfSignedEcDsaCertificate(); + CreateDefaultTlsOptions(serverCert, out SslServerAuthenticationOptions serverOptions, out SslClientAuthenticationOptions clientOptions); + await TestTls(serverOptions, clientOptions); + } + + [ConditionalTheory(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderRsaTests))] + [MemberData(nameof(OpenSslNamedKeysHelpers.RSASignaturePaddingValues), MemberType = typeof(OpenSslNamedKeysHelpers))] + public static async void Provider_TPM2SslStream_ServerCertIsTpmRsa(RSASignaturePadding padding) + { + using X509Certificate2 serverCert = CreateSelfSignedRsaCertificate(padding); + CreateTlsOptionsForRsa(serverCert, out SslServerAuthenticationOptions serverOptions, out SslClientAuthenticationOptions clientOptions); + await TestTls(serverOptions, clientOptions); + } + + private static async Task TestTls(SslServerAuthenticationOptions serverOptions, SslClientAuthenticationOptions clientOptions) + { + (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); + + using (clientStream) + using (serverStream) + { + using SslStream server = new SslStream(serverStream, leaveInnerStreamOpen: false); + using SslStream client = new SslStream(clientStream, leaveInnerStreamOpen: false); + + Exception failure = await TestHelper.WaitForSecureConnection(client, clientOptions, server, serverOptions).WaitAsync(TestConfiguration.PassingTestTimeoutMilliseconds); + if (failure is not null) + { + throw failure; + } + + byte[] testData = [1, 2, 3]; + byte[] receivedData = new byte[testData.Length]; + Span receivedDataSpan = receivedData; + + // server can write to the client + server.Write(testData); + client.ReadExactly(receivedData); + Assert.True(testData.SequenceEqual(receivedData)); + + // client can write to the server + receivedDataSpan.Fill(0); + client.Write(testData); + server.ReadExactly(receivedData); + Assert.True(testData.SequenceEqual(receivedData)); + } + } + + private static X509Certificate2 CreateSelfSignedEcDsaCertificate() + { + Assert.True(OpenSslNamedKeysHelpers.ShouldRunProviderEcDsaTests); + + // We will get rid of original handle and make sure X509Certificate2's duplicate is still working. + X509Certificate2 serverCert; + using (SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmEcDsaKeyHandleUri)) + using (ECDsa ecdsaPri = new ECDsaOpenSsl(priKeyHandle)) + { + serverCert = CreateSelfSignedCertificate(ecdsaPri); + } + + return serverCert; + } + + private static X509Certificate2 CreateSelfSignedRsaCertificate(RSASignaturePadding padding) + { + Assert.True(OpenSslNamedKeysHelpers.ShouldRunProviderRsaTests); + + // We will get rid of original handle and make sure X509Certificate2's duplicate is still working. + X509Certificate2 serverCert; + using (SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmRsaKeyHandleUri)) + using (RSA rsaPri = new RSAOpenSsl(priKeyHandle)) + { + serverCert = CreateSelfSignedCertificate(rsaPri, padding); + } + + return serverCert; + } + + private static X509Certificate2 CreateSelfSignedCertificate(ECDsa ecdsa) + { + var certReq = new CertificateRequest("CN=testservereku.contoso.com", ecdsa, HashAlgorithmName.SHA256); + return FinishCertCreation(certReq); + } + + private static X509Certificate2 CreateSelfSignedCertificate(RSA rsa, RSASignaturePadding padding) + { + var certReq = new CertificateRequest("CN=testservereku.contoso.com", rsa, HashAlgorithmName.SHA256, padding); + return FinishCertCreation(certReq); + } + + private static X509Certificate2 FinishCertCreation(CertificateRequest certificateRequest) + { + certificateRequest.CertificateExtensions.Add(X509BasicConstraintsExtension.CreateForEndEntity()); + certificateRequest.CertificateExtensions.Add( + new X509KeyUsageExtension( + // We need to allow KeyEncipherment for RSA ciphersuite which doesn't use PSS. + // PSS is causing issues with some TPMs (ignoring salt length) + X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, + critical: false) + ); + + certificateRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); + + return certificateRequest.CreateSelfSigned(DateTimeOffset.UtcNow.AddMonths(-1), DateTimeOffset.UtcNow.AddMonths(1)); + } + + private static RemoteCertificateValidationCallback CreateRemoteCertificateValidationCallback(byte[] expectedCert) + { + return (object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) => + { + X509Certificate2? cert = certificate as X509Certificate2; + return cert != null && cert.RawData.SequenceEqual(expectedCert); + }; + } + + private static void CreateTlsOptionsForRsa(X509Certificate2 serverCert, out SslServerAuthenticationOptions serverOptions, out SslClientAuthenticationOptions clientOptions) + { + CreateDefaultTlsOptions(serverCert, out serverOptions, out clientOptions); + serverOptions.CipherSuitesPolicy = new CipherSuitesPolicy(new[] + { + // Some TPMs don't support PSS fully (i.e. may ignore salt length) + // which will cause 'bad signature' when used inside of TLS. + // This ciphersuite still allows PKCS1 padding for signing. + TlsCipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, + }); + } + + private static void CreateDefaultTlsOptions(X509Certificate2 serverCert, out SslServerAuthenticationOptions serverOptions, out SslClientAuthenticationOptions clientOptions) + { + serverOptions = new SslServerAuthenticationOptions() + { + ServerCertificate = serverCert, + }; + + clientOptions = new SslClientAuthenticationOptions() + { + TargetHost = "test", + RemoteCertificateValidationCallback = CreateRemoteCertificateValidationCallback(serverCert.RawData), + }; + } + } +} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index 6fca6cd05e3135..79610468fe7995 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -94,6 +94,8 @@ Link="CommonTest\System\Security\Cryptography\X509Certificates\CertificateAuthority.cs" /> + + diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs index abc41691e6cf0e..2be52387d7792f 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.ComponentModel; using System.IO; using System.Linq; using System.Net.Sockets; @@ -190,5 +191,92 @@ static string ProtocolToString(SslProtocols? protocol) return name; } + + internal static async Task WaitForSecureConnection(SslStream client, SslClientAuthenticationOptions clientOptions, SslStream server, SslServerAuthenticationOptions serverOptions) + { + Task serverTask = null; + Task clientTask = null; + + // check if failed synchronously + try + { + serverTask = server.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); + clientTask = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); + } + catch (Exception e) + { + client.Close(); + server.Close(); + + if (!(e is AuthenticationException || e is Win32Exception)) + { + throw; + } + + if (serverTask != null) + { + // i.e. for server we used DEFAULT options but for client we chose not supported cipher suite + // this will cause client to fail synchronously while server awaits connection + try + { + // since we broke connection the server should finish + await serverTask; + } + catch (AuthenticationException) { } + catch (Win32Exception) { } + catch (IOException) { } + } + + return e; + } + + // Since we got here it means client and server have at least 1 choice + // of cipher suite + // Now we expect both sides to fail or both to succeed + + Exception failure = null; + Task task = null; + + try + { + task = await Task.WhenAny(serverTask, clientTask).WaitAsync(TestConfiguration.PassingTestTimeout); + await task; + } + catch (Exception e) when (e is AuthenticationException || e is Win32Exception) + { + failure = e; + // avoid client waiting for server's response + if (task == serverTask) + { + server.Close(); + } + else + { + client.Close(); + } + } + + try + { + // Now wait for the other task to finish. + task = (task == serverTask ? clientTask : serverTask); + await task.WaitAsync(TestConfiguration.PassingTestTimeout); + + // Fail if server has failed but client has succeeded + Assert.Null(failure); + } + catch (Exception e) when (e is AuthenticationException || e is Win32Exception || e is IOException) + { + // Fail if server has succeeded but client has failed + Assert.NotNull(failure); + + if (e.GetType() != typeof(IOException)) + { + failure = new AggregateException(new Exception[] { failure, e }); + } + } + + return failure; + } } } diff --git a/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs b/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs index 2120d49a924f30..fbb75382a44782 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs @@ -85,7 +85,7 @@ public void Package_Supported_NTLM() } [ConditionalFact(nameof(IsNtlmUnavailable))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/111639", typeof(PlatformDetection), nameof(PlatformDetection.IsUbuntu24))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/111639", typeof(PlatformDetection), nameof(PlatformDetection.IsUbuntu24OrHigher))] public void Package_Unsupported_NTLM() { NegotiateAuthenticationClientOptions clientOptions = new NegotiateAuthenticationClientOptions { Package = "NTLM", Credential = s_testCredentialRight, TargetName = "HTTP/foo" }; diff --git a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj index d35de6d843f3d6..580aa90dfb2087 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj @@ -168,8 +168,6 @@ Link="ProductionCode\System\Net\SslStreamContext.cs" /> - - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs index 9042911d34bb21..0993a0088b4041 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs @@ -14,17 +14,70 @@ public partial class SafeSocketHandle { private int _receiveTimeout = -1; private int _sendTimeout = -1; - private bool _nonBlocking; private SocketAsyncContext? _asyncContext; - internal bool LastConnectFailed { get; set; } - internal bool DualMode { get; set; } - internal bool ExposedHandleOrUntrackedConfiguration { get; private set; } - internal bool PreferInlineCompletions { get; set; } = SocketAsyncEngine.InlineSocketCompletionsEnabled; - internal bool IsSocket { get; set; } = true; // (ab)use Socket class for performing async I/O on non-socket fds. + [Flags] + private enum Flags : byte + { + NonBlocking = 1, + LastConnectFailed = 2, + DualMode = 4, + ExposedHandleOrUntrackedConfiguration = 8, + PreferInlineCompletions = 16, + IsSocket = 32, + IsDisconnected = 64, #if SYSTEM_NET_SOCKETS_APPLE_PLATFROM - internal bool TfoEnabled { get; set; } + TfoEnabled = 128 #endif + } + + private Flags _flags = Flags.IsSocket | (SocketAsyncEngine.InlineSocketCompletionsEnabled ? Flags.PreferInlineCompletions : 0); + + private void SetFlag(Flags flag, bool value) + { + if (value) _flags |= flag; + else _flags &= ~flag; + } + + internal bool LastConnectFailed + { + get => (_flags & Flags.LastConnectFailed) != 0; + set => SetFlag(Flags.LastConnectFailed, value); + } + + internal bool DualMode + { + get => (_flags & Flags.DualMode) != 0; + set => SetFlag(Flags.DualMode, value); + } + + internal bool ExposedHandleOrUntrackedConfiguration + { + get => (_flags & Flags.ExposedHandleOrUntrackedConfiguration) != 0; + private set => SetFlag(Flags.ExposedHandleOrUntrackedConfiguration, value); + } + + internal bool PreferInlineCompletions + { + get => (_flags & Flags.PreferInlineCompletions) != 0; + set => SetFlag(Flags.PreferInlineCompletions, value); + } + + // (ab)use Socket class for performing async I/O on non-socket fds. + internal bool IsSocket + { + get => (_flags & Flags.IsSocket) != 0; + set => SetFlag(Flags.IsSocket, value); + } + +#if SYSTEM_NET_SOCKETS_APPLE_PLATFROM + internal bool TfoEnabled + { + get => (_flags & Flags.TfoEnabled) != 0; + set => SetFlag(Flags.TfoEnabled, value); + } +#endif + internal void RegisterConnectResult(SocketError error) { switch (error) @@ -67,11 +120,11 @@ internal bool IsNonBlocking { get { - return _nonBlocking; + return (_flags & Flags.NonBlocking) != 0; } set { - _nonBlocking = value; + SetFlag(Flags.NonBlocking, value); // If transitioning from blocking to non-blocking, we need to set the native socket to non-blocking mode. // If transitioning from non-blocking to blocking, we keep the native socket in non-blocking mode, and emulate @@ -112,12 +165,9 @@ internal int SendTimeout } } - internal bool IsDisconnected { get; private set; } + internal bool IsDisconnected => (_flags & Flags.IsDisconnected) != 0; - internal void SetToDisconnected() - { - IsDisconnected = true; - } + internal void SetToDisconnected() => _flags |= Flags.IsDisconnected; /// Returns whether operations were canceled. private bool OnHandleClose() diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs index f34c8ee6db72a0..f7334b5f64ec4b 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs +++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs @@ -399,7 +399,7 @@ private async Task SendAsyncCore(ArraySegment buffer, WebSocketMessageType if (sendTask != null) // this is optimization for single-threaded build, see resolvedPromise() in web-socket.ts. Null means synchronously resolved. { - await CancellationHelper(sendTask, cancellationToken, previousState, pinBuffer).ConfigureAwait(false); + await CancellationHelper(sendTask, cancellationToken, previousState).ConfigureAwait(false); } } catch (JSException ex) @@ -442,7 +442,7 @@ private async Task ReceiveAsyncCore(ArraySegment b if (receiveTask != null) // this is optimization for single-threaded build, see resolvedPromise() in web-socket.ts. Null means synchronously resolved. { - await CancellationHelper(receiveTask, cancellationToken, previousState, pinBuffer).ConfigureAwait(false); + await CancellationHelper(receiveTask, cancellationToken, previousState).ConfigureAwait(false); } return ConvertResponse(); @@ -550,13 +550,12 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, string? stat } } - private async Task CancellationHelper(Task promise, CancellationToken cancellationToken, WebSocketState previousState, IDisposable? disposable = null) + private async Task CancellationHelper(Task promise, CancellationToken cancellationToken, WebSocketState previousState) { try { if (promise.IsCompletedSuccessfully) { - disposable?.Dispose(); return; } if (promise.IsCompleted) @@ -602,10 +601,6 @@ private async Task CancellationHelper(Task promise, CancellationToken cancellati throw new WebSocketException(WebSocketError.NativeError, ex); } } - finally - { - disposable?.Dispose(); - } } // needs to be called with locked _lockObject diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs index 850ad307f7c4fb..41a1c32987c353 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs @@ -55,21 +55,28 @@ namespace System.Buffers } namespace System.Numerics.Tensors { - [System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public partial interface IReadOnlyTensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable where TSelf : System.Numerics.Tensors.IReadOnlyTensor + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + public partial interface IReadOnlyTensor { - static abstract TSelf? Empty { get; } nint FlattenedLength { get; } bool IsEmpty { get; } bool IsPinned { get; } - T this[params scoped System.ReadOnlySpan indexes] { get; } - TSelf this[params scoped System.ReadOnlySpan ranges] { get; } - T this[params scoped System.ReadOnlySpan indexes] { get; } + object this[params scoped System.ReadOnlySpan indexes] { get; } + object this[params scoped System.ReadOnlySpan indexes] { get; } [System.Diagnostics.CodeAnalysis.UnscopedRefAttribute] System.ReadOnlySpan Lengths { get; } int Rank { get; } [System.Diagnostics.CodeAnalysis.UnscopedRefAttribute] System.ReadOnlySpan Strides { get; } + System.Buffers.MemoryHandle GetPinnedHandle(); + } + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + public partial interface IReadOnlyTensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor where TSelf : System.Numerics.Tensors.IReadOnlyTensor + { + static abstract TSelf? Empty { get; } + new T this[params scoped System.ReadOnlySpan indexes] { get; } + TSelf this[params scoped System.ReadOnlySpan ranges] { get; } + new T this[params scoped System.ReadOnlySpan indexes] { get; } System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(); System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan startIndex); System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan range); @@ -83,10 +90,18 @@ public partial interface IReadOnlyTensor : System.Collections.Generic. bool TryCopyTo(scoped System.Numerics.Tensors.TensorSpan destination); bool TryFlattenTo(scoped System.Span destination); } - [System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public partial interface ITensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor where TSelf : System.Numerics.Tensors.ITensor + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + public partial interface ITensor : System.Numerics.Tensors.IReadOnlyTensor { bool IsReadOnly { get; } + new object this[params scoped System.ReadOnlySpan indexes] { get; set; } + new object this[params scoped System.ReadOnlySpan indexes] { get; set; } + void Clear(); + void Fill(object value); + } + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + public partial interface ITensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.ITensor where TSelf : System.Numerics.Tensors.ITensor + { new T this[params scoped System.ReadOnlySpan indexes] { get; set; } new TSelf this[params scoped System.ReadOnlySpan ranges] { get; set; } new T this[params scoped System.ReadOnlySpan indexes] { get; set; } @@ -94,7 +109,6 @@ public partial interface ITensor : System.Collections.Generic.IEnumera System.Numerics.Tensors.TensorSpan AsTensorSpan(params scoped System.ReadOnlySpan startIndex); System.Numerics.Tensors.TensorSpan AsTensorSpan(params scoped System.ReadOnlySpan range); System.Numerics.Tensors.TensorSpan AsTensorSpan(params scoped System.ReadOnlySpan start); - void Clear(); static abstract TSelf Create(scoped System.ReadOnlySpan lengths, bool pinned = false); static abstract TSelf Create(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false); static abstract TSelf CreateUninitialized(scoped System.ReadOnlySpan lengths, bool pinned = false); @@ -816,8 +830,8 @@ public ref partial struct Enumerator public bool MoveNext() { throw null; } } } - [System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - public sealed partial class Tensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, T>, System.Numerics.Tensors.ITensor, T> + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + public sealed partial class Tensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor, T>, System.Numerics.Tensors.ITensor, System.Numerics.Tensors.ITensor, T> { internal Tensor() { } public static System.Numerics.Tensors.Tensor Empty { get { throw null; } } @@ -831,12 +845,16 @@ internal Tensor() { } public System.ReadOnlySpan Lengths { get { throw null; } } public int Rank { get { throw null; } } public System.ReadOnlySpan Strides { get { throw null; } } + object System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } } + object System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } } + System.ReadOnlySpan System.Numerics.Tensors.IReadOnlyTensor.Lengths { get { throw null; } } + System.ReadOnlySpan System.Numerics.Tensors.IReadOnlyTensor.Strides { get { throw null; } } T System.Numerics.Tensors.IReadOnlyTensor, T>.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } } System.Numerics.Tensors.Tensor System.Numerics.Tensors.IReadOnlyTensor, T>.this[params scoped System.ReadOnlySpan ranges] { get { throw null; } } T System.Numerics.Tensors.IReadOnlyTensor, T>.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } } - System.ReadOnlySpan System.Numerics.Tensors.IReadOnlyTensor, T>.Lengths { get { throw null; } } - System.ReadOnlySpan System.Numerics.Tensors.IReadOnlyTensor, T>.Strides { get { throw null; } } - bool System.Numerics.Tensors.ITensor, T>.IsReadOnly { get { throw null; } } + bool System.Numerics.Tensors.ITensor.IsReadOnly { get { throw null; } } + object System.Numerics.Tensors.ITensor.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } set { } } + object System.Numerics.Tensors.ITensor.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } set { } } T System.Numerics.Tensors.ITensor, T>.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } set { } } T System.Numerics.Tensors.ITensor, T>.this[params scoped System.ReadOnlySpan indexes] { get { throw null; } set { } } public System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan() { throw null; } @@ -849,12 +867,14 @@ internal Tensor() { } public System.Numerics.Tensors.TensorSpan AsTensorSpan(params scoped System.ReadOnlySpan start) { throw null; } public void Clear() { } public void CopyTo(scoped System.Numerics.Tensors.TensorSpan destination) { } + public void Fill(object value) { } public void Fill(T value) { } public void FlattenTo(scoped System.Span destination) { } public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } public override int GetHashCode() { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public ref T GetPinnableReference() { throw null; } + public System.Buffers.MemoryHandle GetPinnedHandle() { throw null; } public static implicit operator System.Numerics.Tensors.ReadOnlyTensorSpan (System.Numerics.Tensors.Tensor value) { throw null; } public static implicit operator System.Numerics.Tensors.TensorSpan (System.Numerics.Tensors.Tensor value) { throw null; } public static implicit operator System.Numerics.Tensors.Tensor (T[] array) { throw null; } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/IReadOnlyTensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/IReadOnlyTensor.cs index 9d42fa96d3f8af..ce52ab8c279b91 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/IReadOnlyTensor.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/IReadOnlyTensor.cs @@ -7,20 +7,13 @@ namespace System.Numerics.Tensors { + /// /// Represents a read-only tensor. /// - /// The type that implements this interface. - /// The element type. [Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)] - public interface IReadOnlyTensor : IEnumerable - where TSelf : IReadOnlyTensor + public interface IReadOnlyTensor { - /// - /// Gets an empty tensor. - /// - static abstract TSelf? Empty { get; } - /// /// Gets a value that indicates whether the collection is currently empty. /// @@ -41,17 +34,62 @@ public interface IReadOnlyTensor : IEnumerable /// int Rank { get; } + /// + /// Gets the length of each dimension in the tensor. + /// + [UnscopedRef] + ReadOnlySpan Lengths { get; } + + /// + /// Gets the stride of each dimension in the tensor. + /// + [UnscopedRef] + ReadOnlySpan Strides { get; } + + /// + /// Gets the value at the specified indexes. + /// + /// The indexes to be used. + object this[params scoped ReadOnlySpan indexes] { get; } + + /// + /// Gets the value at the specified indexes. + /// + /// The indexes to be used. + object this[params scoped ReadOnlySpan indexes] { get; } + + /// + /// Pins and gets a to the backing memory. + /// + /// + MemoryHandle GetPinnedHandle(); + } + + /// + /// Represents a read-only tensor. + /// + /// The type that implements this interface. + /// The element type. + [Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)] + public interface IReadOnlyTensor : IReadOnlyTensor, IEnumerable + where TSelf : IReadOnlyTensor + { + /// + /// Gets an empty tensor. + /// + static abstract TSelf? Empty { get; } + /// /// Gets the value at the specified indexes. /// /// The indexes to be used. - T this[params scoped ReadOnlySpan indexes] { get; } + new T this[params scoped ReadOnlySpan indexes] { get; } /// /// Gets the value at the specified indexes. /// /// The indexes to be used. - T this[params scoped ReadOnlySpan indexes] { get; } + new T this[params scoped ReadOnlySpan indexes] { get; } /// /// Gets the values at the specified ranges. @@ -98,18 +136,6 @@ public interface IReadOnlyTensor : IEnumerable /// The destination span where the data should be flattened to. void FlattenTo(scoped Span destination); - /// - /// Gets the length of each dimension in the tensor. - /// - [UnscopedRef] - ReadOnlySpan Lengths { get; } - - /// - /// Gets the stride of each dimension in the tensor. - /// - [UnscopedRef] - ReadOnlySpan Strides { get; } - /// /// Returns a reference to the 0th element of the tensor. If the tensor is empty, returns . /// diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs index eba3af96f69df1..4a1cbd2b1bf800 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs @@ -6,14 +6,47 @@ namespace System.Numerics.Tensors { + /// + /// Represents a tensor. + /// + [Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)] + public interface ITensor : IReadOnlyTensor + { + /// + /// Gets the value at the specified indexes. + /// + /// The indexes to be used. + new object this[params scoped ReadOnlySpan indexes] { get; set; } + + /// + /// Gets the value at the specified indexes. + /// + /// The indexes to be used. + new object this[params scoped ReadOnlySpan indexes] { get; set; } + + /// + /// Gets a value that indicates whether the collection is read-only. + /// + bool IsReadOnly { get; } + + /// + /// Clears the tensor. + /// + void Clear(); + + /// + /// Fills the contents of this tensor with the given value. + /// + void Fill(object value); + } + /// /// Represents a tensor. /// /// The type that implements this interface. /// The element type. [Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)] - public interface ITensor - : IReadOnlyTensor + public interface ITensor : ITensor, IReadOnlyTensor where TSelf : ITensor { // TODO: Determine if we can implement `IEqualityOperators`. @@ -67,11 +100,6 @@ public interface ITensor /// static abstract TSelf CreateUninitialized(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false); - /// - /// Gets a value that idicates whether the collection is read-only. - /// - bool IsReadOnly { get; } - /// /// Gets the value at the specified indexes. /// @@ -117,11 +145,6 @@ public interface ITensor /// The converted . TensorSpan AsTensorSpan(params scoped ReadOnlySpan range); - /// - /// Clears the tensor. - /// - void Clear(); - /// /// Fills the contents of this tensor with the given value. /// diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs index 1e3904fb7504d2..29b48f4a613e03 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs @@ -64,7 +64,7 @@ public static Tensor Create(T[] values, scoped ReadOnlySpan lengths, /// public static Tensor Create(T[] values, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false) { - return new Tensor(values, lengths, strides, pinned); + return new Tensor(values, lengths, strides, memoryOffset: 0, pinned); } /// @@ -77,7 +77,7 @@ public static Tensor Create(T[] values, scoped ReadOnlySpan lengths, public static Tensor Create(IEnumerable values, scoped ReadOnlySpan lengths, bool pinned = false) { T[] data = values.ToArray(); - return new Tensor(data, lengths.IsEmpty ? [data.Length] : lengths, pinned); + return new Tensor(data, lengths.IsEmpty ? [data.Length] : lengths, memoryOffset: 0, pinned); } /// @@ -90,7 +90,7 @@ public static Tensor Create(IEnumerable values, scoped ReadOnlySpan Create(IEnumerable values, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false) { T[] data = values.ToArray(); - return new Tensor(data, lengths.IsEmpty ? [data.Length] : lengths, strides, pinned); + return new Tensor(data, lengths.IsEmpty ? [data.Length] : lengths, strides, memoryOffset: 0, pinned); } #region Normal @@ -115,7 +115,7 @@ public static Tensor CreateAndFillGaussianNormalDistribution(Random random nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = new T[linearLength]; GaussianDistribution(values, linearLength, random); - return new Tensor(values, lengths, false); + return new Tensor(values, lengths, memoryOffset: 0, isPinned: false); } private static void GaussianDistribution(in Span values, nint linearLength, Random random) @@ -154,7 +154,7 @@ public static Tensor CreateAndFillUniformDistribution(Random random, param for (int i = 0; i < values.Length; i++) values[i] = T.CreateChecked(random.NextDouble()); - return new Tensor(values, lengths, false); + return new Tensor(values, lengths, memoryOffset: 0, isPinned: false); } /// @@ -175,7 +175,7 @@ public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); - return new Tensor(values, lengths, strides, pinned); + return new Tensor(values, lengths, strides, memoryOffset: 0, pinned); } /// diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs index 29e3cd48f60fa2..4878350449c319 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs @@ -21,8 +21,7 @@ namespace System.Numerics.Tensors /// Represents a tensor. /// [Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)] - public sealed class Tensor - : ITensor, T> + public sealed class Tensor : ITensor, ITensor, T> { /// A byref or a native ptr. internal readonly T[] _values; @@ -34,6 +33,8 @@ public sealed class Tensor internal readonly nint[] _strides; /// If the backing memory is permanently pinned (so not just using a fixed statement). internal readonly bool _isPinned; + /// The offset of the first element in the backing memory. + internal readonly int _memoryOffset; /// /// Creates a new empty Tensor. @@ -44,13 +45,14 @@ internal Tensor() _values = []; _lengths = []; _strides = []; + _memoryOffset = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Tensor(T[]? values, ReadOnlySpan lengths, bool isPinned = false) : this(values, lengths, Array.Empty(), isPinned) { } + internal Tensor(T[]? values, ReadOnlySpan lengths, int memoryOffset, bool isPinned = false) : this(values, lengths, Array.Empty(), memoryOffset, isPinned) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Tensor(T[]? values, ReadOnlySpan lengths, ReadOnlySpan strides, bool isPinned = false) + internal Tensor(T[]? values, ReadOnlySpan lengths, ReadOnlySpan strides, int memoryOffset, bool isPinned = false) { if (values == null) { @@ -60,10 +62,15 @@ internal Tensor(T[]? values, ReadOnlySpan lengths, ReadOnlySpan stri _values = []; _lengths = []; _strides = []; + _memoryOffset = memoryOffset; return; // returns default } _lengths = lengths.IsEmpty ? [values.Length] : lengths.ToArray(); + _memoryOffset = memoryOffset; + + if (_memoryOffset < 0 || (_memoryOffset >= values.Length && values.Length != 0 )) + ThrowHelper.ThrowIndexOutOfRangeException(); _flattenedLength = TensorSpanHelpers.CalculateTotalLength(_lengths); _strides = strides.IsEmpty ? TensorSpanHelpers.CalculateStrides(_lengths, _flattenedLength) : strides.ToArray(); @@ -73,12 +80,12 @@ internal Tensor(T[]? values, ReadOnlySpan lengths, ReadOnlySpan stri if (Environment.Is64BitProcess) { // See comment in Span.Slice for how this works. - if ((ulong)(uint)maxElements >= (ulong)(uint)values.Length && values.Length != 0) + if ((ulong)(uint)maxElements >= (ulong)(uint)(values.Length - memoryOffset) && values.Length != 0) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); } else { - if (((uint)maxElements >= (uint)(values.Length)) && values.Length != 0) + if (((uint)maxElements >= (uint)(values.Length - memoryOffset)) && values.Length != 0) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); } @@ -95,7 +102,7 @@ static Tensor ITensor, T>.Create(scoped ReadOnlySpan lengths, { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); - return new Tensor(values, lengths.ToArray(), pinned); + return new Tensor(values, lengths.ToArray(), memoryOffset: 0, pinned); } /// @@ -108,7 +115,7 @@ static Tensor ITensor, T>.Create(scoped ReadOnlySpan lengths, { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); - return new Tensor(values, lengths.ToArray(), strides.ToArray(), pinned); + return new Tensor(values, lengths.ToArray(), strides.ToArray(), memoryOffset: 0, pinned); } /// @@ -120,7 +127,7 @@ static Tensor ITensor, T>.CreateUninitialized(scoped ReadOnlySpan((int)linearLength, pinned); - return new Tensor(values, lengths.ToArray(), pinned); + return new Tensor(values, lengths.ToArray(), memoryOffset: 0, pinned); } /// @@ -133,7 +140,7 @@ static Tensor ITensor, T>.CreateUninitialized(scoped ReadOnlySpan((int)linearLength, pinned); - return new Tensor(values, lengths.ToArray(), strides.ToArray(), pinned); + return new Tensor(values, lengths.ToArray(), strides.ToArray(), memoryOffset: 0, pinned); } // ITensor @@ -176,7 +183,7 @@ static Tensor ITensor, T>.CreateUninitialized(scoped ReadOnlySpan. /// /// with the lengths of each dimension. - ReadOnlySpan IReadOnlyTensor, T>.Lengths => _lengths; + ReadOnlySpan IReadOnlyTensor.Lengths => _lengths; /// @@ -189,9 +196,16 @@ static Tensor ITensor, T>.CreateUninitialized(scoped ReadOnlySpan. /// /// with the strides of each dimension. - ReadOnlySpan IReadOnlyTensor, T>.Strides => _strides; + ReadOnlySpan IReadOnlyTensor.Strides => _strides; + + bool ITensor.IsReadOnly => false; + + object IReadOnlyTensor.this[params scoped ReadOnlySpan indexes] => this[indexes]!; - bool ITensor, T>.IsReadOnly => false; + object IReadOnlyTensor.this[params scoped ReadOnlySpan indexes] => this[indexes]!; + + object ITensor.this[params scoped ReadOnlySpan indexes] { get => this[indexes]!; set => this[indexes] = (T)value; } + object ITensor.this[params scoped ReadOnlySpan indexes] { get => this[indexes]!; set => this[indexes] = (T)value; } /// /// Returns a reference to specified element of the Tensor. @@ -363,30 +377,30 @@ public Tensor this[Tensor filter] } } - return new Tensor(values, [linearLength], _isPinned); + return new Tensor(values, [linearLength], _memoryOffset, _isPinned); } } /// /// Defines an implicit conversion of an array to a . /// - public static implicit operator Tensor(T[] array) => new Tensor(array, [array.Length]); + public static implicit operator Tensor(T[] array) => new Tensor(array, [array.Length], memoryOffset: 0); /// /// Defines an implicit conversion of a to a . /// - public static implicit operator TensorSpan(Tensor value) => new TensorSpan(ref MemoryMarshal.GetArrayDataReference(value._values), value._lengths, value._strides, value._flattenedLength); + public static implicit operator TensorSpan(Tensor value) => value.AsTensorSpan(); /// /// Defines an implicit conversion of a to a . /// - public static implicit operator ReadOnlyTensorSpan(Tensor value) => new ReadOnlyTensorSpan(ref MemoryMarshal.GetArrayDataReference(value._values), value._lengths, value._strides, value.FlattenedLength); + public static implicit operator ReadOnlyTensorSpan(Tensor value) => value.AsReadOnlyTensorSpan(); /// /// Converts this to a pointing to the same backing memory."/> /// /// - public TensorSpan AsTensorSpan() => new TensorSpan(ref MemoryMarshal.GetArrayDataReference(_values), _lengths, _strides, _flattenedLength); + public TensorSpan AsTensorSpan() => new TensorSpan(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_values), _memoryOffset), _lengths, _strides, _values.Length - _memoryOffset); /// /// Converts this to a pointing to the same backing memory based on the provided ranges."/> @@ -400,7 +414,7 @@ public Tensor this[Tensor filter] /// /// The start location you want in the . /// based on the provided ranges. - public TensorSpan AsTensorSpan(params scoped ReadOnlySpan start) => Slice(start); + public TensorSpan AsTensorSpan(params scoped ReadOnlySpan start) => AsTensorSpan().Slice(start); /// /// Converts this to a pointing to the same backing memory based on the provided start indexes."/> @@ -413,7 +427,7 @@ public Tensor this[Tensor filter] /// Converts this to a pointing to the same backing memory."/> /// /// - public ReadOnlyTensorSpan AsReadOnlyTensorSpan() => new ReadOnlyTensorSpan(ref MemoryMarshal.GetArrayDataReference(_values), _lengths, _strides, _flattenedLength); + public ReadOnlyTensorSpan AsReadOnlyTensorSpan() => new ReadOnlyTensorSpan(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_values), _memoryOffset), _lengths, _strides, _flattenedLength); /// /// Converts this to a pointing to the same backing memory based on the provided ranges."/> @@ -427,7 +441,7 @@ public Tensor this[Tensor filter] /// /// The start locations you want in the /// - public ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan start) => Slice(start); + public ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan start) => AsTensorSpan().Slice(start); /// /// Converts this to a pointing to the same backing memory based on the provided start indexes."/> @@ -454,26 +468,71 @@ public Tensor this[Tensor filter] /// Forms a slice out of the given tensor /// /// The ranges for the slice - /// as a copy of the provided ranges. - // REVIEW: CURRENTLY DOES A COPY. + /// without copying the provided ranges. public Tensor Slice(params ReadOnlySpan start) { if (start.Length != Lengths.Length) throw new ArgumentOutOfRangeException(nameof(start), "Number of dimensions to slice does not equal the number of dimensions in the span"); - TensorSpan s = AsTensorSpan(start); - T[] values = _isPinned ? GC.AllocateArray(checked((int)s.FlattenedLength), _isPinned) : (new T[s.FlattenedLength]); - var outTensor = new Tensor(values, s.Lengths.ToArray(), _isPinned); - s.CopyTo(outTensor); - return outTensor; + scoped Span lengths; + scoped Span offsets; + nint[]? lengthsArray; + nint[]? offsetsArray; + if (Rank > TensorShape.MaxInlineRank) + { + lengthsArray = ArrayPool.Shared.Rent(Rank); + lengths = lengthsArray.AsSpan(0, Rank); + + offsetsArray = ArrayPool.Shared.Rent(Rank); + offsets = offsetsArray.AsSpan(0, Rank); + } + else + { + lengths = stackalloc nint[Rank]; + offsets = stackalloc nint[Rank]; + + lengthsArray = null; + offsetsArray = null; + } + lengths.Clear(); + offsets.Clear(); + + for (int i = 0; i < start.Length; i++) + { + (offsets[i], lengths[i]) = start[i].GetOffsetAndLength(Lengths[i]); + } + + // When we have an empty Tensor and someone wants to slice all of it, we should return an empty Tensor. + // FlattenedLength is computed everytime so using a local to cache the value. + nint flattenedLength = FlattenedLength; + int memoryOffset = 0; + + if (flattenedLength != 0) + { + for (int i = 0; i < offsets.Length; i++) + { + memoryOffset += (int)(Strides[i] * offsets[i]); + } + } + + if ((memoryOffset >= _values.Length || memoryOffset < 0) && flattenedLength != 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + Tensor toReturn = new Tensor(_values, lengths, Strides, memoryOffset, _isPinned); + + if (offsetsArray != null) + ArrayPool.Shared.Return(offsetsArray); + if (lengthsArray != null) + ArrayPool.Shared.Return(lengthsArray); + + return toReturn; } /// /// Forms a slice out of the given tensor /// /// The start indexes for the slice - /// as a copy of the provided ranges. - // REVIEW: CURRENTLY DOES A COPY. + /// without copying the provided ranges. public Tensor Slice(params ReadOnlySpan start) { NRange[] ranges = new NRange[start.Length]; @@ -488,8 +547,7 @@ public Tensor Slice(params ReadOnlySpan start) /// Forms a slice out of the given tensor /// /// The start indexes for the slice - /// as a copy of the provided ranges. - // REVIEW: CURRENTLY DOES A COPY. + /// without copying the provided ranges. public Tensor Slice(params ReadOnlySpan startIndex) { NRange[] ranges = new NRange[startIndex.Length]; @@ -524,6 +582,11 @@ public Tensor Slice(params ReadOnlySpan startIndex) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Fill(T value) => AsTensorSpan().Fill(value); + /// + /// Fills the contents of this span with the given value. + /// + public void Fill(object value) => Fill(value is T t ? t : throw new ArgumentException($"Cannot convert {value} to {typeof(T)}")); + /// /// Copies the contents of this tensor into destination span. If the source /// and destinations overlap, this method behaves as if the original values in @@ -671,5 +734,18 @@ public string ToString(params ReadOnlySpan maximumLengths) sb.AppendLine("}"); return sb.ToString(); } + + /// + /// Pins and gets a to the backing memory. + /// + /// A which has pinned the backing memory. + public MemoryHandle GetPinnedHandle() + { + GCHandle handle = GCHandle.Alloc(_values, GCHandleType.Pinned); + unsafe + { + return new MemoryHandle(Unsafe.AsPointer(ref GetPinnableReference()), handle); + } + } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs index 9e5c4c933cd602..6b9dbec121b207 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs @@ -218,7 +218,7 @@ internal static ReadOnlyTensorSpan LazyBroadcast(in ReadOnlyTensorSpan internal static Tensor LazyBroadcast(Tensor input, ReadOnlySpan lengths) { if (input.Lengths.SequenceEqual(lengths)) - return new Tensor(input._values, lengths, false); + return new Tensor(input._values, lengths, input._memoryOffset, isPinned: false); if (!TensorHelpers.IsBroadcastableTo(input.Lengths, lengths)) ThrowHelper.ThrowArgument_LengthsNotBroadcastCompatible(); @@ -244,7 +244,7 @@ internal static Tensor LazyBroadcast(Tensor input, ReadOnlySpan l } } - Tensor output = new Tensor(input._values, lengths, strides); + Tensor output = new Tensor(input._values, lengths, strides, input._memoryOffset); return output; } @@ -2660,7 +2660,7 @@ public static Tensor PermuteDimensions(this Tensor tensor, params ReadO lengths[i] = tensor.Lengths[dimensions[i]]; permutation = dimensions.ToArray(); } - outTensor = new Tensor(values, lengths, Array.Empty(), tensor._isPinned); + outTensor = new Tensor(values, lengths, Array.Empty(), tensor._memoryOffset, tensor._isPinned); ospan = outTensor.AsTensorSpan(); ispan = tensor.AsTensorSpan(); @@ -2771,7 +2771,7 @@ public static Tensor Reshape(this Tensor tensor, params ReadOnlySpan(tensor._values, arrLengths, strides); + return new Tensor(tensor._values, arrLengths, strides, tensor._memoryOffset); } /// @@ -2926,7 +2926,7 @@ public static Tensor Resize(Tensor tensor, ReadOnlySpan lengths) { nint newSize = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = tensor.IsPinned ? GC.AllocateArray((int)newSize) : (new T[newSize]); - Tensor output = new Tensor(values, lengths, false); + Tensor output = new Tensor(values, lengths, tensor._memoryOffset, isPinned: false); ReadOnlySpan span = MemoryMarshal.CreateSpan(ref tensor.AsTensorSpan()._reference, (int)tensor._values.Length); Span ospan = MemoryMarshal.CreateSpan(ref output.AsTensorSpan()._reference, (int)output.FlattenedLength); if (newSize > tensor._values.Length) @@ -3217,7 +3217,7 @@ public static Tensor[] Split(scoped in ReadOnlyTensorSpan tensor, int s for (int i = 0; i < outputs.Length; i++) { T[] values = new T[(int)totalToCopy]; - outputs[i] = new Tensor(values, newShape); + outputs[i] = new Tensor(values, newShape, memoryOffset: 0); oIndices.Clear(); iIndices.Clear(); @@ -3299,7 +3299,7 @@ public static Tensor SqueezeDimension(this Tensor tensor, int dimension strides = TensorSpanHelpers.CalculateStrides(lengths); } - return new Tensor(tensor._values, lengths, strides); + return new Tensor(tensor._values, lengths, strides, tensor._memoryOffset); } /// @@ -3661,7 +3661,7 @@ public static Tensor Unsqueeze(this Tensor tensor, int dimension) strides[dimension] = tensor.Strides[dimension] * tensor.Lengths[dimension]; } - return new Tensor(tensor._values, lengths, strides); + return new Tensor(tensor._values, lengths, strides, tensor._memoryOffset); } /// diff --git a/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj b/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj index 54deee7ac9fe50..89c744dc04a7ba 100644 --- a/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj +++ b/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true $(NoWarn);SYSLIB5001 @@ -34,8 +34,4 @@ - - - - diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs index b57472302f98aa..0d0fc167b6bfcd 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs @@ -239,43 +239,31 @@ public void TensorExtensionsSpanInTOut(TensorPrimitivesSpanInTOut tensorPr T[] data = new T[length]; FillTensor(data); - Tensor x = Tensor.Create(data, tensorLength, []); + Tensor tensor = Tensor.Create(data, tensorLength, []); T expectedOutput = tensorPrimitivesOperation((ReadOnlySpan)data); - T results = tensorOperation(x); + T results = tensorOperation(tensor); Assert.Equal(expectedOutput, results); - float[] testData = [49.788437f, 32.736755f, -0.25761032f, -46.402596f, 4.5581512f, 21.813591f, 44.976646f, 12.691814f, -44.188023f, 40.35988f, -6.999405f, 4.713642f, 5.274975f, 21.312515f, -12.536407f, -34.888573f, -1.90839f, 28.734451f, -38.64155f, -28.840702f, 7.373543f, 18.600182f, 26.007828f, 0.71430206f, -6.8293495f, -13.327972f, -25.149017f, 9.331852f, 40.87751f, 28.321632f, 42.918175f, 25.213333f, -41.392017f, 36.727768f, 26.49012f, 3.8807983f, 24.933182f, -43.050568f, -42.6283f, 18.01947f, -47.62874f, -49.94487f, -1.036602f, -37.086433f, 32.77098f, -12.903477f, -45.100212f, -20.596504f, 33.67714f, 46.864395f, 44.437485f, -44.092155f, 37.122124f, 25.220505f, 41.994873f, -13.3394165f, -28.193134f, -21.329712f, -36.623306f, 3.3981133f, -26.475079f, 16.339478f, -44.07065f, 36.321762f, -24.63433f, 28.652397f, 4.096817f, 33.29615f, -2.3503838f, -7.509815f, 42.943604f, -32.52115f, -0.20326233f, 29.554626f, 18.044052f]; - nint[] testLengths = [5, 3, 5]; - Tensor testTensor = Tensor.Create(testData, testLengths, []); - float[] testSliceData = new float[75]; - testTensor.FlattenTo(testSliceData); - float testExpectedOutput = TensorPrimitives.Sum((ReadOnlySpan)testSliceData); - float testResults = Tensor.Sum(testTensor); - - // Now test if the source is sliced to be non contiguous that it still gives expected result. NRange[] sliceLengths = Helpers.TensorSliceShapes[index].Select(i => new NRange(0, i)).ToArray(); nint sliceFlattenedLength = CalculateTotalLength(Helpers.TensorSliceShapes[index]); - x = x.Slice(sliceLengths); + tensor = tensor.Slice(sliceLengths); T[] sliceData = new T[sliceFlattenedLength]; - x.FlattenTo(sliceData); + tensor.FlattenTo(sliceData); - IEnumerator enumerator = x.GetEnumerator(); + IEnumerator enumerator = tensor.GetEnumerator(); bool cont = enumerator.MoveNext(); - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref x.AsReadOnlyTensorSpan()._reference, (int)x.FlattenedLength); int i = 0; - Assert.True(span.SequenceEqual(sliceData)); + Assert.True(tensor.SequenceEqual(sliceData)); while (cont) { - Assert.Equal(sliceData[i], enumerator.Current); - Assert.Equal(span[i], enumerator.Current); - Assert.Equal(span[i], sliceData[i++]); + Assert.Equal(sliceData[i++], enumerator.Current); cont = enumerator.MoveNext(); } expectedOutput = tensorPrimitivesOperation((ReadOnlySpan)sliceData); - results = tensorOperation(x); + results = tensorOperation(tensor); Assert.Equal(expectedOutput, results); }); diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs index 607d09788db1ce..fce9d8f68f474f 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -1135,6 +1136,46 @@ public static void TensorStdDevTests() Assert.Equal(0f, Tensor.StdDev(upperLeft)); } + [Fact] + public static void TensorSumTests() + { + float[] values = new float[] { 1, 2, 3, 4, 5, 6 }; + Tensor t0 = Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, [2, 3]); + float sum = Tensor.Sum(t0); + Assert.Equal(21, sum); + + // Slice first row of 2 x 2 for sum + Tensor t1 = t0.Slice(new NRange(new NIndex(0), new NIndex(1)), new NRange(new NIndex(0), new NIndex(0, true))); + sum = Tensor.Sum(t1); + Assert.Equal(6, sum); + + // Slice second row of 2 x 2 for sum. + t1 = t0.Slice(new NRange(new NIndex(1), new NIndex(2)), new NRange(new NIndex(0), new NIndex(0, true))); + sum = Tensor.Sum(t1); + Assert.Equal(15, sum); + + // Slice first column of 2 x 2 for sum. + t1 = t0.Slice(new NRange(new NIndex(0), new NIndex(2)), new NRange(new NIndex(0), new NIndex(1))); + sum = Tensor.Sum(t1); + Assert.Equal(5, sum); + + // Slice second column of 2 x 2 for sum. + t1 = t0.Slice(new NRange(new NIndex(0), new NIndex(2)), new NRange(new NIndex(1), new NIndex(2))); + sum = Tensor.Sum(t1); + Assert.Equal(7, sum); + + // Slice Third column of 2 x 2 for sum. + t1 = t0.Slice(new NRange(new NIndex(0), new NIndex(2)), new NRange(new NIndex(2), new NIndex(3))); + sum = Tensor.Sum(t1); + Assert.Equal(9, sum); + + Assert.Throws(()=> new Tensor(new float[] { 1, 2, 3, 4, 5, 6 }, [2, 3], -1)); + Assert.Throws(()=> new Tensor(new float[] { 1, 2, 3, 4, 5, 6 }, [2, 3], 100)); + Assert.Throws(()=> new Tensor(new float[] { 1, 2, 3, 4, 5, 6 }, [2, 3], int.MinValue)); + Assert.Throws(()=> new Tensor(new float[] { 1, 2, 3, 4, 5, 6 }, [2, 3], int.MaxValue)); + Assert.Throws(()=> new Tensor(new float[] { 1, 2, 3, 4, 5, 6 }, [2, 3], 2)); + } + public static float StdDev(float[] values) { float mean = Mean(values); @@ -1582,12 +1623,12 @@ public static void TensorClearTest() Assert.Equal(0, slice[1, 0]); Assert.Equal(0, slice[1, 1]); - // Since Tensor.Slice does a copy the original tensor shouldn't be modified - Assert.Equal(1, tensor[0, 0]); - Assert.Equal(2, tensor[0, 1]); + // Since Tensor.Slice does do a copy the original tensor should be modified but only in the slice we took. + Assert.Equal(0, tensor[0, 0]); + Assert.Equal(0, tensor[0, 1]); Assert.Equal(3, tensor[0, 2]); - Assert.Equal(4, tensor[1, 0]); - Assert.Equal(5, tensor[1, 1]); + Assert.Equal(0, tensor[1, 0]); + Assert.Equal(0, tensor[1, 1]); Assert.Equal(6, tensor[1, 2]); Assert.Equal(7, tensor[2, 0]); Assert.Equal(8, tensor[2, 1]); @@ -1609,8 +1650,8 @@ public static void TensorClearTest() slice.Clear(); Assert.Equal(0, slice[0]); - // Since Tensor.Slice does a copy the original tensor shouldn't be modified - Assert.Equal(1, tensor[0]); + // Since Tensor.Slice does do a copy the original tensor should be modified but only in the slice we took. + Assert.Equal(0, tensor[0]); Assert.Equal(2, tensor[1]); Assert.Equal(3, tensor[2]); Assert.Equal(4, tensor[3]); @@ -2644,5 +2685,73 @@ public void TensorFilteredUpdateTest() Tensor.FilteredUpdate(tensor1.AsTensorSpan(), filter, replace); Assert.Equal(new int[] { -1, -1, -1 }, tensor1.ToArray()); } + + [Fact] + public void TensorObjectFillTests() + { + ITensor tensor = (ITensor)new Tensor(new int[4], new nint[] { 2, 2 }, 0); + tensor.Fill(5); + + Assert.Equal(5, tensor[0, 0]); + Assert.Equal(5, tensor[0, 1]); + Assert.Equal(5, tensor[1, 0]); + Assert.Equal(5, tensor[1, 1]); + + Assert.Throws(() => tensor.Fill("invalid")); + Assert.Throws(() => tensor.Fill(null)); + + tensor.Fill((object)5); + Assert.Equal(5, tensor[0, 0]); + Assert.Equal(5, tensor[0, 1]); + Assert.Equal(5, tensor[1, 0]); + Assert.Equal(5, tensor[1, 1]); + } + + [Fact] + public void TensorObjectIndexerTests() + { + ITensor tensor = new Tensor(new int[] { 1, 2, 3, 4 }, new nint[] { 2, 2 }, 0); + + Assert.Equal(1, tensor[new nint[] { 0, 0 }]); + Assert.Equal(2, tensor[new nint[] { 0, 1 }]); + Assert.Equal(3, tensor[new nint[] { 1, 0 }]); + Assert.Equal(4, tensor[new nint[] { 1, 1 }]); + + tensor[new nint[] { 0, 0 }] = 10; + tensor[new nint[] { 0, 1 }] = 20; + tensor[new nint[] { 1, 0 }] = 30; + tensor[new nint[] { 1, 1 }] = 40; + + Assert.Equal(10, tensor[new nint[] { 0, 0 }]); + Assert.Equal(20, tensor[new nint[] { 0, 1 }]); + Assert.Equal(30, tensor[new nint[] { 1, 0 }]); + Assert.Equal(40, tensor[new nint[] { 1, 1 }]); + + Assert.Throws(() => tensor[new nint[] { 2, 0 }]); + Assert.Throws(() => tensor[new nint[] { 0, 2 }]); + Assert.Throws(() => tensor[new nint[] { -1, 0 }]); + Assert.Throws(() => tensor[new nint[] { -1, -1 }]); + + Assert.Throws(() => tensor[new nint[] { 2, 0 }] = 10); + Assert.Throws(() => tensor[new nint[] { 0, 2 }] = 20); + Assert.Throws(() => tensor[new nint[] { -1, 0 }] = 20); + Assert.Throws(() => tensor[new nint[] { -1, -1 }] = 20); + } + + [Fact] + public void TensorGetPinnedHandleTests() + { + Tensor tensor = new Tensor(new int[] { 1, 2, 3, 4 }, new nint[] { 2, 2 }, 0); + + using MemoryHandle handle = tensor.GetPinnedHandle(); + unsafe + { + int* ptr = (int*)handle.Pointer; + Assert.Equal(1, ptr[0]); + Assert.Equal(2, ptr[1]); + Assert.Equal(3, ptr[2]); + Assert.Equal(4, ptr[3]); + } + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index 2eb4c0c882437e..0ebac20f1b9194 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -3114,6 +3114,19 @@ public void ConvertUInt32ToSingle() } } + [Fact] + public void ConvertUInt32ToSingleWithReflection() + { + MethodInfo method = typeof(Vector).GetMethod(nameof(Vector.ConvertToSingle), [typeof(Vector)]); + uint[] source = GenerateRandomValuesForVector(); + Vector sourceVec = new Vector(source); + Vector targetVec = (Vector)method.Invoke(null, [sourceVec]); + for (int i = 0; i < Vector.Count; i++) + { + Assert.Equal(unchecked((float)source[i]), targetVec[i]); + } + } + [Fact] public void ConvertInt64ToDouble() { @@ -3126,6 +3139,19 @@ public void ConvertInt64ToDouble() } } + [Fact] + public void ConvertInt64ToDoubleWithReflection() + { + MethodInfo method = typeof(Vector).GetMethod(nameof(Vector.ConvertToDouble), [typeof(Vector)]); + long[] source = GenerateRandomValuesForVector(); + Vector sourceVec = new Vector(source); + Vector targetVec = (Vector)method.Invoke(null, [sourceVec]); + for (int i = 0; i < Vector.Count; i++) + { + Assert.Equal(unchecked((double)source[i]), targetVec[i]); + } + } + [Fact] public void ConvertUInt64ToDouble() { @@ -3138,6 +3164,19 @@ public void ConvertUInt64ToDouble() } } + [Fact] + public void ConvertUInt64ToDoubleWithReflection() + { + MethodInfo method = typeof(Vector).GetMethod(nameof(Vector.ConvertToDouble), [typeof(Vector)]); + ulong[] source = GenerateRandomValuesForVector(); + Vector sourceVec = new Vector(source); + Vector targetVec = (Vector)method.Invoke(null, [sourceVec]); + for (int i = 0; i < Vector.Count; i++) + { + Assert.Equal(unchecked((double)source[i]), targetVec[i]); + } + } + [Fact] public void ConvertSingleToInt32() { diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 7c57b8a835b2d3..0a4afcda2834bd 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -3476,6 +3476,12 @@ The calling thread does not hold the lock. + + The specified name '{0}' has a prefix that is not compatible with the specified option 'CurrentSessionOnly'. + + + An object with the specified name '{0}' exists and can't be opened because it's not compatible with the specified option 'CurrentUserOnly = true'. + Thread tracking is disabled. 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 20d08a75ce8526..a73d2783adf653 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 @@ -1241,6 +1241,7 @@ + @@ -1604,9 +1605,18 @@ + + Common\Interop\Windows\Advapi32\Interop.AccessControlLists.cs + + + Common\Interop\Windows\Advapi32\Interop.CreateWellKnownSid.cs + Common\Interop\Windows\Advapi32\Interop.EncryptDecrypt.cs + + Interop\Windows\Advapi32\Interop.EqualSid.cs + Common\Interop\Windows\Advapi32\Interop.EventActivityIdControl.cs @@ -1628,6 +1638,18 @@ Common\Interop\Windows\Advapi32\Interop.EventWriteTransfer.cs + + Common\Interop\Windows\Advapi32\Interop.GetLengthSid.cs + + + Interop\Windows\Advapi32\Interop.GetSecurityInfoByHandle.cs + + + Interop\Windows\Advapi32\Interop.GetSidIdentifierAuthority.cs + + + Interop\Windows\Advapi32\Interop.GetTokenInformation.cs + Common\Interop\Windows\Advapi32\Interop.GetTokenInformation_void.cs @@ -1637,6 +1659,9 @@ Common\Interop\Windows\Advapi32\Interop.OpenProcessToken.cs + + Common\Interop\Windows\Advapi32\Interop.OpenThreadToken.cs + Common\Interop\Windows\Advapi32\Interop.RegCloseKey.cs @@ -1670,6 +1695,9 @@ Common\Interop\Windows\Advapi32\Interop.RegSetValueEx.cs + + Common\Interop\Windows\Advapi32\Interop.SecurityDescriptors.cs + Common\Interop\Windows\Advapi32\Interop.TOKEN_ACCESS_LEVELS.cs @@ -2144,6 +2172,9 @@ Common\Interop\Windows\Kernel32\Interop.Sleep.cs + + Common\Microsoft\Win32\SafeHandles\SafeLocalAllocHandle.cs + Common\Microsoft\Win32\SafeHandles\SafeTokenHandle.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs index 747927db98c355..37b8c4bb97cf96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs @@ -827,16 +827,14 @@ internal static Vector128 SimdShuffle(Vector128 left, Vector128 utf16Vector) // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data. return zeroIsAscii != Vector512.Zero; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector128 ShuffleUnsafe(Vector128 vector, Vector128 indices) - { - if (Ssse3.IsSupported) - { - return Ssse3.Shuffle(vector, indices); - } - - if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.VectorTableLookup(vector, indices); - } - - if (PackedSimd.IsSupported) - { - return PackedSimd.Swizzle(vector, indices); - } - - return Vector128.Shuffle(vector, indices); - } #endif [DoesNotReturn] diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs index bd6052465590aa..65429998ab5912 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs @@ -22,7 +22,12 @@ namespace System.Diagnostics.CodeAnalysis AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] - public sealed class ExperimentalAttribute : Attribute +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class ExperimentalAttribute : Attribute { /// /// Initializes a new instance of the class, specifying the ID that the compiler will use diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 7eba0654cf71c1..cae62dc6eb8894 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -5822,7 +5822,7 @@ private static bool TryWrite(Span destination, IForma public ref struct SpanSplitEnumerator where T : IEquatable { /// The input span being split. - private readonly ReadOnlySpan _span; + private readonly ReadOnlySpan _source; /// A single separator to use when is . private readonly T _separator = default!; @@ -5836,25 +5836,29 @@ private static bool TryWrite(Span destination, IForma /// Mode that dictates how the instance was configured and how its fields should be used in . private SpanSplitEnumeratorMode _splitMode; - /// The inclusive starting index in of the current range. + /// The inclusive starting index in of the current range. private int _startCurrent = 0; - /// The exclusive ending index in of the current range. + /// The exclusive ending index in of the current range. private int _endCurrent = 0; - /// The index in from which the next separator search should start. + /// The index in from which the next separator search should start. private int _startNext = 0; /// Gets an enumerator that allows for iteration over the split span. /// Returns a that can be used to iterate over the split span. public SpanSplitEnumerator GetEnumerator() => this; + /// Gets the source span being enumerated. + /// Returns the that was provided when creating this enumerator. + public readonly ReadOnlySpan Source => _source; + /// Gets the current element of the enumeration. /// Returns a instance that indicates the bounds of the current element withing the source span. public Range Current => new Range(_startCurrent, _endCurrent); /// Initializes the enumerator for . - internal SpanSplitEnumerator(ReadOnlySpan span, SearchValues searchValues) + internal SpanSplitEnumerator(ReadOnlySpan source, SearchValues searchValues) { - _span = span; + _source = source; _splitMode = SpanSplitEnumeratorMode.SearchValues; _searchValues = searchValues; } @@ -5865,9 +5869,9 @@ internal SpanSplitEnumerator(ReadOnlySpan span, SearchValues searchValues) /// it will instead use with a cached /// for all whitespace characters. /// - internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separators) + internal SpanSplitEnumerator(ReadOnlySpan source, ReadOnlySpan separators) { - _span = span; + _source = source; if (typeof(T) == typeof(char) && separators.Length == 0) { _searchValues = Unsafe.As>(string.SearchValuesStorage.WhiteSpaceChars); @@ -5882,11 +5886,11 @@ internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separators) /// Initializes the enumerator for (or if the separator is empty). /// must be true. - internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separator, bool treatAsSingleSeparator) + internal SpanSplitEnumerator(ReadOnlySpan source, ReadOnlySpan separator, bool treatAsSingleSeparator) { Debug.Assert(treatAsSingleSeparator, "Should only ever be called as true; exists to differentiate from separators overload"); - _span = span; + _source = source; _separatorBuffer = separator; _splitMode = separator.Length == 0 ? SpanSplitEnumeratorMode.EmptySequence : @@ -5894,9 +5898,9 @@ internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separator, bo } /// Initializes the enumerator for . - internal SpanSplitEnumerator(ReadOnlySpan span, T separator) + internal SpanSplitEnumerator(ReadOnlySpan source, T separator) { - _span = span; + _source = source; _separator = separator; _splitMode = SpanSplitEnumeratorMode.SingleElement; } @@ -5915,17 +5919,17 @@ public bool MoveNext() return false; case SpanSplitEnumeratorMode.SingleElement: - separatorIndex = _span.Slice(_startNext).IndexOf(_separator); + separatorIndex = _source.Slice(_startNext).IndexOf(_separator); separatorLength = 1; break; case SpanSplitEnumeratorMode.Any: - separatorIndex = _span.Slice(_startNext).IndexOfAny(_separatorBuffer); + separatorIndex = _source.Slice(_startNext).IndexOfAny(_separatorBuffer); separatorLength = 1; break; case SpanSplitEnumeratorMode.Sequence: - separatorIndex = _span.Slice(_startNext).IndexOf(_separatorBuffer); + separatorIndex = _source.Slice(_startNext).IndexOf(_separatorBuffer); separatorLength = _separatorBuffer.Length; break; @@ -5936,7 +5940,7 @@ public bool MoveNext() default: Debug.Assert(_splitMode == SpanSplitEnumeratorMode.SearchValues, $"Unknown split mode: {_splitMode}"); - separatorIndex = _span.Slice(_startNext).IndexOfAny(_searchValues); + separatorIndex = _source.Slice(_startNext).IndexOfAny(_searchValues); separatorLength = 1; break; } @@ -5949,7 +5953,7 @@ public bool MoveNext() } else { - _startNext = _endCurrent = _span.Length; + _startNext = _endCurrent = _source.Length; // Set _splitMode to None so that subsequent MoveNext calls will return false. _splitMode = SpanSplitEnumeratorMode.None; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs index 1ef9923364e096..9c86b4d74457c0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs @@ -76,8 +76,6 @@ public override string ToString() return vsb.ToString(); } - public override int GetHashCode() => base.GetHashCode(); - public override bool Equals(object? obj) => obj == (object)this; #endregion #region Public Members diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 11c0a7e113dda0..ba7d0fc99e0b00 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -3036,13 +3036,99 @@ internal static Vector128 ShiftLeft(Vector128 vector, Vector128
    ShiftRightLogical(Vector128 vector, int shiftCount) => vector >>> shiftCount; +#if !MONO + // These fallback methods only exist so that ShuffleNative has the same behaviour when called directly or via + // reflection - reflecting into internal runtime methods is not supported, so we don't worry about others + // reflecting into these. TODO: figure out if this can be solved in a nicer way. + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector128 ShuffleNativeFallback(Vector128 vector, Vector128 indices) + { + return Shuffle(vector, indices); + } +#endif + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . /// A new vector containing the values from selected by the given . [Intrinsic] +#if MONO + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif public static Vector128 Shuffle(Vector128 vector, Vector128 indices) { +#if MONO + if (AdvSimd.Arm64.IsSupported) + { + return AdvSimd.Arm64.VectorTableLookup(vector, indices); + } + + if (PackedSimd.IsSupported) + { + return PackedSimd.Swizzle(vector, indices); + } + + return ShuffleFallback(vector, indices); + } + + private static Vector128 ShuffleFallback(Vector128 vector, Vector128 indices) + { +#endif Unsafe.SkipInit(out Vector128 result); for (int index = 0; index < Vector128.Count; index++) @@ -3066,8 +3152,28 @@ public static Vector128 Shuffle(Vector128 vector, Vector128 in /// A new vector containing the values from selected by the given . [Intrinsic] [CLSCompliant(false)] +#if MONO + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif public static Vector128 Shuffle(Vector128 vector, Vector128 indices) { +#if MONO + if (AdvSimd.Arm64.IsSupported) + { + return AdvSimd.Arm64.VectorTableLookup(vector, indices); + } + + if (PackedSimd.IsSupported) + { + return PackedSimd.Swizzle(vector, indices); + } + + return ShuffleFallback(vector, indices); + } + + private static Vector128 ShuffleFallback(Vector128 vector, Vector128 indices) + { +#endif Unsafe.SkipInit(out Vector128 result); for (int index = 0; index < Vector128.Count; index++) @@ -3090,32 +3196,52 @@ public static Vector128 Shuffle(Vector128 vector, Vector128 /// The input vector from which values are selected. /// The per-element indices used to select a value from . /// A new vector containing the values from selected by the given . - /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. - /// On hardware with support, indices are treated as modulo 16, and if the high bit is set, the result will be set to 0 for that element. - /// On hardware with or support, this method behaves the same as Shuffle. + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(Ssse3))] - [CompExactlyDependsOn(typeof(AdvSimd))] - [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] - [CompExactlyDependsOn(typeof(PackedSimd))] - internal static Vector128 ShuffleUnsafe(Vector128 vector, Vector128 indices) +#endif + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else if (Ssse3.IsSupported) { return Ssse3.Shuffle(vector, indices); } - if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.VectorTableLookup(vector, indices); - } + return Shuffle(vector, indices); +#endif + } - if (PackedSimd.IsSupported) + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CompExactlyDependsOn(typeof(Ssse3))] +#endif + [CLSCompliant(false)] + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + if (Ssse3.IsSupported) { - return PackedSimd.Swizzle(vector, indices); + return Ssse3.Shuffle(vector, indices); } return Shuffle(vector, indices); +#endif } /// Creates a new vector by selecting values from an input vector using a set of indices. @@ -3167,6 +3293,45 @@ public static Vector128 Shuffle(Vector128 vector, Vector128Creates a new vector by selecting values from an input vector using a set of indices.
+ /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3240,6 +3405,64 @@ public static Vector128 Shuffle(Vector128 vector, Vector128 i return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3313,6 +3536,64 @@ public static Vector128 Shuffle(Vector128 vector, Vector128Creates a new vector by selecting values from an input vector using a set of indices.
+ /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 1]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 1]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 1]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector128 ShuffleNative(Vector128 vector, Vector128 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Sin(Vector128 vector) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 56cb30e7bf4bea..fd6e96bb18f2ba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -276,12 +276,19 @@ public static Vector256 As(this Vector256 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 AsVector256(this Vector value) { - Debug.Assert(Vector256.Count >= Vector.Count); ThrowHelper.ThrowForUnsupportedIntrinsicsVector256BaseType(); - Vector256 result = default; - Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); - return result; + if (Vector.Count >= Vector256.Count) + { + ref byte address = ref Unsafe.As, byte>(ref value); + return Unsafe.ReadUnaligned>(ref address); + } + else + { + Vector256 result = default; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } } /// Reinterprets a as a new . @@ -293,11 +300,19 @@ public static Vector256 AsVector256(this Vector value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector AsVector(this Vector256 value) { - Debug.Assert(Vector256.Count >= Vector.Count); ThrowHelper.ThrowForUnsupportedIntrinsicsVector256BaseType(); - ref byte address = ref Unsafe.As, byte>(ref value); - return Unsafe.ReadUnaligned>(ref address); + if (Vector256.Count >= Vector.Count) + { + ref byte address = ref Unsafe.As, byte>(ref value); + return Unsafe.ReadUnaligned>(ref address); + } + else + { + Vector result = default; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } } /// Computes the bitwise-and of two vectors. @@ -3125,6 +3140,72 @@ internal static Vector256 ShiftLeft(Vector256 vector, Vector256
    ShiftRightLogical(Vector256 vector, int shiftCount) => vector >>> shiftCount; +#if !MONO + // These fallback methods only exist so that ShuffleNative has the same behaviour when called directly or via + // reflection - reflecting into internal runtime methods is not supported, so we don't worry about others + // reflecting into these. TODO: figure out if this can be solved in a nicer way. + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector256 ShuffleNativeFallback(Vector256 vector, Vector256 indices) + { + return Shuffle(vector, indices); + } +#endif + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3174,6 +3255,47 @@ public static Vector256 Shuffle(Vector256 vector, Vector256 return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 31]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 31]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3223,6 +3345,45 @@ public static Vector256 Shuffle(Vector256 vector, Vector256Creates a new vector by selecting values from an input vector using a set of indices.
+ /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3296,6 +3457,64 @@ public static Vector256 Shuffle(Vector256 vector, Vector256 i return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3369,6 +3588,64 @@ public static Vector256 Shuffle(Vector256 vector, Vector256Creates a new vector by selecting values from an input vector using a set of indices.
+ /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector256 ShuffleNative(Vector256 vector, Vector256 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Sin(Vector256 vector) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index 2cdfba21cd61b9..c7bca739671e8d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -3166,6 +3166,72 @@ internal static Vector512 ShiftLeft(Vector512 vector, Vector512
    ShiftRightLogical(Vector512 vector, int shiftCount) => vector >>> shiftCount; +#if !MONO + // These fallback methods only exist so that ShuffleNative has the same behaviour when called directly or via + // reflection - reflecting into internal runtime methods is not supported, so we don't worry about others + // reflecting into these. TODO: figure out if this can be solved in a nicer way. + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector512 ShuffleNativeFallback(Vector512 vector, Vector512 indices) + { + return Shuffle(vector, indices); + } +#endif + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3215,6 +3281,47 @@ public static Vector512 Shuffle(Vector512 vector, Vector512 return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 63]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 63]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3264,6 +3371,45 @@ public static Vector512 Shuffle(Vector512 vector, Vector512Creates a new vector by selecting values from an input vector using a set of indices.
+ /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 31]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 31]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3337,6 +3483,64 @@ public static Vector512 Shuffle(Vector512 vector, Vector512 i return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 15]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3410,6 +3614,64 @@ public static Vector512 Shuffle(Vector512 vector, Vector512Creates a new vector by selecting values from an input vector using a set of indices.
+ /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector512 ShuffleNative(Vector512 vector, Vector512 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Sin(Vector512 vector) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index d7d17e8599933c..e0ae9bc4cc35b0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -3249,6 +3249,54 @@ internal static Vector64 ShiftLeft(Vector64 vector, Vector64 ShiftRightLogical(Vector64 vector, int shiftCount) => vector >>> shiftCount; +#if !MONO + // These fallback methods only exist so that ShuffleNative has the same behaviour when called directly or via + // reflection - reflecting into internal runtime methods is not supported, so we don't worry about others + // reflecting into these. TODO: figure out if this can be solved in a nicer way. + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } + + [Intrinsic] + internal static Vector64 ShuffleNativeFallback(Vector64 vector, Vector64 indices) + { + return Shuffle(vector, indices); + } +#endif + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3298,6 +3346,47 @@ public static Vector64 Shuffle(Vector64 vector, Vector64 in return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3347,6 +3436,45 @@ public static Vector64 Shuffle(Vector64 vector, Vector64 return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 3]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . @@ -3420,6 +3548,64 @@ public static Vector64 Shuffle(Vector64 vector, Vector64 indi return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 1]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 1]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 1]. +#if !MONO + [Intrinsic] +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Vector64 ShuffleNative(Vector64 vector, Vector64 indices) + { +#if !MONO + return ShuffleNativeFallback(vector, indices); +#else + return Shuffle(vector, indices); +#endif + } + internal static Vector64 Sin(Vector64 vector) where T : ITrigonometricFunctions { diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs index 2c1c19d8878315..7f8393f483179e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/IndexOfAnyAsciiSearcher.cs @@ -1135,7 +1135,7 @@ private static Vector128 IndexOfAnyLookupCore(Vector128< // We use a shuffle to look up potential matches for each byte based on its low nibble. // Since all values have a unique low nibble, there's at most one potential match per nibble. - Vector128 values = Vector128.ShuffleUnsafe(bitmapLookup, lowNibbles); + Vector128 values = SearchValues.ShuffleNativeModified(bitmapLookup, lowNibbles); // Compare potential matches with the source to rule out false positives that have a different high nibble. return Vector128.Equals(source, values); @@ -1157,10 +1157,10 @@ private static Vector128 IndexOfAnyLookupCore(Vector128< // The bitmapLookup represents a 8x16 table of bits, indicating whether a character is present in the needle. // Lookup the rows via the lower nibble and the column via the higher nibble. - Vector128 bitMask = Vector128.ShuffleUnsafe(bitmapLookup, lowNibbles); + Vector128 bitMask = SearchValues.ShuffleNativeModified(bitmapLookup, lowNibbles); // For values above 127, the high nibble will be above 7. We construct the positions vector for the shuffle such that those values map to 0. - Vector128 bitPositions = Vector128.ShuffleUnsafe(Vector128.Create(0x8040201008040201, 0).AsByte(), highNibbles); + Vector128 bitPositions = SearchValues.ShuffleNativeModified(Vector128.Create(0x8040201008040201, 0).AsByte(), highNibbles); return bitMask & bitPositions; } @@ -1212,10 +1212,10 @@ private static Vector128 IndexOfAnyLookup(Vector128 source Vector128 lowNibbles = source & Vector128.Create((byte)0xF); Vector128 highNibbles = source >>> 4; - Vector128 row0 = Vector128.ShuffleUnsafe(bitmapLookup0, lowNibbles); - Vector128 row1 = Vector128.ShuffleUnsafe(bitmapLookup1, lowNibbles); + Vector128 row0 = Vector128.ShuffleNative(bitmapLookup0, lowNibbles); + Vector128 row1 = Vector128.ShuffleNative(bitmapLookup1, lowNibbles); - Vector128 bitmask = Vector128.ShuffleUnsafe(Vector128.Create(0x8040201008040201).AsByte(), highNibbles); + Vector128 bitmask = Vector128.ShuffleNative(Vector128.Create(0x8040201008040201).AsByte(), highNibbles); Vector128 mask = Vector128.GreaterThan(highNibbles.AsSByte(), Vector128.Create((sbyte)0x7)).AsByte(); Vector128 bitsets = Vector128.ConditionalSelect(mask, row1, row0); diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs index 9b7117aff0c714..c17196c2e170d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs @@ -257,7 +257,7 @@ private static Vector128 IsCharBitNotSet(Vector128 charMapLower, Vec { Vector128 shifted = values >>> VectorizedIndexShift; - Vector128 bitPositions = Vector128.ShuffleUnsafe(Vector128.Create(0x8040201008040201).AsByte(), shifted); + Vector128 bitPositions = Vector128.ShuffleNative(Vector128.Create(0x8040201008040201).AsByte(), shifted); Vector128 index = values & Vector128.Create((byte)VectorizedIndexMask); Vector128 bitMask; @@ -268,8 +268,8 @@ private static Vector128 IsCharBitNotSet(Vector128 charMapLower, Vec } else { - Vector128 bitMaskLower = Vector128.ShuffleUnsafe(charMapLower, index); - Vector128 bitMaskUpper = Vector128.ShuffleUnsafe(charMapUpper, index - Vector128.Create((byte)16)); + Vector128 bitMaskLower = Vector128.ShuffleNative(charMapLower, index); + Vector128 bitMaskUpper = Vector128.ShuffleNative(charMapUpper, index - Vector128.Create((byte)16)); Vector128 mask = Vector128.GreaterThan(index, Vector128.Create((byte)15)); bitMask = Vector128.ConditionalSelect(mask, bitMaskUpper, bitMaskLower); } diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs index ab74934a19914a..73de2d970c626d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs @@ -3,7 +3,9 @@ using System.Diagnostics; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Wasm; using System.Runtime.Intrinsics.X86; @@ -292,5 +294,21 @@ internal interface IRuntimeConst { public static bool Value => false; } + + /// + /// Same as , except that we guarantee that is used when available. + /// Some logic in relies on this exact behavior (implicit AND 0xF, and zeroing when the high bit is set). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CompExactlyDependsOn(typeof(Ssse3))] + internal static Vector128 ShuffleNativeModified(Vector128 vector, Vector128 indices) + { + if (Ssse3.IsSupported) + { + return Ssse3.Shuffle(vector, indices); + } + + return Vector128.Shuffle(vector, indices); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyHelper.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyHelper.cs index 8818cdae61cef7..b73302a287eece 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/Helpers/TeddyHelper.cs @@ -306,7 +306,7 @@ private static (Vector512 Low, Vector512 High) GetNibbles(Vector512< [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] private static Vector128 Shuffle(Vector128 maskLow, Vector128 maskHigh, Vector128 low, Vector128 high) { - return Vector128.ShuffleUnsafe(maskLow, low) & Vector128.ShuffleUnsafe(maskHigh, high); + return SearchValues.ShuffleNativeModified(maskLow, low) & Vector128.ShuffleNative(maskHigh, high); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index fb8e18ac2d16b8..35b69944f883cc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -65,27 +65,48 @@ public static unsafe void Fill(ref T refData, nuint numElements, T value) { vector = Vector256.Create(vec128).AsVector(); } + else if (Vector.Count == 64) + { + vector = Vector512.Create(vec128).AsVector(); + } else { - Debug.Fail("Vector isn't 128 or 256 bits in size?"); + Debug.Fail("Vector is unexpected size."); goto CannotVectorize; } } else if (sizeof(T) == 32) { + Vector256 vec256 = Unsafe.As>(ref tmp); if (Vector.Count == 32) { - vector = Unsafe.As>(ref tmp).AsVector(); + vector = vec256.AsVector(); + } + else if (Vector.Count == 64) + { + vector = Vector512.Create(vec256).AsVector(); + } + else + { + Debug.Fail("Vector is unexpected size."); + goto CannotVectorize; + } + } + else if (sizeof(T) == 64) + { + if (Vector.Count == 64) + { + vector = Unsafe.As>(ref tmp).AsVector(); } else { - Debug.Fail("Vector isn't 256 bits in size?"); + Debug.Fail("Vector is unexpected size."); goto CannotVectorize; } } else { - Debug.Fail("Vector is greater than 256 bits in size?"); + Debug.Fail("Vector is greater than 512 bits in size?"); goto CannotVectorize; } diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index b2a8a6c4c65ea5..f9261106b34c73 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -539,7 +539,7 @@ public bool EndsWith(string value, StringComparison comparisonType) { ArgumentNullException.ThrowIfNull(value); - if ((object)this == (object)value) + if (ReferenceEquals(this, value)) { CheckStringComparison(comparisonType); return true; @@ -580,7 +580,7 @@ public bool EndsWith(string value, bool ignoreCase, CultureInfo? culture) { ArgumentNullException.ThrowIfNull(value); - if ((object)this == (object)value) + if (ReferenceEquals(this, value)) { return true; } @@ -1108,7 +1108,7 @@ public bool StartsWith(string value, StringComparison comparisonType) { ArgumentNullException.ThrowIfNull(value); - if ((object)this == (object)value) + if (ReferenceEquals(this, value)) { CheckStringComparison(comparisonType); return true; @@ -1158,7 +1158,7 @@ public bool StartsWith(string value, bool ignoreCase, CultureInfo? culture) { ArgumentNullException.ThrowIfNull(value); - if ((object)this == (object)value) + if (ReferenceEquals(this, value)) { return true; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs index ddd99cabab41f0..fb6ed68f5f9bc9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs @@ -10,16 +10,36 @@ namespace System.Threading { public partial class EventWaitHandle { - private void CreateEventCore(bool initialState, EventResetMode mode, string? name, out bool createdNew) + private void CreateEventCore(bool initialState, EventResetMode mode) { + ValidateMode(mode); + SafeWaitHandle = WaitSubsystem.NewEvent(initialState, mode); + } + +#pragma warning disable IDE0060 // Unused parameter + private void CreateEventCore( + bool initialState, + EventResetMode mode, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) + { + ValidateMode(mode); + if (name != null) + { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); + } SafeWaitHandle = WaitSubsystem.NewEvent(initialState, mode); createdNew = true; } +#pragma warning restore IDE0060 - private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out EventWaitHandle? result) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs index bc41f1bde322e5..5f29df0466955e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs @@ -11,46 +11,131 @@ public partial class EventWaitHandle { private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.EVENT_MODIFY_STATE; +#if TARGET_WINDOWS + // Can't use MAXIMUM_ALLOWED in an access control entry (ACE) + private const int CurrentUserOnlyAceRights = + Interop.Kernel32.STANDARD_RIGHTS_REQUIRED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.EVENT_MODIFY_STATE; +#endif + private EventWaitHandle(SafeWaitHandle handle) { SafeWaitHandle = handle; } - private void CreateEventCore(bool initialState, EventResetMode mode, string? name, out bool createdNew) + private unsafe void CreateEventCore(bool initialState, EventResetMode mode) + { + ValidateMode(mode); + + uint flags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0; + if (mode == EventResetMode.ManualReset) + flags |= Interop.Kernel32.CREATE_EVENT_MANUAL_RESET; + SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(lpSecurityAttributes: 0, name: null, flags, AccessRights); + if (handle.IsInvalid) + { + int errorCode = Marshal.GetLastPInvokeError(); + handle.SetHandleAsInvalid(); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + + SafeWaitHandle = handle; + } + + private unsafe void CreateEventCore( + bool initialState, + EventResetMode mode, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) { -#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI + ValidateMode(mode); + +#if !TARGET_WINDOWS if (name != null) + { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); + } #endif - uint eventFlags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0; - if (mode == EventResetMode.ManualReset) - eventFlags |= (uint)Interop.Kernel32.CREATE_EVENT_MANUAL_RESET; - SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(IntPtr.Zero, name, eventFlags, AccessRights); + void* securityAttributesPtr = null; + SafeWaitHandle handle; + int errorCode; +#if TARGET_WINDOWS + Thread.CurrentUserSecurityDescriptorInfo securityDescriptorInfo = default; + Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default; + if (!string.IsNullOrEmpty(name) && options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + if (options.CurrentUserOnly) + { + securityDescriptorInfo = new(CurrentUserOnlyAceRights); + securityAttributes.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor; + securityAttributesPtr = &securityAttributes; + } + } - int errorCode = Marshal.GetLastPInvokeError(); - if (handle.IsInvalid) + using (securityDescriptorInfo) { - handle.SetHandleAsInvalid(); - if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) - throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); +#endif + uint eventFlags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0; + if (mode == EventResetMode.ManualReset) + eventFlags |= Interop.Kernel32.CREATE_EVENT_MANUAL_RESET; + handle = Interop.Kernel32.CreateEventEx((nint)securityAttributesPtr, name, eventFlags, AccessRights); + errorCode = Marshal.GetLastPInvokeError(); + + if (handle.IsInvalid) + { + handle.SetHandleAsInvalid(); + if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); + + throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); + } +#if TARGET_WINDOWS - throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); + if (errorCode == Interop.Errors.ERROR_ALREADY_EXISTS && securityAttributesPtr != null) + { + try + { + if (!Thread.CurrentUserSecurityDescriptorInfo.IsSecurityDescriptorCompatible( + securityDescriptorInfo.TokenUser, + handle, + Interop.Kernel32.EVENT_MODIFY_STATE)) + { + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.NamedWaitHandles_ExistingObjectIncompatibleWithCurrentUserOnly, name)); + } + } + catch + { + handle.Dispose(); + throw; + } + } } +#endif + createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS; SafeWaitHandle = handle; } - private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out EventWaitHandle? result) { #if TARGET_WINDOWS ArgumentException.ThrowIfNullOrEmpty(name); - result = null; + if (options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + } + SafeWaitHandle myHandle = Interop.Kernel32.OpenEvent(AccessRights, false, name); if (myHandle.IsInvalid) { + result = null; int errorCode = Marshal.GetLastPInvokeError(); myHandle.Dispose(); @@ -64,6 +149,27 @@ private static OpenExistingResult OpenExistingWorker(string name, out EventWaitH throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } + + if (options.WasSpecified && options.CurrentUserOnly) + { + try + { + if (!Thread.CurrentUserSecurityDescriptorInfo.IsValidSecurityDescriptor( + myHandle, + Interop.Kernel32.EVENT_MODIFY_STATE)) + { + myHandle.Dispose(); + result = null; + return OpenExistingResult.ObjectIncompatibleWithCurrentUserOnly; + } + } + catch + { + myHandle.Dispose(); + throw; + } + } + result = new EventWaitHandle(myHandle); return OpenExistingResult.Success; #else diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs index f17eaddb5d132b..e1a1ab2962d684 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs @@ -10,28 +10,110 @@ namespace System.Threading { public partial class EventWaitHandle : WaitHandle { - public EventWaitHandle(bool initialState, EventResetMode mode) : - this(initialState, mode, null, out _) + public EventWaitHandle(bool initialState, EventResetMode mode) { + CreateEventCore(initialState, mode); } - public EventWaitHandle(bool initialState, EventResetMode mode, string? name) : - this(initialState, mode, name, out _) + /// + /// Creates a named or unnamed event, or opens a named event if a event with the name already exists. + /// + /// True to initially set the event to a signaled state; false otherwise. + /// Indicates whether the event resets automatically or manually. + /// + /// The name, if the event is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named event. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying event object. + /// + public EventWaitHandle(bool initialState, EventResetMode mode, string? name, NamedWaitHandleOptions options) { + CreateEventCore(initialState, mode, name, new(options), out _); + } + + public EventWaitHandle(bool initialState, EventResetMode mode, string? name) + { + CreateEventCore(initialState, mode, name, options: default, out _); + } + + /// + /// Creates a named or unnamed event, or opens a named event if a event with the name already exists. + /// + /// True to initially set the event to a signaled state; false otherwise. + /// Indicates whether the event resets automatically or manually. + /// + /// The name, if the event is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named event. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying event object. + /// + /// + /// True if the event was created; false if an existing named event was opened. + /// + public EventWaitHandle(bool initialState, EventResetMode mode, string? name, NamedWaitHandleOptions options, out bool createdNew) + { + CreateEventCore(initialState, mode, name, new(options), out createdNew); } public EventWaitHandle(bool initialState, EventResetMode mode, string? name, out bool createdNew) + { + CreateEventCore(initialState, mode, name, options: default, out createdNew); + } + + private static void ValidateMode(EventResetMode mode) { if (mode != EventResetMode.AutoReset && mode != EventResetMode.ManualReset) + { throw new ArgumentException(SR.Argument_InvalidFlag, nameof(mode)); + } + } + + /// + /// Opens an existing named event. + /// + /// The name of the event to be shared with other processes. + /// + /// Options for the named event. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying event object. + /// + /// An object that represents the named event. + [SupportedOSPlatform("windows")] + public static EventWaitHandle OpenExisting(string name, NamedWaitHandleOptions options) + { + OpenExistingResult openExistingResult = OpenExistingWorker(name, new(options), out EventWaitHandle? result); + if (openExistingResult != OpenExistingResult.Success) + { + ThrowForOpenExistingFailure(openExistingResult, name); + } - CreateEventCore(initialState, mode, name, out createdNew); + Debug.Assert(result != null, "result should be non-null on success"); + return result; } [SupportedOSPlatform("windows")] public static EventWaitHandle OpenExisting(string name) { - switch (OpenExistingWorker(name, out EventWaitHandle? result)) + OpenExistingResult openExistingResult = OpenExistingWorker(name, options: default, out EventWaitHandle? result); + if (openExistingResult != OpenExistingResult.Success) + { + ThrowForOpenExistingFailure(openExistingResult, name); + } + + Debug.Assert(result != null, "result should be non-null on success"); + return result; + } + + [DoesNotReturn] + private static void ThrowForOpenExistingFailure(OpenExistingResult openExistingResult, string name) + { + Debug.Assert(openExistingResult != OpenExistingResult.Success); + + switch (openExistingResult) { case OpenExistingResult.NameNotFound: throw new WaitHandleCannotBeOpenedException(); @@ -40,13 +122,30 @@ public static EventWaitHandle OpenExisting(string name) case OpenExistingResult.PathNotFound: throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name)); default: - Debug.Assert(result != null, "result should be non-null on success"); - return result; + Debug.Assert(openExistingResult == OpenExistingResult.ObjectIncompatibleWithCurrentUserOnly); + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.NamedWaitHandles_ExistingObjectIncompatibleWithCurrentUserOnly, name)); } } + /// + /// Tries to open an existing named event and returns a value indicating whether it was successful. + /// + /// The name of the event to be shared with other processes. + /// + /// Options for the named event. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying event object. + /// + /// + /// An object that represents the named event if the method returns true; otherwise, null. + /// + /// True if the named event was opened successfully; otherwise, false. + [SupportedOSPlatform("windows")] + public static bool TryOpenExisting(string name, NamedWaitHandleOptions options, [NotNullWhen(true)] out EventWaitHandle? result) => + OpenExistingWorker(name, new(options), out result!) == OpenExistingResult.Success; + [SupportedOSPlatform("windows")] public static bool TryOpenExisting(string name, [NotNullWhen(true)] out EventWaitHandle? result) => - OpenExistingWorker(name, out result!) == OpenExistingResult.Success; + OpenExistingWorker(name, options: default, out result!) == OpenExistingResult.Success; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs index 12bce9b1aa44e1..4ee0c6c7000246 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs @@ -10,10 +10,18 @@ namespace System.Threading { public sealed partial class Mutex { - private void CreateMutexCore(bool initiallyOwned, string? name, out bool createdNew) + private void CreateMutexCore(bool initiallyOwned) => SafeWaitHandle = WaitSubsystem.NewMutex(initiallyOwned); + + private void CreateMutexCore( + bool initiallyOwned, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) { - if (name != null) + if (!string.IsNullOrEmpty(name)) { + name = BuildNameForOptions(name, options); + SafeWaitHandle? safeWaitHandle = WaitSubsystem.CreateNamedMutex(initiallyOwned, name, out createdNew); if (safeWaitHandle == null) { @@ -27,15 +35,41 @@ private void CreateMutexCore(bool initiallyOwned, string? name, out bool created createdNew = true; } - private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out Mutex? result) { ArgumentException.ThrowIfNullOrEmpty(name); + name = BuildNameForOptions(name, options); + OpenExistingResult status = WaitSubsystem.OpenNamedMutex(name, out SafeWaitHandle? safeWaitHandle); result = status == OpenExistingResult.Success ? new Mutex(safeWaitHandle!) : null; return status; } + private static string BuildNameForOptions(string name, NamedWaitHandleOptionsInternal options) + { + if (options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + } + + if (name.StartsWith(NamedWaitHandleOptionsInternal.CurrentSessionPrefix) && + name.Length > NamedWaitHandleOptionsInternal.CurrentSessionPrefix.Length) + { + name = name.Substring(NamedWaitHandleOptionsInternal.CurrentSessionPrefix.Length); + } + + if (options.WasSpecified && options.CurrentUserOnly) + { + name = @"User\" + name; + } + + return name; + } + public void ReleaseMutex() { // The field value is modifiable via the public property, save it locally diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs index 6c5a6a38da21e8..be9969806a49f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs @@ -15,30 +15,98 @@ public sealed partial class Mutex : WaitHandle private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.MUTEX_MODIFY_STATE; - private void CreateMutexCore(bool initiallyOwned, string? name, out bool createdNew) + // Can't use MAXIMUM_ALLOWED in an access control entry (ACE) + private const int CurrentUserOnlyAceRights = + Interop.Kernel32.STANDARD_RIGHTS_REQUIRED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.MUTEX_MODIFY_STATE; + + private void CreateMutexCore(bool initiallyOwned) { - uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0; - SafeWaitHandle mutexHandle = Interop.Kernel32.CreateMutexEx(IntPtr.Zero, name, mutexFlags, AccessRights); - int errorCode = Marshal.GetLastPInvokeError(); + uint flags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0; + SafeWaitHandle handle = Interop.Kernel32.CreateMutexEx(lpMutexAttributes: 0, name: null, flags, AccessRights); + if (handle.IsInvalid) + { + int errorCode = Marshal.GetLastPInvokeError(); + handle.SetHandleAsInvalid(); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + + SafeWaitHandle = handle; + } - if (mutexHandle.IsInvalid) + private unsafe void CreateMutexCore( + bool initiallyOwned, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) + { + Thread.CurrentUserSecurityDescriptorInfo securityDescriptorInfo = default; + Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default; + Interop.Kernel32.SECURITY_ATTRIBUTES* securityAttributesPtr = null; + if (!string.IsNullOrEmpty(name) && options.WasSpecified) { - mutexHandle.SetHandleAsInvalid(); - if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) - throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); + name = options.GetNameWithSessionPrefix(name); + if (options.CurrentUserOnly) + { + securityDescriptorInfo = new(CurrentUserOnlyAceRights); + securityAttributes.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor; + securityAttributesPtr = &securityAttributes; + } + } - throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); + SafeWaitHandle mutexHandle; + int errorCode; + using (securityDescriptorInfo) + { + uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0; + mutexHandle = Interop.Kernel32.CreateMutexEx((nint)securityAttributesPtr, name, mutexFlags, AccessRights); + errorCode = Marshal.GetLastPInvokeError(); + + if (mutexHandle.IsInvalid) + { + mutexHandle.SetHandleAsInvalid(); + if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); + + throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); + } + + if (errorCode == Interop.Errors.ERROR_ALREADY_EXISTS && securityAttributesPtr != null) + { + try + { + if (!Thread.CurrentUserSecurityDescriptorInfo.IsSecurityDescriptorCompatible( + securityDescriptorInfo.TokenUser, + mutexHandle, + Interop.Kernel32.MUTEX_MODIFY_STATE)) + { + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.NamedWaitHandles_ExistingObjectIncompatibleWithCurrentUserOnly, name)); + } + } + catch + { + mutexHandle.Dispose(); + throw; + } + } } createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS; SafeWaitHandle = mutexHandle; } - private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out Mutex? result) { ArgumentException.ThrowIfNullOrEmpty(name); - result = null; + if (options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + } + // To allow users to view & edit the ACL's, call OpenMutex // with parameters to allow us to view & edit the ACL. This will // fail if we don't have permission to view or edit the ACL's. @@ -47,6 +115,7 @@ private static OpenExistingResult OpenExistingWorker(string name, out Mutex? res if (myHandle.IsInvalid) { + result = null; int errorCode = Marshal.GetLastPInvokeError(); myHandle.Dispose(); @@ -61,6 +130,26 @@ private static OpenExistingResult OpenExistingWorker(string name, out Mutex? res throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } + if (options.WasSpecified && options.CurrentUserOnly) + { + try + { + if (!Thread.CurrentUserSecurityDescriptorInfo.IsValidSecurityDescriptor( + myHandle, + Interop.Kernel32.MUTEX_MODIFY_STATE)) + { + myHandle.Dispose(); + result = null; + return OpenExistingResult.ObjectIncompatibleWithCurrentUserOnly; + } + } + catch + { + myHandle.Dispose(); + throw; + } + } + result = new Mutex(myHandle); return OpenExistingResult.Success; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.cs index d2a945fd37eba0..8e28943d2a284f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.cs @@ -13,24 +13,81 @@ namespace System.Threading ///
public sealed partial class Mutex : WaitHandle { + /// + /// Creates a named or unnamed mutex, or opens a named mutex if a mutex with the name already exists. + /// + /// + /// True to acquire the mutex on the calling thread if it's created; otherwise, false. + /// + /// + /// The name, if the mutex is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named mutex. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying mutex object. + /// + /// + /// True if the mutex was created; false if an existing named mutex was opened. + /// + public Mutex(bool initiallyOwned, string? name, NamedWaitHandleOptions options, out bool createdNew) + { + CreateMutexCore(initiallyOwned, name, new(options), out createdNew); + } + public Mutex(bool initiallyOwned, string? name, out bool createdNew) { - CreateMutexCore(initiallyOwned, name, out createdNew); + CreateMutexCore(initiallyOwned, name, options: default, out createdNew); + } + + /// + /// Creates a named or unnamed mutex, or opens a named mutex if a mutex with the name already exists. + /// + /// + /// True to acquire the mutex on the calling thread if it's created; otherwise, false. + /// + /// + /// The name, if the mutex is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named mutex. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying mutex object. + /// + public Mutex(bool initiallyOwned, string? name, NamedWaitHandleOptions options) + { + CreateMutexCore(initiallyOwned, name, new(options), createdNew: out _); } public Mutex(bool initiallyOwned, string? name) { - CreateMutexCore(initiallyOwned, name, out _); + CreateMutexCore(initiallyOwned, name, options: default, createdNew: out _); + } + + /// + /// Creates a named or unnamed mutex, or opens a named mutex if a mutex with the name already exists. + /// + /// + /// The name, if the mutex is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named mutex. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying mutex object. + /// + public Mutex(string? name, NamedWaitHandleOptions options) + { + CreateMutexCore(initiallyOwned: false, name, new(options), createdNew: out _); } public Mutex(bool initiallyOwned) { - CreateMutexCore(initiallyOwned, null, out _); + CreateMutexCore(initiallyOwned); } public Mutex() { - CreateMutexCore(false, null, out _); + CreateMutexCore(initiallyOwned: false); } private Mutex(SafeWaitHandle handle) @@ -38,9 +95,46 @@ private Mutex(SafeWaitHandle handle) SafeWaitHandle = handle; } + /// + /// Opens an existing named mutex. + /// + /// The name of the mutex to be shared with other processes. + /// + /// Options for the named mutex. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying mutex object. + /// + /// An object that represents the named mutex. + public static Mutex OpenExisting(string name, NamedWaitHandleOptions options) + { + OpenExistingResult openExistingResult = OpenExistingWorker(name, new(options), out Mutex? result); + if (openExistingResult != OpenExistingResult.Success) + { + ThrowForOpenExistingFailure(openExistingResult, name); + } + + Debug.Assert(result != null, "result should be non-null on success"); + return result; + } + public static Mutex OpenExisting(string name) { - switch (OpenExistingWorker(name, out Mutex? result)) + OpenExistingResult openExistingResult = OpenExistingWorker(name, options: default, out Mutex? result); + if (openExistingResult != OpenExistingResult.Success) + { + ThrowForOpenExistingFailure(openExistingResult, name); + } + + Debug.Assert(result != null, "result should be non-null on success"); + return result; + } + + [DoesNotReturn] + private static void ThrowForOpenExistingFailure(OpenExistingResult openExistingResult, string name) + { + Debug.Assert(openExistingResult != OpenExistingResult.Success); + + switch (openExistingResult) { case OpenExistingResult.NameNotFound: throw new WaitHandleCannotBeOpenedException(); @@ -48,14 +142,29 @@ public static Mutex OpenExisting(string name) throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); case OpenExistingResult.PathNotFound: throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name)); - default: - Debug.Assert(result != null, "result should be non-null on success"); - return result; + Debug.Assert(openExistingResult == OpenExistingResult.ObjectIncompatibleWithCurrentUserOnly); + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.NamedWaitHandles_ExistingObjectIncompatibleWithCurrentUserOnly, name)); } } + /// + /// Tries to open an existing named mutex and returns a value indicating whether it was successful. + /// + /// The name of the mutex to be shared with other processes. + /// + /// Options for the named mutex. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying mutex object. + /// + /// + /// An object that represents the named mutex if the method returns true; otherwise, null. + /// + /// True if the named mutex was opened successfully; otherwise, false. + public static bool TryOpenExisting(string name, NamedWaitHandleOptions options, [NotNullWhen(true)] out Mutex? result) => + OpenExistingWorker(name, new(options), out result!) == OpenExistingResult.Success; + public static bool TryOpenExisting(string name, [NotNullWhen(true)] out Mutex? result) => - OpenExistingWorker(name, out result!) == OpenExistingResult.Success; + OpenExistingWorker(name, options: default, out result!) == OpenExistingResult.Success; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/NamedWaitHandleOptions.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/NamedWaitHandleOptions.cs new file mode 100644 index 00000000000000..8fbee124b55145 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/NamedWaitHandleOptions.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System.Threading +{ + /// + /// Represents a set of options for named synchronization objects that are wait handles and can be shared between processes, + /// such as 'Mutex', 'Semaphore', and 'EventWaitHandle'. + /// + public struct NamedWaitHandleOptions + { + private bool _notCurrentUserOnly; + private bool _notCurrentSessionOnly; + + /// + /// Indicates whether the named synchronization object should be limited in access to the current user. + /// + /// + /// The default value is true. + /// + /// If the option is true when creating a named synchronization object, the object is limited in access to the calling + /// user. If the option is true when opening an existing named synchronization object, the object's access controls are + /// verified for the calling user. + /// + /// If the option is false when creating a named synchronization object, the object is not limited in access to a user. + /// + /// On Unix-like operating systems, each user has namespaces for the object's name that are used when the option is + /// true. These user-scoped namespaces are distinct from user-scoped namespaces for other users, and also distinct from + /// namespaces used when the option is false. + /// + public bool CurrentUserOnly + { + get => !_notCurrentUserOnly; + set => _notCurrentUserOnly = !value; + } + + /// + /// Indicates whether the named synchronization object is intended to be used only within the current session. + /// + /// + /// The default value is true. + /// + /// Each session has namespaces for the object's name that are used when the option is true. These session-scoped + /// namespaces are distinct from session-scoped namespaces for other sessions, and also distinct from namespaces used + /// when the option is false. + /// + /// If the option is true when creating a named synchronization object, the object is limited in scope to the current + /// session, and can't be opened by processes running in different sessions. + /// + /// On Windows, a session is a Terminal Services session. On Unix-like operating systems, a session is typically a shell + /// session, where each shell gets its own session in which processes started from the shell run. + /// + public bool CurrentSessionOnly + { + get => !_notCurrentSessionOnly; + set => _notCurrentSessionOnly = !value; + } + } + + // This is an internal struct used by named wait handle helpers to also track whether the options were specified in APIs + // that were used. Using the constructor indicates WasSpecified=true, and 'default' indicates WasSpecified=false. + internal readonly struct NamedWaitHandleOptionsInternal + { + public const string CurrentSessionPrefix = @"Local\"; + public const string AllSessionsPrefix = @"Global\"; + + private readonly NamedWaitHandleOptions _options; + private readonly bool _wasSpecified; + + public NamedWaitHandleOptionsInternal(NamedWaitHandleOptions options) + { + _options = options; + _wasSpecified = true; + } + + public bool CurrentUserOnly + { + get + { + Debug.Assert(WasSpecified); + return _options.CurrentUserOnly; + } + } + + public bool CurrentSessionOnly + { + get + { + Debug.Assert(WasSpecified); + return _options.CurrentSessionOnly; + } + } + + public bool WasSpecified => _wasSpecified; + + public string GetNameWithSessionPrefix(string name) + { + Debug.Assert(!string.IsNullOrEmpty(name)); + Debug.Assert(WasSpecified); + + bool hasPrefix = name.Contains('\\'); + if (!hasPrefix) + { + if (CurrentSessionOnly) + { +#if TARGET_WINDOWS + // Services use the global namespace by default, so always include a prefix on Windows + name = CurrentSessionPrefix + name; +#endif + } + else + { + name = AllSessionsPrefix + name; + } + + return name; + } + + // Verify that the prefix is compatible with the CurrentSessionOnly option. On Windows, when CurrentSessionOnly is + // false, any other prefix is permitted here, as a custom namespace can be created and used with a prefix. + + bool incompatible; + if (CurrentSessionOnly) + { + incompatible = !name.StartsWith(CurrentSessionPrefix, StringComparison.Ordinal); + } + else + { +#if TARGET_WINDOWS + incompatible = name.StartsWith(CurrentSessionPrefix, StringComparison.Ordinal); +#else + incompatible = !name.StartsWith(AllSessionsPrefix, StringComparison.Ordinal); +#endif + } + + if (incompatible) + { + throw new ArgumentException(SR.Format(SR.NamedWaitHandles_IncompatibleNamePrefix, name), nameof(name)); + } + + return name; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs index 4940acad545f5d..e68aaf516f65ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs @@ -10,8 +10,22 @@ namespace System.Threading { public sealed partial class Semaphore { - private void CreateSemaphoreCore(int initialCount, int maximumCount, string? name, out bool createdNew) + private void CreateSemaphoreCore(int initialCount, int maximumCount) { + ValidateArguments(initialCount, maximumCount); + SafeWaitHandle = WaitSubsystem.NewSemaphore(initialCount, maximumCount); + } + +#pragma warning disable IDE0060 // Unused parameter + private void CreateSemaphoreCore( + int initialCount, + int maximumCount, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) + { + ValidateArguments(initialCount, maximumCount); + if (name != null) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); @@ -20,8 +34,12 @@ private void CreateSemaphoreCore(int initialCount, int maximumCount, string? nam SafeWaitHandle = WaitSubsystem.NewSemaphore(initialCount, maximumCount); createdNew = true; } +#pragma warning restore IDE0060 - private static OpenExistingResult OpenExistingWorker(string name, out Semaphore? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out Semaphore? result) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs index adf4b94ec5c312..2e0d8b4eeae789 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; @@ -12,43 +11,138 @@ public sealed partial class Semaphore { private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.SEMAPHORE_MODIFY_STATE; +#if TARGET_WINDOWS + // Can't use MAXIMUM_ALLOWED in an access control entry (ACE) + private const int CurrentUserOnlyAceRights = + Interop.Kernel32.STANDARD_RIGHTS_REQUIRED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.SEMAPHORE_MODIFY_STATE; +#endif + private Semaphore(SafeWaitHandle handle) { SafeWaitHandle = handle; } - private void CreateSemaphoreCore(int initialCount, int maximumCount, string? name, out bool createdNew) + private void CreateSemaphoreCore(int initialCount, int maximumCount) { - Debug.Assert(initialCount >= 0); - Debug.Assert(maximumCount >= 1); - Debug.Assert(initialCount <= maximumCount); + ValidateArguments(initialCount, maximumCount); + + SafeWaitHandle handle = + Interop.Kernel32.CreateSemaphoreEx( + lpSecurityAttributes: 0, + initialCount, + maximumCount, + name: null, + flags: 0, + AccessRights); + if (handle.IsInvalid) + { + int errorCode = Marshal.GetLastPInvokeError(); + handle.SetHandleAsInvalid(); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } -#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI + SafeWaitHandle = handle; + } + + private unsafe void CreateSemaphoreCore( + int initialCount, + int maximumCount, + string? name, + NamedWaitHandleOptionsInternal options, + out bool createdNew) + { + ValidateArguments(initialCount, maximumCount); + +#if !TARGET_WINDOWS if (name != null) + { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); + } #endif - SafeWaitHandle myHandle = Interop.Kernel32.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights); - int errorCode = Marshal.GetLastPInvokeError(); - if (myHandle.IsInvalid) + void* securityAttributesPtr = null; + SafeWaitHandle myHandle; + int errorCode; +#if TARGET_WINDOWS + Thread.CurrentUserSecurityDescriptorInfo securityDescriptorInfo = default; + Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default; + if (!string.IsNullOrEmpty(name) && options.WasSpecified) { - myHandle.Dispose(); + name = options.GetNameWithSessionPrefix(name); + if (options.CurrentUserOnly) + { + securityDescriptorInfo = new(CurrentUserOnlyAceRights); + securityAttributes.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor; + securityAttributesPtr = &securityAttributes; + } + } - if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) - throw new WaitHandleCannotBeOpenedException( - SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); + using (securityDescriptorInfo) + { +#endif + myHandle = + Interop.Kernel32.CreateSemaphoreEx( + (nint)securityAttributesPtr, + initialCount, + maximumCount, + name, + flags: 0, + AccessRights); + errorCode = Marshal.GetLastPInvokeError(); + + if (myHandle.IsInvalid) + { + myHandle.SetHandleAsInvalid(); + + if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) + { + throw new WaitHandleCannotBeOpenedException( + SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); + } + + throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); + } +#if TARGET_WINDOWS - throw Win32Marshal.GetExceptionForLastWin32Error(); + if (errorCode == Interop.Errors.ERROR_ALREADY_EXISTS && securityAttributesPtr != null) + { + try + { + if (!Thread.CurrentUserSecurityDescriptorInfo.IsSecurityDescriptorCompatible( + securityDescriptorInfo.TokenUser, + myHandle, + Interop.Kernel32.SEMAPHORE_MODIFY_STATE)) + { + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.NamedWaitHandles_ExistingObjectIncompatibleWithCurrentUserOnly, name)); + } + } + catch + { + myHandle.Dispose(); + throw; + } + } } +#endif + createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS; this.SafeWaitHandle = myHandle; } - private static OpenExistingResult OpenExistingWorker(string name, out Semaphore? result) + private static OpenExistingResult OpenExistingWorker( + string name, + NamedWaitHandleOptionsInternal options, + out Semaphore? result) { #if TARGET_WINDOWS ArgumentException.ThrowIfNullOrEmpty(name); + if (options.WasSpecified) + { + name = options.GetNameWithSessionPrefix(name); + } + // Pass false to OpenSemaphore to prevent inheritedHandles SafeWaitHandle myHandle = Interop.Kernel32.OpenSemaphore(AccessRights, false, name); @@ -65,10 +159,31 @@ private static OpenExistingResult OpenExistingWorker(string name, out Semaphore? return OpenExistingResult.PathNotFound; if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) return OpenExistingResult.NameInvalid; + // this is for passed through NativeMethods Errors throw Win32Marshal.GetExceptionForLastWin32Error(); } + if (options.WasSpecified && options.CurrentUserOnly) + { + try + { + if (!Thread.CurrentUserSecurityDescriptorInfo.IsValidSecurityDescriptor( + myHandle, + Interop.Kernel32.SEMAPHORE_MODIFY_STATE)) + { + myHandle.Dispose(); + result = null; + return OpenExistingResult.ObjectIncompatibleWithCurrentUserOnly; + } + } + catch + { + myHandle.Dispose(); + throw; + } + } + result = new Semaphore(myHandle); return OpenExistingResult.Success; #else diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.cs index 39af9b9416ff95..fb709ceb299b74 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.cs @@ -12,28 +12,121 @@ public sealed partial class Semaphore : WaitHandle { // creates a nameless semaphore object // Win32 only takes maximum count of int.MaxValue - public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { } + public Semaphore(int initialCount, int maximumCount) + { + CreateSemaphoreCore(initialCount, maximumCount); + } + + /// + /// Creates a named or unnamed semaphore, or opens a named semaphore if a semaphore with the name already exists. + /// + /// + /// The initial number of requests for the semaphore that can be satisfied concurrently. + /// + /// + /// The maximum number of requests for the semaphore that can be satisfied concurrently. + /// + /// + /// The name, if the semaphore is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named semaphore. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying semaphore object. + /// + public Semaphore(int initialCount, int maximumCount, string? name, NamedWaitHandleOptions options) + { + CreateSemaphoreCore(initialCount, maximumCount, name, new(options), out _); + } + + public Semaphore(int initialCount, int maximumCount, string? name) + { + CreateSemaphoreCore(initialCount, maximumCount, name, options: default, out _); + } - public Semaphore(int initialCount, int maximumCount, string? name) : - this(initialCount, maximumCount, name, out _) + /// + /// Creates a named or unnamed semaphore, or opens a named semaphore if a semaphore with the name already exists. + /// + /// + /// The initial number of requests for the semaphore that can be satisfied concurrently. + /// + /// + /// The maximum number of requests for the semaphore that can be satisfied concurrently. + /// + /// + /// The name, if the semaphore is to be shared with other processes; otherwise, null or an empty string. + /// + /// + /// Options for the named semaphore. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying semaphore object. + /// + /// + /// True if the semaphore was created; false if an existing named semaphore was opened. + /// + public Semaphore(int initialCount, int maximumCount, string? name, NamedWaitHandleOptions options, out bool createdNew) { + CreateSemaphoreCore(initialCount, maximumCount, name, new(options), out createdNew); } public Semaphore(int initialCount, int maximumCount, string? name, out bool createdNew) + { + CreateSemaphoreCore(initialCount, maximumCount, name, options: default, out createdNew); + } + + private static void ValidateArguments(int initialCount, int maximumCount) { ArgumentOutOfRangeException.ThrowIfNegative(initialCount); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(maximumCount); if (initialCount > maximumCount) + { throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum); + } + } - CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew); + /// + /// Opens an existing named semaphore. + /// + /// The name of the semaphore to be shared with other processes. + /// + /// Options for the named semaphore. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying semaphore object. + /// + /// An object that represents the named semaphore. + [SupportedOSPlatform("windows")] + public static Semaphore OpenExisting(string name, NamedWaitHandleOptions options) + { + OpenExistingResult openExistingResult = OpenExistingWorker(name, new(options), out Semaphore? result); + if (openExistingResult != OpenExistingResult.Success) + { + ThrowForOpenExistingFailure(openExistingResult, name); + } + + Debug.Assert(result != null, "result should be non-null on success"); + return result; } [SupportedOSPlatform("windows")] public static Semaphore OpenExisting(string name) { - switch (OpenExistingWorker(name, out Semaphore? result)) + OpenExistingResult openExistingResult = OpenExistingWorker(name, options: default, out Semaphore? result); + if (openExistingResult != OpenExistingResult.Success) + { + ThrowForOpenExistingFailure(openExistingResult, name); + } + + Debug.Assert(result != null, "result should be non-null on success"); + return result; + } + + [DoesNotReturn] + private static void ThrowForOpenExistingFailure(OpenExistingResult openExistingResult, string name) + { + Debug.Assert(openExistingResult != OpenExistingResult.Success); + + switch (openExistingResult) { case OpenExistingResult.NameNotFound: throw new WaitHandleCannotBeOpenedException(); @@ -42,14 +135,31 @@ public static Semaphore OpenExisting(string name) case OpenExistingResult.PathNotFound: throw new IOException(SR.Format(SR.IO_PathNotFound_Path, name)); default: - Debug.Assert(result != null, "result should be non-null on success"); - return result; + Debug.Assert(openExistingResult == OpenExistingResult.ObjectIncompatibleWithCurrentUserOnly); + throw new WaitHandleCannotBeOpenedException(SR.Format(SR.NamedWaitHandles_ExistingObjectIncompatibleWithCurrentUserOnly, name)); } } + /// + /// Tries to open an existing named semaphore and returns a value indicating whether it was successful. + /// + /// The name of the semaphore to be shared with other processes. + /// + /// Options for the named semaphore. Defaulted options, such as when passing 'options: default' in C#, are + /// 'CurrentUserOnly = true' and 'CurrentSessionOnly = true'. For more information, see 'NamedWaitHandleOptions'. The + /// specified options may affect the namespace for the name, and access to the underlying semaphore object. + /// + /// + /// An object that represents the named semaphore if the method returns true; otherwise, null. + /// + /// True if the named semaphore was opened successfully; otherwise, false. + [SupportedOSPlatform("windows")] + public static bool TryOpenExisting(string name, NamedWaitHandleOptions options, [NotNullWhen(true)] out Semaphore? result) => + OpenExistingWorker(name, new(options), out result!) == OpenExistingResult.Success; + [SupportedOSPlatform("windows")] public static bool TryOpenExisting(string name, [NotNullWhen(true)] out Semaphore? result) => - OpenExistingWorker(name, out result!) == OpenExistingResult.Success; + OpenExistingWorker(name, options: default, out result!) == OpenExistingResult.Success; public int Release() => ReleaseCore(1); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Windows.cs index e4cb87cc894041..b9b9a0e16f9289 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Windows.cs @@ -1,10 +1,15 @@ // 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.Numerics; using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; namespace System.Threading @@ -27,5 +32,466 @@ internal static int GetCurrentProcessorNumber() Interop.Kernel32.GetCurrentProcessorNumberEx(out procNumber); return (procNumber.Group << 6) | procNumber.Number; } + + internal readonly ref struct CurrentUserSecurityDescriptorInfo + { + private readonly SafeTokenHandle _token; + private readonly SafeLocalAllocHandle _tokenUser; + private readonly SafeLocalAllocHandle _dacl; + private readonly SafeLocalAllocHandle _sacl; + private readonly SafeLocalAllocHandle _securityDescriptor; + + public SafeLocalAllocHandle TokenUser + { + get + { + Debug.Assert(_securityDescriptor is not null); + return _tokenUser; + } + } + + public nint SecurityDescriptor + { + get + { + Debug.Assert(_securityDescriptor is not null); + return _securityDescriptor.DangerousGetHandle(); + } + } + + public CurrentUserSecurityDescriptorInfo(int accessMask) + { + this = default; // zero-initialize first in case of exception + _token = OpenCurrentToken(); + try + { + _tokenUser = GetTokenUser(_token); + nint tokenUserSid = GetTokenUserSid(_tokenUser); + _dacl = CreateDacl(tokenUserSid, accessMask); + _sacl = CreateMandatoryLabelAceSacl(_token); + _securityDescriptor = CreateSecurityDescriptor(tokenUserSid, _dacl, _sacl); + } + catch + { + _securityDescriptor?.Dispose(); + _sacl?.Dispose(); + _dacl?.Dispose(); + _tokenUser?.Dispose(); + _token.Dispose(); + throw; + } + } + + public void Dispose() + { + if (_securityDescriptor is null) + { + return; + } + + _securityDescriptor.Dispose(); + _sacl.Dispose(); + _dacl.Dispose(); + _tokenUser.Dispose(); + _token.Dispose(); + } + + private static SafeTokenHandle OpenCurrentToken() + { + nint threadHandle = Interop.Kernel32.GetCurrentThread(); + if (Interop.Advapi32.OpenThreadToken( + threadHandle, + (int)Interop.Advapi32.TOKEN_ACCESS_LEVELS.Query, + OpenAsSelf: true, + out SafeTokenHandle token)) + { + return token; + } + + token.Dispose(); + if (Interop.Advapi32.OpenThreadToken( + threadHandle, + (int)Interop.Advapi32.TOKEN_ACCESS_LEVELS.Query, + OpenAsSelf: false, + out token)) + { + return token; + } + + token.Dispose(); + if (!Interop.Advapi32.OpenProcessToken( + Interop.Kernel32.GetCurrentProcess(), + (int)Interop.Advapi32.TOKEN_ACCESS_LEVELS.Query, + out token)) + { + int error = Marshal.GetLastPInvokeError(); + token.Dispose(); + ThrowExceptionForError(error); + } + + return token; + } + + private static SafeLocalAllocHandle GetTokenUser(SafeTokenHandle token) + { + // Get the buffer size needed for user info + Interop.Advapi32.GetTokenInformation( + token.DangerousGetHandle(), + (uint)Interop.Advapi32.TOKEN_INFORMATION_CLASS.TokenUser, + TokenInformation: 0, + TokenInformationLength: 0, + out uint tokenUserSize); + int error = Marshal.GetLastPInvokeError(); + if (error != Interop.Errors.ERROR_INSUFFICIENT_BUFFER) + { + ThrowExceptionForError(error); + } + + Debug.Assert((int)tokenUserSize > 0); + SafeLocalAllocHandle tokenUser = SafeLocalAllocHandle.LocalAlloc((int)tokenUserSize); + try + { + if (!Interop.Advapi32.GetTokenInformation( + token.DangerousGetHandle(), + (uint)Interop.Advapi32.TOKEN_INFORMATION_CLASS.TokenUser, + tokenUser.DangerousGetHandle(), + tokenUserSize, + out tokenUserSize)) + { + ThrowExceptionForLastError(); + } + + return tokenUser; + } + catch + { + tokenUser.Dispose(); + throw; + } + } + + private static nint GetTokenUserSid(SafeLocalAllocHandle tokenUser) => + tokenUser.Read(0); // TOKEN_USER.User.Sid + + private static unsafe SafeLocalAllocHandle CreateDacl(nint tokenUserSid, int userAccessMask) + { + // Create an SID for the BUILTIN\Administrators group + uint adminGroupSidSize = Interop.Advapi32.SECURITY_MAX_SID_SIZE; + byte* adminGroupSid = stackalloc byte[(int)adminGroupSidSize]; + if (!Interop.Advapi32.CreateWellKnownSid( + (int)Interop.Advapi32.WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, + domainSid: 0, + (nint)adminGroupSid, + ref adminGroupSidSize)) + { + ThrowExceptionForLastError(); + } + + Interop.Advapi32.EXPLICIT_ACCESS* ea = stackalloc Interop.Advapi32.EXPLICIT_ACCESS[2] { default, default }; + + // Allow the requested access rights for the token user + ea[0].grfAccessPermissions = userAccessMask; + ea[0].grfAccessMode = Interop.Advapi32.ACCESS_MODE.SET_ACCESS; + ea[0].grfInheritance = Interop.Advapi32.EXPLICIT_ACCESS_NO_INHERITANCE; + ea[0].Trustee.TrusteeForm = Interop.Advapi32.TRUSTEE_FORM.TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = Interop.Advapi32.TRUSTEE_TYPE.TRUSTEE_IS_USER; + ea[0].Trustee.ptstrName = tokenUserSid; + + // Allow READ_CONTROL for the BUILTIN\Administrators group to enable administrators to read object permissions + // using a tool like SysInternals accesschk + ea[1].grfAccessPermissions = Interop.Kernel32.READ_CONTROL; + ea[1].grfAccessMode = Interop.Advapi32.ACCESS_MODE.SET_ACCESS; + ea[1].grfInheritance = Interop.Advapi32.EXPLICIT_ACCESS_NO_INHERITANCE; + ea[1].Trustee.TrusteeForm = Interop.Advapi32.TRUSTEE_FORM.TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = Interop.Advapi32.TRUSTEE_TYPE.TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = (nint)adminGroupSid; + + int error = + Interop.Advapi32.SetEntriesInAcl(cCountOfExplicitEntries: 2, ea, OldAcl: 0, out SafeLocalAllocHandle dacl); + if (error != Interop.Errors.ERROR_SUCCESS) + { + dacl.Dispose(); + if (error == Interop.Errors.ERROR_PROC_NOT_FOUND) + { + // This error may result when the current token has reduced privileges due to other access restrictions + // during delay loading. Other ACL APIs result in access-denied in this case, which is more clear, so + // treat it as such. + error = Interop.Errors.ERROR_ACCESS_DENIED; + } + + ThrowExceptionForError(error); + } + + return dacl; + } + + private static unsafe SafeLocalAllocHandle CreateMandatoryLabelAceSacl(SafeTokenHandle token) + { + // By default, the system assigns a mandatory label of an appropriate integrity level with + // SYSTEM_MANDATORY_LABEL_NO_WRITE_UP to new objects, which means relevant lower-integrity processes cannot get + // write access to the object. This is not sufficient for named synchronization objects though, for named + // mutexes for instance, the SYNCHRONIZE access right is enough to acquire and release a named mutex, but it's + // not classified as write access. We need to explicitly assign a mandatory label that also has + // SYSTEM_MANDATORY_LABEL_NO_READ_UP to prevent relevant lower-integrity processes from operating on the object. + + // Get the token's integrity level + using SafeLocalAllocHandle tokenMandatoryLabel = GetTokenMandatoryLabel(token); + nint tokenIntegrityLevelSid = tokenMandatoryLabel.Read(0); // TOKEN_MANDATORY_LABEL.Label.Sid + uint tokenIntegrityLevel = GetIntegrityLevel(tokenIntegrityLevelSid); + + uint integrityLevelSidSize; + byte* integrityLevelSidBuffer = stackalloc byte[Interop.Advapi32.SECURITY_MAX_SID_SIZE]; + nint integrityLevelSid; + if (tokenIntegrityLevel >= Interop.Advapi32.SECURITY_MANDATORY_MEDIUM_RID) + { + // For Medium or higher token integrity levels, the default integrity level for new objects is Medium for + // interoperability, for instance when UAC is enabled, between elevated and unelevated processes running as + // an admin user, or in the presence of changes to UAC enablement. The goal is mainly to restrict processes + // running at integrity levels lower than Medium from interacting with objects at Medium or higher integrity + // levels. The default integrity level is retained here. + + // Create a SID for the Medium integrity level + integrityLevelSidSize = Interop.Advapi32.SECURITY_MAX_SID_SIZE; + if (!Interop.Advapi32.CreateWellKnownSid( + (int)Interop.Advapi32.WELL_KNOWN_SID_TYPE.WinMediumLabelSid, + domainSid: 0, + (nint)integrityLevelSidBuffer, + ref integrityLevelSidSize)) + { + ThrowExceptionForLastError(); + } + + integrityLevelSid = (nint)integrityLevelSidBuffer; + } + else + { + // For integrity levels less than Medium, just transfer the token's integrity level to the object. For + // instance, if the token's integrity level is greater than Low and less than Medium, it may be undesirable + // to allow a process with an integrity level of Low to interoperate with our objects. + integrityLevelSid = tokenIntegrityLevelSid; + integrityLevelSidSize = (uint)Interop.Advapi32.GetLengthSid(integrityLevelSid); + } + + Debug.Assert((int)integrityLevelSidSize > 0); + int saclSize = + sizeof(Interop.Advapi32.ACL) + + sizeof(Interop.Advapi32.ACE) - Interop.Advapi32.ACE.SizeOfSidPortionInAce + + (int)integrityLevelSidSize; + saclSize = (saclSize + 3) & ~3; // must be DWORD-aligned + SafeLocalAllocHandle sacl = SafeLocalAllocHandle.LocalAlloc(saclSize); + try + { + if (!Interop.Advapi32.InitializeAcl(sacl.DangerousGetHandle(), saclSize, Interop.Advapi32.ACL_REVISION)) + { + ThrowExceptionForLastError(); + } + + if (!Interop.Advapi32.AddMandatoryAce( + sacl.DangerousGetHandle(), + Interop.Advapi32.ACL_REVISION, + AceFlags: 0, + ( + Interop.Advapi32.SYSTEM_MANDATORY_LABEL_NO_WRITE_UP | + Interop.Advapi32.SYSTEM_MANDATORY_LABEL_NO_READ_UP + ), + integrityLevelSid)) + { + ThrowExceptionForLastError(); + } + + return sacl; + } + catch + { + sacl.Dispose(); + throw; + } + } + + private static SafeLocalAllocHandle GetTokenMandatoryLabel(SafeTokenHandle token) + { + // Get the buffer size needed for integrity level info + Interop.Advapi32.GetTokenInformation( + token.DangerousGetHandle(), + (uint)Interop.Advapi32.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, + TokenInformation: 0, + TokenInformationLength: 0, + out uint tokenMandatoryLabelSize); + int error = Marshal.GetLastPInvokeError(); + if (error != Interop.Errors.ERROR_INSUFFICIENT_BUFFER) + { + ThrowExceptionForError(error); + } + + Debug.Assert((int)tokenMandatoryLabelSize > 0); + SafeLocalAllocHandle tokenMandatoryLabel = SafeLocalAllocHandle.LocalAlloc((int)tokenMandatoryLabelSize); + try + { + if (!Interop.Advapi32.GetTokenInformation( + token.DangerousGetHandle(), + (uint)Interop.Advapi32.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, + tokenMandatoryLabel.DangerousGetHandle(), + tokenMandatoryLabelSize, + out tokenMandatoryLabelSize)) + { + ThrowExceptionForLastError(); + } + + return tokenMandatoryLabel; + } + catch + { + tokenMandatoryLabel.Dispose(); + throw; + } + } + + private static unsafe uint GetIntegrityLevel(nint integrityLevelSid) + { + // The last sub-authority has the RID that represents the integrity level + byte subAuthorityCount = + Unsafe.Read((void*)Interop.Advapi32.GetSidSubAuthorityCount(integrityLevelSid)); + Debug.Assert(subAuthorityCount != 0); + return Unsafe.Read((void*)Interop.Advapi32.GetSidSubAuthority(integrityLevelSid, subAuthorityCount - 1)); + } + + private static SafeLocalAllocHandle CreateSecurityDescriptor( + nint tokenUserSid, + SafeLocalAllocHandle dacl, + SafeLocalAllocHandle? sacl) + { + SafeLocalAllocHandle securityDescriptor = + SafeLocalAllocHandle.LocalAlloc(Interop.Advapi32.SECURITY_DESCRIPTOR_MIN_LENGTH); + try + { + if (!Interop.Advapi32.InitializeSecurityDescriptor( + securityDescriptor.DangerousGetHandle(), + Interop.Advapi32.SECURITY_DESCRIPTOR_REVISION)) + { + ThrowExceptionForLastError(); + } + + if (!Interop.Advapi32.SetSecurityDescriptorOwner( + securityDescriptor.DangerousGetHandle(), + tokenUserSid, + bOwnerDefaulted: false)) + { + ThrowExceptionForLastError(); + } + + if (!Interop.Advapi32.SetSecurityDescriptorGroup( + securityDescriptor.DangerousGetHandle(), + tokenUserSid, + bGroupDefaulted: false)) + { + ThrowExceptionForLastError(); + } + + if (!Interop.Advapi32.SetSecurityDescriptorDacl( + securityDescriptor.DangerousGetHandle(), + bDaclPresent: true, + dacl.DangerousGetHandle(), + bDaclDefaulted: false)) + { + ThrowExceptionForLastError(); + } + + if (sacl is not null && + !Interop.Advapi32.SetSecurityDescriptorSacl( + securityDescriptor.DangerousGetHandle(), + bSaclPresent: true, + sacl.DangerousGetHandle(), + bSaclDefaulted: false)) + { + ThrowExceptionForLastError(); + } + + return securityDescriptor; + } + catch + { + securityDescriptor.Dispose(); + throw; + } + } + + public static bool IsValidSecurityDescriptor(SafeWaitHandle objectHandle, int modifyStateAccessMask) + { + using SafeTokenHandle token = OpenCurrentToken(); + using SafeLocalAllocHandle tokenUser = GetTokenUser(token); + return IsSecurityDescriptorCompatible(tokenUser, objectHandle, modifyStateAccessMask); + } + + public static unsafe bool IsSecurityDescriptorCompatible( + SafeLocalAllocHandle tokenUser, + SafeWaitHandle objectHandle, + int modifyStateAccessMask) + { + Debug.Assert( + modifyStateAccessMask == Interop.Kernel32.MUTEX_MODIFY_STATE || + modifyStateAccessMask == Interop.Kernel32.SEMAPHORE_MODIFY_STATE || + modifyStateAccessMask == Interop.Kernel32.EVENT_MODIFY_STATE); + + nint tokenUserSid = GetTokenUserSid(tokenUser); + + // Get the object's relevant security information + using var securityDescriptor = new SafeLocalAllocHandle(); + nint ownerSid = 0; + Interop.Advapi32.ACL* dacl = null; + nint securityDescriptorNInt = 0; + int error = + (int) + Interop.Advapi32.GetSecurityInfoByHandle( + objectHandle, + (int)Interop.Advapi32.SE_OBJECT_TYPE.SE_KERNEL_OBJECT, + Interop.Advapi32.OWNER_SECURITY_INFORMATION | Interop.Advapi32.DACL_SECURITY_INFORMATION, + &ownerSid, + null, // sidGroup + (nint*)(&dacl), + null, // sacl + &securityDescriptorNInt); + if (error != Interop.Errors.ERROR_SUCCESS) + { + ThrowExceptionForError(error); + } + + securityDescriptor.SetHandle(securityDescriptorNInt); + + // The owner must be the same as the token user + if (!Interop.Advapi32.EqualSid(ownerSid, tokenUserSid)) + { + return false; + } + + // Any access-allowed ACE that allows manipulating the object must be for the token user + int anyWriteAccessMask = + Interop.Kernel32.WRITE_DAC | + Interop.Kernel32.WRITE_OWNER | + Interop.Kernel32.SYNCHRONIZE | + modifyStateAccessMask; + for (int i = 0, n = dacl->AceCount; i < n; i++) + { + if (!Interop.Advapi32.GetAce(dacl, i, out Interop.Advapi32.ACE* ace)) + { + ThrowExceptionForError(error); + } + + if (ace->Header.AceType == Interop.Advapi32.ACCESS_ALLOWED_ACE_TYPE && + (ace->Mask & anyWriteAccessMask) != 0 && + !Interop.Advapi32.EqualSid((nint)(&ace->SidStart), tokenUserSid)) + { + return false; + } + } + + return true; + } + + [DoesNotReturn] + private static void ThrowExceptionForLastError() => ThrowExceptionForError(Marshal.GetLastPInvokeError()); + + [DoesNotReturn] + private static void ThrowExceptionForError(int error) => throw Win32Marshal.GetExceptionForWin32Error(error); + } } } diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaders.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaders.cs index cc8ba755199efd..e1ef1f71236bc9 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaders.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaders.cs @@ -90,16 +90,30 @@ public PEHeaders(Stream peStream, int size, bool isLoadedImage) SkipDosHeader(ref reader, out bool isCoffOnly); + if (isCoffOnly && isLoadedImage) + { + // Only images can be loaded. + throw new BadImageFormatException(SR.InvalidPESignature); + } + _coffHeaderStartOffset = reader.Offset; _coffHeader = new CoffHeader(ref reader); - if (!isCoffOnly) + if (isCoffOnly) + { + // In COFF files the size of the optional header must be zero. + if (_coffHeader.SizeOfOptionalHeader != 0) + { + throw new BadImageFormatException(SR.UnknownFileFormat); + } + } + else { _peHeaderStartOffset = reader.Offset; _peHeader = new PEHeader(ref reader); } - _sectionHeaders = ReadSectionHeaders(ref reader); + _sectionHeaders = ReadSectionHeaders(ref reader, actualSize); if (!isCoffOnly) { @@ -289,10 +303,10 @@ private static void SkipDosHeader(ref PEBinaryReader reader, out bool isCOFFOnly } } - private ImmutableArray ReadSectionHeaders(ref PEBinaryReader reader) + private ImmutableArray ReadSectionHeaders(ref PEBinaryReader reader, int size) { int numberOfSections = _coffHeader.NumberOfSections; - if (numberOfSections < 0) + if (numberOfSections < 0 || numberOfSections * SectionHeader.Size > size - reader.Offset) { throw new BadImageFormatException(SR.InvalidNumberOfSections); } @@ -384,16 +398,8 @@ private void CalculateMetadataLocation(long peImageSize, out int start, out int return; } - if (_isLoadedImage) - { - start = SectionHeaders[cormeta].VirtualAddress; - size = SectionHeaders[cormeta].VirtualSize; - } - else - { - start = SectionHeaders[cormeta].PointerToRawData; - size = SectionHeaders[cormeta].SizeOfRawData; - } + start = SectionHeaders[cormeta].PointerToRawData; + size = SectionHeaders[cormeta].SizeOfRawData; } else if (_corHeader == null) { diff --git a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEHeadersTests.cs b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEHeadersTests.cs index a5be92ff0d2f20..e38dae2bf59e44 100644 --- a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEHeadersTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEHeadersTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers.Binary; using System.IO; using System.Linq; using System.Reflection.Metadata.Tests; @@ -50,6 +51,29 @@ public void Ctor_Streams() Assert.Equal(0, s.Position); } + [Fact] + public void Ctor_InvalidCoffHeader() + { + byte[] header = new byte[CoffHeader.Size]; + _ = new PEHeaders(new MemoryStream(header)); + + // NumberOfSections is too big. + BinaryPrimitives.WriteInt16LittleEndian(header.AsSpan(16), 5); + Assert.Throws(() => new PEHeaders(new MemoryStream(header))); + + header = new byte[CoffHeader.Size]; + // SizeOfOptionalHeader is non-zero. + BinaryPrimitives.WriteInt16LittleEndian(header.AsSpan(2), 10); + Assert.Throws(() => new PEHeaders(new MemoryStream(header))); + } + + [Fact] + public void Ctor_CoffFileLoadedImage() + { + byte[] file = new byte[CoffHeader.Size]; + Assert.Throws(() => new PEHeaders(new MemoryStream(file), file.Length, isLoadedImage: true)); + } + [Fact] public void FromEmptyStream() { diff --git a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs index b367fff3c382c5..13c9deab4498e7 100644 --- a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs @@ -820,10 +820,7 @@ public void Dispose() Assert.Throws(() => reader.ReadDebugDirectory()); Assert.Throws(() => reader.ReadCodeViewDebugDirectoryData(ddCodeView)); Assert.Throws(() => reader.ReadEmbeddedPortablePdbDebugDirectoryData(ddEmbedded)); - - MetadataReaderProvider __; - string ___; - Assert.Throws(() => reader.TryOpenAssociatedPortablePdb(@"x", _ => null, out __, out ___)); + Assert.Throws(() => reader.TryOpenAssociatedPortablePdb(@"x", _ => null, out _, out _)); // ok to use providers after PEReader disposed: var pdbReader = pdbProvider.GetMetadataReader(); @@ -869,15 +866,5 @@ public unsafe void InvokeCtorWithIsLoadedImageAndPrefetchMetadataOptions2() } } } - - [Fact] - public void HasMetadataShouldReturnFalseWhenPrefetchingMetadataOfImageWithoutMetadata() - { - using (var fileStream = new MemoryStream(Misc.KeyPair)) - using (var peReader = new PEReader(fileStream, PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen)) - { - Assert.False(peReader.HasMetadata); - } - } } } diff --git a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj index bb61c7204c8571..18d037049bdc1e 100644 --- a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj +++ b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true false - - - - - diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj b/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj index 4feacf3ede60ec..e38a35c5063c9b 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true diff --git a/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj b/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj index f1a9261795b6c8..5b4819e102073c 100644 --- a/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj +++ b/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetFrameworkCurrent) true true @@ -33,10 +33,6 @@ - - - - diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj index 846442cca6ca1c..c000f916e5ba29 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj @@ -20,6 +20,7 @@ $(NoWarn);NU1511 + false @@ -32,6 +33,7 @@ + diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/HttpRequestMessageTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/HttpRequestMessageTest.cs index 815dfeb0dcd2df..401d3c64feea2a 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/HttpRequestMessageTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/HttpRequestMessageTest.cs @@ -16,6 +16,8 @@ namespace System.Runtime.InteropServices.JavaScript.Http.Tests { public class HttpRequestMessageTest { + public static readonly string LocalHttpEcho = "http://" + Environment.GetEnvironmentVariable("DOTNET_TEST_HTTPHOST") + "/Echo.ashx"; + private readonly Version _expectedRequestMessageVersion = HttpVersion.Version11; private HttpRequestOptionsKey EnableStreamingResponse = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); private HttpRequestOptionsKey> FetchOptions = new HttpRequestOptionsKey>("WebAssemblyFetchOptions"); @@ -295,6 +297,32 @@ public void Properties_SetOptionsAndGetTheirValue_NotSet_EnableStreamingResponse Assert.False(streamingEnabledValue); } + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/113628", TestPlatforms.Browser)] + public async Task HttpStreamingDisabledBy_WasmEnableStreamingResponse_InProject() + { + using var client = new HttpClient(); + using var req = new HttpRequestMessage(HttpMethod.Get, LocalHttpEcho + "?guid=" + Guid.NewGuid()); + using var response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); + Assert.Equal("BrowserHttpContent", response.Content.GetType().Name); + using var stream = await response.Content.ReadAsStreamAsync(); + Assert.Equal("MemoryStream", stream.GetType().Name); + Assert.True(stream.CanSeek); + } + + [Fact] + public async Task HttpStreamingEnabledBy_WebAssemblyEnableStreamingResponse_Option() + { + using var client = new HttpClient(); + using var req = new HttpRequestMessage(HttpMethod.Get, LocalHttpEcho + "?guid=" + Guid.NewGuid()); + req.Options.Set(new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"), true); + using var response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); + Assert.Equal("StreamContent", response.Content.GetType().Name); + using var stream = await response.Content.ReadAsStreamAsync(); + Assert.Equal("ReadOnlyStream", stream.GetType().Name); + Assert.False(stream.CanSeek); + } + [Fact] public void Version_SetToNull_ThrowsArgumentNullException() { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index ea49ef193dcd40..26b81d5bf52273 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -1032,6 +1032,15 @@ public static JSObject EchoIJSObject([JSMarshalAs] JSObject arg1) return arg1; } + [JSImport("beforeYield", "JavaScriptTestHelper")] + public static partial void BeforeYield(); + + [JSImport("isSetTimeoutHit", "JavaScriptTestHelper")] + public static partial bool IsSetTimeoutHit(); + + [JSImport("isPromiseThenHit", "JavaScriptTestHelper")] + public static partial bool IsPromiseThenHit(); + [JSImport("callJavaScriptLibrary", "JavaScriptTestHelper")] public static partial Task callJavaScriptLibrary(int a, int b); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs index 131f5cd9a9d0c7..f4f2772fdda8b5 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs @@ -466,3 +466,28 @@ export function delay(ms) { export function reject(what) { return new Promise((_, reject) => globalThis.setTimeout(() => reject(what), 0)); } + +let setTimeoutHit = false; +let promiseThenHit = false; +export function beforeYield() { + setTimeoutHit = false; + promiseThenHit = false; + setTimeout(() => { + setTimeoutHit = true; + }, 0); + let res; + new Promise((resolve) => { + res = resolve; + }).then(() => { + promiseThenHit = true; + }); + res(); +} + +export function isSetTimeoutHit() { + return setTimeoutHit; +} + +export function isPromiseThenHit() { + return promiseThenHit; +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.Http.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.Http.cs index 56505353cff6f6..4550bef70dd4f5 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.Http.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.Http.cs @@ -32,7 +32,6 @@ await executor.Execute(async () => } private static HttpRequestOptionsKey WebAssemblyEnableStreamingRequestKey = new("WebAssemblyEnableStreamingRequest"); - private static HttpRequestOptionsKey WebAssemblyEnableStreamingResponseKey = new("WebAssemblyEnableStreamingResponse"); private static string HelloJson = "{'hello':'world'}".Replace('\'', '"'); private static string EchoStart = "{\"Method\":\"POST\",\"Url\":\"/Echo.ashx"; @@ -46,7 +45,6 @@ private async Task HttpClient_ActionInDifferentThread(string url, Executor execu await ms.WriteAsync(Encoding.UTF8.GetBytes(HelloJson)); using var req = new HttpRequestMessage(HttpMethod.Post, url); - req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); req.Content = new StreamContent(ms); using var client = new HttpClient(); var pr = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/YieldAwaitableTests.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/YieldAwaitableTests.cs new file mode 100644 index 00000000000000..1765d060601521 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/YieldAwaitableTests.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Runtime.InteropServices.JavaScript.Tests +{ + public class YieldAwaitableTests : IAsyncLifetime + { + [Fact] + public async Task TaskYieldsToBrowserLoop() + { + JavaScriptTestHelper.BeforeYield(); + await Task.Yield(); + Assert.True(JavaScriptTestHelper.IsSetTimeoutHit()); + Assert.True(JavaScriptTestHelper.IsPromiseThenHit()); + } + + [Fact] + public async Task TaskDelay0DoesNotYieldToBrowserLoop() + { + JavaScriptTestHelper.BeforeYield(); + await Task.Delay(0); + Assert.False(JavaScriptTestHelper.IsSetTimeoutHit()); + Assert.False(JavaScriptTestHelper.IsPromiseThenHit()); + } + + [Fact] + public async Task TaskDelay1YieldsToBrowserLoop() + { + JavaScriptTestHelper.BeforeYield(); + await Task.Delay(1); + Assert.True(JavaScriptTestHelper.IsSetTimeoutHit()); + Assert.True(JavaScriptTestHelper.IsPromiseThenHit()); + } + + public async Task InitializeAsync() + { + await JavaScriptTestHelper.InitializeAsync(); + await Task.Delay(100); + } + + public async Task DisposeAsync() + { + await JavaScriptTestHelper.DisposeAsync(); + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs index 2d0c0b2b93d8a4..19b07e9a8e6856 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs @@ -31,12 +31,25 @@ public void SizeOf_Object_ReturnsExpected() Assert.NotEqual(0, Marshal.SizeOf(typeof(SomeTestStruct))); } + [Fact] + public unsafe void SizeOf_FunctionPointer_ReturnsExpected() + { + Assert.Equal(IntPtr.Size, Marshal.SizeOf(typeof(delegate*))); + } + [Fact] public void SizeOf_Pointer_ReturnsExpected() { Assert.Equal(IntPtr.Size, Marshal.SizeOf(typeof(int).MakePointerType())); } + [Fact] + public void SizeOf_Primitives_ReturnsExpected() + { + Assert.Equal(1, Marshal.SizeOf()); + Assert.Equal(4, Marshal.SizeOf()); + } + [Fact] public void SizeOf_NullType_ThrowsArgumentNullException() { diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 59a245ff13b587..fa00f8e560f8c9 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -321,6 +321,20 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } public static System.Runtime.Intrinsics.Vector128 Sin(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Sin(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static (System.Runtime.Intrinsics.Vector128 Sin, System.Runtime.Intrinsics.Vector128 Cos) SinCos(System.Runtime.Intrinsics.Vector128 vector) { throw null; } @@ -720,6 +734,20 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleNative(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } public static System.Runtime.Intrinsics.Vector256 Sin(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Sin(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static (System.Runtime.Intrinsics.Vector256 Sin, System.Runtime.Intrinsics.Vector256 Cos) SinCos(System.Runtime.Intrinsics.Vector256 vector) { throw null; } @@ -1120,6 +1148,20 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 Shuffle(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } public static System.Runtime.Intrinsics.Vector512 Shuffle(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleNative(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } public static System.Runtime.Intrinsics.Vector512 Sin(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Sin(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static (System.Runtime.Intrinsics.Vector512 Sin, System.Runtime.Intrinsics.Vector512 Cos) SinCos(System.Runtime.Intrinsics.Vector512 vector) { throw null; } @@ -1485,6 +1527,16 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShuffleNative(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } public static System.Runtime.Intrinsics.Vector64 Sin(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Sin(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static (System.Runtime.Intrinsics.Vector64 Sin, System.Runtime.Intrinsics.Vector64 Cos) SinCos(System.Runtime.Intrinsics.Vector64 vector) { throw null; } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 7163c17c8f8c17..8e41e2b955616a 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -2776,6 +2776,486 @@ public void Vector128UInt64ShuffleOneInputWithZeroIndicesTest() } } + [Fact] + public void Vector128ByteShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128DoubleShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((double)1, 2); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((long)1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((double)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int16ShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((short)1, 2, 3, 4, 5, 6, 7, 8); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((short)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((short)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int32ShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((int)1, 2, 3, 4); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((int)3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((int)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int64ShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((long)1, 2); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((long)1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((long)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128SByteShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((sbyte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((sbyte)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128SingleShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((float)1, 2, 3, 4); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((int)3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((float)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt16ShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((ushort)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ushort)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt32ShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((uint)1, 2, 3, 4); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((uint)3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((uint)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt64ShuffleNativeOneInputTest() + { + Vector128 vector = Vector128.Create((ulong)1, 2); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Create((ulong)1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ulong)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128ByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128DoubleShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((double)1, 2), Vector128.Create((long)1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((double)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((short)1, 2, 3, 4, 5, 6, 7, 8), Vector128.Create((short)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((short)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((int)1, 2, 3, 4), Vector128.Create((int)3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((int)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int64ShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((long)1, 2), Vector128.Create((long)1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((long)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128SByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector128.Create((sbyte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((sbyte)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128SingleShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((float)1, 2, 3, 4), Vector128.Create((int)3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((float)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8), Vector128.Create((ushort)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ushort)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((uint)1, 2, 3, 4), Vector128.Create((uint)3, 2, 1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((uint)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt64ShuffleNativeOneInputWithDirectVectorTest() + { + Vector128 result = Vector128.ShuffleNative(Vector128.Create((ulong)1, 2), Vector128.Create((ulong)1, 0)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ulong)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128ByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 indices = Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128DoubleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((double)1, 2); + Vector128 indices = Vector128.Create((long)1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((double)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((short)1, 2, 3, 4, 5, 6, 7, 8); + Vector128 indices = Vector128.Create((short)7, 6, 5, 4, 3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((short)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((int)1, 2, 3, 4); + Vector128 indices = Vector128.Create((int)3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((int)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int64ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((long)1, 2); + Vector128 indices = Vector128.Create((long)1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((long)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128SByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 indices = Vector128.Create((sbyte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((sbyte)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128SingleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((float)1, 2, 3, 4); + Vector128 indices = Vector128.Create((int)3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((float)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8); + Vector128 indices = Vector128.Create((ushort)7, 6, 5, 4, 3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ushort)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((uint)1, 2, 3, 4); + Vector128 indices = Vector128.Create((uint)3, 2, 1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((uint)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt64ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector128 vector = Vector128.Create((ulong)1, 2); + Vector128 indices = Vector128.Create((ulong)1, 0); + Vector128 result = Vector128.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ulong)(Vector128.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector128ByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128DoubleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((double)1, 2); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((double)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((short)1, 2, 3, 4, 5, 6, 7, 8); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((short)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((int)1, 2, 3, 4); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((int)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128Int64ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((long)1, 2); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((long)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128SByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((sbyte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128SingleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((float)1, 2, 3, 4); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((float)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ushort)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((uint)1, 2, 3, 4); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((uint)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector128UInt64ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector128 vector = Vector128.Create((ulong)1, 2); + Vector128 result = Vector128.ShuffleNative(vector, Vector128.Zero); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ulong)1, result.GetElement(index)); + } + } + [Fact] public unsafe void Vector128ByteStoreTest() { diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index 30c92e16c12b4c..c29de431d1a081 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -3402,6 +3402,646 @@ public void Vector256UInt64ShuffleOneInputWithZeroIndicesTest() } } + [Fact] + public void Vector256ByteShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256DoubleShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((double)1, 2, 3, 4); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((long)3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((double)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int16ShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((short)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((short)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int32ShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((int)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((int)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((int)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int64ShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((long)1, 2, 3, 4); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((long)3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((long)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SByteShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((sbyte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SingleShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((float)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((int)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((float)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt16ShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((ushort)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ushort)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt32ShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((uint)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((uint)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((uint)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt64ShuffleNativeOneInputTest() + { + Vector256 vector = Vector256.Create((ulong)1, 2, 3, 4); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Create((ulong)3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ulong)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256ByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256DoubleShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((double)1, 2, 3, 4), Vector256.Create((long)3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((double)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector256.Create((short)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((short)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((int)1, 2, 3, 4, 5, 6, 7, 8), Vector256.Create((int)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((int)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int64ShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((long)1, 2, 3, 4), Vector256.Create((long)3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((long)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((sbyte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SingleShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((float)1, 2, 3, 4, 5, 6, 7, 8), Vector256.Create((int)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((float)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector256.Create((ushort)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ushort)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((uint)1, 2, 3, 4, 5, 6, 7, 8), Vector256.Create((uint)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((uint)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt64ShuffleNativeOneInputWithDirectVectorTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((ulong)1, 2, 3, 4), Vector256.Create((ulong)3, 2, 1, 0)); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ulong)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256ByteShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256DoubleShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((double)1, 2, 3, 4), Vector256.Create((long)1, 0, 3, 2)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((double)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((double)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int16ShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector256.Create((short)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((short)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((short)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int32ShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((int)1, 2, 3, 4, 5, 6, 7, 8), Vector256.Create((int)3, 2, 1, 0, 7, 6, 5, 4)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((int)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((int)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int64ShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((long)1, 2, 3, 4), Vector256.Create((long)1, 0, 3, 2)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((long)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((long)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SByteShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((sbyte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((sbyte)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SingleShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((float)1, 2, 3, 4, 5, 6, 7, 8), Vector256.Create((int)3, 2, 1, 0, 7, 6, 5, 4)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((float)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((float)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt16ShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector256.Create((ushort)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ushort)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((ushort)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt32ShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((uint)1, 2, 3, 4, 5, 6, 7, 8), Vector256.Create((uint)3, 2, 1, 0, 7, 6, 5, 4)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((uint)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((uint)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt64ShuffleNativeOneInputWithDirectVectorAndNoCrossLaneTest() + { + Vector256 result = Vector256.ShuffleNative(Vector256.Create((ulong)1, 2, 3, 4), Vector256.Create((ulong)1, 0, 3, 2)); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ulong)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((ulong)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector256ByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 indices = Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256DoubleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((double)1, 2, 3, 4); + Vector256 indices = Vector256.Create((long)3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((double)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector256 indices = Vector256.Create((short)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((short)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((int)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 indices = Vector256.Create((int)7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((int)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int64ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((long)1, 2, 3, 4); + Vector256 indices = Vector256.Create((long)3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((long)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 indices = Vector256.Create((sbyte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256SingleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((float)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 indices = Vector256.Create((int)7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((float)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector256 indices = Vector256.Create((ushort)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ushort)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((uint)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 indices = Vector256.Create((uint)7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((uint)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt64ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector256 vector = Vector256.Create((ulong)1, 2, 3, 4); + Vector256 indices = Vector256.Create((ulong)3, 2, 1, 0); + Vector256 result = Vector256.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ulong)(Vector256.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector256ByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256DoubleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((double)1, 2, 3, 4); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((double)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((short)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((int)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((int)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256Int64ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((long)1, 2, 3, 4); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((long)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256SByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256SingleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((float)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((float)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ushort)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((uint)1, 2, 3, 4, 5, 6, 7, 8); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((uint)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector256UInt64ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector256 vector = Vector256.Create((ulong)1, 2, 3, 4); + Vector256 result = Vector256.ShuffleNative(vector, Vector256.Zero); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ulong)1, result.GetElement(index)); + } + } + [Fact] public unsafe void Vector256ByteStoreTest() { diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index 6016fc822a1cab..2f1d298406f930 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -3394,6 +3394,996 @@ public void Vector512UInt64ShuffleOneInputWithZeroIndicesTest() } } + [Fact] + public void Vector512ByteShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512DoubleShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((double)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((long)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((double)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int16ShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((short)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((short)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int32ShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((int)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((int)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int64ShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((long)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((long)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((long)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SByteShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((sbyte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((sbyte)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SingleShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((int)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((float)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt16ShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((ushort)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ushort)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt32ShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((uint)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((uint)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((uint)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt64ShuffleNativeOneInputTest() + { + Vector512 vector = Vector512.Create((ulong)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Create((ulong)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ulong)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512ByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512DoubleShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((double)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((long)7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((double)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), + Vector512.Create((short)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((short)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((int)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((int)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int64ShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((long)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((long)7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((long)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((sbyte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((sbyte)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SingleShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((int)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((float)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), + Vector512.Create((ushort)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ushort)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((uint)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((uint)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((uint)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt64ShuffleNativeOneInputWithDirectVectorTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((ulong)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((ulong)7, 6, 5, 4, 3, 2, 1, 0) + ); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ulong)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512ByteShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512DoubleShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((double)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((long)1, 0, 3, 2, 5, 4, 7, 6) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((double)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((double)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((double)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((double)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int16ShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), + Vector512.Create((short)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((short)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((short)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((short)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((short)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int32ShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((int)3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((int)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((int)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((int)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((int)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int64ShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((long)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((long)1, 0, 3, 2, 5, 4, 7, 6) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((long)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((long)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((long)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((long)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SByteShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((sbyte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((sbyte)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((sbyte)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((sbyte)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SingleShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((int)3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((float)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((float)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((float)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((float)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt16ShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), + Vector512.Create((ushort)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ushort)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((ushort)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((ushort)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((ushort)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt32ShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((uint)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((uint)3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((uint)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((uint)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((uint)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((uint)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt64ShuffleNativeOneInputWithDirectVectorAndNoCross128BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((ulong)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((ulong)1, 0, 3, 2, 5, 4, 7, 6) + ); + + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((ulong)(Vector128.Count - index), result.GetElement(index)); + } + + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((ulong)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((ulong)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } + + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((ulong)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512ByteShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512DoubleShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((double)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((long)3, 2, 1, 0, 7, 6, 5, 4) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((double)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((double)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int16ShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), + Vector512.Create((short)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((short)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((short)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int32ShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((int)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((int)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((int)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int64ShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((long)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((long)3, 2, 1, 0, 7, 6, 5, 4) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((long)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((long)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SByteShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((sbyte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((sbyte)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((sbyte)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SingleShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((int)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((float)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((float)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt16ShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), + Vector512.Create((ushort)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ushort)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((ushort)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt32ShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((uint)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + Vector512.Create((uint)7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((uint)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((uint)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt64ShuffleNativeOneInputWithDirectVectorAndNoCross256BitLaneTest() + { + Vector512 result = Vector512.ShuffleNative( + Vector512.Create((ulong)1, 2, 3, 4, 5, 6, 7, 8), + Vector512.Create((ulong)3, 2, 1, 0, 7, 6, 5, 4) + ); + + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((ulong)(Vector256.Count - index), result.GetElement(index)); + } + + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((ulong)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + } + + [Fact] + public void Vector512ByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 indices = Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512DoubleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((double)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 indices = Vector512.Create((long)7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((double)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector512 indices = Vector512.Create((short)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((short)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 indices = Vector512.Create((int)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((int)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int64ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((long)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 indices = Vector512.Create((long)7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((long)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 indices = Vector512.Create((sbyte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((sbyte)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512SingleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 indices = Vector512.Create((int)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((float)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector512 indices = Vector512.Create((ushort)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ushort)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((uint)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 indices = Vector512.Create((uint)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((uint)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt64ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector512 vector = Vector512.Create((ulong)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 indices = Vector512.Create((ulong)7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ulong)(Vector512.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector512ByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512DoubleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((double)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((double)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((short)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((short)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((int)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((int)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512Int64ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((long)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((long)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512SByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((sbyte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512SingleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((float)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((float)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((ushort)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ushort)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((uint)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((uint)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector512UInt64ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector512 vector = Vector512.Create((ulong)1, 2, 3, 4, 5, 6, 7, 8); + Vector512 result = Vector512.ShuffleNative(vector, Vector512.Zero); + + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((ulong)1, result.GetElement(index)); + } + } + [Fact] public unsafe void Vector512ByteStoreTest() { diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index 9cdbc25be4a723..189b56d3ce536d 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -2399,6 +2399,342 @@ public void Vector64UInt32ShuffleOneInputWithZeroIndicesTest() } } + [Fact] + public void Vector64ByteShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int16ShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((short)1, 2, 3, 4); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((short)3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((short)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int32ShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((int)1, 2); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((int)1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((int)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64SByteShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((sbyte)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((sbyte)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64SingleShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((float)1, 2); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((int)1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((float)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt16ShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((ushort)1, 2, 3, 4); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((ushort)3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((ushort)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt32ShuffleNativeOneInputTest() + { + Vector64 vector = Vector64.Create((uint)1, 2); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Create((uint)1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((uint)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64ByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8), Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((short)1, 2, 3, 4), Vector64.Create((short)3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((short)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((int)1, 2), Vector64.Create((int)1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((int)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64SByteShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8), Vector64.Create((sbyte)7, 6, 5, 4, 3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((sbyte)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64SingleShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((float)1, 2), Vector64.Create((int)1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((float)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt16ShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((ushort)1, 2, 3, 4), Vector64.Create((ushort)3, 2, 1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((ushort)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt32ShuffleNativeOneInputWithDirectVectorTest() + { + Vector64 result = Vector64.ShuffleNative(Vector64.Create((uint)1, 2), Vector64.Create((uint)1, 0)); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((uint)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64ByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 indices = Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((short)1, 2, 3, 4); + Vector64 indices = Vector64.Create((short)3, 2, 1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((short)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((int)1, 2); + Vector64 indices = Vector64.Create((int)1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((int)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64SByteShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 indices = Vector64.Create((sbyte)7, 6, 5, 4, 3, 2, 1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((sbyte)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64SingleShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((float)1, 2); + Vector64 indices = Vector64.Create((int)1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((float)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt16ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((ushort)1, 2, 3, 4); + Vector64 indices = Vector64.Create((ushort)3, 2, 1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((ushort)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt32ShuffleNativeOneInputWithLocalIndicesTest() + { + Vector64 vector = Vector64.Create((uint)1, 2); + Vector64 indices = Vector64.Create((uint)1, 0); + Vector64 result = Vector64.ShuffleNative(vector, indices); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((uint)(Vector64.Count - index), result.GetElement(index)); + } + } + + [Fact] + public void Vector64ByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((short)1, 2, 3, 4); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal(1, result.GetElement(index)); + } + } + + [Fact] + public void Vector64Int32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((int)1, 2); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((int)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector64SByteShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((sbyte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((sbyte)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector64SingleShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((float)1, 2); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((float)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt16ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((ushort)1, 2, 3, 4); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((ushort)1, result.GetElement(index)); + } + } + + [Fact] + public void Vector64UInt32ShuffleNativeOneInputWithZeroIndicesTest() + { + Vector64 vector = Vector64.Create((uint)1, 2); + Vector64 result = Vector64.ShuffleNative(vector, Vector64.Zero); + + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((uint)1, result.GetElement(index)); + } + } + [Fact] public unsafe void Vector64ByteStoreTest() { diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterTypesTests.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterTypesTests.cs index c21b3157294a8d..9dab40e4793b72 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterTypesTests.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterTypesTests.cs @@ -19,7 +19,7 @@ public ExporterTypesTests(ITestOutputHelper output) _output = output; } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.DataSetXmlSerializationIsSupported))] public void TypesTest() { var types = new List() @@ -79,7 +79,7 @@ public static IEnumerable GetDynamicallyVersionedTypesTestNegativeData }; } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.DataSetXmlSerializationIsSupported))] [SkipOnPlatform(TestPlatforms.Browser, "Inconsistent and unpredictable results.")] // TODO - Why does 'TypeWithReadWriteCollectionAndNoCtorOnCollection' only cause an exception sometimes, but not all the time? What's special about wasm here? [ActiveIssue("https://github.com/dotnet/runtime/issues/82967", TestPlatforms.Wasi)] [InlineData(typeof(NoDataContractWithoutParameterlessConstructor), typeof(InvalidDataContractException), @"Type 'System.Runtime.Serialization.Xml.XsdDataContractExporterTests.ExporterTypesTests+NoDataContractWithoutParameterlessConstructor' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.")] diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaTestResult.cs b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaTestResult.cs index 1d78610dd06ad2..b1427436392f8f 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaTestResult.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaTestResult.cs @@ -27,22 +27,30 @@ public class ConformanceIdnaTestResult ///
public string Value { get; private set; } + public string? Source { get; private set; } + public IdnaTestResultType ResultType { get; private set; } public string StatusValue { get; private set; } public ConformanceIdnaTestResult(string entry, string fallbackValue, IdnaTestResultType resultType = IdnaTestResultType.ToAscii) - : this(entry, fallbackValue, null, null, useValueForStatus: true, resultType) + : this(entry, fallbackValue, null, null, useValueForStatus: true, resultType, null) { } public ConformanceIdnaTestResult(string entry, string fallbackValue, string statusValue, string statusFallbackValue, IdnaTestResultType resultType = IdnaTestResultType.ToAscii) - : this(entry, fallbackValue, statusValue, statusFallbackValue, useValueForStatus: false, resultType) + : this(entry, fallbackValue, statusValue, statusFallbackValue, useValueForStatus: false, resultType, null) + { + } + + public ConformanceIdnaTestResult(string entry, string fallbackValue, string statusValue, string statusFallbackValue, string? source, IdnaTestResultType resultType = IdnaTestResultType.ToAscii) + : this(entry, fallbackValue, statusValue, statusFallbackValue, useValueForStatus: false, resultType, source) { } - private ConformanceIdnaTestResult(string entry, string fallbackValue, string statusValue, string statusFallbackValue, bool useValueForStatus, IdnaTestResultType resultType) + private ConformanceIdnaTestResult(string entry, string fallbackValue, string statusValue, string statusFallbackValue, bool useValueForStatus, IdnaTestResultType resultType, string? source) { + Source = source; ResultType = resultType; SetValue(string.IsNullOrEmpty(entry.Trim()) ? fallbackValue : entry); SetSuccess(useValueForStatus ? @@ -81,11 +89,120 @@ private void SetSuccess(string statusValue) } } + // Fullwidth Full Stop, Ideographic Full Stop, and Halfwidth Ideographic Full Stop + private static char[] AllDots = ['.', '\uFF0E', '\u3002', '\uFF61']; + + private const char SoftHyphen = '\u00AD'; + + private bool IsIgnorableA4_2Rule() + { + if (Source is null) + { + return false; + } + + // Check the label lengths for the ASCII + int lastIndex = 0; + int index = Value.IndexOfAny(AllDots); + while (index >= 0) + { + if (index - lastIndex > 63) // 63 max label length + { + return false; + } + + lastIndex = index + 1; + index = Value.IndexOfAny(AllDots, lastIndex); + } + + if (Value.Length - lastIndex > 63) + { + return false; + } + + // Remove Hyphen as it is ignored + if (Source.IndexOf(SoftHyphen) >= 0) + { + Span span = stackalloc char[Source.Length]; + int spanIndex = 0; + + for (int i = 0; i < Source.Length; i++) + { + if (Source[i] != SoftHyphen) + { + span[spanIndex++] = Source[i]; + } + } + + Source = span.Slice(0, spanIndex).ToString(); + } + + // Check the label lengths for the Source + lastIndex = 0; + index = Source.IndexOfAny(AllDots); + while (index >= 0) + { + if (index - lastIndex > 63) // 63 max label length + { + return false; + } + + lastIndex = index + 1; + index = Source.IndexOfAny(AllDots, lastIndex); + } + + if (Source.Length - lastIndex > 63) + { + return false; + } + + if (Source[0] is '.') // Leading dot + { + return false; + } + + for (int i = 0; i < Source.Length - 1; i++) + { + // Consequence dots + if ((Source[i] is '.' or '\uFF0E' or '\u3002' or '\uFF61') && (Source[i + 1] is '.' or '\uFF0E' or '\u3002' or '\uFF61')) + { + return false; + } + + // Check Historical Ranges + if (Source[i] >= 0x2C00 && Source[i] <= 0x2C5F) // Glagolitic (U+2C00–U+2C5F) + return false; + + switch (Source[i]) + { + case '\uD800': + if (Source[i + 1] >= 0xDFA0 && Source[i + 1] <= 0xDFDF) return false; // Old Persian (U+103A0–U+103DF) + if (Source[i + 1] >= 0xDF30 && Source[i + 1] <= 0xDF4F) return false; // Gothic (U+10330–U+1034F) + if (Source[i + 1] >= 0xDC00 && Source[i + 1] <= 0xDC7F) return false; // Linear B (U+10000–U+1007F) + break; + case '\uD802': + if (Source[i + 1] >= 0xDD00 && Source[i + 1] <= 0xDD1F) return false; // Phoenician (U+10900–U+1091F) + break; + case '\uD803': + if (Source[i + 1] >= 0xDEA0 && Source[i + 1] <= 0xDEAF) return false; // Elymaic (U+10EA0–U+10EAF) + break; + case '\uD808': + if (Source[i + 1] >= 0xDC00 && Source[i + 1] <= 0xDFFF) return false; // Cuneiform (U+12000–U+123FF) + break; + case '\uD838': + if (Source[i + 1] >= 0xDC00 && Source[i + 1] <= 0xDCDF) return false; // Indic Siyaq Numbers (U+1E800–U+1E8DF) + break; + } + } + + return true; + } + private bool IsIgnoredError(string statusCode) { // We don't validate for BIDI rule so we can ignore BIDI codes // If we're validating ToAscii we ignore rule V2 (UIDNA_ERROR_HYPHEN_3_4) for compatibility with windows. - return statusCode.StartsWith('B') || (ResultType == IdnaTestResultType.ToAscii && statusCode == "V2"); + return statusCode.StartsWith('B') || (ResultType == IdnaTestResultType.ToAscii && statusCode == "V2") || (statusCode.StartsWith("A4_2") && IsIgnorableA4_2Rule()); } } } diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaUnicodeTestResult.cs b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaUnicodeTestResult.cs index e712dcb8afc356..edd60f4e73bb8a 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaUnicodeTestResult.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/ConformanceIdnaUnicodeTestResult.cs @@ -13,6 +13,12 @@ public ConformanceIdnaUnicodeTestResult(string entry, string fallbackValue, bool ValidDomainName = validDomainName; } + public ConformanceIdnaUnicodeTestResult(string entry, string fallbackValue, string statusValue, string statusFallbackValue, string? source, bool validDomainName = true) + : base(entry, fallbackValue, statusValue, statusFallbackValue, source, IdnaTestResultType.ToUnicode) + { + ValidDomainName = validDomainName; + } + public ConformanceIdnaUnicodeTestResult(string entry, string fallbackValue, string statusValue, string statusFallbackValue, bool validDomainName = true) : base(entry, fallbackValue, statusValue, statusFallbackValue, IdnaTestResultType.ToUnicode) { diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Factory.cs b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Factory.cs index 0c1b9d97e277c5..c2610eb092ced3 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Factory.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Factory.cs @@ -26,7 +26,9 @@ private static string RemoveComment(string line) private static Stream GetIdnaTestTxt() { string fileName = null; - if (PlatformDetection.ICUVersion >= new Version(74, 0)) + if (PlatformDetection.ICUVersion >= new Version(76, 0)) + fileName = "IdnaTest_16.txt"; + else if (PlatformDetection.ICUVersion >= new Version(74, 0)) fileName = "IdnaTest_15_1.txt"; else if (PlatformDetection.ICUVersion >= new Version(66, 0) || PlatformDetection.IsHybridGlobalizationOnApplePlatform) fileName = "IdnaTest_13.txt"; @@ -63,7 +65,9 @@ private static IEnumerable ParseFile(Stream stream, Func= new Version(74, 0)) + if (PlatformDetection.ICUVersion >= new Version(76, 0)) + return new Unicode_16_0_IdnaTest(line, lineCount); + else if (PlatformDetection.ICUVersion >= new Version(74, 0)) return new Unicode_15_1_IdnaTest(line, lineCount); else if (PlatformDetection.ICUVersion >= new Version(66, 0) || PlatformDetection.IsHybridGlobalizationOnApplePlatform) return new Unicode_13_0_IdnaTest(line, lineCount); diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/IdnaTest_16.txt b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/IdnaTest_16.txt new file mode 100644 index 00000000000000..cdd24dd8a7d43b --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/IdnaTest_16.txt @@ -0,0 +1,6506 @@ +# IdnaTestV2.txt +# Date: 2024-07-03, 22:06:44 GMT +# © 2024 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use and license, see https://www.unicode.org/terms_of_use.html +# +# Unicode IDNA Compatible Preprocessing for UTS #46 +# Version: 16.0.0 +# +# For documentation and usage, see https://www.unicode.org/reports/tr46 +# +# Test cases for verifying UTS #46 conformance. +# +# FORMAT: +# +# This file is in UTF-8, where characters may be escaped using the \uXXXX or \x{XXXX} +# convention where they could otherwise have a confusing display. +# These characters include control codes and combining marks. +# +# Columns (c1, c2,...) are separated by semicolons. +# Leading and trailing spaces and tabs in each column are ignored. +# Comments are indicated with hash marks. +# +# Column 1: source - The source string to be tested. +# "" means the empty string. +# Column 2: toUnicode - The result of applying toUnicode to the source, +# with Transitional_Processing=false. +# A blank value means the same as the source value. +# "" means the empty string. +# Column 3: toUnicodeStatus - A set of status codes, each corresponding to a particular test. +# A blank value means [] (no errors). +# Column 4: toAsciiN - The result of applying toASCII to the source, +# with Transitional_Processing=false. +# A blank value means the same as the toUnicode value. +# "" means the empty string. +# Column 5: toAsciiNStatus - A set of status codes, each corresponding to a particular test. +# A blank value means the same as the toUnicodeStatus value. +# An explicit [] means no errors. +# Column 6: toAsciiT - The result of applying toASCII to the source, +# with Transitional_Processing=true. +# A blank value means the same as the toAsciiN value. +# "" means the empty string. +# Column 7: toAsciiTStatus - A set of status codes, each corresponding to a particular test. +# A blank value means the same as the toAsciiNStatus value. +# An explicit [] means no errors. +# +# The line comments currently show visible characters that have been escaped. +# +# CONFORMANCE: +# +# To test for conformance to UTS #46, an implementation will perform the toUnicode, toAsciiN, and +# toAsciiT operations on the source string, then verify the resulting strings and relevant status +# values. +# +# If the implementation converts illegal code points into U+FFFD (as per +# https://www.unicode.org/reports/tr46/#Processing) then the string comparisons need to +# account for that by treating U+FFFD in the actual value as a wildcard when comparing to the +# expected value in the test file. +# +# A status in toUnicode, toAsciiN or toAsciiT is indicated by a value in square brackets, +# such as "[B5, B6]". In such a case, the contents is a list of status codes based on the step +# numbers in UTS #46 and IDNA2008, with the following formats. +# +# Pn for Section 4 Processing step n +# Vn for 4.1 Validity Criteria step n +# U1 for UseSTD3ASCIIRules +# An for 4.2 ToASCII step n +# Bn for Bidi (in IDNA2008) +# Cn for ContextJ (in IDNA2008) +# Xn for toUnicode issues (see below) +# +# Thus C1 = Appendix A.1. ZERO WIDTH NON-JOINER, and C2 = Appendix A.2. ZERO WIDTH JOINER. +# (The CONTEXTO tests are optional for client software, and not tested here.) +# +# Implementations that allow values of particular input flags to be false would ignore +# the corresponding status codes listed in the table below when testing for errors. +# +# VerifyDnsLength: A4_1, A4_2 +# CheckHyphens: V2, V3 +# CheckJoiners: Cn +# CheckBidi: Bn +# UseSTD3ASCIIRules: U1 +# +# Implementations that cannot work with ill-formed strings would skip test cases that contain them. +# For example, the status code A3 is set for a Punycode encoding error, +# which may be due to an unpaired surrogate. +# +# Implementations may be more strict than the default settings for UTS #46. +# In particular, an implementation conformant to IDNA2008 would skip any line in this test file that +# contained a character in the toUnicode field that has the IDNA2008 Status value NV8 or XV8 +# in IdnaMappingTable.txt. +# For example, it would skip a line containing ¢ (U+00A2 CENT SIGN) in the toUnicode field, +# because of the following line in IdnaMappingTable.txt: +# +# 00A1..00A7 ; valid ; ; NV8 # 1.1 INVERTED EXCLAMATION MARK..SECTION SIGN +# +# Implementations need only record that there is an error: they need not reproduce the +# precise status codes (after removing the ignored status values). +# +# Compatibility errors +# +# The special error code X4_2 is now returned where a toASCII error code +# was formerly being generated in toUnicode due to an empty label: +# A4_2 was being generated for an empty label in CheckBidi (in addition to A4_2’s normal usage). +# ============================================================================================ +fass.de; ; ; ; ; ; # fass.de +faß.de; ; ; xn--fa-hia.de; ; fass.de; # faß.de +Faß.de; faß.de; ; xn--fa-hia.de; ; fass.de; # faß.de +xn--fa-hia.de; faß.de; ; xn--fa-hia.de; ; ; # faß.de + +# BIDI TESTS + +à\u05D0; ; [B5, B6]; xn--0ca24w; ; ; # àא +a\u0300\u05D0; à\u05D0; [B5, B6]; xn--0ca24w; ; ; # àא +A\u0300\u05D0; à\u05D0; [B5, B6]; xn--0ca24w; ; ; # àא +À\u05D0; à\u05D0; [B5, B6]; xn--0ca24w; ; ; # àא +xn--0ca24w; à\u05D0; [B5, B6]; xn--0ca24w; ; ; # àא +0à.\u05D0; ; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א +0a\u0300.\u05D0; 0à.\u05D0; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א +0A\u0300.\u05D0; 0à.\u05D0; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א +0À.\u05D0; 0à.\u05D0; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א +xn--0-sfa.xn--4db; 0à.\u05D0; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א +à.\u05D0\u0308; ; ; xn--0ca.xn--ssa73l; ; ; # à.א̈ +a\u0300.\u05D0\u0308; à.\u05D0\u0308; ; xn--0ca.xn--ssa73l; ; ; # à.א̈ +A\u0300.\u05D0\u0308; à.\u05D0\u0308; ; xn--0ca.xn--ssa73l; ; ; # à.א̈ +À.\u05D0\u0308; à.\u05D0\u0308; ; xn--0ca.xn--ssa73l; ; ; # à.א̈ +xn--0ca.xn--ssa73l; à.\u05D0\u0308; ; xn--0ca.xn--ssa73l; ; ; # à.א̈ +à.\u05D00\u0660\u05D0; ; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א +a\u0300.\u05D00\u0660\u05D0; à.\u05D00\u0660\u05D0; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א +A\u0300.\u05D00\u0660\u05D0; à.\u05D00\u0660\u05D0; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א +À.\u05D00\u0660\u05D0; à.\u05D00\u0660\u05D0; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א +xn--0ca.xn--0-zhcb98c; à.\u05D00\u0660\u05D0; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א +\u0308.\u05D0; ; [B1, V6]; xn--ssa.xn--4db; ; ; # ̈.א +xn--ssa.xn--4db; \u0308.\u05D0; [B1, V6]; xn--ssa.xn--4db; ; ; # ̈.א +à.\u05D00\u0660; ; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠ +a\u0300.\u05D00\u0660; à.\u05D00\u0660; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠ +A\u0300.\u05D00\u0660; à.\u05D00\u0660; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠ +À.\u05D00\u0660; à.\u05D00\u0660; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠ +xn--0ca.xn--0-zhc74b; à.\u05D00\u0660; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠ +àˇ.\u05D0; ; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א +a\u0300ˇ.\u05D0; àˇ.\u05D0; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א +A\u0300ˇ.\u05D0; àˇ.\u05D0; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א +Àˇ.\u05D0; àˇ.\u05D0; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א +xn--0ca88g.xn--4db; àˇ.\u05D0; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א +à\u0308.\u05D0; ; ; xn--0ca81i.xn--4db; ; ; # à̈.א +a\u0300\u0308.\u05D0; à\u0308.\u05D0; ; xn--0ca81i.xn--4db; ; ; # à̈.א +A\u0300\u0308.\u05D0; à\u0308.\u05D0; ; xn--0ca81i.xn--4db; ; ; # à̈.א +À\u0308.\u05D0; à\u0308.\u05D0; ; xn--0ca81i.xn--4db; ; ; # à̈.א +xn--0ca81i.xn--4db; à\u0308.\u05D0; ; xn--0ca81i.xn--4db; ; ; # à̈.א + +# CONTEXT TESTS + +a\u200Cb; ; [C1]; xn--ab-j1t; ; ab; [] # ab +A\u200CB; a\u200Cb; [C1]; xn--ab-j1t; ; ab; [] # ab +A\u200Cb; a\u200Cb; [C1]; xn--ab-j1t; ; ab; [] # ab +ab; ; ; ; ; ; # ab +xn--ab-j1t; a\u200Cb; [C1]; xn--ab-j1t; ; ; # ab +a\u094D\u200Cb; ; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b +A\u094D\u200CB; a\u094D\u200Cb; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b +A\u094D\u200Cb; a\u094D\u200Cb; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b +xn--ab-fsf; a\u094Db; ; xn--ab-fsf; ; ; # a्b +a\u094Db; ; ; xn--ab-fsf; ; ; # a्b +A\u094DB; a\u094Db; ; xn--ab-fsf; ; ; # a्b +A\u094Db; a\u094Db; ; xn--ab-fsf; ; ; # a्b +xn--ab-fsf604u; a\u094D\u200Cb; ; xn--ab-fsf604u; ; ; # a्b +\u0308\u200C\u0308\u0628b; ; [B1, C1, V6]; xn--b-bcba413a2w8b; ; xn--b-bcba413a; [B1, V6] # ̈̈بb +\u0308\u200C\u0308\u0628B; \u0308\u200C\u0308\u0628b; [B1, C1, V6]; xn--b-bcba413a2w8b; ; xn--b-bcba413a; [B1, V6] # ̈̈بb +xn--b-bcba413a; \u0308\u0308\u0628b; [B1, V6]; xn--b-bcba413a; ; ; # ̈̈بb +xn--b-bcba413a2w8b; \u0308\u200C\u0308\u0628b; [B1, C1, V6]; xn--b-bcba413a2w8b; ; ; # ̈̈بb +a\u0628\u0308\u200C\u0308; ; [B5, B6, C1]; xn--a-ccba213a5w8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈ +A\u0628\u0308\u200C\u0308; a\u0628\u0308\u200C\u0308; [B5, B6, C1]; xn--a-ccba213a5w8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈ +xn--a-ccba213a; a\u0628\u0308\u0308; [B5, B6]; xn--a-ccba213a; ; ; # aب̈̈ +xn--a-ccba213a5w8b; a\u0628\u0308\u200C\u0308; [B5, B6, C1]; xn--a-ccba213a5w8b; ; ; # aب̈̈ +a\u0628\u0308\u200C\u0308\u0628b; ; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb +A\u0628\u0308\u200C\u0308\u0628B; a\u0628\u0308\u200C\u0308\u0628b; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb +A\u0628\u0308\u200C\u0308\u0628b; a\u0628\u0308\u200C\u0308\u0628b; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb +xn--ab-uuba211bca; a\u0628\u0308\u0308\u0628b; [B5]; xn--ab-uuba211bca; ; ; # aب̈̈بb +xn--ab-uuba211bca8057b; a\u0628\u0308\u200C\u0308\u0628b; [B5]; xn--ab-uuba211bca8057b; ; ; # aب̈̈بb +a\u200Db; ; [C2]; xn--ab-m1t; ; ab; [] # ab +A\u200DB; a\u200Db; [C2]; xn--ab-m1t; ; ab; [] # ab +A\u200Db; a\u200Db; [C2]; xn--ab-m1t; ; ab; [] # ab +xn--ab-m1t; a\u200Db; [C2]; xn--ab-m1t; ; ; # ab +a\u094D\u200Db; ; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b +A\u094D\u200DB; a\u094D\u200Db; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b +A\u094D\u200Db; a\u094D\u200Db; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b +xn--ab-fsf014u; a\u094D\u200Db; ; xn--ab-fsf014u; ; ; # a्b +\u0308\u200D\u0308\u0628b; ; [B1, C2, V6]; xn--b-bcba413a7w8b; ; xn--b-bcba413a; [B1, V6] # ̈̈بb +\u0308\u200D\u0308\u0628B; \u0308\u200D\u0308\u0628b; [B1, C2, V6]; xn--b-bcba413a7w8b; ; xn--b-bcba413a; [B1, V6] # ̈̈بb +xn--b-bcba413a7w8b; \u0308\u200D\u0308\u0628b; [B1, C2, V6]; xn--b-bcba413a7w8b; ; ; # ̈̈بb +a\u0628\u0308\u200D\u0308; ; [B5, B6, C2]; xn--a-ccba213abx8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈ +A\u0628\u0308\u200D\u0308; a\u0628\u0308\u200D\u0308; [B5, B6, C2]; xn--a-ccba213abx8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈ +xn--a-ccba213abx8b; a\u0628\u0308\u200D\u0308; [B5, B6, C2]; xn--a-ccba213abx8b; ; ; # aب̈̈ +a\u0628\u0308\u200D\u0308\u0628b; ; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb +A\u0628\u0308\u200D\u0308\u0628B; a\u0628\u0308\u200D\u0308\u0628b; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb +A\u0628\u0308\u200D\u0308\u0628b; a\u0628\u0308\u200D\u0308\u0628b; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb +xn--ab-uuba211bca5157b; a\u0628\u0308\u200D\u0308\u0628b; [B5, C2]; xn--ab-uuba211bca5157b; ; ; # aب̈̈بb + +# SELECTED TESTS + +¡; ; ; xn--7a; ; ; # ¡ +xn--7a; ¡; ; xn--7a; ; ; # ¡ +᧚; ; ; xn--pkf; ; ; # ᧚ +xn--pkf; ᧚; ; xn--pkf; ; ; # ᧚ +""; ; [X4_2]; ; [A4_1, A4_2]; ; # +。; .; [X4_2]; ; [A4_1, A4_2]; ; # . +.; ; [X4_2]; ; [A4_1, A4_2]; ; # . +ꭠ; ; ; xn--3y9a; ; ; # ꭠ +xn--3y9a; ꭠ; ; xn--3y9a; ; ; # ꭠ +1234567890ä1234567890123456789012345678901234567890123456; ; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456 +1234567890a\u03081234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456 +1234567890A\u03081234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456 +1234567890Ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456 +xn--12345678901234567890123456789012345678901234567890123456-fxe; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456 +www.eXample.cOm; www.example.com; ; ; ; ; # www.example.com +Bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de +Bu\u0308cher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de +bu\u0308cher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de +bücher.de; ; ; xn--bcher-kva.de; ; ; # bücher.de +BÜCHER.DE; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de +BU\u0308CHER.DE; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de +xn--bcher-kva.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de +ÖBB; öbb; ; xn--bb-eka; ; ; # öbb +O\u0308BB; öbb; ; xn--bb-eka; ; ; # öbb +o\u0308bb; öbb; ; xn--bb-eka; ; ; # öbb +öbb; ; ; xn--bb-eka; ; ; # öbb +Öbb; öbb; ; xn--bb-eka; ; ; # öbb +O\u0308bb; öbb; ; xn--bb-eka; ; ; # öbb +xn--bb-eka; öbb; ; xn--bb-eka; ; ; # öbb +FAẞ.de; faß.de; ; xn--fa-hia.de; ; fass.de; # faß.de +FAẞ.DE; faß.de; ; xn--fa-hia.de; ; fass.de; # faß.de +βόλος.com; ; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com +βο\u0301λος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com +ΒΟ\u0301ΛΟΣ.COM; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +ΒΌΛΟΣ.COM; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +βόλοσ.com; ; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +βο\u0301λοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +Βο\u0301λοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +Βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +xn--nxasmq6b.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com +Βο\u0301λος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com +Βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com +xn--nxasmm1c.com; βόλος.com; ; xn--nxasmm1c.com; ; ; # βόλος.com +xn--nxasmm1c; βόλος; ; xn--nxasmm1c; ; ; # βόλος +βόλος; ; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος +βο\u0301λος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος +ΒΟ\u0301ΛΟΣ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ +ΒΌΛΟΣ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ +βόλοσ; ; ; xn--nxasmq6b; ; ; # βόλοσ +βο\u0301λοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ +Βο\u0301λοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ +Βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ +xn--nxasmq6b; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ +Βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος +Βο\u0301λος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος +www.ශ\u0DCA\u200Dර\u0DD3.com; ; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com +WWW.ශ\u0DCA\u200Dර\u0DD3.COM; www.ශ\u0DCA\u200Dර\u0DD3.com; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com +Www.ශ\u0DCA\u200Dර\u0DD3.com; www.ශ\u0DCA\u200Dර\u0DD3.com; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com +www.xn--10cl1a0b.com; www.ශ\u0DCAර\u0DD3.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com +www.ශ\u0DCAර\u0DD3.com; ; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com +WWW.ශ\u0DCAර\u0DD3.COM; www.ශ\u0DCAර\u0DD3.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com +Www.ශ\u0DCAර\u0DD3.com; www.ශ\u0DCAර\u0DD3.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com +www.xn--10cl1a0b660p.com; www.ශ\u0DCA\u200Dර\u0DD3.com; ; www.xn--10cl1a0b660p.com; ; ; # www.ශ්රී.com +\u0646\u0627\u0645\u0647\u200C\u0627\u06CC; ; ; xn--mgba3gch31f060k; ; xn--mgba3gch31f; # نامهای +xn--mgba3gch31f; \u0646\u0627\u0645\u0647\u0627\u06CC; ; xn--mgba3gch31f; ; ; # نامهای +\u0646\u0627\u0645\u0647\u0627\u06CC; ; ; xn--mgba3gch31f; ; ; # نامهای +xn--mgba3gch31f060k; \u0646\u0627\u0645\u0647\u200C\u0627\u06CC; ; xn--mgba3gch31f060k; ; ; # نامهای +xn--mgba3gch31f060k.com; \u0646\u0627\u0645\u0647\u200C\u0627\u06CC.com; ; xn--mgba3gch31f060k.com; ; ; # نامهای.com +\u0646\u0627\u0645\u0647\u200C\u0627\u06CC.com; ; ; xn--mgba3gch31f060k.com; ; xn--mgba3gch31f.com; # نامهای.com +\u0646\u0627\u0645\u0647\u200C\u0627\u06CC.COM; \u0646\u0627\u0645\u0647\u200C\u0627\u06CC.com; ; xn--mgba3gch31f060k.com; ; xn--mgba3gch31f.com; # نامهای.com +xn--mgba3gch31f.com; \u0646\u0627\u0645\u0647\u0627\u06CC.com; ; xn--mgba3gch31f.com; ; ; # نامهای.com +\u0646\u0627\u0645\u0647\u0627\u06CC.com; ; ; xn--mgba3gch31f.com; ; ; # نامهای.com +\u0646\u0627\u0645\u0647\u0627\u06CC.COM; \u0646\u0627\u0645\u0647\u0627\u06CC.com; ; xn--mgba3gch31f.com; ; ; # نامهای.com +a.b.c。d。; a.b.c.d.; ; ; [A4_2]; ; # a.b.c.d. +a.b.c。d。; a.b.c.d.; ; ; [A4_2]; ; # a.b.c.d. +A.B.C。D。; a.b.c.d.; ; ; [A4_2]; ; # a.b.c.d. +A.b.c。D。; a.b.c.d.; ; ; [A4_2]; ; # a.b.c.d. +a.b.c.d.; ; ; ; [A4_2]; ; # a.b.c.d. +A.B.C。D。; a.b.c.d.; ; ; [A4_2]; ; # a.b.c.d. +A.b.c。D。; a.b.c.d.; ; ; [A4_2]; ; # a.b.c.d. +U\u0308.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +Ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +u\u0308.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +U\u0308.XN--TDA; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +Ü.XN--TDA; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +Ü.xn--Tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +U\u0308.xn--Tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +xn--tda.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +ü.ü; ; ; xn--tda.xn--tda; ; ; # ü.ü +u\u0308.u\u0308; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +U\u0308.U\u0308; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +Ü.Ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +Ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +U\u0308.u\u0308; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü +xn--u-ccb; u\u0308; [V1]; xn--u-ccb; ; ; # ü +a⒈com; ; [V7]; xn--acom-0w1b; ; ; # a⒈com +a1.com; ; ; ; ; ; # a1.com +A⒈COM; a⒈com; [V7]; xn--acom-0w1b; ; ; # a⒈com +A⒈Com; a⒈com; [V7]; xn--acom-0w1b; ; ; # a⒈com +xn--acom-0w1b; a⒈com; [V7]; xn--acom-0w1b; ; ; # a⒈com +xn--a-ecp.ru; a⒈.ru; [V7]; xn--a-ecp.ru; ; ; # a⒈.ru +xn--0.pt; ; [P4]; ; ; ; # xn--0.pt +xn--a.pt; \u0080.pt; [V7]; xn--a.pt; ; ; # .pt +xn--a-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +xn--a-A\u0308.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +xn--a-a\u0308.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +xn--a-ä.pt; ; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +XN--A-Ä.PT; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +XN--A-A\u0308.PT; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +Xn--A-A\u0308.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +Xn--A-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +xn--xn--a--gua.pt; xn--a-ä.pt; [V2, V4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt +日本語。JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語。JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語。jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語。Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +xn--wgv71a119e.jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語.jp; ; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語.JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語.Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語。jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +日本語。Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp +☕; ; ; xn--53h; ; ; # ☕ +xn--53h; ☕; ; xn--53h; ; ; # ☕ +1.aß\u200C\u200Db\u200C\u200Dcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß\u0302ßz; ; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz +1.ASS\u200C\u200DB\u200C\u200DCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSS\u0302SSZ; 1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.ASS\u200C\u200DB\u200C\u200DCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssyssssssssssssssss\u0302ssz; 1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.Ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssyssssssssssssssss\u0302ssz; 1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.Ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssyssssssssssssssss\u0302ssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.ASSBCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSS\u0302SSZ; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.ASSBCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.Assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.Assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssyssssssssssssssss\u0302ssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; 1.ass\u200C\u200Db\u200C\u200Dcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz +1.Aß\u200C\u200Db\u200C\u200Dcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß\u0302ßz; 1.aß\u200C\u200Db\u200C\u200Dcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß\u0302ßz; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz +1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; 1.aß\u200C\u200Db\u200C\u200Dcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß\u0302ßz; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; ; # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz +\u200Cx\u200Dn\u200C-\u200D-bß; ; [C1, C2]; xn--xn--b-pqa5796ccahd; ; xn--bss; [] # xn--bß +\u200CX\u200DN\u200C-\u200D-BSS; \u200Cx\u200Dn\u200C-\u200D-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss +\u200Cx\u200Dn\u200C-\u200D-bss; ; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss +\u200CX\u200Dn\u200C-\u200D-Bss; \u200Cx\u200Dn\u200C-\u200D-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss +xn--bss; 夙; ; xn--bss; ; ; # 夙 +夙; ; ; xn--bss; ; ; # 夙 +xn--xn--bss-7z6ccid; \u200Cx\u200Dn\u200C-\u200D-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; ; # xn--bss +\u200CX\u200Dn\u200C-\u200D-Bß; \u200Cx\u200Dn\u200C-\u200D-bß; [C1, C2]; xn--xn--b-pqa5796ccahd; ; xn--bss; [] # xn--bß +xn--xn--b-pqa5796ccahd; \u200Cx\u200Dn\u200C-\u200D-bß; [C1, C2]; xn--xn--b-pqa5796ccahd; ; ; # xn--bß +ˣ\u034Fℕ\u200B﹣\u00AD-\u180Cℬ\uFE00ſ\u2064𝔰󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +x\u034FN\u200B-\u00AD-\u180CB\uFE00s\u2064s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +x\u034Fn\u200B-\u00AD-\u180Cb\uFE00s\u2064s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +X\u034FN\u200B-\u00AD-\u180CB\uFE00S\u2064S󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +X\u034Fn\u200B-\u00AD-\u180CB\uFE00s\u2064s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +xn--bssffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +夡夞夜夙; ; ; xn--bssffl; ; ; # 夡夞夜夙 +ˣ\u034Fℕ\u200B﹣\u00AD-\u180Cℬ\uFE00S\u2064𝔰󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +x\u034FN\u200B-\u00AD-\u180CB\uFE00S\u2064s󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +ˣ\u034Fℕ\u200B﹣\u00AD-\u180Cℬ\uFE00s\u2064𝔰󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙 +123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; ; ; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; ; ; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; ; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +ä1234567890123456789012345678901234567890123456789012345; ; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345 +a\u03081234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345 +A\u03081234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345 +Ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345 +xn--1234567890123456789012345678901234567890123456789012345-9te; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345 +123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890a\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.1234567890a\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890a\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901C; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901C; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890a\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890a\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890a\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +a.b..-q--a-.e; ; [V2, V3, X4_2]; ; [V2, V3, A4_2]; ; # a.b..-q--a-.e +a.b..-q--ä-.e; ; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +a.b..-q--a\u0308-.e; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +A.B..-Q--A\u0308-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +A.B..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +A.b..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +A.b..-Q--A\u0308-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +a.b..xn---q----jra.e; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e +a..c; ; [X4_2]; ; [A4_2]; ; # a..c +a.-b.; ; [V3]; ; [V3, A4_2]; ; # a.-b. +a.b-.c; ; [V3]; ; ; ; # a.b-.c +a.-.c; ; [V3]; ; ; ; # a.-.c +a.bc--de.f; ; [V2]; ; ; ; # a.bc--de.f +xn--xn---epa; xn--é; [V2, V4]; xn--xn---epa; ; ; # xn--é +ä.\u00AD.c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c +a\u0308.\u00AD.c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c +A\u0308.\u00AD.C; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c +Ä.\u00AD.C; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c +xn--4ca..c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c +ä.-b.; ; [V3]; xn--4ca.-b.; [V3, A4_2]; ; # ä.-b. +a\u0308.-b.; ä.-b.; [V3]; xn--4ca.-b.; [V3, A4_2]; ; # ä.-b. +A\u0308.-B.; ä.-b.; [V3]; xn--4ca.-b.; [V3, A4_2]; ; # ä.-b. +Ä.-B.; ä.-b.; [V3]; xn--4ca.-b.; [V3, A4_2]; ; # ä.-b. +xn--4ca.-b.; ä.-b.; [V3]; xn--4ca.-b.; [V3, A4_2]; ; # ä.-b. +ä.b-.c; ; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +a\u0308.b-.c; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +A\u0308.B-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +Ä.B-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +Ä.b-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +A\u0308.b-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +xn--4ca.b-.c; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c +ä.-.c; ; [V3]; xn--4ca.-.c; ; ; # ä.-.c +a\u0308.-.c; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c +A\u0308.-.C; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c +Ä.-.C; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c +xn--4ca.-.c; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c +ä.bc--de.f; ; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +a\u0308.bc--de.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +A\u0308.BC--DE.F; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +Ä.BC--DE.F; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +Ä.bc--De.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +A\u0308.bc--De.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +xn--4ca.bc--de.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f +a.b.\u0308c.d; ; [V6]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d +A.B.\u0308C.D; a.b.\u0308c.d; [V6]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d +A.b.\u0308c.d; a.b.\u0308c.d; [V6]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d +a.b.xn--c-bcb.d; a.b.\u0308c.d; [V6]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d +A0; a0; ; ; ; ; # a0 +0A; 0a; ; ; ; ; # 0a +0A.\u05D0; 0a.\u05D0; [B1]; 0a.xn--4db; ; ; # 0a.א +0a.\u05D0; ; [B1]; 0a.xn--4db; ; ; # 0a.א +0a.xn--4db; 0a.\u05D0; [B1]; 0a.xn--4db; ; ; # 0a.א +c.xn--0-eha.xn--4db; c.0ü.\u05D0; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +b-.\u05D0; ; [B6, V3]; b-.xn--4db; ; ; # b-.א +B-.\u05D0; b-.\u05D0; [B6, V3]; b-.xn--4db; ; ; # b-.א +b-.xn--4db; b-.\u05D0; [B6, V3]; b-.xn--4db; ; ; # b-.א +d.xn----dha.xn--4db; d.ü-.\u05D0; [B6, V3]; d.xn----dha.xn--4db; ; ; # d.ü-.א +a\u05D0; ; [B5, B6]; xn--a-0hc; ; ; # aא +A\u05D0; a\u05D0; [B5, B6]; xn--a-0hc; ; ; # aא +xn--a-0hc; a\u05D0; [B5, B6]; xn--a-0hc; ; ; # aא +\u05D0\u05C7; ; ; xn--vdbr; ; ; # אׇ +xn--vdbr; \u05D0\u05C7; ; xn--vdbr; ; ; # אׇ +\u05D09\u05C7; ; ; xn--9-ihcz; ; ; # א9ׇ +xn--9-ihcz; \u05D09\u05C7; ; xn--9-ihcz; ; ; # א9ׇ +\u05D0a\u05C7; ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ +\u05D0A\u05C7; \u05D0a\u05C7; [B2, B3]; xn--a-ihcz; ; ; # אaׇ +xn--a-ihcz; \u05D0a\u05C7; [B2, B3]; xn--a-ihcz; ; ; # אaׇ +\u05D0\u05EA; ; ; xn--4db6c; ; ; # את +xn--4db6c; \u05D0\u05EA; ; xn--4db6c; ; ; # את +\u05D0\u05F3\u05EA; ; ; xn--4db6c0a; ; ; # א׳ת +xn--4db6c0a; \u05D0\u05F3\u05EA; ; xn--4db6c0a; ; ; # א׳ת +a\u05D0Tz; a\u05D0tz; [B5]; xn--atz-qpe; ; ; # aאtz +a\u05D0tz; ; [B5]; xn--atz-qpe; ; ; # aאtz +A\u05D0TZ; a\u05D0tz; [B5]; xn--atz-qpe; ; ; # aאtz +A\u05D0tz; a\u05D0tz; [B5]; xn--atz-qpe; ; ; # aאtz +xn--atz-qpe; a\u05D0tz; [B5]; xn--atz-qpe; ; ; # aאtz +\u05D0T\u05EA; \u05D0t\u05EA; [B2]; xn--t-zhc3f; ; ; # אtת +\u05D0t\u05EA; ; [B2]; xn--t-zhc3f; ; ; # אtת +xn--t-zhc3f; \u05D0t\u05EA; [B2]; xn--t-zhc3f; ; ; # אtת +\u05D07\u05EA; ; ; xn--7-zhc3f; ; ; # א7ת +xn--7-zhc3f; \u05D07\u05EA; ; xn--7-zhc3f; ; ; # א7ת +\u05D0\u0667\u05EA; ; ; xn--4db6c6t; ; ; # א٧ת +xn--4db6c6t; \u05D0\u0667\u05EA; ; xn--4db6c6t; ; ; # א٧ת +a7\u0667z; ; [B5]; xn--a7z-06e; ; ; # a7٧z +A7\u0667Z; a7\u0667z; [B5]; xn--a7z-06e; ; ; # a7٧z +A7\u0667z; a7\u0667z; [B5]; xn--a7z-06e; ; ; # a7٧z +xn--a7z-06e; a7\u0667z; [B5]; xn--a7z-06e; ; ; # a7٧z +\u05D07\u0667\u05EA; ; [B4]; xn--7-zhc3fty; ; ; # א7٧ת +xn--7-zhc3fty; \u05D07\u0667\u05EA; [B4]; xn--7-zhc3fty; ; ; # א7٧ת +ஹ\u0BCD\u200D; ; ; xn--dmc4b194h; ; xn--dmc4b; # ஹ் +xn--dmc4b; ஹ\u0BCD; ; xn--dmc4b; ; ; # ஹ் +ஹ\u0BCD; ; ; xn--dmc4b; ; ; # ஹ் +xn--dmc4b194h; ஹ\u0BCD\u200D; ; xn--dmc4b194h; ; ; # ஹ் +ஹ\u200D; ; [C2]; xn--dmc225h; ; xn--dmc; [] # ஹ +xn--dmc; ஹ; ; xn--dmc; ; ; # ஹ +ஹ; ; ; xn--dmc; ; ; # ஹ +xn--dmc225h; ஹ\u200D; [C2]; xn--dmc225h; ; ; # ஹ +\u200D; ; [C2]; xn--1ug; ; ""; [A4_1, A4_2] # +xn--1ug; \u200D; [C2]; xn--1ug; ; ; # +ஹ\u0BCD\u200C; ; ; xn--dmc4by94h; ; xn--dmc4b; # ஹ் +xn--dmc4by94h; ஹ\u0BCD\u200C; ; xn--dmc4by94h; ; ; # ஹ் +ஹ\u200C; ; [C1]; xn--dmc025h; ; xn--dmc; [] # ஹ +xn--dmc025h; ஹ\u200C; [C1]; xn--dmc025h; ; ; # ஹ +\u200C; ; [C1]; xn--0ug; ; ""; [A4_1, A4_2] # +xn--0ug; \u200C; [C1]; xn--0ug; ; ; # +\u0644\u0670\u200C\u06ED\u06EF; ; ; xn--ghb2gxqia7523a; ; xn--ghb2gxqia; # لٰۭۯ +xn--ghb2gxqia; \u0644\u0670\u06ED\u06EF; ; xn--ghb2gxqia; ; ; # لٰۭۯ +\u0644\u0670\u06ED\u06EF; ; ; xn--ghb2gxqia; ; ; # لٰۭۯ +xn--ghb2gxqia7523a; \u0644\u0670\u200C\u06ED\u06EF; ; xn--ghb2gxqia7523a; ; ; # لٰۭۯ +\u0644\u0670\u200C\u06EF; ; ; xn--ghb2g3qq34f; ; xn--ghb2g3q; # لٰۯ +xn--ghb2g3q; \u0644\u0670\u06EF; ; xn--ghb2g3q; ; ; # لٰۯ +\u0644\u0670\u06EF; ; ; xn--ghb2g3q; ; ; # لٰۯ +xn--ghb2g3qq34f; \u0644\u0670\u200C\u06EF; ; xn--ghb2g3qq34f; ; ; # لٰۯ +\u0644\u200C\u06ED\u06EF; ; ; xn--ghb25aga828w; ; xn--ghb25aga; # لۭۯ +xn--ghb25aga; \u0644\u06ED\u06EF; ; xn--ghb25aga; ; ; # لۭۯ +\u0644\u06ED\u06EF; ; ; xn--ghb25aga; ; ; # لۭۯ +xn--ghb25aga828w; \u0644\u200C\u06ED\u06EF; ; xn--ghb25aga828w; ; ; # لۭۯ +\u0644\u200C\u06EF; ; ; xn--ghb65a953d; ; xn--ghb65a; # لۯ +xn--ghb65a; \u0644\u06EF; ; xn--ghb65a; ; ; # لۯ +\u0644\u06EF; ; ; xn--ghb65a; ; ; # لۯ +xn--ghb65a953d; \u0644\u200C\u06EF; ; xn--ghb65a953d; ; ; # لۯ +\u0644\u0670\u200C\u06ED; ; [B3, C1]; xn--ghb2gxqy34f; ; xn--ghb2gxq; [] # لٰۭ +xn--ghb2gxq; \u0644\u0670\u06ED; ; xn--ghb2gxq; ; ; # لٰۭ +\u0644\u0670\u06ED; ; ; xn--ghb2gxq; ; ; # لٰۭ +xn--ghb2gxqy34f; \u0644\u0670\u200C\u06ED; [B3, C1]; xn--ghb2gxqy34f; ; ; # لٰۭ +\u06EF\u200C\u06EF; ; [C1]; xn--cmba004q; ; xn--cmba; [] # ۯۯ +xn--cmba; \u06EF\u06EF; ; xn--cmba; ; ; # ۯۯ +\u06EF\u06EF; ; ; xn--cmba; ; ; # ۯۯ +xn--cmba004q; \u06EF\u200C\u06EF; [C1]; xn--cmba004q; ; ; # ۯۯ +\u0644\u200C; ; [B3, C1]; xn--ghb413k; ; xn--ghb; [] # ل +xn--ghb; \u0644; ; xn--ghb; ; ; # ل +\u0644; ; ; xn--ghb; ; ; # ل +xn--ghb413k; \u0644\u200C; [B3, C1]; xn--ghb413k; ; ; # ل +a。。b; a..b; [X4_2]; ; [A4_2]; ; # a..b +A。。B; a..b; [X4_2]; ; [A4_2]; ; # a..b +a..b; ; [X4_2]; ; [A4_2]; ; # a..b +\u200D。。\u06B9\u200C; \u200D..\u06B9\u200C; [B1, B3, C1, C2, X4_2]; xn--1ug..xn--skb080k; [B1, B3, C1, C2, A4_2]; ..xn--skb; [A4_2] # ..ڹ +..xn--skb; ..\u06B9; [X4_2]; ..xn--skb; [A4_2]; ; # ..ڹ +xn--1ug..xn--skb080k; \u200D..\u06B9\u200C; [B1, B3, C1, C2, X4_2]; xn--1ug..xn--skb080k; [B1, B3, C1, C2, A4_2]; ; # ..ڹ +\u05D00\u0660; ; [B4]; xn--0-zhc74b; ; ; # א0٠ +xn--0-zhc74b; \u05D00\u0660; [B4]; xn--0-zhc74b; ; ; # א0٠ +$; ; [U1]; ; ; ; # $ +⑷.four; (4).four; [U1]; ; ; ; # (4).four +(4).four; ; [U1]; ; ; ; # (4).four +⑷.FOUR; (4).four; [U1]; ; ; ; # (4).four +⑷.Four; (4).four; [U1]; ; ; ; # (4).four +a\uD900z; ; [V7]; ; [V7, A3]; ; # az +A\uD900Z; a\uD900z; [V7]; ; [V7, A3]; ; # az +xn--; ""; [P4, X4_2]; ; [P4, A4_1, A4_2]; ; # +xn---; ; [P4]; ; ; ; # xn--- +xn--ASCII-; ascii; [P4]; ; ; ; # ascii +ascii; ; ; ; ; ; # ascii +xn--unicode-.org; unicode.org; [P4]; ; ; ; # unicode.org +unicode.org; ; ; ; ; ; # unicode.org +陋㛼当𤎫竮䗗; 陋㛼当𤎫竮䗗; ; xn--snl253bgitxhzwu2arn60c; ; ; # 陋㛼当𤎫竮䗗 +陋㛼当𤎫竮䗗; ; ; xn--snl253bgitxhzwu2arn60c; ; ; # 陋㛼当𤎫竮䗗 +xn--snl253bgitxhzwu2arn60c; 陋㛼当𤎫竮䗗; ; xn--snl253bgitxhzwu2arn60c; ; ; # 陋㛼当𤎫竮䗗 +電𡍪弳䎫窮䵗; ; ; xn--kbo60w31ob3z6t3av9z5b; ; ; # 電𡍪弳䎫窮䵗 +xn--kbo60w31ob3z6t3av9z5b; 電𡍪弳䎫窮䵗; ; xn--kbo60w31ob3z6t3av9z5b; ; ; # 電𡍪弳䎫窮䵗 +xn--A-1ga; aö; ; xn--a-1ga; ; ; # aö +aö; ; ; xn--a-1ga; ; ; # aö +ao\u0308; aö; ; xn--a-1ga; ; ; # aö +AO\u0308; aö; ; xn--a-1ga; ; ; # aö +AÖ; aö; ; xn--a-1ga; ; ; # aö +Aö; aö; ; xn--a-1ga; ; ; # aö +Ao\u0308; aö; ; xn--a-1ga; ; ; # aö +=\u0338; ≠; ; xn--1ch; ; ; # ≠ +≠; ; ; xn--1ch; ; ; # ≠ +=\u0338; ≠; ; xn--1ch; ; ; # ≠ +xn--1ch; ≠; ; xn--1ch; ; ; # ≠ + +# RANDOMIZED TESTS + +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b. +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a. +123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b +c.0ü.\u05D0; ; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +c.0u\u0308.\u05D0; c.0ü.\u05D0; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +C.0U\u0308.\u05D0; c.0ü.\u05D0; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +C.0Ü.\u05D0; c.0ü.\u05D0; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +C.0ü.\u05D0; c.0ü.\u05D0; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +C.0u\u0308.\u05D0; c.0ü.\u05D0; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א +⒕∝\u065F򓤦.-󠄯; ⒕∝\u065F򓤦.-; [V3, V7]; xn--7hb713lfwbi1311b.-; ; ; # ⒕∝ٟ.- +14.∝\u065F򓤦.-󠄯; 14.∝\u065F򓤦.-; [V3, V7]; 14.xn--7hb713l3v90n.-; ; ; # 14.∝ٟ.- +14.xn--7hb713l3v90n.-; 14.∝\u065F򓤦.-; [V3, V7]; 14.xn--7hb713l3v90n.-; ; ; # 14.∝ٟ.- +xn--7hb713lfwbi1311b.-; ⒕∝\u065F򓤦.-; [V3, V7]; xn--7hb713lfwbi1311b.-; ; ; # ⒕∝ٟ.- +ꡣ.\u07CF; ; ; xn--8c9a.xn--qsb; ; ; # ꡣ.ߏ +xn--8c9a.xn--qsb; ꡣ.\u07CF; ; xn--8c9a.xn--qsb; ; ; # ꡣ.ߏ +≯\u0603。-; ≯\u0603.-; [B1, V3, V7]; xn--lfb566l.-; ; ; # ≯.- +>\u0338\u0603。-; ≯\u0603.-; [B1, V3, V7]; xn--lfb566l.-; ; ; # ≯.- +≯\u0603。-; ≯\u0603.-; [B1, V3, V7]; xn--lfb566l.-; ; ; # ≯.- +>\u0338\u0603。-; ≯\u0603.-; [B1, V3, V7]; xn--lfb566l.-; ; ; # ≯.- +xn--lfb566l.-; ≯\u0603.-; [B1, V3, V7]; xn--lfb566l.-; ; ; # ≯.- +⾛𐹧⾕.\u115F󠗰ςႭ; 走𐹧谷.󠗰ςⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--3xa652s5d17u; ; xn--6g3a1x434z.xn--4xa452s5d17u; # 走𐹧谷.ςⴍ +走𐹧谷.\u115F󠗰ςႭ; 走𐹧谷.󠗰ςⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--3xa652s5d17u; ; xn--6g3a1x434z.xn--4xa452s5d17u; # 走𐹧谷.ςⴍ +走𐹧谷.\u115F󠗰ςⴍ; 走𐹧谷.󠗰ςⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--3xa652s5d17u; ; xn--6g3a1x434z.xn--4xa452s5d17u; # 走𐹧谷.ςⴍ +走𐹧谷.\u115F󠗰ΣႭ; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +走𐹧谷.\u115F󠗰σⴍ; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +走𐹧谷.\u115F󠗰Σⴍ; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +xn--6g3a1x434z.xn--4xa452s5d17u; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +xn--6g3a1x434z.xn--3xa652s5d17u; 走𐹧谷.󠗰ςⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--3xa652s5d17u; ; ; # 走𐹧谷.ςⴍ +⾛𐹧⾕.\u115F󠗰ςⴍ; 走𐹧谷.󠗰ςⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--3xa652s5d17u; ; xn--6g3a1x434z.xn--4xa452s5d17u; # 走𐹧谷.ςⴍ +⾛𐹧⾕.\u115F󠗰ΣႭ; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +⾛𐹧⾕.\u115F󠗰σⴍ; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +⾛𐹧⾕.\u115F󠗰Σⴍ; 走𐹧谷.󠗰σⴍ; [B1, B5, V7]; xn--6g3a1x434z.xn--4xa452s5d17u; ; ; # 走𐹧谷.σⴍ +xn--6g3a1x434z.xn--4xa180eotvh7453a; 走𐹧谷.\u115F󠗰σⴍ; [B5, V7]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ +xn--6g3a1x434z.xn--4xa627dhpae6345i; 走𐹧谷.\u115F󠗰σႭ; [B5, V7]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ +xn--6g3a1x434z.xn--3xa380eotvh7453a; 走𐹧谷.\u115F󠗰ςⴍ; [B5, V7]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; ; # 走𐹧谷.ςⴍ +xn--6g3a1x434z.xn--3xa827dhpae6345i; 走𐹧谷.\u115F󠗰ςႭ; [B5, V7]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; ; # 走𐹧谷.ςႭ +\u200D≠ᢙ≯.솣-ᡴႠ; \u200D≠ᢙ≯.솣-ᡴⴀ; [C2]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [] # ≠ᢙ≯.솣-ᡴⴀ +\u200D=\u0338ᢙ>\u0338.솣-ᡴႠ; \u200D≠ᢙ≯.솣-ᡴⴀ; [C2]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [] # ≠ᢙ≯.솣-ᡴⴀ +\u200D=\u0338ᢙ>\u0338.솣-ᡴⴀ; \u200D≠ᢙ≯.솣-ᡴⴀ; [C2]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [] # ≠ᢙ≯.솣-ᡴⴀ +\u200D≠ᢙ≯.솣-ᡴⴀ; ; [C2]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [] # ≠ᢙ≯.솣-ᡴⴀ +xn--jbf911clb.xn----p9j493ivi4l; ≠ᢙ≯.솣-ᡴⴀ; ; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ +≠ᢙ≯.솣-ᡴⴀ; ; ; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ +=\u0338ᢙ>\u0338.솣-ᡴⴀ; ≠ᢙ≯.솣-ᡴⴀ; ; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ +=\u0338ᢙ>\u0338.솣-ᡴႠ; ≠ᢙ≯.솣-ᡴⴀ; ; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ +≠ᢙ≯.솣-ᡴႠ; ≠ᢙ≯.솣-ᡴⴀ; ; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ +xn--jbf929a90b0b.xn----p9j493ivi4l; \u200D≠ᢙ≯.솣-ᡴⴀ; [C2]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ +xn--jbf911clb.xn----6zg521d196p; ≠ᢙ≯.솣-ᡴႠ; [V7]; xn--jbf911clb.xn----6zg521d196p; ; ; # ≠ᢙ≯.솣-ᡴႠ +xn--jbf929a90b0b.xn----6zg521d196p; \u200D≠ᢙ≯.솣-ᡴႠ; [C2, V7]; xn--jbf929a90b0b.xn----6zg521d196p; ; ; # ≠ᢙ≯.솣-ᡴႠ +񯞜.𐿇\u0FA2\u077D\u0600; 񯞜.𐿇\u0FA1\u0FB7\u077D\u0600; [V7]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ +񯞜.𐿇\u0FA1\u0FB7\u077D\u0600; 񯞜.𐿇\u0FA1\u0FB7\u077D\u0600; [V7]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ +񯞜.𐿇\u0FA1\u0FB7\u077D\u0600; ; [V7]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ +xn--gw68a.xn--ifb57ev2psc6027m; 񯞜.𐿇\u0FA1\u0FB7\u077D\u0600; [V7]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ +𣳔\u0303.𑓂; ; [V6]; xn--nsa95820a.xn--wz1d; ; ; # 𣳔̃.𑓂 +xn--nsa95820a.xn--wz1d; 𣳔\u0303.𑓂; [V6]; xn--nsa95820a.xn--wz1d; ; ; # 𣳔̃.𑓂 +𞤀𞥅񘐱。󠄌Ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, V7]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ +𞤢𞥅񘐱。󠄌ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, V7]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ +xn--9d6hgcy3556a.xn--rlju750b; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, V7]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ +xn--9d6hgcy3556a.xn--7nd0578e; 𞤢𞥅񘐱.Ⴣꡥ; [B2, B3, V7]; xn--9d6hgcy3556a.xn--7nd0578e; ; ; # 𞤢𞥅.Ⴣꡥ +𞤀𞥅񘐱。󠄌ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, V7]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ +\u08E2𑁿ς𖬱。󠅡렧; \u08E2𑁿ς𖬱.렧; [B1, V7]; xn--3xa73xp48ys2xc.xn--kn2b; ; xn--4xa53xp48ys2xc.xn--kn2b; # 𑁿ς𖬱.렧 +\u08E2𑁿ς𖬱。󠅡렧; \u08E2𑁿ς𖬱.렧; [B1, V7]; xn--3xa73xp48ys2xc.xn--kn2b; ; xn--4xa53xp48ys2xc.xn--kn2b; # 𑁿ς𖬱.렧 +\u08E2𑁿Σ𖬱。󠅡렧; \u08E2𑁿σ𖬱.렧; [B1, V7]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧 +\u08E2𑁿Σ𖬱。󠅡렧; \u08E2𑁿σ𖬱.렧; [B1, V7]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧 +\u08E2𑁿σ𖬱。󠅡렧; \u08E2𑁿σ𖬱.렧; [B1, V7]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧 +\u08E2𑁿σ𖬱。󠅡렧; \u08E2𑁿σ𖬱.렧; [B1, V7]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧 +xn--4xa53xp48ys2xc.xn--kn2b; \u08E2𑁿σ𖬱.렧; [B1, V7]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧 +xn--3xa73xp48ys2xc.xn--kn2b; \u08E2𑁿ς𖬱.렧; [B1, V7]; xn--3xa73xp48ys2xc.xn--kn2b; ; ; # 𑁿ς𖬱.렧 +-\u200D。𞤍\u200C\u200D⒈; -\u200D.𞤯\u200C\u200D⒈; [B1, C1, C2, V3, V7]; xn----ugn.xn--0ugc555aiv51d; ; -.xn--tsh3666n; [B1, V3, V7] # -.𞤯⒈ +-\u200D。𞤍\u200C\u200D1.; -\u200D.𞤯\u200C\u200D1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; [B1, C1, C2, V3, A4_2]; -.xn--1-0i8r.; [B1, V3, A4_2] # -.𞤯1. +-\u200D。𞤯\u200C\u200D1.; -\u200D.𞤯\u200C\u200D1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; [B1, C1, C2, V3, A4_2]; -.xn--1-0i8r.; [B1, V3, A4_2] # -.𞤯1. +-.xn--1-0i8r.; -.𞤯1.; [B1, V3]; -.xn--1-0i8r.; [B1, V3, A4_2]; ; # -.𞤯1. +xn----ugn.xn--1-rgnd61297b.; -\u200D.𞤯\u200C\u200D1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; [B1, C1, C2, V3, A4_2]; ; # -.𞤯1. +-\u200D。𞤯\u200C\u200D⒈; -\u200D.𞤯\u200C\u200D⒈; [B1, C1, C2, V3, V7]; xn----ugn.xn--0ugc555aiv51d; ; -.xn--tsh3666n; [B1, V3, V7] # -.𞤯⒈ +-.xn--tsh3666n; -.𞤯⒈; [B1, V3, V7]; -.xn--tsh3666n; ; ; # -.𞤯⒈ +xn----ugn.xn--0ugc555aiv51d; -\u200D.𞤯\u200C\u200D⒈; [B1, C1, C2, V3, V7]; xn----ugn.xn--0ugc555aiv51d; ; ; # -.𞤯⒈ +\u200C򅎭.Ⴒ𑇀; \u200C򅎭.ⴒ𑇀; [C1, V7]; xn--0ug15083f.xn--9kj2034e; ; xn--bn95b.xn--9kj2034e; [V7] # .ⴒ𑇀 +\u200C򅎭.ⴒ𑇀; ; [C1, V7]; xn--0ug15083f.xn--9kj2034e; ; xn--bn95b.xn--9kj2034e; [V7] # .ⴒ𑇀 +xn--bn95b.xn--9kj2034e; 򅎭.ⴒ𑇀; [V7]; xn--bn95b.xn--9kj2034e; ; ; # .ⴒ𑇀 +xn--0ug15083f.xn--9kj2034e; \u200C򅎭.ⴒ𑇀; [C1, V7]; xn--0ug15083f.xn--9kj2034e; ; ; # .ⴒ𑇀 +xn--bn95b.xn--qnd6272k; 򅎭.Ⴒ𑇀; [V7]; xn--bn95b.xn--qnd6272k; ; ; # .Ⴒ𑇀 +xn--0ug15083f.xn--qnd6272k; \u200C򅎭.Ⴒ𑇀; [C1, V7]; xn--0ug15083f.xn--qnd6272k; ; ; # .Ⴒ𑇀 +繱𑖿\u200D.8︒; 繱𑖿\u200D.8︒; [V7]; xn--1ug6928ac48e.xn--8-o89h; ; xn--gl0as212a.xn--8-o89h; # 繱𑖿.8︒ +繱𑖿\u200D.8。; 繱𑖿\u200D.8.; ; xn--1ug6928ac48e.8.; [A4_2]; xn--gl0as212a.8.; # 繱𑖿.8. +xn--gl0as212a.i.; 繱𑖿.i.; ; xn--gl0as212a.i.; [A4_2]; ; # 繱𑖿.i. +繱𑖿.i.; ; ; xn--gl0as212a.i.; [A4_2]; ; # 繱𑖿.i. +繱𑖿.I.; 繱𑖿.i.; ; xn--gl0as212a.i.; [A4_2]; ; # 繱𑖿.i. +xn--1ug6928ac48e.i.; 繱𑖿\u200D.i.; ; xn--1ug6928ac48e.i.; [A4_2]; ; # 繱𑖿.i. +繱𑖿\u200D.i.; ; ; xn--1ug6928ac48e.i.; [A4_2]; xn--gl0as212a.i.; # 繱𑖿.i. +繱𑖿\u200D.I.; 繱𑖿\u200D.i.; ; xn--1ug6928ac48e.i.; [A4_2]; xn--gl0as212a.i.; # 繱𑖿.i. +xn--gl0as212a.xn--8-o89h; 繱𑖿.8︒; [V7]; xn--gl0as212a.xn--8-o89h; ; ; # 繱𑖿.8︒ +xn--1ug6928ac48e.xn--8-o89h; 繱𑖿\u200D.8︒; [V7]; xn--1ug6928ac48e.xn--8-o89h; ; ; # 繱𑖿.8︒ +󠆾.𞀈; .𞀈; [V6, X4_2]; .xn--ph4h; [V6, A4_2]; ; # .𞀈 +󠆾.𞀈; .𞀈; [V6, X4_2]; .xn--ph4h; [V6, A4_2]; ; # .𞀈 +.xn--ph4h; .𞀈; [V6, X4_2]; .xn--ph4h; [V6, A4_2]; ; # .𞀈 +ß\u06EB。\u200D; ß\u06EB.\u200D; [C2]; xn--zca012a.xn--1ug; ; xn--ss-59d.; [A4_2] # ß۫. +SS\u06EB。\u200D; ss\u06EB.\u200D; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [A4_2] # ss۫. +ss\u06EB。\u200D; ss\u06EB.\u200D; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [A4_2] # ss۫. +Ss\u06EB。\u200D; ss\u06EB.\u200D; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [A4_2] # ss۫. +xn--ss-59d.; ss\u06EB.; ; xn--ss-59d.; [A4_2]; ; # ss۫. +ss\u06EB.; ; ; xn--ss-59d.; [A4_2]; ; # ss۫. +SS\u06EB.; ss\u06EB.; ; xn--ss-59d.; [A4_2]; ; # ss۫. +Ss\u06EB.; ss\u06EB.; ; xn--ss-59d.; [A4_2]; ; # ss۫. +xn--ss-59d.xn--1ug; ss\u06EB.\u200D; [C2]; xn--ss-59d.xn--1ug; ; ; # ss۫. +xn--zca012a.xn--1ug; ß\u06EB.\u200D; [C2]; xn--zca012a.xn--1ug; ; ; # ß۫. +󠐵\u200C⒈.󠎇; 󠐵\u200C⒈.󠎇; [C1, V7]; xn--0ug88o47900b.xn--tv36e; ; xn--tshz2001k.xn--tv36e; [V7] # ⒈. +󠐵\u200C1..󠎇; ; [C1, V7, X4_2]; xn--1-rgn37671n..xn--tv36e; [C1, V7, A4_2]; xn--1-bs31m..xn--tv36e; [V7, A4_2] # 1.. +xn--1-bs31m..xn--tv36e; 󠐵1..󠎇; [V7, X4_2]; xn--1-bs31m..xn--tv36e; [V7, A4_2]; ; # 1.. +xn--1-rgn37671n..xn--tv36e; 󠐵\u200C1..󠎇; [C1, V7, X4_2]; xn--1-rgn37671n..xn--tv36e; [C1, V7, A4_2]; ; # 1.. +xn--tshz2001k.xn--tv36e; 󠐵⒈.󠎇; [V7]; xn--tshz2001k.xn--tv36e; ; ; # ⒈. +xn--0ug88o47900b.xn--tv36e; 󠐵\u200C⒈.󠎇; [C1, V7]; xn--0ug88o47900b.xn--tv36e; ; ; # ⒈. +󟈣\u065F\uAAB2ß。󌓧; 󟈣\u065F\uAAB2ß.󌓧; [V7]; xn--zca92z0t7n5w96j.xn--bb79d; ; xn--ss-3xd2839nncy1m.xn--bb79d; # ٟꪲß. +󟈣\u065F\uAAB2SS。󌓧; 󟈣\u065F\uAAB2ss.󌓧; [V7]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss. +󟈣\u065F\uAAB2ss。󌓧; 󟈣\u065F\uAAB2ss.󌓧; [V7]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss. +󟈣\u065F\uAAB2Ss。󌓧; 󟈣\u065F\uAAB2ss.󌓧; [V7]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss. +xn--ss-3xd2839nncy1m.xn--bb79d; 󟈣\u065F\uAAB2ss.󌓧; [V7]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss. +xn--zca92z0t7n5w96j.xn--bb79d; 󟈣\u065F\uAAB2ß.󌓧; [V7]; xn--zca92z0t7n5w96j.xn--bb79d; ; ; # ٟꪲß. +\u0774\u200C𞤿。𽘐䉜\u200D񿤼; \u0774\u200C𞤿.𽘐䉜\u200D񿤼; [C1, C2, V7]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; xn--4pb2977v.xn--z0nt555ukbnv; [V7] # ݴ𞤿.䉜 +\u0774\u200C𞤝。𽘐䉜\u200D񿤼; \u0774\u200C𞤿.𽘐䉜\u200D񿤼; [C1, C2, V7]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; xn--4pb2977v.xn--z0nt555ukbnv; [V7] # ݴ𞤿.䉜 +xn--4pb2977v.xn--z0nt555ukbnv; \u0774𞤿.𽘐䉜񿤼; [V7]; xn--4pb2977v.xn--z0nt555ukbnv; ; ; # ݴ𞤿.䉜 +xn--4pb607jjt73a.xn--1ug236ke314donv1a; \u0774\u200C𞤿.𽘐䉜\u200D񿤼; [C1, C2, V7]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; ; # ݴ𞤿.䉜 +򔭜ςᡱ⒈.≮𑄳\u200D𐮍; ; [B1, V7]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # ςᡱ⒈.≮𑄳𐮍 +򔭜ςᡱ⒈.<\u0338𑄳\u200D𐮍; 򔭜ςᡱ⒈.≮𑄳\u200D𐮍; [B1, V7]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # ςᡱ⒈.≮𑄳𐮍 +򔭜ςᡱ1..≮𑄳\u200D𐮍; ; [B1, V7, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # ςᡱ1..≮𑄳𐮍 +򔭜ςᡱ1..<\u0338𑄳\u200D𐮍; 򔭜ςᡱ1..≮𑄳\u200D𐮍; [B1, V7, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # ςᡱ1..≮𑄳𐮍 +򔭜Σᡱ1..<\u0338𑄳\u200D𐮍; 򔭜σᡱ1..≮𑄳\u200D𐮍; [B1, V7, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍 +򔭜Σᡱ1..≮𑄳\u200D𐮍; 򔭜σᡱ1..≮𑄳\u200D𐮍; [B1, V7, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍 +򔭜σᡱ1..≮𑄳\u200D𐮍; ; [B1, V7, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍 +򔭜σᡱ1..<\u0338𑄳\u200D𐮍; 򔭜σᡱ1..≮𑄳\u200D𐮍; [B1, V7, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍 +xn--1-zmb699meq63t..xn--gdh5392g6sd; 򔭜σᡱ1..≮𑄳𐮍; [B1, V7, X4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; [B1, V7, A4_2]; ; # σᡱ1..≮𑄳𐮍 +xn--1-zmb699meq63t..xn--1ug85gn777ahze; 򔭜σᡱ1..≮𑄳\u200D𐮍; [B1, V7, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; ; # σᡱ1..≮𑄳𐮍 +xn--1-xmb999meq63t..xn--1ug85gn777ahze; 򔭜ςᡱ1..≮𑄳\u200D𐮍; [B1, V7, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, V7, A4_2]; ; # ςᡱ1..≮𑄳𐮍 +򔭜Σᡱ⒈.<\u0338𑄳\u200D𐮍; 򔭜σᡱ⒈.≮𑄳\u200D𐮍; [B1, V7]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍 +򔭜Σᡱ⒈.≮𑄳\u200D𐮍; 򔭜σᡱ⒈.≮𑄳\u200D𐮍; [B1, V7]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍 +򔭜σᡱ⒈.≮𑄳\u200D𐮍; ; [B1, V7]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍 +򔭜σᡱ⒈.<\u0338𑄳\u200D𐮍; 򔭜σᡱ⒈.≮𑄳\u200D𐮍; [B1, V7]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍 +xn--4xa207hkzinr77u.xn--gdh5392g6sd; 򔭜σᡱ⒈.≮𑄳𐮍; [B1, V7]; xn--4xa207hkzinr77u.xn--gdh5392g6sd; ; ; # σᡱ⒈.≮𑄳𐮍 +xn--4xa207hkzinr77u.xn--1ug85gn777ahze; 򔭜σᡱ⒈.≮𑄳\u200D𐮍; [B1, V7]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; ; # σᡱ⒈.≮𑄳𐮍 +xn--3xa407hkzinr77u.xn--1ug85gn777ahze; 򔭜ςᡱ⒈.≮𑄳\u200D𐮍; [B1, V7]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; ; # ςᡱ⒈.≮𑄳𐮍 +\u3164\u094DႠ\u17D0.\u180B; \u094Dⴀ\u17D0.; [V6]; xn--n3b445e53p.; [V6, A4_2]; ; # ्ⴀ័. +\u1160\u094DႠ\u17D0.\u180B; \u094Dⴀ\u17D0.; [V6]; xn--n3b445e53p.; [V6, A4_2]; ; # ्ⴀ័. +\u1160\u094Dⴀ\u17D0.\u180B; \u094Dⴀ\u17D0.; [V6]; xn--n3b445e53p.; [V6, A4_2]; ; # ्ⴀ័. +xn--n3b445e53p.; \u094Dⴀ\u17D0.; [V6]; xn--n3b445e53p.; [V6, A4_2]; ; # ्ⴀ័. +\u3164\u094Dⴀ\u17D0.\u180B; \u094Dⴀ\u17D0.; [V6]; xn--n3b445e53p.; [V6, A4_2]; ; # ्ⴀ័. +xn--n3b742bkqf4ty.; \u1160\u094Dⴀ\u17D0.; [V7]; xn--n3b742bkqf4ty.; [V7, A4_2]; ; # ्ⴀ័. +xn--n3b468aoqa89r.; \u1160\u094DႠ\u17D0.; [V7]; xn--n3b468aoqa89r.; [V7, A4_2]; ; # ्Ⴀ័. +xn--n3b445e53po6d.; \u3164\u094Dⴀ\u17D0.; [V7]; xn--n3b445e53po6d.; [V7, A4_2]; ; # ्ⴀ័. +xn--n3b468azngju2a.; \u3164\u094DႠ\u17D0.; [V7]; xn--n3b468azngju2a.; [V7, A4_2]; ; # ्Ⴀ័. +❣\u200D.\u09CD𑰽\u0612\uA929; ❣\u200D.\u09CD𑰽\u0612\uA929; [C2, V6]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; xn--pei.xn--0fb32q3w7q2g4d; [V6] # ❣.্𑰽ؒꤩ +❣\u200D.\u09CD𑰽\u0612\uA929; ; [C2, V6]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; xn--pei.xn--0fb32q3w7q2g4d; [V6] # ❣.্𑰽ؒꤩ +xn--pei.xn--0fb32q3w7q2g4d; ❣.\u09CD𑰽\u0612\uA929; [V6]; xn--pei.xn--0fb32q3w7q2g4d; ; ; # ❣.্𑰽ؒꤩ +xn--1ugy10a.xn--0fb32q3w7q2g4d; ❣\u200D.\u09CD𑰽\u0612\uA929; [C2, V6]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; ; # ❣.্𑰽ؒꤩ +≮𐳺𐹄.≯񪮸ꡅ; ; [B1, V7]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ +<\u0338𐳺𐹄.>\u0338񪮸ꡅ; ≮𐳺𐹄.≯񪮸ꡅ; [B1, V7]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ +xn--gdh7943gk2a.xn--hdh1383c5e36c; ≮𐳺𐹄.≯񪮸ꡅ; [B1, V7]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ +\u0CCC𐧅𐳏󠲺。\u0CCDᠦ; \u0CCC𐧅𐳏󠲺.\u0CCDᠦ; [B1, V6, V7]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ +\u0CCC𐧅𐳏󠲺。\u0CCDᠦ; \u0CCC𐧅𐳏󠲺.\u0CCDᠦ; [B1, V6, V7]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ +\u0CCC𐧅𐲏󠲺。\u0CCDᠦ; \u0CCC𐧅𐳏󠲺.\u0CCDᠦ; [B1, V6, V7]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ +xn--7tc6360ky5bn2732c.xn--8tc429c; \u0CCC𐧅𐳏󠲺.\u0CCDᠦ; [B1, V6, V7]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ +\u0CCC𐧅𐲏󠲺。\u0CCDᠦ; \u0CCC𐧅𐳏󠲺.\u0CCDᠦ; [B1, V6, V7]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ +\u0349。𧡫; \u0349.𧡫; [V6]; xn--nua.xn--bc6k; ; ; # ͉.𧡫 +xn--nua.xn--bc6k; \u0349.𧡫; [V6]; xn--nua.xn--bc6k; ; ; # ͉.𧡫 +𑰿󠅦.\u1160; 𑰿.; [V6]; xn--ok3d.; [V6, A4_2]; ; # 𑰿. +𑰿󠅦.\u1160; 𑰿.; [V6]; xn--ok3d.; [V6, A4_2]; ; # 𑰿. +xn--ok3d.; 𑰿.; [V6]; xn--ok3d.; [V6, A4_2]; ; # 𑰿. +xn--ok3d.xn--psd; 𑰿.\u1160; [V6, V7]; xn--ok3d.xn--psd; ; ; # 𑰿. +-𞤆\u200D。󸼄𞳒; -𞤨\u200D.󸼄𞳒; [B1, B5, B6, C2, V3, V7]; xn----ugnx367r.xn--846h96596c; ; xn----ni8r.xn--846h96596c; [B1, B5, B6, V3, V7] # -𞤨. +-𞤨\u200D。󸼄𞳒; -𞤨\u200D.󸼄𞳒; [B1, B5, B6, C2, V3, V7]; xn----ugnx367r.xn--846h96596c; ; xn----ni8r.xn--846h96596c; [B1, B5, B6, V3, V7] # -𞤨. +xn----ni8r.xn--846h96596c; -𞤨.󸼄𞳒; [B1, B5, B6, V3, V7]; xn----ni8r.xn--846h96596c; ; ; # -𞤨. +xn----ugnx367r.xn--846h96596c; -𞤨\u200D.󸼄𞳒; [B1, B5, B6, C2, V3, V7]; xn----ugnx367r.xn--846h96596c; ; ; # -𞤨. +ꡏ󠇶≯𳾽。\u1DFD⾇滸𐹰; ꡏ󠇶≯𳾽.\u1DFD舛滸𐹰; [B1, V6, V7]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰 +ꡏ󠇶>\u0338𳾽。\u1DFD⾇滸𐹰; ꡏ󠇶≯𳾽.\u1DFD舛滸𐹰; [B1, V6, V7]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰 +ꡏ󠇶≯𳾽。\u1DFD舛滸𐹰; ꡏ󠇶≯𳾽.\u1DFD舛滸𐹰; [B1, V6, V7]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰 +ꡏ󠇶>\u0338𳾽。\u1DFD舛滸𐹰; ꡏ󠇶≯𳾽.\u1DFD舛滸𐹰; [B1, V6, V7]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰 +xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ꡏ󠇶≯𳾽.\u1DFD舛滸𐹰; [B1, V6, V7]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰 +蔏。𑰺; 蔏.𑰺; [V6]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺 +蔏。𑰺; 蔏.𑰺; [V6]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺 +xn--uy1a.xn--jk3d; 蔏.𑰺; [V6]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺 +𝟿𐮋。󠄊; 9𐮋.; [B1]; xn--9-rv5i.; [B1, A4_2]; ; # 9𐮋. +9𐮋。󠄊; 9𐮋.; [B1]; xn--9-rv5i.; [B1, A4_2]; ; # 9𐮋. +xn--9-rv5i.; 9𐮋.; [B1]; xn--9-rv5i.; [B1, A4_2]; ; # 9𐮋. +󟇇-䟖F。\u07CB⒈\u0662; 󟇇-䟖f.\u07CB⒈\u0662; [B4, V7]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢ +󟇇-䟖F。\u07CB1.\u0662; 󟇇-䟖f.\u07CB1.\u0662; [B1, V7]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢ +󟇇-䟖f。\u07CB1.\u0662; 󟇇-䟖f.\u07CB1.\u0662; [B1, V7]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢ +xn---f-mz8b08788k.xn--1-ybd.xn--bib; 󟇇-䟖f.\u07CB1.\u0662; [B1, V7]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢ +󟇇-䟖f。\u07CB⒈\u0662; 󟇇-䟖f.\u07CB⒈\u0662; [B4, V7]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢ +xn---f-mz8b08788k.xn--bib53ev44d; 󟇇-䟖f.\u07CB⒈\u0662; [B4, V7]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢ +\u200C。𐹺; \u200C.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; .xn--yo0d; [B1, A4_2] # .𐹺 +\u200C。𐹺; \u200C.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; .xn--yo0d; [B1, A4_2] # .𐹺 +.xn--yo0d; .𐹺; [B1, X4_2]; .xn--yo0d; [B1, A4_2]; ; # .𐹺 +xn--0ug.xn--yo0d; \u200C.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; ; # .𐹺 +𐡆.≯\u200C-𞥀; ; [B1, C1]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1] # 𐡆.≯-𞥀 +𐡆.>\u0338\u200C-𞥀; 𐡆.≯\u200C-𞥀; [B1, C1]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1] # 𐡆.≯-𞥀 +𐡆.>\u0338\u200C-𞤞; 𐡆.≯\u200C-𞥀; [B1, C1]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1] # 𐡆.≯-𞥀 +𐡆.≯\u200C-𞤞; 𐡆.≯\u200C-𞥀; [B1, C1]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1] # 𐡆.≯-𞥀 +xn--le9c.xn----ogo9956r; 𐡆.≯-𞥀; [B1]; xn--le9c.xn----ogo9956r; ; ; # 𐡆.≯-𞥀 +xn--le9c.xn----rgn40iy359e; 𐡆.≯\u200C-𞥀; [B1, C1]; xn--le9c.xn----rgn40iy359e; ; ; # 𐡆.≯-𞥀 +󠁀-。≠\uFCD7; 󠁀-.≠\u0647\u062C; [B1, V3, V7]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج +󠁀-。=\u0338\uFCD7; 󠁀-.≠\u0647\u062C; [B1, V3, V7]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج +󠁀-。≠\u0647\u062C; 󠁀-.≠\u0647\u062C; [B1, V3, V7]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج +󠁀-。=\u0338\u0647\u062C; 󠁀-.≠\u0647\u062C; [B1, V3, V7]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج +xn----f411m.xn--rgb7c611j; 󠁀-.≠\u0647\u062C; [B1, V3, V7]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج +񻬹𑈵。\u200D𞨶; 񻬹𑈵.\u200D𞨶; [B1, C2, V7]; xn--8g1d12120a.xn--1ug6651p; ; xn--8g1d12120a.xn--5l6h; [V7] # 𑈵. +xn--8g1d12120a.xn--5l6h; 񻬹𑈵.𞨶; [V7]; xn--8g1d12120a.xn--5l6h; ; ; # 𑈵. +xn--8g1d12120a.xn--1ug6651p; 񻬹𑈵.\u200D𞨶; [B1, C2, V7]; xn--8g1d12120a.xn--1ug6651p; ; ; # 𑈵. +𑋧\uA9C02。㧉򒖄; 𑋧\uA9C02.㧉򒖄; [V6, V7]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉 +𑋧\uA9C02。㧉򒖄; 𑋧\uA9C02.㧉򒖄; [V6, V7]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉 +xn--2-5z4eu89y.xn--97l02706d; 𑋧\uA9C02.㧉򒖄; [V6, V7]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉 +\u200C𽬄𐹴𞩥。≯6; \u200C𽬄𐹴𞩥.≯6; [B1, C1, V7]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; xn--so0du768aim9m.xn--6-ogo; [B1, B5, B6, V7] # 𐹴.≯6 +\u200C𽬄𐹴𞩥。>\u03386; \u200C𽬄𐹴𞩥.≯6; [B1, C1, V7]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; xn--so0du768aim9m.xn--6-ogo; [B1, B5, B6, V7] # 𐹴.≯6 +xn--so0du768aim9m.xn--6-ogo; 𽬄𐹴𞩥.≯6; [B1, B5, B6, V7]; xn--so0du768aim9m.xn--6-ogo; ; ; # 𐹴.≯6 +xn--0ug7105gf5wfxepq.xn--6-ogo; \u200C𽬄𐹴𞩥.≯6; [B1, C1, V7]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; ; # 𐹴.≯6 +𑁿.𐹦𻞵-\u200D; 𑁿.𐹦𻞵-\u200D; [B1, C2, V6, V7]; xn--q30d.xn----ugn1088hfsxv; ; xn--q30d.xn----i26i1299n; [B1, V3, V6, V7] # 𑁿.𐹦- +𑁿.𐹦𻞵-\u200D; ; [B1, C2, V6, V7]; xn--q30d.xn----ugn1088hfsxv; ; xn--q30d.xn----i26i1299n; [B1, V3, V6, V7] # 𑁿.𐹦- +xn--q30d.xn----i26i1299n; 𑁿.𐹦𻞵-; [B1, V3, V6, V7]; xn--q30d.xn----i26i1299n; ; ; # 𑁿.𐹦- +xn--q30d.xn----ugn1088hfsxv; 𑁿.𐹦𻞵-\u200D; [B1, C2, V6, V7]; xn--q30d.xn----ugn1088hfsxv; ; ; # 𑁿.𐹦- +⤸ς𺱀。\uFFA0; ⤸ς𺱀.; [V7]; xn--3xa392qmp03d.; [V7, A4_2]; xn--4xa192qmp03d.; # ⤸ς. +⤸ς𺱀。\u1160; ⤸ς𺱀.; [V7]; xn--3xa392qmp03d.; [V7, A4_2]; xn--4xa192qmp03d.; # ⤸ς. +⤸Σ𺱀。\u1160; ⤸σ𺱀.; [V7]; xn--4xa192qmp03d.; [V7, A4_2]; ; # ⤸σ. +⤸σ𺱀。\u1160; ⤸σ𺱀.; [V7]; xn--4xa192qmp03d.; [V7, A4_2]; ; # ⤸σ. +xn--4xa192qmp03d.; ⤸σ𺱀.; [V7]; xn--4xa192qmp03d.; [V7, A4_2]; ; # ⤸σ. +xn--3xa392qmp03d.; ⤸ς𺱀.; [V7]; xn--3xa392qmp03d.; [V7, A4_2]; ; # ⤸ς. +⤸Σ𺱀。\uFFA0; ⤸σ𺱀.; [V7]; xn--4xa192qmp03d.; [V7, A4_2]; ; # ⤸σ. +⤸σ𺱀。\uFFA0; ⤸σ𺱀.; [V7]; xn--4xa192qmp03d.; [V7, A4_2]; ; # ⤸σ. +xn--4xa192qmp03d.xn--psd; ⤸σ𺱀.\u1160; [V7]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ. +xn--3xa392qmp03d.xn--psd; ⤸ς𺱀.\u1160; [V7]; xn--3xa392qmp03d.xn--psd; ; ; # ⤸ς. +xn--4xa192qmp03d.xn--cl7c; ⤸σ𺱀.\uFFA0; [V7]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ. +xn--3xa392qmp03d.xn--cl7c; ⤸ς𺱀.\uFFA0; [V7]; xn--3xa392qmp03d.xn--cl7c; ; ; # ⤸ς. +\u0765\u1035𐫔\u06D5.𐦬𑋪Ⴃ; \u0765\u1035𐫔\u06D5.𐦬𑋪ⴃ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ +\u0765\u1035𐫔\u06D5.𐦬𑋪ⴃ; ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ +xn--llb10as9tqp5y.xn--ukj7371e21f; \u0765\u1035𐫔\u06D5.𐦬𑋪ⴃ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ +xn--llb10as9tqp5y.xn--bnd9168j21f; \u0765\u1035𐫔\u06D5.𐦬𑋪Ⴃ; [B2, B3, V7]; xn--llb10as9tqp5y.xn--bnd9168j21f; ; ; # ݥဵ𐫔ە.𐦬𑋪Ⴃ +\u0661\u1B44-킼.\u1BAA\u0616\u066C≯; ; [B1, B5, B6, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯ +\u0661\u1B44-킼.\u1BAA\u0616\u066C>\u0338; \u0661\u1B44-킼.\u1BAA\u0616\u066C≯; [B1, B5, B6, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯ +xn----9pc551nk39n.xn--4fb6o571degg; \u0661\u1B44-킼.\u1BAA\u0616\u066C≯; [B1, B5, B6, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯ +-。\u06C2\u0604򅖡𑓂; -.\u06C2\u0604򅖡𑓂; [B1, B2, B3, V3, V7]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂 +-。\u06C1\u0654\u0604򅖡𑓂; -.\u06C2\u0604򅖡𑓂; [B1, B2, B3, V3, V7]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂 +-.xn--mfb39a7208dzgs3d; -.\u06C2\u0604򅖡𑓂; [B1, B2, B3, V3, V7]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂 +\u200D󯑖󠁐.\u05BD𙮰ꡝ𐋡; \u200D󯑖󠁐.\u05BD𙮰ꡝ𐋡; [C2, V6, V7]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; xn--b726ey18m.xn--ldb8734fg0qcyzzg; [V6, V7] # .ֽꡝ𐋡 +\u200D󯑖󠁐.\u05BD𙮰ꡝ𐋡; ; [C2, V6, V7]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; xn--b726ey18m.xn--ldb8734fg0qcyzzg; [V6, V7] # .ֽꡝ𐋡 +xn--b726ey18m.xn--ldb8734fg0qcyzzg; 󯑖󠁐.\u05BD𙮰ꡝ𐋡; [V6, V7]; xn--b726ey18m.xn--ldb8734fg0qcyzzg; ; ; # .ֽꡝ𐋡 +xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; \u200D󯑖󠁐.\u05BD𙮰ꡝ𐋡; [C2, V6, V7]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; ; # .ֽꡝ𐋡 +︒􃈵ς񀠇。𐮈; ︒􃈵ς񀠇.𐮈; [B1, V7]; xn--3xa3729jwz5t7gl5f.xn--f29c; ; xn--4xa1729jwz5t7gl5f.xn--f29c; # ︒ς.𐮈 +。􃈵ς񀠇。𐮈; .􃈵ς񀠇.𐮈; [V7, X4_2]; .xn--3xa88573c7n64d.xn--f29c; [V7, A4_2]; .xn--4xa68573c7n64d.xn--f29c; # .ς.𐮈 +。􃈵Σ񀠇。𐮈; .􃈵σ񀠇.𐮈; [V7, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [V7, A4_2]; ; # .σ.𐮈 +。􃈵σ񀠇。𐮈; .􃈵σ񀠇.𐮈; [V7, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [V7, A4_2]; ; # .σ.𐮈 +.xn--4xa68573c7n64d.xn--f29c; .􃈵σ񀠇.𐮈; [V7, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [V7, A4_2]; ; # .σ.𐮈 +.xn--3xa88573c7n64d.xn--f29c; .􃈵ς񀠇.𐮈; [V7, X4_2]; .xn--3xa88573c7n64d.xn--f29c; [V7, A4_2]; ; # .ς.𐮈 +︒􃈵Σ񀠇。𐮈; ︒􃈵σ񀠇.𐮈; [B1, V7]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈 +︒􃈵σ񀠇。𐮈; ︒􃈵σ񀠇.𐮈; [B1, V7]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈 +xn--4xa1729jwz5t7gl5f.xn--f29c; ︒􃈵σ񀠇.𐮈; [B1, V7]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈 +xn--3xa3729jwz5t7gl5f.xn--f29c; ︒􃈵ς񀠇.𐮈; [B1, V7]; xn--3xa3729jwz5t7gl5f.xn--f29c; ; ; # ︒ς.𐮈 +\u07D9.\u06EE󆾃≯󠅲; \u07D9.\u06EE󆾃≯; [B2, B3, V7]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯ +\u07D9.\u06EE󆾃>\u0338󠅲; \u07D9.\u06EE󆾃≯; [B2, B3, V7]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯ +\u07D9.\u06EE󆾃≯󠅲; \u07D9.\u06EE󆾃≯; [B2, B3, V7]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯ +\u07D9.\u06EE󆾃>\u0338󠅲; \u07D9.\u06EE󆾃≯; [B2, B3, V7]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯ +xn--0sb.xn--bmb691l0524t; \u07D9.\u06EE󆾃≯; [B2, B3, V7]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯ +\u1A73󚙸.𐭍; ; [B1, V6, V7]; xn--2of22352n.xn--q09c; ; ; # ᩳ.𐭍 +xn--2of22352n.xn--q09c; \u1A73󚙸.𐭍; [B1, V6, V7]; xn--2of22352n.xn--q09c; ; ; # ᩳ.𐭍 +⒉󠊓≠。Ⴟ⬣Ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [V7]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ +⒉󠊓=\u0338。Ⴟ⬣Ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [V7]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ +2.󠊓≠。Ⴟ⬣Ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [V7]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ +2.󠊓=\u0338。Ⴟ⬣Ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [V7]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ +2.󠊓=\u0338。ⴟ⬣ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [V7]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ +2.󠊓≠。ⴟ⬣ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [V7]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ +2.xn--1chz4101l.xn--45iz7d6b; 2.󠊓≠.ⴟ⬣ⴈ; [V7]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ +⒉󠊓=\u0338。ⴟ⬣ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [V7]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ +⒉󠊓≠。ⴟ⬣ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [V7]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ +xn--1ch07f91401d.xn--45iz7d6b; ⒉󠊓≠.ⴟ⬣ⴈ; [V7]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ +2.xn--1chz4101l.xn--gnd9b297j; 2.󠊓≠.Ⴟ⬣Ⴈ; [V7]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ +xn--1ch07f91401d.xn--gnd9b297j; ⒉󠊓≠.Ⴟ⬣Ⴈ; [V7]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ +-󠉱\u0FB8Ⴥ。-𐹽\u0774𞣑; -󠉱\u0FB8ⴥ.-𐹽\u0774𞣑; [B1, V3, V7]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑 +-󠉱\u0FB8ⴥ。-𐹽\u0774𞣑; -󠉱\u0FB8ⴥ.-𐹽\u0774𞣑; [B1, V3, V7]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑 +xn----xmg317tgv352a.xn----05c4213ryr0g; -󠉱\u0FB8ⴥ.-𐹽\u0774𞣑; [B1, V3, V7]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑 +xn----xmg12fm2555h.xn----05c4213ryr0g; -󠉱\u0FB8Ⴥ.-𐹽\u0774𞣑; [B1, V3, V7]; xn----xmg12fm2555h.xn----05c4213ryr0g; ; ; # -ྸჅ.-𐹽ݴ𞣑 +\u0659。𑄴︒\u0627\u07DD; \u0659.𑄴︒\u0627\u07DD; [B1, V6, V7]; xn--1hb.xn--mgb09fp820c08pa; ; ; # ٙ.𑄴︒اߝ +\u0659。𑄴。\u0627\u07DD; \u0659.𑄴.\u0627\u07DD; [B1, V6]; xn--1hb.xn--w80d.xn--mgb09f; ; ; # ٙ.𑄴.اߝ +xn--1hb.xn--w80d.xn--mgb09f; \u0659.𑄴.\u0627\u07DD; [B1, V6]; xn--1hb.xn--w80d.xn--mgb09f; ; ; # ٙ.𑄴.اߝ +xn--1hb.xn--mgb09fp820c08pa; \u0659.𑄴︒\u0627\u07DD; [B1, V6, V7]; xn--1hb.xn--mgb09fp820c08pa; ; ; # ٙ.𑄴︒اߝ +Ⴙ\u0638.󠆓\u200D; ⴙ\u0638.\u200D; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; xn--3gb910r.; [B5, B6, A4_2] # ⴙظ. +ⴙ\u0638.󠆓\u200D; ⴙ\u0638.\u200D; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; xn--3gb910r.; [B5, B6, A4_2] # ⴙظ. +xn--3gb910r.; ⴙ\u0638.; [B5, B6]; xn--3gb910r.; [B5, B6, A4_2]; ; # ⴙظ. +xn--3gb910r.xn--1ug; ⴙ\u0638.\u200D; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; ; # ⴙظ. +xn--3gb194c.; Ⴙ\u0638.; [B5, B6, V7]; xn--3gb194c.; [B5, B6, V7, A4_2]; ; # Ⴙظ. +xn--3gb194c.xn--1ug; Ⴙ\u0638.\u200D; [B1, B5, B6, C2, V7]; xn--3gb194c.xn--1ug; ; ; # Ⴙظ. +󠆸。₆0𐺧\u0756; .60𐺧\u0756; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ +󠆸。60𐺧\u0756; .60𐺧\u0756; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ +.xn--60-cke9470y; .60𐺧\u0756; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ +6\u084F。-𑈴; 6\u084F.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴 +6\u084F。-𑈴; 6\u084F.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴 +xn--6-jjd.xn----6n8i; 6\u084F.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴 +\u200D񋌿𐹰。\u0ACDς𞰎\u08D6; \u200D񋌿𐹰.\u0ACDς𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, V6, V7] # 𐹰.્ςࣖ +\u200D񋌿𐹰。\u0ACDς𞰎\u08D6; \u200D񋌿𐹰.\u0ACDς𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, V6, V7] # 𐹰.્ςࣖ +\u200D񋌿𐹰。\u0ACDΣ𞰎\u08D6; \u200D񋌿𐹰.\u0ACDσ𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, V6, V7] # 𐹰.્σࣖ +\u200D񋌿𐹰。\u0ACDσ𞰎\u08D6; \u200D񋌿𐹰.\u0ACDσ𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, V6, V7] # 𐹰.્σࣖ +xn--oo0d1330n.xn--4xa21xcwbfz15g; 񋌿𐹰.\u0ACDσ𞰎\u08D6; [B1, B5, B6, V6, V7]; xn--oo0d1330n.xn--4xa21xcwbfz15g; ; ; # 𐹰.્σࣖ +xn--1ugx105gq26y.xn--4xa21xcwbfz15g; \u200D񋌿𐹰.\u0ACDσ𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; ; # 𐹰.્σࣖ +xn--1ugx105gq26y.xn--3xa41xcwbfz15g; \u200D񋌿𐹰.\u0ACDς𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; ; # 𐹰.્ςࣖ +\u200D񋌿𐹰。\u0ACDΣ𞰎\u08D6; \u200D񋌿𐹰.\u0ACDσ𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, V6, V7] # 𐹰.્σࣖ +\u200D񋌿𐹰。\u0ACDσ𞰎\u08D6; \u200D񋌿𐹰.\u0ACDσ𞰎\u08D6; [B1, C2, V6, V7]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, V6, V7] # 𐹰.્σࣖ +⒈񟄜Ⴓ⒪.\u0DCA򘘶\u088B𐹢; ⒈񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, V6, V7, U1]; xn--(o)-ge4ax01c3t74t.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ(o).්ࢋ𐹢 +1.񟄜Ⴓ(o).\u0DCA򘘶\u088B𐹢; 1.񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, B6, V6, V7, U1]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢 +1.񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; ; [B1, B6, V6, V7, U1]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢 +1.񟄜Ⴓ(O).\u0DCA򘘶\u088B𐹢; 1.񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, B6, V6, V7, U1]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢 +1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; 1.񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, B6, V6, V7, U1]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢 +⒈񟄜ⴓ⒪.\u0DCA򘘶\u088B𐹢; ⒈񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, V6, V7, U1]; xn--(o)-ge4ax01c3t74t.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ(o).්ࢋ𐹢 +xn--(o)-ge4ax01c3t74t.xn--3xb99xpx1yoes3e; ⒈񟄜ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, V6, V7, U1]; xn--(o)-ge4ax01c3t74t.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ(o).්ࢋ𐹢 +1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; 1.񟄜Ⴓ(o).\u0DCA򘘶\u088B𐹢; [B1, B6, V6, V7, U1]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢 +xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ⒈񟄜ⴓ⒪.\u0DCA򘘶\u088B𐹢; [B1, V6, V7]; xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ⒪.්ࢋ𐹢 +xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ⒈񟄜Ⴓ⒪.\u0DCA򘘶\u088B𐹢; [B1, V6, V7]; xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ; ; # ⒈Ⴓ⒪.්ࢋ𐹢 +𞤷.𐮐𞢁𐹠\u0624; ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ +𞤷.𐮐𞢁𐹠\u0648\u0654; 𞤷.𐮐𞢁𐹠\u0624; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ +𞤕.𐮐𞢁𐹠\u0648\u0654; 𞤷.𐮐𞢁𐹠\u0624; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ +𞤕.𐮐𞢁𐹠\u0624; 𞤷.𐮐𞢁𐹠\u0624; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ +xn--ve6h.xn--jgb1694kz0b2176a; 𞤷.𐮐𞢁𐹠\u0624; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ +𐲈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, V3, V6, V7]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳 +𐲈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, V3, V6, V7]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳 +𐳈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, V3, V6, V7]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳 +xn----ue6i.xn--v80d6662t; 𐳈-.𑄳񢌻; [B1, B3, V3, V6, V7]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳 +𐳈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, V3, V6, V7]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳 +-󠉖ꡧ.󠊂񇆃🄉; -󠉖ꡧ.󠊂񇆃8,; [V3, V7, U1]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8, +-󠉖ꡧ.󠊂񇆃8,; ; [V3, V7, U1]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8, +xn----hg4ei0361g.xn--8,-k362evu488a; -󠉖ꡧ.󠊂񇆃8,; [V3, V7, U1]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8, +xn----hg4ei0361g.xn--207ht163h7m94c; -󠉖ꡧ.󠊂񇆃🄉; [V3, V7]; xn----hg4ei0361g.xn--207ht163h7m94c; ; ; # -ꡧ.🄉 +󠾛󠈴臯𧔤.\u0768𝟝; 󠾛󠈴臯𧔤.\u07685; [B1, V7]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5 +󠾛󠈴臯𧔤.\u07685; ; [B1, V7]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5 +xn--zb1at733hm579ddhla.xn--5-b5c; 󠾛󠈴臯𧔤.\u07685; [B1, V7]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5 +≮𐹣.𝨿; ≮𐹣.𝨿; [B1, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿 +<\u0338𐹣.𝨿; ≮𐹣.𝨿; [B1, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿 +≮𐹣.𝨿; ; [B1, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿 +<\u0338𐹣.𝨿; ≮𐹣.𝨿; [B1, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿 +xn--gdh1504g.xn--e92h; ≮𐹣.𝨿; [B1, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿 +𐹯ᯛ\u0A4D。脥; 𐹯ᯛ\u0A4D.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥 +𐹯ᯛ\u0A4D。脥; 𐹯ᯛ\u0A4D.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥 +xn--ybc101g3m1p.xn--740a; 𐹯ᯛ\u0A4D.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥 +\u1B44\u115F𞷿򃀍.-; \u1B44𞷿򃀍.-; [B1, B5, V3, V6, V7]; xn--1uf9538sxny9a.-; ; ; # ᭄.- +xn--1uf9538sxny9a.-; \u1B44𞷿򃀍.-; [B1, B5, V3, V6, V7]; xn--1uf9538sxny9a.-; ; ; # ᭄.- +xn--osd971cpx70btgt8b.-; \u1B44\u115F𞷿򃀍.-; [B1, B5, V3, V6, V7]; xn--osd971cpx70btgt8b.-; ; ; # ᭄.- +\u200C。\u0354; \u200C.\u0354; [C1, V6]; xn--0ug.xn--yua; ; .xn--yua; [V6, A4_2] # .͔ +\u200C。\u0354; \u200C.\u0354; [C1, V6]; xn--0ug.xn--yua; ; .xn--yua; [V6, A4_2] # .͔ +.xn--yua; .\u0354; [V6, X4_2]; .xn--yua; [V6, A4_2]; ; # .͔ +xn--0ug.xn--yua; \u200C.\u0354; [C1, V6]; xn--0ug.xn--yua; ; ; # .͔ +𞤥󠅮.ᡄႮ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤥󠅮.ᡄႮ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤥󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤃󠅮.ᡄႮ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤃󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +xn--de6h.xn--37e857h; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤥.ᡄⴎ; ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤃.ᡄႮ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤃.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤥󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤃󠅮.ᡄႮ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤃󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +xn--de6h.xn--mnd799a; 𞤥.ᡄႮ; [V7]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ +𞤥.ᡄႮ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ +𞤧𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤧𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤧𝨨ξ.𪺏㛨❸; ; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤅𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤅𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +xn--zxa5691vboja.xn--bfi293ci119b; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤧𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤅𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +𞤅𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸ +᠆몆\u200C-。Ⴛ𐦅︒; ᠆몆\u200C-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, V3, V7] # ᠆몆-.ⴛ𐦅︒ +᠆몆\u200C-。Ⴛ𐦅︒; ᠆몆\u200C-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, V3, V7] # ᠆몆-.ⴛ𐦅︒ +᠆몆\u200C-。Ⴛ𐦅。; ᠆몆\u200C-.ⴛ𐦅.; [B1, B5, B6, C1, V3]; xn----e3j425bsk1o.xn--jlju661e.; [B1, B5, B6, C1, V3, A4_2]; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, V3, A4_2] # ᠆몆-.ⴛ𐦅. +᠆몆\u200C-。Ⴛ𐦅。; ᠆몆\u200C-.ⴛ𐦅.; [B1, B5, B6, C1, V3]; xn----e3j425bsk1o.xn--jlju661e.; [B1, B5, B6, C1, V3, A4_2]; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, V3, A4_2] # ᠆몆-.ⴛ𐦅. +᠆몆\u200C-。ⴛ𐦅。; ᠆몆\u200C-.ⴛ𐦅.; [B1, B5, B6, C1, V3]; xn----e3j425bsk1o.xn--jlju661e.; [B1, B5, B6, C1, V3, A4_2]; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, V3, A4_2] # ᠆몆-.ⴛ𐦅. +᠆몆\u200C-。ⴛ𐦅。; ᠆몆\u200C-.ⴛ𐦅.; [B1, B5, B6, C1, V3]; xn----e3j425bsk1o.xn--jlju661e.; [B1, B5, B6, C1, V3, A4_2]; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, V3, A4_2] # ᠆몆-.ⴛ𐦅. +xn----e3j6620g.xn--jlju661e.; ᠆몆-.ⴛ𐦅.; [B1, B5, B6, V3]; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, V3, A4_2]; ; # ᠆몆-.ⴛ𐦅. +xn----e3j425bsk1o.xn--jlju661e.; ᠆몆\u200C-.ⴛ𐦅.; [B1, B5, B6, C1, V3]; xn----e3j425bsk1o.xn--jlju661e.; [B1, B5, B6, C1, V3, A4_2]; ; # ᠆몆-.ⴛ𐦅. +᠆몆\u200C-。ⴛ𐦅︒; ᠆몆\u200C-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, V3, V7] # ᠆몆-.ⴛ𐦅︒ +᠆몆\u200C-。ⴛ𐦅︒; ᠆몆\u200C-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, V3, V7] # ᠆몆-.ⴛ𐦅︒ +xn----e3j6620g.xn--jlj4997dhgh; ᠆몆-.ⴛ𐦅︒; [B1, B5, B6, V3, V7]; xn----e3j6620g.xn--jlj4997dhgh; ; ; # ᠆몆-.ⴛ𐦅︒ +xn----e3j425bsk1o.xn--jlj4997dhgh; ᠆몆\u200C-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; ; # ᠆몆-.ⴛ𐦅︒ +xn----e3j6620g.xn--znd4948j.; ᠆몆-.Ⴛ𐦅.; [B1, B5, B6, V3, V7]; xn----e3j6620g.xn--znd4948j.; [B1, B5, B6, V3, V7, A4_2]; ; # ᠆몆-.Ⴛ𐦅. +xn----e3j425bsk1o.xn--znd4948j.; ᠆몆\u200C-.Ⴛ𐦅.; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--znd4948j.; [B1, B5, B6, C1, V3, V7, A4_2]; ; # ᠆몆-.Ⴛ𐦅. +xn----e3j6620g.xn--znd2362jhgh; ᠆몆-.Ⴛ𐦅︒; [B1, B5, B6, V3, V7]; xn----e3j6620g.xn--znd2362jhgh; ; ; # ᠆몆-.Ⴛ𐦅︒ +xn----e3j425bsk1o.xn--znd2362jhgh; ᠆몆\u200C-.Ⴛ𐦅︒; [B1, B5, B6, C1, V3, V7]; xn----e3j425bsk1o.xn--znd2362jhgh; ; ; # ᠆몆-.Ⴛ𐦅︒ +󠾳.︒⥱\u200C𐹬; ; [B1, C1, V7]; xn--uf66e.xn--0ugz28axl3pqxna; ; xn--uf66e.xn--qtiz073e3ik; [B1, V7] # .︒⥱𐹬 +󠾳.。⥱\u200C𐹬; 󠾳..⥱\u200C𐹬; [B1, C1, V7, X4_2]; xn--uf66e..xn--0ugz28as66q; [B1, C1, V7, A4_2]; xn--uf66e..xn--qti2829e; [B1, V7, A4_2] # ..⥱𐹬 +xn--uf66e..xn--qti2829e; 󠾳..⥱𐹬; [B1, V7, X4_2]; xn--uf66e..xn--qti2829e; [B1, V7, A4_2]; ; # ..⥱𐹬 +xn--uf66e..xn--0ugz28as66q; 󠾳..⥱\u200C𐹬; [B1, C1, V7, X4_2]; xn--uf66e..xn--0ugz28as66q; [B1, C1, V7, A4_2]; ; # ..⥱𐹬 +xn--uf66e.xn--qtiz073e3ik; 󠾳.︒⥱𐹬; [B1, V7]; xn--uf66e.xn--qtiz073e3ik; ; ; # .︒⥱𐹬 +xn--uf66e.xn--0ugz28axl3pqxna; 󠾳.︒⥱\u200C𐹬; [B1, C1, V7]; xn--uf66e.xn--0ugz28axl3pqxna; ; ; # .︒⥱𐹬 +𐯖.𐹠Ⴑ񚇜𐫊; 𐯖.𐹠ⴑ񚇜𐫊; [B1, V7]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊 +𐯖.𐹠ⴑ񚇜𐫊; ; [B1, V7]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊 +xn--n49c.xn--8kj8702ewicl862o; 𐯖.𐹠ⴑ񚇜𐫊; [B1, V7]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊 +xn--n49c.xn--pnd4619jwicl862o; 𐯖.𐹠Ⴑ񚇜𐫊; [B1, V7]; xn--n49c.xn--pnd4619jwicl862o; ; ; # .𐹠Ⴑ𐫊 +\u0FA4񱤯.𝟭Ⴛ; \u0FA4񱤯.1ⴛ; [V6, V7]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ +\u0FA4񱤯.1Ⴛ; \u0FA4񱤯.1ⴛ; [V6, V7]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ +\u0FA4񱤯.1ⴛ; ; [V6, V7]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ +xn--0fd40533g.xn--1-tws; \u0FA4񱤯.1ⴛ; [V6, V7]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ +\u0FA4񱤯.𝟭ⴛ; \u0FA4񱤯.1ⴛ; [V6, V7]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ +xn--0fd40533g.xn--1-q1g; \u0FA4񱤯.1Ⴛ; [V6, V7]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ +-\u0826齀。릿𐸋; -\u0826齀.릿𐸋; [B1, B5, B6, V3, V7]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿 +-\u0826齀。릿𐸋; -\u0826齀.릿𐸋; [B1, B5, B6, V3, V7]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿 +xn----6gd0617i.xn--7y2bm55m; -\u0826齀.릿𐸋; [B1, B5, B6, V3, V7]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿 +󠔊\u071C鹝꾗。񾵐\u200D\u200D⏃; 󠔊\u071C鹝꾗.񾵐\u200D\u200D⏃; [B1, B6, C2, V7]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; xn--mnb6558e91kyq533a.xn--6mh27269e; [B1, B6, V7] # ܜ鹝꾗.⏃ +󠔊\u071C鹝꾗。񾵐\u200D\u200D⏃; 󠔊\u071C鹝꾗.񾵐\u200D\u200D⏃; [B1, B6, C2, V7]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; xn--mnb6558e91kyq533a.xn--6mh27269e; [B1, B6, V7] # ܜ鹝꾗.⏃ +xn--mnb6558e91kyq533a.xn--6mh27269e; 󠔊\u071C鹝꾗.񾵐⏃; [B1, B6, V7]; xn--mnb6558e91kyq533a.xn--6mh27269e; ; ; # ܜ鹝꾗.⏃ +xn--mnb6558e91kyq533a.xn--1uga46zs309y; 󠔊\u071C鹝꾗.񾵐\u200D\u200D⏃; [B1, B6, C2, V7]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; ; # ܜ鹝꾗.⏃ +≮.-\u0708--; ≮.-\u0708--; [B1, V2, V3]; xn--gdh.xn------eqf; ; ; # ≮.-܈-- +<\u0338.-\u0708--; ≮.-\u0708--; [B1, V2, V3]; xn--gdh.xn------eqf; ; ; # ≮.-܈-- +≮.-\u0708--; ; [B1, V2, V3]; xn--gdh.xn------eqf; ; ; # ≮.-܈-- +<\u0338.-\u0708--; ≮.-\u0708--; [B1, V2, V3]; xn--gdh.xn------eqf; ; ; # ≮.-܈-- +xn--gdh.xn------eqf; ≮.-\u0708--; [B1, V2, V3]; xn--gdh.xn------eqf; ; ; # ≮.-܈-- +𐹸󠋳。\u200Dς𝟩; 𐹸󠋳.\u200Dς7; [B1, C2, V7]; xn--wo0di5177c.xn--7-xmb248s; ; xn--wo0di5177c.xn--7-zmb; [B1, V7] # 𐹸.ς7 +𐹸󠋳。\u200Dς7; 𐹸󠋳.\u200Dς7; [B1, C2, V7]; xn--wo0di5177c.xn--7-xmb248s; ; xn--wo0di5177c.xn--7-zmb; [B1, V7] # 𐹸.ς7 +𐹸󠋳。\u200DΣ7; 𐹸󠋳.\u200Dσ7; [B1, C2, V7]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, V7] # 𐹸.σ7 +𐹸󠋳。\u200Dσ7; 𐹸󠋳.\u200Dσ7; [B1, C2, V7]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, V7] # 𐹸.σ7 +xn--wo0di5177c.xn--7-zmb; 𐹸󠋳.σ7; [B1, V7]; xn--wo0di5177c.xn--7-zmb; ; ; # 𐹸.σ7 +xn--wo0di5177c.xn--7-zmb938s; 𐹸󠋳.\u200Dσ7; [B1, C2, V7]; xn--wo0di5177c.xn--7-zmb938s; ; ; # 𐹸.σ7 +xn--wo0di5177c.xn--7-xmb248s; 𐹸󠋳.\u200Dς7; [B1, C2, V7]; xn--wo0di5177c.xn--7-xmb248s; ; ; # 𐹸.ς7 +𐹸󠋳。\u200DΣ𝟩; 𐹸󠋳.\u200Dσ7; [B1, C2, V7]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, V7] # 𐹸.σ7 +𐹸󠋳。\u200Dσ𝟩; 𐹸󠋳.\u200Dσ7; [B1, C2, V7]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, V7] # 𐹸.σ7 +ς򅜌8.𞭤; ς򅜌8.𞭤; [V7]; xn--8-xmb44974n.xn--su6h; ; xn--8-zmb14974n.xn--su6h; # ς8. +ς򅜌8.𞭤; ; [V7]; xn--8-xmb44974n.xn--su6h; ; xn--8-zmb14974n.xn--su6h; # ς8. +Σ򅜌8.𞭤; σ򅜌8.𞭤; [V7]; xn--8-zmb14974n.xn--su6h; ; ; # σ8. +σ򅜌8.𞭤; ; [V7]; xn--8-zmb14974n.xn--su6h; ; ; # σ8. +xn--8-zmb14974n.xn--su6h; σ򅜌8.𞭤; [V7]; xn--8-zmb14974n.xn--su6h; ; ; # σ8. +xn--8-xmb44974n.xn--su6h; ς򅜌8.𞭤; [V7]; xn--8-xmb44974n.xn--su6h; ; ; # ς8. +Σ򅜌8.𞭤; σ򅜌8.𞭤; [V7]; xn--8-zmb14974n.xn--su6h; ; ; # σ8. +σ򅜌8.𞭤; σ򅜌8.𞭤; [V7]; xn--8-zmb14974n.xn--su6h; ; ; # σ8. +\u200Cᡑ🄀\u0684.-𐫄𑲤; \u200Cᡑ🄀\u0684.-𐫄𑲤; [B1, C1, V3, V7]; xn--9ib722gvtfi563c.xn----ek5i065b; ; xn--9ib722gbw95a.xn----ek5i065b; [B1, B5, B6, V3, V7] # ᡑ🄀ڄ.-𐫄𑲤 +\u200Cᡑ0.\u0684.-𐫄𑲤; ; [B1, C1, V3]; xn--0-o7j263b.xn--9ib.xn----ek5i065b; ; xn--0-o7j.xn--9ib.xn----ek5i065b; [B1, V3] # ᡑ0.ڄ.-𐫄𑲤 +xn--0-o7j.xn--9ib.xn----ek5i065b; ᡑ0.\u0684.-𐫄𑲤; [B1, V3]; xn--0-o7j.xn--9ib.xn----ek5i065b; ; ; # ᡑ0.ڄ.-𐫄𑲤 +xn--0-o7j263b.xn--9ib.xn----ek5i065b; \u200Cᡑ0.\u0684.-𐫄𑲤; [B1, C1, V3]; xn--0-o7j263b.xn--9ib.xn----ek5i065b; ; ; # ᡑ0.ڄ.-𐫄𑲤 +xn--9ib722gbw95a.xn----ek5i065b; ᡑ🄀\u0684.-𐫄𑲤; [B1, B5, B6, V3, V7]; xn--9ib722gbw95a.xn----ek5i065b; ; ; # ᡑ🄀ڄ.-𐫄𑲤 +xn--9ib722gvtfi563c.xn----ek5i065b; \u200Cᡑ🄀\u0684.-𐫄𑲤; [B1, C1, V3, V7]; xn--9ib722gvtfi563c.xn----ek5i065b; ; ; # ᡑ🄀ڄ.-𐫄𑲤 +𖠍。𐪿넯򞵲; 𖠍.𐪿넯򞵲; [B2, B3, V7]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯 +𖠍。𐪿넯򞵲; 𖠍.𐪿넯򞵲; [B2, B3, V7]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯 +xn--4e9e.xn--l60bj21opd57g; 𖠍.𐪿넯򞵲; [B2, B3, V7]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯 +᠇Ⴘ。\u0603Ⴈ𝆊; ᠇ⴘ.\u0603ⴈ𝆊; [B1, V7]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊 +᠇ⴘ。\u0603ⴈ𝆊; ᠇ⴘ.\u0603ⴈ𝆊; [B1, V7]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊 +xn--d6e009h.xn--lfb290rfu3z; ᠇ⴘ.\u0603ⴈ𝆊; [B1, V7]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊 +xn--wnd558a.xn--lfb465c1v87a; ᠇Ⴘ.\u0603Ⴈ𝆊; [B1, V7]; xn--wnd558a.xn--lfb465c1v87a; ; ; # ᠇Ⴘ.Ⴈ𝆊 +⒚󠋑𞤰。牣\u0667Ⴜᣥ; ⒚󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ +19.󠋑𞤰。牣\u0667Ⴜᣥ; 19.󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ +19.󠋑𞤰。牣\u0667ⴜᣥ; 19.󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ +19.󠋑𞤎。牣\u0667Ⴜᣥ; 19.󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ +19.󠋑𞤎。牣\u0667ⴜᣥ; 19.󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ +19.xn--oe6h75760c.xn--gib285gtxo2l9d; 19.󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ +⒚󠋑𞤰。牣\u0667ⴜᣥ; ⒚󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ +⒚󠋑𞤎。牣\u0667Ⴜᣥ; ⒚󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ +⒚󠋑𞤎。牣\u0667ⴜᣥ; ⒚󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ +xn--cthy466n29j3e.xn--gib285gtxo2l9d; ⒚󠋑𞤰.牣\u0667ⴜᣥ; [B1, B5, V7]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ +19.xn--oe6h75760c.xn--gib404ccxgh00h; 19.󠋑𞤰.牣\u0667Ⴜᣥ; [B1, B5, V7]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ +xn--cthy466n29j3e.xn--gib404ccxgh00h; ⒚󠋑𞤰.牣\u0667Ⴜᣥ; [B1, B5, V7]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ +-𐋱𐰽⒈.Ⴓ; -𐋱𐰽⒈.ⴓ; [B1, V3, V7]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ +-𐋱𐰽1..Ⴓ; -𐋱𐰽1..ⴓ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ +-𐋱𐰽1..ⴓ; ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ +xn---1-895nq11a..xn--blj; -𐋱𐰽1..ⴓ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ +-𐋱𐰽⒈.ⴓ; ; [B1, V3, V7]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ +xn----ecp0206g90h.xn--blj; -𐋱𐰽⒈.ⴓ; [B1, V3, V7]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ +xn---1-895nq11a..xn--rnd; -𐋱𐰽1..Ⴓ; [B1, V3, V7, X4_2]; xn---1-895nq11a..xn--rnd; [B1, V3, V7, A4_2]; ; # -𐋱𐰽1..Ⴓ +xn----ecp0206g90h.xn--rnd; -𐋱𐰽⒈.Ⴓ; [B1, V3, V7]; xn----ecp0206g90h.xn--rnd; ; ; # -𐋱𐰽⒈.Ⴓ +\u200C긃.榶-; ; [C1, V3]; xn--0ug3307c.xn----d87b; ; xn--ej0b.xn----d87b; [V3] # 긃.榶- +\u200C긃.榶-; \u200C긃.榶-; [C1, V3]; xn--0ug3307c.xn----d87b; ; xn--ej0b.xn----d87b; [V3] # 긃.榶- +xn--ej0b.xn----d87b; 긃.榶-; [V3]; xn--ej0b.xn----d87b; ; ; # 긃.榶- +xn--0ug3307c.xn----d87b; \u200C긃.榶-; [C1, V3]; xn--0ug3307c.xn----d87b; ; ; # 긃.榶- +뉓泓𜵽.\u09CD\u200D; ; [V6]; xn--lwwp69lqs7m.xn--b7b605i; ; xn--lwwp69lqs7m.xn--b7b; # 뉓泓𜵽.্ +뉓泓𜵽.\u09CD\u200D; 뉓泓𜵽.\u09CD\u200D; [V6]; xn--lwwp69lqs7m.xn--b7b605i; ; xn--lwwp69lqs7m.xn--b7b; # 뉓泓𜵽.্ +xn--lwwp69lqs7m.xn--b7b; 뉓泓𜵽.\u09CD; [V6]; xn--lwwp69lqs7m.xn--b7b; ; ; # 뉓泓𜵽.্ +xn--lwwp69lqs7m.xn--b7b605i; 뉓泓𜵽.\u09CD\u200D; [V6]; xn--lwwp69lqs7m.xn--b7b605i; ; ; # 뉓泓𜵽.্ +\u200D𐹴ß。\u0EB4\u2B75񪅌; \u200D𐹴ß.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--zca770nip7n.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ß.ິ +\u200D𐹴ß。\u0EB4\u2B75񪅌; \u200D𐹴ß.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--zca770nip7n.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ß.ິ +\u200D𐹴SS。\u0EB4\u2B75񪅌; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ss.ິ +\u200D𐹴ss。\u0EB4\u2B75񪅌; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ss.ິ +\u200D𐹴Ss。\u0EB4\u2B75񪅌; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ss.ິ +xn--ss-ti3o.xn--57c638l8774i; 𐹴ss.\u0EB4\u2B75񪅌; [B1, V6, V7]; xn--ss-ti3o.xn--57c638l8774i; ; ; # 𐹴ss.ິ +xn--ss-l1t5169j.xn--57c638l8774i; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; ; # 𐹴ss.ິ +xn--zca770nip7n.xn--57c638l8774i; \u200D𐹴ß.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--zca770nip7n.xn--57c638l8774i; ; ; # 𐹴ß.ິ +\u200D𐹴SS。\u0EB4\u2B75񪅌; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ss.ິ +\u200D𐹴ss。\u0EB4\u2B75񪅌; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ss.ິ +\u200D𐹴Ss。\u0EB4\u2B75񪅌; \u200D𐹴ss.\u0EB4\u2B75񪅌; [B1, C2, V6, V7]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, V6, V7] # 𐹴ss.ິ +\u1B44.\u1BAA-≮≠; \u1B44.\u1BAA-≮≠; [V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠ +\u1B44.\u1BAA-<\u0338=\u0338; \u1B44.\u1BAA-≮≠; [V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠ +\u1B44.\u1BAA-≮≠; ; [V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠ +\u1B44.\u1BAA-<\u0338=\u0338; \u1B44.\u1BAA-≮≠; [V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠ +xn--1uf.xn----nmlz65aub; \u1B44.\u1BAA-≮≠; [V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠ +\u1BF3Ⴑ\u115F.𑄴Ⅎ; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +\u1BF3Ⴑ\u115F.𑄴Ⅎ; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +\u1BF3ⴑ\u115F.𑄴ⅎ; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +\u1BF3Ⴑ\u115F.𑄴ⅎ; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +xn--1zf224e.xn--73g3065g; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +\u1BF3ⴑ\u115F.𑄴ⅎ; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +\u1BF3Ⴑ\u115F.𑄴ⅎ; \u1BF3ⴑ.𑄴ⅎ; [V6]; xn--1zf224e.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +xn--pnd26a55x.xn--73g3065g; \u1BF3Ⴑ\u115F.𑄴ⅎ; [V6, V7]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ +xn--osd925cvyn.xn--73g3065g; \u1BF3ⴑ\u115F.𑄴ⅎ; [V6, V7]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ +xn--pnd26a55x.xn--f3g7465g; \u1BF3Ⴑ\u115F.𑄴Ⅎ; [V6, V7]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ +𜉆。Ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, V7]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯 +𜉆。Ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, V7]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯 +𜉆。ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, V7]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯 +𜉆。ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, V7]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯 +xn--187g.xn--ukjy205b8rscdeb; 𜉆.ⴃ𐴣𐹹똯; [B5, V7]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯 +xn--187g.xn--bnd4785f8r8bdeb; 𜉆.Ⴃ𐴣𐹹똯; [B5, V7]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯 +𐫀。⳻󠙾󠄷\u3164; 𐫀.⳻󠙾; [B1, V7]; xn--pw9c.xn--mkjw9654i; ; ; # 𐫀.⳻ +𐫀。⳻󠙾󠄷\u1160; 𐫀.⳻󠙾; [B1, V7]; xn--pw9c.xn--mkjw9654i; ; ; # 𐫀.⳻ +xn--pw9c.xn--mkjw9654i; 𐫀.⳻󠙾; [B1, V7]; xn--pw9c.xn--mkjw9654i; ; ; # 𐫀.⳻ +xn--pw9c.xn--psd742lxt32w; 𐫀.⳻󠙾\u1160; [B1, V7]; xn--pw9c.xn--psd742lxt32w; ; ; # 𐫀.⳻ +xn--pw9c.xn--mkj83l4v899a; 𐫀.⳻󠙾\u3164; [B1, V7]; xn--pw9c.xn--mkj83l4v899a; ; ; # 𐫀.⳻ +\u079A⾇.\u071E-𐋰; \u079A舛.\u071E-𐋰; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰 +\u079A舛.\u071E-𐋰; ; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰 +xn--7qb6383d.xn----20c3154q; \u079A舛.\u071E-𐋰; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰 +Ⴉ猕󹛫≮.︒; ⴉ猕󹛫≮.︒; [V7]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒ +Ⴉ猕󹛫<\u0338.︒; ⴉ猕󹛫≮.︒; [V7]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒ +Ⴉ猕󹛫≮.。; ⴉ猕󹛫≮..; [V7, X4_2]; xn--gdh892bbz0d5438s..; [V7, A4_2]; ; # ⴉ猕≮.. +Ⴉ猕󹛫<\u0338.。; ⴉ猕󹛫≮..; [V7, X4_2]; xn--gdh892bbz0d5438s..; [V7, A4_2]; ; # ⴉ猕≮.. +ⴉ猕󹛫<\u0338.。; ⴉ猕󹛫≮..; [V7, X4_2]; xn--gdh892bbz0d5438s..; [V7, A4_2]; ; # ⴉ猕≮.. +ⴉ猕󹛫≮.。; ⴉ猕󹛫≮..; [V7, X4_2]; xn--gdh892bbz0d5438s..; [V7, A4_2]; ; # ⴉ猕≮.. +xn--gdh892bbz0d5438s..; ⴉ猕󹛫≮..; [V7, X4_2]; xn--gdh892bbz0d5438s..; [V7, A4_2]; ; # ⴉ猕≮.. +ⴉ猕󹛫<\u0338.︒; ⴉ猕󹛫≮.︒; [V7]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒ +ⴉ猕󹛫≮.︒; ⴉ猕󹛫≮.︒; [V7]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒ +xn--gdh892bbz0d5438s.xn--y86c; ⴉ猕󹛫≮.︒; [V7]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒ +xn--hnd212gz32d54x5r..; Ⴉ猕󹛫≮..; [V7, X4_2]; xn--hnd212gz32d54x5r..; [V7, A4_2]; ; # Ⴉ猕≮.. +xn--hnd212gz32d54x5r.xn--y86c; Ⴉ猕󹛫≮.︒; [V7]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒ +🏮。\u062B鳳\u07E2󠅉; 🏮.\u062B鳳\u07E2; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ +🏮。\u062B鳳\u07E2󠅉; 🏮.\u062B鳳\u07E2; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ +xn--8m8h.xn--qgb29f6z90a; 🏮.\u062B鳳\u07E2; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ +\u200D𐹶。ß; \u200D𐹶.ß; [B1, C2]; xn--1ug9105g.xn--zca; ; xn--uo0d.ss; [B1] # 𐹶.ß +\u200D𐹶。SS; \u200D𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss +\u200D𐹶。ss; \u200D𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss +\u200D𐹶。Ss; \u200D𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss +xn--uo0d.ss; 𐹶.ss; [B1]; xn--uo0d.ss; ; ; # 𐹶.ss +xn--1ug9105g.ss; \u200D𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; ; # 𐹶.ss +xn--1ug9105g.xn--zca; \u200D𐹶.ß; [B1, C2]; xn--1ug9105g.xn--zca; ; ; # 𐹶.ß +Å둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +A\u030A둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +Å둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +A\u030A둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +a\u030A둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +å둄-.\u200C; ; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +xn----1fa1788k.; å둄-.; [V3]; xn----1fa1788k.; [V3, A4_2]; ; # å둄-. +xn----1fa1788k.xn--0ug; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; ; # å둄-. +a\u030A둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +å둄-.\u200C; å둄-.\u200C; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3, A4_2] # å둄-. +\u3099򬎑\u1DD7𞤀.򱲢-\u0953; \u3099򬎑\u1DD7𞤢.򱲢-\u0953; [B1, B6, V6, V7]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓ +\u3099򬎑\u1DD7𞤢.򱲢-\u0953; ; [B1, B6, V6, V7]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓ +xn--veg121fwg63altj9d.xn----eyd92688s; \u3099򬎑\u1DD7𞤢.򱲢-\u0953; [B1, B6, V6, V7]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓ +ς.ß񴱄\u06DD\u2D7F; ; [B5, B6, V7]; xn--3xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # ς.ß⵿ +Σ.SS񴱄\u06DD\u2D7F; σ.ss񴱄\u06DD\u2D7F; [B5, B6, V7]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿ +σ.ss񴱄\u06DD\u2D7F; ; [B5, B6, V7]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿ +Σ.ss񴱄\u06DD\u2D7F; σ.ss񴱄\u06DD\u2D7F; [B5, B6, V7]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿ +xn--4xa.xn--ss-y8d4760biv60n; σ.ss񴱄\u06DD\u2D7F; [B5, B6, V7]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿ +Σ.ß񴱄\u06DD\u2D7F; σ.ß񴱄\u06DD\u2D7F; [B5, B6, V7]; xn--4xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # σ.ß⵿ +σ.ß񴱄\u06DD\u2D7F; ; [B5, B6, V7]; xn--4xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # σ.ß⵿ +xn--4xa.xn--zca281az71b8x73m; σ.ß񴱄\u06DD\u2D7F; [B5, B6, V7]; xn--4xa.xn--zca281az71b8x73m; ; ; # σ.ß⵿ +xn--3xa.xn--zca281az71b8x73m; ς.ß񴱄\u06DD\u2D7F; [B5, B6, V7]; xn--3xa.xn--zca281az71b8x73m; ; ; # ς.ß⵿ +ꡀ𞀟。\u066B\u0599; ꡀ𞀟.\u066B\u0599; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙ +ꡀ𞀟。\u066B\u0599; ꡀ𞀟.\u066B\u0599; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙ +xn--8b9a1720d.xn--kcb33b; ꡀ𞀟.\u066B\u0599; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙ +򈛉\u200C\u08A9。⧅񘘡-𐭡; 򈛉\u200C\u08A9.⧅񘘡-𐭡; [B1, B5, B6, C1, V7]; xn--yyb780jll63m.xn----zir1232guu71b; ; xn--yyb56242i.xn----zir1232guu71b; [B1, B5, B6, V7] # ࢩ.⧅-𐭡 +򈛉\u200C\u08A9。⧅񘘡-𐭡; 򈛉\u200C\u08A9.⧅񘘡-𐭡; [B1, B5, B6, C1, V7]; xn--yyb780jll63m.xn----zir1232guu71b; ; xn--yyb56242i.xn----zir1232guu71b; [B1, B5, B6, V7] # ࢩ.⧅-𐭡 +xn--yyb56242i.xn----zir1232guu71b; 򈛉\u08A9.⧅񘘡-𐭡; [B1, B5, B6, V7]; xn--yyb56242i.xn----zir1232guu71b; ; ; # ࢩ.⧅-𐭡 +xn--yyb780jll63m.xn----zir1232guu71b; 򈛉\u200C\u08A9.⧅񘘡-𐭡; [B1, B5, B6, C1, V7]; xn--yyb780jll63m.xn----zir1232guu71b; ; ; # ࢩ.⧅-𐭡 +룱\u200D𰍨\u200C。𝨖︒; 룱\u200D𰍨\u200C.𝨖︒; [C1, C2, V6, V7]; xn--0ugb3358ili2v.xn--y86cl899a; ; xn--ct2b0738h.xn--y86cl899a; [V6, V7] # 룱𰍨.𝨖︒ +룱\u200D𰍨\u200C。𝨖︒; 룱\u200D𰍨\u200C.𝨖︒; [C1, C2, V6, V7]; xn--0ugb3358ili2v.xn--y86cl899a; ; xn--ct2b0738h.xn--y86cl899a; [V6, V7] # 룱𰍨.𝨖︒ +룱\u200D𰍨\u200C。𝨖。; 룱\u200D𰍨\u200C.𝨖.; [C1, C2, V6]; xn--0ugb3358ili2v.xn--772h.; [C1, C2, V6, A4_2]; xn--ct2b0738h.xn--772h.; [V6, A4_2] # 룱𰍨.𝨖. +룱\u200D𰍨\u200C。𝨖。; 룱\u200D𰍨\u200C.𝨖.; [C1, C2, V6]; xn--0ugb3358ili2v.xn--772h.; [C1, C2, V6, A4_2]; xn--ct2b0738h.xn--772h.; [V6, A4_2] # 룱𰍨.𝨖. +xn--ct2b0738h.xn--772h.; 룱𰍨.𝨖.; [V6]; xn--ct2b0738h.xn--772h.; [V6, A4_2]; ; # 룱𰍨.𝨖. +xn--0ugb3358ili2v.xn--772h.; 룱\u200D𰍨\u200C.𝨖.; [C1, C2, V6]; xn--0ugb3358ili2v.xn--772h.; [C1, C2, V6, A4_2]; ; # 룱𰍨.𝨖. +xn--ct2b0738h.xn--y86cl899a; 룱𰍨.𝨖︒; [V6, V7]; xn--ct2b0738h.xn--y86cl899a; ; ; # 룱𰍨.𝨖︒ +xn--0ugb3358ili2v.xn--y86cl899a; 룱\u200D𰍨\u200C.𝨖︒; [C1, C2, V6, V7]; xn--0ugb3358ili2v.xn--y86cl899a; ; ; # 룱𰍨.𝨖︒ +🄄.\u1CDC⒈ß; 3,.\u1CDC⒈ß; [V6, V7, U1]; 3,.xn--zca344lmif; ; 3,.xn--ss-k1r094b; # 3,.᳜⒈ß +3,.\u1CDC1.ß; ; [V6, U1]; 3,.xn--1-43l.xn--zca; ; 3,.xn--1-43l.ss; # 3,.᳜1.ß +3,.\u1CDC1.SS; 3,.\u1CDC1.ss; [V6, U1]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss +3,.\u1CDC1.ss; ; [V6, U1]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss +3,.\u1CDC1.Ss; 3,.\u1CDC1.ss; [V6, U1]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss +3,.xn--1-43l.ss; 3,.\u1CDC1.ss; [V6, U1]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss +3,.xn--1-43l.xn--zca; 3,.\u1CDC1.ß; [V6, U1]; 3,.xn--1-43l.xn--zca; ; ; # 3,.᳜1.ß +🄄.\u1CDC⒈SS; 3,.\u1CDC⒈ss; [V6, V7, U1]; 3,.xn--ss-k1r094b; ; ; # 3,.᳜⒈ss +🄄.\u1CDC⒈ss; 3,.\u1CDC⒈ss; [V6, V7, U1]; 3,.xn--ss-k1r094b; ; ; # 3,.᳜⒈ss +🄄.\u1CDC⒈Ss; 3,.\u1CDC⒈ss; [V6, V7, U1]; 3,.xn--ss-k1r094b; ; ; # 3,.᳜⒈ss +3,.xn--ss-k1r094b; 3,.\u1CDC⒈ss; [V6, V7, U1]; 3,.xn--ss-k1r094b; ; ; # 3,.᳜⒈ss +3,.xn--zca344lmif; 3,.\u1CDC⒈ß; [V6, V7, U1]; 3,.xn--zca344lmif; ; ; # 3,.᳜⒈ß +xn--x07h.xn--ss-k1r094b; 🄄.\u1CDC⒈ss; [V6, V7]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss +xn--x07h.xn--zca344lmif; 🄄.\u1CDC⒈ß; [V6, V7]; xn--x07h.xn--zca344lmif; ; ; # 🄄.᳜⒈ß +񇌍\u2D7F。𞼓򡄨𑐺; 񇌍\u2D7F.𞼓򡄨𑐺; [B2, B3, V7]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺 +񇌍\u2D7F。𞼓򡄨𑐺; 񇌍\u2D7F.𞼓򡄨𑐺; [B2, B3, V7]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺 +xn--eoj16016a.xn--0v1d3848a3lr0d; 񇌍\u2D7F.𞼓򡄨𑐺; [B2, B3, V7]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺 +\u1DFD\u103A\u094D.≠\u200D㇛; \u103A\u094D\u1DFD.≠\u200D㇛; [C2, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [V6] # ်्᷽.≠㇛ +\u103A\u094D\u1DFD.≠\u200D㇛; \u103A\u094D\u1DFD.≠\u200D㇛; [C2, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [V6] # ်्᷽.≠㇛ +\u103A\u094D\u1DFD.=\u0338\u200D㇛; \u103A\u094D\u1DFD.≠\u200D㇛; [C2, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [V6] # ်्᷽.≠㇛ +\u103A\u094D\u1DFD.≠\u200D㇛; ; [C2, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [V6] # ်्᷽.≠㇛ +\u103A\u094D\u1DFD.=\u0338\u200D㇛; \u103A\u094D\u1DFD.≠\u200D㇛; [C2, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [V6] # ်्᷽.≠㇛ +xn--n3b956a9zm.xn--1ch912d; \u103A\u094D\u1DFD.≠㇛; [V6]; xn--n3b956a9zm.xn--1ch912d; ; ; # ်्᷽.≠㇛ +xn--n3b956a9zm.xn--1ug63gz5w; \u103A\u094D\u1DFD.≠\u200D㇛; [C2, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; ; # ်्᷽.≠㇛ +Ⴁ𐋨娤.\u200D\u033C\u0662𑖿; ⴁ𐋨娤.\u200D\u033C\u0662𑖿; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; xn--skjw75lg29h.xn--9ta62nrv36a; [B1, V6] # ⴁ𐋨娤.̼٢𑖿 +ⴁ𐋨娤.\u200D\u033C\u0662𑖿; ; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; xn--skjw75lg29h.xn--9ta62nrv36a; [B1, V6] # ⴁ𐋨娤.̼٢𑖿 +xn--skjw75lg29h.xn--9ta62nrv36a; ⴁ𐋨娤.\u033C\u0662𑖿; [B1, V6]; xn--skjw75lg29h.xn--9ta62nrv36a; ; ; # ⴁ𐋨娤.̼٢𑖿 +xn--skjw75lg29h.xn--9ta62ngt6aou8t; ⴁ𐋨娤.\u200D\u033C\u0662𑖿; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; ; # ⴁ𐋨娤.̼٢𑖿 +xn--8md2578ag21g.xn--9ta62nrv36a; Ⴁ𐋨娤.\u033C\u0662𑖿; [B1, V6, V7]; xn--8md2578ag21g.xn--9ta62nrv36a; ; ; # Ⴁ𐋨娤.̼٢𑖿 +xn--8md2578ag21g.xn--9ta62ngt6aou8t; Ⴁ𐋨娤.\u200D\u033C\u0662𑖿; [B1, C2, V7]; xn--8md2578ag21g.xn--9ta62ngt6aou8t; ; ; # Ⴁ𐋨娤.̼٢𑖿 +🄀Ⴄ\u0669\u0820。⒈\u0FB6ß; 🄀ⴄ\u0669\u0820.⒈\u0FB6ß; [B1, V7]; xn--iib29fp25e0219a.xn--zca117e3vp; ; xn--iib29fp25e0219a.xn--ss-1sj588o; # 🄀ⴄ٩ࠠ.⒈ྶß +0.Ⴄ\u0669\u0820。1.\u0FB6ß; 0.ⴄ\u0669\u0820.1.\u0FB6ß; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--zca117e; ; 0.xn--iib29fp25e.1.xn--ss-1sj; # 0.ⴄ٩ࠠ.1.ྶß +0.ⴄ\u0669\u0820。1.\u0FB6ß; 0.ⴄ\u0669\u0820.1.\u0FB6ß; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--zca117e; ; 0.xn--iib29fp25e.1.xn--ss-1sj; # 0.ⴄ٩ࠠ.1.ྶß +0.Ⴄ\u0669\u0820。1.\u0FB6SS; 0.ⴄ\u0669\u0820.1.\u0FB6ss; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss +0.ⴄ\u0669\u0820。1.\u0FB6ss; 0.ⴄ\u0669\u0820.1.\u0FB6ss; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss +0.Ⴄ\u0669\u0820。1.\u0FB6Ss; 0.ⴄ\u0669\u0820.1.\u0FB6ss; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss +0.xn--iib29fp25e.1.xn--ss-1sj; 0.ⴄ\u0669\u0820.1.\u0FB6ss; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss +0.xn--iib29fp25e.1.xn--zca117e; 0.ⴄ\u0669\u0820.1.\u0FB6ß; [B1, B5, B6, V6]; 0.xn--iib29fp25e.1.xn--zca117e; ; ; # 0.ⴄ٩ࠠ.1.ྶß +🄀ⴄ\u0669\u0820。⒈\u0FB6ß; 🄀ⴄ\u0669\u0820.⒈\u0FB6ß; [B1, V7]; xn--iib29fp25e0219a.xn--zca117e3vp; ; xn--iib29fp25e0219a.xn--ss-1sj588o; # 🄀ⴄ٩ࠠ.⒈ྶß +🄀Ⴄ\u0669\u0820。⒈\u0FB6SS; 🄀ⴄ\u0669\u0820.⒈\u0FB6ss; [B1, V7]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss +🄀ⴄ\u0669\u0820。⒈\u0FB6ss; 🄀ⴄ\u0669\u0820.⒈\u0FB6ss; [B1, V7]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss +🄀Ⴄ\u0669\u0820。⒈\u0FB6Ss; 🄀ⴄ\u0669\u0820.⒈\u0FB6ss; [B1, V7]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss +xn--iib29fp25e0219a.xn--ss-1sj588o; 🄀ⴄ\u0669\u0820.⒈\u0FB6ss; [B1, V7]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss +xn--iib29fp25e0219a.xn--zca117e3vp; 🄀ⴄ\u0669\u0820.⒈\u0FB6ß; [B1, V7]; xn--iib29fp25e0219a.xn--zca117e3vp; ; ; # 🄀ⴄ٩ࠠ.⒈ྶß +0.xn--iib29f26o.1.xn--ss-1sj; 0.Ⴄ\u0669\u0820.1.\u0FB6ss; [B1, B5, B6, V6, V7]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss +0.xn--iib29f26o.1.xn--zca117e; 0.Ⴄ\u0669\u0820.1.\u0FB6ß; [B1, B5, B6, V6, V7]; 0.xn--iib29f26o.1.xn--zca117e; ; ; # 0.Ⴄ٩ࠠ.1.ྶß +xn--iib29f26o6n43c.xn--ss-1sj588o; 🄀Ⴄ\u0669\u0820.⒈\u0FB6ss; [B1, V7]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss +xn--iib29f26o6n43c.xn--zca117e3vp; 🄀Ⴄ\u0669\u0820.⒈\u0FB6ß; [B1, V7]; xn--iib29f26o6n43c.xn--zca117e3vp; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶß +≠.\u200C-\u066B; ; [B1, C1]; xn--1ch.xn----vqc597q; ; xn--1ch.xn----vqc; [B1, V3] # ≠.-٫ +=\u0338.\u200C-\u066B; ≠.\u200C-\u066B; [B1, C1]; xn--1ch.xn----vqc597q; ; xn--1ch.xn----vqc; [B1, V3] # ≠.-٫ +xn--1ch.xn----vqc; ≠.-\u066B; [B1, V3]; xn--1ch.xn----vqc; ; ; # ≠.-٫ +xn--1ch.xn----vqc597q; ≠.\u200C-\u066B; [B1, C1]; xn--1ch.xn----vqc597q; ; ; # ≠.-٫ +\u0660۱。󠳶𞠁\u0665; \u0660۱.󠳶𞠁\u0665; [B1, V7]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥ +\u0660۱。󠳶𞠁\u0665; \u0660۱.󠳶𞠁\u0665; [B1, V7]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥ +xn--8hb40a.xn--eib7967vner3e; \u0660۱.󠳶𞠁\u0665; [B1, V7]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥ +\u200C\u0663⒖。󱅉𽷛\u1BF3; \u200C\u0663⒖.󱅉𽷛\u1BF3; [B1, C1, V7]; xn--cib152kwgd.xn--1zf13512buy41d; ; xn--cib675m.xn--1zf13512buy41d; [B1, V7] # ٣⒖.᯳ +\u200C\u066315.。󱅉𽷛\u1BF3; \u200C\u066315..󱅉𽷛\u1BF3; [B1, C1, V7, X4_2]; xn--15-gyd983x..xn--1zf13512buy41d; [B1, C1, V7, A4_2]; xn--15-gyd..xn--1zf13512buy41d; [B1, V7, A4_2] # ٣15..᯳ +xn--15-gyd..xn--1zf13512buy41d; \u066315..󱅉𽷛\u1BF3; [B1, V7, X4_2]; xn--15-gyd..xn--1zf13512buy41d; [B1, V7, A4_2]; ; # ٣15..᯳ +xn--15-gyd983x..xn--1zf13512buy41d; \u200C\u066315..󱅉𽷛\u1BF3; [B1, C1, V7, X4_2]; xn--15-gyd983x..xn--1zf13512buy41d; [B1, C1, V7, A4_2]; ; # ٣15..᯳ +xn--cib675m.xn--1zf13512buy41d; \u0663⒖.󱅉𽷛\u1BF3; [B1, V7]; xn--cib675m.xn--1zf13512buy41d; ; ; # ٣⒖.᯳ +xn--cib152kwgd.xn--1zf13512buy41d; \u200C\u0663⒖.󱅉𽷛\u1BF3; [B1, C1, V7]; xn--cib152kwgd.xn--1zf13512buy41d; ; ; # ٣⒖.᯳ +\u1BF3.-逋񳦭󙙮; ; [V3, V6, V7]; xn--1zf.xn----483d46987byr50b; ; ; # ᯳.-逋 +xn--1zf.xn----483d46987byr50b; \u1BF3.-逋񳦭󙙮; [V3, V6, V7]; xn--1zf.xn----483d46987byr50b; ; ; # ᯳.-逋 +\u0756。\u3164\u200Dς; \u0756.\u200Dς; [B1, C2]; xn--9ob.xn--3xa995l; ; xn--9ob.xn--4xa; [] # ݖ.ς +\u0756。\u1160\u200Dς; \u0756.\u200Dς; [B1, C2]; xn--9ob.xn--3xa995l; ; xn--9ob.xn--4xa; [] # ݖ.ς +\u0756。\u1160\u200DΣ; \u0756.\u200Dσ; [B1, C2]; xn--9ob.xn--4xa795l; ; xn--9ob.xn--4xa; [] # ݖ.σ +\u0756。\u1160\u200Dσ; \u0756.\u200Dσ; [B1, C2]; xn--9ob.xn--4xa795l; ; xn--9ob.xn--4xa; [] # ݖ.σ +xn--9ob.xn--4xa; \u0756.σ; ; xn--9ob.xn--4xa; ; ; # ݖ.σ +\u0756.σ; ; ; xn--9ob.xn--4xa; ; ; # ݖ.σ +\u0756.Σ; \u0756.σ; ; xn--9ob.xn--4xa; ; ; # ݖ.σ +xn--9ob.xn--4xa795l; \u0756.\u200Dσ; [B1, C2]; xn--9ob.xn--4xa795l; ; ; # ݖ.σ +xn--9ob.xn--3xa995l; \u0756.\u200Dς; [B1, C2]; xn--9ob.xn--3xa995l; ; ; # ݖ.ς +\u0756。\u3164\u200DΣ; \u0756.\u200Dσ; [B1, C2]; xn--9ob.xn--4xa795l; ; xn--9ob.xn--4xa; [] # ݖ.σ +\u0756。\u3164\u200Dσ; \u0756.\u200Dσ; [B1, C2]; xn--9ob.xn--4xa795l; ; xn--9ob.xn--4xa; [] # ݖ.σ +xn--9ob.xn--4xa380e; \u0756.\u1160σ; [V7]; xn--9ob.xn--4xa380e; ; ; # ݖ.σ +xn--9ob.xn--4xa380ebol; \u0756.\u1160\u200Dσ; [C2, V7]; xn--9ob.xn--4xa380ebol; ; ; # ݖ.σ +xn--9ob.xn--3xa580ebol; \u0756.\u1160\u200Dς; [C2, V7]; xn--9ob.xn--3xa580ebol; ; ; # ݖ.ς +xn--9ob.xn--4xa574u; \u0756.\u3164σ; [V7]; xn--9ob.xn--4xa574u; ; ; # ݖ.σ +xn--9ob.xn--4xa795lq2l; \u0756.\u3164\u200Dσ; [C2, V7]; xn--9ob.xn--4xa795lq2l; ; ; # ݖ.σ +xn--9ob.xn--3xa995lq2l; \u0756.\u3164\u200Dς; [C2, V7]; xn--9ob.xn--3xa995lq2l; ; ; # ݖ.ς +ᡆႣ。󞢧\u0315\u200D\u200D; ᡆⴃ.󞢧\u0315\u200D\u200D; [C2, V7]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [V7] # ᡆⴃ.̕ +ᡆႣ。󞢧\u0315\u200D\u200D; ᡆⴃ.󞢧\u0315\u200D\u200D; [C2, V7]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [V7] # ᡆⴃ.̕ +ᡆⴃ。󞢧\u0315\u200D\u200D; ᡆⴃ.󞢧\u0315\u200D\u200D; [C2, V7]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [V7] # ᡆⴃ.̕ +xn--57e237h.xn--5sa98523p; ᡆⴃ.󞢧\u0315; [V7]; xn--57e237h.xn--5sa98523p; ; ; # ᡆⴃ.̕ +xn--57e237h.xn--5sa649la993427a; ᡆⴃ.󞢧\u0315\u200D\u200D; [C2, V7]; xn--57e237h.xn--5sa649la993427a; ; ; # ᡆⴃ.̕ +ᡆⴃ。󞢧\u0315\u200D\u200D; ᡆⴃ.󞢧\u0315\u200D\u200D; [C2, V7]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [V7] # ᡆⴃ.̕ +xn--bnd320b.xn--5sa98523p; ᡆႣ.󞢧\u0315; [V7]; xn--bnd320b.xn--5sa98523p; ; ; # ᡆႣ.̕ +xn--bnd320b.xn--5sa649la993427a; ᡆႣ.󞢧\u0315\u200D\u200D; [C2, V7]; xn--bnd320b.xn--5sa649la993427a; ; ; # ᡆႣ.̕ +㭄\u200D\u084F𑚵.ς𐮮\u200C\u200D; 㭄\u200D\u084F𑚵.ς𐮮\u200C\u200D; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.ς𐮮 +㭄\u200D\u084F𑚵.ς𐮮\u200C\u200D; ; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.ς𐮮 +㭄\u200D\u084F𑚵.Σ𐮮\u200C\u200D; 㭄\u200D\u084F𑚵.σ𐮮\u200C\u200D; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮 +㭄\u200D\u084F𑚵.σ𐮮\u200C\u200D; ; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮 +xn--ewb302xhu1l.xn--4xa0426k; 㭄\u084F𑚵.σ𐮮; [B5, B6]; xn--ewb302xhu1l.xn--4xa0426k; ; ; # 㭄ࡏ𑚵.σ𐮮 +xn--ewb962jfitku4r.xn--4xa695lda6932v; 㭄\u200D\u084F𑚵.σ𐮮\u200C\u200D; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; ; # 㭄ࡏ𑚵.σ𐮮 +xn--ewb962jfitku4r.xn--3xa895lda6932v; 㭄\u200D\u084F𑚵.ς𐮮\u200C\u200D; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; ; # 㭄ࡏ𑚵.ς𐮮 +㭄\u200D\u084F𑚵.Σ𐮮\u200C\u200D; 㭄\u200D\u084F𑚵.σ𐮮\u200C\u200D; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮 +㭄\u200D\u084F𑚵.σ𐮮\u200C\u200D; 㭄\u200D\u084F𑚵.σ𐮮\u200C\u200D; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮 +\u17B5。𞯸ꡀ🄋; .𞯸ꡀ🄋; [B2, B3, V7, X4_2]; .xn--8b9ar252dngd; [B2, B3, V7, A4_2]; ; # .ꡀ🄋 +.xn--8b9ar252dngd; .𞯸ꡀ🄋; [B2, B3, V7, X4_2]; .xn--8b9ar252dngd; [B2, B3, V7, A4_2]; ; # .ꡀ🄋 +xn--03e.xn--8b9ar252dngd; \u17B5.𞯸ꡀ🄋; [B1, B2, B3, V6, V7]; xn--03e.xn--8b9ar252dngd; ; ; # .ꡀ🄋 +󐪺暑.⾑\u0668; 󐪺暑.襾\u0668; [B5, B6, V7]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨ +󐪺暑.襾\u0668; ; [B5, B6, V7]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨ +xn--tlvq3513e.xn--hib9228d; 󐪺暑.襾\u0668; [B5, B6, V7]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨ +󠄚≯ꡢ。\u0891\u1DFF; ≯ꡢ.\u0891\u1DFF; [B1, V7]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿ +󠄚>\u0338ꡢ。\u0891\u1DFF; ≯ꡢ.\u0891\u1DFF; [B1, V7]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿ +xn--hdh7783c.xn--9xb680i; ≯ꡢ.\u0891\u1DFF; [B1, V7]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿ +\uFDC3𮁱\u0B4D𐨿.󐧤Ⴗ; \u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤ⴗ; [B2, B3, V7]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ +\u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤Ⴗ; \u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤ⴗ; [B2, B3, V7]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ +\u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤ⴗ; ; [B2, B3, V7]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ +xn--fhbea662czx68a2tju.xn--fljz2846h; \u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤ⴗ; [B2, B3, V7]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ +\uFDC3𮁱\u0B4D𐨿.󐧤ⴗ; \u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤ⴗ; [B2, B3, V7]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ +xn--fhbea662czx68a2tju.xn--vnd55511o; \u0643\u0645\u0645𮁱\u0B4D𐨿.󐧤Ⴗ; [B2, B3, V7]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ +𞀨。\u1B44򡛨𞎇; 𞀨.\u1B44򡛨𞎇; [V6, V7]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄ +𞀨。\u1B44򡛨𞎇; 𞀨.\u1B44򡛨𞎇; [V6, V7]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄ +xn--mi4h.xn--1uf6843smg20c; 𞀨.\u1B44򡛨𞎇; [V6, V7]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄ +󠣼\u200C.𐺰\u200Cᡟ; 󠣼\u200C.𐺰\u200Cᡟ; [B1, B2, B3, C1, V7]; xn--0ug18531l.xn--v8e340bp21t; ; xn--q046e.xn--v8e7227j; [B1, B2, B3, V7] # .𐺰ᡟ +󠣼\u200C.𐺰\u200Cᡟ; ; [B1, B2, B3, C1, V7]; xn--0ug18531l.xn--v8e340bp21t; ; xn--q046e.xn--v8e7227j; [B1, B2, B3, V7] # .𐺰ᡟ +xn--q046e.xn--v8e7227j; 󠣼.𐺰ᡟ; [B1, B2, B3, V7]; xn--q046e.xn--v8e7227j; ; ; # .𐺰ᡟ +xn--0ug18531l.xn--v8e340bp21t; 󠣼\u200C.𐺰\u200Cᡟ; [B1, B2, B3, C1, V7]; xn--0ug18531l.xn--v8e340bp21t; ; ; # .𐺰ᡟ +ᢛ󨅟ß.ጧ; ; [V7]; xn--zca562jc642x.xn--p5d; ; xn--ss-7dp66033t.xn--p5d; # ᢛß.ጧ +ᢛ󨅟SS.ጧ; ᢛ󨅟ss.ጧ; [V7]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ +ᢛ󨅟ss.ጧ; ; [V7]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ +ᢛ󨅟Ss.ጧ; ᢛ󨅟ss.ጧ; [V7]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ +xn--ss-7dp66033t.xn--p5d; ᢛ󨅟ss.ጧ; [V7]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ +xn--zca562jc642x.xn--p5d; ᢛ󨅟ß.ጧ; [V7]; xn--zca562jc642x.xn--p5d; ; ; # ᢛß.ጧ +⮒\u200C.񒚗\u200C; ; [C1, V7]; xn--0ugx66b.xn--0ugz2871c; ; xn--b9i.xn--5p9y; [V7] # ⮒. +xn--b9i.xn--5p9y; ⮒.񒚗; [V7]; xn--b9i.xn--5p9y; ; ; # ⮒. +xn--0ugx66b.xn--0ugz2871c; ⮒\u200C.񒚗\u200C; [C1, V7]; xn--0ugx66b.xn--0ugz2871c; ; ; # ⮒. +𞤂񹞁𐹯。Ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, V7]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ +𞤤񹞁𐹯。ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, V7]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ +xn--no0dr648a51o3b.xn--klj; 𞤤񹞁𐹯.ⴜ; [B2, V7]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ +xn--no0dr648a51o3b.xn--0nd; 𞤤񹞁𐹯.Ⴜ; [B2, V7]; xn--no0dr648a51o3b.xn--0nd; ; ; # 𞤤𐹯.Ⴜ +𞤂񹞁𐹯。ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, V7]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ +𐹵⮣\u200C𑄰。񷴿\uFCB7; 𐹵⮣\u200C𑄰.񷴿\u0636\u0645; [B1, B5, B6, C1, V7]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; xn--s9i5458e7yb.xn--1gb4a66004i; [B1, B5, B6, V7] # 𐹵⮣𑄰.ضم +𐹵⮣\u200C𑄰。񷴿\u0636\u0645; 𐹵⮣\u200C𑄰.񷴿\u0636\u0645; [B1, B5, B6, C1, V7]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; xn--s9i5458e7yb.xn--1gb4a66004i; [B1, B5, B6, V7] # 𐹵⮣𑄰.ضم +xn--s9i5458e7yb.xn--1gb4a66004i; 𐹵⮣𑄰.񷴿\u0636\u0645; [B1, B5, B6, V7]; xn--s9i5458e7yb.xn--1gb4a66004i; ; ; # 𐹵⮣𑄰.ضم +xn--0ug586bcj8p7jc.xn--1gb4a66004i; 𐹵⮣\u200C𑄰.񷴿\u0636\u0645; [B1, B5, B6, C1, V7]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; ; # 𐹵⮣𑄰.ضم +Ⴒ。デß𞤵\u0C4D; ⴒ.デß𞤵\u0C4D; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్ +Ⴒ。テ\u3099ß𞤵\u0C4D; ⴒ.デß𞤵\u0C4D; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్ +ⴒ。テ\u3099ß𞤵\u0C4D; ⴒ.デß𞤵\u0C4D; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్ +ⴒ。デß𞤵\u0C4D; ⴒ.デß𞤵\u0C4D; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్ +Ⴒ。デSS𞤓\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +Ⴒ。テ\u3099SS𞤓\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +ⴒ。テ\u3099ss𞤵\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +ⴒ。デss𞤵\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +Ⴒ。デSs𞤵\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +Ⴒ。テ\u3099Ss𞤵\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +xn--9kj.xn--ss-9nh3648ahh20b; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +xn--9kj.xn--zca669cmr3a0f28a; ⴒ.デß𞤵\u0C4D; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; ; # ⴒ.デß𞤵్ +xn--qnd.xn--ss-9nh3648ahh20b; Ⴒ.デss𞤵\u0C4D; [B5, B6, V7]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్ +xn--qnd.xn--zca669cmr3a0f28a; Ⴒ.デß𞤵\u0C4D; [B5, B6, V7]; xn--qnd.xn--zca669cmr3a0f28a; ; ; # Ⴒ.デß𞤵్ +Ⴒ。デSS𞤵\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +Ⴒ。テ\u3099SS𞤵\u0C4D; ⴒ.デss𞤵\u0C4D; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్ +𑁿\u0D4D.7-\u07D2; 𑁿\u0D4D.7-\u07D2; [B1, V6]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ +𑁿\u0D4D.7-\u07D2; ; [B1, V6]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ +xn--wxc1283k.xn--7--yue; 𑁿\u0D4D.7-\u07D2; [B1, V6]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ +≯𑜫󠭇.\u1734񒞤𑍬ᢧ; ; [V6, V7]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ +>\u0338𑜫󠭇.\u1734񒞤𑍬ᢧ; ≯𑜫󠭇.\u1734񒞤𑍬ᢧ; [V6, V7]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ +xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ≯𑜫󠭇.\u1734񒞤𑍬ᢧ; [V6, V7]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ +\u1DDB򎐙Ⴗ쏔。\u0781; \u1DDB򎐙ⴗ쏔.\u0781; [B1, V6, V7]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ +\u1DDB򎐙Ⴗ쏔。\u0781; \u1DDB򎐙ⴗ쏔.\u0781; [B1, V6, V7]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ +\u1DDB򎐙ⴗ쏔。\u0781; \u1DDB򎐙ⴗ쏔.\u0781; [B1, V6, V7]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ +\u1DDB򎐙ⴗ쏔。\u0781; \u1DDB򎐙ⴗ쏔.\u0781; [B1, V6, V7]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ +xn--zegy26dw47iy6w2f.xn--iqb; \u1DDB򎐙ⴗ쏔.\u0781; [B1, V6, V7]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ +xn--vnd148d733ky6n9e.xn--iqb; \u1DDB򎐙Ⴗ쏔.\u0781; [B1, V6, V7]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ +ß。𐋳Ⴌ\u0FB8; ß.𐋳ⴌ\u0FB8; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ +ß。𐋳Ⴌ\u0FB8; ß.𐋳ⴌ\u0FB8; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ +ß。𐋳ⴌ\u0FB8; ß.𐋳ⴌ\u0FB8; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ +SS。𐋳Ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +ss。𐋳ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +Ss。𐋳Ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +ss.xn--lgd921mvv0m; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +ss.𐋳ⴌ\u0FB8; ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +SS.𐋳Ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +Ss.𐋳Ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +xn--zca.xn--lgd921mvv0m; ß.𐋳ⴌ\u0FB8; ; xn--zca.xn--lgd921mvv0m; ; ; # ß.𐋳ⴌྸ +ß.𐋳ⴌ\u0FB8; ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ +ß。𐋳ⴌ\u0FB8; ß.𐋳ⴌ\u0FB8; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ +SS。𐋳Ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +ss。𐋳ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +Ss。𐋳Ⴌ\u0FB8; ss.𐋳ⴌ\u0FB8; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ +ss.xn--lgd10cu829c; ss.𐋳Ⴌ\u0FB8; [V7]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ +xn--zca.xn--lgd10cu829c; ß.𐋳Ⴌ\u0FB8; [V7]; xn--zca.xn--lgd10cu829c; ; ; # ß.𐋳Ⴌྸ +-\u069E𐶡.\u200C⾝\u09CD; -\u069E𐶡.\u200C身\u09CD; [B1, C1, V3, V7]; xn----stc7013r.xn--b7b305imj2f; ; xn----stc7013r.xn--b7b1419d; [B1, V3, V7] # -ڞ.身্ +-\u069E𐶡.\u200C身\u09CD; ; [B1, C1, V3, V7]; xn----stc7013r.xn--b7b305imj2f; ; xn----stc7013r.xn--b7b1419d; [B1, V3, V7] # -ڞ.身্ +xn----stc7013r.xn--b7b1419d; -\u069E𐶡.身\u09CD; [B1, V3, V7]; xn----stc7013r.xn--b7b1419d; ; ; # -ڞ.身্ +xn----stc7013r.xn--b7b305imj2f; -\u069E𐶡.\u200C身\u09CD; [B1, C1, V3, V7]; xn----stc7013r.xn--b7b305imj2f; ; ; # -ڞ.身্ +😮\u0764𑈵𞀖.💅\u200D; 😮\u0764𑈵𞀖.💅\u200D; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; xn--opb4277kuc7elqsa.xn--kr8h; [B1] # 😮ݤ𑈵𞀖.💅 +😮\u0764𑈵𞀖.💅\u200D; ; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; xn--opb4277kuc7elqsa.xn--kr8h; [B1] # 😮ݤ𑈵𞀖.💅 +xn--opb4277kuc7elqsa.xn--kr8h; 😮\u0764𑈵𞀖.💅; [B1]; xn--opb4277kuc7elqsa.xn--kr8h; ; ; # 😮ݤ𑈵𞀖.💅 +xn--opb4277kuc7elqsa.xn--1ug5265p; 😮\u0764𑈵𞀖.💅\u200D; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; ; # 😮ݤ𑈵𞀖.💅 +\u08F2\u200D꙳\u0712.ᢏ\u200C󠍄; ; [B1, B6, C1, C2, V6, V7]; xn--cnb37g904be26j.xn--89e849ax9363a; ; xn--cnb37gdy00a.xn--89e02253p; [B1, B6, V6, V7] # ࣲ꙳ܒ.ᢏ +xn--cnb37gdy00a.xn--89e02253p; \u08F2꙳\u0712.ᢏ󠍄; [B1, B6, V6, V7]; xn--cnb37gdy00a.xn--89e02253p; ; ; # ࣲ꙳ܒ.ᢏ +xn--cnb37g904be26j.xn--89e849ax9363a; \u08F2\u200D꙳\u0712.ᢏ\u200C󠍄; [B1, B6, C1, C2, V6, V7]; xn--cnb37g904be26j.xn--89e849ax9363a; ; ; # ࣲ꙳ܒ.ᢏ +Ⴑ.\u06BF𞯓ᠲ; ⴑ.\u06BF𞯓ᠲ; [B2, B3, V7]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ +Ⴑ.\u06BF𞯓ᠲ; ⴑ.\u06BF𞯓ᠲ; [B2, B3, V7]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ +ⴑ.\u06BF𞯓ᠲ; ; [B2, B3, V7]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ +xn--8kj.xn--ykb840gd555a; ⴑ.\u06BF𞯓ᠲ; [B2, B3, V7]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ +ⴑ.\u06BF𞯓ᠲ; ⴑ.\u06BF𞯓ᠲ; [B2, B3, V7]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ +xn--pnd.xn--ykb840gd555a; Ⴑ.\u06BF𞯓ᠲ; [B2, B3, V7]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ +\u1A5A𛦝\u0C4D。𚝬𝟵; \u1A5A𛦝\u0C4D.𚝬9; [V6, V7]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9 +\u1A5A𛦝\u0C4D。𚝬9; \u1A5A𛦝\u0C4D.𚝬9; [V6, V7]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9 +xn--lqc703ebm93a.xn--9-000p; \u1A5A𛦝\u0C4D.𚝬9; [V6, V7]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9 +\u200C\u06A0𿺆𝟗。Ⴣ꒘\uFCD0񐘖; \u200C\u06A0𿺆9.ⴣ꒘\u0645\u062E񐘖; [B1, B5, C1, V7]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, V7] # ڠ9.ⴣ꒘مخ +\u200C\u06A0𿺆9。Ⴣ꒘\u0645\u062E񐘖; \u200C\u06A0𿺆9.ⴣ꒘\u0645\u062E񐘖; [B1, B5, C1, V7]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, V7] # ڠ9.ⴣ꒘مخ +\u200C\u06A0𿺆9。ⴣ꒘\u0645\u062E񐘖; \u200C\u06A0𿺆9.ⴣ꒘\u0645\u062E񐘖; [B1, B5, C1, V7]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, V7] # ڠ9.ⴣ꒘مخ +xn--9-vtc42319e.xn--tgb9bz87p833hw316c; \u06A0𿺆9.ⴣ꒘\u0645\u062E񐘖; [B2, B5, V7]; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; ; ; # ڠ9.ⴣ꒘مخ +xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; \u200C\u06A0𿺆9.ⴣ꒘\u0645\u062E񐘖; [B1, B5, C1, V7]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; ; # ڠ9.ⴣ꒘مخ +\u200C\u06A0𿺆𝟗。ⴣ꒘\uFCD0񐘖; \u200C\u06A0𿺆9.ⴣ꒘\u0645\u062E񐘖; [B1, B5, C1, V7]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, V7] # ڠ9.ⴣ꒘مخ +xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; \u06A0𿺆9.Ⴣ꒘\u0645\u062E񐘖; [B2, B5, V7]; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; ; ; # ڠ9.Ⴣ꒘مخ +xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; \u200C\u06A0𿺆9.Ⴣ꒘\u0645\u062E񐘖; [B1, B5, C1, V7]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; ; # ڠ9.Ⴣ꒘مخ +ᡖ。\u031F񗛨\u0B82-; ᡖ.\u031F񗛨\u0B82-; [V3, V6, V7]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ- +ᡖ。\u031F񗛨\u0B82-; ᡖ.\u031F񗛨\u0B82-; [V3, V6, V7]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ- +xn--m8e.xn----mdb555dkk71m; ᡖ.\u031F񗛨\u0B82-; [V3, V6, V7]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ- +𞠠浘。絧𞀀; 𞠠浘.絧𞀀; [B2, B3]; xn--e0wp491f.xn--ud0a3573e; ; ; # 𞠠浘.絧𞀀 +xn--e0wp491f.xn--ud0a3573e; 𞠠浘.絧𞀀; [B2, B3]; xn--e0wp491f.xn--ud0a3573e; ; ; # 𞠠浘.絧𞀀 +\u0596Ⴋ.𝟳≯︒\uFE0A; \u0596ⴋ.7≯︒; [V6, V7]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒ +\u0596Ⴋ.𝟳>\u0338︒\uFE0A; \u0596ⴋ.7≯︒; [V6, V7]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒ +\u0596Ⴋ.7≯。\uFE0A; \u0596ⴋ.7≯.; [V6]; xn--hcb613r.xn--7-pgo.; [V6, A4_2]; ; # ֖ⴋ.7≯. +\u0596Ⴋ.7>\u0338。\uFE0A; \u0596ⴋ.7≯.; [V6]; xn--hcb613r.xn--7-pgo.; [V6, A4_2]; ; # ֖ⴋ.7≯. +\u0596ⴋ.7>\u0338。\uFE0A; \u0596ⴋ.7≯.; [V6]; xn--hcb613r.xn--7-pgo.; [V6, A4_2]; ; # ֖ⴋ.7≯. +\u0596ⴋ.7≯。\uFE0A; \u0596ⴋ.7≯.; [V6]; xn--hcb613r.xn--7-pgo.; [V6, A4_2]; ; # ֖ⴋ.7≯. +xn--hcb613r.xn--7-pgo.; \u0596ⴋ.7≯.; [V6]; xn--hcb613r.xn--7-pgo.; [V6, A4_2]; ; # ֖ⴋ.7≯. +\u0596ⴋ.𝟳>\u0338︒\uFE0A; \u0596ⴋ.7≯︒; [V6, V7]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒ +\u0596ⴋ.𝟳≯︒\uFE0A; \u0596ⴋ.7≯︒; [V6, V7]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒ +xn--hcb613r.xn--7-pgoy530h; \u0596ⴋ.7≯︒; [V6, V7]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒ +xn--hcb887c.xn--7-pgo.; \u0596Ⴋ.7≯.; [V6, V7]; xn--hcb887c.xn--7-pgo.; [V6, V7, A4_2]; ; # ֖Ⴋ.7≯. +xn--hcb887c.xn--7-pgoy530h; \u0596Ⴋ.7≯︒; [V6, V7]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒ +\u200DF𑓂。󠺨︒\u077E𐹢; \u200Df𑓂.󠺨︒\u077E𐹢; [B1, C2, V7]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; xn--f-kq9i.xn--fqb1637j8hky9452a; [B1, V7] # f𑓂.︒ݾ𐹢 +\u200DF𑓂。󠺨。\u077E𐹢; \u200Df𑓂.󠺨.\u077E𐹢; [B1, C2, V7]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; xn--f-kq9i.xn--7656e.xn--fqb4175k; [B1, V7] # f𑓂..ݾ𐹢 +\u200Df𑓂。󠺨。\u077E𐹢; \u200Df𑓂.󠺨.\u077E𐹢; [B1, C2, V7]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; xn--f-kq9i.xn--7656e.xn--fqb4175k; [B1, V7] # f𑓂..ݾ𐹢 +xn--f-kq9i.xn--7656e.xn--fqb4175k; f𑓂.󠺨.\u077E𐹢; [B1, V7]; xn--f-kq9i.xn--7656e.xn--fqb4175k; ; ; # f𑓂..ݾ𐹢 +xn--f-tgn9761i.xn--7656e.xn--fqb4175k; \u200Df𑓂.󠺨.\u077E𐹢; [B1, C2, V7]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; ; # f𑓂..ݾ𐹢 +\u200Df𑓂。󠺨︒\u077E𐹢; \u200Df𑓂.󠺨︒\u077E𐹢; [B1, C2, V7]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; xn--f-kq9i.xn--fqb1637j8hky9452a; [B1, V7] # f𑓂.︒ݾ𐹢 +xn--f-kq9i.xn--fqb1637j8hky9452a; f𑓂.󠺨︒\u077E𐹢; [B1, V7]; xn--f-kq9i.xn--fqb1637j8hky9452a; ; ; # f𑓂.︒ݾ𐹢 +xn--f-tgn9761i.xn--fqb1637j8hky9452a; \u200Df𑓂.󠺨︒\u077E𐹢; [B1, C2, V7]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; ; # f𑓂.︒ݾ𐹢 +\u0845🄇𐼗︒。𐹻𑜫; \u08456,𐼗︒.𐹻𑜫; [B1, B3, V7, U1]; xn--6,-r4e6182wo1ra.xn--zo0di2m; ; ; # ࡅ6,𐼗︒.𐹻𑜫 +\u08456,𐼗。。𐹻𑜫; \u08456,𐼗..𐹻𑜫; [B1, U1, X4_2]; xn--6,-r4e4420y..xn--zo0di2m; [B1, U1, A4_2]; ; # ࡅ6,𐼗..𐹻𑜫 +xn--6,-r4e4420y..xn--zo0di2m; \u08456,𐼗..𐹻𑜫; [B1, U1, X4_2]; xn--6,-r4e4420y..xn--zo0di2m; [B1, U1, A4_2]; ; # ࡅ6,𐼗..𐹻𑜫 +xn--6,-r4e6182wo1ra.xn--zo0di2m; \u08456,𐼗︒.𐹻𑜫; [B1, B3, V7, U1]; xn--6,-r4e6182wo1ra.xn--zo0di2m; ; ; # ࡅ6,𐼗︒.𐹻𑜫 +xn--3vb4696jpxkjh7s.xn--zo0di2m; \u0845🄇𐼗︒.𐹻𑜫; [B1, B3, V7]; xn--3vb4696jpxkjh7s.xn--zo0di2m; ; ; # ࡅ🄇𐼗︒.𐹻𑜫 +𐹈.\u1DC0𑈱𐦭; ; [B1, V6, V7]; xn--jn0d.xn--7dg0871h3lf; ; ; # .᷀𑈱𐦭 +xn--jn0d.xn--7dg0871h3lf; 𐹈.\u1DC0𑈱𐦭; [B1, V6, V7]; xn--jn0d.xn--7dg0871h3lf; ; ; # .᷀𑈱𐦭 +Ⴂ䠺。𞤃񅏎󙮦\u0693; ⴂ䠺.𞤥񅏎󙮦\u0693; [B2, V7]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ +ⴂ䠺。𞤥񅏎󙮦\u0693; ⴂ䠺.𞤥񅏎󙮦\u0693; [B2, V7]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ +xn--tkj638f.xn--pjb9818vg4xno967d; ⴂ䠺.𞤥񅏎󙮦\u0693; [B2, V7]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ +xn--9md875z.xn--pjb9818vg4xno967d; Ⴂ䠺.𞤥񅏎󙮦\u0693; [B2, V7]; xn--9md875z.xn--pjb9818vg4xno967d; ; ; # Ⴂ䠺.𞤥ړ +ⴂ䠺。𞤃񅏎󙮦\u0693; ⴂ䠺.𞤥񅏎󙮦\u0693; [B2, V7]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ +🄇伐︒.𜙚\uA8C4; 6,伐︒.𜙚\uA8C4; [V7, U1]; xn--6,-7i3cj157d.xn--0f9ao925c; ; ; # 6,伐︒.꣄ +6,伐。.𜙚\uA8C4; 6,伐..𜙚\uA8C4; [V7, U1, X4_2]; xn--6,-7i3c..xn--0f9ao925c; [V7, U1, A4_2]; ; # 6,伐..꣄ +xn--6,-7i3c..xn--0f9ao925c; 6,伐..𜙚\uA8C4; [V7, U1, X4_2]; xn--6,-7i3c..xn--0f9ao925c; [V7, U1, A4_2]; ; # 6,伐..꣄ +xn--6,-7i3cj157d.xn--0f9ao925c; 6,伐︒.𜙚\uA8C4; [V7, U1]; xn--6,-7i3cj157d.xn--0f9ao925c; ; ; # 6,伐︒.꣄ +xn--woqs083bel0g.xn--0f9ao925c; 🄇伐︒.𜙚\uA8C4; [V7]; xn--woqs083bel0g.xn--0f9ao925c; ; ; # 🄇伐︒.꣄ +\u200D𐹠\uABED\uFFFB。\u200D𐫓Ⴚ𑂹; \u200D𐹠\uABED\uFFFB.\u200D𐫓ⴚ𑂹; [B1, C2, V7]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; xn--429az70n29i.xn--ilj7702eqyd; [B1, B2, B3, V7] # 𐹠꯭.𐫓ⴚ𑂹 +\u200D𐹠\uABED\uFFFB。\u200D𐫓ⴚ𑂹; \u200D𐹠\uABED\uFFFB.\u200D𐫓ⴚ𑂹; [B1, C2, V7]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; xn--429az70n29i.xn--ilj7702eqyd; [B1, B2, B3, V7] # 𐹠꯭.𐫓ⴚ𑂹 +xn--429az70n29i.xn--ilj7702eqyd; 𐹠\uABED\uFFFB.𐫓ⴚ𑂹; [B1, B2, B3, V7]; xn--429az70n29i.xn--ilj7702eqyd; ; ; # 𐹠꯭.𐫓ⴚ𑂹 +xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; \u200D𐹠\uABED\uFFFB.\u200D𐫓ⴚ𑂹; [B1, C2, V7]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; ; # 𐹠꯭.𐫓ⴚ𑂹 +xn--429az70n29i.xn--ynd3619jqyd; 𐹠\uABED\uFFFB.𐫓Ⴚ𑂹; [B1, B2, B3, V7]; xn--429az70n29i.xn--ynd3619jqyd; ; ; # 𐹠꯭.𐫓Ⴚ𑂹 +xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; \u200D𐹠\uABED\uFFFB.\u200D𐫓Ⴚ𑂹; [B1, C2, V7]; xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ; ; # 𐹠꯭.𐫓Ⴚ𑂹 +󠆠.񷐴󌟈; .񷐴󌟈; [V7, X4_2]; .xn--rx21bhv12i; [V7, A4_2]; ; # . +󠆠.񷐴󌟈; .񷐴󌟈; [V7, X4_2]; .xn--rx21bhv12i; [V7, A4_2]; ; # . +.xn--rx21bhv12i; .񷐴󌟈; [V7, X4_2]; .xn--rx21bhv12i; [V7, A4_2]; ; # . +𐫃\u200CႦ.≠𞷙; 𐫃\u200Cⴆ.≠𞷙; [B1, B2, B3, C1, V7]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, V7] # 𐫃ⴆ.≠ +𐫃\u200CႦ.=\u0338𞷙; 𐫃\u200Cⴆ.≠𞷙; [B1, B2, B3, C1, V7]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, V7] # 𐫃ⴆ.≠ +𐫃\u200Cⴆ.=\u0338𞷙; 𐫃\u200Cⴆ.≠𞷙; [B1, B2, B3, C1, V7]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, V7] # 𐫃ⴆ.≠ +𐫃\u200Cⴆ.≠𞷙; ; [B1, B2, B3, C1, V7]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, V7] # 𐫃ⴆ.≠ +xn--xkjz802e.xn--1ch2802p; 𐫃ⴆ.≠𞷙; [B1, B2, B3, V7]; xn--xkjz802e.xn--1ch2802p; ; ; # 𐫃ⴆ.≠ +xn--0ug132csv7o.xn--1ch2802p; 𐫃\u200Cⴆ.≠𞷙; [B1, B2, B3, C1, V7]; xn--0ug132csv7o.xn--1ch2802p; ; ; # 𐫃ⴆ.≠ +xn--end1719j.xn--1ch2802p; 𐫃Ⴆ.≠𞷙; [B1, B2, B3, V7]; xn--end1719j.xn--1ch2802p; ; ; # 𐫃Ⴆ.≠ +xn--end799ekr1p.xn--1ch2802p; 𐫃\u200CႦ.≠𞷙; [B1, B2, B3, C1, V7]; xn--end799ekr1p.xn--1ch2802p; ; ; # 𐫃Ⴆ.≠ +󠁲𙩢𝟥ꘌ.\u0841; 󠁲𙩢3ꘌ.\u0841; [B1, V7]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ +󠁲𙩢3ꘌ.\u0841; ; [B1, V7]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ +xn--3-0g3es485d8i15h.xn--zvb; 󠁲𙩢3ꘌ.\u0841; [B1, V7]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ +-.\u1886󡲣-; ; [V3, V6, V7]; -.xn----pbkx6497q; ; ; # -.ᢆ- +-.xn----pbkx6497q; -.\u1886󡲣-; [V3, V6, V7]; -.xn----pbkx6497q; ; ; # -.ᢆ- +󲚗\u200C。\u200C𞰆ς; 󲚗\u200C.\u200C𞰆ς; [B1, B6, C1, V7]; xn--0ug76062m.xn--3xa795lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, V7] # .ς +󲚗\u200C。\u200C𞰆ς; 󲚗\u200C.\u200C𞰆ς; [B1, B6, C1, V7]; xn--0ug76062m.xn--3xa795lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, V7] # .ς +󲚗\u200C。\u200C𞰆Σ; 󲚗\u200C.\u200C𞰆σ; [B1, B6, C1, V7]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, V7] # .σ +󲚗\u200C。\u200C𞰆σ; 󲚗\u200C.\u200C𞰆σ; [B1, B6, C1, V7]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, V7] # .σ +xn--qp42f.xn--4xa3011w; 󲚗.𞰆σ; [B2, B3, V7]; xn--qp42f.xn--4xa3011w; ; ; # .σ +xn--0ug76062m.xn--4xa595lhn92a; 󲚗\u200C.\u200C𞰆σ; [B1, B6, C1, V7]; xn--0ug76062m.xn--4xa595lhn92a; ; ; # .σ +xn--0ug76062m.xn--3xa795lhn92a; 󲚗\u200C.\u200C𞰆ς; [B1, B6, C1, V7]; xn--0ug76062m.xn--3xa795lhn92a; ; ; # .ς +󲚗\u200C。\u200C𞰆Σ; 󲚗\u200C.\u200C𞰆σ; [B1, B6, C1, V7]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, V7] # .σ +󲚗\u200C。\u200C𞰆σ; 󲚗\u200C.\u200C𞰆σ; [B1, B6, C1, V7]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, V7] # .σ +堕𑓂\u1B02。𐮇𞤽\u200C-; 堕𑓂\u1B02.𐮇𞤽\u200C-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; xn--5sf345zdk8h.xn----iv5iw606c; [B3, V3] # 堕𑓂ᬂ.𐮇𞤽- +堕𑓂\u1B02。𐮇𞤛\u200C-; 堕𑓂\u1B02.𐮇𞤽\u200C-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; xn--5sf345zdk8h.xn----iv5iw606c; [B3, V3] # 堕𑓂ᬂ.𐮇𞤽- +xn--5sf345zdk8h.xn----iv5iw606c; 堕𑓂\u1B02.𐮇𞤽-; [B3, V3]; xn--5sf345zdk8h.xn----iv5iw606c; ; ; # 堕𑓂ᬂ.𐮇𞤽- +xn--5sf345zdk8h.xn----rgnt157hwl9g; 堕𑓂\u1B02.𐮇𞤽\u200C-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; ; # 堕𑓂ᬂ.𐮇𞤽- +𐹶𑁆ᡕ𞤢。ᡥς\u062Aς; 𐹶𑁆ᡕ𞤢.ᡥς\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥςتς +𐹶𑁆ᡕ𞤢。ᡥς\u062Aς; 𐹶𑁆ᡕ𞤢.ᡥς\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥςتς +𐹶𑁆ᡕ𞤀。ᡥΣ\u062AΣ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥσ\u062Aσ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +xn--l8e1317j1ebz456b.xn--4xaa85plx4a; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +xn--l8e1317j1ebz456b.xn--3xaa16plx4a; 𐹶𑁆ᡕ𞤢.ᡥς\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥςتς +𐹶𑁆ᡕ𞤀。ᡥΣ\u062AΣ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥσ\u062Aσ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥΣ\u062AΣ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥΣ\u062Aσ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥΣ\u062Aς; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς +𐹶𑁆ᡕ𞤢。ᡥσ\u062Aς; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς +xn--l8e1317j1ebz456b.xn--3xab95plx4a; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتς +𐹶𑁆ᡕ𞤢。ᡥΣ\u062AΣ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥΣ\u062Aσ; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ +𐹶𑁆ᡕ𞤢。ᡥΣ\u062Aς; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς +𐹶𑁆ᡕ𞤢。ᡥσ\u062Aς; 𐹶𑁆ᡕ𞤢.ᡥσ\u062Aς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς +󏒰.-𝟻ß; 󏒰.-5ß; [V3, V7]; xn--t960e.xn---5-hia; ; xn--t960e.-5ss; # .-5ß +󏒰.-5ß; ; [V3, V7]; xn--t960e.xn---5-hia; ; xn--t960e.-5ss; # .-5ß +󏒰.-5SS; 󏒰.-5ss; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +󏒰.-5ss; ; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +xn--t960e.-5ss; 󏒰.-5ss; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +xn--t960e.xn---5-hia; 󏒰.-5ß; [V3, V7]; xn--t960e.xn---5-hia; ; ; # .-5ß +󏒰.-𝟻SS; 󏒰.-5ss; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +󏒰.-𝟻ss; 󏒰.-5ss; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +󏒰.-𝟻Ss; 󏒰.-5ss; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +󏒰.-5Ss; 󏒰.-5ss; [V3, V7]; xn--t960e.-5ss; ; ; # .-5ss +\u200D𐨿.🤒Ⴥ򑮶; \u200D𐨿.🤒ⴥ򑮶; [C2, V7]; xn--1ug9533g.xn--tljz038l0gz4b; ; xn--0s9c.xn--tljz038l0gz4b; [V6, V7] # 𐨿.🤒ⴥ +\u200D𐨿.🤒ⴥ򑮶; ; [C2, V7]; xn--1ug9533g.xn--tljz038l0gz4b; ; xn--0s9c.xn--tljz038l0gz4b; [V6, V7] # 𐨿.🤒ⴥ +xn--0s9c.xn--tljz038l0gz4b; 𐨿.🤒ⴥ򑮶; [V6, V7]; xn--0s9c.xn--tljz038l0gz4b; ; ; # 𐨿.🤒ⴥ +xn--1ug9533g.xn--tljz038l0gz4b; \u200D𐨿.🤒ⴥ򑮶; [C2, V7]; xn--1ug9533g.xn--tljz038l0gz4b; ; ; # 𐨿.🤒ⴥ +xn--0s9c.xn--9nd3211w0gz4b; 𐨿.🤒Ⴥ򑮶; [V6, V7]; xn--0s9c.xn--9nd3211w0gz4b; ; ; # 𐨿.🤒Ⴥ +xn--1ug9533g.xn--9nd3211w0gz4b; \u200D𐨿.🤒Ⴥ򑮶; [C2, V7]; xn--1ug9533g.xn--9nd3211w0gz4b; ; ; # 𐨿.🤒Ⴥ +𵋅。ß𬵩\u200D; 𵋅.ß𬵩\u200D; [C2, V7]; xn--ey1p.xn--zca870nz438b; ; xn--ey1p.xn--ss-eq36b; [V7] # .ß𬵩 +𵋅。SS𬵩\u200D; 𵋅.ss𬵩\u200D; [C2, V7]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [V7] # .ss𬵩 +𵋅。ss𬵩\u200D; 𵋅.ss𬵩\u200D; [C2, V7]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [V7] # .ss𬵩 +𵋅。Ss𬵩\u200D; 𵋅.ss𬵩\u200D; [C2, V7]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [V7] # .ss𬵩 +xn--ey1p.xn--ss-eq36b; 𵋅.ss𬵩; [V7]; xn--ey1p.xn--ss-eq36b; ; ; # .ss𬵩 +xn--ey1p.xn--ss-n1tx0508a; 𵋅.ss𬵩\u200D; [C2, V7]; xn--ey1p.xn--ss-n1tx0508a; ; ; # .ss𬵩 +xn--ey1p.xn--zca870nz438b; 𵋅.ß𬵩\u200D; [C2, V7]; xn--ey1p.xn--zca870nz438b; ; ; # .ß𬵩 +\u200C𭉝。\u07F1\u0301𞹻; \u200C𭉝.\u07F1\u0301\u063A; [B1, C1, V6]; xn--0ugy003y.xn--lsa46nuub; ; xn--634m.xn--lsa46nuub; [B1, V6] # 𭉝.߱́غ +\u200C𭉝。\u07F1\u0301\u063A; \u200C𭉝.\u07F1\u0301\u063A; [B1, C1, V6]; xn--0ugy003y.xn--lsa46nuub; ; xn--634m.xn--lsa46nuub; [B1, V6] # 𭉝.߱́غ +xn--634m.xn--lsa46nuub; 𭉝.\u07F1\u0301\u063A; [B1, V6]; xn--634m.xn--lsa46nuub; ; ; # 𭉝.߱́غ +xn--0ugy003y.xn--lsa46nuub; \u200C𭉝.\u07F1\u0301\u063A; [B1, C1, V6]; xn--0ugy003y.xn--lsa46nuub; ; ; # 𭉝.߱́غ +𞼌\u200C𑈶。𐹡; 𞼌\u200C𑈶.𐹡; [B1, B3, C1, V7]; xn--0ug7946gzpxf.xn--8n0d; ; xn--9g1d1288a.xn--8n0d; [B1, V7] # 𑈶.𐹡 +xn--9g1d1288a.xn--8n0d; 𞼌𑈶.𐹡; [B1, V7]; xn--9g1d1288a.xn--8n0d; ; ; # 𑈶.𐹡 +xn--0ug7946gzpxf.xn--8n0d; 𞼌\u200C𑈶.𐹡; [B1, B3, C1, V7]; xn--0ug7946gzpxf.xn--8n0d; ; ; # 𑈶.𐹡 +󠅯򇽭\u200C🜭。𑖿\u1ABBς≠; 򇽭\u200C🜭.𑖿\u1ABBς≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻ς≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBς=\u0338; 򇽭\u200C🜭.𑖿\u1ABBς≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻ς≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBς≠; 򇽭\u200C🜭.𑖿\u1ABBς≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻ς≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBς=\u0338; 򇽭\u200C🜭.𑖿\u1ABBς≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻ς≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBΣ=\u0338; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBΣ≠; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBσ≠; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBσ=\u0338; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +xn--zb9h5968x.xn--4xa378i1mfjw7y; 򇽭🜭.𑖿\u1ABBσ≠; [V6, V7]; xn--zb9h5968x.xn--4xa378i1mfjw7y; ; ; # 🜭.𑖿᪻σ≠ +xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; ; # 🜭.𑖿᪻σ≠ +xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; 򇽭\u200C🜭.𑖿\u1ABBς≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; ; # 🜭.𑖿᪻ς≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBΣ=\u0338; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBΣ≠; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBσ≠; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +󠅯򇽭\u200C🜭。𑖿\u1ABBσ=\u0338; 򇽭\u200C🜭.𑖿\u1ABBσ≠; [C1, V6, V7]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [V6, V7] # 🜭.𑖿᪻σ≠ +⒋。⒈\u200D򳴢; ⒋.⒈\u200D򳴢; [C2, V7]; xn--wsh.xn--1ug58o74922a; ; xn--wsh.xn--tsh07994h; [V7] # ⒋.⒈ +4.。1.\u200D򳴢; 4..1.\u200D򳴢; [C2, V7, X4_2]; 4..1.xn--1ug64613i; [C2, V7, A4_2]; 4..1.xn--sf51d; [V7, A4_2] # 4..1. +4..1.xn--sf51d; 4..1.򳴢; [V7, X4_2]; 4..1.xn--sf51d; [V7, A4_2]; ; # 4..1. +4..1.xn--1ug64613i; 4..1.\u200D򳴢; [C2, V7, X4_2]; 4..1.xn--1ug64613i; [C2, V7, A4_2]; ; # 4..1. +xn--wsh.xn--tsh07994h; ⒋.⒈򳴢; [V7]; xn--wsh.xn--tsh07994h; ; ; # ⒋.⒈ +xn--wsh.xn--1ug58o74922a; ⒋.⒈\u200D򳴢; [C2, V7]; xn--wsh.xn--1ug58o74922a; ; ; # ⒋.⒈ +\u0644ß。𐇽\u1A60򾅢𞤾; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾 +\u0644ß。\u1A60𐇽򾅢𞤾; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾 +\u0644ß。\u1A60𐇽򾅢𞤾; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾 +\u0644SS。\u1A60𐇽򾅢𞤜; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ss。\u1A60𐇽򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ss。\u1A60𐇽򾅢𞤜; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +xn--ss-svd.xn--jof2298hn83fln78f; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ß。\u1A60𐇽򾅢𞤜; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾 +xn--zca57y.xn--jof2298hn83fln78f; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; ; # لß.᩠𐇽𞤾 +\u0644SS。\u1A60𐇽򾅢𞤜; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ss。\u1A60𐇽򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ss。\u1A60𐇽򾅢𞤜; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ß。\u1A60𐇽򾅢𞤜; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾 +\u0644SS。𐇽\u1A60򾅢𞤜; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ss。𐇽\u1A60򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ss。𐇽\u1A60򾅢𞤜; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644ß。𐇽\u1A60򾅢𞤜; \u0644ß.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾 +\u0644SS。\u1A60𐇽򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644Ss。\u1A60𐇽򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644SS。\u1A60𐇽򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644Ss。\u1A60𐇽򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644SS。𐇽\u1A60򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +\u0644Ss。𐇽\u1A60򾅢𞤾; \u0644ss.\u1A60𐇽򾅢𞤾; [B1, B2, B3, V6, V7]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾 +𐹽𑄳񼜲.\u1DDF\u17B8\uA806𑜫; ; [B1, V6, V7]; xn--1o0di0c0652w.xn--33e362arr1l153d; ; ; # 𐹽𑄳.ᷟី꠆𑜫 +xn--1o0di0c0652w.xn--33e362arr1l153d; 𐹽𑄳񼜲.\u1DDF\u17B8\uA806𑜫; [B1, V6, V7]; xn--1o0di0c0652w.xn--33e362arr1l153d; ; ; # 𐹽𑄳.ᷟី꠆𑜫 +Ⴓ𑜫\u200D򗭓.\u06A7𑰶; ⴓ𑜫\u200D򗭓.\u06A7𑰶; [V7]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶 +Ⴓ𑜫\u200D򗭓.\u06A7𑰶; ⴓ𑜫\u200D򗭓.\u06A7𑰶; [V7]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶 +ⴓ𑜫\u200D򗭓.\u06A7𑰶; ; [V7]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶 +xn--blj6306ey091d.xn--9jb4223l; ⴓ𑜫򗭓.\u06A7𑰶; [V7]; xn--blj6306ey091d.xn--9jb4223l; ; ; # ⴓ𑜫.ڧ𑰶 +xn--1ugy52cym7p7xu5e.xn--9jb4223l; ⴓ𑜫\u200D򗭓.\u06A7𑰶; [V7]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; ; # ⴓ𑜫.ڧ𑰶 +ⴓ𑜫\u200D򗭓.\u06A7𑰶; ⴓ𑜫\u200D򗭓.\u06A7𑰶; [V7]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶 +xn--rnd8945ky009c.xn--9jb4223l; Ⴓ𑜫򗭓.\u06A7𑰶; [V7]; xn--rnd8945ky009c.xn--9jb4223l; ; ; # Ⴓ𑜫.ڧ𑰶 +xn--rnd479ep20q7x12e.xn--9jb4223l; Ⴓ𑜫\u200D򗭓.\u06A7𑰶; [V7]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; ; # Ⴓ𑜫.ڧ𑰶 +𐨿.🄆—; 𐨿.5,—; [V6, U1]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,— +𐨿.5,—; ; [V6, U1]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,— +xn--0s9c.xn--5,-81t; 𐨿.5,—; [V6, U1]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,— +xn--0s9c.xn--8ug8324p; 𐨿.🄆—; [V6, V7]; xn--0s9c.xn--8ug8324p; ; ; # 𐨿.🄆— +򔊱񁦮۸。󠾭-; 򔊱񁦮۸.󠾭-; [V3, V7]; xn--lmb18944c0g2z.xn----2k81m; ; ; # ۸.- +xn--lmb18944c0g2z.xn----2k81m; 򔊱񁦮۸.󠾭-; [V3, V7]; xn--lmb18944c0g2z.xn----2k81m; ; ; # ۸.- +𼗸\u07CD𐹮。\u06DDᡎᠴ; 𼗸\u07CD𐹮.\u06DDᡎᠴ; [B1, B5, B6, V7]; xn--osb0855kcc2r.xn--tlb299fhc; ; ; # ߍ𐹮.ᡎᠴ +xn--osb0855kcc2r.xn--tlb299fhc; 𼗸\u07CD𐹮.\u06DDᡎᠴ; [B1, B5, B6, V7]; xn--osb0855kcc2r.xn--tlb299fhc; ; ; # ߍ𐹮.ᡎᠴ +\u200DᠮႾ🄂.🚗\u0841𮹌\u200C; \u200Dᠮⴞ1,.🚗\u0841𮹌\u200C; [B1, C1, C2, U1]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; xn--1,-v3o625k.xn--zvb3124wpkpf; [B1, B6, U1] # ᠮⴞ1,.🚗ࡁ𮹌 +\u200DᠮႾ1,.🚗\u0841𮹌\u200C; \u200Dᠮⴞ1,.🚗\u0841𮹌\u200C; [B1, C1, C2, U1]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; xn--1,-v3o625k.xn--zvb3124wpkpf; [B1, B6, U1] # ᠮⴞ1,.🚗ࡁ𮹌 +\u200Dᠮⴞ1,.🚗\u0841𮹌\u200C; ; [B1, C1, C2, U1]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; xn--1,-v3o625k.xn--zvb3124wpkpf; [B1, B6, U1] # ᠮⴞ1,.🚗ࡁ𮹌 +xn--1,-v3o625k.xn--zvb3124wpkpf; ᠮⴞ1,.🚗\u0841𮹌; [B1, B6, U1]; xn--1,-v3o625k.xn--zvb3124wpkpf; ; ; # ᠮⴞ1,.🚗ࡁ𮹌 +xn--1,-v3o161c53q.xn--zvb692j9664aic1g; \u200Dᠮⴞ1,.🚗\u0841𮹌\u200C; [B1, C1, C2, U1]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; ; # ᠮⴞ1,.🚗ࡁ𮹌 +\u200Dᠮⴞ🄂.🚗\u0841𮹌\u200C; \u200Dᠮⴞ1,.🚗\u0841𮹌\u200C; [B1, C1, C2, U1]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; xn--1,-v3o625k.xn--zvb3124wpkpf; [B1, B6, U1] # ᠮⴞ1,.🚗ࡁ𮹌 +xn--1,-ogkx89c.xn--zvb3124wpkpf; ᠮႾ1,.🚗\u0841𮹌; [B1, B6, V7, U1]; xn--1,-ogkx89c.xn--zvb3124wpkpf; ; ; # ᠮႾ1,.🚗ࡁ𮹌 +xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; \u200DᠮႾ1,.🚗\u0841𮹌\u200C; [B1, C1, C2, V7, U1]; xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ; ; # ᠮႾ1,.🚗ࡁ𮹌 +xn--h7e438h1p44a.xn--zvb3124wpkpf; ᠮⴞ🄂.🚗\u0841𮹌; [B1, V7]; xn--h7e438h1p44a.xn--zvb3124wpkpf; ; ; # ᠮⴞ🄂.🚗ࡁ𮹌 +xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; \u200Dᠮⴞ🄂.🚗\u0841𮹌\u200C; [B1, C1, C2, V7]; xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ; ; # ᠮⴞ🄂.🚗ࡁ𮹌 +xn--2nd129ai554b.xn--zvb3124wpkpf; ᠮႾ🄂.🚗\u0841𮹌; [B1, V7]; xn--2nd129ai554b.xn--zvb3124wpkpf; ; ; # ᠮႾ🄂.🚗ࡁ𮹌 +xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; \u200DᠮႾ🄂.🚗\u0841𮹌\u200C; [B1, C1, C2, V7]; xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ; ; # ᠮႾ🄂.🚗ࡁ𮹌 +\u0601\u0697.𑚶񼡷⾆; \u0601\u0697.𑚶񼡷舌; [B1, V6, V7]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌 +\u0601\u0697.𑚶񼡷舌; ; [B1, V6, V7]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌 +xn--jfb41a.xn--tc1ap851axo39c; \u0601\u0697.𑚶񼡷舌; [B1, V6, V7]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌 +🞅󠳡󜍙.񲖷; ; [V7]; xn--ie9hi1349bqdlb.xn--oj69a; ; ; # 🞅. +xn--ie9hi1349bqdlb.xn--oj69a; 🞅󠳡󜍙.񲖷; [V7]; xn--ie9hi1349bqdlb.xn--oj69a; ; ; # 🞅. +\u20E7񯡎-򫣝.4Ⴄ\u200C; \u20E7񯡎-򫣝.4ⴄ\u200C; [C1, V6, V7]; xn----9snu5320fi76w.xn--4-sgn589c; ; xn----9snu5320fi76w.xn--4-ivs; [V6, V7] # ⃧-.4ⴄ +\u20E7񯡎-򫣝.4ⴄ\u200C; ; [C1, V6, V7]; xn----9snu5320fi76w.xn--4-sgn589c; ; xn----9snu5320fi76w.xn--4-ivs; [V6, V7] # ⃧-.4ⴄ +xn----9snu5320fi76w.xn--4-ivs; \u20E7񯡎-򫣝.4ⴄ; [V6, V7]; xn----9snu5320fi76w.xn--4-ivs; ; ; # ⃧-.4ⴄ +xn----9snu5320fi76w.xn--4-sgn589c; \u20E7񯡎-򫣝.4ⴄ\u200C; [C1, V6, V7]; xn----9snu5320fi76w.xn--4-sgn589c; ; ; # ⃧-.4ⴄ +xn----9snu5320fi76w.xn--4-f0g; \u20E7񯡎-򫣝.4Ⴄ; [V6, V7]; xn----9snu5320fi76w.xn--4-f0g; ; ; # ⃧-.4Ⴄ +xn----9snu5320fi76w.xn--4-f0g649i; \u20E7񯡎-򫣝.4Ⴄ\u200C; [C1, V6, V7]; xn----9snu5320fi76w.xn--4-f0g649i; ; ; # ⃧-.4Ⴄ +ᚭ。𝌠ß𖫱; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱 +ᚭ。𝌠ß𖫱; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱 +ᚭ。𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ。𝌠ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ。𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +xn--hwe.xn--ss-ci1ub261a; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ.𝌠ss𖫱; ; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ.𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ.𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +xn--hwe.xn--zca4946pblnc; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; ; # ᚭ.𝌠ß𖫱 +ᚭ.𝌠ß𖫱; ; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱 +ᚭ。𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ。𝌠ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +ᚭ。𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱 +₁。𞤫ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ +1。𞤫ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ +1。𞤉ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ +1.xn--gd9al691d; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ +₁。𞤉ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ +𯻼\u200C.𞶞򻙤񥘇; ; [B2, B3, B6, C1, V7]; xn--0ug27500a.xn--2b7hs861pl540a; ; xn--kg4n.xn--2b7hs861pl540a; [B2, B3, V7] # . +xn--kg4n.xn--2b7hs861pl540a; 𯻼.𞶞򻙤񥘇; [B2, B3, V7]; xn--kg4n.xn--2b7hs861pl540a; ; ; # . +xn--0ug27500a.xn--2b7hs861pl540a; 𯻼\u200C.𞶞򻙤񥘇; [B2, B3, B6, C1, V7]; xn--0ug27500a.xn--2b7hs861pl540a; ; ; # . +𑑄≯。𑜤; 𑑄≯.𑜤; [V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤 +𑑄>\u0338。𑜤; 𑑄≯.𑜤; [V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤 +𑑄≯。𑜤; 𑑄≯.𑜤; [V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤 +𑑄>\u0338。𑜤; 𑑄≯.𑜤; [V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤 +xn--hdh5636g.xn--ci2d; 𑑄≯.𑜤; [V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤 +Ⴋ≮𱲆。\u200D\u07A7𐋣; ⴋ≮𱲆.\u200D\u07A7𐋣; [C2]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [V6] # ⴋ≮𱲆.ާ𐋣 +Ⴋ<\u0338𱲆。\u200D\u07A7𐋣; ⴋ≮𱲆.\u200D\u07A7𐋣; [C2]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [V6] # ⴋ≮𱲆.ާ𐋣 +ⴋ<\u0338𱲆。\u200D\u07A7𐋣; ⴋ≮𱲆.\u200D\u07A7𐋣; [C2]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [V6] # ⴋ≮𱲆.ާ𐋣 +ⴋ≮𱲆。\u200D\u07A7𐋣; ⴋ≮𱲆.\u200D\u07A7𐋣; [C2]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [V6] # ⴋ≮𱲆.ާ𐋣 +xn--gdhz03bxt42d.xn--lrb6479j; ⴋ≮𱲆.\u07A7𐋣; [V6]; xn--gdhz03bxt42d.xn--lrb6479j; ; ; # ⴋ≮𱲆.ާ𐋣 +xn--gdhz03bxt42d.xn--lrb506jqr4n; ⴋ≮𱲆.\u200D\u07A7𐋣; [C2]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; ; # ⴋ≮𱲆.ާ𐋣 +xn--jnd802gsm17c.xn--lrb6479j; Ⴋ≮𱲆.\u07A7𐋣; [V6, V7]; xn--jnd802gsm17c.xn--lrb6479j; ; ; # Ⴋ≮𱲆.ާ𐋣 +xn--jnd802gsm17c.xn--lrb506jqr4n; Ⴋ≮𱲆.\u200D\u07A7𐋣; [C2, V7]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; ; # Ⴋ≮𱲆.ާ𐋣 +\u17D2.򆽒≯; ; [V6, V7]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯ +\u17D2.򆽒>\u0338; \u17D2.򆽒≯; [V6, V7]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯ +xn--u4e.xn--hdhx0084f; \u17D2.򆽒≯; [V6, V7]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯ +񏁇\u1734.𐨺É⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺E\u0301⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺É⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺E\u0301⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺e\u0301⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺é⬓𑄴; ; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +xn--c0e34564d.xn--9ca207st53lg3f; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺e\u0301⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +񏁇\u1734.𐨺é⬓𑄴; 񏁇\u1734.𐨺é⬓𑄴; [V6, V7]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴 +ᢇ\u200D\uA8C4。︒𞤺; ᢇ\u200D\uA8C4.︒𞤺; [B1, B6, C2, V7]; xn--09e669a6x8j.xn--y86cv562b; ; xn--09e4694e.xn--y86cv562b; [B1, V7] # ᢇ꣄.︒𞤺 +ᢇ\u200D\uA8C4。。𞤺; ᢇ\u200D\uA8C4..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; xn--09e4694e..xn--ye6h; [A4_2] # ᢇ꣄..𞤺 +ᢇ\u200D\uA8C4。。𞤘; ᢇ\u200D\uA8C4..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; xn--09e4694e..xn--ye6h; [A4_2] # ᢇ꣄..𞤺 +xn--09e4694e..xn--ye6h; ᢇ\uA8C4..𞤺; [X4_2]; xn--09e4694e..xn--ye6h; [A4_2]; ; # ᢇ꣄..𞤺 +xn--09e669a6x8j..xn--ye6h; ᢇ\u200D\uA8C4..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; ; # ᢇ꣄..𞤺 +ᢇ\u200D\uA8C4。︒𞤘; ᢇ\u200D\uA8C4.︒𞤺; [B1, B6, C2, V7]; xn--09e669a6x8j.xn--y86cv562b; ; xn--09e4694e.xn--y86cv562b; [B1, V7] # ᢇ꣄.︒𞤺 +xn--09e4694e.xn--y86cv562b; ᢇ\uA8C4.︒𞤺; [B1, V7]; xn--09e4694e.xn--y86cv562b; ; ; # ᢇ꣄.︒𞤺 +xn--09e669a6x8j.xn--y86cv562b; ᢇ\u200D\uA8C4.︒𞤺; [B1, B6, C2, V7]; xn--09e669a6x8j.xn--y86cv562b; ; ; # ᢇ꣄.︒𞤺 +𞩬򖙱\u1714\u200C。\u0631\u07AA≮; 𞩬򖙱\u1714\u200C.\u0631\u07AA≮; [B2, B3, V7]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮ +𞩬򖙱\u1714\u200C。\u0631\u07AA<\u0338; 𞩬򖙱\u1714\u200C.\u0631\u07AA≮; [B2, B3, V7]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮ +𞩬򖙱\u1714\u200C。\u0631\u07AA≮; 𞩬򖙱\u1714\u200C.\u0631\u07AA≮; [B2, B3, V7]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮ +𞩬򖙱\u1714\u200C。\u0631\u07AA<\u0338; 𞩬򖙱\u1714\u200C.\u0631\u07AA≮; [B2, B3, V7]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮ +xn--fze3930v7hz6b.xn--wgb86el10d; 𞩬򖙱\u1714.\u0631\u07AA≮; [B2, B3, V7]; xn--fze3930v7hz6b.xn--wgb86el10d; ; ; # ᜔.رު≮ +xn--fze607b9651bjwl7c.xn--wgb86el10d; 𞩬򖙱\u1714\u200C.\u0631\u07AA≮; [B2, B3, V7]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; ; # ᜔.رު≮ +Ⴣ.\u0653ᢤ; ⴣ.\u0653ᢤ; [V6]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ +Ⴣ.\u0653ᢤ; ⴣ.\u0653ᢤ; [V6]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ +ⴣ.\u0653ᢤ; ; [V6]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ +xn--rlj.xn--vhb294g; ⴣ.\u0653ᢤ; [V6]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ +ⴣ.\u0653ᢤ; ⴣ.\u0653ᢤ; [V6]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ +xn--7nd.xn--vhb294g; Ⴣ.\u0653ᢤ; [V6, V7]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ +󠄈\u0813.싉򄆻Ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻Ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻Ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻Ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +xn--oub.xn--sljz109bpe25dviva; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +󠄈\u0813.싉򄆻ⴤ򂡐; \u0813.싉򄆻ⴤ򂡐; [V7]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ +xn--oub.xn--8nd9522gpe69cviva; \u0813.싉򄆻Ⴤ򂡐; [V7]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ +\uAA2C𑲫≮.⤂; \uAA2C𑲫≮.⤂; [V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂ +\uAA2C𑲫<\u0338.⤂; \uAA2C𑲫≮.⤂; [V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂ +\uAA2C𑲫≮.⤂; ; [V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂ +\uAA2C𑲫<\u0338.⤂; \uAA2C𑲫≮.⤂; [V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂ +xn--gdh1854cn19c.xn--kqi; \uAA2C𑲫≮.⤂; [V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂ +\u0604𐩔≮Ⴢ.Ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔<\u0338Ⴢ.Ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔≮Ⴢ.Ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔<\u0338Ⴢ.Ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔<\u0338ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔≮ⴢ.ⴃ; ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔≮Ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔<\u0338Ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +xn--mfb266l4khr54u.xn--ukj; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔<\u0338ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔≮ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔≮Ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +\u0604𐩔<\u0338Ⴢ.ⴃ; \u0604𐩔≮ⴢ.ⴃ; [B1, V7]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ +xn--mfb416c0jox02t.xn--ukj; \u0604𐩔≮Ⴢ.ⴃ; [B1, V7]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ +xn--mfb416c0jox02t.xn--bnd; \u0604𐩔≮Ⴢ.Ⴃ; [B1, V7]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ +𑁅。-; 𑁅.-; [V3, V6]; xn--210d.-; ; ; # 𑁅.- +xn--210d.-; 𑁅.-; [V3, V6]; xn--210d.-; ; ; # 𑁅.- +\u0DCA򕸽󠧱。饈≠\u0664; \u0DCA򕸽󠧱.饈≠\u0664; [B1, B5, B6, V6, V7]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤ +\u0DCA򕸽󠧱。饈=\u0338\u0664; \u0DCA򕸽󠧱.饈≠\u0664; [B1, B5, B6, V6, V7]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤ +\u0DCA򕸽󠧱。饈≠\u0664; \u0DCA򕸽󠧱.饈≠\u0664; [B1, B5, B6, V6, V7]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤ +\u0DCA򕸽󠧱。饈=\u0338\u0664; \u0DCA򕸽󠧱.饈≠\u0664; [B1, B5, B6, V6, V7]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤ +xn--h1c25913jfwov.xn--dib144ler5f; \u0DCA򕸽󠧱.饈≠\u0664; [B1, B5, B6, V6, V7]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤ +𞥃ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞥃ᠠ⁷。>\u0338邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞥃ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞥃ᠠ7。>\u0338邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞤡ᠠ7。>\u0338邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞤡ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +xn--7-v4j2826w.xn--4-ogoy01bou3i; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞤡ᠠ⁷。>\u0338邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +𞤡ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4 +򠿯ᡳ-𑐻.𐹴𐋫\u0605󑎳; ; [B1, B6, V7]; xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; ; ; # ᡳ-𑐻.𐹴𐋫 +xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; 򠿯ᡳ-𑐻.𐹴𐋫\u0605󑎳; [B1, B6, V7]; xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; ; ; # ᡳ-𑐻.𐹴𐋫 +򠶆\u0845\u0A51.넨-󶧈; ; [B5, B6, V7]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨- +򠶆\u0845\u0A51.넨-󶧈; 򠶆\u0845\u0A51.넨-󶧈; [B5, B6, V7]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨- +xn--3vb26hb6834b.xn----i37ez0957g; 򠶆\u0845\u0A51.넨-󶧈; [B5, B6, V7]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨- +ꡦᡑ\u200D⒈。𐋣-; ꡦᡑ\u200D⒈.𐋣-; [C2, V3, V7]; xn--h8e470bl0d838o.xn----381i; ; xn--h8e863drj7h.xn----381i; [V3, V7] # ꡦᡑ⒈.𐋣- +ꡦᡑ\u200D1.。𐋣-; ꡦᡑ\u200D1..𐋣-; [C2, V3, X4_2]; xn--1-o7j663bdl7m..xn----381i; [C2, V3, A4_2]; xn--1-o7j0610f..xn----381i; [V3, A4_2] # ꡦᡑ1..𐋣- +xn--1-o7j0610f..xn----381i; ꡦᡑ1..𐋣-; [V3, X4_2]; xn--1-o7j0610f..xn----381i; [V3, A4_2]; ; # ꡦᡑ1..𐋣- +xn--1-o7j663bdl7m..xn----381i; ꡦᡑ\u200D1..𐋣-; [C2, V3, X4_2]; xn--1-o7j663bdl7m..xn----381i; [C2, V3, A4_2]; ; # ꡦᡑ1..𐋣- +xn--h8e863drj7h.xn----381i; ꡦᡑ⒈.𐋣-; [V3, V7]; xn--h8e863drj7h.xn----381i; ; ; # ꡦᡑ⒈.𐋣- +xn--h8e470bl0d838o.xn----381i; ꡦᡑ\u200D⒈.𐋣-; [C2, V3, V7]; xn--h8e470bl0d838o.xn----381i; ; ; # ꡦᡑ⒈.𐋣- +Ⴌ。􍼠\uFB69; ⴌ.􍼠\u0679; [B5, B6, V7]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ +Ⴌ。􍼠\u0679; ⴌ.􍼠\u0679; [B5, B6, V7]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ +ⴌ。􍼠\u0679; ⴌ.􍼠\u0679; [B5, B6, V7]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ +xn--3kj.xn--yib19191t; ⴌ.􍼠\u0679; [B5, B6, V7]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ +ⴌ。􍼠\uFB69; ⴌ.􍼠\u0679; [B5, B6, V7]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ +xn--knd.xn--yib19191t; Ⴌ.􍼠\u0679; [B5, B6, V7]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ +𐮁𐭱.\u0F84\u135E-ᳺ; ; [B1, V6]; xn--r19c5a.xn----xjg270ag3m; ; ; # 𐮁𐭱.྄፞-ᳺ +xn--r19c5a.xn----xjg270ag3m; 𐮁𐭱.\u0F84\u135E-ᳺ; [B1, V6]; xn--r19c5a.xn----xjg270ag3m; ; ; # 𐮁𐭱.྄፞-ᳺ +⒈䰹\u200D-。웈; ⒈䰹\u200D-.웈; [C2, V3, V7]; xn----tgnx5rjr6c.xn--kp5b; ; xn----dcp160o.xn--kp5b; [V3, V7] # ⒈䰹-.웈 +⒈䰹\u200D-。웈; ⒈䰹\u200D-.웈; [C2, V3, V7]; xn----tgnx5rjr6c.xn--kp5b; ; xn----dcp160o.xn--kp5b; [V3, V7] # ⒈䰹-.웈 +1.䰹\u200D-。웈; 1.䰹\u200D-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; 1.xn----zw5a.xn--kp5b; [V3] # 1.䰹-.웈 +1.䰹\u200D-。웈; 1.䰹\u200D-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; 1.xn----zw5a.xn--kp5b; [V3] # 1.䰹-.웈 +1.xn----zw5a.xn--kp5b; 1.䰹-.웈; [V3]; 1.xn----zw5a.xn--kp5b; ; ; # 1.䰹-.웈 +1.xn----tgnz80r.xn--kp5b; 1.䰹\u200D-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; ; # 1.䰹-.웈 +xn----dcp160o.xn--kp5b; ⒈䰹-.웈; [V3, V7]; xn----dcp160o.xn--kp5b; ; ; # ⒈䰹-.웈 +xn----tgnx5rjr6c.xn--kp5b; ⒈䰹\u200D-.웈; [C2, V3, V7]; xn----tgnx5rjr6c.xn--kp5b; ; ; # ⒈䰹-.웈 +て。\u200C󠳽\u07F3; て.\u200C󠳽\u07F3; [C1, V7]; xn--m9j.xn--rtb154j9l73w; ; xn--m9j.xn--rtb10784p; [V7] # て.߳ +xn--m9j.xn--rtb10784p; て.󠳽\u07F3; [V7]; xn--m9j.xn--rtb10784p; ; ; # て.߳ +xn--m9j.xn--rtb154j9l73w; て.\u200C󠳽\u07F3; [C1, V7]; xn--m9j.xn--rtb154j9l73w; ; ; # て.߳ +ς。\uA9C0\u06E7; ς.\uA9C0\u06E7; [V6]; xn--3xa.xn--3lb1944f; ; xn--4xa.xn--3lb1944f; # ς.꧀ۧ +ς。\uA9C0\u06E7; ς.\uA9C0\u06E7; [V6]; xn--3xa.xn--3lb1944f; ; xn--4xa.xn--3lb1944f; # ς.꧀ۧ +Σ。\uA9C0\u06E7; σ.\uA9C0\u06E7; [V6]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ +σ。\uA9C0\u06E7; σ.\uA9C0\u06E7; [V6]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ +xn--4xa.xn--3lb1944f; σ.\uA9C0\u06E7; [V6]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ +xn--3xa.xn--3lb1944f; ς.\uA9C0\u06E7; [V6]; xn--3xa.xn--3lb1944f; ; ; # ς.꧀ۧ +Σ。\uA9C0\u06E7; σ.\uA9C0\u06E7; [V6]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ +σ。\uA9C0\u06E7; σ.\uA9C0\u06E7; [V6]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ +\u0BCD󥫅򌉑.ႢႵ; \u0BCD󥫅򌉑.ⴂⴕ; [V6, V7]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ +\u0BCD󥫅򌉑.ⴂⴕ; ; [V6, V7]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ +\u0BCD󥫅򌉑.Ⴂⴕ; \u0BCD󥫅򌉑.ⴂⴕ; [V6, V7]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ +xn--xmc83135idcxza.xn--tkjwb; \u0BCD󥫅򌉑.ⴂⴕ; [V6, V7]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ +xn--xmc83135idcxza.xn--9md086l; \u0BCD󥫅򌉑.Ⴂⴕ; [V6, V7]; xn--xmc83135idcxza.xn--9md086l; ; ; # ்.Ⴂⴕ +xn--xmc83135idcxza.xn--9md2b; \u0BCD󥫅򌉑.ႢႵ; [V6, V7]; xn--xmc83135idcxza.xn--9md2b; ; ; # ்.ႢႵ +\u1C32🄈⾛\u05A6.\u200D򯥤\u07FD; \u1C327,走\u05A6.\u200D򯥤\u07FD; [C2, V6, V7, U1]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; xn--7,-bid991urn3k.xn--1tb13454l; [V6, V7, U1] # ᰲ7,走֦.߽ +\u1C327,走\u05A6.\u200D򯥤\u07FD; ; [C2, V6, V7, U1]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; xn--7,-bid991urn3k.xn--1tb13454l; [V6, V7, U1] # ᰲ7,走֦.߽ +xn--7,-bid991urn3k.xn--1tb13454l; \u1C327,走\u05A6.򯥤\u07FD; [V6, V7, U1]; xn--7,-bid991urn3k.xn--1tb13454l; ; ; # ᰲ7,走֦.߽ +xn--7,-bid991urn3k.xn--1tb334j1197q; \u1C327,走\u05A6.\u200D򯥤\u07FD; [C2, V6, V7, U1]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; ; # ᰲ7,走֦.߽ +xn--xcb756i493fwi5o.xn--1tb13454l; \u1C32🄈走\u05A6.򯥤\u07FD; [V6, V7]; xn--xcb756i493fwi5o.xn--1tb13454l; ; ; # ᰲ🄈走֦.߽ +xn--xcb756i493fwi5o.xn--1tb334j1197q; \u1C32🄈走\u05A6.\u200D򯥤\u07FD; [C2, V6, V7]; xn--xcb756i493fwi5o.xn--1tb334j1197q; ; ; # ᰲ🄈走֦.߽ +ᢗ。Ӏ񝄻; ᢗ.ӏ񝄻; [V7]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ +ᢗ。Ӏ񝄻; ᢗ.ӏ񝄻; [V7]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ +ᢗ。ӏ񝄻; ᢗ.ӏ񝄻; [V7]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ +xn--hbf.xn--s5a83117e; ᢗ.ӏ񝄻; [V7]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ +ᢗ。ӏ񝄻; ᢗ.ӏ񝄻; [V7]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ +xn--hbf.xn--d5a86117e; ᢗ.Ӏ񝄻; [V7]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ +\u0668-。񠏇🝆ᄾ; \u0668-.񠏇🝆ᄾ; [B1, V3, V7]; xn----oqc.xn--qrd1699v327w; ; ; # ٨-.🝆ᄾ +xn----oqc.xn--qrd1699v327w; \u0668-.񠏇🝆ᄾ; [B1, V3, V7]; xn----oqc.xn--qrd1699v327w; ; ; # ٨-.🝆ᄾ +-𐋷𖾑。󠆬; -𐋷𖾑.; [V3]; xn----991iq40y.; [V3, A4_2]; ; # -𐋷𖾑. +xn----991iq40y.; -𐋷𖾑.; [V3]; xn----991iq40y.; [V3, A4_2]; ; # -𐋷𖾑. +\u200C𐹳🐴멈.\uABED񐡼; ; [B1, C1, V6, V7]; xn--0ug6681d406b7bwk.xn--429a8682s; ; xn--422b325mqb6i.xn--429a8682s; [B1, V6, V7] # 𐹳🐴멈.꯭ +\u200C𐹳🐴멈.\uABED񐡼; \u200C𐹳🐴멈.\uABED񐡼; [B1, C1, V6, V7]; xn--0ug6681d406b7bwk.xn--429a8682s; ; xn--422b325mqb6i.xn--429a8682s; [B1, V6, V7] # 𐹳🐴멈.꯭ +xn--422b325mqb6i.xn--429a8682s; 𐹳🐴멈.\uABED񐡼; [B1, V6, V7]; xn--422b325mqb6i.xn--429a8682s; ; ; # 𐹳🐴멈.꯭ +xn--0ug6681d406b7bwk.xn--429a8682s; \u200C𐹳🐴멈.\uABED񐡼; [B1, C1, V6, V7]; xn--0ug6681d406b7bwk.xn--429a8682s; ; ; # 𐹳🐴멈.꯭ +≮.\u0769\u0603; ; [B1, V7]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ +<\u0338.\u0769\u0603; ≮.\u0769\u0603; [B1, V7]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ +xn--gdh.xn--lfb92e; ≮.\u0769\u0603; [B1, V7]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ +𐶭⾆。\u200C𑚶򟱃𞰘; 𐶭舌.\u200C𑚶򟱃𞰘; [B1, B2, B3, C1, V7]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; xn--tc1ao37z.xn--6e2dw557azds2d; [B2, B3, B5, B6, V6, V7] # 舌.𑚶 +𐶭舌。\u200C𑚶򟱃𞰘; 𐶭舌.\u200C𑚶򟱃𞰘; [B1, B2, B3, C1, V7]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; xn--tc1ao37z.xn--6e2dw557azds2d; [B2, B3, B5, B6, V6, V7] # 舌.𑚶 +xn--tc1ao37z.xn--6e2dw557azds2d; 𐶭舌.𑚶򟱃𞰘; [B2, B3, B5, B6, V6, V7]; xn--tc1ao37z.xn--6e2dw557azds2d; ; ; # 舌.𑚶 +xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; 𐶭舌.\u200C𑚶򟱃𞰘; [B1, B2, B3, C1, V7]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; ; # 舌.𑚶 +\u200CჀ-.𝟷ς𞴺ς; \u200Cⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς +\u200CჀ-.1ς𞴺ς; \u200Cⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς +\u200Cⴠ-.1ς𞴺ς; ; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς +\u200CჀ-.1Σ𞴺Σ; \u200Cⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ +\u200Cⴠ-.1σ𞴺σ; ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ +\u200CჀ-.1σ𞴺Σ; \u200Cⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ +xn----2ws.xn--1-0mba52321c; ⴠ-.1σ𞴺σ; [B1, B6, V3]; xn----2ws.xn--1-0mba52321c; ; ; # ⴠ-.1σ𞴺σ +xn----rgn530d.xn--1-0mba52321c; \u200Cⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; ; # ⴠ-.1σ𞴺σ +\u200CჀ-.1ς𞴺Σ; \u200Cⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ +\u200Cⴠ-.1ς𞴺σ; ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ +xn----rgn530d.xn--1-ymbd52321c; \u200Cⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; ; # ⴠ-.1ς𞴺σ +xn----rgn530d.xn--1-ymba92321c; \u200Cⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; ; # ⴠ-.1ς𞴺ς +\u200Cⴠ-.𝟷ς𞴺ς; \u200Cⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς +\u200CჀ-.𝟷Σ𞴺Σ; \u200Cⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ +\u200Cⴠ-.𝟷σ𞴺σ; \u200Cⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ +\u200CჀ-.𝟷σ𞴺Σ; \u200Cⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ +\u200CჀ-.𝟷ς𞴺Σ; \u200Cⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ +\u200Cⴠ-.𝟷ς𞴺σ; \u200Cⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ +xn----z1g.xn--1-0mba52321c; Ⴠ-.1σ𞴺σ; [B1, B6, V3, V7]; xn----z1g.xn--1-0mba52321c; ; ; # Ⴠ-.1σ𞴺σ +xn----z1g168i.xn--1-0mba52321c; \u200CჀ-.1σ𞴺σ; [B1, C1, V3, V7]; xn----z1g168i.xn--1-0mba52321c; ; ; # Ⴠ-.1σ𞴺σ +xn----z1g168i.xn--1-ymbd52321c; \u200CჀ-.1ς𞴺σ; [B1, C1, V3, V7]; xn----z1g168i.xn--1-ymbd52321c; ; ; # Ⴠ-.1ς𞴺σ +xn----z1g168i.xn--1-ymba92321c; \u200CჀ-.1ς𞴺ς; [B1, C1, V3, V7]; xn----z1g168i.xn--1-ymba92321c; ; ; # Ⴠ-.1ς𞴺ς +𑲘󠄒𓑡。𝟪Ⴜ; 𑲘𓑡.8ⴜ; [V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘𓑡.8ⴜ +𑲘󠄒𓑡。8Ⴜ; 𑲘𓑡.8ⴜ; [V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘𓑡.8ⴜ +𑲘󠄒𓑡。8ⴜ; 𑲘𓑡.8ⴜ; [V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘𓑡.8ⴜ +xn--7m3d291b.xn--8-vws; 𑲘𓑡.8ⴜ; [V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘𓑡.8ⴜ +𑲘󠄒𓑡。𝟪ⴜ; 𑲘𓑡.8ⴜ; [V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘𓑡.8ⴜ +xn--7m3d291b.xn--8-s1g; 𑲘𓑡.8Ⴜ; [V6, V7]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘𓑡.8Ⴜ +䪏\u06AB\u07E0\u0941。뭕ᢝ\u17B9; 䪏\u06AB\u07E0\u0941.뭕ᢝ\u17B9; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ +䪏\u06AB\u07E0\u0941。뭕ᢝ\u17B9; 䪏\u06AB\u07E0\u0941.뭕ᢝ\u17B9; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ +䪏\u06AB\u07E0\u0941。뭕ᢝ\u17B9; 䪏\u06AB\u07E0\u0941.뭕ᢝ\u17B9; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ +䪏\u06AB\u07E0\u0941。뭕ᢝ\u17B9; 䪏\u06AB\u07E0\u0941.뭕ᢝ\u17B9; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ +xn--ekb23dj4at01n.xn--43e96bh910b; 䪏\u06AB\u07E0\u0941.뭕ᢝ\u17B9; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ +\u1BAB。🂉󠁰; \u1BAB.🂉󠁰; [V6, V7]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉 +\u1BAB。🂉󠁰; \u1BAB.🂉󠁰; [V6, V7]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉 +xn--zxf.xn--fx7ho0250c; \u1BAB.🂉󠁰; [V6, V7]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉 +󩎃\u0AC4。ς\u200D𐹮𑈵; 󩎃\u0AC4.ς\u200D𐹮𑈵; [B5, C2, V7]; xn--dfc53161q.xn--3xa006lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, V7] # ૄ.ς𐹮𑈵 +󩎃\u0AC4。Σ\u200D𐹮𑈵; 󩎃\u0AC4.σ\u200D𐹮𑈵; [B5, C2, V7]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, V7] # ૄ.σ𐹮𑈵 +󩎃\u0AC4。σ\u200D𐹮𑈵; 󩎃\u0AC4.σ\u200D𐹮𑈵; [B5, C2, V7]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, V7] # ૄ.σ𐹮𑈵 +xn--dfc53161q.xn--4xa8467k5mc; 󩎃\u0AC4.σ𐹮𑈵; [B5, V7]; xn--dfc53161q.xn--4xa8467k5mc; ; ; # ૄ.σ𐹮𑈵 +xn--dfc53161q.xn--4xa895lzo7nsfd; 󩎃\u0AC4.σ\u200D𐹮𑈵; [B5, C2, V7]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; ; # ૄ.σ𐹮𑈵 +xn--dfc53161q.xn--3xa006lzo7nsfd; 󩎃\u0AC4.ς\u200D𐹮𑈵; [B5, C2, V7]; xn--dfc53161q.xn--3xa006lzo7nsfd; ; ; # ૄ.ς𐹮𑈵 +𐫀ᡂ𑜫.𑘿; 𐫀ᡂ𑜫.𑘿; [B1, B2, B3, V6]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿 +𐫀ᡂ𑜫.𑘿; ; [B1, B2, B3, V6]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿 +xn--17e9625js1h.xn--sb2d; 𐫀ᡂ𑜫.𑘿; [B1, B2, B3, V6]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿 +󬚶󸋖򖩰-。\u200C; 󬚶󸋖򖩰-.\u200C; [C1, V3, V7]; xn----7i12hu122k9ire.xn--0ug; ; xn----7i12hu122k9ire.; [V3, V7, A4_2] # -. +xn----7i12hu122k9ire.; 󬚶󸋖򖩰-.; [V3, V7]; xn----7i12hu122k9ire.; [V3, V7, A4_2]; ; # -. +xn----7i12hu122k9ire.xn--0ug; 󬚶󸋖򖩰-.\u200C; [C1, V3, V7]; xn----7i12hu122k9ire.xn--0ug; ; ; # -. +𐹣.\u07C2; 𐹣.\u07C2; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂ +𐹣.\u07C2; ; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂ +xn--bo0d.xn--dsb; 𐹣.\u07C2; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂ +-\u07E1。Ↄ; -\u07E1.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ +-\u07E1。Ↄ; -\u07E1.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ +-\u07E1。ↄ; -\u07E1.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ +xn----8cd.xn--r5g; -\u07E1.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ +-\u07E1。ↄ; -\u07E1.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ +xn----8cd.xn--q5g; -\u07E1.Ↄ; [B1, V3, V7]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ +\u200D-︒󠄄。ß哑\u200C𐵿; \u200D-︒.ß哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--zca670n5f0binyk; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, V3, V7] # -︒.ß哑𐵿 +\u200D-。󠄄。ß哑\u200C𐵿; \u200D-..ß哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--zca670n5f0binyk; [B1, B5, B6, C1, C2, V3, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2] # -..ß哑𐵿 +\u200D-。󠄄。SS哑\u200C𐵟; \u200D-..ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2] # -..ss哑𐵿 +\u200D-。󠄄。ss哑\u200C𐵿; \u200D-..ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2] # -..ss哑𐵿 +\u200D-。󠄄。Ss哑\u200C𐵟; \u200D-..ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2] # -..ss哑𐵿 +-..xn--ss-h46c5711e; -..ss哑𐵿; [B1, B5, B6, V3, X4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2]; ; # -..ss哑𐵿 +xn----tgn..xn--ss-k1ts75zb8ym; \u200D-..ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, A4_2]; ; # -..ss哑𐵿 +xn----tgn..xn--zca670n5f0binyk; \u200D-..ß哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--zca670n5f0binyk; [B1, B5, B6, C1, C2, V3, A4_2]; ; # -..ß哑𐵿 +\u200D-︒󠄄。SS哑\u200C𐵟; \u200D-︒.ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, V3, V7] # -︒.ss哑𐵿 +\u200D-︒󠄄。ss哑\u200C𐵿; \u200D-︒.ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, V3, V7] # -︒.ss哑𐵿 +\u200D-︒󠄄。Ss哑\u200C𐵟; \u200D-︒.ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, V3, V7] # -︒.ss哑𐵿 +xn----o89h.xn--ss-h46c5711e; -︒.ss哑𐵿; [B1, B5, B6, V3, V7]; xn----o89h.xn--ss-h46c5711e; ; ; # -︒.ss哑𐵿 +xn----tgnt341h.xn--ss-k1ts75zb8ym; \u200D-︒.ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; ; # -︒.ss哑𐵿 +xn----tgnt341h.xn--zca670n5f0binyk; \u200D-︒.ß哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--zca670n5f0binyk; ; ; # -︒.ß哑𐵿 +\u200D-。󠄄。SS哑\u200C𐵿; \u200D-..ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2] # -..ss哑𐵿 +\u200D-。󠄄。Ss哑\u200C𐵿; \u200D-..ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V3, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, A4_2] # -..ss哑𐵿 +\u200D-︒󠄄。SS哑\u200C𐵿; \u200D-︒.ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, V3, V7] # -︒.ss哑𐵿 +\u200D-︒󠄄。Ss哑\u200C𐵿; \u200D-︒.ss哑\u200C𐵿; [B1, B5, B6, C1, C2, V7]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, V3, V7] # -︒.ss哑𐵿 +︒.\uFE2F𑑂; ︒.𑑂\uFE2F; [V6, V7]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯ +︒.𑑂\uFE2F; ︒.𑑂\uFE2F; [V6, V7]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯ +。.𑑂\uFE2F; ..𑑂\uFE2F; [V6, X4_2]; ..xn--s96cu30b; [V6, A4_2]; ; # ..𑑂︯ +..xn--s96cu30b; ..𑑂\uFE2F; [V6, X4_2]; ..xn--s96cu30b; [V6, A4_2]; ; # ..𑑂︯ +xn--y86c.xn--s96cu30b; ︒.𑑂\uFE2F; [V6, V7]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯ +\uA92C。\u200D; \uA92C.\u200D; [C2, V6]; xn--zi9a.xn--1ug; ; xn--zi9a.; [V6, A4_2] # ꤬. +xn--zi9a.; \uA92C.; [V6]; xn--zi9a.; [V6, A4_2]; ; # ꤬. +xn--zi9a.xn--1ug; \uA92C.\u200D; [C2, V6]; xn--zi9a.xn--1ug; ; ; # ꤬. +\u200D󠸡。\uFCD7; \u200D󠸡.\u0647\u062C; [B1, C2, V7]; xn--1ug80651l.xn--rgb7c; ; xn--d356e.xn--rgb7c; [B1, V7] # .هج +\u200D󠸡。\u0647\u062C; \u200D󠸡.\u0647\u062C; [B1, C2, V7]; xn--1ug80651l.xn--rgb7c; ; xn--d356e.xn--rgb7c; [B1, V7] # .هج +xn--d356e.xn--rgb7c; 󠸡.\u0647\u062C; [B1, V7]; xn--d356e.xn--rgb7c; ; ; # .هج +xn--1ug80651l.xn--rgb7c; \u200D󠸡.\u0647\u062C; [B1, C2, V7]; xn--1ug80651l.xn--rgb7c; ; ; # .هج +-Ⴄ𝟢\u0663.𑍴ς; -ⴄ0\u0663.𑍴ς; [B1, V3, V6]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς +-Ⴄ0\u0663.𑍴ς; -ⴄ0\u0663.𑍴ς; [B1, V3, V6]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς +-ⴄ0\u0663.𑍴ς; ; [B1, V3, V6]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς +-Ⴄ0\u0663.𑍴Σ; -ⴄ0\u0663.𑍴σ; [B1, V3, V6]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ +-ⴄ0\u0663.𑍴σ; ; [B1, V3, V6]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ +xn---0-iyd8660b.xn--4xa9120l; -ⴄ0\u0663.𑍴σ; [B1, V3, V6]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ +xn---0-iyd8660b.xn--3xa1220l; -ⴄ0\u0663.𑍴ς; [B1, V3, V6]; xn---0-iyd8660b.xn--3xa1220l; ; ; # -ⴄ0٣.𑍴ς +-ⴄ𝟢\u0663.𑍴ς; -ⴄ0\u0663.𑍴ς; [B1, V3, V6]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς +-Ⴄ𝟢\u0663.𑍴Σ; -ⴄ0\u0663.𑍴σ; [B1, V3, V6]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ +-ⴄ𝟢\u0663.𑍴σ; -ⴄ0\u0663.𑍴σ; [B1, V3, V6]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ +xn---0-iyd216h.xn--4xa9120l; -Ⴄ0\u0663.𑍴σ; [B1, V3, V6, V7]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ +xn---0-iyd216h.xn--3xa1220l; -Ⴄ0\u0663.𑍴ς; [B1, V3, V6, V7]; xn---0-iyd216h.xn--3xa1220l; ; ; # -Ⴄ0٣.𑍴ς +󦈄。-; 󦈄.-; [V3, V7]; xn--xm38e.-; ; ; # .- +xn--xm38e.-; 󦈄.-; [V3, V7]; xn--xm38e.-; ; ; # .- +⋠𐋮.򶈮\u0F18ß≯; ⋠𐋮.򶈮\u0F18ß≯; [V7]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯ +≼\u0338𐋮.򶈮\u0F18ß>\u0338; ⋠𐋮.򶈮\u0F18ß≯; [V7]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯ +⋠𐋮.򶈮\u0F18ß≯; ; [V7]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯ +≼\u0338𐋮.򶈮\u0F18ß>\u0338; ⋠𐋮.򶈮\u0F18ß≯; [V7]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯ +≼\u0338𐋮.򶈮\u0F18SS>\u0338; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +⋠𐋮.򶈮\u0F18SS≯; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +⋠𐋮.򶈮\u0F18ss≯; ; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +≼\u0338𐋮.򶈮\u0F18ss>\u0338; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +≼\u0338𐋮.򶈮\u0F18Ss>\u0338; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +⋠𐋮.򶈮\u0F18Ss≯; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +xn--pgh4639f.xn--ss-ifj426nle504a; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +xn--pgh4639f.xn--zca593eo6oc013y; ⋠𐋮.򶈮\u0F18ß≯; [V7]; xn--pgh4639f.xn--zca593eo6oc013y; ; ; # ⋠𐋮.༘ß≯ +≼\u0338𐋮.򶈮\u0F18SS>\u0338; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +⋠𐋮.򶈮\u0F18SS≯; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +⋠𐋮.򶈮\u0F18ss≯; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +≼\u0338𐋮.򶈮\u0F18ss>\u0338; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +≼\u0338𐋮.򶈮\u0F18Ss>\u0338; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +⋠𐋮.򶈮\u0F18Ss≯; ⋠𐋮.򶈮\u0F18ss≯; [V7]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯ +1𐋸\u0664。󠢮\uFBA4񷝊; 1𐋸\u0664.󠢮\u06C0񷝊; [B1, V7]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ +1𐋸\u0664。󠢮\u06C0񷝊; 1𐋸\u0664.󠢮\u06C0񷝊; [B1, V7]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ +1𐋸\u0664。󠢮\u06D5\u0654񷝊; 1𐋸\u0664.󠢮\u06C0񷝊; [B1, V7]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ +xn--1-hqc3905q.xn--zkb83268gqee4a; 1𐋸\u0664.󠢮\u06C0񷝊; [B1, V7]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ +儭-。𐹴Ⴢ񥳠\u200C; 儭-.𐹴ⴢ񥳠\u200C; [B1, B6, C1, V3, V7]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, V3, V7] # 儭-.𐹴ⴢ +儭-。𐹴Ⴢ񥳠\u200C; 儭-.𐹴ⴢ񥳠\u200C; [B1, B6, C1, V3, V7]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, V3, V7] # 儭-.𐹴ⴢ +儭-。𐹴ⴢ񥳠\u200C; 儭-.𐹴ⴢ񥳠\u200C; [B1, B6, C1, V3, V7]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, V3, V7] # 儭-.𐹴ⴢ +xn----gz7a.xn--qlj9223eywx0b; 儭-.𐹴ⴢ񥳠; [B1, B6, V3, V7]; xn----gz7a.xn--qlj9223eywx0b; ; ; # 儭-.𐹴ⴢ +xn----gz7a.xn--0ug472cfq0pus98b; 儭-.𐹴ⴢ񥳠\u200C; [B1, B6, C1, V3, V7]; xn----gz7a.xn--0ug472cfq0pus98b; ; ; # 儭-.𐹴ⴢ +儭-。𐹴ⴢ񥳠\u200C; 儭-.𐹴ⴢ񥳠\u200C; [B1, B6, C1, V3, V7]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, V3, V7] # 儭-.𐹴ⴢ +xn----gz7a.xn--6nd5001kyw98a; 儭-.𐹴Ⴢ񥳠; [B1, B6, V3, V7]; xn----gz7a.xn--6nd5001kyw98a; ; ; # 儭-.𐹴Ⴢ +xn----gz7a.xn--6nd249ejl4pusr7b; 儭-.𐹴Ⴢ񥳠\u200C; [B1, B6, C1, V3, V7]; xn----gz7a.xn--6nd249ejl4pusr7b; ; ; # 儭-.𐹴Ⴢ +𝟺𐋷\u06B9.𞤭򿍡; 4𐋷\u06B9.𞤭򿍡; [B1, B2, B3, V7]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭 +4𐋷\u06B9.𞤭򿍡; ; [B1, B2, B3, V7]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭 +4𐋷\u06B9.𞤋򿍡; 4𐋷\u06B9.𞤭򿍡; [B1, B2, B3, V7]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭 +xn--4-cvc5384q.xn--le6hi7322b; 4𐋷\u06B9.𞤭򿍡; [B1, B2, B3, V7]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭 +𝟺𐋷\u06B9.𞤋򿍡; 4𐋷\u06B9.𞤭򿍡; [B1, B2, B3, V7]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭 +≯-ꡋ𑲣.⒈𐹭; ; [B1, V7]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭 +>\u0338-ꡋ𑲣.⒈𐹭; ≯-ꡋ𑲣.⒈𐹭; [B1, V7]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭 +≯-ꡋ𑲣.1.𐹭; ; [B1]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭 +>\u0338-ꡋ𑲣.1.𐹭; ≯-ꡋ𑲣.1.𐹭; [B1]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭 +xn----ogox061d5i8d.1.xn--lo0d; ≯-ꡋ𑲣.1.𐹭; [B1]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭 +xn----ogox061d5i8d.xn--tsh0666f; ≯-ꡋ𑲣.⒈𐹭; [B1, V7]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭 +\u0330.󰜱蚀; \u0330.󰜱蚀; [V6, V7]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀 +\u0330.󰜱蚀; ; [V6, V7]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀 +xn--xta.xn--e91aw9417e; \u0330.󰜱蚀; [V6, V7]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀 +\uFB39Ⴘ.𞡼𑇀ß\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ß\u20D7; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗ +\u05D9\u05BCႸ.𞡼𑇀ß\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ß\u20D7; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗ +\u05D9\u05BCⴘ.𞡼𑇀ß\u20D7; ; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗ +\u05D9\u05BCႸ.𞡼𑇀SS\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +\u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; ; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +xn--kdb1d278n.xn--ss-yju5690ken9h; \u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +xn--kdb1d278n.xn--zca284nhg9nrrxg; \u05D9\u05BCⴘ.𞡼𑇀ß\u20D7; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; ; # יּⴘ.𞡼𑇀ß⃗ +\uFB39ⴘ.𞡼𑇀ß\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ß\u20D7; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗ +\uFB39Ⴘ.𞡼𑇀SS\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +\uFB39ⴘ.𞡼𑇀ss\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +xn--kdb1d867b.xn--ss-yju5690ken9h; \u05D9\u05BCႸ.𞡼𑇀ss\u20D7; [B2, B3, V7]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗ +xn--kdb1d867b.xn--zca284nhg9nrrxg; \u05D9\u05BCႸ.𞡼𑇀ß\u20D7; [B2, B3, V7]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; ; # יּႸ.𞡼𑇀ß⃗ +\u05D9\u05BCႸ.𞡼𑇀ss\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +\uFB39Ⴘ.𞡼𑇀ss\u20D7; \u05D9\u05BCⴘ.𞡼𑇀ss\u20D7; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗ +\u1BA3𐹰򁱓。凬; \u1BA3𐹰򁱓.凬; [B1, V6, V7]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬 +\u1BA3𐹰򁱓。凬; \u1BA3𐹰򁱓.凬; [B1, V6, V7]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬 +xn--rxfz314ilg20c.xn--t9q; \u1BA3𐹰򁱓.凬; [B1, V6, V7]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬 +🢟🄈\u200Dꡎ。\u0F84; 🢟7,\u200Dꡎ.\u0F84; [C2, V6, U1]; xn--7,-n1t0654eqo3o.xn--3ed; ; xn--7,-gh9hg322i.xn--3ed; [V6, U1] # 🢟7,ꡎ.྄ +🢟7,\u200Dꡎ。\u0F84; 🢟7,\u200Dꡎ.\u0F84; [C2, V6, U1]; xn--7,-n1t0654eqo3o.xn--3ed; ; xn--7,-gh9hg322i.xn--3ed; [V6, U1] # 🢟7,ꡎ.྄ +xn--7,-gh9hg322i.xn--3ed; 🢟7,ꡎ.\u0F84; [V6, U1]; xn--7,-gh9hg322i.xn--3ed; ; ; # 🢟7,ꡎ.྄ +xn--7,-n1t0654eqo3o.xn--3ed; 🢟7,\u200Dꡎ.\u0F84; [C2, V6, U1]; xn--7,-n1t0654eqo3o.xn--3ed; ; ; # 🢟7,ꡎ.྄ +xn--nc9aq743ds0e.xn--3ed; 🢟🄈ꡎ.\u0F84; [V6, V7]; xn--nc9aq743ds0e.xn--3ed; ; ; # 🢟🄈ꡎ.྄ +xn--1ug4874cfd0kbmg.xn--3ed; 🢟🄈\u200Dꡎ.\u0F84; [C2, V6, V7]; xn--1ug4874cfd0kbmg.xn--3ed; ; ; # 🢟🄈ꡎ.྄ +ꡔ。\u1039ᢇ; ꡔ.\u1039ᢇ; [V6]; xn--tc9a.xn--9jd663b; ; ; # ꡔ.္ᢇ +xn--tc9a.xn--9jd663b; ꡔ.\u1039ᢇ; [V6]; xn--tc9a.xn--9jd663b; ; ; # ꡔ.္ᢇ +\u20EB≮.𝨖; ; [V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖 +\u20EB<\u0338.𝨖; \u20EB≮.𝨖; [V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖 +xn--e1g71d.xn--772h; \u20EB≮.𝨖; [V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖 +Ⴢ≯褦.ᠪ\u07EAႾ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ>\u0338褦.ᠪ\u07EAႾ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ≯褦.ᠪ\u07EAႾ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ>\u0338褦.ᠪ\u07EAႾ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +ⴢ>\u0338褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +ⴢ≯褦.ᠪ\u07EAⴞ\u0767; ; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ≯褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ>\u0338褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +xn--hdh433bev8e.xn--rpb5x392bcyt; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +ⴢ>\u0338褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +ⴢ≯褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ≯褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +Ⴢ>\u0338褦.ᠪ\u07EAⴞ\u0767; ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ +xn--6nd461g478e.xn--rpb5x392bcyt; Ⴢ≯褦.ᠪ\u07EAⴞ\u0767; [B5, B6, V7]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ +xn--6nd461g478e.xn--rpb5x49td2h; Ⴢ≯褦.ᠪ\u07EAႾ\u0767; [B5, B6, V7]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ +򊉆󠆒\u200C\uA953。𞤙\u067Bꡘ; 򊉆\u200C\uA953.𞤻\u067Bꡘ; [B2, B3, C1, V7]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; xn--3j9al6189a.xn--0ib8893fegvj; [B2, B3, V7] # ꥓.𞤻ٻꡘ +򊉆󠆒\u200C\uA953。𞤻\u067Bꡘ; 򊉆\u200C\uA953.𞤻\u067Bꡘ; [B2, B3, C1, V7]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; xn--3j9al6189a.xn--0ib8893fegvj; [B2, B3, V7] # ꥓.𞤻ٻꡘ +xn--3j9al6189a.xn--0ib8893fegvj; 򊉆\uA953.𞤻\u067Bꡘ; [B2, B3, V7]; xn--3j9al6189a.xn--0ib8893fegvj; ; ; # ꥓.𞤻ٻꡘ +xn--0ug8815chtz0e.xn--0ib8893fegvj; 򊉆\u200C\uA953.𞤻\u067Bꡘ; [B2, B3, C1, V7]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; ; # ꥓.𞤻ٻꡘ +\u200C.≯; ; [C1]; xn--0ug.xn--hdh; ; .xn--hdh; [A4_2] # .≯ +\u200C.>\u0338; \u200C.≯; [C1]; xn--0ug.xn--hdh; ; .xn--hdh; [A4_2] # .≯ +.xn--hdh; .≯; [X4_2]; .xn--hdh; [A4_2]; ; # .≯ +xn--0ug.xn--hdh; \u200C.≯; [C1]; xn--0ug.xn--hdh; ; ; # .≯ +𰅧񣩠-.\uABED-悜; 𰅧񣩠-.\uABED-悜; [V3, V6, V7]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜 +𰅧񣩠-.\uABED-悜; ; [V3, V6, V7]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜 +xn----7m53aj640l.xn----8f4br83t; 𰅧񣩠-.\uABED-悜; [V3, V6, V7]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜 +ᡉ𶓧⬞ᢜ.-\u200D𞣑\u202E; ; [C2, V3, V7]; xn--87e0ol04cdl39e.xn----ugn5e3763s; ; xn--87e0ol04cdl39e.xn----qinu247r; [V3, V7] # ᡉ⬞ᢜ.-𞣑 +xn--87e0ol04cdl39e.xn----qinu247r; ᡉ𶓧⬞ᢜ.-𞣑\u202E; [V3, V7]; xn--87e0ol04cdl39e.xn----qinu247r; ; ; # ᡉ⬞ᢜ.-𞣑 +xn--87e0ol04cdl39e.xn----ugn5e3763s; ᡉ𶓧⬞ᢜ.-\u200D𞣑\u202E; [C2, V3, V7]; xn--87e0ol04cdl39e.xn----ugn5e3763s; ; ; # ᡉ⬞ᢜ.-𞣑 +⒐\u200C衃Ⴝ.\u0682Ⴔ; ⒐\u200C衃ⴝ.\u0682ⴔ; [B1, B2, B3, C1, V7]; xn--0ugx0px1izu2h.xn--7ib268q; ; xn--1shy52abz3f.xn--7ib268q; [B1, B2, B3, V7] # ⒐衃ⴝ.ڂⴔ +9.\u200C衃Ⴝ.\u0682Ⴔ; 9.\u200C衃ⴝ.\u0682ⴔ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; 9.xn--llj1920a.xn--7ib268q; [B1, B2, B3] # 9.衃ⴝ.ڂⴔ +9.\u200C衃ⴝ.\u0682ⴔ; ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; 9.xn--llj1920a.xn--7ib268q; [B1, B2, B3] # 9.衃ⴝ.ڂⴔ +9.\u200C衃Ⴝ.\u0682ⴔ; 9.\u200C衃ⴝ.\u0682ⴔ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; 9.xn--llj1920a.xn--7ib268q; [B1, B2, B3] # 9.衃ⴝ.ڂⴔ +9.xn--llj1920a.xn--7ib268q; 9.衃ⴝ.\u0682ⴔ; [B1, B2, B3]; 9.xn--llj1920a.xn--7ib268q; ; ; # 9.衃ⴝ.ڂⴔ +9.xn--0ug862cbm5e.xn--7ib268q; 9.\u200C衃ⴝ.\u0682ⴔ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; ; # 9.衃ⴝ.ڂⴔ +⒐\u200C衃ⴝ.\u0682ⴔ; ; [B1, B2, B3, C1, V7]; xn--0ugx0px1izu2h.xn--7ib268q; ; xn--1shy52abz3f.xn--7ib268q; [B1, B2, B3, V7] # ⒐衃ⴝ.ڂⴔ +⒐\u200C衃Ⴝ.\u0682ⴔ; ⒐\u200C衃ⴝ.\u0682ⴔ; [B1, B2, B3, C1, V7]; xn--0ugx0px1izu2h.xn--7ib268q; ; xn--1shy52abz3f.xn--7ib268q; [B1, B2, B3, V7] # ⒐衃ⴝ.ڂⴔ +xn--1shy52abz3f.xn--7ib268q; ⒐衃ⴝ.\u0682ⴔ; [B1, B2, B3, V7]; xn--1shy52abz3f.xn--7ib268q; ; ; # ⒐衃ⴝ.ڂⴔ +xn--0ugx0px1izu2h.xn--7ib268q; ⒐\u200C衃ⴝ.\u0682ⴔ; [B1, B2, B3, C1, V7]; xn--0ugx0px1izu2h.xn--7ib268q; ; ; # ⒐衃ⴝ.ڂⴔ +9.xn--1nd9032d.xn--7ib268q; 9.衃Ⴝ.\u0682ⴔ; [B1, B2, B3, V7]; 9.xn--1nd9032d.xn--7ib268q; ; ; # 9.衃Ⴝ.ڂⴔ +9.xn--1nd159e1y2f.xn--7ib268q; 9.\u200C衃Ⴝ.\u0682ⴔ; [B1, B2, B3, C1, V7]; 9.xn--1nd159e1y2f.xn--7ib268q; ; ; # 9.衃Ⴝ.ڂⴔ +9.xn--1nd9032d.xn--7ib433c; 9.衃Ⴝ.\u0682Ⴔ; [B1, B2, B3, V7]; 9.xn--1nd9032d.xn--7ib433c; ; ; # 9.衃Ⴝ.ڂႴ +9.xn--1nd159e1y2f.xn--7ib433c; 9.\u200C衃Ⴝ.\u0682Ⴔ; [B1, B2, B3, C1, V7]; 9.xn--1nd159e1y2f.xn--7ib433c; ; ; # 9.衃Ⴝ.ڂႴ +xn--1nd362hy16e.xn--7ib268q; ⒐衃Ⴝ.\u0682ⴔ; [B1, B2, B3, V7]; xn--1nd362hy16e.xn--7ib268q; ; ; # ⒐衃Ⴝ.ڂⴔ +xn--1nd159ecmd785k.xn--7ib268q; ⒐\u200C衃Ⴝ.\u0682ⴔ; [B1, B2, B3, C1, V7]; xn--1nd159ecmd785k.xn--7ib268q; ; ; # ⒐衃Ⴝ.ڂⴔ +xn--1nd362hy16e.xn--7ib433c; ⒐衃Ⴝ.\u0682Ⴔ; [B1, B2, B3, V7]; xn--1nd362hy16e.xn--7ib433c; ; ; # ⒐衃Ⴝ.ڂႴ +xn--1nd159ecmd785k.xn--7ib433c; ⒐\u200C衃Ⴝ.\u0682Ⴔ; [B1, B2, B3, C1, V7]; xn--1nd159ecmd785k.xn--7ib433c; ; ; # ⒐衃Ⴝ.ڂႴ +\u07E1\u200C。--⸬; \u07E1\u200C.--⸬; [B1, B3, C1, V3]; xn--8sb884j.xn-----iw2a; ; xn--8sb.xn-----iw2a; [B1, V3] # ߡ.--⸬ +xn--8sb.xn-----iw2a; \u07E1.--⸬; [B1, V3]; xn--8sb.xn-----iw2a; ; ; # ߡ.--⸬ +xn--8sb884j.xn-----iw2a; \u07E1\u200C.--⸬; [B1, B3, C1, V3]; xn--8sb884j.xn-----iw2a; ; ; # ߡ.--⸬ +𞥓.\u0718; 𞥓.\u0718; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ +𞥓.\u0718; ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ +xn--of6h.xn--inb; 𞥓.\u0718; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ +󠄽-.-\u0DCA; -.-\u0DCA; [V3]; -.xn----ptf; ; ; # -.-් +󠄽-.-\u0DCA; -.-\u0DCA; [V3]; -.xn----ptf; ; ; # -.-් +-.xn----ptf; -.-\u0DCA; [V3]; -.xn----ptf; ; ; # -.-් +󠇝\u075B-.\u1927; \u075B-.\u1927; [B1, B3, V3, V6]; xn----k4c.xn--lff; ; ; # ݛ-.ᤧ +xn----k4c.xn--lff; \u075B-.\u1927; [B1, B3, V3, V6]; xn----k4c.xn--lff; ; ; # ݛ-.ᤧ +𞤴󠆹⦉𐹺.\uA806⒌󘤸; 𞤴⦉𐹺.\uA806⒌󘤸; [B1, V6, V7]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌ +𞤴󠆹⦉𐹺.\uA8065.󘤸; 𞤴⦉𐹺.\uA8065.󘤸; [B1, V6, V7]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5. +𞤒󠆹⦉𐹺.\uA8065.󘤸; 𞤴⦉𐹺.\uA8065.󘤸; [B1, V6, V7]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5. +xn--fuix729epewf.xn--5-w93e.xn--7b83e; 𞤴⦉𐹺.\uA8065.󘤸; [B1, V6, V7]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5. +𞤒󠆹⦉𐹺.\uA806⒌󘤸; 𞤴⦉𐹺.\uA806⒌󘤸; [B1, V6, V7]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌ +xn--fuix729epewf.xn--xsh5029b6e77i; 𞤴⦉𐹺.\uA806⒌󘤸; [B1, V6, V7]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌ +󠄸₀。𑖿\u200C𐦂\u200D; 0.𑖿\u200C𐦂\u200D; [B1, C2, V6]; 0.xn--0ugc8040p9hk; ; 0.xn--mn9cz2s; [B1, V6] # 0.𑖿𐦂 +󠄸0。𑖿\u200C𐦂\u200D; 0.𑖿\u200C𐦂\u200D; [B1, C2, V6]; 0.xn--0ugc8040p9hk; ; 0.xn--mn9cz2s; [B1, V6] # 0.𑖿𐦂 +0.xn--mn9cz2s; 0.𑖿𐦂; [B1, V6]; 0.xn--mn9cz2s; ; ; # 0.𑖿𐦂 +0.xn--0ugc8040p9hk; 0.𑖿\u200C𐦂\u200D; [B1, C2, V6]; 0.xn--0ugc8040p9hk; ; ; # 0.𑖿𐦂 +Ⴚ𐋸󠄄。𝟝ퟶ\u103A; ⴚ𐋸.5ퟶ\u103A; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +Ⴚ𐋸󠄄。5ퟶ\u103A; ⴚ𐋸.5ퟶ\u103A; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +ⴚ𐋸󠄄。5ퟶ\u103A; ⴚ𐋸.5ퟶ\u103A; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +xn--ilj2659d.xn--5-dug9054m; ⴚ𐋸.5ퟶ\u103A; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +ⴚ𐋸.5ퟶ\u103A; ; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +Ⴚ𐋸.5ퟶ\u103A; ⴚ𐋸.5ퟶ\u103A; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +ⴚ𐋸󠄄。𝟝ퟶ\u103A; ⴚ𐋸.5ퟶ\u103A; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ် +xn--ynd2415j.xn--5-dug9054m; Ⴚ𐋸.5ퟶ\u103A; [V7]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ် +\u200D-ᠹ﹪.\u1DE1\u1922; \u200D-ᠹ%.\u1DE1\u1922; [C2, V6, U1]; xn---%-u4oy48b.xn--gff52t; ; xn---%-u4o.xn--gff52t; [V3, V6, U1] # -ᠹ%.ᷡᤢ +\u200D-ᠹ%.\u1DE1\u1922; ; [C2, V6, U1]; xn---%-u4oy48b.xn--gff52t; ; xn---%-u4o.xn--gff52t; [V3, V6, U1] # -ᠹ%.ᷡᤢ +xn---%-u4o.xn--gff52t; -ᠹ%.\u1DE1\u1922; [V3, V6, U1]; xn---%-u4o.xn--gff52t; ; ; # -ᠹ%.ᷡᤢ +xn---%-u4oy48b.xn--gff52t; \u200D-ᠹ%.\u1DE1\u1922; [C2, V6, U1]; xn---%-u4oy48b.xn--gff52t; ; ; # -ᠹ%.ᷡᤢ +xn----c6jx047j.xn--gff52t; -ᠹ﹪.\u1DE1\u1922; [V3, V6, V7]; xn----c6jx047j.xn--gff52t; ; ; # -ᠹ﹪.ᷡᤢ +xn----c6j614b1z4v.xn--gff52t; \u200D-ᠹ﹪.\u1DE1\u1922; [C2, V6, V7]; xn----c6j614b1z4v.xn--gff52t; ; ; # -ᠹ﹪.ᷡᤢ +≠.ᠿ; ; ; xn--1ch.xn--y7e; ; ; # ≠.ᠿ +=\u0338.ᠿ; ≠.ᠿ; ; xn--1ch.xn--y7e; ; ; # ≠.ᠿ +xn--1ch.xn--y7e; ≠.ᠿ; ; xn--1ch.xn--y7e; ; ; # ≠.ᠿ +\u0723\u05A3。㌪; \u0723\u05A3.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ +\u0723\u05A3。ハイツ; \u0723\u05A3.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ +xn--ucb18e.xn--eck4c5a; \u0723\u05A3.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ +\u0723\u05A3.ハイツ; ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ +𞷥󠆀≮.\u2D7F-; 𞷥≮.\u2D7F-; [B1, B3, V3, V6, V7]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿- +𞷥󠆀<\u0338.\u2D7F-; 𞷥≮.\u2D7F-; [B1, B3, V3, V6, V7]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿- +xn--gdhx802p.xn----i2s; 𞷥≮.\u2D7F-; [B1, B3, V3, V6, V7]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿- +₆榎򦖎\u0D4D。𞤅\u06ED\uFC5A󠮨; 6榎򦖎\u0D4D.𞤧\u06ED\u064A\u064A󠮨; [B1, B3, V7]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي +6榎򦖎\u0D4D。𞤅\u06ED\u064A\u064A󠮨; 6榎򦖎\u0D4D.𞤧\u06ED\u064A\u064A󠮨; [B1, B3, V7]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي +6榎򦖎\u0D4D。𞤧\u06ED\u064A\u064A󠮨; 6榎򦖎\u0D4D.𞤧\u06ED\u064A\u064A󠮨; [B1, B3, V7]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي +xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; 6榎򦖎\u0D4D.𞤧\u06ED\u064A\u064A󠮨; [B1, B3, V7]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي +₆榎򦖎\u0D4D。𞤧\u06ED\uFC5A󠮨; 6榎򦖎\u0D4D.𞤧\u06ED\u064A\u064A󠮨; [B1, B3, V7]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي +𣩫.򌑲; 𣩫.򌑲; [V7]; xn--td3j.xn--4628b; ; ; # 𣩫. +𣩫.򌑲; ; [V7]; xn--td3j.xn--4628b; ; ; # 𣩫. +xn--td3j.xn--4628b; 𣩫.򌑲; [V7]; xn--td3j.xn--4628b; ; ; # 𣩫. +\u200D︒。\u06B9\u200C; \u200D︒.\u06B9\u200C; [B1, B3, C1, C2, V7]; xn--1ug2658f.xn--skb080k; ; xn--y86c.xn--skb; [B1, V7] # ︒.ڹ +xn--y86c.xn--skb; ︒.\u06B9; [B1, V7]; xn--y86c.xn--skb; ; ; # ︒.ڹ +xn--1ug2658f.xn--skb080k; \u200D︒.\u06B9\u200C; [B1, B3, C1, C2, V7]; xn--1ug2658f.xn--skb080k; ; ; # ︒.ڹ +xn--skb; \u06B9; ; xn--skb; ; ; # ڹ +\u06B9; ; ; xn--skb; ; ; # ڹ +𐹦\u200C𐹶。\u206D; 𐹦\u200C𐹶.; [B1, C1]; xn--0ug4994goba.; [B1, C1, A4_2]; xn--eo0d6a.; [B1, A4_2] # 𐹦𐹶. +xn--eo0d6a.; 𐹦𐹶.; [B1]; xn--eo0d6a.; [B1, A4_2]; ; # 𐹦𐹶. +xn--0ug4994goba.; 𐹦\u200C𐹶.; [B1, C1]; xn--0ug4994goba.; [B1, C1, A4_2]; ; # 𐹦𐹶. +xn--eo0d6a.xn--sxg; 𐹦𐹶.\u206D; [B1, V7]; xn--eo0d6a.xn--sxg; ; ; # 𐹦𐹶. +xn--0ug4994goba.xn--sxg; 𐹦\u200C𐹶.\u206D; [B1, C1, V7]; xn--0ug4994goba.xn--sxg; ; ; # 𐹦𐹶. +\u0C4D𝨾\u05A9𝟭。-𑜨; \u0C4D𝨾\u05A91.-𑜨; [V3, V6]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨 +\u0C4D𝨾\u05A91。-𑜨; \u0C4D𝨾\u05A91.-𑜨; [V3, V6]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨 +xn--1-rfc312cdp45c.xn----nq0j; \u0C4D𝨾\u05A91.-𑜨; [V3, V6]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨 +򣿈。뙏; 򣿈.뙏; [V7]; xn--ph26c.xn--281b; ; ; # .뙏 +򣿈。뙏; 򣿈.뙏; [V7]; xn--ph26c.xn--281b; ; ; # .뙏 +xn--ph26c.xn--281b; 򣿈.뙏; [V7]; xn--ph26c.xn--281b; ; ; # .뙏 +񕨚󠄌󑽀ᡀ.\u08B6; 񕨚󑽀ᡀ.\u08B6; [V7]; xn--z7e98100evc01b.xn--czb; ; ; # ᡀ.ࢶ +xn--z7e98100evc01b.xn--czb; 񕨚󑽀ᡀ.\u08B6; [V7]; xn--z7e98100evc01b.xn--czb; ; ; # ᡀ.ࢶ +\u200D。񅁛; \u200D.񅁛; [C2, V7]; xn--1ug.xn--6x4u; ; .xn--6x4u; [V7, A4_2] # . +\u200D。񅁛; \u200D.񅁛; [C2, V7]; xn--1ug.xn--6x4u; ; .xn--6x4u; [V7, A4_2] # . +.xn--6x4u; .񅁛; [V7, X4_2]; .xn--6x4u; [V7, A4_2]; ; # . +xn--1ug.xn--6x4u; \u200D.񅁛; [C2, V7]; xn--1ug.xn--6x4u; ; ; # . +\u084B皥.-; \u084B皥.-; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.- +\u084B皥.-; ; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.- +xn--9vb4167c.-; \u084B皥.-; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.- +𐣸\u0315𐮇.⒈ꡦ; 𐣸\u0315𐮇.⒈ꡦ; [B1, V7]; xn--5sa9915kgvb.xn--tshw539b; ; ; # ̕𐮇.⒈ꡦ +𐣸\u0315𐮇.1.ꡦ; ; [B1, V7]; xn--5sa9915kgvb.1.xn--cd9a; ; ; # ̕𐮇.1.ꡦ +xn--5sa9915kgvb.1.xn--cd9a; 𐣸\u0315𐮇.1.ꡦ; [B1, V7]; xn--5sa9915kgvb.1.xn--cd9a; ; ; # ̕𐮇.1.ꡦ +xn--5sa9915kgvb.xn--tshw539b; 𐣸\u0315𐮇.⒈ꡦ; [B1, V7]; xn--5sa9915kgvb.xn--tshw539b; ; ; # ̕𐮇.⒈ꡦ +Ⴛ\u200C\u05A2\u200D。\uFFA0ā𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\uFFA0a\u0304𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\u1160ā𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\u1160a\u0304𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +ⴛ\u200C\u05A2\u200D。\u1160a\u0304𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +ⴛ\u200C\u05A2\u200D。\u1160ā𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\u1160Ā𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\u1160A\u0304𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +xn--tcb323r.xn--yda4409k; ⴛ\u05A2.ā𐹦; [B5, B6]; xn--tcb323r.xn--yda4409k; ; ; # ⴛ֢.ā𐹦 +xn--tcb736kea974k.xn--yda4409k; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; ; # ⴛ֢.ā𐹦 +ⴛ\u200C\u05A2\u200D。\uFFA0a\u0304𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +ⴛ\u200C\u05A2\u200D。\uFFA0ā𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\uFFA0Ā𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +Ⴛ\u200C\u05A2\u200D。\uFFA0A\u0304𐹦; ⴛ\u200C\u05A2\u200D.ā𐹦; [B5, B6, C1, C2]; xn--tcb736kea974k.xn--yda4409k; ; xn--tcb323r.xn--yda4409k; [B5, B6] # ⴛ֢.ā𐹦 +xn--tcb597c.xn--yda594fdn5q; Ⴛ\u05A2.\u1160ā𐹦; [B5, B6, V7]; xn--tcb597c.xn--yda594fdn5q; ; ; # Ⴛ֢.ā𐹦 +xn--tcb597cdmmfa.xn--yda594fdn5q; Ⴛ\u200C\u05A2\u200D.\u1160ā𐹦; [B5, B6, C1, C2, V7]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; ; # Ⴛ֢.ā𐹦 +xn--tcb323r.xn--yda594fdn5q; ⴛ\u05A2.\u1160ā𐹦; [B5, B6, V7]; xn--tcb323r.xn--yda594fdn5q; ; ; # ⴛ֢.ā𐹦 +xn--tcb736kea974k.xn--yda594fdn5q; ⴛ\u200C\u05A2\u200D.\u1160ā𐹦; [B5, B6, C1, C2, V7]; xn--tcb736kea974k.xn--yda594fdn5q; ; ; # ⴛ֢.ā𐹦 +xn--tcb597c.xn--yda9741khjj; Ⴛ\u05A2.\uFFA0ā𐹦; [B5, B6, V7]; xn--tcb597c.xn--yda9741khjj; ; ; # Ⴛ֢.ā𐹦 +xn--tcb597cdmmfa.xn--yda9741khjj; Ⴛ\u200C\u05A2\u200D.\uFFA0ā𐹦; [B5, B6, C1, C2, V7]; xn--tcb597cdmmfa.xn--yda9741khjj; ; ; # Ⴛ֢.ā𐹦 +xn--tcb323r.xn--yda9741khjj; ⴛ\u05A2.\uFFA0ā𐹦; [B5, B6, V7]; xn--tcb323r.xn--yda9741khjj; ; ; # ⴛ֢.ā𐹦 +xn--tcb736kea974k.xn--yda9741khjj; ⴛ\u200C\u05A2\u200D.\uFFA0ā𐹦; [B5, B6, C1, C2, V7]; xn--tcb736kea974k.xn--yda9741khjj; ; ; # ⴛ֢.ā𐹦 +\uFFF9\u200C。曳⾑𐋰≯; \uFFF9\u200C.曳襾𐋰≯; [C1, V7]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [V7] # .曳襾𐋰≯ +\uFFF9\u200C。曳⾑𐋰>\u0338; \uFFF9\u200C.曳襾𐋰≯; [C1, V7]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [V7] # .曳襾𐋰≯ +\uFFF9\u200C。曳襾𐋰≯; \uFFF9\u200C.曳襾𐋰≯; [C1, V7]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [V7] # .曳襾𐋰≯ +\uFFF9\u200C。曳襾𐋰>\u0338; \uFFF9\u200C.曳襾𐋰≯; [C1, V7]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [V7] # .曳襾𐋰≯ +xn--vn7c.xn--hdh501y8wvfs5h; \uFFF9.曳襾𐋰≯; [V7]; xn--vn7c.xn--hdh501y8wvfs5h; ; ; # .曳襾𐋰≯ +xn--0ug2139f.xn--hdh501y8wvfs5h; \uFFF9\u200C.曳襾𐋰≯; [C1, V7]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; ; # .曳襾𐋰≯ +≯⒈。ß; ≯⒈.ß; [V7]; xn--hdh84f.xn--zca; ; xn--hdh84f.ss; # ≯⒈.ß +>\u0338⒈。ß; ≯⒈.ß; [V7]; xn--hdh84f.xn--zca; ; xn--hdh84f.ss; # ≯⒈.ß +≯1.。ß; ≯1..ß; [X4_2]; xn--1-ogo..xn--zca; [A4_2]; xn--1-ogo..ss; # ≯1..ß +>\u03381.。ß; ≯1..ß; [X4_2]; xn--1-ogo..xn--zca; [A4_2]; xn--1-ogo..ss; # ≯1..ß +>\u03381.。SS; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +≯1.。SS; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +≯1.。ss; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +>\u03381.。ss; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +>\u03381.。Ss; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +≯1.。Ss; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +xn--1-ogo..ss; ≯1..ss; [X4_2]; xn--1-ogo..ss; [A4_2]; ; # ≯1..ss +xn--1-ogo..xn--zca; ≯1..ß; [X4_2]; xn--1-ogo..xn--zca; [A4_2]; ; # ≯1..ß +>\u0338⒈。SS; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +≯⒈。SS; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +≯⒈。ss; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +>\u0338⒈。ss; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +>\u0338⒈。Ss; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +≯⒈。Ss; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +xn--hdh84f.ss; ≯⒈.ss; [V7]; xn--hdh84f.ss; ; ; # ≯⒈.ss +xn--hdh84f.xn--zca; ≯⒈.ß; [V7]; xn--hdh84f.xn--zca; ; ; # ≯⒈.ß +\u0667\u200D\uFB96。\u07DA-₆Ⴙ; \u0667\u200D\u06B3.\u07DA-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ +\u0667\u200D\u06B3。\u07DA-6Ⴙ; \u0667\u200D\u06B3.\u07DA-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ +\u0667\u200D\u06B3。\u07DA-6ⴙ; \u0667\u200D\u06B3.\u07DA-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ +xn--gib6m.xn---6-lve6529a; \u0667\u06B3.\u07DA-6ⴙ; [B1, B2, B3]; xn--gib6m.xn---6-lve6529a; ; ; # ٧ڳ.ߚ-6ⴙ +xn--gib6m343e.xn---6-lve6529a; \u0667\u200D\u06B3.\u07DA-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; ; # ٧ڳ.ߚ-6ⴙ +\u0667\u200D\uFB96。\u07DA-₆ⴙ; \u0667\u200D\u06B3.\u07DA-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ +xn--gib6m.xn---6-lve002g; \u0667\u06B3.\u07DA-6Ⴙ; [B1, B2, B3, V7]; xn--gib6m.xn---6-lve002g; ; ; # ٧ڳ.ߚ-6Ⴙ +xn--gib6m343e.xn---6-lve002g; \u0667\u200D\u06B3.\u07DA-6Ⴙ; [B1, B2, B3, C2, V7]; xn--gib6m343e.xn---6-lve002g; ; ; # ٧ڳ.ߚ-6Ⴙ +\u200C。≠; \u200C.≠; [C1]; xn--0ug.xn--1ch; ; .xn--1ch; [A4_2] # .≠ +\u200C。=\u0338; \u200C.≠; [C1]; xn--0ug.xn--1ch; ; .xn--1ch; [A4_2] # .≠ +\u200C。≠; \u200C.≠; [C1]; xn--0ug.xn--1ch; ; .xn--1ch; [A4_2] # .≠ +\u200C。=\u0338; \u200C.≠; [C1]; xn--0ug.xn--1ch; ; .xn--1ch; [A4_2] # .≠ +.xn--1ch; .≠; [X4_2]; .xn--1ch; [A4_2]; ; # .≠ +xn--0ug.xn--1ch; \u200C.≠; [C1]; xn--0ug.xn--1ch; ; ; # .≠ +𑖿𝨔.ᡟ𑖿\u1B42\u200C; ; [C1, V6]; xn--461dw464a.xn--v8e29ldzfo952a; ; xn--461dw464a.xn--v8e29loy65a; [V6] # 𑖿𝨔.ᡟ𑖿ᭂ +xn--461dw464a.xn--v8e29loy65a; 𑖿𝨔.ᡟ𑖿\u1B42; [V6]; xn--461dw464a.xn--v8e29loy65a; ; ; # 𑖿𝨔.ᡟ𑖿ᭂ +xn--461dw464a.xn--v8e29ldzfo952a; 𑖿𝨔.ᡟ𑖿\u1B42\u200C; [C1, V6]; xn--461dw464a.xn--v8e29ldzfo952a; ; ; # 𑖿𝨔.ᡟ𑖿ᭂ +򔣳\u200D򑝱.𖬴Ↄ≠-; 򔣳\u200D򑝱.𖬴ↄ≠-; [C2, V3, V6, V7]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [V3, V6, V7] # .𖬴ↄ≠- +򔣳\u200D򑝱.𖬴Ↄ=\u0338-; 򔣳\u200D򑝱.𖬴ↄ≠-; [C2, V3, V6, V7]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [V3, V6, V7] # .𖬴ↄ≠- +򔣳\u200D򑝱.𖬴ↄ=\u0338-; 򔣳\u200D򑝱.𖬴ↄ≠-; [C2, V3, V6, V7]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [V3, V6, V7] # .𖬴ↄ≠- +򔣳\u200D򑝱.𖬴ↄ≠-; ; [C2, V3, V6, V7]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [V3, V6, V7] # .𖬴ↄ≠- +xn--6j00chy9a.xn----81n51bt713h; 򔣳򑝱.𖬴ↄ≠-; [V3, V6, V7]; xn--6j00chy9a.xn----81n51bt713h; ; ; # .𖬴ↄ≠- +xn--1ug15151gkb5a.xn----81n51bt713h; 򔣳\u200D򑝱.𖬴ↄ≠-; [C2, V3, V6, V7]; xn--1ug15151gkb5a.xn----81n51bt713h; ; ; # .𖬴ↄ≠- +xn--6j00chy9a.xn----61n81bt713h; 򔣳򑝱.𖬴Ↄ≠-; [V3, V6, V7]; xn--6j00chy9a.xn----61n81bt713h; ; ; # .𖬴Ↄ≠- +xn--1ug15151gkb5a.xn----61n81bt713h; 򔣳\u200D򑝱.𖬴Ↄ≠-; [C2, V3, V6, V7]; xn--1ug15151gkb5a.xn----61n81bt713h; ; ; # .𖬴Ↄ≠- +\u07E2ς\u200D𝟳。蔑򛖢; \u07E2ς\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, V7] # ߢς7.蔑 +\u07E2ς\u200D7。蔑򛖢; \u07E2ς\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, V7] # ߢς7.蔑 +\u07E2Σ\u200D7。蔑򛖢; \u07E2σ\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, V7] # ߢσ7.蔑 +\u07E2σ\u200D7。蔑򛖢; \u07E2σ\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, V7] # ߢσ7.蔑 +xn--7-zmb872a.xn--wy1ao4929b; \u07E2σ7.蔑򛖢; [B2, V7]; xn--7-zmb872a.xn--wy1ao4929b; ; ; # ߢσ7.蔑 +xn--7-zmb872aez5a.xn--wy1ao4929b; \u07E2σ\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; ; # ߢσ7.蔑 +xn--7-xmb182aez5a.xn--wy1ao4929b; \u07E2ς\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; ; # ߢς7.蔑 +\u07E2Σ\u200D𝟳。蔑򛖢; \u07E2σ\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, V7] # ߢσ7.蔑 +\u07E2σ\u200D𝟳。蔑򛖢; \u07E2σ\u200D7.蔑򛖢; [B2, C2, V7]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, V7] # ߢσ7.蔑 +𐹰.\u0600; ; [B1, V7]; xn--oo0d.xn--ifb; ; ; # 𐹰. +xn--oo0d.xn--ifb; 𐹰.\u0600; [B1, V7]; xn--oo0d.xn--ifb; ; ; # 𐹰. +-\u08A8.𱠖; ; [B1, V3]; xn----mod.xn--5o9n; ; ; # -ࢨ.𱠖 +xn----mod.xn--5o9n; -\u08A8.𱠖; [B1, V3]; xn----mod.xn--5o9n; ; ; # -ࢨ.𱠖 +≯𞱸󠇀。誆⒈; ≯𞱸.誆⒈; [B1, V7]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈ +>\u0338𞱸󠇀。誆⒈; ≯𞱸.誆⒈; [B1, V7]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈ +≯𞱸󠇀。誆1.; ≯𞱸.誆1.; [B1]; xn--hdh7151p.xn--1-dy1d.; [B1, A4_2]; ; # ≯𞱸.誆1. +>\u0338𞱸󠇀。誆1.; ≯𞱸.誆1.; [B1]; xn--hdh7151p.xn--1-dy1d.; [B1, A4_2]; ; # ≯𞱸.誆1. +xn--hdh7151p.xn--1-dy1d.; ≯𞱸.誆1.; [B1]; xn--hdh7151p.xn--1-dy1d.; [B1, A4_2]; ; # ≯𞱸.誆1. +xn--hdh7151p.xn--tsh1248a; ≯𞱸.誆⒈; [B1, V7]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈ +\u0616𞥙䐊\u0650.︒\u0645↺\u069C; \u0616𞥙䐊\u0650.︒\u0645↺\u069C; [B1, V6, V7]; xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ; ; # ؖ𞥙䐊ِ.︒م↺ڜ +\u0616𞥙䐊\u0650.。\u0645↺\u069C; \u0616𞥙䐊\u0650..\u0645↺\u069C; [B1, V6, X4_2]; xn--4fb0j490qjg4x..xn--hhb8o948e; [B1, V6, A4_2]; ; # ؖ𞥙䐊ِ..م↺ڜ +xn--4fb0j490qjg4x..xn--hhb8o948e; \u0616𞥙䐊\u0650..\u0645↺\u069C; [B1, V6, X4_2]; xn--4fb0j490qjg4x..xn--hhb8o948e; [B1, V6, A4_2]; ; # ؖ𞥙䐊ِ..م↺ڜ +xn--4fb0j490qjg4x.xn--hhb8o948euo5r; \u0616𞥙䐊\u0650.︒\u0645↺\u069C; [B1, V6, V7]; xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ; ; # ؖ𞥙䐊ِ.︒م↺ڜ +퀬-?񶳒.\u200C\u0AC5󩸤۴; ; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; xn---?-6g4k75207c.xn--hmb76q74166b; [V6, V7, U1] # 퀬-?.ૅ۴ +퀬-?񶳒.\u200C\u0AC5󩸤۴; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; xn---?-6g4k75207c.xn--hmb76q74166b; [V6, V7, U1] # 퀬-?.ૅ۴ +xn---?-6g4k75207c.xn--hmb76q74166b; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +xn---?-6g4k75207c.xn--hmb76q48y18505a; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.xn--hmb76q74166b; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.xn--hmb76q74166b; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.XN--HMB76Q74166B; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.XN--HMB76Q74166B; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.Xn--Hmb76q74166b; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.Xn--Hmb76q74166b; 퀬-?񶳒.\u0AC5󩸤۴; [V6, V7, U1]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.xn--hmb76q48y18505a; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.xn--hmb76q48y18505a; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.XN--HMB76Q48Y18505A; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.XN--HMB76Q48Y18505A; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.Xn--Hmb76q48y18505a; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +퀬-?񶳒.Xn--Hmb76q48y18505a; 퀬-?񶳒.\u200C\u0AC5󩸤۴; [C1, V7, U1]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴ +Ⴌ.𐹾︒𑁿𞾄; ⴌ.𐹾︒𑁿𞾄; [B1, V7]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿 +Ⴌ.𐹾。𑁿𞾄; ⴌ.𐹾.𑁿𞾄; [B1, V6, V7]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿 +ⴌ.𐹾。𑁿𞾄; ⴌ.𐹾.𑁿𞾄; [B1, V6, V7]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿 +xn--3kj.xn--2o0d.xn--q30dg029a; ⴌ.𐹾.𑁿𞾄; [B1, V6, V7]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿 +ⴌ.𐹾︒𑁿𞾄; ; [B1, V7]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿 +xn--3kj.xn--y86c030a9ob6374b; ⴌ.𐹾︒𑁿𞾄; [B1, V7]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿 +xn--knd.xn--2o0d.xn--q30dg029a; Ⴌ.𐹾.𑁿𞾄; [B1, V6, V7]; xn--knd.xn--2o0d.xn--q30dg029a; ; ; # Ⴌ.𐹾.𑁿 +xn--knd.xn--y86c030a9ob6374b; Ⴌ.𐹾︒𑁿𞾄; [B1, V7]; xn--knd.xn--y86c030a9ob6374b; ; ; # Ⴌ.𐹾︒𑁿 +񧞿╏。𞩕󠁾; 񧞿╏.𞩕󠁾; [B3, B6, V7]; xn--iyh90030d.xn--1m6hs0260c; ; ; # ╏. +xn--iyh90030d.xn--1m6hs0260c; 񧞿╏.𞩕󠁾; [B3, B6, V7]; xn--iyh90030d.xn--1m6hs0260c; ; ; # ╏. +\u200D┮󠇐.\u0C00\u0C4D\u1734\u200D; \u200D┮.\u0C00\u0C4D\u1734\u200D; [C2, V6]; xn--1ug04r.xn--eoc8m432a40i; ; xn--kxh.xn--eoc8m432a; [V6] # ┮.ఀ్᜴ +\u200D┮󠇐.\u0C00\u0C4D\u1734\u200D; \u200D┮.\u0C00\u0C4D\u1734\u200D; [C2, V6]; xn--1ug04r.xn--eoc8m432a40i; ; xn--kxh.xn--eoc8m432a; [V6] # ┮.ఀ్᜴ +xn--kxh.xn--eoc8m432a; ┮.\u0C00\u0C4D\u1734; [V6]; xn--kxh.xn--eoc8m432a; ; ; # ┮.ఀ్᜴ +xn--1ug04r.xn--eoc8m432a40i; \u200D┮.\u0C00\u0C4D\u1734\u200D; [C2, V6]; xn--1ug04r.xn--eoc8m432a40i; ; ; # ┮.ఀ్᜴ +򹚪。🄂; 򹚪.1,; [V7, U1]; xn--n433d.1,; ; ; # .1, +򹚪。1,; 򹚪.1,; [V7, U1]; xn--n433d.1,; ; ; # .1, +xn--n433d.1,; 򹚪.1,; [V7, U1]; xn--n433d.1,; ; ; # .1, +xn--n433d.xn--v07h; 򹚪.🄂; [V7]; xn--n433d.xn--v07h; ; ; # .🄂 +𑍨刍.🛦; ; [V6]; xn--rbry728b.xn--y88h; ; ; # 𑍨刍.🛦 +xn--rbry728b.xn--y88h; 𑍨刍.🛦; [V6]; xn--rbry728b.xn--y88h; ; ; # 𑍨刍.🛦 +󠌏3。\u1BF1𝟒; 󠌏3.\u1BF14; [V6, V7]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4 +󠌏3。\u1BF14; 󠌏3.\u1BF14; [V6, V7]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4 +xn--3-ib31m.xn--4-pql; 󠌏3.\u1BF14; [V6, V7]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4 +\u06876Ⴔ辘.\uFD22\u0687\u200C; \u06876ⴔ辘.\u0635\u064A\u0687\u200C; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ +\u06876Ⴔ辘.\u0635\u064A\u0687\u200C; \u06876ⴔ辘.\u0635\u064A\u0687\u200C; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ +\u06876ⴔ辘.\u0635\u064A\u0687\u200C; ; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ +xn--6-gsc2270akm6f.xn--0gb6bxk; \u06876ⴔ辘.\u0635\u064A\u0687; [B2, B3]; xn--6-gsc2270akm6f.xn--0gb6bxk; ; ; # ڇ6ⴔ辘.صيڇ +xn--6-gsc2270akm6f.xn--0gb6bxkx18g; \u06876ⴔ辘.\u0635\u064A\u0687\u200C; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; ; # ڇ6ⴔ辘.صيڇ +\u06876ⴔ辘.\uFD22\u0687\u200C; \u06876ⴔ辘.\u0635\u064A\u0687\u200C; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ +xn--6-gsc039eqq6k.xn--0gb6bxk; \u06876Ⴔ辘.\u0635\u064A\u0687; [B2, B3, V7]; xn--6-gsc039eqq6k.xn--0gb6bxk; ; ; # ڇ6Ⴔ辘.صيڇ +xn--6-gsc039eqq6k.xn--0gb6bxkx18g; \u06876Ⴔ辘.\u0635\u064A\u0687\u200C; [B2, B3, C1, V7]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; ; # ڇ6Ⴔ辘.صيڇ +󠄍.𐮭𞰬򻫞۹; .𐮭𞰬򻫞۹; [B2, V7, X4_2]; .xn--mmb3954kd0uf1zx7f; [B2, V7, A4_2]; ; # .𐮭۹ +.xn--mmb3954kd0uf1zx7f; .𐮭𞰬򻫞۹; [B2, V7, X4_2]; .xn--mmb3954kd0uf1zx7f; [B2, V7, A4_2]; ; # .𐮭۹ +\uA87D≯.򻲀򒳄; \uA87D≯.򻲀򒳄; [V7]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯. +\uA87D>\u0338.򻲀򒳄; \uA87D≯.򻲀򒳄; [V7]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯. +\uA87D≯.򻲀򒳄; ; [V7]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯. +\uA87D>\u0338.򻲀򒳄; \uA87D≯.򻲀򒳄; [V7]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯. +xn--hdh8193c.xn--5z40cp629b; \uA87D≯.򻲀򒳄; [V7]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯. +ςო\u067B.ς\u0714; ; [B5, B6]; xn--3xa80l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # ςოٻ.ςܔ +ΣᲝ\u067B.Σ\u0714; σო\u067B.σ\u0714; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ +σო\u067B.σ\u0714; ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ +Σო\u067B.σ\u0714; σო\u067B.σ\u0714; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ +xn--4xa60l26n.xn--4xa21o; σო\u067B.σ\u0714; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ +Σო\u067B.ς\u0714; σო\u067B.ς\u0714; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # σოٻ.ςܔ +σო\u067B.ς\u0714; ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # σოٻ.ςܔ +xn--4xa60l26n.xn--3xa41o; σო\u067B.ς\u0714; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; ; # σოٻ.ςܔ +xn--3xa80l26n.xn--3xa41o; ςო\u067B.ς\u0714; [B5, B6]; xn--3xa80l26n.xn--3xa41o; ; ; # ςოٻ.ςܔ +Σო\u067B.Σ\u0714; σო\u067B.σ\u0714; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ +򄖚\u0748𠄯\u075F。󠛩; 򄖚\u0748𠄯\u075F.󠛩; [B1, B5, B6, V7]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ. +򄖚\u0748𠄯\u075F。󠛩; 򄖚\u0748𠄯\u075F.󠛩; [B1, B5, B6, V7]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ. +xn--vob0c4369twfv8b.xn--kl46e; 򄖚\u0748𠄯\u075F.󠛩; [B1, B5, B6, V7]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ. +󠳛.\u200D䤫≠Ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +󠳛.\u200D䤫=\u0338Ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +󠳛.\u200D䤫≠Ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +󠳛.\u200D䤫=\u0338Ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +󠳛.\u200D䤫=\u0338ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +󠳛.\u200D䤫≠ⴞ; ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +xn--1t56e.xn--1ch153bqvw; 󠳛.䤫≠ⴞ; [V7]; xn--1t56e.xn--1ch153bqvw; ; ; # .䤫≠ⴞ +xn--1t56e.xn--1ug73gzzpwi3a; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; ; # .䤫≠ⴞ +󠳛.\u200D䤫=\u0338ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +󠳛.\u200D䤫≠ⴞ; 󠳛.\u200D䤫≠ⴞ; [C2, V7]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [V7] # .䤫≠ⴞ +xn--1t56e.xn--2nd141ghl2a; 󠳛.䤫≠Ⴞ; [V7]; xn--1t56e.xn--2nd141ghl2a; ; ; # .䤫≠Ⴞ +xn--1t56e.xn--2nd159e9vb743e; 󠳛.\u200D䤫≠Ⴞ; [C2, V7]; xn--1t56e.xn--2nd159e9vb743e; ; ; # .䤫≠Ⴞ +𐽘𑈵.𐹣🕥; 𐽘𑈵.𐹣🕥; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥 +𐽘𑈵.𐹣🕥; ; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥 +xn--bv0d02c.xn--bo0dq650b; 𐽘𑈵.𐹣🕥; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥 +⒊⒈𑁄。9; ⒊⒈𑁄.9; [V7]; xn--tshd3512p.9; ; ; # ⒊⒈𑁄.9 +3.1.𑁄。9; 3.1.𑁄.9; [V6]; 3.1.xn--110d.9; ; ; # 3.1.𑁄.9 +3.1.xn--110d.j; 3.1.𑁄.j; [V6]; 3.1.xn--110d.j; ; ; # 3.1.𑁄.j +xn--tshd3512p.j; ⒊⒈𑁄.j; [V7]; xn--tshd3512p.j; ; ; # ⒊⒈𑁄.j +-\u200C\u2DF1≮.𐹱򭏴4₉; -\u200C\u2DF1≮.𐹱򭏴49; [B1, C1, V3, V7]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, V3, V7] # -ⷱ≮.𐹱49 +-\u200C\u2DF1<\u0338.𐹱򭏴4₉; -\u200C\u2DF1≮.𐹱򭏴49; [B1, C1, V3, V7]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, V3, V7] # -ⷱ≮.𐹱49 +-\u200C\u2DF1≮.𐹱򭏴49; ; [B1, C1, V3, V7]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, V3, V7] # -ⷱ≮.𐹱49 +-\u200C\u2DF1<\u0338.𐹱򭏴49; -\u200C\u2DF1≮.𐹱򭏴49; [B1, C1, V3, V7]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, V3, V7] # -ⷱ≮.𐹱49 +xn----ngo823c.xn--49-ki3om2611f; -\u2DF1≮.𐹱򭏴49; [B1, V3, V7]; xn----ngo823c.xn--49-ki3om2611f; ; ; # -ⷱ≮.𐹱49 +xn----sgn20i14s.xn--49-ki3om2611f; -\u200C\u2DF1≮.𐹱򭏴49; [B1, C1, V3, V7]; xn----sgn20i14s.xn--49-ki3om2611f; ; ; # -ⷱ≮.𐹱49 +-≯딾。\u0847; -≯딾.\u0847; [B1, V3]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ +->\u0338딾。\u0847; -≯딾.\u0847; [B1, V3]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ +-≯딾。\u0847; -≯딾.\u0847; [B1, V3]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ +->\u0338딾。\u0847; -≯딾.\u0847; [B1, V3]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ +xn----pgow547d.xn--5vb; -≯딾.\u0847; [B1, V3]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ +𑙢⒈𐹠-。󠗐\u200C; 𑙢⒈𐹠-.󠗐\u200C; [B1, C1, V3, V7]; xn----dcpy090hiyg.xn--0ug23321l; ; xn----dcpy090hiyg.xn--jd46e; [B1, V3, V7] # 𑙢⒈𐹠-. +𑙢1.𐹠-。󠗐\u200C; 𑙢1.𐹠-.󠗐\u200C; [B1, C1, V3, V7]; xn--1-bf0j.xn----516i.xn--0ug23321l; ; xn--1-bf0j.xn----516i.xn--jd46e; [B1, V3, V7] # 𑙢1.𐹠-. +xn--1-bf0j.xn----516i.xn--jd46e; 𑙢1.𐹠-.󠗐; [B1, V3, V7]; xn--1-bf0j.xn----516i.xn--jd46e; ; ; # 𑙢1.𐹠-. +xn--1-bf0j.xn----516i.xn--0ug23321l; 𑙢1.𐹠-.󠗐\u200C; [B1, C1, V3, V7]; xn--1-bf0j.xn----516i.xn--0ug23321l; ; ; # 𑙢1.𐹠-. +xn----dcpy090hiyg.xn--jd46e; 𑙢⒈𐹠-.󠗐; [B1, V3, V7]; xn----dcpy090hiyg.xn--jd46e; ; ; # 𑙢⒈𐹠-. +xn----dcpy090hiyg.xn--0ug23321l; 𑙢⒈𐹠-.󠗐\u200C; [B1, C1, V3, V7]; xn----dcpy090hiyg.xn--0ug23321l; ; ; # 𑙢⒈𐹠-. +\u034A.𐨎; \u034A.𐨎; [V6]; xn--oua.xn--mr9c; ; ; # ͊.𐨎 +\u034A.𐨎; ; [V6]; xn--oua.xn--mr9c; ; ; # ͊.𐨎 +xn--oua.xn--mr9c; \u034A.𐨎; [V6]; xn--oua.xn--mr9c; ; ; # ͊.𐨎 +훉≮。\u0E34; 훉≮.\u0E34; [V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ +훉<\u0338。\u0E34; 훉≮.\u0E34; [V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ +훉≮。\u0E34; 훉≮.\u0E34; [V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ +훉<\u0338。\u0E34; 훉≮.\u0E34; [V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ +xn--gdh2512e.xn--i4c; 훉≮.\u0E34; [V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ +\u2DF7򞣉🃘.𴈇𝟸\u0659𞤯; \u2DF7򞣉🃘.𴈇2\u0659𞤯; [B1, B5, B6, V6, V7]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯 +\u2DF7򞣉🃘.𴈇2\u0659𞤯; ; [B1, B5, B6, V6, V7]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯 +\u2DF7򞣉🃘.𴈇2\u0659𞤍; \u2DF7򞣉🃘.𴈇2\u0659𞤯; [B1, B5, B6, V6, V7]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯 +xn--trj8045le6s9b.xn--2-upc23918acjsj; \u2DF7򞣉🃘.𴈇2\u0659𞤯; [B1, B5, B6, V6, V7]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯 +\u2DF7򞣉🃘.𴈇𝟸\u0659𞤍; \u2DF7򞣉🃘.𴈇2\u0659𞤯; [B1, B5, B6, V6, V7]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯 +󗇩ßᢞ\u200C。\u0660𞷻\uFCD4-; 󗇩ßᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ßᢞ.٠نخ- +󗇩ßᢞ\u200C。\u0660𞷻\u0646\u062E-; 󗇩ßᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ßᢞ.٠نخ- +󗇩SSᢞ\u200C。\u0660𞷻\u0646\u062E-; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ssᢞ.٠نخ- +󗇩ssᢞ\u200C。\u0660𞷻\u0646\u062E-; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ssᢞ.٠نخ- +󗇩Ssᢞ\u200C。\u0660𞷻\u0646\u062E-; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ssᢞ.٠نخ- +xn--ss-jepz4596r.xn----dnc5e1er384z; 󗇩ssᢞ.\u0660𞷻\u0646\u062E-; [B1, V3, V7]; xn--ss-jepz4596r.xn----dnc5e1er384z; ; ; # ssᢞ.٠نخ- +xn--ss-jep006bqt765b.xn----dnc5e1er384z; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; ; # ssᢞ.٠نخ- +xn--zca272jbif10059a.xn----dnc5e1er384z; 󗇩ßᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; ; # ßᢞ.٠نخ- +󗇩SSᢞ\u200C。\u0660𞷻\uFCD4-; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ssᢞ.٠نخ- +󗇩ssᢞ\u200C。\u0660𞷻\uFCD4-; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ssᢞ.٠نخ- +󗇩Ssᢞ\u200C。\u0660𞷻\uFCD4-; 󗇩ssᢞ\u200C.\u0660𞷻\u0646\u062E-; [B1, B6, C1, V3, V7]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, V3, V7] # ssᢞ.٠نخ- +ꡆ。Ↄ\u0FB5놮-; ꡆ.ↄ\u0FB5놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮- +ꡆ。Ↄ\u0FB5놮-; ꡆ.ↄ\u0FB5놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮- +ꡆ。ↄ\u0FB5놮-; ꡆ.ↄ\u0FB5놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮- +ꡆ。ↄ\u0FB5놮-; ꡆ.ↄ\u0FB5놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮- +xn--fc9a.xn----qmg097k469k; ꡆ.ↄ\u0FB5놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮- +xn--fc9a.xn----qmg787k869k; ꡆ.Ↄ\u0FB5놮-; [V3, V7]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮- +\uFDAD\u200D.񥰌\u06A9; \u0644\u0645\u064A\u200D.񥰌\u06A9; [B3, B5, B6, C2, V7]; xn--ghbcp494x.xn--ckb36214f; ; xn--ghbcp.xn--ckb36214f; [B5, B6, V7] # لمي.ک +\u0644\u0645\u064A\u200D.񥰌\u06A9; ; [B3, B5, B6, C2, V7]; xn--ghbcp494x.xn--ckb36214f; ; xn--ghbcp.xn--ckb36214f; [B5, B6, V7] # لمي.ک +xn--ghbcp.xn--ckb36214f; \u0644\u0645\u064A.񥰌\u06A9; [B5, B6, V7]; xn--ghbcp.xn--ckb36214f; ; ; # لمي.ک +xn--ghbcp494x.xn--ckb36214f; \u0644\u0645\u064A\u200D.񥰌\u06A9; [B3, B5, B6, C2, V7]; xn--ghbcp494x.xn--ckb36214f; ; ; # لمي.ک +Ⴜ\u1C2F𐳒≯。\u06E0\u1732\u0FBA; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +Ⴜ\u1C2F𐳒>\u0338。\u06E0\u1732\u0FBA; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +ⴜ\u1C2F𐳒>\u0338。\u06E0\u1732\u0FBA; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +ⴜ\u1C2F𐳒≯。\u06E0\u1732\u0FBA; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +Ⴜ\u1C2F𐲒≯。\u06E0\u1732\u0FBA; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +Ⴜ\u1C2F𐲒>\u0338。\u06E0\u1732\u0FBA; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +xn--r1f68xh1jgv7u.xn--wlb646b4ng; ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ +xn--0nd679cf3eq67y.xn--wlb646b4ng; Ⴜ\u1C2F𐳒≯.\u06E0\u1732\u0FBA; [B1, B5, B6, V6, V7]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ +𐋵。\uFCEC; 𐋵.\u0643\u0645; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم +𐋵。\u0643\u0645; 𐋵.\u0643\u0645; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم +xn--p97c.xn--fhbe; 𐋵.\u0643\u0645; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم +𐋵.\u0643\u0645; ; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم +≮𝅶.񱲁\uAAEC⹈󰥭; ≮.񱲁\uAAEC⹈󰥭; [V7]; xn--gdh.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈ +<\u0338𝅶.񱲁\uAAEC⹈󰥭; ≮.񱲁\uAAEC⹈󰥭; [V7]; xn--gdh.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈ +≮𝅶.񱲁\uAAEC⹈󰥭; ≮.񱲁\uAAEC⹈󰥭; [V7]; xn--gdh.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈ +<\u0338𝅶.񱲁\uAAEC⹈󰥭; ≮.񱲁\uAAEC⹈󰥭; [V7]; xn--gdh.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈ +xn--gdh.xn--4tjx101bsg00ds9pyc; ≮.񱲁\uAAEC⹈󰥭; [V7]; xn--gdh.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈ +xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ≮𝅶.񱲁\uAAEC⹈󰥭; [V7]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈ +\u2DF0\u0358ᢕ.\u0361𐹷󠴍; \u2DF0\u0358ᢕ.\u0361𐹷󠴍; [B1, V6, V7]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷 +\u2DF0\u0358ᢕ.\u0361𐹷󠴍; ; [B1, V6, V7]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷 +xn--2ua889htsp.xn--cva2687k2tv0g; \u2DF0\u0358ᢕ.\u0361𐹷󠴍; [B1, V6, V7]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷 +\uFD79ᡐ\u200C\u06AD.𑋪\u05C7; \u063A\u0645\u0645ᡐ\u200C\u06AD.𑋪\u05C7; [B1, B2, V6]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; xn--5gbwa03bg24e.xn--vdb1198k; # غممᡐڭ.𑋪ׇ +\u063A\u0645\u0645ᡐ\u200C\u06AD.𑋪\u05C7; ; [B1, B2, V6]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; xn--5gbwa03bg24e.xn--vdb1198k; # غممᡐڭ.𑋪ׇ +xn--5gbwa03bg24e.xn--vdb1198k; \u063A\u0645\u0645ᡐ\u06AD.𑋪\u05C7; [B1, B2, V6]; xn--5gbwa03bg24e.xn--vdb1198k; ; ; # غممᡐڭ.𑋪ׇ +xn--5gbwa03bg24eptk.xn--vdb1198k; \u063A\u0645\u0645ᡐ\u200C\u06AD.𑋪\u05C7; [B1, B2, V6]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; ; # غممᡐڭ.𑋪ׇ +𑑂。\u200D󥞀🞕򥁔; 𑑂.\u200D󥞀🞕򥁔; [C2, V6, V7]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; xn--8v1d.xn--ye9h41035a2qqs; [V6, V7] # 𑑂.🞕 +𑑂。\u200D󥞀🞕򥁔; 𑑂.\u200D󥞀🞕򥁔; [C2, V6, V7]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; xn--8v1d.xn--ye9h41035a2qqs; [V6, V7] # 𑑂.🞕 +xn--8v1d.xn--ye9h41035a2qqs; 𑑂.󥞀🞕򥁔; [V6, V7]; xn--8v1d.xn--ye9h41035a2qqs; ; ; # 𑑂.🞕 +xn--8v1d.xn--1ug1386plvx1cd8vya; 𑑂.\u200D󥞀🞕򥁔; [C2, V6, V7]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; ; # 𑑂.🞕 +-\u05E9。⒚; -\u05E9.⒚; [B1, V3, V7]; xn----gjc.xn--cth; ; ; # -ש.⒚ +-\u05E9。19.; -\u05E9.19.; [B1, V3]; xn----gjc.19.; [B1, V3, A4_2]; ; # -ש.19. +xn----gjc.1j.; -\u05E9.1j.; [B1, V3]; xn----gjc.1j.; [B1, V3, A4_2]; ; # -ש.1j. +xn----gjc.xn--cth; -\u05E9.⒚; [B1, V3, V7]; xn----gjc.xn--cth; ; ; # -ש.⒚ +􊾻\u0845\u200C。ᢎ\u200D; 􊾻\u0845\u200C.ᢎ\u200D; [B5, B6, C1, C2, V7]; xn--3vb882jz4411a.xn--79e259a; ; xn--3vb50049s.xn--79e; [B5, B6, V7] # ࡅ.ᢎ +􊾻\u0845\u200C。ᢎ\u200D; 􊾻\u0845\u200C.ᢎ\u200D; [B5, B6, C1, C2, V7]; xn--3vb882jz4411a.xn--79e259a; ; xn--3vb50049s.xn--79e; [B5, B6, V7] # ࡅ.ᢎ +xn--3vb50049s.xn--79e; 􊾻\u0845.ᢎ; [B5, B6, V7]; xn--3vb50049s.xn--79e; ; ; # ࡅ.ᢎ +xn--3vb882jz4411a.xn--79e259a; 􊾻\u0845\u200C.ᢎ\u200D; [B5, B6, C1, C2, V7]; xn--3vb882jz4411a.xn--79e259a; ; ; # ࡅ.ᢎ +ß\u09C1\u1DED。\u06208₅; ß\u09C1\u1DED.\u062085; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85 +ß\u09C1\u1DED。\u062085; ß\u09C1\u1DED.\u062085; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85 +SS\u09C1\u1DED。\u062085; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +ss\u09C1\u1DED。\u062085; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +Ss\u09C1\u1DED。\u062085; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +xn--ss-e2f077r.xn--85-psd; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +ss\u09C1\u1DED.\u062085; ; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +SS\u09C1\u1DED.\u062085; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +Ss\u09C1\u1DED.\u062085; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +xn--zca266bwrr.xn--85-psd; ß\u09C1\u1DED.\u062085; ; xn--zca266bwrr.xn--85-psd; ; ; # ßুᷭ.ؠ85 +ß\u09C1\u1DED.\u062085; ; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85 +SS\u09C1\u1DED。\u06208₅; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +ss\u09C1\u1DED。\u06208₅; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +Ss\u09C1\u1DED。\u06208₅; ss\u09C1\u1DED.\u062085; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85 +\u0ACD\u0484魅𝟣.₃𐹥ß; \u0ACD\u0484魅1.3𐹥ß; [B1, V6]; xn--1-0xb049b102o.xn--3-qfa7018r; ; xn--1-0xb049b102o.xn--3ss-nv9t; # ્҄魅1.3𐹥ß +\u0ACD\u0484魅1.3𐹥ß; ; [B1, V6]; xn--1-0xb049b102o.xn--3-qfa7018r; ; xn--1-0xb049b102o.xn--3ss-nv9t; # ્҄魅1.3𐹥ß +\u0ACD\u0484魅1.3𐹥SS; \u0ACD\u0484魅1.3𐹥ss; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +\u0ACD\u0484魅1.3𐹥ss; ; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +\u0ACD\u0484魅1.3𐹥Ss; \u0ACD\u0484魅1.3𐹥ss; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +xn--1-0xb049b102o.xn--3ss-nv9t; \u0ACD\u0484魅1.3𐹥ss; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +xn--1-0xb049b102o.xn--3-qfa7018r; \u0ACD\u0484魅1.3𐹥ß; [B1, V6]; xn--1-0xb049b102o.xn--3-qfa7018r; ; ; # ્҄魅1.3𐹥ß +\u0ACD\u0484魅𝟣.₃𐹥SS; \u0ACD\u0484魅1.3𐹥ss; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +\u0ACD\u0484魅𝟣.₃𐹥ss; \u0ACD\u0484魅1.3𐹥ss; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +\u0ACD\u0484魅𝟣.₃𐹥Ss; \u0ACD\u0484魅1.3𐹥ss; [B1, V6]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss +\u072B。𑓂⒈𑜫󠿻; \u072B.𑓂⒈𑜫󠿻; [B1, V6, V7]; xn--1nb.xn--tsh7798f6rbrt828c; ; ; # ܫ.𑓂⒈𑜫 +\u072B。𑓂1.𑜫󠿻; \u072B.𑓂1.𑜫󠿻; [B1, V6, V7]; xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ; ; # ܫ.𑓂1.𑜫 +xn--1nb.xn--1-jq9i.xn--ji2dg9877c; \u072B.𑓂1.𑜫󠿻; [B1, V6, V7]; xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ; ; # ܫ.𑓂1.𑜫 +xn--1nb.xn--tsh7798f6rbrt828c; \u072B.𑓂⒈𑜫󠿻; [B1, V6, V7]; xn--1nb.xn--tsh7798f6rbrt828c; ; ; # ܫ.𑓂⒈𑜫 +\uFE0Dછ。嵨; છ.嵨; ; xn--6dc.xn--tot; ; ; # છ.嵨 +xn--6dc.xn--tot; છ.嵨; ; xn--6dc.xn--tot; ; ; # છ.嵨 +છ.嵨; ; ; xn--6dc.xn--tot; ; ; # છ.嵨 +Ⴔ≠Ⴀ.𐹥𐹰; ⴔ≠ⴀ.𐹥𐹰; [B1]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰 +Ⴔ=\u0338Ⴀ.𐹥𐹰; ⴔ≠ⴀ.𐹥𐹰; [B1]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰 +ⴔ=\u0338ⴀ.𐹥𐹰; ⴔ≠ⴀ.𐹥𐹰; [B1]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰 +ⴔ≠ⴀ.𐹥𐹰; ; [B1]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰 +xn--1ch603bxb.xn--do0dwa; ⴔ≠ⴀ.𐹥𐹰; [B1]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰 +xn--7md3b171g.xn--do0dwa; Ⴔ≠Ⴀ.𐹥𐹰; [B1, V7]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰 +-\u200C⒙𐫥。𝨵; -\u200C⒙𐫥.𝨵; [C1, V3, V6, V7]; xn----sgn18r3191a.xn--382h; ; xn----ddps939g.xn--382h; [V3, V6, V7] # -⒙𐫥.𝨵 +-\u200C18.𐫥。𝨵; -\u200C18.𐫥.𝨵; [C1, V3, V6]; xn---18-9m0a.xn--rx9c.xn--382h; ; -18.xn--rx9c.xn--382h; [V3, V6] # -18.𐫥.𝨵 +-18.xn--rx9c.xn--382h; -18.𐫥.𝨵; [V3, V6]; -18.xn--rx9c.xn--382h; ; ; # -18.𐫥.𝨵 +xn---18-9m0a.xn--rx9c.xn--382h; -\u200C18.𐫥.𝨵; [C1, V3, V6]; xn---18-9m0a.xn--rx9c.xn--382h; ; ; # -18.𐫥.𝨵 +xn----ddps939g.xn--382h; -⒙𐫥.𝨵; [V3, V6, V7]; xn----ddps939g.xn--382h; ; ; # -⒙𐫥.𝨵 +xn----sgn18r3191a.xn--382h; -\u200C⒙𐫥.𝨵; [C1, V3, V6, V7]; xn----sgn18r3191a.xn--382h; ; ; # -⒙𐫥.𝨵 +︒.ʌᠣ-𐹽; ; [B1, B5, B6, V7]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽 +。.ʌᠣ-𐹽; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽 +。.Ʌᠣ-𐹽; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽 +..xn----73a596nuh9t; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽 +︒.Ʌᠣ-𐹽; ︒.ʌᠣ-𐹽; [B1, B5, B6, V7]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽 +xn--y86c.xn----73a596nuh9t; ︒.ʌᠣ-𐹽; [B1, B5, B6, V7]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽 +\uFE05︒。𦀾\u1CE0; ︒.𦀾\u1CE0; [V7]; xn--y86c.xn--t6f5138v; ; ; # ︒.𦀾᳠ +\uFE05。。𦀾\u1CE0; ..𦀾\u1CE0; [X4_2]; ..xn--t6f5138v; [A4_2]; ; # ..𦀾᳠ +..xn--t6f5138v; ..𦀾\u1CE0; [X4_2]; ..xn--t6f5138v; [A4_2]; ; # ..𦀾᳠ +xn--y86c.xn--t6f5138v; ︒.𦀾\u1CE0; [V7]; xn--y86c.xn--t6f5138v; ; ; # ︒.𦀾᳠ +xn--t6f5138v; 𦀾\u1CE0; ; xn--t6f5138v; ; ; # 𦀾᳠ +𦀾\u1CE0; ; ; xn--t6f5138v; ; ; # 𦀾᳠ +𞮑ß􏞞。ᡁ; 𞮑ß􏞞.ᡁ; [B2, B3, V7]; xn--zca9432wb989f.xn--07e; ; xn--ss-o412ac6305g.xn--07e; # ß.ᡁ +𞮑SS􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, V7]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ +𞮑ss􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, V7]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ +𞮑Ss􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, V7]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ +xn--ss-o412ac6305g.xn--07e; 𞮑ss􏞞.ᡁ; [B2, B3, V7]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ +xn--zca9432wb989f.xn--07e; 𞮑ß􏞞.ᡁ; [B2, B3, V7]; xn--zca9432wb989f.xn--07e; ; ; # ß.ᡁ +\uA953\u200D\u062C\u066C。𱆎󻡟\u200C󠅆; \uA953\u200D\u062C\u066C.𱆎󻡟\u200C; [B5, B6, C1, V6, V7]; xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ; xn--rgb2k6711c.xn--ec8nj3948b; [B5, B6, V6, V7] # ꥓ج٬.𱆎 +xn--rgb2k6711c.xn--ec8nj3948b; \uA953\u062C\u066C.𱆎󻡟; [B5, B6, V6, V7]; xn--rgb2k6711c.xn--ec8nj3948b; ; ; # ꥓ج٬.𱆎 +xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; \uA953\u200D\u062C\u066C.𱆎󻡟\u200C; [B5, B6, C1, V6, V7]; xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ; ; # ꥓ج٬.𱆎 +󠕏.-ß\u200C≠; 󠕏.-ß\u200C≠; [C1, V3, V7]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ß≠ +󠕏.-ß\u200C=\u0338; 󠕏.-ß\u200C≠; [C1, V3, V7]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ß≠ +󠕏.-ß\u200C≠; ; [C1, V3, V7]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ß≠ +󠕏.-ß\u200C=\u0338; 󠕏.-ß\u200C≠; [C1, V3, V7]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ß≠ +󠕏.-SS\u200C=\u0338; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-SS\u200C≠; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-ss\u200C≠; ; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-ss\u200C=\u0338; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-Ss\u200C=\u0338; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-Ss\u200C≠; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +xn--u836e.xn---ss-gl2a; 󠕏.-ss≠; [V3, V7]; xn--u836e.xn---ss-gl2a; ; ; # .-ss≠ +xn--u836e.xn---ss-cn0at5l; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; ; # .-ss≠ +xn--u836e.xn----qfa750ve7b; 󠕏.-ß\u200C≠; [C1, V3, V7]; xn--u836e.xn----qfa750ve7b; ; ; # .-ß≠ +󠕏.-SS\u200C=\u0338; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-SS\u200C≠; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-ss\u200C≠; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-ss\u200C=\u0338; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-Ss\u200C=\u0338; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +󠕏.-Ss\u200C≠; 󠕏.-ss\u200C≠; [C1, V3, V7]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [V3, V7] # .-ss≠ +ᡙ\u200C。≯𐋲≠; ᡙ\u200C.≯𐋲≠; [C1]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [] # ᡙ.≯𐋲≠ +ᡙ\u200C。>\u0338𐋲=\u0338; ᡙ\u200C.≯𐋲≠; [C1]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [] # ᡙ.≯𐋲≠ +ᡙ\u200C。≯𐋲≠; ᡙ\u200C.≯𐋲≠; [C1]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [] # ᡙ.≯𐋲≠ +ᡙ\u200C。>\u0338𐋲=\u0338; ᡙ\u200C.≯𐋲≠; [C1]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [] # ᡙ.≯𐋲≠ +xn--p8e.xn--1ch3a7084l; ᡙ.≯𐋲≠; ; xn--p8e.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠ +ᡙ.≯𐋲≠; ; ; xn--p8e.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠ +ᡙ.>\u0338𐋲=\u0338; ᡙ.≯𐋲≠; ; xn--p8e.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠ +xn--p8e650b.xn--1ch3a7084l; ᡙ\u200C.≯𐋲≠; [C1]; xn--p8e650b.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠ +𐹧𞲄󠁭񆼩。\u034E🄀; 𐹧𞲄󠁭񆼩.\u034E🄀; [B1, V6, V7]; xn--fo0dw409aq58qrn69d.xn--sua6883w; ; ; # 𐹧𞲄.͎🄀 +𐹧𞲄󠁭񆼩。\u034E0.; 𐹧𞲄󠁭񆼩.\u034E0.; [B1, V6, V7]; xn--fo0dw409aq58qrn69d.xn--0-bgb.; [B1, V6, V7, A4_2]; ; # 𐹧𞲄.͎0. +xn--fo0dw409aq58qrn69d.xn--0-bgb.; 𐹧𞲄󠁭񆼩.\u034E0.; [B1, V6, V7]; xn--fo0dw409aq58qrn69d.xn--0-bgb.; [B1, V6, V7, A4_2]; ; # 𐹧𞲄.͎0. +xn--fo0dw409aq58qrn69d.xn--sua6883w; 𐹧𞲄󠁭񆼩.\u034E🄀; [B1, V6, V7]; xn--fo0dw409aq58qrn69d.xn--sua6883w; ; ; # 𐹧𞲄.͎🄀 +Ⴄ.\u200D\u0721󻣋ς; ⴄ.\u200D\u0721󻣋ς; [B1, C2, V7]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡς +Ⴄ.\u200D\u0721󻣋ς; ⴄ.\u200D\u0721󻣋ς; [B1, C2, V7]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡς +ⴄ.\u200D\u0721󻣋ς; ; [B1, C2, V7]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡς +Ⴄ.\u200D\u0721󻣋Σ; ⴄ.\u200D\u0721󻣋σ; [B1, C2, V7]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡσ +ⴄ.\u200D\u0721󻣋σ; ; [B1, C2, V7]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡσ +xn--vkj.xn--4xa73ob5892c; ⴄ.\u0721󻣋σ; [B2, B3, V7]; xn--vkj.xn--4xa73ob5892c; ; ; # ⴄ.ܡσ +xn--vkj.xn--4xa73o3t5ajq467a; ⴄ.\u200D\u0721󻣋σ; [B1, C2, V7]; xn--vkj.xn--4xa73o3t5ajq467a; ; ; # ⴄ.ܡσ +xn--vkj.xn--3xa93o3t5ajq467a; ⴄ.\u200D\u0721󻣋ς; [B1, C2, V7]; xn--vkj.xn--3xa93o3t5ajq467a; ; ; # ⴄ.ܡς +ⴄ.\u200D\u0721󻣋ς; ⴄ.\u200D\u0721󻣋ς; [B1, C2, V7]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡς +Ⴄ.\u200D\u0721󻣋Σ; ⴄ.\u200D\u0721󻣋σ; [B1, C2, V7]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡσ +ⴄ.\u200D\u0721󻣋σ; ⴄ.\u200D\u0721󻣋σ; [B1, C2, V7]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, V7] # ⴄ.ܡσ +xn--cnd.xn--4xa73ob5892c; Ⴄ.\u0721󻣋σ; [B2, B3, V7]; xn--cnd.xn--4xa73ob5892c; ; ; # Ⴄ.ܡσ +xn--cnd.xn--4xa73o3t5ajq467a; Ⴄ.\u200D\u0721󻣋σ; [B1, C2, V7]; xn--cnd.xn--4xa73o3t5ajq467a; ; ; # Ⴄ.ܡσ +xn--cnd.xn--3xa93o3t5ajq467a; Ⴄ.\u200D\u0721󻣋ς; [B1, C2, V7]; xn--cnd.xn--3xa93o3t5ajq467a; ; ; # Ⴄ.ܡς +򮵛\u0613.Ⴕ; 򮵛\u0613.ⴕ; [V7]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ +򮵛\u0613.ⴕ; ; [V7]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ +xn--1fb94204l.xn--dlj; 򮵛\u0613.ⴕ; [V7]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ +xn--1fb94204l.xn--tnd; 򮵛\u0613.Ⴕ; [V7]; xn--1fb94204l.xn--tnd; ; ; # ؓ.Ⴕ +≯\u1DF3𞤥。\u200C\uA8C4󠪉\u200D; ≯\u1DF3𞤥.\u200C\uA8C4󠪉\u200D; [B1, C1, C2, V7]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, V6, V7] # ≯ᷳ𞤥.꣄ +>\u0338\u1DF3𞤥。\u200C\uA8C4󠪉\u200D; ≯\u1DF3𞤥.\u200C\uA8C4󠪉\u200D; [B1, C1, C2, V7]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, V6, V7] # ≯ᷳ𞤥.꣄ +>\u0338\u1DF3𞤃。\u200C\uA8C4󠪉\u200D; ≯\u1DF3𞤥.\u200C\uA8C4󠪉\u200D; [B1, C1, C2, V7]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, V6, V7] # ≯ᷳ𞤥.꣄ +≯\u1DF3𞤃。\u200C\uA8C4󠪉\u200D; ≯\u1DF3𞤥.\u200C\uA8C4󠪉\u200D; [B1, C1, C2, V7]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, V6, V7] # ≯ᷳ𞤥.꣄ +xn--ofg13qyr21c.xn--0f9au6706d; ≯\u1DF3𞤥.\uA8C4󠪉; [B1, V6, V7]; xn--ofg13qyr21c.xn--0f9au6706d; ; ; # ≯ᷳ𞤥.꣄ +xn--ofg13qyr21c.xn--0ugc0116hix29k; ≯\u1DF3𞤥.\u200C\uA8C4󠪉\u200D; [B1, C1, C2, V7]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; ; # ≯ᷳ𞤥.꣄ +\u200C󠄷。򒑁; \u200C.򒑁; [C1, V7]; xn--0ug.xn--w720c; ; .xn--w720c; [V7, A4_2] # . +\u200C󠄷。򒑁; \u200C.򒑁; [C1, V7]; xn--0ug.xn--w720c; ; .xn--w720c; [V7, A4_2] # . +.xn--w720c; .򒑁; [V7, X4_2]; .xn--w720c; [V7, A4_2]; ; # . +xn--0ug.xn--w720c; \u200C.򒑁; [C1, V7]; xn--0ug.xn--w720c; ; ; # . +⒈\u0DD6焅.󗡙\u200Dꡟ; ; [C2, V7]; xn--t1c337io97c.xn--1ugz184c9lw7i; ; xn--t1c337io97c.xn--4c9a21133d; [V7] # ⒈ූ焅.ꡟ +1.\u0DD6焅.󗡙\u200Dꡟ; ; [C2, V6, V7]; 1.xn--t1c6981c.xn--1ugz184c9lw7i; ; 1.xn--t1c6981c.xn--4c9a21133d; [V6, V7] # 1.ූ焅.ꡟ +1.xn--t1c6981c.xn--4c9a21133d; 1.\u0DD6焅.󗡙ꡟ; [V6, V7]; 1.xn--t1c6981c.xn--4c9a21133d; ; ; # 1.ූ焅.ꡟ +1.xn--t1c6981c.xn--1ugz184c9lw7i; 1.\u0DD6焅.󗡙\u200Dꡟ; [C2, V6, V7]; 1.xn--t1c6981c.xn--1ugz184c9lw7i; ; ; # 1.ූ焅.ꡟ +xn--t1c337io97c.xn--4c9a21133d; ⒈\u0DD6焅.󗡙ꡟ; [V7]; xn--t1c337io97c.xn--4c9a21133d; ; ; # ⒈ූ焅.ꡟ +xn--t1c337io97c.xn--1ugz184c9lw7i; ⒈\u0DD6焅.󗡙\u200Dꡟ; [C2, V7]; xn--t1c337io97c.xn--1ugz184c9lw7i; ; ; # ⒈ූ焅.ꡟ +\u1DCDς≮.ς𝪦𞤕0; \u1DCDς≮.ς𝪦𞤷0; [B1, B5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0 +\u1DCDς<\u0338.ς𝪦𞤕0; \u1DCDς≮.ς𝪦𞤷0; [B1, B5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0 +\u1DCDς<\u0338.ς𝪦𞤷0; \u1DCDς≮.ς𝪦𞤷0; [B1, B5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0 +\u1DCDς≮.ς𝪦𞤷0; ; [B1, B5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0 +\u1DCDΣ≮.Σ𝪦𞤕0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +\u1DCDΣ<\u0338.Σ𝪦𞤕0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +\u1DCDσ<\u0338.σ𝪦𞤷0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +\u1DCDσ≮.σ𝪦𞤷0; ; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +\u1DCDΣ≮.Σ𝪦𞤷0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +\u1DCDΣ<\u0338.Σ𝪦𞤷0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +xn--4xa544kvid.xn--0-zmb55727aggma; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +xn--3xa744kvid.xn--0-xmb85727aggma; \u1DCDς≮.ς𝪦𞤷0; [B1, B5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; ; # ᷍ς≮.ς𝪦𞤷0 +\u1DCDσ≮.σ𝪦𞤕0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +\u1DCDσ<\u0338.σ𝪦𞤕0; \u1DCDσ≮.σ𝪦𞤷0; [B1, B5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0 +򢦾ß\u05B9𐫙.\u05AD\u08A1; ; [B1, B5, B6, V6, V7]; xn--zca89v339zj118e.xn--4cb62m; ; xn--ss-xjd6058xlz50g.xn--4cb62m; # ßֹ𐫙.֭ࢡ +򢦾SS\u05B9𐫙.\u05AD\u08A1; 򢦾ss\u05B9𐫙.\u05AD\u08A1; [B1, B5, B6, V6, V7]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ +򢦾ss\u05B9𐫙.\u05AD\u08A1; ; [B1, B5, B6, V6, V7]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ +򢦾Ss\u05B9𐫙.\u05AD\u08A1; 򢦾ss\u05B9𐫙.\u05AD\u08A1; [B1, B5, B6, V6, V7]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ +xn--ss-xjd6058xlz50g.xn--4cb62m; 򢦾ss\u05B9𐫙.\u05AD\u08A1; [B1, B5, B6, V6, V7]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ +xn--zca89v339zj118e.xn--4cb62m; 򢦾ß\u05B9𐫙.\u05AD\u08A1; [B1, B5, B6, V6, V7]; xn--zca89v339zj118e.xn--4cb62m; ; ; # ßֹ𐫙.֭ࢡ +-𞣄。⒈; -𞣄.⒈; [B1, V3, V7]; xn----xc8r.xn--tsh; ; ; # -𞣄.⒈ +-𞣄。1.; -𞣄.1.; [B1, V3]; xn----xc8r.1.; [B1, V3, A4_2]; ; # -𞣄.1. +xn----xc8r.b.; -𞣄.b.; [B1, V3]; xn----xc8r.b.; [B1, V3, A4_2]; ; # -𞣄.b. +xn----xc8r.xn--tsh; -𞣄.⒈; [B1, V3, V7]; xn----xc8r.xn--tsh; ; ; # -𞣄.⒈ +񈠢𐫖𝟡。\u063E𑘿; 񈠢𐫖9.\u063E𑘿; [B5, V7]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿 +񈠢𐫖9。\u063E𑘿; 񈠢𐫖9.\u063E𑘿; [B5, V7]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿 +xn--9-el5iv442t.xn--9gb0830l; 񈠢𐫖9.\u063E𑘿; [B5, V7]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿 +\u0668\uFC8C\u0668\u1A5D.\u200D; \u0668\u0646\u0645\u0668\u1A5D.\u200D; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; xn--hhbb5hc956w.; [B1, A4_2] # ٨نم٨ᩝ. +\u0668\u0646\u0645\u0668\u1A5D.\u200D; ; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; xn--hhbb5hc956w.; [B1, A4_2] # ٨نم٨ᩝ. +xn--hhbb5hc956w.; \u0668\u0646\u0645\u0668\u1A5D.; [B1]; xn--hhbb5hc956w.; [B1, A4_2]; ; # ٨نم٨ᩝ. +xn--hhbb5hc956w.xn--1ug; \u0668\u0646\u0645\u0668\u1A5D.\u200D; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; ; # ٨نم٨ᩝ. +𝟘.Ⴇ󀳑\uFD50񫃱; 0.ⴇ󀳑\u062A\u062C\u0645񫃱; [B1, B5, V7]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم +0.Ⴇ󀳑\u062A\u062C\u0645񫃱; 0.ⴇ󀳑\u062A\u062C\u0645񫃱; [B1, B5, V7]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم +0.ⴇ󀳑\u062A\u062C\u0645񫃱; ; [B1, B5, V7]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم +0.xn--pgbe9ez79qd207lvff8b; 0.ⴇ󀳑\u062A\u062C\u0645񫃱; [B1, B5, V7]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم +𝟘.ⴇ󀳑\uFD50񫃱; 0.ⴇ󀳑\u062A\u062C\u0645񫃱; [B1, B5, V7]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم +0.xn--pgbe9e344c2725svff8b; 0.Ⴇ󀳑\u062A\u062C\u0645񫃱; [B1, B5, V7]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم +𑇀▍.⁞ᠰ; ; [V6]; xn--9zh3057f.xn--j7e103b; ; ; # 𑇀▍.⁞ᠰ +xn--9zh3057f.xn--j7e103b; 𑇀▍.⁞ᠰ; [V6]; xn--9zh3057f.xn--j7e103b; ; ; # 𑇀▍.⁞ᠰ +\u200D-\u067A.򏯩; ; [B1, C2, V7]; xn----qrc357q.xn--ts49b; ; xn----qrc.xn--ts49b; [B1, V3, V7] # -ٺ. +xn----qrc.xn--ts49b; -\u067A.򏯩; [B1, V3, V7]; xn----qrc.xn--ts49b; ; ; # -ٺ. +xn----qrc357q.xn--ts49b; \u200D-\u067A.򏯩; [B1, C2, V7]; xn----qrc357q.xn--ts49b; ; ; # -ٺ. +ᠢ𐮂𐫘寐。\u200C≯✳; ᠢ𐮂𐫘寐.\u200C≯✳; [B1, B5, C1]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5] # ᠢ𐮂𐫘寐.≯✳ +ᠢ𐮂𐫘寐。\u200C>\u0338✳; ᠢ𐮂𐫘寐.\u200C≯✳; [B1, B5, C1]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5] # ᠢ𐮂𐫘寐.≯✳ +ᠢ𐮂𐫘寐。\u200C≯✳; ᠢ𐮂𐫘寐.\u200C≯✳; [B1, B5, C1]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5] # ᠢ𐮂𐫘寐.≯✳ +ᠢ𐮂𐫘寐。\u200C>\u0338✳; ᠢ𐮂𐫘寐.\u200C≯✳; [B1, B5, C1]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5] # ᠢ𐮂𐫘寐.≯✳ +xn--46e6675axzzhota.xn--hdh99p; ᠢ𐮂𐫘寐.≯✳; [B1, B5]; xn--46e6675axzzhota.xn--hdh99p; ; ; # ᠢ𐮂𐫘寐.≯✳ +xn--46e6675axzzhota.xn--0ug06gu8f; ᠢ𐮂𐫘寐.\u200C≯✳; [B1, B5, C1]; xn--46e6675axzzhota.xn--0ug06gu8f; ; ; # ᠢ𐮂𐫘寐.≯✳ +\u200D。󸲜ႺႴ𞨇; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2] # .ⴚⴔ +\u200D。󸲜ႺႴ𞨇; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2] # .ⴚⴔ +\u200D。󸲜ⴚⴔ𞨇; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2] # .ⴚⴔ +\u200D。󸲜Ⴚⴔ𞨇; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2] # .ⴚⴔ +.xn--cljl81825an3r4h; .󸲜ⴚⴔ𞨇; [B5, B6, V7, X4_2]; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2]; ; # .ⴚⴔ +xn--1ug.xn--cljl81825an3r4h; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; ; # .ⴚⴔ +\u200D。󸲜ⴚⴔ𞨇; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2] # .ⴚⴔ +\u200D。󸲜Ⴚⴔ𞨇; \u200D.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, V7, A4_2] # .ⴚⴔ +.xn--ynd036lq981an3r4h; .󸲜Ⴚⴔ𞨇; [B5, B6, V7, X4_2]; .xn--ynd036lq981an3r4h; [B5, B6, V7, A4_2]; ; # .Ⴚⴔ +xn--1ug.xn--ynd036lq981an3r4h; \u200D.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--ynd036lq981an3r4h; ; ; # .Ⴚⴔ +.xn--sndl01647an3h1h; .󸲜ႺႴ𞨇; [B5, B6, V7, X4_2]; .xn--sndl01647an3h1h; [B5, B6, V7, A4_2]; ; # .ႺႴ +xn--1ug.xn--sndl01647an3h1h; \u200D.󸲜ႺႴ𞨇; [B1, B5, B6, C2, V7]; xn--1ug.xn--sndl01647an3h1h; ; ; # .ႺႴ +-3.\u200Dヌᢕ; ; [C2, V3]; -3.xn--fbf739aq5o; ; -3.xn--fbf115j; [V3] # -3.ヌᢕ +-3.xn--fbf115j; -3.ヌᢕ; [V3]; -3.xn--fbf115j; ; ; # -3.ヌᢕ +-3.xn--fbf739aq5o; -3.\u200Dヌᢕ; [C2, V3]; -3.xn--fbf739aq5o; ; ; # -3.ヌᢕ +🂃\u0666ß\u200D。󠠂򭰍𞩒-; 🂃\u0666ß\u200D.󠠂򭰍𞩒-; [B1, C2, V3, V7]; xn--zca34z68yzu83b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, V3, V7] # 🂃٦ß.- +🂃\u0666SS\u200D。󠠂򭰍𞩒-; 🂃\u0666ss\u200D.󠠂򭰍𞩒-; [B1, C2, V3, V7]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, V3, V7] # 🂃٦ss.- +🂃\u0666ss\u200D。󠠂򭰍𞩒-; 🂃\u0666ss\u200D.󠠂򭰍𞩒-; [B1, C2, V3, V7]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, V3, V7] # 🂃٦ss.- +xn--ss-pyd98921c.xn----nz8rh7531csznt; 🂃\u0666ss.󠠂򭰍𞩒-; [B1, V3, V7]; xn--ss-pyd98921c.xn----nz8rh7531csznt; ; ; # 🂃٦ss.- +xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; 🂃\u0666ss\u200D.󠠂򭰍𞩒-; [B1, C2, V3, V7]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; ; # 🂃٦ss.- +xn--zca34z68yzu83b.xn----nz8rh7531csznt; 🂃\u0666ß\u200D.󠠂򭰍𞩒-; [B1, C2, V3, V7]; xn--zca34z68yzu83b.xn----nz8rh7531csznt; ; ; # 🂃٦ß.- +🂃\u0666Ss\u200D。󠠂򭰍𞩒-; 🂃\u0666ss\u200D.󠠂򭰍𞩒-; [B1, C2, V3, V7]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, V3, V7] # 🂃٦ss.- +ꇟ-𐾺\u069F。򰀺\u200C; ꇟ-𐾺\u069F.򰀺\u200C; [B5, B6, C1, V7]; xn----utc4430jd3zd.xn--0ugx6670i; ; xn----utc4430jd3zd.xn--bp20d; [B5, B6, V7] # ꇟ-𐾺ڟ. +xn----utc4430jd3zd.xn--bp20d; ꇟ-𐾺\u069F.򰀺; [B5, B6, V7]; xn----utc4430jd3zd.xn--bp20d; ; ; # ꇟ-𐾺ڟ. +xn----utc4430jd3zd.xn--0ugx6670i; ꇟ-𐾺\u069F.򰀺\u200C; [B5, B6, C1, V7]; xn----utc4430jd3zd.xn--0ugx6670i; ; ; # ꇟ-𐾺ڟ. +\u0665.\u0484𐨗𝩋𴤃; ; [B1, V6, V7]; xn--eib.xn--n3a0405kus8eft5l; ; ; # ٥.҄𐨗𝩋 +xn--eib.xn--n3a0405kus8eft5l; \u0665.\u0484𐨗𝩋𴤃; [B1, V6, V7]; xn--eib.xn--n3a0405kus8eft5l; ; ; # ٥.҄𐨗𝩋 +-.񱼓\u0649𐨿; ; [B1, B5, B6, V3, V7]; -.xn--lhb4124khbq4b; ; ; # -.ى𐨿 +-.xn--lhb4124khbq4b; -.񱼓\u0649𐨿; [B1, B5, B6, V3, V7]; -.xn--lhb4124khbq4b; ; ; # -.ى𐨿 +󾬨ς.𞶙녫ß; ; [B2, B3, V7]; xn--3xa96659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # ς.녫ß +󾬨ς.𞶙녫ß; 󾬨ς.𞶙녫ß; [B2, B3, V7]; xn--3xa96659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # ς.녫ß +󾬨Σ.𞶙녫SS; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨Σ.𞶙녫SS; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨σ.𞶙녫ss; ; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨Σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨Σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨Σ.𞶙녫Ss; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨Σ.𞶙녫Ss; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +xn--4xa76659r.xn--ss-d64i8755h; 󾬨σ.𞶙녫ss; [B2, B3, V7]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss +󾬨Σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, V7]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß +󾬨Σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, V7]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß +󾬨σ.𞶙녫ß; ; [B2, B3, V7]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß +󾬨σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, V7]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß +xn--4xa76659r.xn--zca5051g4h4i; 󾬨σ.𞶙녫ß; [B2, B3, V7]; xn--4xa76659r.xn--zca5051g4h4i; ; ; # σ.녫ß +xn--3xa96659r.xn--zca5051g4h4i; 󾬨ς.𞶙녫ß; [B2, B3, V7]; xn--3xa96659r.xn--zca5051g4h4i; ; ; # ς.녫ß +Ⅎ\u17D2\u200D。≠\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +Ⅎ\u17D2\u200D。=\u0338\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +Ⅎ\u17D2\u200D。≠\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +Ⅎ\u17D2\u200D。=\u0338\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +ⅎ\u17D2\u200D。=\u0338\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +ⅎ\u17D2\u200D。≠\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +xn--u4e969b.xn--1ch; ⅎ\u17D2.≠; ; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠ +ⅎ\u17D2.≠; ; ; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠ +ⅎ\u17D2.=\u0338; ⅎ\u17D2.≠; ; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠ +Ⅎ\u17D2.=\u0338; ⅎ\u17D2.≠; ; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠ +Ⅎ\u17D2.≠; ⅎ\u17D2.≠; ; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠ +xn--u4e823bq1a.xn--0ugb89o; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; ; # ⅎ្.≠ +ⅎ\u17D2\u200D。=\u0338\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +ⅎ\u17D2\u200D。≠\u200D\u200C; ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [] # ⅎ្.≠ +xn--u4e319b.xn--1ch; Ⅎ\u17D2.≠; [V7]; xn--u4e319b.xn--1ch; ; ; # Ⅎ្.≠ +xn--u4e823bcza.xn--0ugb89o; Ⅎ\u17D2\u200D.≠\u200D\u200C; [C1, C2, V7]; xn--u4e823bcza.xn--0ugb89o; ; ; # Ⅎ្.≠ +𐋺\uAAF6\uA953󧦉.\u200C\u1714\u068F; 𐋺\uAAF6\uA953󧦉.\u200C\u1714\u068F; [B1, C1, V7]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; xn--3j9a14ak27osbz2o.xn--ljb175f; [B1, V6, V7] # 𐋺꫶꥓.᜔ڏ +𐋺\uAAF6\uA953󧦉.\u200C\u1714\u068F; ; [B1, C1, V7]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; xn--3j9a14ak27osbz2o.xn--ljb175f; [B1, V6, V7] # 𐋺꫶꥓.᜔ڏ +xn--3j9a14ak27osbz2o.xn--ljb175f; 𐋺\uAAF6\uA953󧦉.\u1714\u068F; [B1, V6, V7]; xn--3j9a14ak27osbz2o.xn--ljb175f; ; ; # 𐋺꫶꥓.᜔ڏ +xn--3j9a14ak27osbz2o.xn--ljb175f1wg; 𐋺\uAAF6\uA953󧦉.\u200C\u1714\u068F; [B1, C1, V7]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; ; # 𐋺꫶꥓.᜔ڏ +񺔯\u0FA8.≯; 񺔯\u0FA8.≯; [V7]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯ +񺔯\u0FA8.>\u0338; 񺔯\u0FA8.≯; [V7]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯ +񺔯\u0FA8.≯; ; [V7]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯ +񺔯\u0FA8.>\u0338; 񺔯\u0FA8.≯; [V7]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯ +xn--4fd57150h.xn--hdh; 񺔯\u0FA8.≯; [V7]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯ +\u200D𞡄Ⴓ.𐇽; \u200D𞡄ⴓ.𐇽; [B1, C2, V6]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, V6] # 𞡄ⴓ.𐇽 +\u200D𞡄Ⴓ.𐇽; \u200D𞡄ⴓ.𐇽; [B1, C2, V6]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, V6] # 𞡄ⴓ.𐇽 +\u200D𞡄ⴓ.𐇽; ; [B1, C2, V6]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, V6] # 𞡄ⴓ.𐇽 +xn--blj7492l.xn--m27c; 𞡄ⴓ.𐇽; [B1, B2, B3, V6]; xn--blj7492l.xn--m27c; ; ; # 𞡄ⴓ.𐇽 +xn--1ugz52c4i16a.xn--m27c; \u200D𞡄ⴓ.𐇽; [B1, C2, V6]; xn--1ugz52c4i16a.xn--m27c; ; ; # 𞡄ⴓ.𐇽 +\u200D𞡄ⴓ.𐇽; \u200D𞡄ⴓ.𐇽; [B1, C2, V6]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, V6] # 𞡄ⴓ.𐇽 +xn--rnd5552v.xn--m27c; 𞡄Ⴓ.𐇽; [B1, B2, B3, V6, V7]; xn--rnd5552v.xn--m27c; ; ; # 𞡄Ⴓ.𐇽 +xn--rnd379ex885a.xn--m27c; \u200D𞡄Ⴓ.𐇽; [B1, C2, V6, V7]; xn--rnd379ex885a.xn--m27c; ; ; # 𞡄Ⴓ.𐇽 +𐪒ß\uA8EA.ᡤ; 𐪒ß\uA8EA.ᡤ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; xn--ss-tu9hw933a.xn--08e; # 𐪒ß꣪.ᡤ +𐪒ß\uA8EA.ᡤ; ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; xn--ss-tu9hw933a.xn--08e; # 𐪒ß꣪.ᡤ +𐪒SS\uA8EA.ᡤ; 𐪒ss\uA8EA.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +𐪒ss\uA8EA.ᡤ; ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +xn--ss-tu9hw933a.xn--08e; 𐪒ss\uA8EA.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +xn--zca2517f2hvc.xn--08e; 𐪒ß\uA8EA.ᡤ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; ; # 𐪒ß꣪.ᡤ +𐪒SS\uA8EA.ᡤ; 𐪒ss\uA8EA.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +𐪒ss\uA8EA.ᡤ; 𐪒ss\uA8EA.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +𐪒Ss\uA8EA.ᡤ; 𐪒ss\uA8EA.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +𐪒Ss\uA8EA.ᡤ; 𐪒ss\uA8EA.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ +𐨿󠆌鸮𑚶.ς; 𐨿鸮𑚶.ς; [V6]; xn--l76a726rt2h.xn--3xa; ; xn--l76a726rt2h.xn--4xa; # 𐨿鸮𑚶.ς +𐨿󠆌鸮𑚶.Σ; 𐨿鸮𑚶.σ; [V6]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ +𐨿󠆌鸮𑚶.σ; 𐨿鸮𑚶.σ; [V6]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ +xn--l76a726rt2h.xn--4xa; 𐨿鸮𑚶.σ; [V6]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ +xn--l76a726rt2h.xn--3xa; 𐨿鸮𑚶.ς; [V6]; xn--l76a726rt2h.xn--3xa; ; ; # 𐨿鸮𑚶.ς +⒗𞤬。-𑚶; ⒗𞤬.-𑚶; [B1, V3, V7]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶 +16.𞤬。-𑚶; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶 +16.𞤊。-𑚶; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶 +16.xn--ke6h.xn----4j0j; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶 +⒗𞤊。-𑚶; ⒗𞤬.-𑚶; [B1, V3, V7]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶 +xn--8shw466n.xn----4j0j; ⒗𞤬.-𑚶; [B1, V3, V7]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶 +\u08B3𞤿⾫。𐹣\u068F⒈; \u08B3𞤿隹.𐹣\u068F⒈; [B1, B2, B3, V7]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈ +\u08B3𞤿隹。𐹣\u068F1.; \u08B3𞤿隹.𐹣\u068F1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; [B1, B2, B3, A4_2]; ; # ࢳ𞤿隹.𐹣ڏ1. +\u08B3𞤝隹。𐹣\u068F1.; \u08B3𞤿隹.𐹣\u068F1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; [B1, B2, B3, A4_2]; ; # ࢳ𞤿隹.𐹣ڏ1. +xn--8yb0383efiwk.xn--1-wsc3373r.; \u08B3𞤿隹.𐹣\u068F1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; [B1, B2, B3, A4_2]; ; # ࢳ𞤿隹.𐹣ڏ1. +\u08B3𞤝⾫。𐹣\u068F⒈; \u08B3𞤿隹.𐹣\u068F⒈; [B1, B2, B3, V7]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈ +xn--8yb0383efiwk.xn--ljb064mol4n; \u08B3𞤿隹.𐹣\u068F⒈; [B1, B2, B3, V7]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈ +\u2433𚎛𝟧\u0661.ᡢ8\u0F72\u0600; \u2433𚎛5\u0661.ᡢ8\u0F72\u0600; [B5, B6, V7]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི +\u2433𚎛5\u0661.ᡢ8\u0F72\u0600; ; [B5, B6, V7]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི +xn--5-bqc410un435a.xn--8-rkc763epjj; \u2433𚎛5\u0661.ᡢ8\u0F72\u0600; [B5, B6, V7]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི +𐹠.🄀⒒-󨰈; ; [B1, V7]; xn--7n0d.xn----xcp9757q1s13g; ; ; # 𐹠.🄀⒒- +𐹠.0.11.-󨰈; ; [B1, V3, V7]; xn--7n0d.0.11.xn----8j07m; ; ; # 𐹠.0.11.- +xn--7n0d.0.11.xn----8j07m; 𐹠.0.11.-󨰈; [B1, V3, V7]; xn--7n0d.0.11.xn----8j07m; ; ; # 𐹠.0.11.- +xn--7n0d.xn----xcp9757q1s13g; 𐹠.🄀⒒-󨰈; [B1, V7]; xn--7n0d.xn----xcp9757q1s13g; ; ; # 𐹠.🄀⒒- +ς-。\u200C𝟭-; ς-.\u200C1-; [C1, V3]; xn----xmb.xn--1--i1t; ; xn----zmb.1-; [V3] # ς-.1- +ς-。\u200C1-; ς-.\u200C1-; [C1, V3]; xn----xmb.xn--1--i1t; ; xn----zmb.1-; [V3] # ς-.1- +Σ-。\u200C1-; σ-.\u200C1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1- +σ-。\u200C1-; σ-.\u200C1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1- +xn----zmb.1-; σ-.1-; [V3]; xn----zmb.1-; ; ; # σ-.1- +xn----zmb.xn--1--i1t; σ-.\u200C1-; [C1, V3]; xn----zmb.xn--1--i1t; ; ; # σ-.1- +xn----xmb.xn--1--i1t; ς-.\u200C1-; [C1, V3]; xn----xmb.xn--1--i1t; ; ; # ς-.1- +Σ-。\u200C𝟭-; σ-.\u200C1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1- +σ-。\u200C𝟭-; σ-.\u200C1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1- +\u1734-\u0CE2.󠄩Ⴄ; \u1734-\u0CE2.ⴄ; [V6]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ +\u1734-\u0CE2.󠄩Ⴄ; \u1734-\u0CE2.ⴄ; [V6]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ +\u1734-\u0CE2.󠄩ⴄ; \u1734-\u0CE2.ⴄ; [V6]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ +xn----ggf830f.xn--vkj; \u1734-\u0CE2.ⴄ; [V6]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ +\u1734-\u0CE2.󠄩ⴄ; \u1734-\u0CE2.ⴄ; [V6]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ +xn----ggf830f.xn--cnd; \u1734-\u0CE2.Ⴄ; [V6, V7]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ +򭈗♋\u06BB𐦥。\u0954⒈; 򭈗♋\u06BB𐦥.\u0954⒈; [B1, B5, B6, V6, V7]; xn--ukb372n129m3rs7f.xn--u3b240l; ; ; # ♋ڻ𐦥.॔⒈ +򭈗♋\u06BB𐦥。\u09541.; 򭈗♋\u06BB𐦥.\u09541.; [B1, B5, B6, V6, V7]; xn--ukb372n129m3rs7f.xn--1-fyd.; [B1, B5, B6, V6, V7, A4_2]; ; # ♋ڻ𐦥.॔1. +xn--ukb372n129m3rs7f.xn--1-fyd.; 򭈗♋\u06BB𐦥.\u09541.; [B1, B5, B6, V6, V7]; xn--ukb372n129m3rs7f.xn--1-fyd.; [B1, B5, B6, V6, V7, A4_2]; ; # ♋ڻ𐦥.॔1. +xn--ukb372n129m3rs7f.xn--u3b240l; 򭈗♋\u06BB𐦥.\u0954⒈; [B1, B5, B6, V6, V7]; xn--ukb372n129m3rs7f.xn--u3b240l; ; ; # ♋ڻ𐦥.॔⒈ +\u05A4.\u06C1\u1AB3\u200C; \u05A4.\u06C1\u1AB3\u200C; [B1, B3, C1, V6]; xn--vcb.xn--0kb623hm1d; ; xn--vcb.xn--0kb623h; [B1, V6] # ֤.ہ᪳ +\u05A4.\u06C1\u1AB3\u200C; ; [B1, B3, C1, V6]; xn--vcb.xn--0kb623hm1d; ; xn--vcb.xn--0kb623h; [B1, V6] # ֤.ہ᪳ +xn--vcb.xn--0kb623h; \u05A4.\u06C1\u1AB3; [B1, V6]; xn--vcb.xn--0kb623h; ; ; # ֤.ہ᪳ +xn--vcb.xn--0kb623hm1d; \u05A4.\u06C1\u1AB3\u200C; [B1, B3, C1, V6]; xn--vcb.xn--0kb623hm1d; ; ; # ֤.ہ᪳ +񢭏\u0846≮\u0ACD.𞦊; 񢭏\u0846≮\u0ACD.𞦊; [B5, B6, V7]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્. +񢭏\u0846<\u0338\u0ACD.𞦊; 񢭏\u0846≮\u0ACD.𞦊; [B5, B6, V7]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્. +񢭏\u0846≮\u0ACD.𞦊; ; [B5, B6, V7]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્. +񢭏\u0846<\u0338\u0ACD.𞦊; 񢭏\u0846≮\u0ACD.𞦊; [B5, B6, V7]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્. +xn--4vb80kq29ayo62l.xn--8g6h; 񢭏\u0846≮\u0ACD.𞦊; [B5, B6, V7]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્. +\u200D。𞀘⒈ꡍ擉; \u200D.𞀘⒈ꡍ擉; [C2, V6, V7]; xn--1ug.xn--tsh026uql4bew9p; ; .xn--tsh026uql4bew9p; [V6, V7, A4_2] # .𞀘⒈ꡍ擉 +\u200D。𞀘1.ꡍ擉; \u200D.𞀘1.ꡍ擉; [C2, V6]; xn--1ug.xn--1-1p4r.xn--s7uv61m; ; .xn--1-1p4r.xn--s7uv61m; [V6, A4_2] # .𞀘1.ꡍ擉 +.xn--1-1p4r.xn--s7uv61m; .𞀘1.ꡍ擉; [V6, X4_2]; .xn--1-1p4r.xn--s7uv61m; [V6, A4_2]; ; # .𞀘1.ꡍ擉 +xn--1ug.xn--1-1p4r.xn--s7uv61m; \u200D.𞀘1.ꡍ擉; [C2, V6]; xn--1ug.xn--1-1p4r.xn--s7uv61m; ; ; # .𞀘1.ꡍ擉 +.xn--tsh026uql4bew9p; .𞀘⒈ꡍ擉; [V6, V7, X4_2]; .xn--tsh026uql4bew9p; [V6, V7, A4_2]; ; # .𞀘⒈ꡍ擉 +xn--1ug.xn--tsh026uql4bew9p; \u200D.𞀘⒈ꡍ擉; [C2, V6, V7]; xn--1ug.xn--tsh026uql4bew9p; ; ; # .𞀘⒈ꡍ擉 +₈\u07CB.\uFB64≠; 8\u07CB.\u067F≠; [B1, B3]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠ +₈\u07CB.\uFB64=\u0338; 8\u07CB.\u067F≠; [B1, B3]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠ +8\u07CB.\u067F≠; ; [B1, B3]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠ +8\u07CB.\u067F=\u0338; 8\u07CB.\u067F≠; [B1, B3]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠ +xn--8-zbd.xn--4ib883l; 8\u07CB.\u067F≠; [B1, B3]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠ +ᢡ\u07DE򹐣.⒒\u0642𑍦; ; [B1, B5, V7]; xn--5sb596fi873t.xn--ehb336mvy7n; ; ; # ᢡߞ.⒒ق𑍦 +ᢡ\u07DE򹐣.11.\u0642𑍦; ; [B1, B5, V7]; xn--5sb596fi873t.11.xn--ehb4198k; ; ; # ᢡߞ.11.ق𑍦 +xn--5sb596fi873t.11.xn--ehb4198k; ᢡ\u07DE򹐣.11.\u0642𑍦; [B1, B5, V7]; xn--5sb596fi873t.11.xn--ehb4198k; ; ; # ᢡߞ.11.ق𑍦 +xn--5sb596fi873t.xn--ehb336mvy7n; ᢡ\u07DE򹐣.⒒\u0642𑍦; [B1, B5, V7]; xn--5sb596fi873t.xn--ehb336mvy7n; ; ; # ᢡߞ.⒒ق𑍦 +\u0E48-𐹺𝟜.\u0363\u06E1⒏; \u0E48-𐹺4.\u0363\u06E1⒏; [B1, V6, V7]; xn---4-owiz479s.xn--eva20pjv9a; ; ; # ่-𐹺4.ͣۡ⒏ +\u0E48-𐹺4.\u0363\u06E18.; ; [B1, V6]; xn---4-owiz479s.xn--8-ihb69x.; [B1, V6, A4_2]; ; # ่-𐹺4.ͣۡ8. +xn---4-owiz479s.xn--8-ihb69x.; \u0E48-𐹺4.\u0363\u06E18.; [B1, V6]; xn---4-owiz479s.xn--8-ihb69x.; [B1, V6, A4_2]; ; # ่-𐹺4.ͣۡ8. +xn---4-owiz479s.xn--eva20pjv9a; \u0E48-𐹺4.\u0363\u06E1⒏; [B1, V6, V7]; xn---4-owiz479s.xn--eva20pjv9a; ; ; # ่-𐹺4.ͣۡ⒏ +⫐。Ⴠ-󃐢; ⫐.ⴠ-󃐢; [V7]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ- +⫐。Ⴠ-󃐢; ⫐.ⴠ-󃐢; [V7]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ- +⫐。ⴠ-󃐢; ⫐.ⴠ-󃐢; [V7]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ- +xn--r3i.xn----2wst7439i; ⫐.ⴠ-󃐢; [V7]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ- +⫐。ⴠ-󃐢; ⫐.ⴠ-󃐢; [V7]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ- +xn--r3i.xn----z1g58579u; ⫐.Ⴠ-󃐢; [V7]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ- +𑑂◊.⦟∠; 𑑂◊.⦟∠; [V6]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠ +𑑂◊.⦟∠; ; [V6]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠ +xn--01h3338f.xn--79g270a; 𑑂◊.⦟∠; [V6]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠ +𿌰-\u0662。󋸛ꡂ; 𿌰-\u0662.󋸛ꡂ; [B5, B6, V7]; xn----dqc20828e.xn--bc9an2879c; ; ; # -٢.ꡂ +xn----dqc20828e.xn--bc9an2879c; 𿌰-\u0662.󋸛ꡂ; [B5, B6, V7]; xn----dqc20828e.xn--bc9an2879c; ; ; # -٢.ꡂ +\u0678。󠏬\u0741𞪭𐹪; \u064A\u0674.󠏬\u0741𞪭𐹪; [B1, V7]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪 +\u064A\u0674。󠏬\u0741𞪭𐹪; \u064A\u0674.󠏬\u0741𞪭𐹪; [B1, V7]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪 +xn--mhb8f.xn--oob2585kfdsfsbo7h; \u064A\u0674.󠏬\u0741𞪭𐹪; [B1, V7]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪 +𐫆ꌄ。\u200Dᣬ; 𐫆ꌄ.\u200Dᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; xn--y77ao18q.xn--wdf; [B2, B3] # 𐫆ꌄ.ᣬ +𐫆ꌄ。\u200Dᣬ; 𐫆ꌄ.\u200Dᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; xn--y77ao18q.xn--wdf; [B2, B3] # 𐫆ꌄ.ᣬ +xn--y77ao18q.xn--wdf; 𐫆ꌄ.ᣬ; [B2, B3]; xn--y77ao18q.xn--wdf; ; ; # 𐫆ꌄ.ᣬ +xn--y77ao18q.xn--wdf367a; 𐫆ꌄ.\u200Dᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; ; # 𐫆ꌄ.ᣬ +₀\u0662。󅪞≯-; 0\u0662.󅪞≯-; [B1, B6, V3, V7]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯- +₀\u0662。󅪞>\u0338-; 0\u0662.󅪞≯-; [B1, B6, V3, V7]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯- +0\u0662。󅪞≯-; 0\u0662.󅪞≯-; [B1, B6, V3, V7]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯- +0\u0662。󅪞>\u0338-; 0\u0662.󅪞≯-; [B1, B6, V3, V7]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯- +xn--0-dqc.xn----ogov3342l; 0\u0662.󅪞≯-; [B1, B6, V3, V7]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯- +\u031C𐹫-𞯃.𐋤\u0845; ; [B1, V6, V7]; xn----gdb7046r692g.xn--3vb1349j; ; ; # ̜𐹫-.𐋤ࡅ +xn----gdb7046r692g.xn--3vb1349j; \u031C𐹫-𞯃.𐋤\u0845; [B1, V6, V7]; xn----gdb7046r692g.xn--3vb1349j; ; ; # ̜𐹫-.𐋤ࡅ +≠。𝩑𐹩Ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +=\u0338。𝩑𐹩Ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +≠。𝩑𐹩Ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +=\u0338。𝩑𐹩Ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +=\u0338。𝩑𐹩ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +≠。𝩑𐹩ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +xn--1ch.xn--fcb363rk03mypug; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +=\u0338。𝩑𐹩ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +≠。𝩑𐹩ⴡ\u0594; ≠.𝩑𐹩ⴡ\u0594; [B1, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔ +xn--1ch.xn--fcb538c649rypog; ≠.𝩑𐹩Ⴡ\u0594; [B1, V6, V7]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔ +𖫳≠.Ⴀ𐮀; 𖫳≠.ⴀ𐮀; [B1, B5, B6, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀 +𖫳=\u0338.Ⴀ𐮀; 𖫳≠.ⴀ𐮀; [B1, B5, B6, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀 +𖫳=\u0338.ⴀ𐮀; 𖫳≠.ⴀ𐮀; [B1, B5, B6, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀 +𖫳≠.ⴀ𐮀; ; [B1, B5, B6, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀 +xn--1ch9250k.xn--rkj6232e; 𖫳≠.ⴀ𐮀; [B1, B5, B6, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀 +xn--1ch9250k.xn--7md2659j; 𖫳≠.Ⴀ𐮀; [B1, B5, B6, V6, V7]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀 +󠅾\u0736\u0726.ᢚ閪\u08E2𝩟; \u0736\u0726.ᢚ閪\u08E2𝩟; [B1, B5, B6, V6, V7]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟 +󠅾\u0736\u0726.ᢚ閪\u08E2𝩟; \u0736\u0726.ᢚ閪\u08E2𝩟; [B1, B5, B6, V6, V7]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟 +xn--wnb5a.xn--l0b161fis8gbp5m; \u0736\u0726.ᢚ閪\u08E2𝩟; [B1, B5, B6, V6, V7]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟 +\u200D󠇜\u06CB\uA8E9。\u20DD\u0FB0-ᛟ; \u200D\u06CB\uA8E9.\u20DD\u0FB0-ᛟ; [B1, C2, V6]; xn--blb540ke10h.xn----gmg236cj6k; ; xn--blb8114f.xn----gmg236cj6k; [B1, V6] # ۋ꣩.⃝ྰ-ᛟ +\u200D󠇜\u06CB\uA8E9。\u20DD\u0FB0-ᛟ; \u200D\u06CB\uA8E9.\u20DD\u0FB0-ᛟ; [B1, C2, V6]; xn--blb540ke10h.xn----gmg236cj6k; ; xn--blb8114f.xn----gmg236cj6k; [B1, V6] # ۋ꣩.⃝ྰ-ᛟ +xn--blb8114f.xn----gmg236cj6k; \u06CB\uA8E9.\u20DD\u0FB0-ᛟ; [B1, V6]; xn--blb8114f.xn----gmg236cj6k; ; ; # ۋ꣩.⃝ྰ-ᛟ +xn--blb540ke10h.xn----gmg236cj6k; \u200D\u06CB\uA8E9.\u20DD\u0FB0-ᛟ; [B1, C2, V6]; xn--blb540ke10h.xn----gmg236cj6k; ; ; # ۋ꣩.⃝ྰ-ᛟ +헁󘖙\u0E3A󚍚。\u06BA𝟜; 헁󘖙\u0E3A󚍚.\u06BA4; [V7]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4 +헁󘖙\u0E3A󚍚。\u06BA𝟜; 헁󘖙\u0E3A󚍚.\u06BA4; [V7]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4 +헁󘖙\u0E3A󚍚。\u06BA4; 헁󘖙\u0E3A󚍚.\u06BA4; [V7]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4 +헁󘖙\u0E3A󚍚。\u06BA4; 헁󘖙\u0E3A󚍚.\u06BA4; [V7]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4 +xn--o4c1723h8g85gt4ya.xn--4-dvc; 헁󘖙\u0E3A󚍚.\u06BA4; [V7]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4 +𐹭。󃱂\u200CႾ; 𐹭.󃱂\u200Cⴞ; [B1, C1, V7]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, V7] # 𐹭.ⴞ +𐹭。󃱂\u200CႾ; 𐹭.󃱂\u200Cⴞ; [B1, C1, V7]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, V7] # 𐹭.ⴞ +𐹭。󃱂\u200Cⴞ; 𐹭.󃱂\u200Cⴞ; [B1, C1, V7]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, V7] # 𐹭.ⴞ +xn--lo0d.xn--mljx1099g; 𐹭.󃱂ⴞ; [B1, V7]; xn--lo0d.xn--mljx1099g; ; ; # 𐹭.ⴞ +xn--lo0d.xn--0ugx72cwi33v; 𐹭.󃱂\u200Cⴞ; [B1, C1, V7]; xn--lo0d.xn--0ugx72cwi33v; ; ; # 𐹭.ⴞ +𐹭。󃱂\u200Cⴞ; 𐹭.󃱂\u200Cⴞ; [B1, C1, V7]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, V7] # 𐹭.ⴞ +xn--lo0d.xn--2nd75260n; 𐹭.󃱂Ⴞ; [B1, V7]; xn--lo0d.xn--2nd75260n; ; ; # 𐹭.Ⴞ +xn--lo0d.xn--2nd949eqw95u; 𐹭.󃱂\u200CႾ; [B1, C1, V7]; xn--lo0d.xn--2nd949eqw95u; ; ; # 𐹭.Ⴞ +\uA953.\u033D𑂽馋; ; [V6, V7]; xn--3j9a.xn--bua0708eqzrd; ; ; # ꥓.̽馋 +xn--3j9a.xn--bua0708eqzrd; \uA953.\u033D𑂽馋; [V6, V7]; xn--3j9a.xn--bua0708eqzrd; ; ; # ꥓.̽馋 +󈫝򪛸\u200D。䜖; 󈫝򪛸\u200D.䜖; [C2, V7]; xn--1ug30527h9mxi.xn--k0o; ; xn--g138cxw05a.xn--k0o; [V7] # .䜖 +󈫝򪛸\u200D。䜖; 󈫝򪛸\u200D.䜖; [C2, V7]; xn--1ug30527h9mxi.xn--k0o; ; xn--g138cxw05a.xn--k0o; [V7] # .䜖 +xn--g138cxw05a.xn--k0o; 󈫝򪛸.䜖; [V7]; xn--g138cxw05a.xn--k0o; ; ; # .䜖 +xn--1ug30527h9mxi.xn--k0o; 󈫝򪛸\u200D.䜖; [C2, V7]; xn--1ug30527h9mxi.xn--k0o; ; ; # .䜖 +ᡯ⚉姶🄉.۷\u200D🎪\u200D; ᡯ⚉姶8,.۷\u200D🎪\u200D; [C2, U1]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; xn--8,-g9oy26fzu4d.xn--kmb6733w; [U1] # ᡯ⚉姶8,.۷🎪 +ᡯ⚉姶8,.۷\u200D🎪\u200D; ; [C2, U1]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; xn--8,-g9oy26fzu4d.xn--kmb6733w; [U1] # ᡯ⚉姶8,.۷🎪 +xn--8,-g9oy26fzu4d.xn--kmb6733w; ᡯ⚉姶8,.۷🎪; [U1]; xn--8,-g9oy26fzu4d.xn--kmb6733w; ; ; # ᡯ⚉姶8,.۷🎪 +xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ᡯ⚉姶8,.۷\u200D🎪\u200D; [C2, U1]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; ; # ᡯ⚉姶8,.۷🎪 +xn--c9e433epi4b3j20a.xn--kmb6733w; ᡯ⚉姶🄉.۷🎪; [V7]; xn--c9e433epi4b3j20a.xn--kmb6733w; ; ; # ᡯ⚉姶🄉.۷🎪 +xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ᡯ⚉姶🄉.۷\u200D🎪\u200D; [C2, V7]; xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ; ; # ᡯ⚉姶🄉.۷🎪 +𞽀.𐹸🚖\u0E3A; ; [B1, V7]; xn--0n7h.xn--o4c9032klszf; ; ; # .𐹸🚖ฺ +xn--0n7h.xn--o4c9032klszf; 𞽀.𐹸🚖\u0E3A; [B1, V7]; xn--0n7h.xn--o4c9032klszf; ; ; # .𐹸🚖ฺ +Ⴔᠵ。𐹧\u0747۹; ⴔᠵ.𐹧\u0747۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹ +Ⴔᠵ。𐹧\u0747۹; ⴔᠵ.𐹧\u0747۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹ +ⴔᠵ。𐹧\u0747۹; ⴔᠵ.𐹧\u0747۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹ +xn--o7e997h.xn--mmb9ml895e; ⴔᠵ.𐹧\u0747۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹ +ⴔᠵ。𐹧\u0747۹; ⴔᠵ.𐹧\u0747۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹ +xn--snd659a.xn--mmb9ml895e; Ⴔᠵ.𐹧\u0747۹; [B1, V7]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹ +\u135Fᡈ\u200C.︒-𖾐-; \u135Fᡈ\u200C.︒-𖾐-; [C1, V3, V6, V7]; xn--b7d82wo4h.xn-----c82nz547a; ; xn--b7d82w.xn-----c82nz547a; [V3, V6, V7] # ፟ᡈ.︒-𖾐- +\u135Fᡈ\u200C.。-𖾐-; \u135Fᡈ\u200C..-𖾐-; [C1, V3, V6, X4_2]; xn--b7d82wo4h..xn-----pe4u; [C1, V3, V6, A4_2]; xn--b7d82w..xn-----pe4u; [V3, V6, A4_2] # ፟ᡈ..-𖾐- +xn--b7d82w..xn-----pe4u; \u135Fᡈ..-𖾐-; [V3, V6, X4_2]; xn--b7d82w..xn-----pe4u; [V3, V6, A4_2]; ; # ፟ᡈ..-𖾐- +xn--b7d82wo4h..xn-----pe4u; \u135Fᡈ\u200C..-𖾐-; [C1, V3, V6, X4_2]; xn--b7d82wo4h..xn-----pe4u; [C1, V3, V6, A4_2]; ; # ፟ᡈ..-𖾐- +xn--b7d82w.xn-----c82nz547a; \u135Fᡈ.︒-𖾐-; [V3, V6, V7]; xn--b7d82w.xn-----c82nz547a; ; ; # ፟ᡈ.︒-𖾐- +xn--b7d82wo4h.xn-----c82nz547a; \u135Fᡈ\u200C.︒-𖾐-; [C1, V3, V6, V7]; xn--b7d82wo4h.xn-----c82nz547a; ; ; # ፟ᡈ.︒-𖾐- +⒈\u0601⒖\u200C.\u1DF0\u07DB; ; [B1, C1, V6, V7]; xn--jfb844kmfdwb.xn--2sb914i; ; xn--jfb347mib.xn--2sb914i; [B1, V6, V7] # ⒈⒖.ᷰߛ +1.\u060115.\u200C.\u1DF0\u07DB; ; [B1, C1, V6, V7]; 1.xn--15-1pd.xn--0ug.xn--2sb914i; ; 1.xn--15-1pd..xn--2sb914i; [B1, V6, V7, A4_2] # 1.15..ᷰߛ +1.xn--15-1pd..xn--2sb914i; 1.\u060115..\u1DF0\u07DB; [B1, V6, V7, X4_2]; 1.xn--15-1pd..xn--2sb914i; [B1, V6, V7, A4_2]; ; # 1.15..ᷰߛ +1.xn--15-1pd.xn--0ug.xn--2sb914i; 1.\u060115.\u200C.\u1DF0\u07DB; [B1, C1, V6, V7]; 1.xn--15-1pd.xn--0ug.xn--2sb914i; ; ; # 1.15..ᷰߛ +xn--jfb347mib.xn--2sb914i; ⒈\u0601⒖.\u1DF0\u07DB; [B1, V6, V7]; xn--jfb347mib.xn--2sb914i; ; ; # ⒈⒖.ᷰߛ +xn--jfb844kmfdwb.xn--2sb914i; ⒈\u0601⒖\u200C.\u1DF0\u07DB; [B1, C1, V6, V7]; xn--jfb844kmfdwb.xn--2sb914i; ; ; # ⒈⒖.ᷰߛ +𝩜。-\u0B4DႫ; 𝩜.-\u0B4Dⴋ; [V3, V6]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ +𝩜。-\u0B4Dⴋ; 𝩜.-\u0B4Dⴋ; [V3, V6]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ +xn--792h.xn----bse820x; 𝩜.-\u0B4Dⴋ; [V3, V6]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ +xn--792h.xn----bse632b; 𝩜.-\u0B4DႫ; [V3, V6, V7]; xn--792h.xn----bse632b; ; ; # 𝩜.-୍Ⴋ +ßჀ.\u0620刯Ⴝ; ßⴠ.\u0620刯ⴝ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; xn--ss-j81a.xn--fgb670rovy; # ßⴠ.ؠ刯ⴝ +ßⴠ.\u0620刯ⴝ; ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; xn--ss-j81a.xn--fgb670rovy; # ßⴠ.ؠ刯ⴝ +SSჀ.\u0620刯Ⴝ; ssⴠ.\u0620刯ⴝ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ +ssⴠ.\u0620刯ⴝ; ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ +Ssⴠ.\u0620刯Ⴝ; ssⴠ.\u0620刯ⴝ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ +xn--ss-j81a.xn--fgb670rovy; ssⴠ.\u0620刯ⴝ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ +xn--zca277t.xn--fgb670rovy; ßⴠ.\u0620刯ⴝ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; ; # ßⴠ.ؠ刯ⴝ +xn--ss-j81a.xn--fgb845cb66c; ssⴠ.\u0620刯Ⴝ; [B2, B3, V7]; xn--ss-j81a.xn--fgb845cb66c; ; ; # ssⴠ.ؠ刯Ⴝ +xn--ss-wgk.xn--fgb845cb66c; ssჀ.\u0620刯Ⴝ; [B2, B3, V7]; xn--ss-wgk.xn--fgb845cb66c; ; ; # ssჀ.ؠ刯Ⴝ +xn--zca442f.xn--fgb845cb66c; ßჀ.\u0620刯Ⴝ; [B2, B3, V7]; xn--zca442f.xn--fgb845cb66c; ; ; # ßჀ.ؠ刯Ⴝ +\u1BAAႣℲ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣℲ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣℲ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣℲ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAⴃⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAⴃⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +xn--yxf24x4ol.xn--sib102gc69k; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAⴃⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAⴃⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +\u1BAAႣⅎ。ᠳ툻\u0673; \u1BAAⴃⅎ.ᠳ툻\u0673; [B5, B6, V6]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ +xn--bnd957c2pe.xn--sib102gc69k; \u1BAAႣⅎ.ᠳ툻\u0673; [B5, B6, V6, V7]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ +xn--bnd957cone.xn--sib102gc69k; \u1BAAႣℲ.ᠳ툻\u0673; [B5, B6, V6, V7]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ +\u06EC.\u08A2𐹫\u067C; ; [B1, V6]; xn--8lb.xn--1ib31ily45b; ; ; # ۬.ࢢ𐹫ټ +xn--8lb.xn--1ib31ily45b; \u06EC.\u08A2𐹫\u067C; [B1, V6]; xn--8lb.xn--1ib31ily45b; ; ; # ۬.ࢢ𐹫ټ +\u06B6\u06DF。₇\uA806; \u06B6\u06DF.7\uA806; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆ +\u06B6\u06DF。7\uA806; \u06B6\u06DF.7\uA806; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆ +xn--pkb6f.xn--7-x93e; \u06B6\u06DF.7\uA806; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆ +\u06B6\u06DF.7\uA806; ; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆ +Ⴣ𐹻.\u200C𝪣≮󠩉; ⴣ𐹻.\u200C𝪣≮󠩉; [B1, B5, B6, C1, V7]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, V6, V7] # ⴣ𐹻.𝪣≮ +Ⴣ𐹻.\u200C𝪣<\u0338󠩉; ⴣ𐹻.\u200C𝪣≮󠩉; [B1, B5, B6, C1, V7]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, V6, V7] # ⴣ𐹻.𝪣≮ +ⴣ𐹻.\u200C𝪣<\u0338󠩉; ⴣ𐹻.\u200C𝪣≮󠩉; [B1, B5, B6, C1, V7]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, V6, V7] # ⴣ𐹻.𝪣≮ +ⴣ𐹻.\u200C𝪣≮󠩉; ; [B1, B5, B6, C1, V7]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, V6, V7] # ⴣ𐹻.𝪣≮ +xn--rlj6323e.xn--gdh4944ob3x3e; ⴣ𐹻.𝪣≮󠩉; [B1, B5, B6, V6, V7]; xn--rlj6323e.xn--gdh4944ob3x3e; ; ; # ⴣ𐹻.𝪣≮ +xn--rlj6323e.xn--0ugy6gn120eb103g; ⴣ𐹻.\u200C𝪣≮󠩉; [B1, B5, B6, C1, V7]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; ; # ⴣ𐹻.𝪣≮ +xn--7nd8101k.xn--gdh4944ob3x3e; Ⴣ𐹻.𝪣≮󠩉; [B1, B5, B6, V6, V7]; xn--7nd8101k.xn--gdh4944ob3x3e; ; ; # Ⴣ𐹻.𝪣≮ +xn--7nd8101k.xn--0ugy6gn120eb103g; Ⴣ𐹻.\u200C𝪣≮󠩉; [B1, B5, B6, C1, V7]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; ; # Ⴣ𐹻.𝪣≮ +𝟵隁⯮.\u180D\u200C; 9隁⯮.\u200C; [C1]; xn--9-mfs8024b.xn--0ug; ; xn--9-mfs8024b.; [A4_2] # 9隁⯮. +9隁⯮.\u180D\u200C; 9隁⯮.\u200C; [C1]; xn--9-mfs8024b.xn--0ug; ; xn--9-mfs8024b.; [A4_2] # 9隁⯮. +xn--9-mfs8024b.; 9隁⯮.; ; xn--9-mfs8024b.; [A4_2]; ; # 9隁⯮. +9隁⯮.; ; ; xn--9-mfs8024b.; [A4_2]; ; # 9隁⯮. +xn--9-mfs8024b.xn--0ug; 9隁⯮.\u200C; [C1]; xn--9-mfs8024b.xn--0ug; ; ; # 9隁⯮. +⒏𐹧。Ⴣ\u0F84彦; ⒏𐹧.ⴣ\u0F84彦; [B1, V7]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦 +8.𐹧。Ⴣ\u0F84彦; 8.𐹧.ⴣ\u0F84彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦 +8.𐹧。ⴣ\u0F84彦; 8.𐹧.ⴣ\u0F84彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦 +8.xn--fo0d.xn--3ed972m6o8a; 8.𐹧.ⴣ\u0F84彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦 +⒏𐹧。ⴣ\u0F84彦; ⒏𐹧.ⴣ\u0F84彦; [B1, V7]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦 +xn--0sh2466f.xn--3ed972m6o8a; ⒏𐹧.ⴣ\u0F84彦; [B1, V7]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦 +8.xn--fo0d.xn--3ed15dt93o; 8.𐹧.Ⴣ\u0F84彦; [B1, V7]; 8.xn--fo0d.xn--3ed15dt93o; ; ; # 8.𐹧.Ⴣ྄彦 +xn--0sh2466f.xn--3ed15dt93o; ⒏𐹧.Ⴣ\u0F84彦; [B1, V7]; xn--0sh2466f.xn--3ed15dt93o; ; ; # ⒏𐹧.Ⴣ྄彦 +-问񬰔⒛。\u0604-񜗉橬; -问񬰔⒛.\u0604-񜗉橬; [B1, V3, V7]; xn----hdpu849bhis3e.xn----ykc7228efm46d; ; ; # -问⒛.-橬 +-问񬰔20.。\u0604-񜗉橬; -问񬰔20..\u0604-񜗉橬; [B1, V3, V7, X4_2]; xn---20-658jx1776d..xn----ykc7228efm46d; [B1, V3, V7, A4_2]; ; # -问20..-橬 +xn---20-658jx1776d..xn----ykc7228efm46d; -问񬰔20..\u0604-񜗉橬; [B1, V3, V7, X4_2]; xn---20-658jx1776d..xn----ykc7228efm46d; [B1, V3, V7, A4_2]; ; # -问20..-橬 +xn----hdpu849bhis3e.xn----ykc7228efm46d; -问񬰔⒛.\u0604-񜗉橬; [B1, V3, V7]; xn----hdpu849bhis3e.xn----ykc7228efm46d; ; ; # -问⒛.-橬 +\u1BACႬ\u200C\u0325。𝟸; \u1BACⴌ\u200C\u0325.2; [C1, V6]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V6] # ᮬⴌ̥.2 +\u1BACႬ\u200C\u0325。2; \u1BACⴌ\u200C\u0325.2; [C1, V6]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V6] # ᮬⴌ̥.2 +\u1BACⴌ\u200C\u0325。2; \u1BACⴌ\u200C\u0325.2; [C1, V6]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V6] # ᮬⴌ̥.2 +xn--mta176jjjm.c; \u1BACⴌ\u0325.c; [V6]; xn--mta176jjjm.c; ; ; # ᮬⴌ̥.c +xn--mta176j97cl2q.c; \u1BACⴌ\u200C\u0325.c; [C1, V6]; xn--mta176j97cl2q.c; ; ; # ᮬⴌ̥.c +\u1BACⴌ\u200C\u0325。𝟸; \u1BACⴌ\u200C\u0325.2; [C1, V6]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V6] # ᮬⴌ̥.2 +xn--mta930emri.c; \u1BACႬ\u0325.c; [V6, V7]; xn--mta930emri.c; ; ; # ᮬႬ̥.c +xn--mta930emribme.c; \u1BACႬ\u200C\u0325.c; [C1, V6, V7]; xn--mta930emribme.c; ; ; # ᮬႬ̥.c +?。\uA806\u0669󠒩; ?.\uA806\u0669󠒩; [B1, V6, V7, U1]; ?.xn--iib9583fusy0i; ; ; # ?.꠆٩ +?.xn--iib9583fusy0i; ?.\uA806\u0669󠒩; [B1, V6, V7, U1]; ?.xn--iib9583fusy0i; ; ; # ?.꠆٩ +󠄁\u035F⾶。₇︒눇≮; \u035F飛.7︒눇≮; [V6, V7]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮ +󠄁\u035F⾶。₇︒눇<\u0338; \u035F飛.7︒눇≮; [V6, V7]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮ +󠄁\u035F飛。7。눇≮; \u035F飛.7.눇≮; [V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮ +󠄁\u035F飛。7。눇<\u0338; \u035F飛.7.눇≮; [V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮ +xn--9ua0567e.7.xn--gdh6767c; \u035F飛.7.눇≮; [V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮ +xn--9ua0567e.xn--7-ngou006d1ttc; \u035F飛.7︒눇≮; [V6, V7]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮ +\u200C\uFE09𐹴\u200D.\u200C⿃; \u200C𐹴\u200D.\u200C鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; xn--so0d.xn--6x6a; [B1] # 𐹴.鳥 +\u200C\uFE09𐹴\u200D.\u200C鳥; \u200C𐹴\u200D.\u200C鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; xn--so0d.xn--6x6a; [B1] # 𐹴.鳥 +xn--so0d.xn--6x6a; 𐹴.鳥; [B1]; xn--so0d.xn--6x6a; ; ; # 𐹴.鳥 +xn--0ugc6024p.xn--0ug1920c; \u200C𐹴\u200D.\u200C鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; ; # 𐹴.鳥 +🍮.\u200D󠗒𐦁𝨝; 🍮.\u200D󠗒𐦁𝨝; [B1, C2, V7]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; xn--lj8h.xn--ln9ci476aqmr2g; [B1, V7] # 🍮.𐦁𝨝 +🍮.\u200D󠗒𐦁𝨝; ; [B1, C2, V7]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; xn--lj8h.xn--ln9ci476aqmr2g; [B1, V7] # 🍮.𐦁𝨝 +xn--lj8h.xn--ln9ci476aqmr2g; 🍮.󠗒𐦁𝨝; [B1, V7]; xn--lj8h.xn--ln9ci476aqmr2g; ; ; # 🍮.𐦁𝨝 +xn--lj8h.xn--1ug6603gr1pfwq37h; 🍮.\u200D󠗒𐦁𝨝; [B1, C2, V7]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; ; # 🍮.𐦁𝨝 +\u067D\u0943.𞤓\u200D; \u067D\u0943.𞤵\u200D; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; xn--2ib43l.xn--te6h; [] # ٽृ.𞤵 +\u067D\u0943.𞤵\u200D; ; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; xn--2ib43l.xn--te6h; [] # ٽृ.𞤵 +xn--2ib43l.xn--te6h; \u067D\u0943.𞤵; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵 +\u067D\u0943.𞤵; ; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵 +\u067D\u0943.𞤓; \u067D\u0943.𞤵; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵 +xn--2ib43l.xn--1ugy711p; \u067D\u0943.𞤵\u200D; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; ; # ٽृ.𞤵 +\u0664\u0A4D-.󥜽\u1039񦦐; \u0664\u0A4D-.󥜽\u1039񦦐; [B1, V3, V7]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္ +\u0664\u0A4D-.󥜽\u1039񦦐; ; [B1, V3, V7]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္ +xn----gqc711a.xn--9jd88234f3qm0b; \u0664\u0A4D-.󥜽\u1039񦦐; [B1, V3, V7]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္ +4\u103A-𐹸。\uAA29\u200C𐹴≮; 4\u103A-𐹸.\uAA29\u200C𐹴≮; [B1, C1, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, V6] # 4်-𐹸.ꨩ𐹴≮ +4\u103A-𐹸。\uAA29\u200C𐹴<\u0338; 4\u103A-𐹸.\uAA29\u200C𐹴≮; [B1, C1, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, V6] # 4်-𐹸.ꨩ𐹴≮ +4\u103A-𐹸。\uAA29\u200C𐹴≮; 4\u103A-𐹸.\uAA29\u200C𐹴≮; [B1, C1, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, V6] # 4်-𐹸.ꨩ𐹴≮ +4\u103A-𐹸。\uAA29\u200C𐹴<\u0338; 4\u103A-𐹸.\uAA29\u200C𐹴≮; [B1, C1, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, V6] # 4်-𐹸.ꨩ𐹴≮ +xn--4--e4j7831r.xn--gdh8754cz40c; 4\u103A-𐹸.\uAA29𐹴≮; [B1, V6]; xn--4--e4j7831r.xn--gdh8754cz40c; ; ; # 4်-𐹸.ꨩ𐹴≮ +xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; 4\u103A-𐹸.\uAA29\u200C𐹴≮; [B1, C1, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; ; # 4်-𐹸.ꨩ𐹴≮ +\u200C。\uFFA0\u0F84\u0F96; \u200C.\u0F84\u0F96; [C1, V6]; xn--0ug.xn--3ed0b; ; .xn--3ed0b; [V6, A4_2] # .྄ྖ +\u200C。\u1160\u0F84\u0F96; \u200C.\u0F84\u0F96; [C1, V6]; xn--0ug.xn--3ed0b; ; .xn--3ed0b; [V6, A4_2] # .྄ྖ +.xn--3ed0b; .\u0F84\u0F96; [V6, X4_2]; .xn--3ed0b; [V6, A4_2]; ; # .྄ྖ +xn--0ug.xn--3ed0b; \u200C.\u0F84\u0F96; [C1, V6]; xn--0ug.xn--3ed0b; ; ; # .྄ྖ +.xn--3ed0b20h; .\u1160\u0F84\u0F96; [V7, X4_2]; .xn--3ed0b20h; [V7, A4_2]; ; # .྄ྖ +xn--0ug.xn--3ed0b20h; \u200C.\u1160\u0F84\u0F96; [C1, V7]; xn--0ug.xn--3ed0b20h; ; ; # .྄ྖ +.xn--3ed0by082k; .\uFFA0\u0F84\u0F96; [V7, X4_2]; .xn--3ed0by082k; [V7, A4_2]; ; # .྄ྖ +xn--0ug.xn--3ed0by082k; \u200C.\uFFA0\u0F84\u0F96; [C1, V7]; xn--0ug.xn--3ed0by082k; ; ; # .྄ྖ +≯򍘅.\u200D𐅼򲇛; ≯򍘅.\u200D𐅼򲇛; [C2, V7]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [V7] # ≯.𐅼 +>\u0338򍘅.\u200D𐅼򲇛; ≯򍘅.\u200D𐅼򲇛; [C2, V7]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [V7] # ≯.𐅼 +≯򍘅.\u200D𐅼򲇛; ; [C2, V7]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [V7] # ≯.𐅼 +>\u0338򍘅.\u200D𐅼򲇛; ≯򍘅.\u200D𐅼򲇛; [C2, V7]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [V7] # ≯.𐅼 +xn--hdh84488f.xn--xy7cw2886b; ≯򍘅.𐅼򲇛; [V7]; xn--hdh84488f.xn--xy7cw2886b; ; ; # ≯.𐅼 +xn--hdh84488f.xn--1ug8099fbjp4e; ≯򍘅.\u200D𐅼򲇛; [C2, V7]; xn--hdh84488f.xn--1ug8099fbjp4e; ; ; # ≯.𐅼 +\u0641ß𐰯。𝟕𐫫; \u0641ß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; xn--ss-jvd2339x.xn--7-mm5i; # فß𐰯.7𐫫 +\u0641ß𐰯。7𐫫; \u0641ß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; xn--ss-jvd2339x.xn--7-mm5i; # فß𐰯.7𐫫 +\u0641SS𐰯。7𐫫; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +\u0641ss𐰯。7𐫫; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +xn--ss-jvd2339x.xn--7-mm5i; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +xn--zca96ys96y.xn--7-mm5i; \u0641ß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; ; # فß𐰯.7𐫫 +\u0641SS𐰯。𝟕𐫫; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +\u0641ss𐰯。𝟕𐫫; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +\u0641Ss𐰯。7𐫫; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +\u0641Ss𐰯。𝟕𐫫; \u0641ss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫 +ß\u07AC\u07A7\u08B1。𐭁􅮙𐹲; ß\u07AC\u07A7\u08B1.𐭁􅮙𐹲; [B2, B5, B6, V7]; xn--zca685aoa95h.xn--e09co8cr9861c; ; xn--ss-9qet02k.xn--e09co8cr9861c; # ßެާࢱ.𐭁𐹲 +SS\u07AC\u07A7\u08B1。𐭁􅮙𐹲; ss\u07AC\u07A7\u08B1.𐭁􅮙𐹲; [B2, B5, B6, V7]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲 +ss\u07AC\u07A7\u08B1。𐭁􅮙𐹲; ss\u07AC\u07A7\u08B1.𐭁􅮙𐹲; [B2, B5, B6, V7]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲 +Ss\u07AC\u07A7\u08B1。𐭁􅮙𐹲; ss\u07AC\u07A7\u08B1.𐭁􅮙𐹲; [B2, B5, B6, V7]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲 +xn--ss-9qet02k.xn--e09co8cr9861c; ss\u07AC\u07A7\u08B1.𐭁􅮙𐹲; [B2, B5, B6, V7]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲 +xn--zca685aoa95h.xn--e09co8cr9861c; ß\u07AC\u07A7\u08B1.𐭁􅮙𐹲; [B2, B5, B6, V7]; xn--zca685aoa95h.xn--e09co8cr9861c; ; ; # ßެާࢱ.𐭁𐹲 +-。󠉗⒌𞯛; -.󠉗⒌𞯛; [B1, V3, V7]; -.xn--xsh6367n1bi3e; ; ; # -.⒌ +-。󠉗5.𞯛; -.󠉗5.𞯛; [B1, V3, V7]; -.xn--5-zz21m.xn--6x6h; ; ; # -.5. +-.xn--5-zz21m.xn--6x6h; -.󠉗5.𞯛; [B1, V3, V7]; -.xn--5-zz21m.xn--6x6h; ; ; # -.5. +-.xn--xsh6367n1bi3e; -.󠉗⒌𞯛; [B1, V3, V7]; -.xn--xsh6367n1bi3e; ; ; # -.⒌ +𼎏ς.-≮\uFCAB; 𼎏ς.-≮\u062E\u062C; [B1, V3, V7]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج +𼎏ς.-<\u0338\uFCAB; 𼎏ς.-≮\u062E\u062C; [B1, V3, V7]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج +𼎏ς.-≮\u062E\u062C; ; [B1, V3, V7]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج +𼎏ς.-<\u0338\u062E\u062C; 𼎏ς.-≮\u062E\u062C; [B1, V3, V7]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج +𼎏Σ.-<\u0338\u062E\u062C; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +𼎏Σ.-≮\u062E\u062C; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +𼎏σ.-≮\u062E\u062C; ; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +𼎏σ.-<\u0338\u062E\u062C; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +xn--4xa92520c.xn----9mcf1400a; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +xn--3xa13520c.xn----9mcf1400a; 𼎏ς.-≮\u062E\u062C; [B1, V3, V7]; xn--3xa13520c.xn----9mcf1400a; ; ; # ς.-≮خج +𼎏Σ.-<\u0338\uFCAB; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +𼎏Σ.-≮\uFCAB; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +𼎏σ.-≮\uFCAB; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +𼎏σ.-<\u0338\uFCAB; 𼎏σ.-≮\u062E\u062C; [B1, V3, V7]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج +ꡗ\u08B8\u0719.񔤔󠛙\u0C4D\uFC3E; ꡗ\u08B8\u0719.񔤔󠛙\u0C4D\u0643\u064A; [B5, B6, V7]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي +ꡗ\u08B8\u0719.񔤔󠛙\u0C4D\u0643\u064A; ; [B5, B6, V7]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي +xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ꡗ\u08B8\u0719.񔤔󠛙\u0C4D\u0643\u064A; [B5, B6, V7]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي +𐠰\u08B7𞤌𐫭。𐋦\u17CD𝩃; 𐠰\u08B7𞤮𐫭.𐋦\u17CD𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃 +𐠰\u08B7𞤮𐫭。𐋦\u17CD𝩃; 𐠰\u08B7𞤮𐫭.𐋦\u17CD𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃 +xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; 𐠰\u08B7𞤮𐫭.𐋦\u17CD𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃 +𐠰\u08B7𞤮𐫭.𐋦\u17CD𝩃; ; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃 +𐠰\u08B7𞤌𐫭.𐋦\u17CD𝩃; 𐠰\u08B7𞤮𐫭.𐋦\u17CD𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃 +₂㘷--。\u06D3\u200C𐫆𑖿; 2㘷--.\u06D3\u200C𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿 +₂㘷--。\u06D2\u0654\u200C𐫆𑖿; 2㘷--.\u06D3\u200C𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿 +2㘷--。\u06D3\u200C𐫆𑖿; 2㘷--.\u06D3\u200C𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿 +2㘷--。\u06D2\u0654\u200C𐫆𑖿; 2㘷--.\u06D3\u200C𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿 +xn--2---u58b.xn--jlb8024k14g; 2㘷--.\u06D3𐫆𑖿; [B1, V2, V3]; xn--2---u58b.xn--jlb8024k14g; ; ; # 2㘷--.ۓ𐫆𑖿 +xn--2---u58b.xn--jlb820ku99nbgj; 2㘷--.\u06D3\u200C𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; ; # 2㘷--.ۓ𐫆𑖿 +-𘊻.ᡮ\u062D-; -𘊻.ᡮ\u062D-; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح- +-𘊻.ᡮ\u062D-; ; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح- +xn----bp5n.xn----bnc231l; -𘊻.ᡮ\u062D-; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح- +\u200C-ß。ᢣ𐹭\u063F; \u200C-ß.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ß.ᢣ𐹭ؿ +\u200C-ß。ᢣ𐹭\u063F; \u200C-ß.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ß.ᢣ𐹭ؿ +\u200C-SS。ᢣ𐹭\u063F; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ +\u200C-ss。ᢣ𐹭\u063F; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ +\u200C-Ss。ᢣ𐹭\u063F; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ +-ss.xn--bhb925glx3p; -ss.ᢣ𐹭\u063F; [B1, B5, B6, V3]; -ss.xn--bhb925glx3p; ; ; # -ss.ᢣ𐹭ؿ +xn---ss-8m0a.xn--bhb925glx3p; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; ; # -ss.ᢣ𐹭ؿ +xn----qfa550v.xn--bhb925glx3p; \u200C-ß.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; ; # -ß.ᢣ𐹭ؿ +\u200C-SS。ᢣ𐹭\u063F; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ +\u200C-ss。ᢣ𐹭\u063F; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ +\u200C-Ss。ᢣ𐹭\u063F; \u200C-ss.ᢣ𐹭\u063F; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ +꧐Ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐Ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐Ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐Ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐ӏ\u1BAA\u08F6.눵; ; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +xn--s5a04sn4u297k.xn--2e1b; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +꧐ӏ\u1BAA\u08F6.눵; ꧐ӏ\u1BAA\u08F6.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵 +xn--d5a07sn4u297k.xn--2e1b; ꧐Ӏ\u1BAA\u08F6.눵; [V7]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵 +\uA8EA。𖄿𑆾󠇗; \uA8EA.𖄿𑆾; [V6, V7]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾 +\uA8EA。𖄿𑆾󠇗; \uA8EA.𖄿𑆾; [V6, V7]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾 +xn--3g9a.xn--ud1dz07k; \uA8EA.𖄿𑆾; [V6, V7]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾 +󇓓𑚳。񐷿≯⾇; 󇓓𑚳.񐷿≯舛; [V7]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛 +󇓓𑚳。񐷿>\u0338⾇; 󇓓𑚳.񐷿≯舛; [V7]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛 +󇓓𑚳。񐷿≯舛; 󇓓𑚳.񐷿≯舛; [V7]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛 +󇓓𑚳。񐷿>\u0338舛; 󇓓𑚳.񐷿≯舛; [V7]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛 +xn--3e2d79770c.xn--hdh0088abyy1c; 󇓓𑚳.񐷿≯舛; [V7]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛 +𐫇\u0661\u200C.\u200D\u200C; 𐫇\u0661\u200C.\u200D\u200C; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; xn--9hb7344k.; [A4_2] # 𐫇١. +𐫇\u0661\u200C.\u200D\u200C; ; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; xn--9hb7344k.; [A4_2] # 𐫇١. +xn--9hb7344k.; 𐫇\u0661.; ; xn--9hb7344k.; [A4_2]; ; # 𐫇١. +𐫇\u0661.; ; ; xn--9hb7344k.; [A4_2]; ; # 𐫇١. +xn--9hb652kv99n.xn--0ugb; 𐫇\u0661\u200C.\u200D\u200C; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; ; # 𐫇١. +񡅈砪≯ᢑ。≯𝩚򓴔\u200C; 񡅈砪≯ᢑ.≯𝩚򓴔\u200C; [C1, V7]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [V7] # 砪≯ᢑ.≯𝩚 +񡅈砪>\u0338ᢑ。>\u0338𝩚򓴔\u200C; 񡅈砪≯ᢑ.≯𝩚򓴔\u200C; [C1, V7]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [V7] # 砪≯ᢑ.≯𝩚 +񡅈砪≯ᢑ。≯𝩚򓴔\u200C; 񡅈砪≯ᢑ.≯𝩚򓴔\u200C; [C1, V7]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [V7] # 砪≯ᢑ.≯𝩚 +񡅈砪>\u0338ᢑ。>\u0338𝩚򓴔\u200C; 񡅈砪≯ᢑ.≯𝩚򓴔\u200C; [C1, V7]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [V7] # 砪≯ᢑ.≯𝩚 +xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; 񡅈砪≯ᢑ.≯𝩚򓴔; [V7]; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; ; ; # 砪≯ᢑ.≯𝩚 +xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; 񡅈砪≯ᢑ.≯𝩚򓴔\u200C; [C1, V7]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; ; # 砪≯ᢑ.≯𝩚 +Ⴥ.𑄳㊸; ⴥ.𑄳43; [V6]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43 +Ⴥ.𑄳43; ⴥ.𑄳43; [V6]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43 +ⴥ.𑄳43; ; [V6]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43 +xn--tlj.xn--43-274o; ⴥ.𑄳43; [V6]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43 +ⴥ.𑄳㊸; ⴥ.𑄳43; [V6]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43 +xn--9nd.xn--43-274o; Ⴥ.𑄳43; [V6, V7]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43 +𝟎\u0663。Ⴒᡇ\u08F2𐹠; 0\u0663.ⴒᡇ\u08F2𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠 +0\u0663。Ⴒᡇ\u08F2𐹠; 0\u0663.ⴒᡇ\u08F2𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠 +0\u0663。ⴒᡇ\u08F2𐹠; 0\u0663.ⴒᡇ\u08F2𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠 +xn--0-fqc.xn--10b369eivp359r; 0\u0663.ⴒᡇ\u08F2𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠 +𝟎\u0663。ⴒᡇ\u08F2𐹠; 0\u0663.ⴒᡇ\u08F2𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠 +xn--0-fqc.xn--10b180bnwgfy0z; 0\u0663.Ⴒᡇ\u08F2𐹠; [B1, B5, B6, V7]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠 +񗪨󠄉\uFFA0\u0FB7.񸞰\uA953; 񗪨\u0FB7.񸞰\uA953; [V7]; xn--kgd72212e.xn--3j9au7544a; ; ; # ྷ.꥓ +񗪨󠄉\u1160\u0FB7.񸞰\uA953; 񗪨\u0FB7.񸞰\uA953; [V7]; xn--kgd72212e.xn--3j9au7544a; ; ; # ྷ.꥓ +xn--kgd72212e.xn--3j9au7544a; 񗪨\u0FB7.񸞰\uA953; [V7]; xn--kgd72212e.xn--3j9au7544a; ; ; # ྷ.꥓ +xn--kgd36f9z57y.xn--3j9au7544a; 񗪨\u1160\u0FB7.񸞰\uA953; [V7]; xn--kgd36f9z57y.xn--3j9au7544a; ; ; # ྷ.꥓ +xn--kgd7493jee34a.xn--3j9au7544a; 񗪨\uFFA0\u0FB7.񸞰\uA953; [V7]; xn--kgd7493jee34a.xn--3j9au7544a; ; ; # ྷ.꥓ +\u0618.۳\u200C\uA953; ; [C1, V6]; xn--6fb.xn--gmb469jjf1h; ; xn--6fb.xn--gmb0524f; [V6] # ؘ.۳꥓ +xn--6fb.xn--gmb0524f; \u0618.۳\uA953; [V6]; xn--6fb.xn--gmb0524f; ; ; # ؘ.۳꥓ +xn--6fb.xn--gmb469jjf1h; \u0618.۳\u200C\uA953; [C1, V6]; xn--6fb.xn--gmb469jjf1h; ; ; # ؘ.۳꥓ +ᡌ.︒ᢑ; ᡌ.︒ᢑ; [V7]; xn--c8e.xn--bbf9168i; ; ; # ᡌ.︒ᢑ +ᡌ.。ᢑ; ᡌ..ᢑ; [X4_2]; xn--c8e..xn--bbf; [A4_2]; ; # ᡌ..ᢑ +xn--c8e..xn--bbf; ᡌ..ᢑ; [X4_2]; xn--c8e..xn--bbf; [A4_2]; ; # ᡌ..ᢑ +xn--c8e.xn--bbf9168i; ᡌ.︒ᢑ; [V7]; xn--c8e.xn--bbf9168i; ; ; # ᡌ.︒ᢑ +𑋪\u1073。𞽧; 𑋪\u1073.𞽧; [B1, V6, V7]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ. +𑋪\u1073。𞽧; 𑋪\u1073.𞽧; [B1, V6, V7]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ. +xn--xld7443k.xn--4o7h; 𑋪\u1073.𞽧; [B1, V6, V7]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ. +𞷏。ᠢ򓘆; 𞷏.ᠢ򓘆; [V7]; xn--hd7h.xn--46e66060j; ; ; # .ᠢ +xn--hd7h.xn--46e66060j; 𞷏.ᠢ򓘆; [V7]; xn--hd7h.xn--46e66060j; ; ; # .ᠢ +𑄳㴼.\u200C𐹡\u20EB񫺦; 𑄳㴼.\u200C𐹡\u20EB񫺦; [B1, C1, V6, V7]; xn--iym9428c.xn--0ug46a7218cllv0c; ; xn--iym9428c.xn--e1g3464g08p3b; [B1, V6, V7] # 𑄳㴼.𐹡⃫ +𑄳㴼.\u200C𐹡\u20EB񫺦; ; [B1, C1, V6, V7]; xn--iym9428c.xn--0ug46a7218cllv0c; ; xn--iym9428c.xn--e1g3464g08p3b; [B1, V6, V7] # 𑄳㴼.𐹡⃫ +xn--iym9428c.xn--e1g3464g08p3b; 𑄳㴼.𐹡\u20EB񫺦; [B1, V6, V7]; xn--iym9428c.xn--e1g3464g08p3b; ; ; # 𑄳㴼.𐹡⃫ +xn--iym9428c.xn--0ug46a7218cllv0c; 𑄳㴼.\u200C𐹡\u20EB񫺦; [B1, C1, V6, V7]; xn--iym9428c.xn--0ug46a7218cllv0c; ; ; # 𑄳㴼.𐹡⃫ +񠻟𐹳𑈯。\u031D; 񠻟𐹳𑈯.\u031D; [B1, B5, B6, V6, V7]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝ +񠻟𐹳𑈯。\u031D; 񠻟𐹳𑈯.\u031D; [B1, B5, B6, V6, V7]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝ +xn--ro0dw7dey96m.xn--eta; 񠻟𐹳𑈯.\u031D; [B1, B5, B6, V6, V7]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝ +ᢊ뾜󠱴𑚶。\u089D𐹥; ᢊ뾜󠱴𑚶.\u089D𐹥; [B1, V6, V7]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥 +ᢊ뾜󠱴𑚶。\u089D𐹥; ᢊ뾜󠱴𑚶.\u089D𐹥; [B1, V6, V7]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥 +xn--39e4566fjv8bwmt6n.xn--myb6415k; ᢊ뾜󠱴𑚶.\u089D𐹥; [B1, V6, V7]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥 +𐹥≠。𐋲󠧠\u200C; 𐹥≠.𐋲󠧠\u200C; [B1, C1, V7]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, V7] # 𐹥≠.𐋲 +𐹥=\u0338。𐋲󠧠\u200C; 𐹥≠.𐋲󠧠\u200C; [B1, C1, V7]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, V7] # 𐹥≠.𐋲 +𐹥≠。𐋲󠧠\u200C; 𐹥≠.𐋲󠧠\u200C; [B1, C1, V7]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, V7] # 𐹥≠.𐋲 +𐹥=\u0338。𐋲󠧠\u200C; 𐹥≠.𐋲󠧠\u200C; [B1, C1, V7]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, V7] # 𐹥≠.𐋲 +xn--1ch6704g.xn--m97cw2999c; 𐹥≠.𐋲󠧠; [B1, V7]; xn--1ch6704g.xn--m97cw2999c; ; ; # 𐹥≠.𐋲 +xn--1ch6704g.xn--0ug3840g51u4g; 𐹥≠.𐋲󠧠\u200C; [B1, C1, V7]; xn--1ch6704g.xn--0ug3840g51u4g; ; ; # 𐹥≠.𐋲 +\u115F񙯠\u094D.\u200D\uA953𐪤; 񙯠\u094D.\u200D\uA953𐪤; [B1, C2, V7]; xn--n3b91514e.xn--1ug6815co9wc; ; xn--n3b91514e.xn--3j9al95p; [B5, B6, V6, V7] # ्.꥓ +\u115F񙯠\u094D.\u200D\uA953𐪤; 񙯠\u094D.\u200D\uA953𐪤; [B1, C2, V7]; xn--n3b91514e.xn--1ug6815co9wc; ; xn--n3b91514e.xn--3j9al95p; [B5, B6, V6, V7] # ्.꥓ +xn--n3b91514e.xn--3j9al95p; 񙯠\u094D.\uA953𐪤; [B5, B6, V6, V7]; xn--n3b91514e.xn--3j9al95p; ; ; # ्.꥓ +xn--n3b91514e.xn--1ug6815co9wc; 񙯠\u094D.\u200D\uA953𐪤; [B1, C2, V7]; xn--n3b91514e.xn--1ug6815co9wc; ; ; # ्.꥓ +xn--n3b542bb085j.xn--3j9al95p; \u115F񙯠\u094D.\uA953𐪤; [B5, B6, V6, V7]; xn--n3b542bb085j.xn--3j9al95p; ; ; # ्.꥓ +xn--n3b542bb085j.xn--1ug6815co9wc; \u115F񙯠\u094D.\u200D\uA953𐪤; [B1, C2, V7]; xn--n3b542bb085j.xn--1ug6815co9wc; ; ; # ्.꥓ +򌋔󠆎󠆗𑲕。≮; 򌋔𑲕.≮; [V7]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮ +򌋔󠆎󠆗𑲕。<\u0338; 򌋔𑲕.≮; [V7]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮ +xn--4m3dv4354a.xn--gdh; 򌋔𑲕.≮; [V7]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮ +󠆦.\u08E3暀≠; .\u08E3暀≠; [V6, X4_2]; .xn--m0b461k3g2c; [V6, A4_2]; ; # .ࣣ暀≠ +󠆦.\u08E3暀=\u0338; .\u08E3暀≠; [V6, X4_2]; .xn--m0b461k3g2c; [V6, A4_2]; ; # .ࣣ暀≠ +.xn--m0b461k3g2c; .\u08E3暀≠; [V6, X4_2]; .xn--m0b461k3g2c; [V6, A4_2]; ; # .ࣣ暀≠ +𐡤\uABED。\uFD30򜖅\u1DF0; 𐡤\uABED.\u0634\u0645򜖅\u1DF0; [B2, B3, V7]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ +𐡤\uABED。\u0634\u0645򜖅\u1DF0; 𐡤\uABED.\u0634\u0645򜖅\u1DF0; [B2, B3, V7]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ +xn--429ak76o.xn--zgb8a701kox37t; 𐡤\uABED.\u0634\u0645򜖅\u1DF0; [B2, B3, V7]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ +𝉃\u200D⒈。Ⴌ𞱓; 𝉃\u200D⒈.ⴌ𞱓; [B1, B5, B6, C2, V6, V7]; xn--1ug68oq348b.xn--3kj4524l; ; xn--tshz828m.xn--3kj4524l; [B1, B5, B6, V6, V7] # 𝉃⒈.ⴌ +𝉃\u200D1.。Ⴌ𞱓; 𝉃\u200D1..ⴌ𞱓; [B1, B5, B6, C2, V6, V7, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, V6, V7, A4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, V6, V7, A4_2] # 𝉃1..ⴌ +𝉃\u200D1.。ⴌ𞱓; 𝉃\u200D1..ⴌ𞱓; [B1, B5, B6, C2, V6, V7, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, V6, V7, A4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, V6, V7, A4_2] # 𝉃1..ⴌ +xn--1-px8q..xn--3kj4524l; 𝉃1..ⴌ𞱓; [B1, B5, B6, V6, V7, X4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, V6, V7, A4_2]; ; # 𝉃1..ⴌ +xn--1-tgn9827q..xn--3kj4524l; 𝉃\u200D1..ⴌ𞱓; [B1, B5, B6, C2, V6, V7, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, V6, V7, A4_2]; ; # 𝉃1..ⴌ +𝉃\u200D⒈。ⴌ𞱓; 𝉃\u200D⒈.ⴌ𞱓; [B1, B5, B6, C2, V6, V7]; xn--1ug68oq348b.xn--3kj4524l; ; xn--tshz828m.xn--3kj4524l; [B1, B5, B6, V6, V7] # 𝉃⒈.ⴌ +xn--tshz828m.xn--3kj4524l; 𝉃⒈.ⴌ𞱓; [B1, B5, B6, V6, V7]; xn--tshz828m.xn--3kj4524l; ; ; # 𝉃⒈.ⴌ +xn--1ug68oq348b.xn--3kj4524l; 𝉃\u200D⒈.ⴌ𞱓; [B1, B5, B6, C2, V6, V7]; xn--1ug68oq348b.xn--3kj4524l; ; ; # 𝉃⒈.ⴌ +xn--1-px8q..xn--knd8464v; 𝉃1..Ⴌ𞱓; [B1, B5, B6, V6, V7, X4_2]; xn--1-px8q..xn--knd8464v; [B1, B5, B6, V6, V7, A4_2]; ; # 𝉃1..Ⴌ +xn--1-tgn9827q..xn--knd8464v; 𝉃\u200D1..Ⴌ𞱓; [B1, B5, B6, C2, V6, V7, X4_2]; xn--1-tgn9827q..xn--knd8464v; [B1, B5, B6, C2, V6, V7, A4_2]; ; # 𝉃1..Ⴌ +xn--tshz828m.xn--knd8464v; 𝉃⒈.Ⴌ𞱓; [B1, B5, B6, V6, V7]; xn--tshz828m.xn--knd8464v; ; ; # 𝉃⒈.Ⴌ +xn--1ug68oq348b.xn--knd8464v; 𝉃\u200D⒈.Ⴌ𞱓; [B1, B5, B6, C2, V6, V7]; xn--1ug68oq348b.xn--knd8464v; ; ; # 𝉃⒈.Ⴌ +󠣙\u0A4D𱫘𞤸.ς񵯞􈰔; ; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; # ੍𱫘𞤸.ς +󠣙\u0A4D𱫘𞤖.Σ񵯞􈰔; 󠣙\u0A4D𱫘𞤸.σ񵯞􈰔; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𱫘𞤸.σ +󠣙\u0A4D𱫘𞤸.σ񵯞􈰔; ; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𱫘𞤸.σ +󠣙\u0A4D𱫘𞤖.σ񵯞􈰔; 󠣙\u0A4D𱫘𞤸.σ񵯞􈰔; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𱫘𞤸.σ +xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; 󠣙\u0A4D𱫘𞤸.σ񵯞􈰔; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𱫘𞤸.σ +󠣙\u0A4D𱫘𞤖.ς񵯞􈰔; 󠣙\u0A4D𱫘𞤸.ς񵯞􈰔; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; # ੍𱫘𞤸.ς +xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; 󠣙\u0A4D𱫘𞤸.ς񵯞􈰔; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; ; # ੍𱫘𞤸.ς +󠣙\u0A4D𱫘𞤸.Σ񵯞􈰔; 󠣙\u0A4D𱫘𞤸.σ񵯞􈰔; [B1, V7]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𱫘𞤸.σ +\u07D3。\u200C𐫀򞭱; \u07D3.\u200C𐫀򞭱; [B1, C1, V7]; xn--usb.xn--0ug9553gm3v5d; ; xn--usb.xn--pw9ci1099a; [B2, B3, V7] # ߓ.𐫀 +xn--usb.xn--pw9ci1099a; \u07D3.𐫀򞭱; [B2, B3, V7]; xn--usb.xn--pw9ci1099a; ; ; # ߓ.𐫀 +xn--usb.xn--0ug9553gm3v5d; \u07D3.\u200C𐫀򞭱; [B1, C1, V7]; xn--usb.xn--0ug9553gm3v5d; ; ; # ߓ.𐫀 +\u1C2E𞀝.\u05A6ꡟ𞤕󠆖; \u1C2E𞀝.\u05A6ꡟ𞤷; [B1, V6]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷 +\u1C2E𞀝.\u05A6ꡟ𞤷󠆖; \u1C2E𞀝.\u05A6ꡟ𞤷; [B1, V6]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷 +xn--q1f4493q.xn--xcb8244fifvj; \u1C2E𞀝.\u05A6ꡟ𞤷; [B1, V6]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷 +䂹󾖅𐋦.\u200D; 䂹󾖅𐋦.\u200D; [C2, V7]; xn--0on3543c5981i.xn--1ug; ; xn--0on3543c5981i.; [V7, A4_2] # 䂹𐋦. +䂹󾖅𐋦.\u200D; ; [C2, V7]; xn--0on3543c5981i.xn--1ug; ; xn--0on3543c5981i.; [V7, A4_2] # 䂹𐋦. +xn--0on3543c5981i.; 䂹󾖅𐋦.; [V7]; xn--0on3543c5981i.; [V7, A4_2]; ; # 䂹𐋦. +xn--0on3543c5981i.xn--1ug; 䂹󾖅𐋦.\u200D; [C2, V7]; xn--0on3543c5981i.xn--1ug; ; ; # 䂹𐋦. +\uA9C0\u200C𐹲\u200C。\u0767🄉; \uA9C0\u200C𐹲\u200C.\u07678,; [B3, B5, B6, C1, V6, U1]; xn--0uga8686hdgvd.xn--8,-qle; ; xn--7m9an32q.xn--8,-qle; [B3, B5, B6, V6, U1] # ꧀𐹲.ݧ8, +\uA9C0\u200C𐹲\u200C。\u07678,; \uA9C0\u200C𐹲\u200C.\u07678,; [B3, B5, B6, C1, V6, U1]; xn--0uga8686hdgvd.xn--8,-qle; ; xn--7m9an32q.xn--8,-qle; [B3, B5, B6, V6, U1] # ꧀𐹲.ݧ8, +xn--7m9an32q.xn--8,-qle; \uA9C0𐹲.\u07678,; [B3, B5, B6, V6, U1]; xn--7m9an32q.xn--8,-qle; ; ; # ꧀𐹲.ݧ8, +xn--0uga8686hdgvd.xn--8,-qle; \uA9C0\u200C𐹲\u200C.\u07678,; [B3, B5, B6, C1, V6, U1]; xn--0uga8686hdgvd.xn--8,-qle; ; ; # ꧀𐹲.ݧ8, +xn--7m9an32q.xn--rpb6081w; \uA9C0𐹲.\u0767🄉; [B5, B6, V6, V7]; xn--7m9an32q.xn--rpb6081w; ; ; # ꧀𐹲.ݧ🄉 +xn--0uga8686hdgvd.xn--rpb6081w; \uA9C0\u200C𐹲\u200C.\u0767🄉; [B5, B6, C1, V6, V7]; xn--0uga8686hdgvd.xn--rpb6081w; ; ; # ꧀𐹲.ݧ🄉 +︒。Ⴃ≯; ︒.ⴃ≯; [V7]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯ +︒。Ⴃ>\u0338; ︒.ⴃ≯; [V7]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯ +。。Ⴃ≯; ..ⴃ≯; [X4_2]; ..xn--hdh782b; [A4_2]; ; # ..ⴃ≯ +。。Ⴃ>\u0338; ..ⴃ≯; [X4_2]; ..xn--hdh782b; [A4_2]; ; # ..ⴃ≯ +。。ⴃ>\u0338; ..ⴃ≯; [X4_2]; ..xn--hdh782b; [A4_2]; ; # ..ⴃ≯ +。。ⴃ≯; ..ⴃ≯; [X4_2]; ..xn--hdh782b; [A4_2]; ; # ..ⴃ≯ +..xn--hdh782b; ..ⴃ≯; [X4_2]; ..xn--hdh782b; [A4_2]; ; # ..ⴃ≯ +︒。ⴃ>\u0338; ︒.ⴃ≯; [V7]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯ +︒。ⴃ≯; ︒.ⴃ≯; [V7]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯ +xn--y86c.xn--hdh782b; ︒.ⴃ≯; [V7]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯ +..xn--bnd622g; ..Ⴃ≯; [V7, X4_2]; ..xn--bnd622g; [V7, A4_2]; ; # ..Ⴃ≯ +xn--y86c.xn--bnd622g; ︒.Ⴃ≯; [V7]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯ +𐹮。󠢼\u200D; 𐹮.󠢼\u200D; [B1, C2, V7]; xn--mo0d.xn--1ug18431l; ; xn--mo0d.xn--wy46e; [B1, V7] # 𐹮. +𐹮。󠢼\u200D; 𐹮.󠢼\u200D; [B1, C2, V7]; xn--mo0d.xn--1ug18431l; ; xn--mo0d.xn--wy46e; [B1, V7] # 𐹮. +xn--mo0d.xn--wy46e; 𐹮.󠢼; [B1, V7]; xn--mo0d.xn--wy46e; ; ; # 𐹮. +xn--mo0d.xn--1ug18431l; 𐹮.󠢼\u200D; [B1, C2, V7]; xn--mo0d.xn--1ug18431l; ; ; # 𐹮. +Ⴞ𐹨。︒\u077D\u200DႯ; ⴞ𐹨.︒\u077D\u200Dⴏ; [B1, B5, B6, C2, V7]; xn--mlju223e.xn--eqb096jpgj9y7r; ; xn--mlju223e.xn--eqb053qjk7l; [B1, B5, B6, V7] # ⴞ𐹨.︒ݽⴏ +Ⴞ𐹨。。\u077D\u200DႯ; ⴞ𐹨..\u077D\u200Dⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2] # ⴞ𐹨..ݽⴏ +ⴞ𐹨。。\u077D\u200Dⴏ; ⴞ𐹨..\u077D\u200Dⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2] # ⴞ𐹨..ݽⴏ +Ⴞ𐹨。。\u077D\u200Dⴏ; ⴞ𐹨..\u077D\u200Dⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2] # ⴞ𐹨..ݽⴏ +xn--mlju223e..xn--eqb053q; ⴞ𐹨..\u077Dⴏ; [B2, B3, B5, B6, X4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2]; ; # ⴞ𐹨..ݽⴏ +xn--mlju223e..xn--eqb096jpgj; ⴞ𐹨..\u077D\u200Dⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; ; # ⴞ𐹨..ݽⴏ +ⴞ𐹨。︒\u077D\u200Dⴏ; ⴞ𐹨.︒\u077D\u200Dⴏ; [B1, B5, B6, C2, V7]; xn--mlju223e.xn--eqb096jpgj9y7r; ; xn--mlju223e.xn--eqb053qjk7l; [B1, B5, B6, V7] # ⴞ𐹨.︒ݽⴏ +Ⴞ𐹨。︒\u077D\u200Dⴏ; ⴞ𐹨.︒\u077D\u200Dⴏ; [B1, B5, B6, C2, V7]; xn--mlju223e.xn--eqb096jpgj9y7r; ; xn--mlju223e.xn--eqb053qjk7l; [B1, B5, B6, V7] # ⴞ𐹨.︒ݽⴏ +xn--mlju223e.xn--eqb053qjk7l; ⴞ𐹨.︒\u077Dⴏ; [B1, B5, B6, V7]; xn--mlju223e.xn--eqb053qjk7l; ; ; # ⴞ𐹨.︒ݽⴏ +xn--mlju223e.xn--eqb096jpgj9y7r; ⴞ𐹨.︒\u077D\u200Dⴏ; [B1, B5, B6, C2, V7]; xn--mlju223e.xn--eqb096jpgj9y7r; ; ; # ⴞ𐹨.︒ݽⴏ +xn--2nd0990k..xn--eqb053q; Ⴞ𐹨..\u077Dⴏ; [B2, B3, B5, B6, V7, X4_2]; xn--2nd0990k..xn--eqb053q; [B2, B3, B5, B6, V7, A4_2]; ; # Ⴞ𐹨..ݽⴏ +xn--2nd0990k..xn--eqb096jpgj; Ⴞ𐹨..\u077D\u200Dⴏ; [B2, B3, B5, B6, C2, V7, X4_2]; xn--2nd0990k..xn--eqb096jpgj; [B2, B3, B5, B6, C2, V7, A4_2]; ; # Ⴞ𐹨..ݽⴏ +xn--2nd0990k..xn--eqb228b; Ⴞ𐹨..\u077DႯ; [B2, B3, B5, B6, V7, X4_2]; xn--2nd0990k..xn--eqb228b; [B2, B3, B5, B6, V7, A4_2]; ; # Ⴞ𐹨..ݽႯ +xn--2nd0990k..xn--eqb228bgzm; Ⴞ𐹨..\u077D\u200DႯ; [B2, B3, B5, B6, C2, V7, X4_2]; xn--2nd0990k..xn--eqb228bgzm; [B2, B3, B5, B6, C2, V7, A4_2]; ; # Ⴞ𐹨..ݽႯ +xn--2nd0990k.xn--eqb053qjk7l; Ⴞ𐹨.︒\u077Dⴏ; [B1, B5, B6, V7]; xn--2nd0990k.xn--eqb053qjk7l; ; ; # Ⴞ𐹨.︒ݽⴏ +xn--2nd0990k.xn--eqb096jpgj9y7r; Ⴞ𐹨.︒\u077D\u200Dⴏ; [B1, B5, B6, C2, V7]; xn--2nd0990k.xn--eqb096jpgj9y7r; ; ; # Ⴞ𐹨.︒ݽⴏ +xn--2nd0990k.xn--eqb228b583r; Ⴞ𐹨.︒\u077DႯ; [B1, B5, B6, V7]; xn--2nd0990k.xn--eqb228b583r; ; ; # Ⴞ𐹨.︒ݽႯ +xn--2nd0990k.xn--eqb228bgzmvp0t; Ⴞ𐹨.︒\u077D\u200DႯ; [B1, B5, B6, C2, V7]; xn--2nd0990k.xn--eqb228bgzmvp0t; ; ; # Ⴞ𐹨.︒ݽႯ +\u200CႦ𝟹。-\u20D2-\u07D1; \u200Cⴆ3.-\u20D2-\u07D1; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ +\u200CႦ3。-\u20D2-\u07D1; \u200Cⴆ3.-\u20D2-\u07D1; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ +\u200Cⴆ3。-\u20D2-\u07D1; \u200Cⴆ3.-\u20D2-\u07D1; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ +xn--3-lvs.xn-----vue617w; ⴆ3.-\u20D2-\u07D1; [B1, V3]; xn--3-lvs.xn-----vue617w; ; ; # ⴆ3.-⃒-ߑ +xn--3-rgnv99c.xn-----vue617w; \u200Cⴆ3.-\u20D2-\u07D1; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; ; # ⴆ3.-⃒-ߑ +\u200Cⴆ𝟹。-\u20D2-\u07D1; \u200Cⴆ3.-\u20D2-\u07D1; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ +xn--3-i0g.xn-----vue617w; Ⴆ3.-\u20D2-\u07D1; [B1, V3, V7]; xn--3-i0g.xn-----vue617w; ; ; # Ⴆ3.-⃒-ߑ +xn--3-i0g939i.xn-----vue617w; \u200CႦ3.-\u20D2-\u07D1; [B1, C1, V3, V7]; xn--3-i0g939i.xn-----vue617w; ; ; # Ⴆ3.-⃒-ߑ +箃Ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃Ⴡ-󠁝。=\u0338-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃Ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃Ⴡ-󠁝。=\u0338-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃ⴡ-󠁝。=\u0338-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +xn----4wsr321ay823p.xn----tfot873s; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃ⴡ-󠁝。=\u0338-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [V7]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖 +xn----11g3013fy8x5m.xn----tfot873s; 箃Ⴡ-󠁝.≠-🤖; [V7]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖 +\u07E5.\u06B5; ; ; xn--dtb.xn--okb; ; ; # ߥ.ڵ +xn--dtb.xn--okb; \u07E5.\u06B5; ; xn--dtb.xn--okb; ; ; # ߥ.ڵ +\u200C\u200D.𞤿; ; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; .xn--3e6h; [A4_2] # .𞤿 +\u200C\u200D.𞤝; \u200C\u200D.𞤿; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; .xn--3e6h; [A4_2] # .𞤿 +.xn--3e6h; .𞤿; [X4_2]; .xn--3e6h; [A4_2]; ; # .𞤿 +xn--0ugc.xn--3e6h; \u200C\u200D.𞤿; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; ; # .𞤿 +xn--3e6h; 𞤿; ; xn--3e6h; ; ; # 𞤿 +𞤿; ; ; xn--3e6h; ; ; # 𞤿 +𞤝; 𞤿; ; xn--3e6h; ; ; # 𞤿 +🜑𐹧\u0639.ς𑍍蜹; ; [B1]; xn--4gb3736kk4zf.xn--3xa4248dy27d; ; xn--4gb3736kk4zf.xn--4xa2248dy27d; # 🜑𐹧ع.ς𑍍蜹 +🜑𐹧\u0639.Σ𑍍蜹; 🜑𐹧\u0639.σ𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹 +🜑𐹧\u0639.σ𑍍蜹; ; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹 +xn--4gb3736kk4zf.xn--4xa2248dy27d; 🜑𐹧\u0639.σ𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹 +xn--4gb3736kk4zf.xn--3xa4248dy27d; 🜑𐹧\u0639.ς𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--3xa4248dy27d; ; ; # 🜑𐹧ع.ς𑍍蜹 +򫠐ス􆟤\u0669.󚃟; 򫠐ス􆟤\u0669.󚃟; [B5, B6, V7]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩. +򫠐ス􆟤\u0669.󚃟; ; [B5, B6, V7]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩. +xn--iib777sp230oo708a.xn--7824e; 򫠐ス􆟤\u0669.󚃟; [B5, B6, V7]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩. +𝪣򕡝.\u059A?\u06C2; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +𝪣򕡝.\u059A?\u06C1\u0654; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +𝪣򕡝.\u059A?\u06C2; ; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +𝪣򕡝.\u059A?\u06C1\u0654; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +xn--8c3hu7971a.xn--?-wec30g; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +xn--8c3hu7971a.\u059A?\u06C2; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +xn--8c3hu7971a.\u059A?\u06C1\u0654; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +XN--8C3HU7971A.\u059A?\u06C1\u0654; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +XN--8C3HU7971A.\u059A?\u06C2; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +Xn--8c3hu7971a.\u059A?\u06C2; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +Xn--8c3hu7971a.\u059A?\u06C1\u0654; 𝪣򕡝.\u059A?\u06C2; [B1, V6, V7, U1]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ +\u0660򪓵\u200C。\u0757; \u0660򪓵\u200C.\u0757; [B1, C1, V7]; xn--8hb852ke991q.xn--bpb; ; xn--8hb82030l.xn--bpb; [B1, V7] # ٠.ݗ +xn--8hb82030l.xn--bpb; \u0660򪓵.\u0757; [B1, V7]; xn--8hb82030l.xn--bpb; ; ; # ٠.ݗ +xn--8hb852ke991q.xn--bpb; \u0660򪓵\u200C.\u0757; [B1, C1, V7]; xn--8hb852ke991q.xn--bpb; ; ; # ٠.ݗ +\u103A\u200D\u200C。-\u200C; \u103A\u200D\u200C.-\u200C; [C1, V3, V6]; xn--bkd412fca.xn----sgn; ; xn--bkd.-; [V3, V6] # ်.- +xn--bkd.-; \u103A.-; [V3, V6]; xn--bkd.-; ; ; # ်.- +xn--bkd412fca.xn----sgn; \u103A\u200D\u200C.-\u200C; [C1, V3, V6]; xn--bkd412fca.xn----sgn; ; ; # ်.- +︒。\u1B44ᡉ; ︒.\u1B44ᡉ; [V6, V7]; xn--y86c.xn--87e93m; ; ; # ︒.᭄ᡉ +。。\u1B44ᡉ; ..\u1B44ᡉ; [V6, X4_2]; ..xn--87e93m; [V6, A4_2]; ; # ..᭄ᡉ +..xn--87e93m; ..\u1B44ᡉ; [V6, X4_2]; ..xn--87e93m; [V6, A4_2]; ; # ..᭄ᡉ +xn--y86c.xn--87e93m; ︒.\u1B44ᡉ; [V6, V7]; xn--y86c.xn--87e93m; ; ; # ︒.᭄ᡉ +\u0758ß。ጫᢊ\u0768𝟐; \u0758ß.ጫᢊ\u07682; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; xn--ss-gke.xn--2-b5c641gfmf; # ݘß.ጫᢊݨ2 +\u0758ß。ጫᢊ\u07682; \u0758ß.ጫᢊ\u07682; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; xn--ss-gke.xn--2-b5c641gfmf; # ݘß.ጫᢊݨ2 +\u0758SS。ጫᢊ\u07682; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +\u0758ss。ጫᢊ\u07682; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +xn--ss-gke.xn--2-b5c641gfmf; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +xn--zca724a.xn--2-b5c641gfmf; \u0758ß.ጫᢊ\u07682; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; ; # ݘß.ጫᢊݨ2 +\u0758SS。ጫᢊ\u0768𝟐; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +\u0758ss。ጫᢊ\u0768𝟐; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +\u0758Ss。ጫᢊ\u07682; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +\u0758Ss。ጫᢊ\u0768𝟐; \u0758ss.ጫᢊ\u07682; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2 +\u07C3𞶇ᚲ.\u0902\u0353𝟚\u09CD; \u07C3𞶇ᚲ.\u0902\u03532\u09CD; [B1, B2, B3, V6, V7]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্ +\u07C3𞶇ᚲ.\u0902\u03532\u09CD; ; [B1, B2, B3, V6, V7]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্ +xn--esb067enh07a.xn--2-lgb874bjxa; \u07C3𞶇ᚲ.\u0902\u03532\u09CD; [B1, B2, B3, V6, V7]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্ +-\u1BAB︒\u200D.񒶈񥹓; ; [C2, V3, V7]; xn----qmlv7tw180a.xn--x50zy803a; ; xn----qml1407i.xn--x50zy803a; [V3, V7] # -᮫︒. +-\u1BAB。\u200D.񒶈񥹓; -\u1BAB.\u200D.񒶈񥹓; [C2, V3, V7]; xn----qml.xn--1ug.xn--x50zy803a; ; xn----qml..xn--x50zy803a; [V3, V7, A4_2] # -᮫.. +xn----qml..xn--x50zy803a; -\u1BAB..񒶈񥹓; [V3, V7, X4_2]; xn----qml..xn--x50zy803a; [V3, V7, A4_2]; ; # -᮫.. +xn----qml.xn--1ug.xn--x50zy803a; -\u1BAB.\u200D.񒶈񥹓; [C2, V3, V7]; xn----qml.xn--1ug.xn--x50zy803a; ; ; # -᮫.. +xn----qml1407i.xn--x50zy803a; -\u1BAB︒.񒶈񥹓; [V3, V7]; xn----qml1407i.xn--x50zy803a; ; ; # -᮫︒. +xn----qmlv7tw180a.xn--x50zy803a; -\u1BAB︒\u200D.񒶈񥹓; [C2, V3, V7]; xn----qmlv7tw180a.xn--x50zy803a; ; ; # -᮫︒. +󠦮.≯𞀆; ; [V7]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆 +󠦮.>\u0338𞀆; 󠦮.≯𞀆; [V7]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆 +xn--t546e.xn--hdh5166o; 󠦮.≯𞀆; [V7]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆 +-𑄳󠊗𐹩。𞮱; -𑄳󠊗𐹩.𞮱; [B1, V3, V7]; xn----p26i72em2894c.xn--zw6h; ; ; # -𑄳𐹩. +xn----p26i72em2894c.xn--zw6h; -𑄳󠊗𐹩.𞮱; [B1, V3, V7]; xn----p26i72em2894c.xn--zw6h; ; ; # -𑄳𐹩. +\u06B9.ᡳ\u115F; \u06B9.ᡳ; ; xn--skb.xn--g9e; ; ; # ڹ.ᡳ +\u06B9.ᡳ\u115F; \u06B9.ᡳ; ; xn--skb.xn--g9e; ; ; # ڹ.ᡳ +xn--skb.xn--g9e; \u06B9.ᡳ; ; xn--skb.xn--g9e; ; ; # ڹ.ᡳ +\u06B9.ᡳ; ; ; xn--skb.xn--g9e; ; ; # ڹ.ᡳ +xn--skb.xn--osd737a; \u06B9.ᡳ\u115F; [V7]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ +㨛𘱎.︒𝟕\u0D01; 㨛𘱎.︒7\u0D01; [V7]; xn--mbm8237g.xn--7-7hf1526p; ; ; # 㨛𘱎.︒7ഁ +㨛𘱎.。7\u0D01; 㨛𘱎..7\u0D01; [X4_2]; xn--mbm8237g..xn--7-7hf; [A4_2]; ; # 㨛𘱎..7ഁ +xn--mbm8237g..xn--7-7hf; 㨛𘱎..7\u0D01; [X4_2]; xn--mbm8237g..xn--7-7hf; [A4_2]; ; # 㨛𘱎..7ഁ +xn--mbm8237g.xn--7-7hf1526p; 㨛𘱎.︒7\u0D01; [V7]; xn--mbm8237g.xn--7-7hf1526p; ; ; # 㨛𘱎.︒7ഁ +\u06DD𻱧-。𞷁\u2064𞤣≮; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤣<\u0338; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤣≮; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤣<\u0338; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤁<\u0338; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤁≮; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +xn----dxc06304e.xn--gdh5020pk5c; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤁<\u0338; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +\u06DD𻱧-。𞷁\u2064𞤁≮; \u06DD𻱧-.𞷁𞤣≮; [B1, B3, V3, V7]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮ +ß\u200C\uAAF6ᢥ.⊶ჁႶ; ß\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ +ß\u200C\uAAF6ᢥ.⊶ჁႶ; ß\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ +ß\u200C\uAAF6ᢥ.⊶ⴡⴖ; ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ +SS\u200C\uAAF6ᢥ.⊶ჁႶ; ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ +ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ +Ss\u200C\uAAF6ᢥ.⊶Ⴡⴖ; ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ +xn--ss-4epx629f.xn--ifh802b6a; ss\uAAF6ᢥ.⊶ⴡⴖ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ +ss\uAAF6ᢥ.⊶ⴡⴖ; ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ +SS\uAAF6ᢥ.⊶ჁႶ; ss\uAAF6ᢥ.⊶ⴡⴖ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ +Ss\uAAF6ᢥ.⊶Ⴡⴖ; ss\uAAF6ᢥ.⊶ⴡⴖ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ +xn--ss-4ep585bkm5p.xn--ifh802b6a; ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ +xn--zca682johfi89m.xn--ifh802b6a; ß\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; ; # ß꫶ᢥ.⊶ⴡⴖ +ß\u200C\uAAF6ᢥ.⊶ⴡⴖ; ß\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ +SS\u200C\uAAF6ᢥ.⊶ჁႶ; ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ +ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ +Ss\u200C\uAAF6ᢥ.⊶Ⴡⴖ; ss\u200C\uAAF6ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ +xn--ss-4epx629f.xn--5nd703gyrh; ss\uAAF6ᢥ.⊶Ⴡⴖ; [V7]; xn--ss-4epx629f.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ +xn--ss-4ep585bkm5p.xn--5nd703gyrh; ss\u200C\uAAF6ᢥ.⊶Ⴡⴖ; [C1, V7]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ +xn--ss-4epx629f.xn--undv409k; ss\uAAF6ᢥ.⊶ჁႶ; [V7]; xn--ss-4epx629f.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ +xn--ss-4ep585bkm5p.xn--undv409k; ss\u200C\uAAF6ᢥ.⊶ჁႶ; [C1, V7]; xn--ss-4ep585bkm5p.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ +xn--zca682johfi89m.xn--undv409k; ß\u200C\uAAF6ᢥ.⊶ჁႶ; [C1, V7]; xn--zca682johfi89m.xn--undv409k; ; ; # ß꫶ᢥ.⊶ჁႶ +\u200D。ς󠁉; \u200D.ς󠁉; [C2, V7]; xn--1ug.xn--3xa44344p; ; .xn--4xa24344p; [V7, A4_2] # .ς +\u200D。Σ󠁉; \u200D.σ󠁉; [C2, V7]; xn--1ug.xn--4xa24344p; ; .xn--4xa24344p; [V7, A4_2] # .σ +\u200D。σ󠁉; \u200D.σ󠁉; [C2, V7]; xn--1ug.xn--4xa24344p; ; .xn--4xa24344p; [V7, A4_2] # .σ +.xn--4xa24344p; .σ󠁉; [V7, X4_2]; .xn--4xa24344p; [V7, A4_2]; ; # .σ +xn--1ug.xn--4xa24344p; \u200D.σ󠁉; [C2, V7]; xn--1ug.xn--4xa24344p; ; ; # .σ +xn--1ug.xn--3xa44344p; \u200D.ς󠁉; [C2, V7]; xn--1ug.xn--3xa44344p; ; ; # .ς +𞵑ß.\u0751\u200D𞤛-; 𞵑ß.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--zca5423w.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ß.ݑ𞤽- +𞵑ß.\u0751\u200D𞤽-; ; [B2, B3, C2, V3, V7]; xn--zca5423w.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ß.ݑ𞤽- +𞵑SS.\u0751\u200D𞤛-; 𞵑ss.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ss.ݑ𞤽- +𞵑ss.\u0751\u200D𞤽-; ; [B2, B3, C2, V3, V7]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ss.ݑ𞤽- +𞵑Ss.\u0751\u200D𞤽-; 𞵑ss.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ss.ݑ𞤽- +xn--ss-2722a.xn----z3c03218a; 𞵑ss.\u0751𞤽-; [B2, B3, V3, V7]; xn--ss-2722a.xn----z3c03218a; ; ; # ss.ݑ𞤽- +xn--ss-2722a.xn----z3c011q9513b; 𞵑ss.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--ss-2722a.xn----z3c011q9513b; ; ; # ss.ݑ𞤽- +xn--zca5423w.xn----z3c011q9513b; 𞵑ß.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--zca5423w.xn----z3c011q9513b; ; ; # ß.ݑ𞤽- +𞵑ss.\u0751\u200D𞤛-; 𞵑ss.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ss.ݑ𞤽- +𞵑Ss.\u0751\u200D𞤛-; 𞵑ss.\u0751\u200D𞤽-; [B2, B3, C2, V3, V7]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, V3, V7] # ss.ݑ𞤽- +𑘽\u200D𞤧.𐹧󡦪-; 𑘽\u200D𞤧.𐹧󡦪-; [B1, C2, V3, V6, V7]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, V3, V6, V7] # 𑘽𞤧.𐹧- +𑘽\u200D𞤧.𐹧󡦪-; ; [B1, C2, V3, V6, V7]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, V3, V6, V7] # 𑘽𞤧.𐹧- +𑘽\u200D𞤅.𐹧󡦪-; 𑘽\u200D𞤧.𐹧󡦪-; [B1, C2, V3, V6, V7]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, V3, V6, V7] # 𑘽𞤧.𐹧- +xn--qb2ds317a.xn----k26iq1483f; 𑘽𞤧.𐹧󡦪-; [B1, V3, V6, V7]; xn--qb2ds317a.xn----k26iq1483f; ; ; # 𑘽𞤧.𐹧- +xn--1ugz808gdimf.xn----k26iq1483f; 𑘽\u200D𞤧.𐹧󡦪-; [B1, C2, V3, V6, V7]; xn--1ugz808gdimf.xn----k26iq1483f; ; ; # 𑘽𞤧.𐹧- +𑘽\u200D𞤅.𐹧󡦪-; 𑘽\u200D𞤧.𐹧󡦪-; [B1, C2, V3, V6, V7]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, V3, V6, V7] # 𑘽𞤧.𐹧- +⒒򨘙򳳠𑓀.-󞡊; ; [V3, V7]; xn--3shy698frsu9dt1me.xn----x310m; ; ; # ⒒𑓀.- +11.򨘙򳳠𑓀.-󞡊; ; [V3, V7]; 11.xn--uz1d59632bxujd.xn----x310m; ; ; # 11.𑓀.- +11.xn--uz1d59632bxujd.xn----x310m; 11.򨘙򳳠𑓀.-󞡊; [V3, V7]; 11.xn--uz1d59632bxujd.xn----x310m; ; ; # 11.𑓀.- +xn--3shy698frsu9dt1me.xn----x310m; ⒒򨘙򳳠𑓀.-󞡊; [V3, V7]; xn--3shy698frsu9dt1me.xn----x310m; ; ; # ⒒𑓀.- +-。\u200D; -.\u200D; [C2, V3]; -.xn--1ug; ; -.; [V3, A4_2] # -. +-。\u200D; -.\u200D; [C2, V3]; -.xn--1ug; ; -.; [V3, A4_2] # -. +-.; ; [V3]; ; [V3, A4_2]; ; # -. +-.xn--1ug; -.\u200D; [C2, V3]; -.xn--1ug; ; ; # -. +≮ᡬ.ς¹-?; ≮ᡬ.ς1-?; [U1]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-? +<\u0338ᡬ.ς¹-?; ≮ᡬ.ς1-?; [U1]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-? +≮ᡬ.ς1-?; ; [U1]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-? +<\u0338ᡬ.ς1-?; ≮ᡬ.ς1-?; [U1]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-? +<\u0338ᡬ.Σ1-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +≮ᡬ.Σ1-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +≮ᡬ.σ1-?; ; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +<\u0338ᡬ.σ1-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +xn--88e732c.xn--1-?-pzc; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +xn--88e732c.xn--1-?-lzc; ≮ᡬ.ς1-?; [U1]; xn--88e732c.xn--1-?-lzc; ; ; # ≮ᡬ.ς1-? +<\u0338ᡬ.Σ¹-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +≮ᡬ.Σ¹-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +≮ᡬ.σ¹-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +<\u0338ᡬ.σ¹-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +xn--88e732c.σ1-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +XN--88E732C.Σ1-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +xn--88e732c.ς1-?; ≮ᡬ.ς1-?; [U1]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-? +Xn--88e732c.ς1-?; ≮ᡬ.ς1-?; [U1]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-? +Xn--88e732c.σ1-?; ≮ᡬ.σ1-?; [U1]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-? +ቬ򔠼񁗶。𐨬𝟠; ቬ򔠼񁗶.𐨬8; [V7]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8 +ቬ򔠼񁗶。𐨬8; ቬ򔠼񁗶.𐨬8; [V7]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8 +xn--d0d41273c887z.xn--8-ob5i; ቬ򔠼񁗶.𐨬8; [V7]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8 +𐱲。蔫\u0766; 𐱲.蔫\u0766; [B5, B6, V7]; xn--389c.xn--qpb7055d; ; ; # .蔫ݦ +xn--389c.xn--qpb7055d; 𐱲.蔫\u0766; [B5, B6, V7]; xn--389c.xn--qpb7055d; ; ; # .蔫ݦ +򒲧₃。ꡚ𛇑󠄳\u0647; 򒲧3.ꡚ𛇑\u0647; [B5, B6, V7]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه +򒲧3。ꡚ𛇑󠄳\u0647; 򒲧3.ꡚ𛇑\u0647; [B5, B6, V7]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه +xn--3-ep59g.xn--jhb5904fcp0h; 򒲧3.ꡚ𛇑\u0647; [B5, B6, V7]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه +蓸\u0642≠.ß; ; [B5, B6]; xn--ehb015lnt1e.xn--zca; ; xn--ehb015lnt1e.ss; # 蓸ق≠.ß +蓸\u0642=\u0338.ß; 蓸\u0642≠.ß; [B5, B6]; xn--ehb015lnt1e.xn--zca; ; xn--ehb015lnt1e.ss; # 蓸ق≠.ß +蓸\u0642=\u0338.SS; 蓸\u0642≠.ss; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +蓸\u0642≠.SS; 蓸\u0642≠.ss; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +蓸\u0642≠.ss; ; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +蓸\u0642=\u0338.ss; 蓸\u0642≠.ss; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +蓸\u0642=\u0338.Ss; 蓸\u0642≠.ss; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +蓸\u0642≠.Ss; 蓸\u0642≠.ss; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +xn--ehb015lnt1e.ss; 蓸\u0642≠.ss; [B5, B6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss +xn--ehb015lnt1e.xn--zca; 蓸\u0642≠.ß; [B5, B6]; xn--ehb015lnt1e.xn--zca; ; ; # 蓸ق≠.ß +\u084E\u067A\u0DD3⒊.𐹹𞱩󠃪\u200C; ; [B1, C1, V7]; xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ; xn--zib94gfziuq1a.xn--xo0dw109an237f; [B1, V7] # ࡎٺී⒊.𐹹 +\u084E\u067A\u0DD33..𐹹𞱩󠃪\u200C; ; [B1, C1, V7, X4_2]; xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; [B1, C1, V7, A4_2]; xn--3-prc71ls9j..xn--xo0dw109an237f; [B1, V7, A4_2] # ࡎٺී3..𐹹 +xn--3-prc71ls9j..xn--xo0dw109an237f; \u084E\u067A\u0DD33..𐹹𞱩󠃪; [B1, V7, X4_2]; xn--3-prc71ls9j..xn--xo0dw109an237f; [B1, V7, A4_2]; ; # ࡎٺී3..𐹹 +xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; \u084E\u067A\u0DD33..𐹹𞱩󠃪\u200C; [B1, C1, V7, X4_2]; xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; [B1, C1, V7, A4_2]; ; # ࡎٺී3..𐹹 +xn--zib94gfziuq1a.xn--xo0dw109an237f; \u084E\u067A\u0DD3⒊.𐹹𞱩󠃪; [B1, V7]; xn--zib94gfziuq1a.xn--xo0dw109an237f; ; ; # ࡎٺී⒊.𐹹 +xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; \u084E\u067A\u0DD3⒊.𐹹𞱩󠃪\u200C; [B1, C1, V7]; xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ; ; # ࡎٺී⒊.𐹹 +ς\u200D-.Ⴣ𦟙; ς\u200D-.ⴣ𦟙; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # ς-.ⴣ𦟙 +ς\u200D-.ⴣ𦟙; ; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # ς-.ⴣ𦟙 +Σ\u200D-.Ⴣ𦟙; σ\u200D-.ⴣ𦟙; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # σ-.ⴣ𦟙 +σ\u200D-.ⴣ𦟙; ; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # σ-.ⴣ𦟙 +xn----zmb.xn--rlj2573p; σ-.ⴣ𦟙; [V3]; xn----zmb.xn--rlj2573p; ; ; # σ-.ⴣ𦟙 +xn----zmb048s.xn--rlj2573p; σ\u200D-.ⴣ𦟙; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; ; # σ-.ⴣ𦟙 +xn----xmb348s.xn--rlj2573p; ς\u200D-.ⴣ𦟙; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; ; # ς-.ⴣ𦟙 +xn----zmb.xn--7nd64871a; σ-.Ⴣ𦟙; [V3, V7]; xn----zmb.xn--7nd64871a; ; ; # σ-.Ⴣ𦟙 +xn----zmb048s.xn--7nd64871a; σ\u200D-.Ⴣ𦟙; [C2, V3, V7]; xn----zmb048s.xn--7nd64871a; ; ; # σ-.Ⴣ𦟙 +xn----xmb348s.xn--7nd64871a; ς\u200D-.Ⴣ𦟙; [C2, V3, V7]; xn----xmb348s.xn--7nd64871a; ; ; # ς-.Ⴣ𦟙 +≠。🞳𝟲; ≠.🞳6; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +=\u0338。🞳𝟲; ≠.🞳6; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +≠。🞳6; ≠.🞳6; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +=\u0338。🞳6; ≠.🞳6; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +xn--1ch.xn--6-dl4s; ≠.🞳6; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +≠.🞳6; ; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +=\u0338.🞳6; ≠.🞳6; ; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6 +󅬽.蠔; ; [V7]; xn--g747d.xn--xl2a; ; ; # .蠔 +xn--g747d.xn--xl2a; 󅬽.蠔; [V7]; xn--g747d.xn--xl2a; ; ; # .蠔 +\u08E6\u200D.뼽; \u08E6\u200D.뼽; [C2, V6]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V6] # ࣦ.뼽 +\u08E6\u200D.뼽; \u08E6\u200D.뼽; [C2, V6]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V6] # ࣦ.뼽 +\u08E6\u200D.뼽; ; [C2, V6]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V6] # ࣦ.뼽 +\u08E6\u200D.뼽; \u08E6\u200D.뼽; [C2, V6]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V6] # ࣦ.뼽 +xn--p0b.xn--e43b; \u08E6.뼽; [V6]; xn--p0b.xn--e43b; ; ; # ࣦ.뼽 +xn--p0b869i.xn--e43b; \u08E6\u200D.뼽; [C2, V6]; xn--p0b869i.xn--e43b; ; ; # ࣦ.뼽 +₇\u0BCD􃂷\u06D2。👖\u0675-𞪑; 7\u0BCD􃂷\u06D2.👖\u0627\u0674-𞪑; [B1, V7]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ- +7\u0BCD􃂷\u06D2。👖\u0627\u0674-𞪑; 7\u0BCD􃂷\u06D2.👖\u0627\u0674-𞪑; [B1, V7]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ- +xn--7-rwc839aj3073c.xn----ymc5uv818oghka; 7\u0BCD􃂷\u06D2.👖\u0627\u0674-𞪑; [B1, V7]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ- +-。\u077B; -.\u077B; [B1, V3]; -.xn--cqb; ; ; # -.ݻ +-。\u077B; -.\u077B; [B1, V3]; -.xn--cqb; ; ; # -.ݻ +-.xn--cqb; -.\u077B; [B1, V3]; -.xn--cqb; ; ; # -.ݻ +𑇌𵛓。-⒈ꡏ\u072B; 𑇌𵛓.-⒈ꡏ\u072B; [B1, V3, V6, V7]; xn--8d1dg030h.xn----u1c466tp10j; ; ; # 𑇌.-⒈ꡏܫ +𑇌𵛓。-1.ꡏ\u072B; 𑇌𵛓.-1.ꡏ\u072B; [B1, B5, B6, V3, V6, V7]; xn--8d1dg030h.-1.xn--1nb7163f; ; ; # 𑇌.-1.ꡏܫ +xn--8d1dg030h.-1.xn--1nb7163f; 𑇌𵛓.-1.ꡏ\u072B; [B1, B5, B6, V3, V6, V7]; xn--8d1dg030h.-1.xn--1nb7163f; ; ; # 𑇌.-1.ꡏܫ +xn--8d1dg030h.xn----u1c466tp10j; 𑇌𵛓.-⒈ꡏ\u072B; [B1, V3, V6, V7]; xn--8d1dg030h.xn----u1c466tp10j; ; ; # 𑇌.-⒈ꡏܫ +璛\u1734\u06AF.-; ; [B1, B5, B6, V3]; xn--ikb175frt4e.-; ; ; # 璛᜴گ.- +xn--ikb175frt4e.-; 璛\u1734\u06AF.-; [B1, B5, B6, V3]; xn--ikb175frt4e.-; ; ; # 璛᜴گ.- +󠆰\u08A1\u0A4D샕.𐹲휁; \u08A1\u0A4D샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁 +󠆰\u08A1\u0A4D샕.𐹲휁; \u08A1\u0A4D샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁 +󠆰\u08A1\u0A4D샕.𐹲휁; \u08A1\u0A4D샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁 +󠆰\u08A1\u0A4D샕.𐹲휁; \u08A1\u0A4D샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁 +xn--qyb07fj857a.xn--728bv72h; \u08A1\u0A4D샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁 +񍨽.񋸕; 񍨽.񋸕; [V7]; xn--pr3x.xn--rv7w; ; ; # . +񍨽.񋸕; ; [V7]; xn--pr3x.xn--rv7w; ; ; # . +xn--pr3x.xn--rv7w; 񍨽.񋸕; [V7]; xn--pr3x.xn--rv7w; ; ; # . +\u067D𞥕。𑑂𞤶Ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤶Ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤶ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤔Ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤔ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +xn--2ib0338v.xn----zvs0199fo91g; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤶ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤔Ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +\u067D𞥕。𑑂𞤔ⴍ-; \u067D𞥕.𑑂𞤶ⴍ-; [B1, V3, V6]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ- +xn--2ib0338v.xn----w0g2740ro9vg; \u067D𞥕.𑑂𞤶Ⴍ-; [B1, V3, V6, V7]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ- +𐯀𐸉𞧏。񢚧₄Ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V7]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ +𐯀𐸉𞧏。񢚧4Ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V7]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ +𐯀𐸉𞧏。񢚧4ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V7]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ +xn--039c42bq865a.xn--4-wvs27840bnrzm; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V7]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ +𐯀𐸉𞧏。񢚧₄ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V7]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ +xn--039c42bq865a.xn--4-t0g49302fnrzm; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [V7]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ +4\u06BD︒󠑥.≠; ; [B1, V7]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠ +4\u06BD︒󠑥.=\u0338; 4\u06BD︒󠑥.≠; [B1, V7]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠ +4\u06BD。󠑥.≠; 4\u06BD.󠑥.≠; [B1, V7]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠ +4\u06BD。󠑥.=\u0338; 4\u06BD.󠑥.≠; [B1, V7]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠ +xn--4-kvc.xn--5136e.xn--1ch; 4\u06BD.󠑥.≠; [B1, V7]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠ +xn--4-kvc5601q2h50i.xn--1ch; 4\u06BD︒󠑥.≠; [B1, V7]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠ +𝟓。\u06D7; 5.\u06D7; [V6]; 5.xn--nlb; ; ; # 5.ۗ +5。\u06D7; 5.\u06D7; [V6]; 5.xn--nlb; ; ; # 5.ۗ +5.xn--nlb; 5.\u06D7; [V6]; 5.xn--nlb; ; ; # 5.ۗ +\u200C򺸩.⾕; \u200C򺸩.谷; [C1, V7]; xn--0ug26167i.xn--6g3a; ; xn--i183d.xn--6g3a; [V7] # .谷 +\u200C򺸩.谷; ; [C1, V7]; xn--0ug26167i.xn--6g3a; ; xn--i183d.xn--6g3a; [V7] # .谷 +xn--i183d.xn--6g3a; 򺸩.谷; [V7]; xn--i183d.xn--6g3a; ; ; # .谷 +xn--0ug26167i.xn--6g3a; \u200C򺸩.谷; [C1, V7]; xn--0ug26167i.xn--6g3a; ; ; # .谷 +︒󎰇\u200D.-\u073C\u200C; ; [C1, C2, V3, V7]; xn--1ug1658ftw26f.xn----t2c071q; ; xn--y86c71305c.xn----t2c; [V3, V7] # ︒.-ܼ +。󎰇\u200D.-\u073C\u200C; .󎰇\u200D.-\u073C\u200C; [C1, C2, V3, V7, X4_2]; .xn--1ug05310k.xn----t2c071q; [C1, C2, V3, V7, A4_2]; .xn--hh50e.xn----t2c; [V3, V7, A4_2] # ..-ܼ +.xn--hh50e.xn----t2c; .󎰇.-\u073C; [V3, V7, X4_2]; .xn--hh50e.xn----t2c; [V3, V7, A4_2]; ; # ..-ܼ +.xn--1ug05310k.xn----t2c071q; .󎰇\u200D.-\u073C\u200C; [C1, C2, V3, V7, X4_2]; .xn--1ug05310k.xn----t2c071q; [C1, C2, V3, V7, A4_2]; ; # ..-ܼ +xn--y86c71305c.xn----t2c; ︒󎰇.-\u073C; [V3, V7]; xn--y86c71305c.xn----t2c; ; ; # ︒.-ܼ +xn--1ug1658ftw26f.xn----t2c071q; ︒󎰇\u200D.-\u073C\u200C; [C1, C2, V3, V7]; xn--1ug1658ftw26f.xn----t2c071q; ; ; # ︒.-ܼ +≯𞤟。ᡨ; ≯𞥁.ᡨ; [B1]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ +>\u0338𞤟。ᡨ; ≯𞥁.ᡨ; [B1]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ +>\u0338𞥁。ᡨ; ≯𞥁.ᡨ; [B1]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ +≯𞥁。ᡨ; ≯𞥁.ᡨ; [B1]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ +xn--hdhz520p.xn--48e; ≯𞥁.ᡨ; [B1]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ +\u0F74𫫰𝨄。\u0713𐹦; \u0F74𫫰𝨄.\u0713𐹦; [B1, V6]; xn--ned8985uo92e.xn--dnb6395k; ; ; # ུ𫫰𝨄.ܓ𐹦 +xn--ned8985uo92e.xn--dnb6395k; \u0F74𫫰𝨄.\u0713𐹦; [B1, V6]; xn--ned8985uo92e.xn--dnb6395k; ; ; # ུ𫫰𝨄.ܓ𐹦 +\u033C\u07DB⁷𝟹。𝟬; \u033C\u07DB73.0; [B1, V6]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0 +\u033C\u07DB73。0; \u033C\u07DB73.0; [B1, V6]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0 +xn--73-9yb648b.a; \u033C\u07DB73.a; [B1, V6]; xn--73-9yb648b.a; ; ; # ̼ߛ73.a +\u200D.𝟗; \u200D.9; [C2]; xn--1ug.9; ; .9; [A4_2] # .9 +\u200D.j; ; [C2]; xn--1ug.j; ; .j; [A4_2] # .j +\u200D.J; \u200D.j; [C2]; xn--1ug.j; ; .j; [A4_2] # .j +.j; ; [X4_2]; ; [A4_2]; ; # .j +xn--1ug.j; \u200D.j; [C2]; xn--1ug.j; ; ; # .j +j; ; ; ; ; ; # j +\u0779ᡭ𪕈。\u06B6\u08D9; \u0779ᡭ𪕈.\u06B6\u08D9; [B2, B3]; xn--9pb497fs270c.xn--pkb80i; ; ; # ݹᡭ𪕈.ڶࣙ +xn--9pb497fs270c.xn--pkb80i; \u0779ᡭ𪕈.\u06B6\u08D9; [B2, B3]; xn--9pb497fs270c.xn--pkb80i; ; ; # ݹᡭ𪕈.ڶࣙ +\u07265\u07E2겙。\u1CF4𐷚; \u07265\u07E2겙.\u1CF4𐷚; [B1, B2, B3, V6, V7]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴ +\u07265\u07E2겙。\u1CF4𐷚; \u07265\u07E2겙.\u1CF4𐷚; [B1, B2, B3, V6, V7]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴ +\u07265\u07E2겙。\u1CF4𐷚; \u07265\u07E2겙.\u1CF4𐷚; [B1, B2, B3, V6, V7]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴ +\u07265\u07E2겙。\u1CF4𐷚; \u07265\u07E2겙.\u1CF4𐷚; [B1, B2, B3, V6, V7]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴ +xn--5-j1c97c2483c.xn--e7f2093h; \u07265\u07E2겙.\u1CF4𐷚; [B1, B2, B3, V6, V7]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴ +Ⴍ𿣍ꡨ\u05AE。Ⴞ\u200C\u200C; ⴍ𿣍ꡨ\u05AE.ⴞ\u200C\u200C; [C1, V7]; xn--5cb172r175fug38a.xn--0uga051h; ; xn--5cb172r175fug38a.xn--mlj; [V7] # ⴍꡨ֮.ⴞ +ⴍ𿣍ꡨ\u05AE。ⴞ\u200C\u200C; ⴍ𿣍ꡨ\u05AE.ⴞ\u200C\u200C; [C1, V7]; xn--5cb172r175fug38a.xn--0uga051h; ; xn--5cb172r175fug38a.xn--mlj; [V7] # ⴍꡨ֮.ⴞ +xn--5cb172r175fug38a.xn--mlj; ⴍ𿣍ꡨ\u05AE.ⴞ; [V7]; xn--5cb172r175fug38a.xn--mlj; ; ; # ⴍꡨ֮.ⴞ +xn--5cb172r175fug38a.xn--0uga051h; ⴍ𿣍ꡨ\u05AE.ⴞ\u200C\u200C; [C1, V7]; xn--5cb172r175fug38a.xn--0uga051h; ; ; # ⴍꡨ֮.ⴞ +xn--5cb347co96jug15a.xn--2nd; Ⴍ𿣍ꡨ\u05AE.Ⴞ; [V7]; xn--5cb347co96jug15a.xn--2nd; ; ; # Ⴍꡨ֮.Ⴞ +xn--5cb347co96jug15a.xn--2nd059ea; Ⴍ𿣍ꡨ\u05AE.Ⴞ\u200C\u200C; [C1, V7]; xn--5cb347co96jug15a.xn--2nd059ea; ; ; # Ⴍꡨ֮.Ⴞ +𐋰。󑓱; 𐋰.󑓱; [V7]; xn--k97c.xn--q031e; ; ; # 𐋰. +xn--k97c.xn--q031e; 𐋰.󑓱; [V7]; xn--k97c.xn--q031e; ; ; # 𐋰. +󡎦\u17B4\u0B4D.𐹾; 󡎦\u0B4D.𐹾; [B1, V7]; xn--9ic59305p.xn--2o0d; ; ; # ୍.𐹾 +xn--9ic59305p.xn--2o0d; 󡎦\u0B4D.𐹾; [B1, V7]; xn--9ic59305p.xn--2o0d; ; ; # ୍.𐹾 +xn--9ic364dho91z.xn--2o0d; 󡎦\u17B4\u0B4D.𐹾; [B1, V7]; xn--9ic364dho91z.xn--2o0d; ; ; # ୍.𐹾 +\u08DFႫ𶿸귤.򠅼𝟢휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFႫ𶿸귤.򠅼𝟢휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFႫ𶿸귤.򠅼0휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFႫ𶿸귤.򠅼0휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFⴋ𶿸귤.򠅼0휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFⴋ𶿸귤.򠅼0휪\u0AE3; ; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFⴋ𶿸귤.򠅼𝟢휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +\u08DFⴋ𶿸귤.򠅼𝟢휪\u0AE3; \u08DFⴋ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ +xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; \u08DFႫ𶿸귤.򠅼0휪\u0AE3; [V6, V7]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ +\u0784.𞡝\u0601; \u0784.𞡝\u0601; [V7]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝 +\u0784.𞡝\u0601; ; [V7]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝 +xn--lqb.xn--jfb1808v; \u0784.𞡝\u0601; [V7]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝 +\u0ACD₃.8\uA8C4\u200D🃤; \u0ACD3.8\uA8C4\u200D🃤; [V6]; xn--3-yke.xn--8-ugnv982dbkwm; ; xn--3-yke.xn--8-sl4et308f; # ્3.8꣄🃤 +\u0ACD3.8\uA8C4\u200D🃤; ; [V6]; xn--3-yke.xn--8-ugnv982dbkwm; ; xn--3-yke.xn--8-sl4et308f; # ્3.8꣄🃤 +xn--3-yke.xn--8-sl4et308f; \u0ACD3.8\uA8C4🃤; [V6]; xn--3-yke.xn--8-sl4et308f; ; ; # ્3.8꣄🃤 +xn--3-yke.xn--8-ugnv982dbkwm; \u0ACD3.8\uA8C4\u200D🃤; [V6]; xn--3-yke.xn--8-ugnv982dbkwm; ; ; # ્3.8꣄🃤 +℻⩷𝆆。𞤠󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +FAX⩷𝆆。𞤠󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +fax⩷𝆆。𞥂󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +Fax⩷𝆆。𞤠󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +xn--fax-4c9a1676t.xn--6e6h; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +℻⩷𝆆。𞥂󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +FAX⩷𝆆。𞥂󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +fax⩷𝆆。𞤠󠆁\u180C; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +fax⩷𝆆.𞥂; ; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +FAX⩷𝆆.𞤠; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +Fax⩷𝆆.𞤠; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +FAX⩷𝆆.𞥂; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +Fax⩷𝆆.𞥂; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂 +ꡕ≠\u105E󮿱。𐵧󠄫\uFFA0; ꡕ≠\u105E󮿱.𐵧; [V7]; xn--cld333gn31h0158l.xn--3g0d; ; ; # ꡕ≠ၞ. +ꡕ=\u0338\u105E󮿱。𐵧󠄫\uFFA0; ꡕ≠\u105E󮿱.𐵧; [V7]; xn--cld333gn31h0158l.xn--3g0d; ; ; # ꡕ≠ၞ. +ꡕ≠\u105E󮿱。𐵧󠄫\u1160; ꡕ≠\u105E󮿱.𐵧; [V7]; xn--cld333gn31h0158l.xn--3g0d; ; ; # ꡕ≠ၞ. +ꡕ=\u0338\u105E󮿱。𐵧󠄫\u1160; ꡕ≠\u105E󮿱.𐵧; [V7]; xn--cld333gn31h0158l.xn--3g0d; ; ; # ꡕ≠ၞ. +xn--cld333gn31h0158l.xn--3g0d; ꡕ≠\u105E󮿱.𐵧; [V7]; xn--cld333gn31h0158l.xn--3g0d; ; ; # ꡕ≠ၞ. +xn--cld333gn31h0158l.xn--psd1510k; ꡕ≠\u105E󮿱.𐵧\u1160; [B2, B3, V7]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ. +xn--cld333gn31h0158l.xn--cl7c96v; ꡕ≠\u105E󮿱.𐵧\uFFA0; [B2, B3, V7]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ. +鱊。\u200C; 鱊.\u200C; [C1]; xn--rt6a.xn--0ug; ; xn--rt6a.; [A4_2] # 鱊. +xn--rt6a.; 鱊.; ; xn--rt6a.; [A4_2]; ; # 鱊. +鱊.; ; ; xn--rt6a.; [A4_2]; ; # 鱊. +xn--rt6a.xn--0ug; 鱊.\u200C; [C1]; xn--rt6a.xn--0ug; ; ; # 鱊. +8𐹣.𑍨; 8𐹣.𑍨; [B1, V6]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨 +8𐹣.𑍨; ; [B1, V6]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨 +xn--8-d26i.xn--0p1d; 8𐹣.𑍨; [B1, V6]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨 +⏹𐧀.𐫯; ⏹𐧀.𐫯; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯 +⏹𐧀.𐫯; ; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯 +xn--qoh9161g.xn--1x9c; ⏹𐧀.𐫯; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯 +𞤺\u07CC4.\u200D; 𞤺\u07CC4.\u200D; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [A4_2] # 𞤺ߌ4. +𞤺\u07CC4.\u200D; ; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [A4_2] # 𞤺ߌ4. +𞤘\u07CC4.\u200D; 𞤺\u07CC4.\u200D; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [A4_2] # 𞤺ߌ4. +xn--4-0bd15808a.; 𞤺\u07CC4.; ; xn--4-0bd15808a.; [A4_2]; ; # 𞤺ߌ4. +𞤺\u07CC4.; ; ; xn--4-0bd15808a.; [A4_2]; ; # 𞤺ߌ4. +𞤘\u07CC4.; 𞤺\u07CC4.; ; xn--4-0bd15808a.; [A4_2]; ; # 𞤺ߌ4. +xn--4-0bd15808a.xn--1ug; 𞤺\u07CC4.\u200D; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; ; # 𞤺ߌ4. +𞤘\u07CC4.\u200D; 𞤺\u07CC4.\u200D; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [A4_2] # 𞤺ߌ4. +⒗\u0981\u20EF-.\u08E2•; ; [B1, V3, V7]; xn----z0d801p6kd.xn--l0b810j; ; ; # ⒗ঁ⃯-.• +16.\u0981\u20EF-.\u08E2•; ; [B1, V3, V6, V7]; 16.xn----z0d801p.xn--l0b810j; ; ; # 16.ঁ⃯-.• +16.xn----z0d801p.xn--l0b810j; 16.\u0981\u20EF-.\u08E2•; [B1, V3, V6, V7]; 16.xn----z0d801p.xn--l0b810j; ; ; # 16.ঁ⃯-.• +xn----z0d801p6kd.xn--l0b810j; ⒗\u0981\u20EF-.\u08E2•; [B1, V3, V7]; xn----z0d801p6kd.xn--l0b810j; ; ; # ⒗ঁ⃯-.• +-。䏛; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛 +-。䏛; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛 +-.xn--xco; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛 +\u200C񒃠.\u200D; \u200C񒃠.\u200D; [C1, C2, V7]; xn--0ugz7551c.xn--1ug; ; xn--dj8y.; [V7, A4_2] # . +\u200C񒃠.\u200D; ; [C1, C2, V7]; xn--0ugz7551c.xn--1ug; ; xn--dj8y.; [V7, A4_2] # . +xn--dj8y.; 񒃠.; [V7]; xn--dj8y.; [V7, A4_2]; ; # . +xn--0ugz7551c.xn--1ug; \u200C񒃠.\u200D; [C1, C2, V7]; xn--0ugz7551c.xn--1ug; ; ; # . +⒈⓰󥣇。𐹠\u200D򗷦Ⴕ; ⒈⓰󥣇.𐹠\u200D򗷦ⴕ; [B1, C2, V7]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; xn--tsh0nz9380h.xn--dljv223ee5t2d; [B1, V7] # ⒈⓰.𐹠ⴕ +1.⓰󥣇。𐹠\u200D򗷦Ⴕ; 1.⓰󥣇.𐹠\u200D򗷦ⴕ; [B1, C2, V7]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; 1.xn--svh00804k.xn--dljv223ee5t2d; [B1, V7] # 1.⓰.𐹠ⴕ +1.⓰󥣇。𐹠\u200D򗷦ⴕ; 1.⓰󥣇.𐹠\u200D򗷦ⴕ; [B1, C2, V7]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; 1.xn--svh00804k.xn--dljv223ee5t2d; [B1, V7] # 1.⓰.𐹠ⴕ +1.xn--svh00804k.xn--dljv223ee5t2d; 1.⓰󥣇.𐹠򗷦ⴕ; [B1, V7]; 1.xn--svh00804k.xn--dljv223ee5t2d; ; ; # 1.⓰.𐹠ⴕ +1.xn--svh00804k.xn--1ug352csp0psg45e; 1.⓰󥣇.𐹠\u200D򗷦ⴕ; [B1, C2, V7]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; ; # 1.⓰.𐹠ⴕ +⒈⓰󥣇。𐹠\u200D򗷦ⴕ; ⒈⓰󥣇.𐹠\u200D򗷦ⴕ; [B1, C2, V7]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; xn--tsh0nz9380h.xn--dljv223ee5t2d; [B1, V7] # ⒈⓰.𐹠ⴕ +xn--tsh0nz9380h.xn--dljv223ee5t2d; ⒈⓰󥣇.𐹠򗷦ⴕ; [B1, V7]; xn--tsh0nz9380h.xn--dljv223ee5t2d; ; ; # ⒈⓰.𐹠ⴕ +xn--tsh0nz9380h.xn--1ug352csp0psg45e; ⒈⓰󥣇.𐹠\u200D򗷦ⴕ; [B1, C2, V7]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; ; # ⒈⓰.𐹠ⴕ +1.xn--svh00804k.xn--tnd1990ke579c; 1.⓰󥣇.𐹠򗷦Ⴕ; [B1, V7]; 1.xn--svh00804k.xn--tnd1990ke579c; ; ; # 1.⓰.𐹠Ⴕ +1.xn--svh00804k.xn--tnd969erj4psgl3e; 1.⓰󥣇.𐹠\u200D򗷦Ⴕ; [B1, C2, V7]; 1.xn--svh00804k.xn--tnd969erj4psgl3e; ; ; # 1.⓰.𐹠Ⴕ +xn--tsh0nz9380h.xn--tnd1990ke579c; ⒈⓰󥣇.𐹠򗷦Ⴕ; [B1, V7]; xn--tsh0nz9380h.xn--tnd1990ke579c; ; ; # ⒈⓰.𐹠Ⴕ +xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ⒈⓰󥣇.𐹠\u200D򗷦Ⴕ; [B1, C2, V7]; xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ; ; # ⒈⓰.𐹠Ⴕ +𞠊ᠮ-ß。\u1CD0効\u0601𷣭; 𞠊ᠮ-ß.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; xn---ss-21t18904a.xn--jfb197i791bi6x4c; # 𞠊ᠮ-ß.᳐効 +𞠊ᠮ-ß。\u1CD0効\u0601𷣭; 𞠊ᠮ-ß.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; xn---ss-21t18904a.xn--jfb197i791bi6x4c; # 𞠊ᠮ-ß.᳐効 +𞠊ᠮ-SS。\u1CD0効\u0601𷣭; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +𞠊ᠮ-ss。\u1CD0効\u0601𷣭; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +𞠊ᠮ-Ss。\u1CD0効\u0601𷣭; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +xn---ss-21t18904a.xn--jfb197i791bi6x4c; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +xn----qfa310pg973b.xn--jfb197i791bi6x4c; 𞠊ᠮ-ß.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ß.᳐効 +𞠊ᠮ-SS。\u1CD0効\u0601𷣭; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +𞠊ᠮ-ss。\u1CD0効\u0601𷣭; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +𞠊ᠮ-Ss。\u1CD0効\u0601𷣭; 𞠊ᠮ-ss.\u1CD0効\u0601𷣭; [B1, B2, B3, V6, V7]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効 +𑇀.󠨱; ; [V6, V7]; xn--wd1d.xn--k946e; ; ; # 𑇀. +xn--wd1d.xn--k946e; 𑇀.󠨱; [V6, V7]; xn--wd1d.xn--k946e; ; ; # 𑇀. +␒3\uFB88。𝟘𐨿𐹆; ␒3\u0688.0𐨿𐹆; [B1, V7]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿 +␒3\u0688。0𐨿𐹆; ␒3\u0688.0𐨿𐹆; [B1, V7]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿 +xn--3-jsc897t.xn--0-sc5iy3h; ␒3\u0688.0𐨿𐹆; [B1, V7]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿 +\u076B6\u0A81\u08A6。\u1DE3; \u076B6\u0A81\u08A6.\u1DE3; [B1, V6]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ +\u076B6\u0A81\u08A6。\u1DE3; \u076B6\u0A81\u08A6.\u1DE3; [B1, V6]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ +xn--6-h5c06gj6c.xn--7eg; \u076B6\u0A81\u08A6.\u1DE3; [B1, V6]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ +\u0605-𽤞Ⴂ。򅤶\u200D; \u0605-𽤞ⴂ.򅤶\u200D; [B1, B6, C2, V7]; xn----0kc8501a5399e.xn--1ugy3204f; ; xn----0kc8501a5399e.xn--ss06b; [B1, V7] # -ⴂ. +\u0605-𽤞ⴂ。򅤶\u200D; \u0605-𽤞ⴂ.򅤶\u200D; [B1, B6, C2, V7]; xn----0kc8501a5399e.xn--1ugy3204f; ; xn----0kc8501a5399e.xn--ss06b; [B1, V7] # -ⴂ. +xn----0kc8501a5399e.xn--ss06b; \u0605-𽤞ⴂ.򅤶; [B1, V7]; xn----0kc8501a5399e.xn--ss06b; ; ; # -ⴂ. +xn----0kc8501a5399e.xn--1ugy3204f; \u0605-𽤞ⴂ.򅤶\u200D; [B1, B6, C2, V7]; xn----0kc8501a5399e.xn--1ugy3204f; ; ; # -ⴂ. +xn----0kc662fc152h.xn--ss06b; \u0605-𽤞Ⴂ.򅤶; [B1, V7]; xn----0kc662fc152h.xn--ss06b; ; ; # -Ⴂ. +xn----0kc662fc152h.xn--1ugy3204f; \u0605-𽤞Ⴂ.򅤶\u200D; [B1, B6, C2, V7]; xn----0kc662fc152h.xn--1ugy3204f; ; ; # -Ⴂ. +⾆.ꡈ5≯ß; 舌.ꡈ5≯ß; ; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß +⾆.ꡈ5>\u0338ß; 舌.ꡈ5≯ß; ; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß +舌.ꡈ5≯ß; ; ; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß +舌.ꡈ5>\u0338ß; 舌.ꡈ5≯ß; ; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß +舌.ꡈ5>\u0338SS; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +舌.ꡈ5≯SS; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +舌.ꡈ5≯ss; ; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +舌.ꡈ5>\u0338ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +舌.ꡈ5>\u0338Ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +舌.ꡈ5≯Ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +xn--tc1a.xn--5ss-3m2a5009e; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +xn--tc1a.xn--5-qfa988w745i; 舌.ꡈ5≯ß; ; xn--tc1a.xn--5-qfa988w745i; ; ; # 舌.ꡈ5≯ß +⾆.ꡈ5>\u0338SS; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +⾆.ꡈ5≯SS; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +⾆.ꡈ5≯ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +⾆.ꡈ5>\u0338ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +⾆.ꡈ5>\u0338Ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +⾆.ꡈ5≯Ss; 舌.ꡈ5≯ss; ; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss +\u0ACD8\u200D.򾂈\u075C; \u0ACD8\u200D.򾂈\u075C; [B1, B5, B6, C2, V6, V7]; xn--8-yke534n.xn--gpb79046m; ; xn--8-yke.xn--gpb79046m; [B1, B5, B6, V6, V7] # ્8.ݜ +\u0ACD8\u200D.򾂈\u075C; ; [B1, B5, B6, C2, V6, V7]; xn--8-yke534n.xn--gpb79046m; ; xn--8-yke.xn--gpb79046m; [B1, B5, B6, V6, V7] # ્8.ݜ +xn--8-yke.xn--gpb79046m; \u0ACD8.򾂈\u075C; [B1, B5, B6, V6, V7]; xn--8-yke.xn--gpb79046m; ; ; # ્8.ݜ +xn--8-yke534n.xn--gpb79046m; \u0ACD8\u200D.򾂈\u075C; [B1, B5, B6, C2, V6, V7]; xn--8-yke534n.xn--gpb79046m; ; ; # ્8.ݜ +򸷆\u0A70≮򹓙.񞎧⁷󠯙\u06B6; 򸷆\u0A70≮򹓙.񞎧7󠯙\u06B6; [B5, B6, V7]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ +򸷆\u0A70<\u0338򹓙.񞎧⁷󠯙\u06B6; 򸷆\u0A70≮򹓙.񞎧7󠯙\u06B6; [B5, B6, V7]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ +򸷆\u0A70≮򹓙.񞎧7󠯙\u06B6; ; [B5, B6, V7]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ +򸷆\u0A70<\u0338򹓙.񞎧7󠯙\u06B6; 򸷆\u0A70≮򹓙.񞎧7󠯙\u06B6; [B5, B6, V7]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ +xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; 򸷆\u0A70≮򹓙.񞎧7󠯙\u06B6; [B5, B6, V7]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ +𞤪.ς; ; ; xn--ie6h.xn--3xa; ; xn--ie6h.xn--4xa; # 𞤪.ς +𞤈.Σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ +𞤪.σ; ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ +𞤈.σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ +xn--ie6h.xn--4xa; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ +𞤈.ς; 𞤪.ς; ; xn--ie6h.xn--3xa; ; xn--ie6h.xn--4xa; # 𞤪.ς +xn--ie6h.xn--3xa; 𞤪.ς; ; xn--ie6h.xn--3xa; ; ; # 𞤪.ς +𞤪.Σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ +\u200CႺ。ς; \u200Cⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς +\u200CႺ。ς; \u200Cⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς +\u200Cⴚ。ς; \u200Cⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς +\u200CႺ。Σ; \u200Cⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ +\u200Cⴚ。σ; \u200Cⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ +xn--ilj.xn--4xa; ⴚ.σ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ +ⴚ.σ; ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ +Ⴚ.Σ; ⴚ.σ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ +ⴚ.ς; ; ; xn--ilj.xn--3xa; ; xn--ilj.xn--4xa; # ⴚ.ς +Ⴚ.ς; ⴚ.ς; ; xn--ilj.xn--3xa; ; xn--ilj.xn--4xa; # ⴚ.ς +xn--ilj.xn--3xa; ⴚ.ς; ; xn--ilj.xn--3xa; ; ; # ⴚ.ς +Ⴚ.σ; ⴚ.σ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ +xn--0ug262c.xn--4xa; \u200Cⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; ; # ⴚ.σ +xn--0ug262c.xn--3xa; \u200Cⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; ; # ⴚ.ς +\u200Cⴚ。ς; \u200Cⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς +\u200CႺ。Σ; \u200Cⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ +\u200Cⴚ。σ; \u200Cⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ +xn--ynd.xn--4xa; Ⴚ.σ; [V7]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ +xn--ynd.xn--3xa; Ⴚ.ς; [V7]; xn--ynd.xn--3xa; ; ; # Ⴚ.ς +xn--ynd759e.xn--4xa; \u200CႺ.σ; [C1, V7]; xn--ynd759e.xn--4xa; ; ; # Ⴚ.σ +xn--ynd759e.xn--3xa; \u200CႺ.ς; [C1, V7]; xn--ynd759e.xn--3xa; ; ; # Ⴚ.ς +𞤃.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦 +𞤃.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦 +𞤥.𐹦; ; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦 +xn--de6h.xn--eo0d; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦 +𞤥.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦 +\u200D⾕。\u200C\u0310\uA953ꡎ; \u200D谷.\u200C\uA953\u0310ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V6] # 谷.꥓̐ꡎ +\u200D⾕。\u200C\uA953\u0310ꡎ; \u200D谷.\u200C\uA953\u0310ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V6] # 谷.꥓̐ꡎ +\u200D谷。\u200C\uA953\u0310ꡎ; \u200D谷.\u200C\uA953\u0310ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V6] # 谷.꥓̐ꡎ +xn--6g3a.xn--0sa8175flwa; 谷.\uA953\u0310ꡎ; [V6]; xn--6g3a.xn--0sa8175flwa; ; ; # 谷.꥓̐ꡎ +xn--1ug0273b.xn--0sa359l6n7g13a; \u200D谷.\u200C\uA953\u0310ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; ; # 谷.꥓̐ꡎ +\u06AA-뉔.𞤐\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +\u06AA-뉔.𞤐\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +\u06AA-뉔.𞤐\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +\u06AA-뉔.𞤐\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +\u06AA-뉔.𞤲\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +\u06AA-뉔.𞤲\u200C; ; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +xn----guc3592k.xn--qe6h; \u06AA-뉔.𞤲; [B2, B3]; xn----guc3592k.xn--qe6h; ; ; # ڪ-뉔.𞤲 +xn----guc3592k.xn--0ug7611p; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; ; # ڪ-뉔.𞤲 +\u06AA-뉔.𞤲\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +\u06AA-뉔.𞤲\u200C; \u06AA-뉔.𞤲\u200C; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲 +񔲵5ᦛς.\uA8C4\u077B\u1CD2\u0738; 񔲵5ᦛς.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒ +񔲵5ᦛς.\uA8C4\u077B\u0738\u1CD2; 񔲵5ᦛς.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒ +񔲵5ᦛς.\uA8C4\u077B\u0738\u1CD2; ; [B1, V6, V7]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒ +񔲵5ᦛΣ.\uA8C4\u077B\u0738\u1CD2; 񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; ; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +xn--5-0mb988ng603j.xn--fob7kk44dl41k; 񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +xn--5-ymb298ng603j.xn--fob7kk44dl41k; 񔲵5ᦛς.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛς.꣄ݻܸ᳒ +񔲵5ᦛΣ.\uA8C4\u077B\u0738\u1CD2; 񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; 񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +񔲵5ᦛΣ.\uA8C4\u077B\u1CD2\u0738; 񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +񔲵5ᦛσ.\uA8C4\u077B\u1CD2\u0738; 񔲵5ᦛσ.\uA8C4\u077B\u0738\u1CD2; [B1, V6, V7]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒ +淽。ᠾ; 淽.ᠾ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ +xn--34w.xn--x7e; 淽.ᠾ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ +淽.ᠾ; ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ +𐹴𑘷。-; 𐹴𑘷.-; [B1, V3]; xn--so0do6k.-; ; ; # 𐹴𑘷.- +xn--so0do6k.-; 𐹴𑘷.-; [B1, V3]; xn--so0do6k.-; ; ; # 𐹴𑘷.- +򬨩Ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [V6, V7]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨 +򬨩Ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [V6, V7]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨 +򬨩ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [V6, V7]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨 +xn--8di78qvw32y.xn--k80d; 򬨩ⴓ❓.𑄨; [V6, V7]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨 +򬨩ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [V6, V7]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨 +xn--rnd896i0j14q.xn--k80d; 򬨩Ⴓ❓.𑄨; [V6, V7]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨 +\u200C𐹡𞤌Ⴇ。ßႣ; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤌Ⴇ。ßႣ; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤮ⴇ。ßⴃ; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤌Ⴇ。SSႣ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u200C𐹡𞤮ⴇ。ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u200C𐹡𞤌ⴇ。Ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +xn--ykj9323eegwf.xn--ss-151a; 𐹡𞤮ⴇ.ssⴃ; [B1]; xn--ykj9323eegwf.xn--ss-151a; ; ; # 𐹡𞤮ⴇ.ssⴃ +xn--0ug332c3q0pr56g.xn--ss-151a; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; ; # 𐹡𞤮ⴇ.ssⴃ +xn--0ug332c3q0pr56g.xn--zca417t; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; ; # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤮ⴇ。ßⴃ; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤌Ⴇ。SSႣ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u200C𐹡𞤮ⴇ。ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u200C𐹡𞤌ⴇ。Ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +xn--fnd1201kegrf.xn--ss-fek; 𐹡𞤮Ⴇ.ssႣ; [B1, V7]; xn--fnd1201kegrf.xn--ss-fek; ; ; # 𐹡𞤮Ⴇ.ssႣ +xn--fnd599eyj4pr50g.xn--ss-fek; \u200C𐹡𞤮Ⴇ.ssႣ; [B1, C1, V7]; xn--fnd599eyj4pr50g.xn--ss-fek; ; ; # 𐹡𞤮Ⴇ.ssႣ +xn--fnd599eyj4pr50g.xn--zca681f; \u200C𐹡𞤮Ⴇ.ßႣ; [B1, C1, V7]; xn--fnd599eyj4pr50g.xn--zca681f; ; ; # 𐹡𞤮Ⴇ.ßႣ +\u200C𐹡𞤌ⴇ。ßⴃ; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤌ⴇ。ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u200C𐹡𞤌Ⴇ。Ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +xn--fnd1201kegrf.xn--ss-151a; 𐹡𞤮Ⴇ.ssⴃ; [B1, V7]; xn--fnd1201kegrf.xn--ss-151a; ; ; # 𐹡𞤮Ⴇ.ssⴃ +xn--fnd599eyj4pr50g.xn--ss-151a; \u200C𐹡𞤮Ⴇ.ssⴃ; [B1, C1, V7]; xn--fnd599eyj4pr50g.xn--ss-151a; ; ; # 𐹡𞤮Ⴇ.ssⴃ +\u200C𐹡𞤌ⴇ。ßⴃ; \u200C𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ +\u200C𐹡𞤌ⴇ。ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u200C𐹡𞤌Ⴇ。Ssⴃ; \u200C𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ +\u17FF。𞬳; \u17FF.𞬳; [V7]; xn--45e.xn--et6h; ; ; # . +\u17FF。𞬳; \u17FF.𞬳; [V7]; xn--45e.xn--et6h; ; ; # . +xn--45e.xn--et6h; \u17FF.𞬳; [V7]; xn--45e.xn--et6h; ; ; # . +\u0652\u200D。\u0CCD𑚳; \u0652\u200D.\u0CCD𑚳; [C2, V6]; xn--uhb882k.xn--8tc4527k; ; xn--uhb.xn--8tc4527k; [V6] # ْ.್𑚳 +\u0652\u200D。\u0CCD𑚳; \u0652\u200D.\u0CCD𑚳; [C2, V6]; xn--uhb882k.xn--8tc4527k; ; xn--uhb.xn--8tc4527k; [V6] # ْ.್𑚳 +xn--uhb.xn--8tc4527k; \u0652.\u0CCD𑚳; [V6]; xn--uhb.xn--8tc4527k; ; ; # ْ.್𑚳 +xn--uhb882k.xn--8tc4527k; \u0652\u200D.\u0CCD𑚳; [C2, V6]; xn--uhb882k.xn--8tc4527k; ; ; # ْ.್𑚳 +-≠ᠻ.\u076D𞥃≮󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-=\u0338ᠻ.\u076D𞥃<\u0338󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-≠ᠻ.\u076D𞥃≮󟷺; ; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-=\u0338ᠻ.\u076D𞥃<\u0338󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-=\u0338ᠻ.\u076D𞤡<\u0338󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-≠ᠻ.\u076D𞤡≮󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +xn----g6j886c.xn--xpb049kk353abj99f; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-=\u0338ᠻ.\u076D𞤡<\u0338󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +-≠ᠻ.\u076D𞤡≮󟷺; -≠ᠻ.\u076D𞥃≮󟷺; [B1, B2, B3, V3, V7]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮ +󠰆≯\u07B5𐻪.򊥕≮𑁆\u084C; 󠰆≯\u07B5𐻪.򊥕≮𑁆\u084C; [B1, B5, B6, V7]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ +󠰆>\u0338\u07B5𐻪.򊥕<\u0338𑁆\u084C; 󠰆≯\u07B5𐻪.򊥕≮𑁆\u084C; [B1, B5, B6, V7]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ +󠰆≯\u07B5𐻪.򊥕≮𑁆\u084C; ; [B1, B5, B6, V7]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ +󠰆>\u0338\u07B5𐻪.򊥕<\u0338𑁆\u084C; 󠰆≯\u07B5𐻪.򊥕≮𑁆\u084C; [B1, B5, B6, V7]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ +xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; 󠰆≯\u07B5𐻪.򊥕≮𑁆\u084C; [B1, B5, B6, V7]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ +≠󦋂.\u0600\u0BCD-\u06B9; ; [B1, V7]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ +=\u0338󦋂.\u0600\u0BCD-\u06B9; ≠󦋂.\u0600\u0BCD-\u06B9; [B1, V7]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ +xn--1ch22084l.xn----qkc07co6n; ≠󦋂.\u0600\u0BCD-\u06B9; [B1, V7]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ +\u17DD󠁣≠。𐹼𐋤; \u17DD󠁣≠.𐹼𐋤; [B1, V6, V7]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤 +\u17DD󠁣=\u0338。𐹼𐋤; \u17DD󠁣≠.𐹼𐋤; [B1, V6, V7]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤 +\u17DD󠁣≠。𐹼𐋤; \u17DD󠁣≠.𐹼𐋤; [B1, V6, V7]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤 +\u17DD󠁣=\u0338。𐹼𐋤; \u17DD󠁣≠.𐹼𐋤; [B1, V6, V7]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤 +xn--54e694cn389z.xn--787ct8r; \u17DD󠁣≠.𐹼𐋤; [B1, V6, V7]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤 +ß𰀻񆬗。𝩨🕮ß; ß𰀻񆬗.𝩨🕮ß; [V6, V7]; xn--zca20040bgrkh.xn--zca3653v86qa; ; xn--ss-jl59biy67d.xn--ss-4d11aw87d; # ß𰀻.𝩨🕮ß +ß𰀻񆬗。𝩨🕮ß; ß𰀻񆬗.𝩨🕮ß; [V6, V7]; xn--zca20040bgrkh.xn--zca3653v86qa; ; xn--ss-jl59biy67d.xn--ss-4d11aw87d; # ß𰀻.𝩨🕮ß +SS𰀻񆬗。𝩨🕮SS; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +ss𰀻񆬗。𝩨🕮ss; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +Ss𰀻񆬗。𝩨🕮Ss; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +xn--ss-jl59biy67d.xn--ss-4d11aw87d; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +xn--zca20040bgrkh.xn--zca3653v86qa; ß𰀻񆬗.𝩨🕮ß; [V6, V7]; xn--zca20040bgrkh.xn--zca3653v86qa; ; ; # ß𰀻.𝩨🕮ß +SS𰀻񆬗。𝩨🕮SS; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +ss𰀻񆬗。𝩨🕮ss; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +Ss𰀻񆬗。𝩨🕮Ss; ss𰀻񆬗.𝩨🕮ss; [V6, V7]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss +\u200D。\u200C; \u200D.\u200C; [C1, C2]; xn--1ug.xn--0ug; ; .; [A4_1, A4_2] # . +xn--1ug.xn--0ug; \u200D.\u200C; [C1, C2]; xn--1ug.xn--0ug; ; ; # . +\u0483𐭞\u200D.\u17B9𞯌򟩚; ; [B1, C2, V6, V7]; xn--m3a412lrr0o.xn--43e8670vmd79b; ; xn--m3a6965k.xn--43e8670vmd79b; [B1, V6, V7] # ҃𐭞.ឹ +xn--m3a6965k.xn--43e8670vmd79b; \u0483𐭞.\u17B9𞯌򟩚; [B1, V6, V7]; xn--m3a6965k.xn--43e8670vmd79b; ; ; # ҃𐭞.ឹ +xn--m3a412lrr0o.xn--43e8670vmd79b; \u0483𐭞\u200D.\u17B9𞯌򟩚; [B1, C2, V6, V7]; xn--m3a412lrr0o.xn--43e8670vmd79b; ; ; # ҃𐭞.ឹ +\u200C𐠨\u200C临。ꡢ򄷞ⶏ𐹣; \u200C𐠨\u200C临.ꡢ򄷞ⶏ𐹣; [B1, B5, B6, C1, V7]; xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ; xn--miq9646b.xn--uojv340bk71c99u9f; [B2, B3, B5, B6, V7] # 𐠨临.ꡢⶏ𐹣 +xn--miq9646b.xn--uojv340bk71c99u9f; 𐠨临.ꡢ򄷞ⶏ𐹣; [B2, B3, B5, B6, V7]; xn--miq9646b.xn--uojv340bk71c99u9f; ; ; # 𐠨临.ꡢⶏ𐹣 +xn--0uga2656aop9k.xn--uojv340bk71c99u9f; \u200C𐠨\u200C临.ꡢ򄷞ⶏ𐹣; [B1, B5, B6, C1, V7]; xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ; ; # 𐠨临.ꡢⶏ𐹣 +󠑘.󠄮; 󠑘.; [V7]; xn--s136e.; [V7, A4_2]; ; # . +󠑘.󠄮; 󠑘.; [V7]; xn--s136e.; [V7, A4_2]; ; # . +xn--s136e.; 󠑘.; [V7]; xn--s136e.; [V7, A4_2]; ; # . +𐫄\u0D4D.\uAAF6; 𐫄\u0D4D.\uAAF6; [B1, V6]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶ +𐫄\u0D4D.\uAAF6; ; [B1, V6]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶ +xn--wxc7880k.xn--2v9a; 𐫄\u0D4D.\uAAF6; [B1, V6]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶ +\uA9B7󝵙멹。⒛󠨇; \uA9B7󝵙멹.⒛󠨇; [V6, V7]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛ +\uA9B7󝵙멹。⒛󠨇; \uA9B7󝵙멹.⒛󠨇; [V6, V7]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛ +\uA9B7󝵙멹。20.󠨇; \uA9B7󝵙멹.20.󠨇; [V6, V7]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20. +\uA9B7󝵙멹。20.󠨇; \uA9B7󝵙멹.20.󠨇; [V6, V7]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20. +xn--ym9av13acp85w.20.xn--d846e; \uA9B7󝵙멹.20.󠨇; [V6, V7]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20. +xn--ym9av13acp85w.xn--dth22121k; \uA9B7󝵙멹.⒛󠨇; [V6, V7]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛ +Ⴅ󲬹릖󠶚.\u0777𐹳⒊; ⴅ󲬹릖󠶚.\u0777𐹳⒊; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊ +Ⴅ󲬹릖󠶚.\u0777𐹳⒊; ⴅ󲬹릖󠶚.\u0777𐹳⒊; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊ +Ⴅ󲬹릖󠶚.\u0777𐹳3.; ⴅ󲬹릖󠶚.\u0777𐹳3.; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--3-55c6803r.; [B4, B6, V7, A4_2]; ; # ⴅ릖.ݷ𐹳3. +Ⴅ󲬹릖󠶚.\u0777𐹳3.; ⴅ󲬹릖󠶚.\u0777𐹳3.; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--3-55c6803r.; [B4, B6, V7, A4_2]; ; # ⴅ릖.ݷ𐹳3. +ⴅ󲬹릖󠶚.\u0777𐹳3.; ⴅ󲬹릖󠶚.\u0777𐹳3.; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--3-55c6803r.; [B4, B6, V7, A4_2]; ; # ⴅ릖.ݷ𐹳3. +ⴅ󲬹릖󠶚.\u0777𐹳3.; ; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--3-55c6803r.; [B4, B6, V7, A4_2]; ; # ⴅ릖.ݷ𐹳3. +xn--wkj8016bne45io02g.xn--3-55c6803r.; ⴅ󲬹릖󠶚.\u0777𐹳3.; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--3-55c6803r.; [B4, B6, V7, A4_2]; ; # ⴅ릖.ݷ𐹳3. +ⴅ󲬹릖󠶚.\u0777𐹳⒊; ⴅ󲬹릖󠶚.\u0777𐹳⒊; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊ +ⴅ󲬹릖󠶚.\u0777𐹳⒊; ; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊ +xn--wkj8016bne45io02g.xn--7pb000mwm4n; ⴅ󲬹릖󠶚.\u0777𐹳⒊; [B4, B6, V7]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊ +xn--dnd2167fnet0io02g.xn--3-55c6803r.; Ⴅ󲬹릖󠶚.\u0777𐹳3.; [B4, B6, V7]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; [B4, B6, V7, A4_2]; ; # Ⴅ릖.ݷ𐹳3. +xn--dnd2167fnet0io02g.xn--7pb000mwm4n; Ⴅ󲬹릖󠶚.\u0777𐹳⒊; [B4, B6, V7]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊ +\u200C。︒; \u200C.︒; [C1, V7]; xn--0ug.xn--y86c; ; .xn--y86c; [V7, A4_2] # .︒ +\u200C。。; \u200C..; [C1, X4_2]; xn--0ug..; [C1, A4_2]; ..; [A4_2] # .. +..; ; [X4_2]; ; [A4_2]; ; # .. +xn--0ug..; \u200C..; [C1, X4_2]; xn--0ug..; [C1, A4_2]; ; # .. +.xn--y86c; .︒; [V7, X4_2]; .xn--y86c; [V7, A4_2]; ; # .︒ +xn--0ug.xn--y86c; \u200C.︒; [C1, V7]; xn--0ug.xn--y86c; ; ; # .︒ +≯\u076D.₄; ≯\u076D.4; [B1]; xn--xpb149k.4; ; ; # ≯ݭ.4 +>\u0338\u076D.₄; ≯\u076D.4; [B1]; xn--xpb149k.4; ; ; # ≯ݭ.4 +≯\u076D.e; ; [B1]; xn--xpb149k.e; ; ; # ≯ݭ.e +>\u0338\u076D.e; ≯\u076D.e; [B1]; xn--xpb149k.e; ; ; # ≯ݭ.e +>\u0338\u076D.E; ≯\u076D.e; [B1]; xn--xpb149k.e; ; ; # ≯ݭ.e +≯\u076D.E; ≯\u076D.e; [B1]; xn--xpb149k.e; ; ; # ≯ݭ.e +xn--xpb149k.e; ≯\u076D.e; [B1]; xn--xpb149k.e; ; ; # ≯ݭ.e +ᡲ-𝟹.ß-\u200C-; ᡲ-3.ß-\u200C-; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ß-- +ᡲ-3.ß-\u200C-; ; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ß-- +ᡲ-3.SS-\u200C-; ᡲ-3.ss-\u200C-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss-- +ᡲ-3.ss-\u200C-; ; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss-- +ᡲ-3.Ss-\u200C-; ᡲ-3.ss-\u200C-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss-- +xn---3-p9o.ss--; ᡲ-3.ss--; [V2, V3]; xn---3-p9o.ss--; ; ; # ᡲ-3.ss-- +xn---3-p9o.xn--ss---276a; ᡲ-3.ss-\u200C-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; ; # ᡲ-3.ss-- +xn---3-p9o.xn-----fia9303a; ᡲ-3.ß-\u200C-; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; ; # ᡲ-3.ß-- +ᡲ-𝟹.SS-\u200C-; ᡲ-3.ss-\u200C-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss-- +ᡲ-𝟹.ss-\u200C-; ᡲ-3.ss-\u200C-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss-- +ᡲ-𝟹.Ss-\u200C-; ᡲ-3.ss-\u200C-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss-- +\uFD08𝟦\u0647󎊯。Ӏ; \u0636\u064A4\u0647󎊯.ӏ; [B2, B3, V7]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ +\u0636\u064A4\u0647󎊯。Ӏ; \u0636\u064A4\u0647󎊯.ӏ; [B2, B3, V7]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ +\u0636\u064A4\u0647󎊯。ӏ; \u0636\u064A4\u0647󎊯.ӏ; [B2, B3, V7]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ +xn--4-tnc6ck183523b.xn--s5a; \u0636\u064A4\u0647󎊯.ӏ; [B2, B3, V7]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ +\uFD08𝟦\u0647󎊯。ӏ; \u0636\u064A4\u0647󎊯.ӏ; [B2, B3, V7]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ +xn--4-tnc6ck183523b.xn--d5a; \u0636\u064A4\u0647󎊯.Ӏ; [B2, B3, V7]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ +-.\u0602\u0622𑆾🐹; ; [B1, V3, V7]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹 +-.\u0602\u0627\u0653𑆾🐹; -.\u0602\u0622𑆾🐹; [B1, V3, V7]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹 +-.xn--kfb8dy983hgl7g; -.\u0602\u0622𑆾🐹; [B1, V3, V7]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹 +󙶜ᢘ。\u1A7F⺢; 󙶜ᢘ.\u1A7F⺢; [V6, V7]; xn--ibf35138o.xn--fpfz94g; ; ; # ᢘ.᩿⺢ +xn--ibf35138o.xn--fpfz94g; 󙶜ᢘ.\u1A7F⺢; [V6, V7]; xn--ibf35138o.xn--fpfz94g; ; ; # ᢘ.᩿⺢ +≠ႷᠤႫ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +=\u0338ႷᠤႫ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +≠ႷᠤႫ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +=\u0338ႷᠤႫ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +=\u0338ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +≠ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +≠Ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +=\u0338Ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +xn--66e353ce0ilb.xn--?-7fb34t0u7s; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +=\u0338ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +≠ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +≠Ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +=\u0338Ⴗᠤⴋ。?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ≠Ⴗᠤⴋ.?\u034C\u0633觴; [B1, V7, U1]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴 +xn--jndx718cnnl.xn--?-7fb34t0u7s; ≠ႷᠤႫ.?\u034C\u0633觴; [B1, V7, U1]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴 +xn--vnd619as6ig6k.?\u034C\u0633觴; ≠Ⴗᠤⴋ.?\u034C\u0633觴; [B1, V7, U1]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴 +XN--VND619AS6IG6K.?\u034C\u0633觴; ≠Ⴗᠤⴋ.?\u034C\u0633觴; [B1, V7, U1]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴 +Xn--Vnd619as6ig6k.?\u034C\u0633觴; ≠Ⴗᠤⴋ.?\u034C\u0633觴; [B1, V7, U1]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴 +xn--66e353ce0ilb.?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +XN--66E353CE0ILB.?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +Xn--66e353ce0ilb.?\u034C\u0633觴; ≠ⴗᠤⴋ.?\u034C\u0633觴; [B1, U1]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴 +xn--jndx718cnnl.?\u034C\u0633觴; ≠ႷᠤႫ.?\u034C\u0633觴; [B1, V7, U1]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴 +XN--JNDX718CNNL.?\u034C\u0633觴; ≠ႷᠤႫ.?\u034C\u0633觴; [B1, V7, U1]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴 +Xn--Jndx718cnnl.?\u034C\u0633觴; ≠ႷᠤႫ.?\u034C\u0633觴; [B1, V7, U1]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴 +\u0667.𐥨; ; [B1, V7]; xn--gib.xn--vm9c; ; ; # ٧. +xn--gib.xn--vm9c; \u0667.𐥨; [B1, V7]; xn--gib.xn--vm9c; ; ; # ٧. +\uA9C0𝟯。\u200D񼑥𐹪\u1BF3; \uA9C03.\u200D񼑥𐹪\u1BF3; [B1, C2, V6, V7]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; xn--3-5z4e.xn--1zfz754hncv8b; [B5, V6, V7] # ꧀3.𐹪᯳ +\uA9C03。\u200D񼑥𐹪\u1BF3; \uA9C03.\u200D񼑥𐹪\u1BF3; [B1, C2, V6, V7]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; xn--3-5z4e.xn--1zfz754hncv8b; [B5, V6, V7] # ꧀3.𐹪᯳ +xn--3-5z4e.xn--1zfz754hncv8b; \uA9C03.񼑥𐹪\u1BF3; [B5, V6, V7]; xn--3-5z4e.xn--1zfz754hncv8b; ; ; # ꧀3.𐹪᯳ +xn--3-5z4e.xn--1zf96ony8ygd68c; \uA9C03.\u200D񼑥𐹪\u1BF3; [B1, C2, V6, V7]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; ; # ꧀3.𐹪᯳ +򣕄4񠖽.≯\u0664𑀾󠸌; ; [B1, V7]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾 +򣕄4񠖽.>\u0338\u0664𑀾󠸌; 򣕄4񠖽.≯\u0664𑀾󠸌; [B1, V7]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾 +xn--4-fg85dl688i.xn--dib174li86ntdy0i; 򣕄4񠖽.≯\u0664𑀾󠸌; [B1, V7]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾 +򗆧𝟯。⒈\u1A76𝟚򠘌; 򗆧3.⒈\u1A762򠘌; [V7]; xn--3-rj42h.xn--2-13k746cq465x; ; ; # 3.⒈᩶2 +򗆧3。1.\u1A762򠘌; 򗆧3.1.\u1A762򠘌; [V6, V7]; xn--3-rj42h.1.xn--2-13k96240l; ; ; # 3.1.᩶2 +xn--3-rj42h.1.xn--2-13k96240l; 򗆧3.1.\u1A762򠘌; [V6, V7]; xn--3-rj42h.1.xn--2-13k96240l; ; ; # 3.1.᩶2 +xn--3-rj42h.xn--2-13k746cq465x; 򗆧3.⒈\u1A762򠘌; [V7]; xn--3-rj42h.xn--2-13k746cq465x; ; ; # 3.⒈᩶2 +\u200D₅⒈。≯𝟴\u200D; \u200D5⒈.≯8\u200D; [C2, V7]; xn--5-tgnz5r.xn--8-ugn00i; ; xn--5-ecp.xn--8-ogo; [V7] # 5⒈.≯8 +\u200D₅⒈。>\u0338𝟴\u200D; \u200D5⒈.≯8\u200D; [C2, V7]; xn--5-tgnz5r.xn--8-ugn00i; ; xn--5-ecp.xn--8-ogo; [V7] # 5⒈.≯8 +\u200D51.。≯8\u200D; \u200D51..≯8\u200D; [C2, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, A4_2]; 51..xn--8-ogo; [A4_2] # 51..≯8 +\u200D51.。>\u03388\u200D; \u200D51..≯8\u200D; [C2, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, A4_2]; 51..xn--8-ogo; [A4_2] # 51..≯8 +51..xn--8-ogo; 51..≯8; [X4_2]; 51..xn--8-ogo; [A4_2]; ; # 51..≯8 +xn--51-l1t..xn--8-ugn00i; \u200D51..≯8\u200D; [C2, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, A4_2]; ; # 51..≯8 +xn--5-ecp.xn--8-ogo; 5⒈.≯8; [V7]; xn--5-ecp.xn--8-ogo; ; ; # 5⒈.≯8 +xn--5-tgnz5r.xn--8-ugn00i; \u200D5⒈.≯8\u200D; [C2, V7]; xn--5-tgnz5r.xn--8-ugn00i; ; ; # 5⒈.≯8 +ꡰ\u0697\u1086.򪘙\u072F≠\u200C; ꡰ\u0697\u1086.򪘙\u072F≠\u200C; [B5, B6, C1, V7]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, V7] # ꡰڗႆ.ܯ≠ +ꡰ\u0697\u1086.򪘙\u072F=\u0338\u200C; ꡰ\u0697\u1086.򪘙\u072F≠\u200C; [B5, B6, C1, V7]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, V7] # ꡰڗႆ.ܯ≠ +ꡰ\u0697\u1086.򪘙\u072F≠\u200C; ; [B5, B6, C1, V7]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, V7] # ꡰڗႆ.ܯ≠ +ꡰ\u0697\u1086.򪘙\u072F=\u0338\u200C; ꡰ\u0697\u1086.򪘙\u072F≠\u200C; [B5, B6, C1, V7]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, V7] # ꡰڗႆ.ܯ≠ +xn--tjb002cn51k.xn--5nb630lbj91q; ꡰ\u0697\u1086.򪘙\u072F≠; [B5, B6, V7]; xn--tjb002cn51k.xn--5nb630lbj91q; ; ; # ꡰڗႆ.ܯ≠ +xn--tjb002cn51k.xn--5nb448jcubcz547b; ꡰ\u0697\u1086.򪘙\u072F≠\u200C; [B5, B6, C1, V7]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; ; # ꡰڗႆ.ܯ≠ +𑄱。򪌿𐹵; 𑄱.򪌿𐹵; [B1, B5, B6, V6, V7]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵 +𑄱。򪌿𐹵; 𑄱.򪌿𐹵; [B1, B5, B6, V6, V7]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵 +xn--t80d.xn--to0d14792b; 𑄱.򪌿𐹵; [B1, B5, B6, V6, V7]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵 +𝟥\u0600。\u073D; 3\u0600.\u073D; [B1, V6, V7]; xn--3-rkc.xn--kob; ; ; # 3.ܽ +3\u0600。\u073D; 3\u0600.\u073D; [B1, V6, V7]; xn--3-rkc.xn--kob; ; ; # 3.ܽ +xn--3-rkc.xn--kob; 3\u0600.\u073D; [B1, V6, V7]; xn--3-rkc.xn--kob; ; ; # 3.ܽ +\u0637𐹣\u0666.\u076D긷; ; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷 +\u0637𐹣\u0666.\u076D긷; \u0637𐹣\u0666.\u076D긷; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷 +xn--2gb8gu829f.xn--xpb0156f; \u0637𐹣\u0666.\u076D긷; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷 +︒Ↄ\u2DE7򾀃.Ⴗ𐣞; ︒ↄ\u2DE7򾀃.ⴗ𐣞; [B1, B5, B6, V7]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ +。Ↄ\u2DE7򾀃.Ⴗ𐣞; .ↄ\u2DE7򾀃.ⴗ𐣞; [B5, B6, V7, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, V7, A4_2]; ; # .ↄⷧ.ⴗ +。ↄ\u2DE7򾀃.ⴗ𐣞; .ↄ\u2DE7򾀃.ⴗ𐣞; [B5, B6, V7, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, V7, A4_2]; ; # .ↄⷧ.ⴗ +.xn--r5gy00cll06u.xn--flj4541e; .ↄ\u2DE7򾀃.ⴗ𐣞; [B5, B6, V7, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, V7, A4_2]; ; # .ↄⷧ.ⴗ +︒ↄ\u2DE7򾀃.ⴗ𐣞; ︒ↄ\u2DE7򾀃.ⴗ𐣞; [B1, B5, B6, V7]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ +xn--r5gy00c056n0226g.xn--flj4541e; ︒ↄ\u2DE7򾀃.ⴗ𐣞; [B1, B5, B6, V7]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ +.xn--q5g000cll06u.xn--vnd8618j; .Ↄ\u2DE7򾀃.Ⴗ𐣞; [B5, B6, V7, X4_2]; .xn--q5g000cll06u.xn--vnd8618j; [B5, B6, V7, A4_2]; ; # .Ↄⷧ.Ⴗ +xn--q5g000c056n0226g.xn--vnd8618j; ︒Ↄ\u2DE7򾀃.Ⴗ𐣞; [B1, B5, B6, V7]; xn--q5g000c056n0226g.xn--vnd8618j; ; ; # ︒Ↄⷧ.Ⴗ +\u0600.\u05B1; ; [B1, V6, V7]; xn--ifb.xn--8cb; ; ; # .ֱ +xn--ifb.xn--8cb; \u0600.\u05B1; [B1, V6, V7]; xn--ifb.xn--8cb; ; ; # .ֱ +ς≯。𐹽; ς≯.𐹽; [B1, B6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽 +ς>\u0338。𐹽; ς≯.𐹽; [B1, B6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽 +ς≯。𐹽; ς≯.𐹽; [B1, B6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽 +ς>\u0338。𐹽; ς≯.𐹽; [B1, B6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽 +Σ>\u0338。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +Σ≯。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +σ≯。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +σ>\u0338。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +xn--4xa818m.xn--1o0d; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +xn--3xa028m.xn--1o0d; ς≯.𐹽; [B1, B6]; xn--3xa028m.xn--1o0d; ; ; # ς≯.𐹽 +Σ>\u0338。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +Σ≯。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +σ≯。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +σ>\u0338。𐹽; σ≯.𐹽; [B1, B6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽 +\u17D2\u200D\u075F。𐹶; \u17D2\u200D\u075F.𐹶; [B1, V6]; xn--jpb535fv9f.xn--uo0d; ; xn--jpb535f.xn--uo0d; # ្ݟ.𐹶 +xn--jpb535f.xn--uo0d; \u17D2\u075F.𐹶; [B1, V6]; xn--jpb535f.xn--uo0d; ; ; # ្ݟ.𐹶 +xn--jpb535fv9f.xn--uo0d; \u17D2\u200D\u075F.𐹶; [B1, V6]; xn--jpb535fv9f.xn--uo0d; ; ; # ្ݟ.𐹶 +𾷂\u0A42Ⴊ񂂟.≮; 𾷂\u0A42ⴊ񂂟.≮; [V7]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮ +𾷂\u0A42Ⴊ񂂟.<\u0338; 𾷂\u0A42ⴊ񂂟.≮; [V7]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮ +𾷂\u0A42ⴊ񂂟.<\u0338; 𾷂\u0A42ⴊ񂂟.≮; [V7]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮ +𾷂\u0A42ⴊ񂂟.≮; ; [V7]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮ +xn--nbc229o4y27dgskb.xn--gdh; 𾷂\u0A42ⴊ񂂟.≮; [V7]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮ +xn--nbc493aro75ggskb.xn--gdh; 𾷂\u0A42Ⴊ񂂟.≮; [V7]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮ +ꡠ.۲; ꡠ.۲; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲ +ꡠ.۲; ; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲ +xn--5c9a.xn--fmb; ꡠ.۲; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲ +𐹣񄷄。ꡬ🄄; 𐹣񄷄.ꡬ3,; [B1, B6, V7, U1]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3, +𐹣񄷄。ꡬ3,; 𐹣񄷄.ꡬ3,; [B1, B6, V7, U1]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3, +xn--bo0d0203l.xn--3,-yj9h; 𐹣񄷄.ꡬ3,; [B1, B6, V7, U1]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3, +xn--bo0d0203l.xn--id9a4443d; 𐹣񄷄.ꡬ🄄; [B1, V7]; xn--bo0d0203l.xn--id9a4443d; ; ; # 𐹣.ꡬ🄄 +-\u0C4D𞾀𑲓。\u200D\u0D4D; -\u0C4D𞾀𑲓.\u200D\u0D4D; [B1, C2, V3, V7]; xn----x6e0220sclug.xn--wxc317g; ; xn----x6e0220sclug.xn--wxc; [B1, V3, V6, V7] # -్𑲓.് +-\u0C4D𞾀𑲓。\u200D\u0D4D; -\u0C4D𞾀𑲓.\u200D\u0D4D; [B1, C2, V3, V7]; xn----x6e0220sclug.xn--wxc317g; ; xn----x6e0220sclug.xn--wxc; [B1, V3, V6, V7] # -్𑲓.് +xn----x6e0220sclug.xn--wxc; -\u0C4D𞾀𑲓.\u0D4D; [B1, V3, V6, V7]; xn----x6e0220sclug.xn--wxc; ; ; # -్𑲓.് +xn----x6e0220sclug.xn--wxc317g; -\u0C4D𞾀𑲓.\u200D\u0D4D; [B1, C2, V3, V7]; xn----x6e0220sclug.xn--wxc317g; ; ; # -్𑲓.് +\uA67D\u200C霣🄆。\u200C𑁂\u1B01; \uA67D\u200C霣5,.\u200C𑁂\u1B01; [C1, V6, U1]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; xn--5,-op8g373c.xn--4sf0725i; [V6, U1] # ꙽霣5,.𑁂ᬁ +\uA67D\u200C霣🄆。\u200C𑁂\u1B01; \uA67D\u200C霣5,.\u200C𑁂\u1B01; [C1, V6, U1]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; xn--5,-op8g373c.xn--4sf0725i; [V6, U1] # ꙽霣5,.𑁂ᬁ +\uA67D\u200C霣5,。\u200C𑁂\u1B01; \uA67D\u200C霣5,.\u200C𑁂\u1B01; [C1, V6, U1]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; xn--5,-op8g373c.xn--4sf0725i; [V6, U1] # ꙽霣5,.𑁂ᬁ +xn--5,-op8g373c.xn--4sf0725i; \uA67D霣5,.𑁂\u1B01; [V6, U1]; xn--5,-op8g373c.xn--4sf0725i; ; ; # ꙽霣5,.𑁂ᬁ +xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; \uA67D\u200C霣5,.\u200C𑁂\u1B01; [C1, V6, U1]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; ; # ꙽霣5,.𑁂ᬁ +xn--2q5a751a653w.xn--4sf0725i; \uA67D霣🄆.𑁂\u1B01; [V6, V7]; xn--2q5a751a653w.xn--4sf0725i; ; ; # ꙽霣🄆.𑁂ᬁ +xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; \uA67D\u200C霣🄆.\u200C𑁂\u1B01; [C1, V6, V7]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; ; # ꙽霣🄆.𑁂ᬁ +兎。ᠼ󠴜𑚶𑰿; 兎.ᠼ󠴜𑚶𑰿; [V7]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿 +兎。ᠼ󠴜𑚶𑰿; 兎.ᠼ󠴜𑚶𑰿; [V7]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿 +xn--b5q.xn--v7e6041kqqd4m251b; 兎.ᠼ󠴜𑚶𑰿; [V7]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿 +𝟙。\u200D𝟸\u200D⁷; 1.\u200D2\u200D7; [C2]; 1.xn--27-l1tb; ; 1.27; [] # 1.27 +1。\u200D2\u200D7; 1.\u200D2\u200D7; [C2]; 1.xn--27-l1tb; ; 1.27; [] # 1.27 +1.2h; ; ; ; ; ; # 1.2h +1.xn--27-l1tb; 1.\u200D2\u200D7; [C2]; 1.xn--27-l1tb; ; ; # 1.27 +ᡨ-。󠻋𝟷; ᡨ-.󠻋1; [V3, V7]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1 +ᡨ-。󠻋1; ᡨ-.󠻋1; [V3, V7]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1 +xn----z8j.xn--1-5671m; ᡨ-.󠻋1; [V3, V7]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1 +𑰻񵀐𐫚.\u0668⁹; 𑰻񵀐𐫚.\u06689; [B1, V6, V7]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9 +𑰻񵀐𐫚.\u06689; ; [B1, V6, V7]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9 +xn--gx9cr01aul57i.xn--9-oqc; 𑰻񵀐𐫚.\u06689; [B1, V6, V7]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9 +Ⴜ򈷭\u0F80⾇。Ⴏ♀\u200C\u200C; ⴜ򈷭\u0F80舛.ⴏ♀\u200C\u200C; [C1, V7]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [V7] # ⴜྀ舛.ⴏ♀ +Ⴜ򈷭\u0F80舛。Ⴏ♀\u200C\u200C; ⴜ򈷭\u0F80舛.ⴏ♀\u200C\u200C; [C1, V7]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [V7] # ⴜྀ舛.ⴏ♀ +ⴜ򈷭\u0F80舛。ⴏ♀\u200C\u200C; ⴜ򈷭\u0F80舛.ⴏ♀\u200C\u200C; [C1, V7]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [V7] # ⴜྀ舛.ⴏ♀ +xn--zed372mdj2do3v4h.xn--e5h11w; ⴜ򈷭\u0F80舛.ⴏ♀; [V7]; xn--zed372mdj2do3v4h.xn--e5h11w; ; ; # ⴜྀ舛.ⴏ♀ +xn--zed372mdj2do3v4h.xn--0uga678bgyh; ⴜ򈷭\u0F80舛.ⴏ♀\u200C\u200C; [C1, V7]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; ; # ⴜྀ舛.ⴏ♀ +ⴜ򈷭\u0F80⾇。ⴏ♀\u200C\u200C; ⴜ򈷭\u0F80舛.ⴏ♀\u200C\u200C; [C1, V7]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [V7] # ⴜྀ舛.ⴏ♀ +xn--zed54dz10wo343g.xn--nnd651i; Ⴜ򈷭\u0F80舛.Ⴏ♀; [V7]; xn--zed54dz10wo343g.xn--nnd651i; ; ; # Ⴜྀ舛.Ⴏ♀ +xn--zed54dz10wo343g.xn--nnd089ea464d; Ⴜ򈷭\u0F80舛.Ⴏ♀\u200C\u200C; [C1, V7]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; ; # Ⴜྀ舛.Ⴏ♀ +𑁆𝟰.\u200D; 𑁆4.\u200D; [C2, V6]; xn--4-xu7i.xn--1ug; ; xn--4-xu7i.; [V6, A4_2] # 𑁆4. +𑁆4.\u200D; ; [C2, V6]; xn--4-xu7i.xn--1ug; ; xn--4-xu7i.; [V6, A4_2] # 𑁆4. +xn--4-xu7i.; 𑁆4.; [V6]; xn--4-xu7i.; [V6, A4_2]; ; # 𑁆4. +xn--4-xu7i.xn--1ug; 𑁆4.\u200D; [C2, V6]; xn--4-xu7i.xn--1ug; ; ; # 𑁆4. +񮴘Ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +񮴘Ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +񮴘Ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +񮴘Ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +񮴘ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +񮴘ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +xn--mlju35u7qx2f.xn--et3bn23n; 񮴘ⴞ癀.𑘿붼; [V6, V7]; xn--mlju35u7qx2f.xn--et3bn23n; ; ; # ⴞ癀.𑘿붼 +xn--mlju35u7qx2f.xn--0ugb6122js83c; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; ; # ⴞ癀.𑘿붼 +񮴘ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +񮴘ⴞ癀。𑘿\u200D\u200C붼; 񮴘ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [V6, V7] # ⴞ癀.𑘿붼 +xn--2nd6803c7q37d.xn--et3bn23n; 񮴘Ⴞ癀.𑘿붼; [V6, V7]; xn--2nd6803c7q37d.xn--et3bn23n; ; ; # Ⴞ癀.𑘿붼 +xn--2nd6803c7q37d.xn--0ugb6122js83c; 񮴘Ⴞ癀.𑘿\u200D\u200C붼; [C1, V6, V7]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; ; # Ⴞ癀.𑘿붼 +󚀅-\u0BCD。\u06B9; 󚀅-\u0BCD.\u06B9; [B6, V7]; xn----mze84808x.xn--skb; ; ; # -்.ڹ +xn----mze84808x.xn--skb; 󚀅-\u0BCD.\u06B9; [B6, V7]; xn----mze84808x.xn--skb; ; ; # -்.ڹ +ᡃ𝟧≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [V7]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ +ᡃ𝟧>\u0338ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [V7]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ +ᡃ5≯ᠣ.氁񨏱ꁫ; ; [V7]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ +ᡃ5>\u0338ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [V7]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ +xn--5-24jyf768b.xn--lqw213ime95g; ᡃ5≯ᠣ.氁񨏱ꁫ; [V7]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ +𐹬𝩇.\u0F76; 𐹬𝩇.\u0FB2\u0F80; [B1, V6]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ +𐹬𝩇.\u0FB2\u0F80; 𐹬𝩇.\u0FB2\u0F80; [B1, V6]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ +𐹬𝩇.\u0FB2\u0F80; ; [B1, V6]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ +xn--ko0d8295a.xn--zed3h; 𐹬𝩇.\u0FB2\u0F80; [B1, V6]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ +-𑈶⒏.⒎𰛢󠎭; -𑈶⒏.⒎𰛢󠎭; [V3, V7]; xn----scp6252h.xn--zshy411yzpx2d; ; ; # -𑈶⒏.⒎𰛢 +-𑈶8..7.𰛢󠎭; ; [V3, V7, X4_2]; xn---8-bv5o..7.xn--c35nf1622b; [V3, V7, A4_2]; ; # -𑈶8..7.𰛢 +xn---8-bv5o..7.xn--c35nf1622b; -𑈶8..7.𰛢󠎭; [V3, V7, X4_2]; xn---8-bv5o..7.xn--c35nf1622b; [V3, V7, A4_2]; ; # -𑈶8..7.𰛢 +xn----scp6252h.xn--zshy411yzpx2d; -𑈶⒏.⒎𰛢󠎭; [V3, V7]; xn----scp6252h.xn--zshy411yzpx2d; ; ; # -𑈶⒏.⒎𰛢 +\u200CႡ畝\u200D.≮; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +\u200CႡ畝\u200D.<\u0338; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +\u200CႡ畝\u200D.≮; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +\u200CႡ畝\u200D.<\u0338; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +\u200Cⴁ畝\u200D.<\u0338; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +\u200Cⴁ畝\u200D.≮; ; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +xn--skjy82u.xn--gdh; ⴁ畝.≮; ; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮ +ⴁ畝.≮; ; ; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮ +ⴁ畝.<\u0338; ⴁ畝.≮; ; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮ +Ⴁ畝.<\u0338; ⴁ畝.≮; ; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮ +Ⴁ畝.≮; ⴁ畝.≮; ; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮ +xn--0ugc160hb36e.xn--gdh; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; ; # ⴁ畝.≮ +\u200Cⴁ畝\u200D.<\u0338; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +\u200Cⴁ畝\u200D.≮; \u200Cⴁ畝\u200D.≮; [C1, C2]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [] # ⴁ畝.≮ +xn--8md0962c.xn--gdh; Ⴁ畝.≮; [V7]; xn--8md0962c.xn--gdh; ; ; # Ⴁ畝.≮ +xn--8md700fea3748f.xn--gdh; \u200CႡ畝\u200D.≮; [C1, C2, V7]; xn--8md700fea3748f.xn--gdh; ; ; # Ⴁ畝.≮ +歷。𐹻≯󳛽\u200D; 歷.𐹻≯󳛽\u200D; [B1, C2, V7]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, V7] # 歷.𐹻≯ +歷。𐹻>\u0338󳛽\u200D; 歷.𐹻≯󳛽\u200D; [B1, C2, V7]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, V7] # 歷.𐹻≯ +歷。𐹻≯󳛽\u200D; 歷.𐹻≯󳛽\u200D; [B1, C2, V7]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, V7] # 歷.𐹻≯ +歷。𐹻>\u0338󳛽\u200D; 歷.𐹻≯󳛽\u200D; [B1, C2, V7]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, V7] # 歷.𐹻≯ +xn--nmw.xn--hdh7804gdms2h; 歷.𐹻≯󳛽; [B1, V7]; xn--nmw.xn--hdh7804gdms2h; ; ; # 歷.𐹻≯ +xn--nmw.xn--1ugx6gs128a1134j; 歷.𐹻≯󳛽\u200D; [B1, C2, V7]; xn--nmw.xn--1ugx6gs128a1134j; ; ; # 歷.𐹻≯ +\u0ECB\u200D.鎁󠰑; \u0ECB\u200D.鎁󠰑; [C2, V6, V7]; xn--t8c059f.xn--iz4a43209d; ; xn--t8c.xn--iz4a43209d; [V6, V7] # ໋.鎁 +\u0ECB\u200D.鎁󠰑; ; [C2, V6, V7]; xn--t8c059f.xn--iz4a43209d; ; xn--t8c.xn--iz4a43209d; [V6, V7] # ໋.鎁 +xn--t8c.xn--iz4a43209d; \u0ECB.鎁󠰑; [V6, V7]; xn--t8c.xn--iz4a43209d; ; ; # ໋.鎁 +xn--t8c059f.xn--iz4a43209d; \u0ECB\u200D.鎁󠰑; [C2, V6, V7]; xn--t8c059f.xn--iz4a43209d; ; ; # ໋.鎁 +\u200D\u200C𞤀。𱘅𐶃; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6] # 𞤢.𱘅𐶃 +\u200D\u200C𞤀。𱘅𐶃; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6] # 𞤢.𱘅𐶃 +\u200D\u200C𞤢。𱘅𐶃; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6] # 𞤢.𱘅𐶃 +\u200D\u200C𞤀。𱘅𐵣; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6] # 𞤢.𱘅𐶃 +xn--9d6h.xn--wh0dj799f; 𞤢.𱘅𐶃; [B5, B6]; xn--9d6h.xn--wh0dj799f; ; ; # 𞤢.𱘅𐶃 +xn--0ugb45126a.xn--wh0dj799f; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; ; # 𞤢.𱘅𐶃 +\u200D\u200C𞤢。𱘅𐶃; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6] # 𞤢.𱘅𐶃 +\u200D\u200C𞤀。𱘅𐵣; \u200D\u200C𞤢.𱘅𐶃; [B1, B5, B6, C1, C2]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6] # 𞤢.𱘅𐶃 +\u0628≠𝟫-.ς⒍𐹦≠; \u0628≠9-.ς⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; xn--9--etd0100a.xn--4xa887mzpbzz04b; # ب≠9-.ς⒍𐹦≠ +\u0628=\u0338𝟫-.ς⒍𐹦=\u0338; \u0628≠9-.ς⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; xn--9--etd0100a.xn--4xa887mzpbzz04b; # ب≠9-.ς⒍𐹦≠ +\u0628≠9-.ς6.𐹦≠; ; [B1, B3, V3]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; # ب≠9-.ς6.𐹦≠ +\u0628=\u03389-.ς6.𐹦=\u0338; \u0628≠9-.ς6.𐹦≠; [B1, B3, V3]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; # ب≠9-.ς6.𐹦≠ +\u0628=\u03389-.Σ6.𐹦=\u0338; \u0628≠9-.σ6.𐹦≠; [B1, B3, V3]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠ +\u0628≠9-.Σ6.𐹦≠; \u0628≠9-.σ6.𐹦≠; [B1, B3, V3]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠ +\u0628≠9-.σ6.𐹦≠; ; [B1, B3, V3]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠ +\u0628=\u03389-.σ6.𐹦=\u0338; \u0628≠9-.σ6.𐹦≠; [B1, B3, V3]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠ +xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; \u0628≠9-.σ6.𐹦≠; [B1, B3, V3]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠ +xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; \u0628≠9-.ς6.𐹦≠; [B1, B3, V3]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; ; # ب≠9-.ς6.𐹦≠ +\u0628=\u0338𝟫-.Σ⒍𐹦=\u0338; \u0628≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠ +\u0628≠𝟫-.Σ⒍𐹦≠; \u0628≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠ +\u0628≠𝟫-.σ⒍𐹦≠; \u0628≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠ +\u0628=\u0338𝟫-.σ⒍𐹦=\u0338; \u0628≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠ +xn--9--etd0100a.xn--4xa887mzpbzz04b; \u0628≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠ +xn--9--etd0100a.xn--3xa097mzpbzz04b; \u0628≠9-.ς⒍𐹦≠; [B3, B5, B6, V3, V7]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; ; # ب≠9-.ς⒍𐹦≠ +򉛴.-ᡢ\u0592𝨠; ; [V3, V7]; xn--ep37b.xn----hec165lho83b; ; ; # .-ᡢ֒𝨠 +xn--ep37b.xn----hec165lho83b; 򉛴.-ᡢ\u0592𝨠; [V3, V7]; xn--ep37b.xn----hec165lho83b; ; ; # .-ᡢ֒𝨠 +\u06CB⒈ß󠄽。񷋍-; \u06CB⒈ß.񷋍-; [B2, B3, B6, V3, V7]; xn--zca541ato3a.xn----q001f; ; xn--ss-d7d6651a.xn----q001f; # ۋ⒈ß.- +\u06CB1.ß󠄽。񷋍-; \u06CB1.ß.񷋍-; [B6, V3, V7]; xn--1-cwc.xn--zca.xn----q001f; ; xn--1-cwc.ss.xn----q001f; # ۋ1.ß.- +\u06CB1.SS󠄽。񷋍-; \u06CB1.ss.񷋍-; [B6, V3, V7]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.- +\u06CB1.ss󠄽。񷋍-; \u06CB1.ss.񷋍-; [B6, V3, V7]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.- +\u06CB1.Ss󠄽。񷋍-; \u06CB1.ss.񷋍-; [B6, V3, V7]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.- +xn--1-cwc.ss.xn----q001f; \u06CB1.ss.񷋍-; [B6, V3, V7]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.- +xn--1-cwc.xn--zca.xn----q001f; \u06CB1.ß.񷋍-; [B6, V3, V7]; xn--1-cwc.xn--zca.xn----q001f; ; ; # ۋ1.ß.- +\u06CB⒈SS󠄽。񷋍-; \u06CB⒈ss.񷋍-; [B2, B3, B6, V3, V7]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.- +\u06CB⒈ss󠄽。񷋍-; \u06CB⒈ss.񷋍-; [B2, B3, B6, V3, V7]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.- +\u06CB⒈Ss󠄽。񷋍-; \u06CB⒈ss.񷋍-; [B2, B3, B6, V3, V7]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.- +xn--ss-d7d6651a.xn----q001f; \u06CB⒈ss.񷋍-; [B2, B3, B6, V3, V7]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.- +xn--zca541ato3a.xn----q001f; \u06CB⒈ß.񷋍-; [B2, B3, B6, V3, V7]; xn--zca541ato3a.xn----q001f; ; ; # ۋ⒈ß.- +𿀫.\u1BAAςႦ\u200D; 𿀫.\u1BAAςⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪ςⴆ +𿀫.\u1BAAςႦ\u200D; 𿀫.\u1BAAςⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪ςⴆ +𿀫.\u1BAAςⴆ\u200D; ; [C2, V6, V7]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪ςⴆ +𿀫.\u1BAAΣႦ\u200D; 𿀫.\u1BAAσⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪σⴆ +𿀫.\u1BAAσⴆ\u200D; ; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪σⴆ +𿀫.\u1BAAΣⴆ\u200D; 𿀫.\u1BAAσⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪σⴆ +xn--nu4s.xn--4xa153j7im; 𿀫.\u1BAAσⴆ; [V6, V7]; xn--nu4s.xn--4xa153j7im; ; ; # .᮪σⴆ +xn--nu4s.xn--4xa153jk8cs1q; 𿀫.\u1BAAσⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; ; # .᮪σⴆ +xn--nu4s.xn--3xa353jk8cs1q; 𿀫.\u1BAAςⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--3xa353jk8cs1q; ; ; # .᮪ςⴆ +𿀫.\u1BAAςⴆ\u200D; 𿀫.\u1BAAςⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪ςⴆ +𿀫.\u1BAAΣႦ\u200D; 𿀫.\u1BAAσⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪σⴆ +𿀫.\u1BAAσⴆ\u200D; 𿀫.\u1BAAσⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪σⴆ +𿀫.\u1BAAΣⴆ\u200D; 𿀫.\u1BAAσⴆ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [V6, V7] # .᮪σⴆ +xn--nu4s.xn--4xa217dxri; 𿀫.\u1BAAσႦ; [V6, V7]; xn--nu4s.xn--4xa217dxri; ; ; # .᮪σႦ +xn--nu4s.xn--4xa217dxriome; 𿀫.\u1BAAσႦ\u200D; [C2, V6, V7]; xn--nu4s.xn--4xa217dxriome; ; ; # .᮪σႦ +xn--nu4s.xn--3xa417dxriome; 𿀫.\u1BAAςႦ\u200D; [C2, V6, V7]; xn--nu4s.xn--3xa417dxriome; ; ; # .᮪ςႦ +⾆\u08E2.𝈴; 舌\u08E2.𝈴; [B1, B5, B6, V7]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴 +舌\u08E2.𝈴; ; [B1, B5, B6, V7]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴 +xn--l0b9413d.xn--kl1h; 舌\u08E2.𝈴; [B1, B5, B6, V7]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴 +⫞𐹶𖫴。⭠⒈; ⫞𐹶𖫴.⭠⒈; [B1, V7]; xn--53ix188et88b.xn--tsh52w; ; ; # ⫞𐹶𖫴.⭠⒈ +⫞𐹶𖫴。⭠1.; ⫞𐹶𖫴.⭠1.; [B1]; xn--53ix188et88b.xn--1-h6r.; [B1, A4_2]; ; # ⫞𐹶𖫴.⭠1. +xn--53ix188et88b.xn--1-h6r.; ⫞𐹶𖫴.⭠1.; [B1]; xn--53ix188et88b.xn--1-h6r.; [B1, A4_2]; ; # ⫞𐹶𖫴.⭠1. +xn--53ix188et88b.xn--tsh52w; ⫞𐹶𖫴.⭠⒈; [B1, V7]; xn--53ix188et88b.xn--tsh52w; ; ; # ⫞𐹶𖫴.⭠⒈ +⒈\u200C\uAAEC︒.\u0ACD; ⒈\u200C\uAAEC︒.\u0ACD; [C1, V6, V7]; xn--0ug78o720myr1c.xn--mfc; ; xn--tsh0720cse8b.xn--mfc; [V6, V7] # ⒈ꫬ︒.્ +1.\u200C\uAAEC。.\u0ACD; 1.\u200C\uAAEC..\u0ACD; [C1, V6, X4_2]; 1.xn--0ug7185c..xn--mfc; [C1, V6, A4_2]; 1.xn--sv9a..xn--mfc; [V6, A4_2] # 1.ꫬ..્ +1.xn--sv9a..xn--mfc; 1.\uAAEC..\u0ACD; [V6, X4_2]; 1.xn--sv9a..xn--mfc; [V6, A4_2]; ; # 1.ꫬ..્ +1.xn--0ug7185c..xn--mfc; 1.\u200C\uAAEC..\u0ACD; [C1, V6, X4_2]; 1.xn--0ug7185c..xn--mfc; [C1, V6, A4_2]; ; # 1.ꫬ..્ +xn--tsh0720cse8b.xn--mfc; ⒈\uAAEC︒.\u0ACD; [V6, V7]; xn--tsh0720cse8b.xn--mfc; ; ; # ⒈ꫬ︒.્ +xn--0ug78o720myr1c.xn--mfc; ⒈\u200C\uAAEC︒.\u0ACD; [C1, V6, V7]; xn--0ug78o720myr1c.xn--mfc; ; ; # ⒈ꫬ︒.્ +\u0C46。䰀\u0668𞭅󠅼; \u0C46.䰀\u0668𞭅; [B1, B5, B6, V6, V7]; xn--eqc.xn--hib5476aim6t; ; ; # ె.䰀٨ +xn--eqc.xn--hib5476aim6t; \u0C46.䰀\u0668𞭅; [B1, B5, B6, V6, V7]; xn--eqc.xn--hib5476aim6t; ; ; # ె.䰀٨ +ß\u200D.\u1BF2񄾼; ; [C2, V6, V7]; xn--zca870n.xn--0zf22107b; ; ss.xn--0zf22107b; [V6, V7] # ß.᯲ +SS\u200D.\u1BF2񄾼; ss\u200D.\u1BF2񄾼; [C2, V6, V7]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [V6, V7] # ss.᯲ +ss\u200D.\u1BF2񄾼; ; [C2, V6, V7]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [V6, V7] # ss.᯲ +Ss\u200D.\u1BF2񄾼; ss\u200D.\u1BF2񄾼; [C2, V6, V7]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [V6, V7] # ss.᯲ +ss.xn--0zf22107b; ss.\u1BF2񄾼; [V6, V7]; ss.xn--0zf22107b; ; ; # ss.᯲ +xn--ss-n1t.xn--0zf22107b; ss\u200D.\u1BF2񄾼; [C2, V6, V7]; xn--ss-n1t.xn--0zf22107b; ; ; # ss.᯲ +xn--zca870n.xn--0zf22107b; ß\u200D.\u1BF2񄾼; [C2, V6, V7]; xn--zca870n.xn--0zf22107b; ; ; # ß.᯲ +𑓂\u200C≮.≮; ; [V6]; xn--0ugy6glz29a.xn--gdh; ; xn--gdhz656g.xn--gdh; # 𑓂≮.≮ +𑓂\u200C<\u0338.<\u0338; 𑓂\u200C≮.≮; [V6]; xn--0ugy6glz29a.xn--gdh; ; xn--gdhz656g.xn--gdh; # 𑓂≮.≮ +xn--gdhz656g.xn--gdh; 𑓂≮.≮; [V6]; xn--gdhz656g.xn--gdh; ; ; # 𑓂≮.≮ +xn--0ugy6glz29a.xn--gdh; 𑓂\u200C≮.≮; [V6]; xn--0ugy6glz29a.xn--gdh; ; ; # 𑓂≮.≮ +🕼.\uFFA0; 🕼.; ; xn--my8h.; [A4_2]; ; # 🕼. +🕼.\u1160; 🕼.; ; xn--my8h.; [A4_2]; ; # 🕼. +xn--my8h.; 🕼.; ; xn--my8h.; [A4_2]; ; # 🕼. +🕼.; ; ; xn--my8h.; [A4_2]; ; # 🕼. +xn--my8h.xn--psd; 🕼.\u1160; [V7]; xn--my8h.xn--psd; ; ; # 🕼. +xn--my8h.xn--cl7c; 🕼.\uFFA0; [V7]; xn--my8h.xn--cl7c; ; ; # 🕼. +ᡔ\uFD82。񷘎; ᡔ\u0644\u062D\u0649.񷘎; [B5, B6, V7]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى. +ᡔ\u0644\u062D\u0649。񷘎; ᡔ\u0644\u062D\u0649.񷘎; [B5, B6, V7]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى. +xn--sgb9bq785p.xn--bc31b; ᡔ\u0644\u062D\u0649.񷘎; [B5, B6, V7]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى. +爕򳙑.𝟰気; 爕򳙑.4気; [V7]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気 +爕򳙑.4気; ; [V7]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気 +xn--1zxq3199c.xn--4-678b; 爕򳙑.4気; [V7]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気 +⒋𑍍Ⴝ-.𞬪\u0DCA\u05B5; ⒋𑍍ⴝ-.𞬪\u0DCA\u05B5; [B1, V3, V7]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ +4.𑍍Ⴝ-.𞬪\u0DCA\u05B5; 4.𑍍ⴝ-.𞬪\u0DCA\u05B5; [B1, B6, V3, V6, V7]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ +4.𑍍ⴝ-.𞬪\u0DCA\u05B5; ; [B1, B6, V3, V6, V7]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ +4.xn----wwsx259f.xn--ddb152b7y23b; 4.𑍍ⴝ-.𞬪\u0DCA\u05B5; [B1, B6, V3, V6, V7]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ +⒋𑍍ⴝ-.𞬪\u0DCA\u05B5; ⒋𑍍ⴝ-.𞬪\u0DCA\u05B5; [B1, V3, V7]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ +xn----jcp487avl3w.xn--ddb152b7y23b; ⒋𑍍ⴝ-.𞬪\u0DCA\u05B5; [B1, V3, V7]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ +4.xn----t1g9869q.xn--ddb152b7y23b; 4.𑍍Ⴝ-.𞬪\u0DCA\u05B5; [B1, B6, V3, V6, V7]; 4.xn----t1g9869q.xn--ddb152b7y23b; ; ; # 4.𑍍Ⴝ-.්ֵ +xn----t1g323mnk9t.xn--ddb152b7y23b; ⒋𑍍Ⴝ-.𞬪\u0DCA\u05B5; [B1, V3, V7]; xn----t1g323mnk9t.xn--ddb152b7y23b; ; ; # ⒋𑍍Ⴝ-.්ֵ +󞝃。򑆃񉢗--; 󞝃.򑆃񉢗--; [V2, V3, V7]; xn--2y75e.xn-----1l15eer88n; ; ; # .-- +xn--2y75e.xn-----1l15eer88n; 󞝃.򑆃񉢗--; [V2, V3, V7]; xn--2y75e.xn-----1l15eer88n; ; ; # .-- +\u200D\u07DF。\u200C\uABED; \u200D\u07DF.\u200C\uABED; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; xn--6sb.xn--429a; [B1, V6] # ߟ.꯭ +\u200D\u07DF。\u200C\uABED; \u200D\u07DF.\u200C\uABED; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; xn--6sb.xn--429a; [B1, V6] # ߟ.꯭ +xn--6sb.xn--429a; \u07DF.\uABED; [B1, V6]; xn--6sb.xn--429a; ; ; # ߟ.꯭ +xn--6sb394j.xn--0ug1126c; \u200D\u07DF.\u200C\uABED; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; ; # ߟ.꯭ +𞮽\u07FF\u084E。ᢍ򝹁𐫘; 𞮽\u07FF\u084E.ᢍ򝹁𐫘; [B5, B6, V7]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘 +𞮽\u07FF\u084E。ᢍ򝹁𐫘; 𞮽\u07FF\u084E.ᢍ򝹁𐫘; [B5, B6, V7]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘 +xn--3tb2nz468k.xn--69e8615j5rn5d; 𞮽\u07FF\u084E.ᢍ򝹁𐫘; [B5, B6, V7]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘 +\u06ED𞺌𑄚\u1714.ꡞ\u08B7; \u06ED\u0645𑄚\u1714.ꡞ\u08B7; [B1, B5, B6, V6]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ +\u06ED\u0645𑄚\u1714.ꡞ\u08B7; ; [B1, B5, B6, V6]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ +xn--hhb94ag41b739u.xn--dzb5582f; \u06ED\u0645𑄚\u1714.ꡞ\u08B7; [B1, B5, B6, V6]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ +񻂵킃𑘶\u07DC。ς\u063Cς; 񻂵킃𑘶\u07DC.ς\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς +񻂵킃𑘶\u07DC。ς\u063Cς; 񻂵킃𑘶\u07DC.ς\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς +񻂵킃𑘶\u07DC。ς\u063Cς; 񻂵킃𑘶\u07DC.ς\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς +񻂵킃𑘶\u07DC。ς\u063Cς; 񻂵킃𑘶\u07DC.ς\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς +񻂵킃𑘶\u07DC。Σ\u063CΣ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063CΣ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +xn--3sb7483hoyvbbe76g.xn--4xaa21q; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +񻂵킃𑘶\u07DC。Σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +񻂵킃𑘶\u07DC。σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +񻂵킃𑘶\u07DC。σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +xn--3sb7483hoyvbbe76g.xn--3xab31q; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; ; # 킃𑘶ߜ.σؼς +xn--3sb7483hoyvbbe76g.xn--3xaa51q; 񻂵킃𑘶\u07DC.ς\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; ; # 킃𑘶ߜ.ςؼς +񻂵킃𑘶\u07DC。Σ\u063CΣ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063CΣ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063Cσ; 񻂵킃𑘶\u07DC.σ\u063Cσ; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ +񻂵킃𑘶\u07DC。Σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +񻂵킃𑘶\u07DC。Σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +񻂵킃𑘶\u07DC。σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +񻂵킃𑘶\u07DC。σ\u063Cς; 񻂵킃𑘶\u07DC.σ\u063Cς; [B5, B6, V7]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς +蔰。󠁹\u08DD-𑈵; 蔰.󠁹\u08DD-𑈵; [V7]; xn--sz1a.xn----mrd9984r3dl0i; ; ; # 蔰.ࣝ-𑈵 +xn--sz1a.xn----mrd9984r3dl0i; 蔰.󠁹\u08DD-𑈵; [V7]; xn--sz1a.xn----mrd9984r3dl0i; ; ; # 蔰.ࣝ-𑈵 +ςჅ。\u075A; ςⴥ.\u075A; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ +ςⴥ。\u075A; ςⴥ.\u075A; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ +ΣჅ。\u075A; σⴥ.\u075A; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +σⴥ。\u075A; σⴥ.\u075A; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +Σⴥ。\u075A; σⴥ.\u075A; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +xn--4xa203s.xn--epb; σⴥ.\u075A; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +σⴥ.\u075A; ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +ΣჅ.\u075A; σⴥ.\u075A; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +Σⴥ.\u075A; σⴥ.\u075A; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ +xn--3xa403s.xn--epb; ςⴥ.\u075A; ; xn--3xa403s.xn--epb; ; ; # ςⴥ.ݚ +ςⴥ.\u075A; ; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ +xn--4xa477d.xn--epb; σჅ.\u075A; [V7]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ +xn--3xa677d.xn--epb; ςჅ.\u075A; [V7]; xn--3xa677d.xn--epb; ; ; # ςჅ.ݚ +\u0C4DႩ𞰓.\u1B72; \u0C4Dⴉ𞰓.\u1B72; [B1, V6, V7]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲ +\u0C4DႩ𞰓.\u1B72; \u0C4Dⴉ𞰓.\u1B72; [B1, V6, V7]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲ +\u0C4Dⴉ𞰓.\u1B72; ; [B1, V6, V7]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲ +xn--lqc478nlr02a.xn--dwf; \u0C4Dⴉ𞰓.\u1B72; [B1, V6, V7]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲ +\u0C4Dⴉ𞰓.\u1B72; \u0C4Dⴉ𞰓.\u1B72; [B1, V6, V7]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲ +xn--lqc64t7t26c.xn--dwf; \u0C4DႩ𞰓.\u1B72; [B1, V6, V7]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲ +⮷≮񎈴󠄟。𐠄; ⮷≮񎈴.𐠄; [B1, V7]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄 +⮷<\u0338񎈴󠄟。𐠄; ⮷≮񎈴.𐠄; [B1, V7]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄 +xn--gdh877a3513h.xn--pc9c; ⮷≮񎈴.𐠄; [B1, V7]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄 +\u06BC。\u200Dẏ\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +\u06BC。\u200Dy\u0307\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +\u06BC。\u200Dẏ\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +\u06BC。\u200Dy\u0307\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +\u06BC。\u200DY\u0307\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +\u06BC。\u200DẎ\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +xn--vkb.xn--08e172a; \u06BC.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ +\u06BC.ẏᡤ; ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ +\u06BC.y\u0307ᡤ; \u06BC.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ +\u06BC.Y\u0307ᡤ; \u06BC.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ +\u06BC.Ẏᡤ; \u06BC.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ +xn--vkb.xn--08e172ax6aca; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; ; # ڼ.ẏᡤ +\u06BC。\u200DY\u0307\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +\u06BC。\u200DẎ\u200Cᡤ; \u06BC.\u200Dẏ\u200Cᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ +𐹹𑲛。񑂐\u0DCA; 𐹹𑲛.񑂐\u0DCA; [B1, V7]; xn--xo0dg5v.xn--h1c39876d; ; ; # 𐹹𑲛.් +xn--xo0dg5v.xn--h1c39876d; 𐹹𑲛.񑂐\u0DCA; [B1, V7]; xn--xo0dg5v.xn--h1c39876d; ; ; # 𐹹𑲛.් +-≠𑈵。嵕\uFEF1۴\uA953; -≠𑈵.嵕\u064A۴\uA953; [B1, B5, V3]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓ +-=\u0338𑈵。嵕\uFEF1۴\uA953; -≠𑈵.嵕\u064A۴\uA953; [B1, B5, V3]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓ +-≠𑈵。嵕\u064A۴\uA953; -≠𑈵.嵕\u064A۴\uA953; [B1, B5, V3]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓ +-=\u0338𑈵。嵕\u064A۴\uA953; -≠𑈵.嵕\u064A۴\uA953; [B1, B5, V3]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓ +xn----ufo4749h.xn--mhb45a235sns3c; -≠𑈵.嵕\u064A۴\uA953; [B1, B5, V3]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓ +\u200C񍸰𐹶\u076E.\u06C1\u200D≯\u200D; \u200C񍸰𐹶\u076E.\u06C1\u200D≯\u200D; [B1, B3, C1, C2, V7]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, V7] # 𐹶ݮ.ہ≯ +\u200C񍸰𐹶\u076E.\u06C1\u200D>\u0338\u200D; \u200C񍸰𐹶\u076E.\u06C1\u200D≯\u200D; [B1, B3, C1, C2, V7]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, V7] # 𐹶ݮ.ہ≯ +\u200C񍸰𐹶\u076E.\u06C1\u200D≯\u200D; ; [B1, B3, C1, C2, V7]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, V7] # 𐹶ݮ.ہ≯ +\u200C񍸰𐹶\u076E.\u06C1\u200D>\u0338\u200D; \u200C񍸰𐹶\u076E.\u06C1\u200D≯\u200D; [B1, B3, C1, C2, V7]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, V7] # 𐹶ݮ.ہ≯ +xn--ypb5875khz9y.xn--0kb682l; 񍸰𐹶\u076E.\u06C1≯; [B3, B5, B6, V7]; xn--ypb5875khz9y.xn--0kb682l; ; ; # 𐹶ݮ.ہ≯ +xn--ypb717jrx2o7v94a.xn--0kb660ka35v; \u200C񍸰𐹶\u076E.\u06C1\u200D≯\u200D; [B1, B3, C1, C2, V7]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; ; # 𐹶ݮ.ہ≯ +≮.\u17B5\u0855𐫔; ≮.\u0855𐫔; [B1]; xn--gdh.xn--kwb4643k; ; ; # ≮.ࡕ𐫔 +<\u0338.\u17B5\u0855𐫔; ≮.\u0855𐫔; [B1]; xn--gdh.xn--kwb4643k; ; ; # ≮.ࡕ𐫔 +≮.\u17B5\u0855𐫔; ≮.\u0855𐫔; [B1]; xn--gdh.xn--kwb4643k; ; ; # ≮.ࡕ𐫔 +<\u0338.\u17B5\u0855𐫔; ≮.\u0855𐫔; [B1]; xn--gdh.xn--kwb4643k; ; ; # ≮.ࡕ𐫔 +xn--gdh.xn--kwb4643k; ≮.\u0855𐫔; [B1]; xn--gdh.xn--kwb4643k; ; ; # ≮.ࡕ𐫔 +xn--gdh.xn--kwb589e217p; ≮.\u17B5\u0855𐫔; [B1, V6, V7]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔 +𐩗\u200D。ႩႵ; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ +𐩗\u200D。ႩႵ; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ +𐩗\u200D。ⴉⴕ; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ +𐩗\u200D。Ⴉⴕ; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ +xn--pt9c.xn--0kjya; 𐩗.ⴉⴕ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ +𐩗.ⴉⴕ; ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ +𐩗.ႩႵ; 𐩗.ⴉⴕ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ +𐩗.Ⴉⴕ; 𐩗.ⴉⴕ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ +xn--1ug4933g.xn--0kjya; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; ; # 𐩗.ⴉⴕ +𐩗\u200D。ⴉⴕ; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ +𐩗\u200D。Ⴉⴕ; 𐩗\u200D.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ +xn--pt9c.xn--hnd666l; 𐩗.Ⴉⴕ; [V7]; xn--pt9c.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ +xn--1ug4933g.xn--hnd666l; 𐩗\u200D.Ⴉⴕ; [B3, C2, V7]; xn--1ug4933g.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ +xn--pt9c.xn--hndy; 𐩗.ႩႵ; [V7]; xn--pt9c.xn--hndy; ; ; # 𐩗.ႩႵ +xn--1ug4933g.xn--hndy; 𐩗\u200D.ႩႵ; [B3, C2, V7]; xn--1ug4933g.xn--hndy; ; ; # 𐩗.ႩႵ +\u200C\u200Cㄤ.\u032E󕨑\u09C2; \u200C\u200Cㄤ.\u032E󕨑\u09C2; [C1, V6, V7]; xn--0uga242k.xn--vta284a9o563a; ; xn--1fk.xn--vta284a9o563a; [V6, V7] # ㄤ.̮ূ +\u200C\u200Cㄤ.\u032E󕨑\u09C2; ; [C1, V6, V7]; xn--0uga242k.xn--vta284a9o563a; ; xn--1fk.xn--vta284a9o563a; [V6, V7] # ㄤ.̮ূ +xn--1fk.xn--vta284a9o563a; ㄤ.\u032E󕨑\u09C2; [V6, V7]; xn--1fk.xn--vta284a9o563a; ; ; # ㄤ.̮ূ +xn--0uga242k.xn--vta284a9o563a; \u200C\u200Cㄤ.\u032E󕨑\u09C2; [C1, V6, V7]; xn--0uga242k.xn--vta284a9o563a; ; ; # ㄤ.̮ূ +𐋻。-\u200C𐫄Ⴗ; 𐋻.-\u200C𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ +𐋻。-\u200C𐫄Ⴗ; 𐋻.-\u200C𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ +𐋻。-\u200C𐫄ⴗ; 𐋻.-\u200C𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ +xn--v97c.xn----lws0526f; 𐋻.-𐫄ⴗ; [B1, V3]; xn--v97c.xn----lws0526f; ; ; # 𐋻.-𐫄ⴗ +xn--v97c.xn----sgnv20du99s; 𐋻.-\u200C𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; ; # 𐋻.-𐫄ⴗ +𐋻。-\u200C𐫄ⴗ; 𐋻.-\u200C𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ +xn--v97c.xn----i1g2513q; 𐋻.-𐫄Ⴗ; [B1, V3, V7]; xn--v97c.xn----i1g2513q; ; ; # 𐋻.-𐫄Ⴗ +xn--v97c.xn----i1g888ih12u; 𐋻.-\u200C𐫄Ⴗ; [B1, C1, V3, V7]; xn--v97c.xn----i1g888ih12u; ; ; # 𐋻.-𐫄Ⴗ +🙑𐷺.≠\u200C; 🙑𐷺.≠\u200C; [B1, C1, V7]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, V7] # 🙑.≠ +🙑𐷺.=\u0338\u200C; 🙑𐷺.≠\u200C; [B1, C1, V7]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, V7] # 🙑.≠ +🙑𐷺.≠\u200C; ; [B1, C1, V7]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, V7] # 🙑.≠ +🙑𐷺.=\u0338\u200C; 🙑𐷺.≠\u200C; [B1, C1, V7]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, V7] # 🙑.≠ +xn--bl0dh970b.xn--1ch; 🙑𐷺.≠; [B1, V7]; xn--bl0dh970b.xn--1ch; ; ; # 🙑.≠ +xn--bl0dh970b.xn--0ug83g; 🙑𐷺.≠\u200C; [B1, C1, V7]; xn--bl0dh970b.xn--0ug83g; ; ; # 🙑.≠ +\u064C\u1CD2。𞮞\u2D7F⧎; \u064C\u1CD2.𞮞\u2D7F⧎; [B1, B3, V6, V7]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎ +\u064C\u1CD2。𞮞\u2D7F⧎; \u064C\u1CD2.𞮞\u2D7F⧎; [B1, B3, V6, V7]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎ +xn--ohb646i.xn--ewi38jf765c; \u064C\u1CD2.𞮞\u2D7F⧎; [B1, B3, V6, V7]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎ +Ⴔ𝨨₃󠁦.𝟳𑂹\u0B82; ⴔ𝨨3󠁦.7𑂹\u0B82; [V7]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ +Ⴔ𝨨3󠁦.7𑂹\u0B82; ⴔ𝨨3󠁦.7𑂹\u0B82; [V7]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ +ⴔ𝨨3󠁦.7𑂹\u0B82; ; [V7]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ +xn--3-ews6985n35s3g.xn--7-cve6271r; ⴔ𝨨3󠁦.7𑂹\u0B82; [V7]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ +ⴔ𝨨₃󠁦.𝟳𑂹\u0B82; ⴔ𝨨3󠁦.7𑂹\u0B82; [V7]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ +xn--3-b1g83426a35t0g.xn--7-cve6271r; Ⴔ𝨨3󠁦.7𑂹\u0B82; [V7]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ +䏈\u200C。\u200C⒈񱢕; 䏈\u200C.\u200C⒈񱢕; [C1, V7]; xn--0ug491l.xn--0ug88oot66q; ; xn--eco.xn--tsh21126d; [V7] # 䏈.⒈ +䏈\u200C。\u200C1.񱢕; 䏈\u200C.\u200C1.񱢕; [C1, V7]; xn--0ug491l.xn--1-rgn.xn--ms39a; ; xn--eco.1.xn--ms39a; [V7] # 䏈.1. +xn--eco.1.xn--ms39a; 䏈.1.񱢕; [V7]; xn--eco.1.xn--ms39a; ; ; # 䏈.1. +xn--0ug491l.xn--1-rgn.xn--ms39a; 䏈\u200C.\u200C1.񱢕; [C1, V7]; xn--0ug491l.xn--1-rgn.xn--ms39a; ; ; # 䏈.1. +xn--eco.xn--tsh21126d; 䏈.⒈񱢕; [V7]; xn--eco.xn--tsh21126d; ; ; # 䏈.⒈ +xn--0ug491l.xn--0ug88oot66q; 䏈\u200C.\u200C⒈񱢕; [C1, V7]; xn--0ug491l.xn--0ug88oot66q; ; ; # 䏈.⒈ +1\uAAF6ß𑲥。\u1DD8; 1\uAAF6ß𑲥.\u1DD8; [V6]; xn--1-qfa2471kdb0d.xn--weg; ; xn--1ss-ir6ln166b.xn--weg; # 1꫶ß𑲥.ᷘ +1\uAAF6ß𑲥。\u1DD8; 1\uAAF6ß𑲥.\u1DD8; [V6]; xn--1-qfa2471kdb0d.xn--weg; ; xn--1ss-ir6ln166b.xn--weg; # 1꫶ß𑲥.ᷘ +1\uAAF6SS𑲥。\u1DD8; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +1\uAAF6ss𑲥。\u1DD8; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +xn--1ss-ir6ln166b.xn--weg; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +xn--1-qfa2471kdb0d.xn--weg; 1\uAAF6ß𑲥.\u1DD8; [V6]; xn--1-qfa2471kdb0d.xn--weg; ; ; # 1꫶ß𑲥.ᷘ +1\uAAF6SS𑲥。\u1DD8; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +1\uAAF6ss𑲥。\u1DD8; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +1\uAAF6Ss𑲥。\u1DD8; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +1\uAAF6Ss𑲥。\u1DD8; 1\uAAF6ss𑲥.\u1DD8; [V6]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ +\u200D񫶩𞪯\u0CCD。\u077C⒈; \u200D񫶩𞪯\u0CCD.\u077C⒈; [B1, C2, V7]; xn--8tc969gzn94a4lm8a.xn--dqb689l; ; xn--8tc9875v5is1a.xn--dqb689l; [B5, B6, V7] # ್.ݼ⒈ +\u200D񫶩𞪯\u0CCD。\u077C1.; \u200D񫶩𞪯\u0CCD.\u077C1.; [B1, C2, V7]; xn--8tc969gzn94a4lm8a.xn--1-g6c.; [B1, C2, V7, A4_2]; xn--8tc9875v5is1a.xn--1-g6c.; [B5, B6, V7, A4_2] # ್.ݼ1. +xn--8tc9875v5is1a.xn--1-g6c.; 񫶩𞪯\u0CCD.\u077C1.; [B5, B6, V7]; xn--8tc9875v5is1a.xn--1-g6c.; [B5, B6, V7, A4_2]; ; # ್.ݼ1. +xn--8tc969gzn94a4lm8a.xn--1-g6c.; \u200D񫶩𞪯\u0CCD.\u077C1.; [B1, C2, V7]; xn--8tc969gzn94a4lm8a.xn--1-g6c.; [B1, C2, V7, A4_2]; ; # ್.ݼ1. +xn--8tc9875v5is1a.xn--dqb689l; 񫶩𞪯\u0CCD.\u077C⒈; [B5, B6, V7]; xn--8tc9875v5is1a.xn--dqb689l; ; ; # ್.ݼ⒈ +xn--8tc969gzn94a4lm8a.xn--dqb689l; \u200D񫶩𞪯\u0CCD.\u077C⒈; [B1, C2, V7]; xn--8tc969gzn94a4lm8a.xn--dqb689l; ; ; # ್.ݼ⒈ +\u1AB6.𞤳򓢖򻉒\u07D7; \u1AB6.𞤳򓢖򻉒\u07D7; [B1, B2, V6, V7]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ +\u1AB6.𞤳򓢖򻉒\u07D7; ; [B1, B2, V6, V7]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ +\u1AB6.𞤑򓢖򻉒\u07D7; \u1AB6.𞤳򓢖򻉒\u07D7; [B1, B2, V6, V7]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ +xn--zqf.xn--ysb9657vuiz5bj0ep; \u1AB6.𞤳򓢖򻉒\u07D7; [B1, B2, V6, V7]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ +\u1AB6.𞤑򓢖򻉒\u07D7; \u1AB6.𞤳򓢖򻉒\u07D7; [B1, B2, V6, V7]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ +\u0842𞩚⒈.󠬌8򏳏\u0770; \u0842𞩚⒈.󠬌8򏳏\u0770; [B1, V7]; xn--0vb095ldg52a.xn--8-s5c22427ox454a; ; ; # ࡂ⒈.8ݰ +\u0842𞩚1..󠬌8򏳏\u0770; ; [B1, V7, X4_2]; xn--1-rid26318a..xn--8-s5c22427ox454a; [B1, V7, A4_2]; ; # ࡂ1..8ݰ +xn--1-rid26318a..xn--8-s5c22427ox454a; \u0842𞩚1..󠬌8򏳏\u0770; [B1, V7, X4_2]; xn--1-rid26318a..xn--8-s5c22427ox454a; [B1, V7, A4_2]; ; # ࡂ1..8ݰ +xn--0vb095ldg52a.xn--8-s5c22427ox454a; \u0842𞩚⒈.󠬌8򏳏\u0770; [B1, V7]; xn--0vb095ldg52a.xn--8-s5c22427ox454a; ; ; # ࡂ⒈.8ݰ +\u0361𐫫\u0369ᡷ。-󠰛鞰; \u0361𐫫\u0369ᡷ.-󠰛鞰; [B1, V3, V6, V7]; xn--cvaq482npv5t.xn----yg7dt1332g; ; ; # ͡𐫫ͩᡷ.-鞰 +xn--cvaq482npv5t.xn----yg7dt1332g; \u0361𐫫\u0369ᡷ.-󠰛鞰; [B1, V3, V6, V7]; xn--cvaq482npv5t.xn----yg7dt1332g; ; ; # ͡𐫫ͩᡷ.-鞰 +-.\u0ACD剘ß𐫃; ; [B1, V3, V6]; -.xn--zca791c493duf8i; ; -.xn--ss-bqg4734erywk; # -.્剘ß𐫃 +-.\u0ACD剘SS𐫃; -.\u0ACD剘ss𐫃; [B1, V3, V6]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃 +-.\u0ACD剘ss𐫃; ; [B1, V3, V6]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃 +-.\u0ACD剘Ss𐫃; -.\u0ACD剘ss𐫃; [B1, V3, V6]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃 +-.xn--ss-bqg4734erywk; -.\u0ACD剘ss𐫃; [B1, V3, V6]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃 +-.xn--zca791c493duf8i; -.\u0ACD剘ß𐫃; [B1, V3, V6]; -.xn--zca791c493duf8i; ; ; # -.્剘ß𐫃 +\u08FB𞵸。-; \u08FB𞵸.-; [B1, V3, V6, V7]; xn--b1b2719v.-; ; ; # ࣻ.- +\u08FB𞵸。-; \u08FB𞵸.-; [B1, V3, V6, V7]; xn--b1b2719v.-; ; ; # ࣻ.- +xn--b1b2719v.-; \u08FB𞵸.-; [B1, V3, V6, V7]; xn--b1b2719v.-; ; ; # ࣻ.- +⒈󠈻𐹲。≠\u0603𐹽; ⒈󠈻𐹲.≠\u0603𐹽; [B1, V7]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽 +⒈󠈻𐹲。=\u0338\u0603𐹽; ⒈󠈻𐹲.≠\u0603𐹽; [B1, V7]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽 +1.󠈻𐹲。≠\u0603𐹽; 1.󠈻𐹲.≠\u0603𐹽; [B1, V7]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽 +1.󠈻𐹲。=\u0338\u0603𐹽; 1.󠈻𐹲.≠\u0603𐹽; [B1, V7]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽 +1.xn--qo0dl3077c.xn--lfb536lb35n; 1.󠈻𐹲.≠\u0603𐹽; [B1, V7]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽 +xn--tshw766f1153g.xn--lfb536lb35n; ⒈󠈻𐹲.≠\u0603𐹽; [B1, V7]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽 +𐹢󠈚Ⴎ\u200C.㖾𐹡; 𐹢󠈚ⴎ\u200C.㖾𐹡; [B1, B5, B6, C1, V7]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; xn--5kjx323em053g.xn--pelu572d; [B1, B5, B6, V7] # 𐹢ⴎ.㖾𐹡 +𐹢󠈚ⴎ\u200C.㖾𐹡; ; [B1, B5, B6, C1, V7]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; xn--5kjx323em053g.xn--pelu572d; [B1, B5, B6, V7] # 𐹢ⴎ.㖾𐹡 +xn--5kjx323em053g.xn--pelu572d; 𐹢󠈚ⴎ.㖾𐹡; [B1, B5, B6, V7]; xn--5kjx323em053g.xn--pelu572d; ; ; # 𐹢ⴎ.㖾𐹡 +xn--0ug342clq0pqxv4i.xn--pelu572d; 𐹢󠈚ⴎ\u200C.㖾𐹡; [B1, B5, B6, C1, V7]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; ; # 𐹢ⴎ.㖾𐹡 +xn--mnd9001km0o0g.xn--pelu572d; 𐹢󠈚Ⴎ.㖾𐹡; [B1, B5, B6, V7]; xn--mnd9001km0o0g.xn--pelu572d; ; ; # 𐹢Ⴎ.㖾𐹡 +xn--mnd289ezj4pqxp0i.xn--pelu572d; 𐹢󠈚Ⴎ\u200C.㖾𐹡; [B1, B5, B6, C1, V7]; xn--mnd289ezj4pqxp0i.xn--pelu572d; ; ; # 𐹢Ⴎ.㖾𐹡 +򩼗.\u07C7ᡖႳႧ; 򩼗.\u07C7ᡖⴓⴇ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +򩼗.\u07C7ᡖႳႧ; 򩼗.\u07C7ᡖⴓⴇ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +򩼗.\u07C7ᡖⴓⴇ; ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +xn--te28c.xn--isb295fbtpmb; 򩼗.\u07C7ᡖⴓⴇ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +򩼗.\u07C7ᡖⴓⴇ; 򩼗.\u07C7ᡖⴓⴇ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +xn--te28c.xn--isb856b9a631d; 򩼗.\u07C7ᡖႳႧ; [B2, B3, V7]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ +򩼗.\u07C7ᡖႳⴇ; 򩼗.\u07C7ᡖⴓⴇ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +xn--te28c.xn--isb286btrgo7w; 򩼗.\u07C7ᡖႳⴇ; [B2, B3, V7]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ +򩼗.\u07C7ᡖႳⴇ; 򩼗.\u07C7ᡖⴓⴇ; [B2, B3, V7]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ +\u200D􅍉.\u06B3\u0775; ; [B1, C2, V7]; xn--1ug39444n.xn--mkb20b; ; xn--3j78f.xn--mkb20b; [V7] # .ڳݵ +xn--3j78f.xn--mkb20b; 􅍉.\u06B3\u0775; [V7]; xn--3j78f.xn--mkb20b; ; ; # .ڳݵ +xn--1ug39444n.xn--mkb20b; \u200D􅍉.\u06B3\u0775; [B1, C2, V7]; xn--1ug39444n.xn--mkb20b; ; ; # .ڳݵ +𲤱⒛⾳.ꡦ⒈; 𲤱⒛音.ꡦ⒈; [V7]; xn--dth6033bzbvx.xn--tsh9439b; ; ; # ⒛音.ꡦ⒈ +𲤱20.音.ꡦ1.; ; [V7]; xn--20-9802c.xn--0w5a.xn--1-eg4e.; [V7, A4_2]; ; # 20.音.ꡦ1. +xn--20-9802c.xn--0w5a.xn--1-eg4e.; 𲤱20.音.ꡦ1.; [V7]; xn--20-9802c.xn--0w5a.xn--1-eg4e.; [V7, A4_2]; ; # 20.音.ꡦ1. +xn--dth6033bzbvx.xn--tsh9439b; 𲤱⒛音.ꡦ⒈; [V7]; xn--dth6033bzbvx.xn--tsh9439b; ; ; # ⒛音.ꡦ⒈ +\u07DC8񳦓-。򞲙𑁿𐩥\u09CD; \u07DC8񳦓-.򞲙𑁿𐩥\u09CD; [B2, B3, B5, B6, V3, V7]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্ +\u07DC8񳦓-。򞲙𑁿𐩥\u09CD; \u07DC8񳦓-.򞲙𑁿𐩥\u09CD; [B2, B3, B5, B6, V3, V7]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্ +xn--8--rve13079p.xn--b7b9842k42df776x; \u07DC8񳦓-.򞲙𑁿𐩥\u09CD; [B2, B3, B5, B6, V3, V7]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্ +Ⴕ。۰≮ß\u0745; ⴕ.۰≮ß\u0745; ; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅ +Ⴕ。۰<\u0338ß\u0745; ⴕ.۰≮ß\u0745; ; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅ +ⴕ。۰<\u0338ß\u0745; ⴕ.۰≮ß\u0745; ; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅ +ⴕ。۰≮ß\u0745; ⴕ.۰≮ß\u0745; ; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅ +Ⴕ。۰≮SS\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ。۰<\u0338SS\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +ⴕ。۰<\u0338ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +ⴕ。۰≮ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ。۰≮Ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ。۰<\u0338Ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +xn--dlj.xn--ss-jbe65aw27i; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +ⴕ.۰≮ss\u0745; ; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +ⴕ.۰<\u0338ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ.۰<\u0338SS\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ.۰≮SS\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ.۰≮Ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +Ⴕ.۰<\u0338Ss\u0745; ⴕ.۰≮ss\u0745; ; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅ +xn--dlj.xn--zca912alh227g; ⴕ.۰≮ß\u0745; ; xn--dlj.xn--zca912alh227g; ; ; # ⴕ.۰≮ß݅ +ⴕ.۰≮ß\u0745; ; ; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅ +ⴕ.۰<\u0338ß\u0745; ⴕ.۰≮ß\u0745; ; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅ +xn--tnd.xn--ss-jbe65aw27i; Ⴕ.۰≮ss\u0745; [V7]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅ +xn--tnd.xn--zca912alh227g; Ⴕ.۰≮ß\u0745; [V7]; xn--tnd.xn--zca912alh227g; ; ; # Ⴕ.۰≮ß݅ +\u07E9-.𝨗꒱\u1B72; ; [B1, B3, V3, V6]; xn----odd.xn--dwf8994dc8wj; ; ; # ߩ-.𝨗꒱᭲ +xn----odd.xn--dwf8994dc8wj; \u07E9-.𝨗꒱\u1B72; [B1, B3, V3, V6]; xn----odd.xn--dwf8994dc8wj; ; ; # ߩ-.𝨗꒱᭲ +𞼸\u200C.≯䕵⫧; ; [B1, B3, C1, V7]; xn--0ugx453p.xn--hdh754ax6w; ; xn--sn7h.xn--hdh754ax6w; [B1, V7] # .≯䕵⫧ +𞼸\u200C.>\u0338䕵⫧; 𞼸\u200C.≯䕵⫧; [B1, B3, C1, V7]; xn--0ugx453p.xn--hdh754ax6w; ; xn--sn7h.xn--hdh754ax6w; [B1, V7] # .≯䕵⫧ +xn--sn7h.xn--hdh754ax6w; 𞼸.≯䕵⫧; [B1, V7]; xn--sn7h.xn--hdh754ax6w; ; ; # .≯䕵⫧ +xn--0ugx453p.xn--hdh754ax6w; 𞼸\u200C.≯䕵⫧; [B1, B3, C1, V7]; xn--0ugx453p.xn--hdh754ax6w; ; ; # .≯䕵⫧ +𐨅ß\uFC57.\u06AC۳︒; 𐨅ß\u064A\u062E.\u06AC۳︒; [B1, B3, V6, V7]; xn--zca23yncs877j.xn--fkb6lp314e; ; xn--ss-ytd5i7765l.xn--fkb6lp314e; # 𐨅ßيخ.ڬ۳︒ +𐨅ß\u064A\u062E.\u06AC۳。; 𐨅ß\u064A\u062E.\u06AC۳.; [B1, V6]; xn--zca23yncs877j.xn--fkb6l.; [B1, V6, A4_2]; xn--ss-ytd5i7765l.xn--fkb6l.; # 𐨅ßيخ.ڬ۳. +𐨅SS\u064A\u062E.\u06AC۳。; 𐨅ss\u064A\u062E.\u06AC۳.; [B1, V6]; xn--ss-ytd5i7765l.xn--fkb6l.; [B1, V6, A4_2]; ; # 𐨅ssيخ.ڬ۳. +𐨅ss\u064A\u062E.\u06AC۳。; 𐨅ss\u064A\u062E.\u06AC۳.; [B1, V6]; xn--ss-ytd5i7765l.xn--fkb6l.; [B1, V6, A4_2]; ; # 𐨅ssيخ.ڬ۳. +𐨅Ss\u064A\u062E.\u06AC۳。; 𐨅ss\u064A\u062E.\u06AC۳.; [B1, V6]; xn--ss-ytd5i7765l.xn--fkb6l.; [B1, V6, A4_2]; ; # 𐨅ssيخ.ڬ۳. +xn--ss-ytd5i7765l.xn--fkb6l.; 𐨅ss\u064A\u062E.\u06AC۳.; [B1, V6]; xn--ss-ytd5i7765l.xn--fkb6l.; [B1, V6, A4_2]; ; # 𐨅ssيخ.ڬ۳. +xn--zca23yncs877j.xn--fkb6l.; 𐨅ß\u064A\u062E.\u06AC۳.; [B1, V6]; xn--zca23yncs877j.xn--fkb6l.; [B1, V6, A4_2]; ; # 𐨅ßيخ.ڬ۳. +𐨅SS\uFC57.\u06AC۳︒; 𐨅ss\u064A\u062E.\u06AC۳︒; [B1, B3, V6, V7]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒ +𐨅ss\uFC57.\u06AC۳︒; 𐨅ss\u064A\u062E.\u06AC۳︒; [B1, B3, V6, V7]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒ +𐨅Ss\uFC57.\u06AC۳︒; 𐨅ss\u064A\u062E.\u06AC۳︒; [B1, B3, V6, V7]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒ +xn--ss-ytd5i7765l.xn--fkb6lp314e; 𐨅ss\u064A\u062E.\u06AC۳︒; [B1, B3, V6, V7]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒ +xn--zca23yncs877j.xn--fkb6lp314e; 𐨅ß\u064A\u062E.\u06AC۳︒; [B1, B3, V6, V7]; xn--zca23yncs877j.xn--fkb6lp314e; ; ; # 𐨅ßيخ.ڬ۳︒ +-≮🡒\u1CED.񏿾Ⴁ\u0714; -≮🡒\u1CED.񏿾ⴁ\u0714; [B1, V3, V7]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ +-<\u0338🡒\u1CED.񏿾Ⴁ\u0714; -≮🡒\u1CED.񏿾ⴁ\u0714; [B1, V3, V7]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ +-<\u0338🡒\u1CED.񏿾ⴁ\u0714; -≮🡒\u1CED.񏿾ⴁ\u0714; [B1, V3, V7]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ +-≮🡒\u1CED.񏿾ⴁ\u0714; ; [B1, V3, V7]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ +xn----44l04zxt68c.xn--enb135qf106f; -≮🡒\u1CED.񏿾ⴁ\u0714; [B1, V3, V7]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ +xn----44l04zxt68c.xn--enb300c1597h; -≮🡒\u1CED.񏿾Ⴁ\u0714; [B1, V3, V7]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ +𞤨。ꡏ\u200D\u200C; 𞤨.ꡏ\u200D\u200C; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ +𞤨。ꡏ\u200D\u200C; 𞤨.ꡏ\u200D\u200C; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ +𞤆。ꡏ\u200D\u200C; 𞤨.ꡏ\u200D\u200C; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ +xn--ge6h.xn--oc9a; 𞤨.ꡏ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ +𞤨.ꡏ; ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ +𞤆.ꡏ; 𞤨.ꡏ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ +xn--ge6h.xn--0ugb9575h; 𞤨.ꡏ\u200D\u200C; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; ; # 𞤨.ꡏ +𞤆。ꡏ\u200D\u200C; 𞤨.ꡏ\u200D\u200C; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ +󠅹𑂶.ᢌ𑂹\u0669; 𑂶.ᢌ𑂹\u0669; [B1, B5, B6, V6]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩ +󠅹𑂶.ᢌ𑂹\u0669; 𑂶.ᢌ𑂹\u0669; [B1, B5, B6, V6]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩ +xn--b50d.xn--iib993gyp5p; 𑂶.ᢌ𑂹\u0669; [B1, B5, B6, V6]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩ +Ⅎ󠅺񝵒。≯⾑; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +Ⅎ󠅺񝵒。>\u0338⾑; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +Ⅎ󠅺񝵒。≯襾; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +Ⅎ󠅺񝵒。>\u0338襾; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +ⅎ󠅺񝵒。>\u0338襾; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +ⅎ󠅺񝵒。≯襾; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +xn--73g39298c.xn--hdhz171b; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +ⅎ󠅺񝵒。>\u0338⾑; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +ⅎ󠅺񝵒。≯⾑; ⅎ񝵒.≯襾; [V7]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾 +xn--f3g73398c.xn--hdhz171b; Ⅎ񝵒.≯襾; [V7]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾 +ς\u200D\u0DD4\u0660。-; ς\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # ςු٠.- +ς\u200D\u0DD4\u0660。-; ς\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # ςු٠.- +Σ\u200D\u0DD4\u0660。-; σ\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.- +σ\u200D\u0DD4\u0660。-; σ\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.- +xn--4xa25ks2j.-; σ\u0DD4\u0660.-; [B1, B5, B6, V3]; xn--4xa25ks2j.-; ; ; # σු٠.- +xn--4xa25ks2jenu.-; σ\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; ; # σු٠.- +xn--3xa45ks2jenu.-; ς\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; ; # ςු٠.- +Σ\u200D\u0DD4\u0660。-; σ\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.- +σ\u200D\u0DD4\u0660。-; σ\u200D\u0DD4\u0660.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.- +\u200C.ßႩ-; \u200C.ßⴉ-; [C1, V3]; xn--0ug.xn----pfa2305a; ; .xn--ss--bi1b; [V3, A4_2] # .ßⴉ- +\u200C.ßⴉ-; ; [C1, V3]; xn--0ug.xn----pfa2305a; ; .xn--ss--bi1b; [V3, A4_2] # .ßⴉ- +\u200C.SSႩ-; \u200C.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ- +\u200C.ssⴉ-; ; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ- +\u200C.Ssⴉ-; \u200C.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ- +.xn--ss--bi1b; .ssⴉ-; [V3, X4_2]; .xn--ss--bi1b; [V3, A4_2]; ; # .ssⴉ- +xn--0ug.xn--ss--bi1b; \u200C.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; ; # .ssⴉ- +xn--0ug.xn----pfa2305a; \u200C.ßⴉ-; [C1, V3]; xn--0ug.xn----pfa2305a; ; ; # .ßⴉ- +.xn--ss--4rn; .ssႩ-; [V3, V7, X4_2]; .xn--ss--4rn; [V3, V7, A4_2]; ; # .ssႩ- +xn--0ug.xn--ss--4rn; \u200C.ssႩ-; [C1, V3, V7]; xn--0ug.xn--ss--4rn; ; ; # .ssႩ- +xn--0ug.xn----pfa042j; \u200C.ßႩ-; [C1, V3, V7]; xn--0ug.xn----pfa042j; ; ; # .ßႩ- +󍭲𐫍㓱。⾑; 󍭲𐫍㓱.襾; [B5, V7]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾 +󍭲𐫍㓱。襾; 󍭲𐫍㓱.襾; [B5, V7]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾 +xn--u7kt691dlj09f.xn--9v2a; 󍭲𐫍㓱.襾; [B5, V7]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾 +\u06A0𐮋𐹰≮。≯󠦗\u200D; \u06A0𐮋𐹰≮.≯󠦗\u200D; [B1, B3, C2, V7]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; xn--2jb053lf13nyoc.xn--hdh08821l; [B1, B3, V7] # ڠ𐮋𐹰≮.≯ +\u06A0𐮋𐹰<\u0338。>\u0338󠦗\u200D; \u06A0𐮋𐹰≮.≯󠦗\u200D; [B1, B3, C2, V7]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; xn--2jb053lf13nyoc.xn--hdh08821l; [B1, B3, V7] # ڠ𐮋𐹰≮.≯ +xn--2jb053lf13nyoc.xn--hdh08821l; \u06A0𐮋𐹰≮.≯󠦗; [B1, B3, V7]; xn--2jb053lf13nyoc.xn--hdh08821l; ; ; # ڠ𐮋𐹰≮.≯ +xn--2jb053lf13nyoc.xn--1ugx6gc8096c; \u06A0𐮋𐹰≮.≯󠦗\u200D; [B1, B3, C2, V7]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; ; # ڠ𐮋𐹰≮.≯ +𝟞。񃰶\u0777\u08B0⩋; 6.񃰶\u0777\u08B0⩋; [B1, B5, B6, V7]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋ +6。񃰶\u0777\u08B0⩋; 6.񃰶\u0777\u08B0⩋; [B1, B5, B6, V7]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋ +6.xn--7pb04do15eq748f; 6.񃰶\u0777\u08B0⩋; [B1, B5, B6, V7]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋ +-\uFCFD。𑇀𑍴; -\u0634\u0649.𑇀𑍴; [B1, V3, V6]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴 +-\uFCFD。𑇀𑍴; -\u0634\u0649.𑇀𑍴; [B1, V3, V6]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴 +-\u0634\u0649。𑇀𑍴; -\u0634\u0649.𑇀𑍴; [B1, V3, V6]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴 +xn----qnc7d.xn--wd1d62a; -\u0634\u0649.𑇀𑍴; [B1, V3, V6]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴 +\u200C󠊶𝟏.\u0D43򪥐𐹬󊓶; \u200C󠊶1.\u0D43򪥐𐹬󊓶; [B1, C1, V6, V7]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; xn--1-f521m.xn--mxc0872kcu37dnmem; [B1, V6, V7] # 1.ൃ𐹬 +\u200C󠊶1.\u0D43򪥐𐹬󊓶; ; [B1, C1, V6, V7]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; xn--1-f521m.xn--mxc0872kcu37dnmem; [B1, V6, V7] # 1.ൃ𐹬 +xn--1-f521m.xn--mxc0872kcu37dnmem; 󠊶1.\u0D43򪥐𐹬󊓶; [B1, V6, V7]; xn--1-f521m.xn--mxc0872kcu37dnmem; ; ; # 1.ൃ𐹬 +xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; \u200C󠊶1.\u0D43򪥐𐹬󊓶; [B1, C1, V6, V7]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; ; # 1.ൃ𐹬 +齙--𝟰.ß; 齙--4.ß; ; xn----4-p16k.xn--zca; ; xn----4-p16k.ss; # 齙--4.ß +齙--4.ß; ; ; xn----4-p16k.xn--zca; ; xn----4-p16k.ss; # 齙--4.ß +齙--4.SS; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss +齙--4.ss; ; ; xn----4-p16k.ss; ; ; # 齙--4.ss +齙--4.Ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss +xn----4-p16k.ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss +xn----4-p16k.xn--zca; 齙--4.ß; ; xn----4-p16k.xn--zca; ; ; # 齙--4.ß +齙--𝟰.SS; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss +齙--𝟰.ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss +齙--𝟰.Ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss +\u1BF2.𐹢𞀖\u200C; ; [B1, C1, V6]; xn--0zf.xn--0ug9894grqqf; ; xn--0zf.xn--9n0d2296a; [B1, V6] # ᯲.𐹢𞀖 +xn--0zf.xn--9n0d2296a; \u1BF2.𐹢𞀖; [B1, V6]; xn--0zf.xn--9n0d2296a; ; ; # ᯲.𐹢𞀖 +xn--0zf.xn--0ug9894grqqf; \u1BF2.𐹢𞀖\u200C; [B1, C1, V6]; xn--0zf.xn--0ug9894grqqf; ; ; # ᯲.𐹢𞀖 +󃲙󠋘。?-\u200D; 󃲙󠋘.?-\u200D; [C2, V7, U1]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [V3, V7, U1] # .?- +󃲙󠋘。?-\u200D; 󃲙󠋘.?-\u200D; [C2, V7, U1]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [V3, V7, U1] # .?- +xn--ct86d8w51a.?-; 󃲙󠋘.?-; [V3, V7, U1]; xn--ct86d8w51a.?-; ; ; # .?- +xn--ct86d8w51a.xn--?--n1t; 󃲙󠋘.?-\u200D; [C2, V7, U1]; xn--ct86d8w51a.xn--?--n1t; ; ; # .?- +xn--ct86d8w51a.?-\u200D; 󃲙󠋘.?-\u200D; [C2, V7, U1]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [V3, V7, U1] # .?- +XN--CT86D8W51A.?-\u200D; 󃲙󠋘.?-\u200D; [C2, V7, U1]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [V3, V7, U1] # .?- +Xn--Ct86d8w51a.?-\u200D; 󃲙󠋘.?-\u200D; [C2, V7, U1]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [V3, V7, U1] # .?- +\u1A60.𞵷-𝪩悎; \u1A60.𞵷-𝪩悎; [B1, B2, B3, V6, V7]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎 +\u1A60.𞵷-𝪩悎; ; [B1, B2, B3, V6, V7]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎 +xn--jof.xn----gf4bq282iezpa; \u1A60.𞵷-𝪩悎; [B1, B2, B3, V6, V7]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎 +𛜯󠊛.𞤳񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, V7]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳 +𛜯󠊛.𞤳񏥾; ; [B2, B3, B6, V7]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳 +𛜯󠊛.𞤑񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, V7]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳 +xn--xx5gy2741c.xn--re6hw266j; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, V7]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳 +𛜯󠊛.𞤑񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, V7]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳 +\u071C𐫒\u062E.𐋲; ; [B1]; xn--tgb98b8643d.xn--m97c; ; ; # ܜ𐫒خ.𐋲 +xn--tgb98b8643d.xn--m97c; \u071C𐫒\u062E.𐋲; [B1]; xn--tgb98b8643d.xn--m97c; ; ; # ܜ𐫒خ.𐋲 +𐼑𞤓\u0637\u08E2.?; 𐼑𞤵\u0637\u08E2.?; [B1, V7, U1]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.? +𐼑𞤵\u0637\u08E2.?; ; [B1, V7, U1]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.? +xn--2gb08k9w69agm0g.?; 𐼑𞤵\u0637\u08E2.?; [B1, V7, U1]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.? +Ↄ。\u0A4D\u1CD4𞷣; ↄ.\u1CD4\u0A4D𞷣; [B1, V6, V7]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍ +Ↄ。\u1CD4\u0A4D𞷣; ↄ.\u1CD4\u0A4D𞷣; [B1, V6, V7]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍ +ↄ。\u1CD4\u0A4D𞷣; ↄ.\u1CD4\u0A4D𞷣; [B1, V6, V7]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍ +xn--r5g.xn--ybc995g0835a; ↄ.\u1CD4\u0A4D𞷣; [B1, V6, V7]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍ +ↄ。\u0A4D\u1CD4𞷣; ↄ.\u1CD4\u0A4D𞷣; [B1, V6, V7]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍ +xn--q5g.xn--ybc995g0835a; Ↄ.\u1CD4\u0A4D𞷣; [B1, V6, V7]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍ +󠪢-。򛂏≮𑜫; 󠪢-.򛂏≮𑜫; [V3, V7]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫 +󠪢-。򛂏<\u0338𑜫; 󠪢-.򛂏≮𑜫; [V3, V7]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫 +xn----bh61m.xn--gdhz157g0em1d; 󠪢-.򛂏≮𑜫; [V3, V7]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫 +\u200C󠉹\u200D。򌿧≮Ⴉ; \u200C󠉹\u200D.򌿧≮ⴉ; [C1, C2, V7]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [V7] # .≮ⴉ +\u200C󠉹\u200D。򌿧<\u0338Ⴉ; \u200C󠉹\u200D.򌿧≮ⴉ; [C1, C2, V7]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [V7] # .≮ⴉ +\u200C󠉹\u200D。򌿧<\u0338ⴉ; \u200C󠉹\u200D.򌿧≮ⴉ; [C1, C2, V7]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [V7] # .≮ⴉ +\u200C󠉹\u200D。򌿧≮ⴉ; \u200C󠉹\u200D.򌿧≮ⴉ; [C1, C2, V7]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [V7] # .≮ⴉ +xn--3n36e.xn--gdh992byu01p; 󠉹.򌿧≮ⴉ; [V7]; xn--3n36e.xn--gdh992byu01p; ; ; # .≮ⴉ +xn--0ugc90904y.xn--gdh992byu01p; \u200C󠉹\u200D.򌿧≮ⴉ; [C1, C2, V7]; xn--0ugc90904y.xn--gdh992byu01p; ; ; # .≮ⴉ +xn--3n36e.xn--hnd112gpz83n; 󠉹.򌿧≮Ⴉ; [V7]; xn--3n36e.xn--hnd112gpz83n; ; ; # .≮Ⴉ +xn--0ugc90904y.xn--hnd112gpz83n; \u200C󠉹\u200D.򌿧≮Ⴉ; [C1, C2, V7]; xn--0ugc90904y.xn--hnd112gpz83n; ; ; # .≮Ⴉ +𐹯-𑄴\u08BC。︒䖐⾆; 𐹯-𑄴\u08BC.︒䖐舌; [B1, V7]; xn----rpd7902rclc.xn--fpo216mn07e; ; ; # 𐹯-𑄴ࢼ.︒䖐舌 +𐹯-𑄴\u08BC。。䖐舌; 𐹯-𑄴\u08BC..䖐舌; [B1, X4_2]; xn----rpd7902rclc..xn--fpo216m; [B1, A4_2]; ; # 𐹯-𑄴ࢼ..䖐舌 +xn----rpd7902rclc..xn--fpo216m; 𐹯-𑄴\u08BC..䖐舌; [B1, X4_2]; xn----rpd7902rclc..xn--fpo216m; [B1, A4_2]; ; # 𐹯-𑄴ࢼ..䖐舌 +xn----rpd7902rclc.xn--fpo216mn07e; 𐹯-𑄴\u08BC.︒䖐舌; [B1, V7]; xn----rpd7902rclc.xn--fpo216mn07e; ; ; # 𐹯-𑄴ࢼ.︒䖐舌 +𝪞Ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞Ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞Ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞Ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +xn--7kj1858k.xn--pi6b; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V6]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡 +xn--ond3755u.xn--pi6b; 𝪞Ⴐ.쪡; [V6, V7]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡 +\u0E3A쩁𐹬.􋉳; ; [B1, V6, V7]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬. +\u0E3A쩁𐹬.􋉳; \u0E3A쩁𐹬.􋉳; [B1, V6, V7]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬. +xn--o4c4837g2zvb.xn--5f70g; \u0E3A쩁𐹬.􋉳; [B1, V6, V7]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬. +ᡅ0\u200C。⎢󤨄; ᡅ0\u200C.⎢󤨄; [C1, V7]; xn--0-z6jy93b.xn--8lh28773l; ; xn--0-z6j.xn--8lh28773l; [V7] # ᡅ0.⎢ +ᡅ0\u200C。⎢󤨄; ᡅ0\u200C.⎢󤨄; [C1, V7]; xn--0-z6jy93b.xn--8lh28773l; ; xn--0-z6j.xn--8lh28773l; [V7] # ᡅ0.⎢ +xn--0-z6j.xn--8lh28773l; ᡅ0.⎢󤨄; [V7]; xn--0-z6j.xn--8lh28773l; ; ; # ᡅ0.⎢ +xn--0-z6jy93b.xn--8lh28773l; ᡅ0\u200C.⎢󤨄; [C1, V7]; xn--0-z6jy93b.xn--8lh28773l; ; ; # ᡅ0.⎢ +𲮚9ꍩ\u17D3.\u200Dß; 𲮚9ꍩ\u17D3.\u200Dß; [C2, V7]; xn--9-i0j5967eg3qz.xn--zca770n; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ß +𲮚9ꍩ\u17D3.\u200Dß; ; [C2, V7]; xn--9-i0j5967eg3qz.xn--zca770n; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ß +𲮚9ꍩ\u17D3.\u200DSS; 𲮚9ꍩ\u17D3.\u200Dss; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ss +𲮚9ꍩ\u17D3.\u200Dss; ; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ss +xn--9-i0j5967eg3qz.ss; 𲮚9ꍩ\u17D3.ss; [V7]; xn--9-i0j5967eg3qz.ss; ; ; # 9ꍩ៓.ss +xn--9-i0j5967eg3qz.xn--ss-l1t; 𲮚9ꍩ\u17D3.\u200Dss; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; ; # 9ꍩ៓.ss +xn--9-i0j5967eg3qz.xn--zca770n; 𲮚9ꍩ\u17D3.\u200Dß; [C2, V7]; xn--9-i0j5967eg3qz.xn--zca770n; ; ; # 9ꍩ៓.ß +𲮚9ꍩ\u17D3.\u200DSS; 𲮚9ꍩ\u17D3.\u200Dss; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ss +𲮚9ꍩ\u17D3.\u200Dss; 𲮚9ꍩ\u17D3.\u200Dss; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ss +𲮚9ꍩ\u17D3.\u200DSs; 𲮚9ꍩ\u17D3.\u200Dss; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ss +𲮚9ꍩ\u17D3.\u200DSs; 𲮚9ꍩ\u17D3.\u200Dss; [C2, V7]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [V7] # 9ꍩ៓.ss +ꗷ𑆀.\u075D𐩒; ; ; xn--ju8a625r.xn--hpb0073k; ; ; # ꗷ𑆀.ݝ𐩒 +xn--ju8a625r.xn--hpb0073k; ꗷ𑆀.\u075D𐩒; ; xn--ju8a625r.xn--hpb0073k; ; ; # ꗷ𑆀.ݝ𐩒 +⒐≯-。︒򩑣-񞛠; ⒐≯-.︒򩑣-񞛠; [V3, V7]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒- +⒐>\u0338-。︒򩑣-񞛠; ⒐≯-.︒򩑣-񞛠; [V3, V7]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒- +9.≯-。。򩑣-񞛠; 9.≯-..򩑣-񞛠; [V3, V7, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [V3, V7, A4_2]; ; # 9.≯-..- +9.>\u0338-。。򩑣-񞛠; 9.≯-..򩑣-񞛠; [V3, V7, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [V3, V7, A4_2]; ; # 9.≯-..- +9.xn----ogo..xn----xj54d1s69k; 9.≯-..򩑣-񞛠; [V3, V7, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [V3, V7, A4_2]; ; # 9.≯-..- +xn----ogot9g.xn----n89hl0522az9u2a; ⒐≯-.︒򩑣-񞛠; [V3, V7]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒- +򈪚\u0CE3Ⴡ󠢏.\u061D; 򈪚\u0CE3ⴡ󠢏.\u061D; [B6, V7]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝ +򈪚\u0CE3Ⴡ󠢏.\u061D; 򈪚\u0CE3ⴡ󠢏.\u061D; [B6, V7]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝ +򈪚\u0CE3ⴡ󠢏.\u061D; ; [B6, V7]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝ +xn--vuc226n8n28lmju7a.xn--cgb; 򈪚\u0CE3ⴡ󠢏.\u061D; [B6, V7]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝ +򈪚\u0CE3ⴡ󠢏.\u061D; 򈪚\u0CE3ⴡ󠢏.\u061D; [B6, V7]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝ +xn--vuc49qvu85xmju7a.xn--cgb; 򈪚\u0CE3Ⴡ󠢏.\u061D; [B6, V7]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝ +\u1DEB。𐋩\u0638-𐫮; \u1DEB.𐋩\u0638-𐫮; [B1, V6]; xn--gfg.xn----xnc0815qyyg; ; ; # ᷫ.𐋩ظ-𐫮 +xn--gfg.xn----xnc0815qyyg; \u1DEB.𐋩\u0638-𐫮; [B1, V6]; xn--gfg.xn----xnc0815qyyg; ; ; # ᷫ.𐋩ظ-𐫮 +싇。⾇𐳋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐳋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐳋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐳋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐲋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐲋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。舛𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +xn--9u4b.xn--llj123yh74e; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐲋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐲋Ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +싇。⾇𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ +xn--9u4b.xn--1nd7519ch79d; 싇.舛𐳋Ⴝ; [B5, V7]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ +𐹠ς。\u200C\u06BFჀ; 𐹠ς.\u200C\u06BFⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠ς.ڿⴠ +𐹠ς。\u200C\u06BFⴠ; 𐹠ς.\u200C\u06BFⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠ς.ڿⴠ +𐹠Σ。\u200C\u06BFჀ; 𐹠σ.\u200C\u06BFⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ +𐹠σ。\u200C\u06BFⴠ; 𐹠σ.\u200C\u06BFⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ +𐹠Σ。\u200C\u06BFⴠ; 𐹠σ.\u200C\u06BFⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ +xn--4xa9167k.xn--ykb467q; 𐹠σ.\u06BFⴠ; [B1, B2, B3]; xn--4xa9167k.xn--ykb467q; ; ; # 𐹠σ.ڿⴠ +xn--4xa9167k.xn--ykb760k9hj; 𐹠σ.\u200C\u06BFⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; ; # 𐹠σ.ڿⴠ +xn--3xa1267k.xn--ykb760k9hj; 𐹠ς.\u200C\u06BFⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; ; # 𐹠ς.ڿⴠ +xn--4xa9167k.xn--ykb632c; 𐹠σ.\u06BFჀ; [B1, B2, B3, V7]; xn--4xa9167k.xn--ykb632c; ; ; # 𐹠σ.ڿჀ +xn--4xa9167k.xn--ykb632cvxm; 𐹠σ.\u200C\u06BFჀ; [B1, C1, V7]; xn--4xa9167k.xn--ykb632cvxm; ; ; # 𐹠σ.ڿჀ +xn--3xa1267k.xn--ykb632cvxm; 𐹠ς.\u200C\u06BFჀ; [B1, C1, V7]; xn--3xa1267k.xn--ykb632cvxm; ; ; # 𐹠ς.ڿჀ +򇒐\u200C\u0604.\u069A-ß; ; [B2, B3, B5, B6, C1, V7]; xn--mfb144kqo32m.xn----qfa315b; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, V7] # .ښ-ß +򇒐\u200C\u0604.\u069A-SS; 򇒐\u200C\u0604.\u069A-ss; [B2, B3, B5, B6, C1, V7]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, V7] # .ښ-ss +򇒐\u200C\u0604.\u069A-ss; ; [B2, B3, B5, B6, C1, V7]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, V7] # .ښ-ss +򇒐\u200C\u0604.\u069A-Ss; 򇒐\u200C\u0604.\u069A-ss; [B2, B3, B5, B6, C1, V7]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, V7] # .ښ-ss +xn--mfb98261i.xn---ss-sdf; 򇒐\u0604.\u069A-ss; [B2, B3, B5, B6, V7]; xn--mfb98261i.xn---ss-sdf; ; ; # .ښ-ss +xn--mfb144kqo32m.xn---ss-sdf; 򇒐\u200C\u0604.\u069A-ss; [B2, B3, B5, B6, C1, V7]; xn--mfb144kqo32m.xn---ss-sdf; ; ; # .ښ-ss +xn--mfb144kqo32m.xn----qfa315b; 򇒐\u200C\u0604.\u069A-ß; [B2, B3, B5, B6, C1, V7]; xn--mfb144kqo32m.xn----qfa315b; ; ; # .ښ-ß +\u200C\u200D\u17B5\u067A.-\uFBB0󅄞𐸚; \u200C\u200D\u067A.-\u06D3󅄞𐸚; [B1, C1, C2, V3, V7]; xn--zib502kda.xn----twc1133r17r6g; ; xn--zib.xn----twc1133r17r6g; [B1, V3, V7] # ٺ.-ۓ +\u200C\u200D\u17B5\u067A.-\u06D3󅄞𐸚; \u200C\u200D\u067A.-\u06D3󅄞𐸚; [B1, C1, C2, V3, V7]; xn--zib502kda.xn----twc1133r17r6g; ; xn--zib.xn----twc1133r17r6g; [B1, V3, V7] # ٺ.-ۓ +\u200C\u200D\u17B5\u067A.-\u06D2\u0654󅄞𐸚; \u200C\u200D\u067A.-\u06D3󅄞𐸚; [B1, C1, C2, V3, V7]; xn--zib502kda.xn----twc1133r17r6g; ; xn--zib.xn----twc1133r17r6g; [B1, V3, V7] # ٺ.-ۓ +xn--zib.xn----twc1133r17r6g; \u067A.-\u06D3󅄞𐸚; [B1, V3, V7]; xn--zib.xn----twc1133r17r6g; ; ; # ٺ.-ۓ +xn--zib502kda.xn----twc1133r17r6g; \u200C\u200D\u067A.-\u06D3󅄞𐸚; [B1, C1, C2, V3, V7]; xn--zib502kda.xn----twc1133r17r6g; ; ; # ٺ.-ۓ +xn--zib539f.xn----twc1133r17r6g; \u17B5\u067A.-\u06D3󅄞𐸚; [B1, V3, V6, V7]; xn--zib539f.xn----twc1133r17r6g; ; ; # ٺ.-ۓ +xn--zib539f8igea.xn----twc1133r17r6g; \u200C\u200D\u17B5\u067A.-\u06D3󅄞𐸚; [B1, C1, C2, V3, V7]; xn--zib539f8igea.xn----twc1133r17r6g; ; ; # ٺ.-ۓ +򡶱。𐮬≠; 򡶱.𐮬≠; [B3, V7]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠ +򡶱。𐮬=\u0338; 򡶱.𐮬≠; [B3, V7]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠ +򡶱。𐮬≠; 򡶱.𐮬≠; [B3, V7]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠ +򡶱。𐮬=\u0338; 򡶱.𐮬≠; [B3, V7]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠ +xn--dd55c.xn--1ch3003g; 򡶱.𐮬≠; [B3, V7]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠ +\u0FB2𞶅。𐹮𐹷덝۵; \u0FB2𞶅.𐹮𐹷덝۵; [B1, V6, V7]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵ +\u0FB2𞶅。𐹮𐹷덝۵; \u0FB2𞶅.𐹮𐹷덝۵; [B1, V6, V7]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵ +\u0FB2𞶅。𐹮𐹷덝۵; \u0FB2𞶅.𐹮𐹷덝۵; [B1, V6, V7]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵ +\u0FB2𞶅。𐹮𐹷덝۵; \u0FB2𞶅.𐹮𐹷덝۵; [B1, V6, V7]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵ +xn--fgd0675v.xn--imb5839fidpcbba; \u0FB2𞶅.𐹮𐹷덝۵; [B1, V6, V7]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵ +Ⴏ󠅋-.\u200DႩ; ⴏ-.\u200Dⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ +Ⴏ󠅋-.\u200DႩ; ⴏ-.\u200Dⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ +ⴏ󠅋-.\u200Dⴉ; ⴏ-.\u200Dⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ +xn----3vs.xn--0kj; ⴏ-.ⴉ; [V3]; xn----3vs.xn--0kj; ; ; # ⴏ-.ⴉ +xn----3vs.xn--1ug532c; ⴏ-.\u200Dⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; ; # ⴏ-.ⴉ +ⴏ󠅋-.\u200Dⴉ; ⴏ-.\u200Dⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ +xn----00g.xn--hnd; Ⴏ-.Ⴉ; [V3, V7]; xn----00g.xn--hnd; ; ; # Ⴏ-.Ⴉ +xn----00g.xn--hnd399e; Ⴏ-.\u200DႩ; [C2, V3, V7]; xn----00g.xn--hnd399e; ; ; # Ⴏ-.Ⴉ +⇧𐨏󠾈󯶅。\u0600󠈵󠆉; ⇧𐨏󠾈󯶅.\u0600󠈵; [B1, V7]; xn--l8g5552g64t4g46xf.xn--ifb08144p; ; ; # ⇧𐨏. +xn--l8g5552g64t4g46xf.xn--ifb08144p; ⇧𐨏󠾈󯶅.\u0600󠈵; [B1, V7]; xn--l8g5552g64t4g46xf.xn--ifb08144p; ; ; # ⇧𐨏. +≠𐮂.↑🄇⒈; ≠𐮂.↑6,⒈; [B1, V7, U1]; xn--1chy492g.xn--6,-uzus5m; ; ; # ≠𐮂.↑6,⒈ +=\u0338𐮂.↑🄇⒈; ≠𐮂.↑6,⒈; [B1, V7, U1]; xn--1chy492g.xn--6,-uzus5m; ; ; # ≠𐮂.↑6,⒈ +≠𐮂.↑6,1.; ; [B1, U1]; xn--1chy492g.xn--6,1-pw1a.; [B1, U1, A4_2]; ; # ≠𐮂.↑6,1. +=\u0338𐮂.↑6,1.; ≠𐮂.↑6,1.; [B1, U1]; xn--1chy492g.xn--6,1-pw1a.; [B1, U1, A4_2]; ; # ≠𐮂.↑6,1. +xn--1chy492g.xn--6,1-pw1a.; ≠𐮂.↑6,1.; [B1, U1]; xn--1chy492g.xn--6,1-pw1a.; [B1, U1, A4_2]; ; # ≠𐮂.↑6,1. +xn--1chy492g.xn--6,-uzus5m; ≠𐮂.↑6,⒈; [B1, V7, U1]; xn--1chy492g.xn--6,-uzus5m; ; ; # ≠𐮂.↑6,⒈ +xn--1chy492g.xn--45gx9iuy44d; ≠𐮂.↑🄇⒈; [B1, V7]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈ +𝩏󠲉ß.ᢤ򄦌\u200C𐹫; ; [B1, B5, B6, C1, V6, V7]; xn--zca3153vupz3e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, V6, V7] # 𝩏ß.ᢤ𐹫 +𝩏󠲉SS.ᢤ򄦌\u200C𐹫; 𝩏󠲉ss.ᢤ򄦌\u200C𐹫; [B1, B5, B6, C1, V6, V7]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, V6, V7] # 𝩏ss.ᢤ𐹫 +𝩏󠲉ss.ᢤ򄦌\u200C𐹫; ; [B1, B5, B6, C1, V6, V7]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, V6, V7] # 𝩏ss.ᢤ𐹫 +𝩏󠲉Ss.ᢤ򄦌\u200C𐹫; 𝩏󠲉ss.ᢤ򄦌\u200C𐹫; [B1, B5, B6, C1, V6, V7]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, V6, V7] # 𝩏ss.ᢤ𐹫 +xn--ss-zb11ap1427e.xn--ubf2596jbt61c; 𝩏󠲉ss.ᢤ򄦌𐹫; [B1, B5, B6, V6, V7]; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; ; ; # 𝩏ss.ᢤ𐹫 +xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; 𝩏󠲉ss.ᢤ򄦌\u200C𐹫; [B1, B5, B6, C1, V6, V7]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; ; # 𝩏ss.ᢤ𐹫 +xn--zca3153vupz3e.xn--ubf609atw1tynn3d; 𝩏󠲉ß.ᢤ򄦌\u200C𐹫; [B1, B5, B6, C1, V6, V7]; xn--zca3153vupz3e.xn--ubf609atw1tynn3d; ; ; # 𝩏ß.ᢤ𐹫 +ß𐵳񗘁Ⴇ。\uA67A; ß𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ß𐵳ⴇ.ꙺ +ß𐵳񗘁Ⴇ。\uA67A; ß𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ß𐵳ⴇ.ꙺ +ß𐵳񗘁ⴇ。\uA67A; ß𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ß𐵳ⴇ.ꙺ +SS𐵓񗘁Ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +ss𐵳񗘁ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +Ss𐵳񗘁Ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +xn--ss-e61ar955h4hs7b.xn--9x8a; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +xn--zca227tpy4lkns1b.xn--9x8a; ß𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--zca227tpy4lkns1b.xn--9x8a; ; ; # ß𐵳ⴇ.ꙺ +ß𐵳񗘁ⴇ。\uA67A; ß𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ß𐵳ⴇ.ꙺ +SS𐵓񗘁Ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +ss𐵳񗘁ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +Ss𐵳񗘁Ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +SS𐵳񗘁Ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +xn--ss-rek7420r4hs7b.xn--9x8a; ss𐵳񗘁Ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ss𐵳Ⴇ.ꙺ +xn--zca491fci5qkn79a.xn--9x8a; ß𐵳񗘁Ⴇ.\uA67A; [B1, B5, V6, V7]; xn--zca491fci5qkn79a.xn--9x8a; ; ; # ß𐵳Ⴇ.ꙺ +SS𐵳񗘁Ⴇ。\uA67A; ss𐵳񗘁ⴇ.\uA67A; [B1, B5, V6, V7]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ss𐵳ⴇ.ꙺ +\u1714。󠆣-𑋪; \u1714.-𑋪; [V3, V6]; xn--fze.xn----ly8i; ; ; # ᜔.-𑋪 +xn--fze.xn----ly8i; \u1714.-𑋪; [V3, V6]; xn--fze.xn----ly8i; ; ; # ᜔.-𑋪 +\uABE8-.򨏜\u05BDß; \uABE8-.򨏜\u05BDß; [V3, V6, V7]; xn----pw5e.xn--zca50wfv060a; ; xn----pw5e.xn--ss-7jd10716y; # ꯨ-.ֽß +\uABE8-.򨏜\u05BDß; ; [V3, V6, V7]; xn----pw5e.xn--zca50wfv060a; ; xn----pw5e.xn--ss-7jd10716y; # ꯨ-.ֽß +\uABE8-.򨏜\u05BDSS; \uABE8-.򨏜\u05BDss; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +\uABE8-.򨏜\u05BDss; ; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +\uABE8-.򨏜\u05BDSs; \uABE8-.򨏜\u05BDss; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +xn----pw5e.xn--ss-7jd10716y; \uABE8-.򨏜\u05BDss; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +xn----pw5e.xn--zca50wfv060a; \uABE8-.򨏜\u05BDß; [V3, V6, V7]; xn----pw5e.xn--zca50wfv060a; ; ; # ꯨ-.ֽß +\uABE8-.򨏜\u05BDSS; \uABE8-.򨏜\u05BDss; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +\uABE8-.򨏜\u05BDss; \uABE8-.򨏜\u05BDss; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +\uABE8-.򨏜\u05BDSs; \uABE8-.򨏜\u05BDss; [V3, V6, V7]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss +ᡓ-≮。\u066B󠅱ᡄ; ᡓ-≮.\u066Bᡄ; [B1, B6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ +ᡓ-<\u0338。\u066B󠅱ᡄ; ᡓ-≮.\u066Bᡄ; [B1, B6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ +xn----s7j866c.xn--kib252g; ᡓ-≮.\u066Bᡄ; [B1, B6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ +𝟥♮𑜫\u08ED.\u17D2𑜫8󠆏; 3♮𑜫\u08ED.\u17D2𑜫8; [V6]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8 +3♮𑜫\u08ED.\u17D2𑜫8󠆏; 3♮𑜫\u08ED.\u17D2𑜫8; [V6]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8 +xn--3-ksd277tlo7s.xn--8-f0jx021l; 3♮𑜫\u08ED.\u17D2𑜫8; [V6]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8 +-。򕌀\u200D❡; -.򕌀\u200D❡; [C2, V3, V7]; -.xn--1ug800aq795s; ; -.xn--nei54421f; [V3, V7] # -.❡ +-。򕌀\u200D❡; -.򕌀\u200D❡; [C2, V3, V7]; -.xn--1ug800aq795s; ; -.xn--nei54421f; [V3, V7] # -.❡ +-.xn--nei54421f; -.򕌀❡; [V3, V7]; -.xn--nei54421f; ; ; # -.❡ +-.xn--1ug800aq795s; -.򕌀\u200D❡; [C2, V3, V7]; -.xn--1ug800aq795s; ; ; # -.❡ +𝟓☱𝟐򥰵。𝪮񐡳; 5☱2򥰵.𝪮񐡳; [V6, V7]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮 +5☱2򥰵。𝪮񐡳; 5☱2򥰵.𝪮񐡳; [V6, V7]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮 +xn--52-dwx47758j.xn--kd3hk431k; 5☱2򥰵.𝪮񐡳; [V6, V7]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮 +-.-├򖦣; ; [V3, V7]; -.xn----ukp70432h; ; ; # -.-├ +-.xn----ukp70432h; -.-├򖦣; [V3, V7]; -.xn----ukp70432h; ; ; # -.-├ +\u05A5\u076D。\u200D󠀘; \u05A5\u076D.\u200D󠀘; [B1, C2, V6, V7]; xn--wcb62g.xn--1ugy8001l; ; xn--wcb62g.xn--p526e; [B1, V6, V7] # ֥ݭ. +\u05A5\u076D。\u200D󠀘; \u05A5\u076D.\u200D󠀘; [B1, C2, V6, V7]; xn--wcb62g.xn--1ugy8001l; ; xn--wcb62g.xn--p526e; [B1, V6, V7] # ֥ݭ. +xn--wcb62g.xn--p526e; \u05A5\u076D.󠀘; [B1, V6, V7]; xn--wcb62g.xn--p526e; ; ; # ֥ݭ. +xn--wcb62g.xn--1ugy8001l; \u05A5\u076D.\u200D󠀘; [B1, C2, V6, V7]; xn--wcb62g.xn--1ugy8001l; ; ; # ֥ݭ. +쥥󔏉Ⴎ.\u200C⒈⒈𐫒; 쥥󔏉ⴎ.\u200C⒈⒈𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, V7] # 쥥ⴎ.⒈⒈𐫒 +쥥󔏉Ⴎ.\u200C⒈⒈𐫒; 쥥󔏉ⴎ.\u200C⒈⒈𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, V7] # 쥥ⴎ.⒈⒈𐫒 +쥥󔏉Ⴎ.\u200C1.1.𐫒; 쥥󔏉ⴎ.\u200C1.1.𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, V7] # 쥥ⴎ.1.1.𐫒 +쥥󔏉Ⴎ.\u200C1.1.𐫒; 쥥󔏉ⴎ.\u200C1.1.𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, V7] # 쥥ⴎ.1.1.𐫒 +쥥󔏉ⴎ.\u200C1.1.𐫒; 쥥󔏉ⴎ.\u200C1.1.𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, V7] # 쥥ⴎ.1.1.𐫒 +쥥󔏉ⴎ.\u200C1.1.𐫒; ; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, V7] # 쥥ⴎ.1.1.𐫒 +xn--5kj3511ccyw3h.1.1.xn--7w9c; 쥥󔏉ⴎ.1.1.𐫒; [B1, V7]; xn--5kj3511ccyw3h.1.1.xn--7w9c; ; ; # 쥥ⴎ.1.1.𐫒 +xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; 쥥󔏉ⴎ.\u200C1.1.𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; ; # 쥥ⴎ.1.1.𐫒 +쥥󔏉ⴎ.\u200C⒈⒈𐫒; 쥥󔏉ⴎ.\u200C⒈⒈𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, V7] # 쥥ⴎ.⒈⒈𐫒 +쥥󔏉ⴎ.\u200C⒈⒈𐫒; 쥥󔏉ⴎ.\u200C⒈⒈𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, V7] # 쥥ⴎ.⒈⒈𐫒 +xn--5kj3511ccyw3h.xn--tsha6797o; 쥥󔏉ⴎ.⒈⒈𐫒; [B1, V7]; xn--5kj3511ccyw3h.xn--tsha6797o; ; ; # 쥥ⴎ.⒈⒈𐫒 +xn--5kj3511ccyw3h.xn--0ug88oa0396u; 쥥󔏉ⴎ.\u200C⒈⒈𐫒; [B1, C1, V7]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; ; # 쥥ⴎ.⒈⒈𐫒 +xn--mnd7865gcy28g.1.1.xn--7w9c; 쥥󔏉Ⴎ.1.1.𐫒; [B1, V7]; xn--mnd7865gcy28g.1.1.xn--7w9c; ; ; # 쥥Ⴎ.1.1.𐫒 +xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; 쥥󔏉Ⴎ.\u200C1.1.𐫒; [B1, C1, V7]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; ; # 쥥Ⴎ.1.1.𐫒 +xn--mnd7865gcy28g.xn--tsha6797o; 쥥󔏉Ⴎ.⒈⒈𐫒; [B1, V7]; xn--mnd7865gcy28g.xn--tsha6797o; ; ; # 쥥Ⴎ.⒈⒈𐫒 +xn--mnd7865gcy28g.xn--0ug88oa0396u; 쥥󔏉Ⴎ.\u200C⒈⒈𐫒; [B1, C1, V7]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; ; # 쥥Ⴎ.⒈⒈𐫒 +\u0827𝟶\u06A0-。𑄳; \u08270\u06A0-.𑄳; [B1, V3, V6]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳 +\u08270\u06A0-。𑄳; \u08270\u06A0-.𑄳; [B1, V3, V6]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳 +xn--0--p3d67m.xn--v80d; \u08270\u06A0-.𑄳; [B1, V3, V6]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳 +ς.\uFDC1🞛⒈; ς.\u0641\u0645\u064A🞛⒈; [V7]; xn--3xa.xn--dhbip2802atb20c; ; xn--4xa.xn--dhbip2802atb20c; # ς.فمي🞛⒈ +ς.\u0641\u0645\u064A🞛1.; ; ; xn--3xa.xn--1-gocmu97674d.; [A4_2]; xn--4xa.xn--1-gocmu97674d.; # ς.فمي🞛1. +Σ.\u0641\u0645\u064A🞛1.; σ.\u0641\u0645\u064A🞛1.; ; xn--4xa.xn--1-gocmu97674d.; [A4_2]; ; # σ.فمي🞛1. +σ.\u0641\u0645\u064A🞛1.; ; ; xn--4xa.xn--1-gocmu97674d.; [A4_2]; ; # σ.فمي🞛1. +xn--4xa.xn--1-gocmu97674d.; σ.\u0641\u0645\u064A🞛1.; ; xn--4xa.xn--1-gocmu97674d.; [A4_2]; ; # σ.فمي🞛1. +xn--3xa.xn--1-gocmu97674d.; ς.\u0641\u0645\u064A🞛1.; ; xn--3xa.xn--1-gocmu97674d.; [A4_2]; ; # ς.فمي🞛1. +Σ.\uFDC1🞛⒈; σ.\u0641\u0645\u064A🞛⒈; [V7]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈ +σ.\uFDC1🞛⒈; σ.\u0641\u0645\u064A🞛⒈; [V7]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈ +xn--4xa.xn--dhbip2802atb20c; σ.\u0641\u0645\u064A🞛⒈; [V7]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈ +xn--3xa.xn--dhbip2802atb20c; ς.\u0641\u0645\u064A🞛⒈; [V7]; xn--3xa.xn--dhbip2802atb20c; ; ; # ς.فمي🞛⒈ +🗩-。𐹻󐞆񥉮; 🗩-.𐹻󐞆񥉮; [B1, V3, V7]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻 +🗩-。𐹻󐞆񥉮; 🗩-.𐹻󐞆񥉮; [B1, V3, V7]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻 +xn----6t3s.xn--zo0d4811u6ru6a; 🗩-.𐹻󐞆񥉮; [B1, V3, V7]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻 +𐡜-🔪。𝟻\u200C𐿀; 𐡜-🔪.5\u200C𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; xn----5j4iv089c.xn--5-bn7i; [B1, B3] # 𐡜-🔪.5𐿀 +𐡜-🔪。5\u200C𐿀; 𐡜-🔪.5\u200C𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; xn----5j4iv089c.xn--5-bn7i; [B1, B3] # 𐡜-🔪.5𐿀 +xn----5j4iv089c.xn--5-bn7i; 𐡜-🔪.5𐿀; [B1, B3]; xn----5j4iv089c.xn--5-bn7i; ; ; # 𐡜-🔪.5𐿀 +xn----5j4iv089c.xn--5-sgn7149h; 𐡜-🔪.5\u200C𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; ; # 𐡜-🔪.5𐿀 +𐹣늿\u200Dß.\u07CF0\u05BC; 𐹣늿\u200Dß.\u07CF0\u05BC; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ +𐹣늿\u200Dß.\u07CF0\u05BC; 𐹣늿\u200Dß.\u07CF0\u05BC; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ +𐹣늿\u200Dß.\u07CF0\u05BC; ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ +𐹣늿\u200Dß.\u07CF0\u05BC; 𐹣늿\u200Dß.\u07CF0\u05BC; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ +𐹣늿\u200DSS.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200DSS.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200Dss.\u07CF0\u05BC; ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200Dss.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +xn--ss-i05i7041a.xn--0-vgc50n; 𐹣늿ss.\u07CF0\u05BC; [B1]; xn--ss-i05i7041a.xn--0-vgc50n; ; ; # 𐹣늿ss.ߏ0ּ +xn--ss-l1tu910fo0xd.xn--0-vgc50n; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; ; # 𐹣늿ss.ߏ0ּ +𐹣늿\u200DSs.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200DSs.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +xn--zca770n5s4hev6c.xn--0-vgc50n; 𐹣늿\u200Dß.\u07CF0\u05BC; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; ; # 𐹣늿ß.ߏ0ּ +𐹣늿\u200DSS.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200DSS.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200Dss.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200Dss.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200DSs.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +𐹣늿\u200DSs.\u07CF0\u05BC; 𐹣늿\u200Dss.\u07CF0\u05BC; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ +9󠇥.󪴴ᢓ; 9.󪴴ᢓ; [V7]; 9.xn--dbf91222q; ; ; # 9.ᢓ +9󠇥.󪴴ᢓ; 9.󪴴ᢓ; [V7]; 9.xn--dbf91222q; ; ; # 9.ᢓ +9.xn--dbf91222q; 9.󪴴ᢓ; [V7]; 9.xn--dbf91222q; ; ; # 9.ᢓ +\u200C\uFFA0.𐫭🠗ß⽟; \u200C.𐫭🠗ß玉; [B1, B2, B3, C1]; xn--0ug.xn--zca2289c550e0iwi; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ß玉 +\u200C\u1160.𐫭🠗ß玉; \u200C.𐫭🠗ß玉; [B1, B2, B3, C1]; xn--0ug.xn--zca2289c550e0iwi; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ß玉 +\u200C\u1160.𐫭🠗SS玉; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ss玉 +\u200C\u1160.𐫭🠗ss玉; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ss玉 +\u200C\u1160.𐫭🠗Ss玉; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ss玉 +.xn--ss-je6eq954cp25j; .𐫭🠗ss玉; [B2, B3, X4_2]; .xn--ss-je6eq954cp25j; [B2, B3, A4_2]; ; # .𐫭🠗ss玉 +xn--0ug.xn--ss-je6eq954cp25j; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉 +xn--0ug.xn--zca2289c550e0iwi; \u200C.𐫭🠗ß玉; [B1, B2, B3, C1]; xn--0ug.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉 +\u200C\uFFA0.𐫭🠗SS⽟; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ss玉 +\u200C\uFFA0.𐫭🠗ss⽟; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ss玉 +\u200C\uFFA0.𐫭🠗Ss⽟; \u200C.𐫭🠗ss玉; [B1, B2, B3, C1]; xn--0ug.xn--ss-je6eq954cp25j; ; .xn--ss-je6eq954cp25j; [B2, B3, A4_2] # .𐫭🠗ss玉 +xn--psd.xn--ss-je6eq954cp25j; \u1160.𐫭🠗ss玉; [B2, B3, V7]; xn--psd.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉 +xn--psd526e.xn--ss-je6eq954cp25j; \u200C\u1160.𐫭🠗ss玉; [B1, B2, B3, C1, V7]; xn--psd526e.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉 +xn--psd526e.xn--zca2289c550e0iwi; \u200C\u1160.𐫭🠗ß玉; [B1, B2, B3, C1, V7]; xn--psd526e.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉 +xn--cl7c.xn--ss-je6eq954cp25j; \uFFA0.𐫭🠗ss玉; [B2, B3, V7]; xn--cl7c.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉 +xn--0ug7719f.xn--ss-je6eq954cp25j; \u200C\uFFA0.𐫭🠗ss玉; [B1, B2, B3, C1, V7]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉 +xn--0ug7719f.xn--zca2289c550e0iwi; \u200C\uFFA0.𐫭🠗ß玉; [B1, B2, B3, C1, V7]; xn--0ug7719f.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉 +︒Ⴖ\u0366.\u200C; ︒ⴖ\u0366.\u200C; [C1, V7]; xn--hva754sy94k.xn--0ug; ; xn--hva754sy94k.; [V7, A4_2] # ︒ⴖͦ. +。Ⴖ\u0366.\u200C; .ⴖ\u0366.\u200C; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; .xn--hva754s.; [A4_2] # .ⴖͦ. +。ⴖ\u0366.\u200C; .ⴖ\u0366.\u200C; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; .xn--hva754s.; [A4_2] # .ⴖͦ. +.xn--hva754s.; .ⴖ\u0366.; [X4_2]; .xn--hva754s.; [A4_2]; ; # .ⴖͦ. +.xn--hva754s.xn--0ug; .ⴖ\u0366.\u200C; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; ; # .ⴖͦ. +︒ⴖ\u0366.\u200C; ︒ⴖ\u0366.\u200C; [C1, V7]; xn--hva754sy94k.xn--0ug; ; xn--hva754sy94k.; [V7, A4_2] # ︒ⴖͦ. +xn--hva754sy94k.; ︒ⴖ\u0366.; [V7]; xn--hva754sy94k.; [V7, A4_2]; ; # ︒ⴖͦ. +xn--hva754sy94k.xn--0ug; ︒ⴖ\u0366.\u200C; [C1, V7]; xn--hva754sy94k.xn--0ug; ; ; # ︒ⴖͦ. +.xn--hva929d.; .Ⴖ\u0366.; [V7, X4_2]; .xn--hva929d.; [V7, A4_2]; ; # .Ⴖͦ. +.xn--hva929d.xn--0ug; .Ⴖ\u0366.\u200C; [C1, V7, X4_2]; .xn--hva929d.xn--0ug; [C1, V7, A4_2]; ; # .Ⴖͦ. +xn--hva929dl29p.; ︒Ⴖ\u0366.; [V7]; xn--hva929dl29p.; [V7, A4_2]; ; # ︒Ⴖͦ. +xn--hva929dl29p.xn--0ug; ︒Ⴖ\u0366.\u200C; [C1, V7]; xn--hva929dl29p.xn--0ug; ; ; # ︒Ⴖͦ. +xn--hva754s.; ⴖ\u0366.; ; xn--hva754s.; [A4_2]; ; # ⴖͦ. +ⴖ\u0366.; ; ; xn--hva754s.; [A4_2]; ; # ⴖͦ. +Ⴖ\u0366.; ⴖ\u0366.; ; xn--hva754s.; [A4_2]; ; # ⴖͦ. +xn--hva929d.; Ⴖ\u0366.; [V7]; xn--hva929d.; [V7, A4_2]; ; # Ⴖͦ. +\u08BB.\u200CႣ𞀒; \u08BB.\u200Cⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒 +\u08BB.\u200CႣ𞀒; \u08BB.\u200Cⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒 +\u08BB.\u200Cⴃ𞀒; ; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒 +xn--hzb.xn--ukj4430l; \u08BB.ⴃ𞀒; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒 +\u08BB.ⴃ𞀒; ; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒 +\u08BB.Ⴃ𞀒; \u08BB.ⴃ𞀒; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒 +xn--hzb.xn--0ug822cp045a; \u08BB.\u200Cⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; ; # ࢻ.ⴃ𞀒 +\u08BB.\u200Cⴃ𞀒; \u08BB.\u200Cⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒 +xn--hzb.xn--bnd2938u; \u08BB.Ⴃ𞀒; [V7]; xn--hzb.xn--bnd2938u; ; ; # ࢻ.Ⴃ𞀒 +xn--hzb.xn--bnd300f7225a; \u08BB.\u200CႣ𞀒; [B1, C1, V7]; xn--hzb.xn--bnd300f7225a; ; ; # ࢻ.Ⴃ𞀒 +\u200D\u200C。2䫷󠧷; \u200D\u200C.2䫷󠧷; [C1, C2, V7]; xn--0ugb.xn--2-me5ay1273i; ; .xn--2-me5ay1273i; [V7, A4_2] # .2䫷 +\u200D\u200C。2䫷󠧷; \u200D\u200C.2䫷󠧷; [C1, C2, V7]; xn--0ugb.xn--2-me5ay1273i; ; .xn--2-me5ay1273i; [V7, A4_2] # .2䫷 +.xn--2-me5ay1273i; .2䫷󠧷; [V7, X4_2]; .xn--2-me5ay1273i; [V7, A4_2]; ; # .2䫷 +xn--0ugb.xn--2-me5ay1273i; \u200D\u200C.2䫷󠧷; [C1, C2, V7]; xn--0ugb.xn--2-me5ay1273i; ; ; # .2䫷 +-𞀤󜠐。򈬖; -𞀤󜠐.򈬖; [V3, V7]; xn----rq4re4997d.xn--l707b; ; ; # -𞀤. +xn----rq4re4997d.xn--l707b; -𞀤󜠐.򈬖; [V3, V7]; xn----rq4re4997d.xn--l707b; ; ; # -𞀤. +󳛂︒\u200C㟀.\u0624⒈; 󳛂︒\u200C㟀.\u0624⒈; [C1, V7]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; xn--etlt457ccrq7h.xn--jgb476m; [V7] # ︒㟀.ؤ⒈ +󳛂︒\u200C㟀.\u0648\u0654⒈; 󳛂︒\u200C㟀.\u0624⒈; [C1, V7]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; xn--etlt457ccrq7h.xn--jgb476m; [V7] # ︒㟀.ؤ⒈ +󳛂。\u200C㟀.\u06241.; 󳛂.\u200C㟀.\u06241.; [B1, C1, V7]; xn--z272f.xn--0ug754g.xn--1-smc.; [B1, C1, V7, A4_2]; xn--z272f.xn--etl.xn--1-smc.; [V7, A4_2] # .㟀.ؤ1. +󳛂。\u200C㟀.\u0648\u06541.; 󳛂.\u200C㟀.\u06241.; [B1, C1, V7]; xn--z272f.xn--0ug754g.xn--1-smc.; [B1, C1, V7, A4_2]; xn--z272f.xn--etl.xn--1-smc.; [V7, A4_2] # .㟀.ؤ1. +xn--z272f.xn--etl.xn--1-smc.; 󳛂.㟀.\u06241.; [V7]; xn--z272f.xn--etl.xn--1-smc.; [V7, A4_2]; ; # .㟀.ؤ1. +xn--z272f.xn--0ug754g.xn--1-smc.; 󳛂.\u200C㟀.\u06241.; [B1, C1, V7]; xn--z272f.xn--0ug754g.xn--1-smc.; [B1, C1, V7, A4_2]; ; # .㟀.ؤ1. +xn--etlt457ccrq7h.xn--jgb476m; 󳛂︒㟀.\u0624⒈; [V7]; xn--etlt457ccrq7h.xn--jgb476m; ; ; # ︒㟀.ؤ⒈ +xn--0ug754gxl4ldlt0k.xn--jgb476m; 󳛂︒\u200C㟀.\u0624⒈; [C1, V7]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; ; # ︒㟀.ؤ⒈ +𑲜\u07CA𝅼。-\u200D; 𑲜\u07CA𝅼.-\u200D; [B1, C2, V3, V6]; xn--lsb5482l7nre.xn----ugn; ; xn--lsb5482l7nre.-; [B1, V3, V6] # 𑲜ߊ𝅼.- +xn--lsb5482l7nre.-; 𑲜\u07CA𝅼.-; [B1, V3, V6]; xn--lsb5482l7nre.-; ; ; # 𑲜ߊ𝅼.- +xn--lsb5482l7nre.xn----ugn; 𑲜\u07CA𝅼.-\u200D; [B1, C2, V3, V6]; xn--lsb5482l7nre.xn----ugn; ; ; # 𑲜ߊ𝅼.- +\u200C.Ⴉ≠𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +\u200C.Ⴉ=\u0338𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +\u200C.Ⴉ≠𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +\u200C.Ⴉ=\u0338𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +\u200C.ⴉ=\u0338𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +\u200C.ⴉ≠𐫶; ; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +.xn--1chx23bzj4p; .ⴉ≠𐫶; [B5, B6, X4_2]; .xn--1chx23bzj4p; [B5, B6, A4_2]; ; # .ⴉ≠𐫶 +xn--0ug.xn--1chx23bzj4p; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; ; # .ⴉ≠𐫶 +\u200C.ⴉ=\u0338𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +\u200C.ⴉ≠𐫶; \u200C.ⴉ≠𐫶; [B1, B5, B6, C1]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, A4_2] # .ⴉ≠𐫶 +.xn--hnd481gv73o; .Ⴉ≠𐫶; [B5, B6, V7, X4_2]; .xn--hnd481gv73o; [B5, B6, V7, A4_2]; ; # .Ⴉ≠𐫶 +xn--0ug.xn--hnd481gv73o; \u200C.Ⴉ≠𐫶; [B1, B5, B6, C1, V7]; xn--0ug.xn--hnd481gv73o; ; ; # .Ⴉ≠𐫶 +\u0750。≯ς; \u0750.≯ς; [B1]; xn--3ob.xn--3xa918m; ; xn--3ob.xn--4xa718m; # ݐ.≯ς +\u0750。>\u0338ς; \u0750.≯ς; [B1]; xn--3ob.xn--3xa918m; ; xn--3ob.xn--4xa718m; # ݐ.≯ς +\u0750。>\u0338Σ; \u0750.≯σ; [B1]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ +\u0750。≯Σ; \u0750.≯σ; [B1]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ +\u0750。≯σ; \u0750.≯σ; [B1]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ +\u0750。>\u0338σ; \u0750.≯σ; [B1]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ +xn--3ob.xn--4xa718m; \u0750.≯σ; [B1]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ +xn--3ob.xn--3xa918m; \u0750.≯ς; [B1]; xn--3ob.xn--3xa918m; ; ; # ݐ.≯ς +\u07FC𐸆.𓖏︒񊨩Ⴐ; \u07FC𐸆.𓖏︒񊨩ⴐ; [V7]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .𓖏︒ⴐ +\u07FC𐸆.𓖏。񊨩Ⴐ; \u07FC𐸆.𓖏.񊨩ⴐ; [V7]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # .𓖏.ⴐ +\u07FC𐸆.𓖏。񊨩ⴐ; \u07FC𐸆.𓖏.񊨩ⴐ; [V7]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # .𓖏.ⴐ +xn--0tb8725k.xn--tu8d.xn--7kj73887a; \u07FC𐸆.𓖏.񊨩ⴐ; [V7]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # .𓖏.ⴐ +\u07FC𐸆.𓖏︒񊨩ⴐ; ; [V7]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .𓖏︒ⴐ +xn--0tb8725k.xn--7kj9008dt18a7py9c; \u07FC𐸆.𓖏︒񊨩ⴐ; [V7]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .𓖏︒ⴐ +xn--0tb8725k.xn--tu8d.xn--ond97931d; \u07FC𐸆.𓖏.񊨩Ⴐ; [V7]; xn--0tb8725k.xn--tu8d.xn--ond97931d; ; ; # .𓖏.Ⴐ +xn--0tb8725k.xn--ond3562jt18a7py9c; \u07FC𐸆.𓖏︒񊨩Ⴐ; [V7]; xn--0tb8725k.xn--ond3562jt18a7py9c; ; ; # .𓖏︒Ⴐ +Ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [V6, V7]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼 +Ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [V6, V7]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼 +ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [V6, V7]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼 +xn--vfh16m67gx1162b.xn--ro1d; ⴥ⚭󠖫⋃.𑌼; [V6, V7]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼 +ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [V6, V7]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼 +xn--9nd623g4zc5z060c.xn--ro1d; Ⴥ⚭󠖫⋃.𑌼; [V6, V7]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼 +🄈。󠷳\u0844; 7,.󠷳\u0844; [B1, V7, U1]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ +7,。󠷳\u0844; 7,.󠷳\u0844; [B1, V7, U1]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ +7,.xn--2vb13094p; 7,.󠷳\u0844; [B1, V7, U1]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ +xn--107h.xn--2vb13094p; 🄈.󠷳\u0844; [B1, V7]; xn--107h.xn--2vb13094p; ; ; # 🄈.ࡄ +≮\u0846。섖쮖ß; ≮\u0846.섖쮖ß; [B1]; xn--4vb505k.xn--zca7259goug; ; xn--4vb505k.xn--ss-5z4j006a; # ≮ࡆ.섖쮖ß +<\u0338\u0846。섖쮖ß; ≮\u0846.섖쮖ß; [B1]; xn--4vb505k.xn--zca7259goug; ; xn--4vb505k.xn--ss-5z4j006a; # ≮ࡆ.섖쮖ß +<\u0338\u0846。섖쮖SS; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +≮\u0846。섖쮖SS; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +≮\u0846。섖쮖ss; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +<\u0338\u0846。섖쮖ss; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +xn--4vb505k.xn--ss-5z4j006a; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +≮\u0846。섖쮖Ss; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +<\u0338\u0846。섖쮖Ss; ≮\u0846.섖쮖ss; [B1]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss +xn--4vb505k.xn--zca7259goug; ≮\u0846.섖쮖ß; [B1]; xn--4vb505k.xn--zca7259goug; ; ; # ≮ࡆ.섖쮖ß +󠆓⛏-。ꡒ; ⛏-.ꡒ; [V3]; xn----o9p.xn--rc9a; ; ; # ⛏-.ꡒ +xn----o9p.xn--rc9a; ⛏-.ꡒ; [V3]; xn----o9p.xn--rc9a; ; ; # ⛏-.ꡒ +\u07BB𐹳\u0626𑁆。\u08A7\u06B0\u200Cᢒ; \u07BB𐹳\u0626𑁆.\u08A7\u06B0\u200Cᢒ; [B2, B3, V7]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; xn--lgb32f2753cosb.xn--jkb91hlz1a; # 𐹳ئ𑁆.ࢧڰᢒ +\u07BB𐹳\u064A𑁆\u0654。\u08A7\u06B0\u200Cᢒ; \u07BB𐹳\u0626𑁆.\u08A7\u06B0\u200Cᢒ; [B2, B3, V7]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; xn--lgb32f2753cosb.xn--jkb91hlz1a; # 𐹳ئ𑁆.ࢧڰᢒ +xn--lgb32f2753cosb.xn--jkb91hlz1a; \u07BB𐹳\u0626𑁆.\u08A7\u06B0ᢒ; [B2, B3, V7]; xn--lgb32f2753cosb.xn--jkb91hlz1a; ; ; # 𐹳ئ𑁆.ࢧڰᢒ +xn--lgb32f2753cosb.xn--jkb91hlz1azih; \u07BB𐹳\u0626𑁆.\u08A7\u06B0\u200Cᢒ; [B2, B3, V7]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; ; # 𐹳ئ𑁆.ࢧڰᢒ +\u0816.𐨕𚚕; ; [B1, B2, B3, V6, V7]; xn--rub.xn--tr9c248x; ; ; # ࠖ.𐨕 +xn--rub.xn--tr9c248x; \u0816.𐨕𚚕; [B1, B2, B3, V6, V7]; xn--rub.xn--tr9c248x; ; ; # ࠖ.𐨕 +--。𽊆\u0767𐽋𞠬; --.𽊆\u0767𐽋𞠬; [B1, B5, B6, V3, V7]; --.xn--rpb6226k77pfh58p; ; ; # --.ݧ𐽋𞠬 +--.xn--rpb6226k77pfh58p; --.𽊆\u0767𐽋𞠬; [B1, B5, B6, V3, V7]; --.xn--rpb6226k77pfh58p; ; ; # --.ݧ𐽋𞠬 +򛭦𐋥𹸐.≯\u08B0\u08A6󔛣; ; [B1, V7]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ +򛭦𐋥𹸐.>\u0338\u08B0\u08A6󔛣; 򛭦𐋥𹸐.≯\u08B0\u08A6󔛣; [B1, V7]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ +xn--887c2298i5mv6a.xn--vybt688qm8981a; 򛭦𐋥𹸐.≯\u08B0\u08A6󔛣; [B1, V7]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ +䔛󠇒򤸞𐹧.-䤷; 䔛򤸞𐹧.-䤷; [B1, B5, B6, V3, V7]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷 +䔛󠇒򤸞𐹧.-䤷; 䔛򤸞𐹧.-䤷; [B1, B5, B6, V3, V7]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷 +xn--2loy662coo60e.xn----0n4a; 䔛򤸞𐹧.-䤷; [B1, B5, B6, V3, V7]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷 +𐹩.\u200D-; 𐹩.\u200D-; [B1, C2, V3]; xn--ho0d.xn----tgn; ; xn--ho0d.-; [B1, V3] # 𐹩.- +𐹩.\u200D-; ; [B1, C2, V3]; xn--ho0d.xn----tgn; ; xn--ho0d.-; [B1, V3] # 𐹩.- +xn--ho0d.-; 𐹩.-; [B1, V3]; xn--ho0d.-; ; ; # 𐹩.- +xn--ho0d.xn----tgn; 𐹩.\u200D-; [B1, C2, V3]; xn--ho0d.xn----tgn; ; ; # 𐹩.- +񂈦帷。≯萺\u1DC8-; 񂈦帷.≯萺\u1DC8-; [V3, V7]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈- +񂈦帷。>\u0338萺\u1DC8-; 񂈦帷.≯萺\u1DC8-; [V3, V7]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈- +񂈦帷。≯萺\u1DC8-; 񂈦帷.≯萺\u1DC8-; [V3, V7]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈- +񂈦帷。>\u0338萺\u1DC8-; 񂈦帷.≯萺\u1DC8-; [V3, V7]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈- +xn--qutw175s.xn----mimu6tf67j; 񂈦帷.≯萺\u1DC8-; [V3, V7]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈- +\u200D攌\uABED。ᢖ-Ⴘ; \u200D攌\uABED.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; xn--p9ut19m.xn----mck373i; [] # 攌꯭.ᢖ-ⴘ +\u200D攌\uABED。ᢖ-ⴘ; \u200D攌\uABED.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; xn--p9ut19m.xn----mck373i; [] # 攌꯭.ᢖ-ⴘ +xn--p9ut19m.xn----mck373i; 攌\uABED.ᢖ-ⴘ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ +攌\uABED.ᢖ-ⴘ; ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ +攌\uABED.ᢖ-Ⴘ; 攌\uABED.ᢖ-ⴘ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ +xn--1ug592ykp6b.xn----mck373i; \u200D攌\uABED.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ +xn--p9ut19m.xn----k1g451d; 攌\uABED.ᢖ-Ⴘ; [V7]; xn--p9ut19m.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ +xn--1ug592ykp6b.xn----k1g451d; \u200D攌\uABED.ᢖ-Ⴘ; [C2, V7]; xn--1ug592ykp6b.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ +\u200Cꖨ.⒗3툒۳; \u200Cꖨ.⒗3툒۳; [C1, V7]; xn--0ug2473c.xn--3-nyc678tu07m; ; xn--9r8a.xn--3-nyc678tu07m; [V7] # ꖨ.⒗3툒۳ +\u200Cꖨ.⒗3툒۳; \u200Cꖨ.⒗3툒۳; [C1, V7]; xn--0ug2473c.xn--3-nyc678tu07m; ; xn--9r8a.xn--3-nyc678tu07m; [V7] # ꖨ.⒗3툒۳ +\u200Cꖨ.16.3툒۳; ; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; xn--9r8a.16.xn--3-nyc0117m; [] # ꖨ.16.3툒۳ +\u200Cꖨ.16.3툒۳; \u200Cꖨ.16.3툒۳; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; xn--9r8a.16.xn--3-nyc0117m; [] # ꖨ.16.3툒۳ +xn--9r8a.16.xn--3-nyc0117m; ꖨ.16.3툒۳; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳ +ꖨ.16.3툒۳; ; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳ +ꖨ.16.3툒۳; ꖨ.16.3툒۳; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳ +xn--0ug2473c.16.xn--3-nyc0117m; \u200Cꖨ.16.3툒۳; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳ +xn--9r8a.xn--3-nyc678tu07m; ꖨ.⒗3툒۳; [V7]; xn--9r8a.xn--3-nyc678tu07m; ; ; # ꖨ.⒗3툒۳ +xn--0ug2473c.xn--3-nyc678tu07m; \u200Cꖨ.⒗3툒۳; [C1, V7]; xn--0ug2473c.xn--3-nyc678tu07m; ; ; # ꖨ.⒗3툒۳ +⒈걾6.𐱁\u06D0; ; [B1, V7]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې +⒈걾6.𐱁\u06D0; ⒈걾6.𐱁\u06D0; [B1, V7]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې +1.걾6.𐱁\u06D0; ; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې +1.걾6.𐱁\u06D0; 1.걾6.𐱁\u06D0; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې +1.xn--6-945e.xn--glb1794k; 1.걾6.𐱁\u06D0; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې +xn--6-dcps419c.xn--glb1794k; ⒈걾6.𐱁\u06D0; [B1, V7]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې +𐲞𝟶≮≮.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐲞𝟶<\u0338<\u0338.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐲞0≮≮.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐲞0<\u0338<\u0338.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐳞0<\u0338<\u0338.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐳞0≮≮.󠀧\u0639; ; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +xn--0-ngoa5711v.xn--4gb31034p; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐳞𝟶<\u0338<\u0338.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +𐳞𝟶≮≮.󠀧\u0639; 𐳞0≮≮.󠀧\u0639; [B1, B3, V7]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع +\u0AE3.𐹺\u115F; \u0AE3.𐹺; [B1, V6]; xn--8fc.xn--yo0d; ; ; # ૣ.𐹺 +xn--8fc.xn--yo0d; \u0AE3.𐹺; [B1, V6]; xn--8fc.xn--yo0d; ; ; # ૣ.𐹺 +xn--8fc.xn--osd3070k; \u0AE3.𐹺\u115F; [B1, V6, V7]; xn--8fc.xn--osd3070k; ; ; # ૣ.𐹺 +𝟏𝨙⸖.\u200D; 1𝨙⸖.\u200D; [C2]; xn--1-5bt6845n.xn--1ug; ; xn--1-5bt6845n.; [A4_2] # 1𝨙⸖. +1𝨙⸖.\u200D; ; [C2]; xn--1-5bt6845n.xn--1ug; ; xn--1-5bt6845n.; [A4_2] # 1𝨙⸖. +xn--1-5bt6845n.; 1𝨙⸖.; ; xn--1-5bt6845n.; [A4_2]; ; # 1𝨙⸖. +1𝨙⸖.; ; ; xn--1-5bt6845n.; [A4_2]; ; # 1𝨙⸖. +xn--1-5bt6845n.xn--1ug; 1𝨙⸖.\u200D; [C2]; xn--1-5bt6845n.xn--1ug; ; ; # 1𝨙⸖. +𞤐≠\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𞤐=\u0338\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𞤐≠\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𞤐=\u0338\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𞤲=\u0338\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𞤲≠\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +xn--wnb859grzfzw60c.xn----kcd; 𞤲≠\u0726\u1A60.-\u07D5; [B1, V3]; xn--wnb859grzfzw60c.xn----kcd; ; ; # 𞤲≠ܦ᩠.-ߕ +xn--wnb859grzfzw60c.xn----kcd017p; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; ; # 𞤲≠ܦ᩠.-ߕ +𞤲=\u0338\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𞤲≠\u0726\u1A60。-\u200C\u07D5; 𞤲≠\u0726\u1A60.-\u200C\u07D5; [B1, C1, V3]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, V3] # 𞤲≠ܦ᩠.-ߕ +𐹰\u0368-ꡧ。\u0675; 𐹰\u0368-ꡧ.\u0627\u0674; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ +𐹰\u0368-ꡧ。\u0627\u0674; 𐹰\u0368-ꡧ.\u0627\u0674; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ +xn----shb2387jgkqd.xn--mgb8m; 𐹰\u0368-ꡧ.\u0627\u0674; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ +F󠅟。򏗅♚; f.򏗅♚; [V7]; f.xn--45hz6953f; ; ; # f.♚ +F󠅟。򏗅♚; f.򏗅♚; [V7]; f.xn--45hz6953f; ; ; # f.♚ +f󠅟。򏗅♚; f.򏗅♚; [V7]; f.xn--45hz6953f; ; ; # f.♚ +f.xn--45hz6953f; f.򏗅♚; [V7]; f.xn--45hz6953f; ; ; # f.♚ +f󠅟。򏗅♚; f.򏗅♚; [V7]; f.xn--45hz6953f; ; ; # f.♚ +\u0B4D𑄴\u1DE9。𝟮Ⴘ𞀨񃥇; \u0B4D𑄴\u1DE9.2ⴘ𞀨񃥇; [V6, V7]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨 +\u0B4D𑄴\u1DE9。2Ⴘ𞀨񃥇; \u0B4D𑄴\u1DE9.2ⴘ𞀨񃥇; [V6, V7]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨 +\u0B4D𑄴\u1DE9。2ⴘ𞀨񃥇; \u0B4D𑄴\u1DE9.2ⴘ𞀨񃥇; [V6, V7]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨 +xn--9ic246gs21p.xn--2-nws2918ndrjr; \u0B4D𑄴\u1DE9.2ⴘ𞀨񃥇; [V6, V7]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨 +\u0B4D𑄴\u1DE9。𝟮ⴘ𞀨񃥇; \u0B4D𑄴\u1DE9.2ⴘ𞀨񃥇; [V6, V7]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨 +xn--9ic246gs21p.xn--2-k1g43076adrwq; \u0B4D𑄴\u1DE9.2Ⴘ𞀨񃥇; [V6, V7]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨 +򓠭\u200C\u200C⒈。勉𑁅; 򓠭\u200C\u200C⒈.勉𑁅; [C1, V7]; xn--0uga855aez302a.xn--4grs325b; ; xn--tsh11906f.xn--4grs325b; [V7] # ⒈.勉𑁅 +򓠭\u200C\u200C1.。勉𑁅; 򓠭\u200C\u200C1..勉𑁅; [C1, V7, X4_2]; xn--1-rgna61159u..xn--4grs325b; [C1, V7, A4_2]; xn--1-yi00h..xn--4grs325b; [V7, A4_2] # 1..勉𑁅 +xn--1-yi00h..xn--4grs325b; 򓠭1..勉𑁅; [V7, X4_2]; xn--1-yi00h..xn--4grs325b; [V7, A4_2]; ; # 1..勉𑁅 +xn--1-rgna61159u..xn--4grs325b; 򓠭\u200C\u200C1..勉𑁅; [C1, V7, X4_2]; xn--1-rgna61159u..xn--4grs325b; [C1, V7, A4_2]; ; # 1..勉𑁅 +xn--tsh11906f.xn--4grs325b; 򓠭⒈.勉𑁅; [V7]; xn--tsh11906f.xn--4grs325b; ; ; # ⒈.勉𑁅 +xn--0uga855aez302a.xn--4grs325b; 򓠭\u200C\u200C⒈.勉𑁅; [C1, V7]; xn--0uga855aez302a.xn--4grs325b; ; ; # ⒈.勉𑁅 +ᡃ.玿񫈜󕞐; ; [V7]; xn--27e.xn--7cy81125a0yq4a; ; ; # ᡃ.玿 +xn--27e.xn--7cy81125a0yq4a; ᡃ.玿񫈜󕞐; [V7]; xn--27e.xn--7cy81125a0yq4a; ; ; # ᡃ.玿 +\u200C\u200C。⒈≯𝟵; \u200C\u200C.⒈≯9; [C1, V7]; xn--0uga.xn--9-ogo37g; ; .xn--9-ogo37g; [V7, A4_2] # .⒈≯9 +\u200C\u200C。⒈>\u0338𝟵; \u200C\u200C.⒈≯9; [C1, V7]; xn--0uga.xn--9-ogo37g; ; .xn--9-ogo37g; [V7, A4_2] # .⒈≯9 +\u200C\u200C。1.≯9; \u200C\u200C.1.≯9; [C1]; xn--0uga.1.xn--9-ogo; ; .1.xn--9-ogo; [A4_2] # .1.≯9 +\u200C\u200C。1.>\u03389; \u200C\u200C.1.≯9; [C1]; xn--0uga.1.xn--9-ogo; ; .1.xn--9-ogo; [A4_2] # .1.≯9 +.1.xn--9-ogo; .1.≯9; [X4_2]; .1.xn--9-ogo; [A4_2]; ; # .1.≯9 +xn--0uga.1.xn--9-ogo; \u200C\u200C.1.≯9; [C1]; xn--0uga.1.xn--9-ogo; ; ; # .1.≯9 +.xn--9-ogo37g; .⒈≯9; [V7, X4_2]; .xn--9-ogo37g; [V7, A4_2]; ; # .⒈≯9 +xn--0uga.xn--9-ogo37g; \u200C\u200C.⒈≯9; [C1, V7]; xn--0uga.xn--9-ogo37g; ; ; # .⒈≯9 +\u115F\u1DE0򐀁.𺻆≯𐮁; \u1DE0򐀁.𺻆≯𐮁; [B1, B5, B6, V6, V7]; xn--4eg41418g.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁 +\u115F\u1DE0򐀁.𺻆>\u0338𐮁; \u1DE0򐀁.𺻆≯𐮁; [B1, B5, B6, V6, V7]; xn--4eg41418g.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁 +xn--4eg41418g.xn--hdh5192gkm6r; \u1DE0򐀁.𺻆≯𐮁; [B1, B5, B6, V6, V7]; xn--4eg41418g.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁 +xn--osd615d5659o.xn--hdh5192gkm6r; \u115F\u1DE0򐀁.𺻆≯𐮁; [B5, B6, V7]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁 +󠄫𝩤\u200D\u063E.𝩩-\u081E󑼩; 𝩤\u200D\u063E.𝩩-\u081E󑼩; [B1, C2, V6, V7]; xn--9gb723kg862a.xn----qgd52296avol4f; ; xn--9gb5080v.xn----qgd52296avol4f; [B1, V6, V7] # 𝩤ؾ.𝩩-ࠞ +xn--9gb5080v.xn----qgd52296avol4f; 𝩤\u063E.𝩩-\u081E󑼩; [B1, V6, V7]; xn--9gb5080v.xn----qgd52296avol4f; ; ; # 𝩤ؾ.𝩩-ࠞ +xn--9gb723kg862a.xn----qgd52296avol4f; 𝩤\u200D\u063E.𝩩-\u081E󑼩; [B1, C2, V6, V7]; xn--9gb723kg862a.xn----qgd52296avol4f; ; ; # 𝩤ؾ.𝩩-ࠞ +\u20DA.𑘿-; \u20DA.𑘿-; [V3, V6]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿- +\u20DA.𑘿-; ; [V3, V6]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿- +xn--w0g.xn----bd0j; \u20DA.𑘿-; [V3, V6]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿- +䮸ß.󠵟󠭎紙\u08A8; ; [B1, V7]; xn--zca5349a.xn--xyb1370div70kpzba; ; xn--ss-sf1c.xn--xyb1370div70kpzba; # 䮸ß.紙ࢨ +䮸SS.󠵟󠭎紙\u08A8; 䮸ss.󠵟󠭎紙\u08A8; [B1, V7]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ +䮸ss.󠵟󠭎紙\u08A8; ; [B1, V7]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ +䮸Ss.󠵟󠭎紙\u08A8; 䮸ss.󠵟󠭎紙\u08A8; [B1, V7]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ +xn--ss-sf1c.xn--xyb1370div70kpzba; 䮸ss.󠵟󠭎紙\u08A8; [B1, V7]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ +xn--zca5349a.xn--xyb1370div70kpzba; 䮸ß.󠵟󠭎紙\u08A8; [B1, V7]; xn--zca5349a.xn--xyb1370div70kpzba; ; ; # 䮸ß.紙ࢨ +-Ⴞ.-𝩨⅔𐦕; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕 +-Ⴞ.-𝩨2⁄3𐦕; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕 +-ⴞ.-𝩨2⁄3𐦕; ; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕 +xn----zws.xn---23-pt0a0433lk3jj; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕 +-ⴞ.-𝩨⅔𐦕; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕 +xn----w1g.xn---23-pt0a0433lk3jj; -Ⴞ.-𝩨2⁄3𐦕; [B1, V3, V7]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕 +󧈯𐹯\u0AC2。򖢨𐮁񇼖ᡂ; 󧈯𐹯\u0AC2.򖢨𐮁񇼖ᡂ; [B5, B6, V7]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ +󧈯𐹯\u0AC2。򖢨𐮁񇼖ᡂ; 󧈯𐹯\u0AC2.򖢨𐮁񇼖ᡂ; [B5, B6, V7]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ +xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; 󧈯𐹯\u0AC2.򖢨𐮁񇼖ᡂ; [B5, B6, V7]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ +\u1082-\u200D\uA8EA.ꡊ\u200D񼸳; \u1082-\u200D\uA8EA.ꡊ\u200D񼸳; [C2, V6, V7]; xn----gyg250jio7k.xn--1ug8774cri56d; ; xn----gyg3618i.xn--jc9ao4185a; [V6, V7] # ႂ-꣪.ꡊ +\u1082-\u200D\uA8EA.ꡊ\u200D񼸳; ; [C2, V6, V7]; xn----gyg250jio7k.xn--1ug8774cri56d; ; xn----gyg3618i.xn--jc9ao4185a; [V6, V7] # ႂ-꣪.ꡊ +xn----gyg3618i.xn--jc9ao4185a; \u1082-\uA8EA.ꡊ񼸳; [V6, V7]; xn----gyg3618i.xn--jc9ao4185a; ; ; # ႂ-꣪.ꡊ +xn----gyg250jio7k.xn--1ug8774cri56d; \u1082-\u200D\uA8EA.ꡊ\u200D񼸳; [C2, V6, V7]; xn----gyg250jio7k.xn--1ug8774cri56d; ; ; # ႂ-꣪.ꡊ +۱。≠\u0668; ۱.≠\u0668; [B1]; xn--emb.xn--hib334l; ; ; # ۱.≠٨ +۱。=\u0338\u0668; ۱.≠\u0668; [B1]; xn--emb.xn--hib334l; ; ; # ۱.≠٨ +xn--emb.xn--hib334l; ۱.≠\u0668; [B1]; xn--emb.xn--hib334l; ; ; # ۱.≠٨ +𑈵廊.𐠍; ; [V6]; xn--xytw701b.xn--yc9c; ; ; # 𑈵廊.𐠍 +xn--xytw701b.xn--yc9c; 𑈵廊.𐠍; [V6]; xn--xytw701b.xn--yc9c; ; ; # 𑈵廊.𐠍 +\u200D\u0356-.-Ⴐ\u0661; \u200D\u0356-.-ⴐ\u0661; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V6] # ͖-.-ⴐ١ +\u200D\u0356-.-Ⴐ\u0661; \u200D\u0356-.-ⴐ\u0661; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V6] # ͖-.-ⴐ١ +\u200D\u0356-.-ⴐ\u0661; ; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V6] # ͖-.-ⴐ١ +xn----rgb.xn----bqc2280a; \u0356-.-ⴐ\u0661; [B1, V3, V6]; xn----rgb.xn----bqc2280a; ; ; # ͖-.-ⴐ١ +xn----rgb661t.xn----bqc2280a; \u200D\u0356-.-ⴐ\u0661; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; ; # ͖-.-ⴐ١ +\u200D\u0356-.-ⴐ\u0661; \u200D\u0356-.-ⴐ\u0661; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V6] # ͖-.-ⴐ١ +xn----rgb.xn----bqc030f; \u0356-.-Ⴐ\u0661; [B1, V3, V6, V7]; xn----rgb.xn----bqc030f; ; ; # ͖-.-Ⴐ١ +xn----rgb661t.xn----bqc030f; \u200D\u0356-.-Ⴐ\u0661; [B1, C2, V3, V7]; xn----rgb661t.xn----bqc030f; ; ; # ͖-.-Ⴐ١ +\u063A\u0661挏󾯐.-; ; [B1, B2, B3, V3, V7]; xn--5gb2f4205aqi47p.-; ; ; # غ١挏.- +xn--5gb2f4205aqi47p.-; \u063A\u0661挏󾯐.-; [B1, B2, B3, V3, V7]; xn--5gb2f4205aqi47p.-; ; ; # غ١挏.- +\u06EF。𐹧𞤽; \u06EF.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽 +\u06EF。𐹧𞤽; \u06EF.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽 +\u06EF。𐹧𞤛; \u06EF.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽 +xn--cmb.xn--fo0dy848a; \u06EF.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽 +\u06EF。𐹧𞤛; \u06EF.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽 +Ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +Ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +Ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +Ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +ⴞ𶛀𛗻.ᢗ릫; ; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +xn--mlj0486jgl2j.xn--hbf6853f; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫 +xn--2nd8876sgl2j.xn--hbf6853f; Ⴞ𶛀𛗻.ᢗ릫; [V7]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫 +󠎃󗭞\u06B7𐹷。≯\u200C\u1DFE; 󠎃󗭞\u06B7𐹷.≯\u200C\u1DFE; [B1, C1, V7]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, V7] # ڷ𐹷.≯᷾ +󠎃󗭞\u06B7𐹷。>\u0338\u200C\u1DFE; 󠎃󗭞\u06B7𐹷.≯\u200C\u1DFE; [B1, C1, V7]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, V7] # ڷ𐹷.≯᷾ +󠎃󗭞\u06B7𐹷。≯\u200C\u1DFE; 󠎃󗭞\u06B7𐹷.≯\u200C\u1DFE; [B1, C1, V7]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, V7] # ڷ𐹷.≯᷾ +󠎃󗭞\u06B7𐹷。>\u0338\u200C\u1DFE; 󠎃󗭞\u06B7𐹷.≯\u200C\u1DFE; [B1, C1, V7]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, V7] # ڷ𐹷.≯᷾ +xn--qkb4516kbi06fg2id.xn--zfg31q; 󠎃󗭞\u06B7𐹷.≯\u1DFE; [B1, V7]; xn--qkb4516kbi06fg2id.xn--zfg31q; ; ; # ڷ𐹷.≯᷾ +xn--qkb4516kbi06fg2id.xn--zfg59fm0c; 󠎃󗭞\u06B7𐹷.≯\u200C\u1DFE; [B1, C1, V7]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; ; # ڷ𐹷.≯᷾ +ᛎ󠅍󠐕\u200D。𐹾𐹪𐻝-; ᛎ󠐕\u200D.𐹾𐹪𐻝-; [B1, B6, C2, V3, V7]; xn--fxe848bq3411a.xn----q26i2bvu; ; xn--fxe63563p.xn----q26i2bvu; [B1, B6, V3, V7] # ᛎ.𐹾𐹪- +ᛎ󠅍󠐕\u200D。𐹾𐹪𐻝-; ᛎ󠐕\u200D.𐹾𐹪𐻝-; [B1, B6, C2, V3, V7]; xn--fxe848bq3411a.xn----q26i2bvu; ; xn--fxe63563p.xn----q26i2bvu; [B1, B6, V3, V7] # ᛎ.𐹾𐹪- +xn--fxe63563p.xn----q26i2bvu; ᛎ󠐕.𐹾𐹪𐻝-; [B1, B6, V3, V7]; xn--fxe63563p.xn----q26i2bvu; ; ; # ᛎ.𐹾𐹪- +xn--fxe848bq3411a.xn----q26i2bvu; ᛎ󠐕\u200D.𐹾𐹪𐻝-; [B1, B6, C2, V3, V7]; xn--fxe848bq3411a.xn----q26i2bvu; ; ; # ᛎ.𐹾𐹪- +𐹶.𐫂; ; [B1]; xn--uo0d.xn--rw9c; ; ; # 𐹶.𐫂 +xn--uo0d.xn--rw9c; 𐹶.𐫂; [B1]; xn--uo0d.xn--rw9c; ; ; # 𐹶.𐫂 +ß\u200D\u103A。⒈; ß\u200D\u103A.⒈; [C2, V7]; xn--zca679eh2l.xn--tsh; ; xn--ss-f4j.xn--tsh; [V7] # ß်.⒈ +ß\u200D\u103A。1.; ß\u200D\u103A.1.; [C2]; xn--zca679eh2l.1.; [C2, A4_2]; xn--ss-f4j.1.; [A4_2] # ß်.1. +SS\u200D\u103A。1.; ss\u200D\u103A.1.; [C2]; xn--ss-f4j585j.1.; [C2, A4_2]; xn--ss-f4j.1.; [A4_2] # ss်.1. +ss\u200D\u103A。1.; ss\u200D\u103A.1.; [C2]; xn--ss-f4j585j.1.; [C2, A4_2]; xn--ss-f4j.1.; [A4_2] # ss်.1. +Ss\u200D\u103A。1.; ss\u200D\u103A.1.; [C2]; xn--ss-f4j585j.1.; [C2, A4_2]; xn--ss-f4j.1.; [A4_2] # ss်.1. +xn--ss-f4j.b.; ss\u103A.b.; ; xn--ss-f4j.b.; [A4_2]; ; # ss်.b. +ss\u103A.b.; ; ; xn--ss-f4j.b.; [A4_2]; ; # ss်.b. +SS\u103A.B.; ss\u103A.b.; ; xn--ss-f4j.b.; [A4_2]; ; # ss်.b. +Ss\u103A.b.; ss\u103A.b.; ; xn--ss-f4j.b.; [A4_2]; ; # ss်.b. +xn--ss-f4j585j.b.; ss\u200D\u103A.b.; [C2]; xn--ss-f4j585j.b.; [C2, A4_2]; ; # ss်.b. +xn--zca679eh2l.b.; ß\u200D\u103A.b.; [C2]; xn--zca679eh2l.b.; [C2, A4_2]; ; # ß်.b. +SS\u200D\u103A。⒈; ss\u200D\u103A.⒈; [C2, V7]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [V7] # ss်.⒈ +ss\u200D\u103A。⒈; ss\u200D\u103A.⒈; [C2, V7]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [V7] # ss်.⒈ +Ss\u200D\u103A。⒈; ss\u200D\u103A.⒈; [C2, V7]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [V7] # ss်.⒈ +xn--ss-f4j.xn--tsh; ss\u103A.⒈; [V7]; xn--ss-f4j.xn--tsh; ; ; # ss်.⒈ +xn--ss-f4j585j.xn--tsh; ss\u200D\u103A.⒈; [C2, V7]; xn--ss-f4j585j.xn--tsh; ; ; # ss်.⒈ +xn--zca679eh2l.xn--tsh; ß\u200D\u103A.⒈; [C2, V7]; xn--zca679eh2l.xn--tsh; ; ; # ß်.⒈ +SS\u103A.b.; ss\u103A.b.; ; xn--ss-f4j.b.; [A4_2]; ; # ss်.b. +\u0B4D\u200C𙶵𞻘。\u200D; \u0B4D\u200C𙶵𞻘.\u200D; [B1, C2, V6, V7]; xn--9ic637hz82z32jc.xn--1ug; ; xn--9ic6417rn4xb.; [B1, V6, V7, A4_2] # ୍. +xn--9ic6417rn4xb.; \u0B4D𙶵𞻘.; [B1, V6, V7]; xn--9ic6417rn4xb.; [B1, V6, V7, A4_2]; ; # ୍. +xn--9ic637hz82z32jc.xn--1ug; \u0B4D\u200C𙶵𞻘.\u200D; [B1, C2, V6, V7]; xn--9ic637hz82z32jc.xn--1ug; ; ; # ୍. +𐮅。\u06BC🁕; 𐮅.\u06BC🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕 +𐮅。\u06BC🁕; 𐮅.\u06BC🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕 +xn--c29c.xn--vkb8871w; 𐮅.\u06BC🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕 +\u0620\u17D2。𐫔󠀧\u200C𑈵; \u0620\u17D2.𐫔󠀧\u200C𑈵; [B2, B3, C1, V7]; xn--fgb471g.xn--0ug9853g7verp838a; ; xn--fgb471g.xn--9w9c29jw3931a; [B2, B3, V7] # ؠ្.𐫔𑈵 +xn--fgb471g.xn--9w9c29jw3931a; \u0620\u17D2.𐫔󠀧𑈵; [B2, B3, V7]; xn--fgb471g.xn--9w9c29jw3931a; ; ; # ؠ្.𐫔𑈵 +xn--fgb471g.xn--0ug9853g7verp838a; \u0620\u17D2.𐫔󠀧\u200C𑈵; [B2, B3, C1, V7]; xn--fgb471g.xn--0ug9853g7verp838a; ; ; # ؠ្.𐫔𑈵 +񋉕.𞣕𞤊; 񋉕.𞣕𞤬; [B1, V6, V7]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬 +񋉕.𞣕𞤬; ; [B1, V6, V7]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬 +xn--tf5w.xn--2b6hof; 񋉕.𞣕𞤬; [B1, V6, V7]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬 +\u06CC𐨿.ß\u0F84𑍬; \u06CC𐨿.ß\u0F84𑍬; ; xn--clb2593k.xn--zca216edt0r; ; xn--clb2593k.xn--ss-toj6092t; # ی𐨿.ß྄𑍬 +\u06CC𐨿.ß\u0F84𑍬; ; ; xn--clb2593k.xn--zca216edt0r; ; xn--clb2593k.xn--ss-toj6092t; # ی𐨿.ß྄𑍬 +\u06CC𐨿.SS\u0F84𑍬; \u06CC𐨿.ss\u0F84𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +\u06CC𐨿.ss\u0F84𑍬; ; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +xn--clb2593k.xn--ss-toj6092t; \u06CC𐨿.ss\u0F84𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +xn--clb2593k.xn--zca216edt0r; \u06CC𐨿.ß\u0F84𑍬; ; xn--clb2593k.xn--zca216edt0r; ; ; # ی𐨿.ß྄𑍬 +\u06CC𐨿.SS\u0F84𑍬; \u06CC𐨿.ss\u0F84𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +\u06CC𐨿.ss\u0F84𑍬; \u06CC𐨿.ss\u0F84𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +\u06CC𐨿.Ss\u0F84𑍬; \u06CC𐨿.ss\u0F84𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +\u06CC𐨿.Ss\u0F84𑍬; \u06CC𐨿.ss\u0F84𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬 +𝟠≮\u200C。󠅱\u17B4; 8≮\u200C.; [C1]; xn--8-sgn10i.; [C1, A4_2]; xn--8-ngo.; [A4_2] # 8≮. +𝟠<\u0338\u200C。󠅱\u17B4; 8≮\u200C.; [C1]; xn--8-sgn10i.; [C1, A4_2]; xn--8-ngo.; [A4_2] # 8≮. +8≮\u200C。󠅱\u17B4; 8≮\u200C.; [C1]; xn--8-sgn10i.; [C1, A4_2]; xn--8-ngo.; [A4_2] # 8≮. +8<\u0338\u200C。󠅱\u17B4; 8≮\u200C.; [C1]; xn--8-sgn10i.; [C1, A4_2]; xn--8-ngo.; [A4_2] # 8≮. +xn--8-ngo.; 8≮.; ; xn--8-ngo.; [A4_2]; ; # 8≮. +8≮.; ; ; xn--8-ngo.; [A4_2]; ; # 8≮. +8<\u0338.; 8≮.; ; xn--8-ngo.; [A4_2]; ; # 8≮. +xn--8-sgn10i.; 8≮\u200C.; [C1]; xn--8-sgn10i.; [C1, A4_2]; ; # 8≮. +xn--8-ngo.xn--z3e; 8≮.\u17B4; [V6, V7]; xn--8-ngo.xn--z3e; ; ; # 8≮. +xn--8-sgn10i.xn--z3e; 8≮\u200C.\u17B4; [C1, V6, V7]; xn--8-sgn10i.xn--z3e; ; ; # 8≮. +ᢕ≯︒񄂯.Ⴀ; ᢕ≯︒񄂯.ⴀ; [V7]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ +ᢕ>\u0338︒񄂯.Ⴀ; ᢕ≯︒񄂯.ⴀ; [V7]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ +ᢕ≯。񄂯.Ⴀ; ᢕ≯.񄂯.ⴀ; [V7]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ +ᢕ>\u0338。񄂯.Ⴀ; ᢕ≯.񄂯.ⴀ; [V7]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ +ᢕ>\u0338。񄂯.ⴀ; ᢕ≯.񄂯.ⴀ; [V7]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ +ᢕ≯。񄂯.ⴀ; ᢕ≯.񄂯.ⴀ; [V7]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ +xn--fbf851c.xn--ko1u.xn--rkj; ᢕ≯.񄂯.ⴀ; [V7]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ +ᢕ>\u0338︒񄂯.ⴀ; ᢕ≯︒񄂯.ⴀ; [V7]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ +ᢕ≯︒񄂯.ⴀ; ᢕ≯︒񄂯.ⴀ; [V7]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ +xn--fbf851cq98poxw1a.xn--rkj; ᢕ≯︒񄂯.ⴀ; [V7]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ +xn--fbf851c.xn--ko1u.xn--7md; ᢕ≯.񄂯.Ⴀ; [V7]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ +xn--fbf851cq98poxw1a.xn--7md; ᢕ≯︒񄂯.Ⴀ; [V7]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ +\u0F9F.-\u082A; \u0F9F.-\u082A; [V3, V6]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ +\u0F9F.-\u082A; ; [V3, V6]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ +xn--vfd.xn----fhd; \u0F9F.-\u082A; [V3, V6]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ +ᵬ󠆠.핒⒒⒈􈄦; ᵬ.핒⒒⒈􈄦; [V7]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈ +ᵬ󠆠.핒⒒⒈􈄦; ᵬ.핒⒒⒈􈄦; [V7]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈ +ᵬ󠆠.핒11.1.􈄦; ᵬ.핒11.1.􈄦; [V7]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1. +ᵬ󠆠.핒11.1.􈄦; ᵬ.핒11.1.􈄦; [V7]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1. +xn--tbg.xn--11-5o7k.1.xn--k469f; ᵬ.핒11.1.􈄦; [V7]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1. +xn--tbg.xn--tsht7586kyts9l; ᵬ.핒⒒⒈􈄦; [V7]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈ +ς𑓂𐋢.\u0668; ς𑓂𐋢.\u0668; [B1]; xn--3xa8371khhl.xn--hib; ; xn--4xa6371khhl.xn--hib; # ς𑓂𐋢.٨ +ς𑓂𐋢.\u0668; ; [B1]; xn--3xa8371khhl.xn--hib; ; xn--4xa6371khhl.xn--hib; # ς𑓂𐋢.٨ +Σ𑓂𐋢.\u0668; σ𑓂𐋢.\u0668; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨ +σ𑓂𐋢.\u0668; ; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨ +xn--4xa6371khhl.xn--hib; σ𑓂𐋢.\u0668; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨ +xn--3xa8371khhl.xn--hib; ς𑓂𐋢.\u0668; [B1]; xn--3xa8371khhl.xn--hib; ; ; # ς𑓂𐋢.٨ +Σ𑓂𐋢.\u0668; σ𑓂𐋢.\u0668; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨ +σ𑓂𐋢.\u0668; σ𑓂𐋢.\u0668; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨ +\uA953\u200C𐋻\u200D.\u2DF8𞿄𐹲; ; [B1, B6, C2, V6, V7]; xn--0ugc8356he76c.xn--urju692efj0f; ; xn--3j9a531o.xn--urju692efj0f; [B1, V6, V7] # ꥓𐋻.ⷸ𐹲 +xn--3j9a531o.xn--urju692efj0f; \uA953𐋻.\u2DF8𞿄𐹲; [B1, V6, V7]; xn--3j9a531o.xn--urju692efj0f; ; ; # ꥓𐋻.ⷸ𐹲 +xn--0ugc8356he76c.xn--urju692efj0f; \uA953\u200C𐋻\u200D.\u2DF8𞿄𐹲; [B1, B6, C2, V6, V7]; xn--0ugc8356he76c.xn--urju692efj0f; ; ; # ꥓𐋻.ⷸ𐹲 +⊼。񪧖\u0695; ⊼.񪧖\u0695; [B1, B5, B6, V7]; xn--ofh.xn--rjb13118f; ; ; # ⊼.ڕ +xn--ofh.xn--rjb13118f; ⊼.񪧖\u0695; [B1, B5, B6, V7]; xn--ofh.xn--rjb13118f; ; ; # ⊼.ڕ +𐯬񖋔。󜳥; 𐯬񖋔.󜳥; [B2, B3, V7]; xn--949co370q.xn--7g25e; ; ; # . +xn--949co370q.xn--7g25e; 𐯬񖋔.󜳥; [B2, B3, V7]; xn--949co370q.xn--7g25e; ; ; # . +\u0601𑍧\u07DD。ς򬍘🀞\u17B5; \u0601𑍧\u07DD.ς򬍘🀞; [B1, B6, V7]; xn--jfb66gt010c.xn--3xa2023w4nq4c; ; xn--jfb66gt010c.xn--4xa0023w4nq4c; # 𑍧ߝ.ς🀞 +\u0601𑍧\u07DD。Σ򬍘🀞\u17B5; \u0601𑍧\u07DD.σ򬍘🀞; [B1, B6, V7]; xn--jfb66gt010c.xn--4xa0023w4nq4c; ; ; # 𑍧ߝ.σ🀞 +\u0601𑍧\u07DD。σ򬍘🀞\u17B5; \u0601𑍧\u07DD.σ򬍘🀞; [B1, B6, V7]; xn--jfb66gt010c.xn--4xa0023w4nq4c; ; ; # 𑍧ߝ.σ🀞 +xn--jfb66gt010c.xn--4xa0023w4nq4c; \u0601𑍧\u07DD.σ򬍘🀞; [B1, B6, V7]; xn--jfb66gt010c.xn--4xa0023w4nq4c; ; ; # 𑍧ߝ.σ🀞 +xn--jfb66gt010c.xn--3xa2023w4nq4c; \u0601𑍧\u07DD.ς򬍘🀞; [B1, B6, V7]; xn--jfb66gt010c.xn--3xa2023w4nq4c; ; ; # 𑍧ߝ.ς🀞 +xn--jfb66gt010c.xn--4xa623h9p95ars26d; \u0601𑍧\u07DD.σ򬍘🀞\u17B5; [B1, B6, V7]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞 +xn--jfb66gt010c.xn--3xa823h9p95ars26d; \u0601𑍧\u07DD.ς򬍘🀞\u17B5; [B1, B6, V7]; xn--jfb66gt010c.xn--3xa823h9p95ars26d; ; ; # 𑍧ߝ.ς🀞 +-𐳲\u0646󠺐。\uABED𝟥; -𐳲\u0646󠺐.\uABED3; [B1, V3, V6, V7]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3 +-𐳲\u0646󠺐。\uABED3; -𐳲\u0646󠺐.\uABED3; [B1, V3, V6, V7]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3 +-𐲲\u0646󠺐。\uABED3; -𐳲\u0646󠺐.\uABED3; [B1, V3, V6, V7]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3 +xn----roc5482rek10i.xn--3-zw5e; -𐳲\u0646󠺐.\uABED3; [B1, V3, V6, V7]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3 +-𐲲\u0646󠺐。\uABED𝟥; -𐳲\u0646󠺐.\uABED3; [B1, V3, V6, V7]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3 +\u200C󠴦。񲨕≮𐦜; \u200C󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V7]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, V7] # .≮𐦜 +\u200C󠴦。񲨕<\u0338𐦜; \u200C󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V7]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, V7] # .≮𐦜 +\u200C󠴦。񲨕≮𐦜; \u200C󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V7]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, V7] # .≮𐦜 +\u200C󠴦。񲨕<\u0338𐦜; \u200C󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V7]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, V7] # .≮𐦜 +xn--6v56e.xn--gdhz712gzlr6b; 󠴦.񲨕≮𐦜; [B1, B5, B6, V7]; xn--6v56e.xn--gdhz712gzlr6b; ; ; # .≮𐦜 +xn--0ug22251l.xn--gdhz712gzlr6b; \u200C󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V7]; xn--0ug22251l.xn--gdhz712gzlr6b; ; ; # .≮𐦜 +⒈✌򟬟.𝟡񠱣; ⒈✌򟬟.9񠱣; [V7]; xn--tsh24g49550b.xn--9-o706d; ; ; # ⒈✌.9 +1.✌򟬟.9񠱣; ; [V7]; 1.xn--7bi44996f.xn--9-o706d; ; ; # 1.✌.9 +1.xn--7bi44996f.xn--9-o706d; 1.✌򟬟.9񠱣; [V7]; 1.xn--7bi44996f.xn--9-o706d; ; ; # 1.✌.9 +xn--tsh24g49550b.xn--9-o706d; ⒈✌򟬟.9񠱣; [V7]; xn--tsh24g49550b.xn--9-o706d; ; ; # ⒈✌.9 +𑆾𞤬𐮆.\u0666\u1DD4; ; [B1, V6]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ +𑆾𞤊𐮆.\u0666\u1DD4; 𑆾𞤬𐮆.\u0666\u1DD4; [B1, V6]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ +xn--d29c79hf98r.xn--fib011j; 𑆾𞤬𐮆.\u0666\u1DD4; [B1, V6]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ +ς.\uA9C0\uA8C4; ς.\uA9C0\uA8C4; [V6]; xn--3xa.xn--0f9ars; ; xn--4xa.xn--0f9ars; # ς.꧀꣄ +ς.\uA9C0\uA8C4; ; [V6]; xn--3xa.xn--0f9ars; ; xn--4xa.xn--0f9ars; # ς.꧀꣄ +Σ.\uA9C0\uA8C4; σ.\uA9C0\uA8C4; [V6]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄ +σ.\uA9C0\uA8C4; ; [V6]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄ +xn--4xa.xn--0f9ars; σ.\uA9C0\uA8C4; [V6]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄ +xn--3xa.xn--0f9ars; ς.\uA9C0\uA8C4; [V6]; xn--3xa.xn--0f9ars; ; ; # ς.꧀꣄ +Σ.\uA9C0\uA8C4; σ.\uA9C0\uA8C4; [V6]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄ +σ.\uA9C0\uA8C4; σ.\uA9C0\uA8C4; [V6]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄ +𑰶\u200C≯𐳐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +𑰶\u200C>\u0338𐳐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +𑰶\u200C≯𐳐.\u085B; ; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +𑰶\u200C>\u0338𐳐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +𑰶\u200C>\u0338𐲐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +𑰶\u200C≯𐲐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +xn--hdhz343g3wj.xn--qwb; 𑰶≯𐳐.\u085B; [B1, V6]; xn--hdhz343g3wj.xn--qwb; ; ; # 𑰶≯𐳐.࡛ +xn--0ug06g7697ap4ma.xn--qwb; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; ; # 𑰶≯𐳐.࡛ +𑰶\u200C>\u0338𐲐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +𑰶\u200C≯𐲐.\u085B; 𑰶\u200C≯𐳐.\u085B; [B1, C1, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, V6] # 𑰶≯𐳐.࡛ +羚。≯; 羚.≯; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +羚。>\u0338; 羚.≯; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +羚。≯; 羚.≯; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +羚。>\u0338; 羚.≯; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +xn--xt0a.xn--hdh; 羚.≯; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +羚.≯; ; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +羚.>\u0338; 羚.≯; ; xn--xt0a.xn--hdh; ; ; # 羚.≯ +𑓂\u1759.\u08A8; 𑓂\u1759.\u08A8; [B1, V6, V7]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ +𑓂\u1759.\u08A8; ; [B1, V6, V7]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ +xn--e1e9580k.xn--xyb; 𑓂\u1759.\u08A8; [B1, V6, V7]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ +󨣿󠇀\u200D。\u0663ҠჀ𝟑; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, V7] # .٣ҡⴠ3 +󨣿󠇀\u200D。\u0663ҠჀ3; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, V7] # .٣ҡⴠ3 +󨣿󠇀\u200D。\u0663ҡⴠ3; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, V7] # .٣ҡⴠ3 +xn--1r19e.xn--3-ozb36ko13f; 󨣿.\u0663ҡⴠ3; [B1, V7]; xn--1r19e.xn--3-ozb36ko13f; ; ; # .٣ҡⴠ3 +xn--1ug89936l.xn--3-ozb36ko13f; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; ; # .٣ҡⴠ3 +󨣿󠇀\u200D。\u0663ҡⴠ𝟑; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, V7] # .٣ҡⴠ3 +xn--1r19e.xn--3-ozb36kixu; 󨣿.\u0663ҡჀ3; [B1, V7]; xn--1r19e.xn--3-ozb36kixu; ; ; # .٣ҡჀ3 +xn--1ug89936l.xn--3-ozb36kixu; 󨣿\u200D.\u0663ҡჀ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36kixu; ; ; # .٣ҡჀ3 +󨣿󠇀\u200D。\u0663Ҡⴠ3; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, V7] # .٣ҡⴠ3 +󨣿󠇀\u200D。\u0663Ҡⴠ𝟑; 󨣿\u200D.\u0663ҡⴠ3; [B1, B6, C2, V7]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, V7] # .٣ҡⴠ3 +ᡷ。𐹢\u08E0; ᡷ.𐹢\u08E0; [B1]; xn--k9e.xn--j0b5005k; ; ; # ᡷ.𐹢࣠ +xn--k9e.xn--j0b5005k; ᡷ.𐹢\u08E0; [B1]; xn--k9e.xn--j0b5005k; ; ; # ᡷ.𐹢࣠ +򕮇\u1BF3。\u0666񗜼\u17D2ß; 򕮇\u1BF3.\u0666񗜼\u17D2ß; [B1, V7]; xn--1zf58212h.xn--zca34zk4qx711k; ; xn--1zf58212h.xn--ss-pyd459o3258m; # ᯳.٦្ß +򕮇\u1BF3。\u0666񗜼\u17D2ß; 򕮇\u1BF3.\u0666񗜼\u17D2ß; [B1, V7]; xn--1zf58212h.xn--zca34zk4qx711k; ; xn--1zf58212h.xn--ss-pyd459o3258m; # ᯳.٦្ß +򕮇\u1BF3。\u0666񗜼\u17D2SS; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +򕮇\u1BF3。\u0666񗜼\u17D2ss; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +򕮇\u1BF3。\u0666񗜼\u17D2Ss; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +xn--1zf58212h.xn--ss-pyd459o3258m; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +xn--1zf58212h.xn--zca34zk4qx711k; 򕮇\u1BF3.\u0666񗜼\u17D2ß; [B1, V7]; xn--1zf58212h.xn--zca34zk4qx711k; ; ; # ᯳.٦្ß +򕮇\u1BF3。\u0666񗜼\u17D2SS; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +򕮇\u1BF3。\u0666񗜼\u17D2ss; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +򕮇\u1BF3。\u0666񗜼\u17D2Ss; 򕮇\u1BF3.\u0666񗜼\u17D2ss; [B1, V7]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss +\u0664򤽎𑲛.󠔢︒≠; ; [B1, V7]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠ +\u0664򤽎𑲛.󠔢︒=\u0338; \u0664򤽎𑲛.󠔢︒≠; [B1, V7]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠ +\u0664򤽎𑲛.󠔢。≠; \u0664򤽎𑲛.󠔢.≠; [B1, V7]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠ +\u0664򤽎𑲛.󠔢。=\u0338; \u0664򤽎𑲛.󠔢.≠; [B1, V7]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠ +xn--dib0653l2i02d.xn--k736e.xn--1ch; \u0664򤽎𑲛.󠔢.≠; [B1, V7]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠ +xn--dib0653l2i02d.xn--1ch7467f14u4g; \u0664򤽎𑲛.󠔢︒≠; [B1, V7]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠ +➆񷧕ỗ⒈.򑬒񡘮\u085B𝟫; ➆񷧕ỗ⒈.򑬒񡘮\u085B9; [V7]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9 +➆񷧕o\u0302\u0303⒈.򑬒񡘮\u085B𝟫; ➆񷧕ỗ⒈.򑬒񡘮\u085B9; [V7]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9 +➆񷧕ỗ1..򑬒񡘮\u085B9; ; [V7, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V7, A4_2]; ; # ➆ỗ1..࡛9 +➆񷧕o\u0302\u03031..򑬒񡘮\u085B9; ➆񷧕ỗ1..򑬒񡘮\u085B9; [V7, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V7, A4_2]; ; # ➆ỗ1..࡛9 +➆񷧕O\u0302\u03031..򑬒񡘮\u085B9; ➆񷧕ỗ1..򑬒񡘮\u085B9; [V7, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V7, A4_2]; ; # ➆ỗ1..࡛9 +➆񷧕Ỗ1..򑬒񡘮\u085B9; ➆񷧕ỗ1..򑬒񡘮\u085B9; [V7, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V7, A4_2]; ; # ➆ỗ1..࡛9 +xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; ➆񷧕ỗ1..򑬒񡘮\u085B9; [V7, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V7, A4_2]; ; # ➆ỗ1..࡛9 +➆񷧕O\u0302\u0303⒈.򑬒񡘮\u085B𝟫; ➆񷧕ỗ⒈.򑬒񡘮\u085B9; [V7]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9 +➆񷧕Ỗ⒈.򑬒񡘮\u085B𝟫; ➆񷧕ỗ⒈.򑬒񡘮\u085B9; [V7]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9 +xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ➆񷧕ỗ⒈.򑬒񡘮\u085B9; [V7]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9 +\u200D。𞤘; \u200D.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺 +\u200D。𞤘; \u200D.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺 +\u200D。𞤺; \u200D.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺 +.xn--ye6h; .𞤺; [X4_2]; .xn--ye6h; [A4_2]; ; # .𞤺 +xn--1ug.xn--ye6h; \u200D.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; ; # .𞤺 +\u200D。𞤺; \u200D.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺 +xn--ye6h; 𞤺; ; xn--ye6h; ; ; # 𞤺 +𞤺; ; ; xn--ye6h; ; ; # 𞤺 +𞤘; 𞤺; ; xn--ye6h; ; ; # 𞤺 +\u0829\u0724.ᢣ; ; [B1, V6]; xn--unb53c.xn--tbf; ; ; # ࠩܤ.ᢣ +xn--unb53c.xn--tbf; \u0829\u0724.ᢣ; [B1, V6]; xn--unb53c.xn--tbf; ; ; # ࠩܤ.ᢣ +\u073C\u200C-。𓐾ß; \u073C\u200C-.𓐾ß; [C1, V3, V6, V7]; xn----s2c071q.xn--zca7848m; ; xn----s2c.xn--ss-066q; [V3, V6, V7] # ܼ-.ß +\u073C\u200C-。𓐾SS; \u073C\u200C-.𓐾ss; [C1, V3, V6, V7]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [V3, V6, V7] # ܼ-.ss +\u073C\u200C-。𓐾ss; \u073C\u200C-.𓐾ss; [C1, V3, V6, V7]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [V3, V6, V7] # ܼ-.ss +\u073C\u200C-。𓐾Ss; \u073C\u200C-.𓐾ss; [C1, V3, V6, V7]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [V3, V6, V7] # ܼ-.ss +xn----s2c.xn--ss-066q; \u073C-.𓐾ss; [V3, V6, V7]; xn----s2c.xn--ss-066q; ; ; # ܼ-.ss +xn----s2c071q.xn--ss-066q; \u073C\u200C-.𓐾ss; [C1, V3, V6, V7]; xn----s2c071q.xn--ss-066q; ; ; # ܼ-.ss +xn----s2c071q.xn--zca7848m; \u073C\u200C-.𓐾ß; [C1, V3, V6, V7]; xn----s2c071q.xn--zca7848m; ; ; # ܼ-.ß +\u200Cς🃡⒗.\u0CC6仧\u0756; ; [B1, B5, B6, C1, V6, V7]; xn--3xa795lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, V6, V7] # ς🃡⒗.ೆ仧ݖ +\u200Cς🃡16..\u0CC6仧\u0756; ; [B1, B5, B6, C1, V6, X4_2]; xn--16-rbc1800avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V6, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V6, A4_2] # ς🃡16..ೆ仧ݖ +\u200CΣ🃡16..\u0CC6仧\u0756; \u200Cσ🃡16..\u0CC6仧\u0756; [B1, B5, B6, C1, V6, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V6, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V6, A4_2] # σ🃡16..ೆ仧ݖ +\u200Cσ🃡16..\u0CC6仧\u0756; ; [B1, B5, B6, C1, V6, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V6, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V6, A4_2] # σ🃡16..ೆ仧ݖ +xn--16-ubc66061c..xn--9ob79ycx2e; σ🃡16..\u0CC6仧\u0756; [B5, B6, V6, X4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V6, A4_2]; ; # σ🃡16..ೆ仧ݖ +xn--16-ubc7700avy99b..xn--9ob79ycx2e; \u200Cσ🃡16..\u0CC6仧\u0756; [B1, B5, B6, C1, V6, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V6, A4_2]; ; # σ🃡16..ೆ仧ݖ +xn--16-rbc1800avy99b..xn--9ob79ycx2e; \u200Cς🃡16..\u0CC6仧\u0756; [B1, B5, B6, C1, V6, X4_2]; xn--16-rbc1800avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V6, A4_2]; ; # ς🃡16..ೆ仧ݖ +\u200CΣ🃡⒗.\u0CC6仧\u0756; \u200Cσ🃡⒗.\u0CC6仧\u0756; [B1, B5, B6, C1, V6, V7]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, V6, V7] # σ🃡⒗.ೆ仧ݖ +\u200Cσ🃡⒗.\u0CC6仧\u0756; ; [B1, B5, B6, C1, V6, V7]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, V6, V7] # σ🃡⒗.ೆ仧ݖ +xn--4xa229nbu92a.xn--9ob79ycx2e; σ🃡⒗.\u0CC6仧\u0756; [B5, B6, V6, V7]; xn--4xa229nbu92a.xn--9ob79ycx2e; ; ; # σ🃡⒗.ೆ仧ݖ +xn--4xa595lz9czy52d.xn--9ob79ycx2e; \u200Cσ🃡⒗.\u0CC6仧\u0756; [B1, B5, B6, C1, V6, V7]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; ; # σ🃡⒗.ೆ仧ݖ +xn--3xa795lz9czy52d.xn--9ob79ycx2e; \u200Cς🃡⒗.\u0CC6仧\u0756; [B1, B5, B6, C1, V6, V7]; xn--3xa795lz9czy52d.xn--9ob79ycx2e; ; ; # ς🃡⒗.ೆ仧ݖ +-.𞸚; -.\u0638; [B1, V3]; -.xn--3gb; ; ; # -.ظ +-.\u0638; ; [B1, V3]; -.xn--3gb; ; ; # -.ظ +-.xn--3gb; -.\u0638; [B1, V3]; -.xn--3gb; ; ; # -.ظ +򏛓\u0683.\u0F7E\u0634; ; [B1, B5, B6, V6, V7]; xn--8ib92728i.xn--zgb968b; ; ; # ڃ.ཾش +xn--8ib92728i.xn--zgb968b; 򏛓\u0683.\u0F7E\u0634; [B1, B5, B6, V6, V7]; xn--8ib92728i.xn--zgb968b; ; ; # ڃ.ཾش +\u0FE6\u0843񽶬.𐮏; ; [B5, V7]; xn--1vb320b5m04p.xn--m29c; ; ; # ࡃ.𐮏 +xn--1vb320b5m04p.xn--m29c; \u0FE6\u0843񽶬.𐮏; [B5, V7]; xn--1vb320b5m04p.xn--m29c; ; ; # ࡃ.𐮏 +2񎨠\u07CBß。ᠽ; 2񎨠\u07CBß.ᠽ; [B1, V7]; xn--2-qfa924cez02l.xn--w7e; ; xn--2ss-odg83511n.xn--w7e; # 2ߋß.ᠽ +2񎨠\u07CBSS。ᠽ; 2񎨠\u07CBss.ᠽ; [B1, V7]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ +2񎨠\u07CBss。ᠽ; 2񎨠\u07CBss.ᠽ; [B1, V7]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ +xn--2ss-odg83511n.xn--w7e; 2񎨠\u07CBss.ᠽ; [B1, V7]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ +xn--2-qfa924cez02l.xn--w7e; 2񎨠\u07CBß.ᠽ; [B1, V7]; xn--2-qfa924cez02l.xn--w7e; ; ; # 2ߋß.ᠽ +2񎨠\u07CBSs。ᠽ; 2񎨠\u07CBss.ᠽ; [B1, V7]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ +㸳\u07CA≮.\u06CEß-\u200D; 㸳\u07CA≮.\u06CEß-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێß- +㸳\u07CA<\u0338.\u06CEß-\u200D; 㸳\u07CA≮.\u06CEß-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێß- +㸳\u07CA≮.\u06CEß-\u200D; ; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێß- +㸳\u07CA<\u0338.\u06CEß-\u200D; 㸳\u07CA≮.\u06CEß-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێß- +㸳\u07CA<\u0338.\u06CESS-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA≮.\u06CESS-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA≮.\u06CEss-\u200D; ; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA<\u0338.\u06CEss-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +xn--lsb457kkut.xn--ss--qjf; 㸳\u07CA≮.\u06CEss-; [B2, B3, B5, B6, V3]; xn--lsb457kkut.xn--ss--qjf; ; ; # 㸳ߊ≮.ێss- +xn--lsb457kkut.xn--ss--qjf2343a; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; ; # 㸳ߊ≮.ێss- +xn--lsb457kkut.xn----pfa076bys4a; 㸳\u07CA≮.\u06CEß-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn----pfa076bys4a; ; ; # 㸳ߊ≮.ێß- +㸳\u07CA<\u0338.\u06CESS-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA≮.\u06CESS-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA≮.\u06CEss-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA<\u0338.\u06CEss-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA<\u0338.\u06CESs-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA≮.\u06CESs-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA<\u0338.\u06CESs-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +㸳\u07CA≮.\u06CESs-\u200D; 㸳\u07CA≮.\u06CEss-\u200D; [B2, B3, B5, B6, C2]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, V3] # 㸳ߊ≮.ێss- +-򷝬\u135E𑜧.\u1DEB-︒; ; [V3, V6, V7]; xn----b5h1837n2ok9f.xn----mkmw278h; ; ; # -፞𑜧.ᷫ-︒ +-򷝬\u135E𑜧.\u1DEB-。; -򷝬\u135E𑜧.\u1DEB-.; [V3, V6, V7]; xn----b5h1837n2ok9f.xn----mkm.; [V3, V6, V7, A4_2]; ; # -፞𑜧.ᷫ-. +xn----b5h1837n2ok9f.xn----mkm.; -򷝬\u135E𑜧.\u1DEB-.; [V3, V6, V7]; xn----b5h1837n2ok9f.xn----mkm.; [V3, V6, V7, A4_2]; ; # -፞𑜧.ᷫ-. +xn----b5h1837n2ok9f.xn----mkmw278h; -򷝬\u135E𑜧.\u1DEB-︒; [V3, V6, V7]; xn----b5h1837n2ok9f.xn----mkmw278h; ; ; # -፞𑜧.ᷫ-︒ +︒.򚠡\u1A59; ; [V7]; xn--y86c.xn--cof61594i; ; ; # ︒.ᩙ +。.򚠡\u1A59; ..򚠡\u1A59; [V7, X4_2]; ..xn--cof61594i; [V7, A4_2]; ; # ..ᩙ +..xn--cof61594i; ..򚠡\u1A59; [V7, X4_2]; ..xn--cof61594i; [V7, A4_2]; ; # ..ᩙ +xn--y86c.xn--cof61594i; ︒.򚠡\u1A59; [V7]; xn--y86c.xn--cof61594i; ; ; # ︒.ᩙ +\u0323\u2DE1。\u200C⓾\u200C\u06B9; \u0323\u2DE1.\u200C⓾\u200C\u06B9; [B1, C1, V6]; xn--kta899s.xn--skb970ka771c; ; xn--kta899s.xn--skb116m; [B1, V6] # ̣ⷡ.⓾ڹ +xn--kta899s.xn--skb116m; \u0323\u2DE1.⓾\u06B9; [B1, V6]; xn--kta899s.xn--skb116m; ; ; # ̣ⷡ.⓾ڹ +xn--kta899s.xn--skb970ka771c; \u0323\u2DE1.\u200C⓾\u200C\u06B9; [B1, C1, V6]; xn--kta899s.xn--skb970ka771c; ; ; # ̣ⷡ.⓾ڹ +𞠶ᠴ\u06DD。\u1074𞤵󠅦; 𞠶ᠴ\u06DD.\u1074𞤵; [B1, B2, V6, V7]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵 +𞠶ᠴ\u06DD。\u1074𞤵󠅦; 𞠶ᠴ\u06DD.\u1074𞤵; [B1, B2, V6, V7]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵 +𞠶ᠴ\u06DD。\u1074𞤓󠅦; 𞠶ᠴ\u06DD.\u1074𞤵; [B1, B2, V6, V7]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵 +xn--tlb199fwl35a.xn--yld4613v; 𞠶ᠴ\u06DD.\u1074𞤵; [B1, B2, V6, V7]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵 +𞠶ᠴ\u06DD。\u1074𞤓󠅦; 𞠶ᠴ\u06DD.\u1074𞤵; [B1, B2, V6, V7]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵 +𑰺.-򑟏; ; [V3, V6, V7]; xn--jk3d.xn----iz68g; ; ; # 𑰺.- +xn--jk3d.xn----iz68g; 𑰺.-򑟏; [V3, V6, V7]; xn--jk3d.xn----iz68g; ; ; # 𑰺.- +󠻩.赏; 󠻩.赏; [V7]; xn--2856e.xn--6o3a; ; ; # .赏 +󠻩.赏; ; [V7]; xn--2856e.xn--6o3a; ; ; # .赏 +xn--2856e.xn--6o3a; 󠻩.赏; [V7]; xn--2856e.xn--6o3a; ; ; # .赏 +\u06B0ᠡ。Ⴁ; \u06B0ᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ +\u06B0ᠡ。Ⴁ; \u06B0ᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ +\u06B0ᠡ。ⴁ; \u06B0ᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ +xn--jkb440g.xn--skj; \u06B0ᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ +\u06B0ᠡ。ⴁ; \u06B0ᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ +xn--jkb440g.xn--8md; \u06B0ᠡ.Ⴁ; [B2, B3, V7]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ +\u20DEႪ\u06BBς。-; \u20DEⴊ\u06BBς.-; [B1, V3, V6]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.- +\u20DEႪ\u06BBς。-; \u20DEⴊ\u06BBς.-; [B1, V3, V6]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.- +\u20DEⴊ\u06BBς。-; \u20DEⴊ\u06BBς.-; [B1, V3, V6]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.- +\u20DEႪ\u06BBΣ。-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +\u20DEⴊ\u06BBσ。-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +\u20DEႪ\u06BBσ。-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +xn--4xa33mr38aeel.-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +xn--3xa53mr38aeel.-; \u20DEⴊ\u06BBς.-; [B1, V3, V6]; xn--3xa53mr38aeel.-; ; ; # ⃞ⴊڻς.- +\u20DEⴊ\u06BBς。-; \u20DEⴊ\u06BBς.-; [B1, V3, V6]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.- +\u20DEႪ\u06BBΣ。-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +\u20DEⴊ\u06BBσ。-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +\u20DEႪ\u06BBσ。-; \u20DEⴊ\u06BBσ.-; [B1, V3, V6]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.- +xn--4xa33m7zmb0q.-; \u20DEႪ\u06BBσ.-; [B1, V3, V6, V7]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.- +xn--3xa53m7zmb0q.-; \u20DEႪ\u06BBς.-; [B1, V3, V6, V7]; xn--3xa53m7zmb0q.-; ; ; # ⃞Ⴊڻς.- +Ⴍ.񍇦\u200C; ⴍ.񍇦\u200C; [C1, V7]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [V7] # ⴍ. +Ⴍ.񍇦\u200C; ⴍ.񍇦\u200C; [C1, V7]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [V7] # ⴍ. +ⴍ.񍇦\u200C; ; [C1, V7]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [V7] # ⴍ. +xn--4kj.xn--p01x; ⴍ.񍇦; [V7]; xn--4kj.xn--p01x; ; ; # ⴍ. +xn--4kj.xn--0ug56448b; ⴍ.񍇦\u200C; [C1, V7]; xn--4kj.xn--0ug56448b; ; ; # ⴍ. +ⴍ.񍇦\u200C; ⴍ.񍇦\u200C; [C1, V7]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [V7] # ⴍ. +xn--lnd.xn--p01x; Ⴍ.񍇦; [V7]; xn--lnd.xn--p01x; ; ; # Ⴍ. +xn--lnd.xn--0ug56448b; Ⴍ.񍇦\u200C; [C1, V7]; xn--lnd.xn--0ug56448b; ; ; # Ⴍ. +򉟂󠵣.𐫫\u1A60󴺖\u1B44; ; [B2, B3, B6, V7]; xn--9u37blu98h.xn--jof13bt568cork1j; ; ; # .𐫫᩠᭄ +xn--9u37blu98h.xn--jof13bt568cork1j; 򉟂󠵣.𐫫\u1A60󴺖\u1B44; [B2, B3, B6, V7]; xn--9u37blu98h.xn--jof13bt568cork1j; ; ; # .𐫫᩠᭄ +≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨ +>\u0338❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨ +≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨ +>\u0338❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨ +xn--i7e163ct2d.xn--vwj7372e; ≯❊ᠯ.𐹱⺨; [B1]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨ +􁕜𐹧𞭁𐹩。Ⴈ𐫮Ⴏ; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, V7]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ +􁕜𐹧𞭁𐹩。ⴈ𐫮ⴏ; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, V7]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ +xn--fo0de1270ope54j.xn--zkjo0151o; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, V7]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ +xn--fo0de1270ope54j.xn--gndo2033q; 􁕜𐹧𞭁𐹩.Ⴈ𐫮Ⴏ; [B5, B6, V7]; xn--fo0de1270ope54j.xn--gndo2033q; ; ; # 𐹧𐹩.Ⴈ𐫮Ⴏ +𞠂。\uA926; 𞠂.\uA926; [B1, V6]; xn--145h.xn--ti9a; ; ; # 𞠂.ꤦ +xn--145h.xn--ti9a; 𞠂.\uA926; [B1, V6]; xn--145h.xn--ti9a; ; ; # 𞠂.ꤦ +𝟔𐹫.\u0733\u10379ꡇ; 6𐹫.\u1037\u07339ꡇ; [B1, V6]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ +𝟔𐹫.\u1037\u07339ꡇ; 6𐹫.\u1037\u07339ꡇ; [B1, V6]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ +6𐹫.\u1037\u07339ꡇ; ; [B1, V6]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ +xn--6-t26i.xn--9-91c730e8u8n; 6𐹫.\u1037\u07339ꡇ; [B1, V6]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ +\u0724\u0603𞲶.\u06D8; \u0724\u0603𞲶.\u06D8; [B1, V6, V7]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ +\u0724\u0603𞲶.\u06D8; ; [B1, V6, V7]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ +xn--lfb19ct414i.xn--olb; \u0724\u0603𞲶.\u06D8; [B1, V6, V7]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ +✆񱔩ꡋ.\u0632\u200D𞣴; ✆񱔩ꡋ.\u0632\u200D𞣴; [B1, C2, V7]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; xn--1biv525bcix0d.xn--xgb6828v; [B1, V7] # ✆ꡋ.ز +✆񱔩ꡋ.\u0632\u200D𞣴; ; [B1, C2, V7]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; xn--1biv525bcix0d.xn--xgb6828v; [B1, V7] # ✆ꡋ.ز +xn--1biv525bcix0d.xn--xgb6828v; ✆񱔩ꡋ.\u0632𞣴; [B1, V7]; xn--1biv525bcix0d.xn--xgb6828v; ; ; # ✆ꡋ.ز +xn--1biv525bcix0d.xn--xgb253k0m73a; ✆񱔩ꡋ.\u0632\u200D𞣴; [B1, C2, V7]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; ; # ✆ꡋ.ز +\u0845񃾰𞸍-.≠򃁟𑋪; \u0845񃾰\u0646-.≠򃁟𑋪; [B1, B2, B3, V3, V7]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪 +\u0845񃾰𞸍-.=\u0338򃁟𑋪; \u0845񃾰\u0646-.≠򃁟𑋪; [B1, B2, B3, V3, V7]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪 +\u0845񃾰\u0646-.≠򃁟𑋪; ; [B1, B2, B3, V3, V7]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪 +\u0845񃾰\u0646-.=\u0338򃁟𑋪; \u0845񃾰\u0646-.≠򃁟𑋪; [B1, B2, B3, V3, V7]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪 +xn----qoc64my971s.xn--1ch7585g76o3c; \u0845񃾰\u0646-.≠򃁟𑋪; [B1, B2, B3, V3, V7]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪 +𝟛.笠; 3.笠; ; 3.xn--6vz; ; ; # 3.笠 +𝟛.笠; 3.笠; ; 3.xn--6vz; ; ; # 3.笠 +3.笠; ; ; 3.xn--6vz; ; ; # 3.笠 +3.xn--6vz; 3.笠; ; 3.xn--6vz; ; ; # 3.笠 +-\u200D.Ⴞ𐋷; -\u200D.ⴞ𐋷; [C2, V3]; xn----ugn.xn--mlj8559d; ; -.xn--mlj8559d; [V3] # -.ⴞ𐋷 +-\u200D.ⴞ𐋷; ; [C2, V3]; xn----ugn.xn--mlj8559d; ; -.xn--mlj8559d; [V3] # -.ⴞ𐋷 +-.xn--mlj8559d; -.ⴞ𐋷; [V3]; -.xn--mlj8559d; ; ; # -.ⴞ𐋷 +xn----ugn.xn--mlj8559d; -\u200D.ⴞ𐋷; [C2, V3]; xn----ugn.xn--mlj8559d; ; ; # -.ⴞ𐋷 +-.xn--2nd2315j; -.Ⴞ𐋷; [V3, V7]; -.xn--2nd2315j; ; ; # -.Ⴞ𐋷 +xn----ugn.xn--2nd2315j; -\u200D.Ⴞ𐋷; [C2, V3, V7]; xn----ugn.xn--2nd2315j; ; ; # -.Ⴞ𐋷 +\u200Dςß\u0731.\u0BCD; \u200Dςß\u0731.\u0BCD; [C2, V6]; xn--zca19ln1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # ςßܱ.் +\u200Dςß\u0731.\u0BCD; ; [C2, V6]; xn--zca19ln1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # ςßܱ.் +\u200DΣSS\u0731.\u0BCD; \u200Dσss\u0731.\u0BCD; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σssܱ.் +\u200Dσss\u0731.\u0BCD; ; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σssܱ.் +\u200DΣss\u0731.\u0BCD; \u200Dσss\u0731.\u0BCD; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σssܱ.் +xn--ss-ubc826a.xn--xmc; σss\u0731.\u0BCD; [V6]; xn--ss-ubc826a.xn--xmc; ; ; # σssܱ.் +xn--ss-ubc826ab34b.xn--xmc; \u200Dσss\u0731.\u0BCD; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; ; # σssܱ.் +\u200DΣß\u0731.\u0BCD; \u200Dσß\u0731.\u0BCD; [C2, V6]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σßܱ.் +\u200Dσß\u0731.\u0BCD; ; [C2, V6]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σßܱ.் +xn--zca39lk1di19a.xn--xmc; \u200Dσß\u0731.\u0BCD; [C2, V6]; xn--zca39lk1di19a.xn--xmc; ; ; # σßܱ.் +xn--zca19ln1di19a.xn--xmc; \u200Dςß\u0731.\u0BCD; [C2, V6]; xn--zca19ln1di19a.xn--xmc; ; ; # ςßܱ.் +\u200DΣSS\u0731.\u0BCD; \u200Dσss\u0731.\u0BCD; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σssܱ.் +\u200Dσss\u0731.\u0BCD; \u200Dσss\u0731.\u0BCD; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σssܱ.் +\u200DΣss\u0731.\u0BCD; \u200Dσss\u0731.\u0BCD; [C2, V6]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σssܱ.் +\u200DΣß\u0731.\u0BCD; \u200Dσß\u0731.\u0BCD; [C2, V6]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σßܱ.் +\u200Dσß\u0731.\u0BCD; \u200Dσß\u0731.\u0BCD; [C2, V6]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V6] # σßܱ.் +≠.\u200D; ≠.\u200D; [C2]; xn--1ch.xn--1ug; ; xn--1ch.; [A4_2] # ≠. +=\u0338.\u200D; ≠.\u200D; [C2]; xn--1ch.xn--1ug; ; xn--1ch.; [A4_2] # ≠. +≠.\u200D; ; [C2]; xn--1ch.xn--1ug; ; xn--1ch.; [A4_2] # ≠. +=\u0338.\u200D; ≠.\u200D; [C2]; xn--1ch.xn--1ug; ; xn--1ch.; [A4_2] # ≠. +xn--1ch.; ≠.; ; xn--1ch.; [A4_2]; ; # ≠. +≠.; ; ; xn--1ch.; [A4_2]; ; # ≠. +=\u0338.; ≠.; ; xn--1ch.; [A4_2]; ; # ≠. +xn--1ch.xn--1ug; ≠.\u200D; [C2]; xn--1ch.xn--1ug; ; ; # ≠. +\uFC01。\u0C81ᠼ▗򒁋; \u0626\u062D.\u0C81ᠼ▗򒁋; [B1, V6, V7]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗ +\u0626\u062D。\u0C81ᠼ▗򒁋; \u0626\u062D.\u0C81ᠼ▗򒁋; [B1, V6, V7]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗ +\u064A\u0654\u062D。\u0C81ᠼ▗򒁋; \u0626\u062D.\u0C81ᠼ▗򒁋; [B1, V6, V7]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗ +xn--lgbo.xn--2rc021dcxkrx55t; \u0626\u062D.\u0C81ᠼ▗򒁋; [B1, V6, V7]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗ +󧋵\u09CDς.ς𐨿; 󧋵\u09CDς.ς𐨿; [V7]; xn--3xa702av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্ς.ς𐨿 +󧋵\u09CDς.ς𐨿; ; [V7]; xn--3xa702av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্ς.ς𐨿 +󧋵\u09CDΣ.Σ𐨿; 󧋵\u09CDσ.σ𐨿; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +󧋵\u09CDσ.ς𐨿; ; [V7]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿 +󧋵\u09CDσ.σ𐨿; ; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +󧋵\u09CDΣ.σ𐨿; 󧋵\u09CDσ.σ𐨿; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +xn--4xa502av8297a.xn--4xa6055k; 󧋵\u09CDσ.σ𐨿; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +󧋵\u09CDΣ.ς𐨿; 󧋵\u09CDσ.ς𐨿; [V7]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿 +xn--4xa502av8297a.xn--3xa8055k; 󧋵\u09CDσ.ς𐨿; [V7]; xn--4xa502av8297a.xn--3xa8055k; ; ; # ্σ.ς𐨿 +xn--3xa702av8297a.xn--3xa8055k; 󧋵\u09CDς.ς𐨿; [V7]; xn--3xa702av8297a.xn--3xa8055k; ; ; # ্ς.ς𐨿 +󧋵\u09CDΣ.Σ𐨿; 󧋵\u09CDσ.σ𐨿; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +󧋵\u09CDσ.ς𐨿; 󧋵\u09CDσ.ς𐨿; [V7]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿 +󧋵\u09CDσ.σ𐨿; 󧋵\u09CDσ.σ𐨿; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +󧋵\u09CDΣ.σ𐨿; 󧋵\u09CDσ.σ𐨿; [V7]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿 +󧋵\u09CDΣ.ς𐨿; 󧋵\u09CDσ.ς𐨿; [V7]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿 +𐫓\u07D8牅\u08F8。𞦤\u1A17򱍰Ⴙ; 𐫓\u07D8牅\u08F8.𞦤\u1A17򱍰ⴙ; [B2, B3, V7]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ +𐫓\u07D8牅\u08F8。𞦤\u1A17򱍰Ⴙ; 𐫓\u07D8牅\u08F8.𞦤\u1A17򱍰ⴙ; [B2, B3, V7]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ +𐫓\u07D8牅\u08F8。𞦤\u1A17򱍰ⴙ; 𐫓\u07D8牅\u08F8.𞦤\u1A17򱍰ⴙ; [B2, B3, V7]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ +xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; 𐫓\u07D8牅\u08F8.𞦤\u1A17򱍰ⴙ; [B2, B3, V7]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ +𐫓\u07D8牅\u08F8。𞦤\u1A17򱍰ⴙ; 𐫓\u07D8牅\u08F8.𞦤\u1A17򱍰ⴙ; [B2, B3, V7]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ +xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; 𐫓\u07D8牅\u08F8.𞦤\u1A17򱍰Ⴙ; [B2, B3, V7]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ +񣤒。륧; 񣤒.륧; [V7]; xn--s264a.xn--pw2b; ; ; # .륧 +񣤒。륧; 񣤒.륧; [V7]; xn--s264a.xn--pw2b; ; ; # .륧 +񣤒。륧; 񣤒.륧; [V7]; xn--s264a.xn--pw2b; ; ; # .륧 +񣤒。륧; 񣤒.륧; [V7]; xn--s264a.xn--pw2b; ; ; # .륧 +xn--s264a.xn--pw2b; 񣤒.륧; [V7]; xn--s264a.xn--pw2b; ; ; # .륧 +𐹷\u200D。󉵢; 𐹷\u200D.󉵢; [B1, C2, V7]; xn--1ugx205g.xn--8088d; ; xn--vo0d.xn--8088d; [B1, V7] # 𐹷. +xn--vo0d.xn--8088d; 𐹷.󉵢; [B1, V7]; xn--vo0d.xn--8088d; ; ; # 𐹷. +xn--1ugx205g.xn--8088d; 𐹷\u200D.󉵢; [B1, C2, V7]; xn--1ugx205g.xn--8088d; ; ; # 𐹷. +Ⴘ\u06C2𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +Ⴘ\u06C1\u0654𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +Ⴘ\u06C2𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +Ⴘ\u06C1\u0654𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +ⴘ\u06C1\u0654𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +ⴘ\u06C2𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +xn--1kb147qfk3n.-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +ⴘ\u06C1\u0654𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +ⴘ\u06C2𑲭。-; ⴘ\u06C2𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.- +xn--1kb312c139t.-; Ⴘ\u06C2𑲭.-; [B1, B5, B6, V3, V7]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.- +\uA806\u067B₆ᡐ。🛇\uFCDD; \uA806\u067B6ᡐ.🛇\u064A\u0645; [B1, V6]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم +\uA806\u067B6ᡐ。🛇\u064A\u0645; \uA806\u067B6ᡐ.🛇\u064A\u0645; [B1, V6]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم +xn--6-rrc018krt9k.xn--hhbj61429a; \uA806\u067B6ᡐ.🛇\u064A\u0645; [B1, V6]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم +򸍂.㇄ᡟ𐫂\u0622; ; [B1, V7]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ +򸍂.㇄ᡟ𐫂\u0627\u0653; 򸍂.㇄ᡟ𐫂\u0622; [B1, V7]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ +xn--p292d.xn--hgb154ghrsvm2r; 򸍂.㇄ᡟ𐫂\u0622; [B1, V7]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ +\u07DF򵚌。-\u07E9; \u07DF򵚌.-\u07E9; [B1, B2, B3, V3, V7]; xn--6sb88139l.xn----pdd; ; ; # ߟ.-ߩ +xn--6sb88139l.xn----pdd; \u07DF򵚌.-\u07E9; [B1, B2, B3, V3, V7]; xn--6sb88139l.xn----pdd; ; ; # ߟ.-ߩ +ς\u0643⾑.\u200Cᢟ\u200C⒈; ς\u0643襾.\u200Cᢟ\u200C⒈; [B1, B5, C1, V7]; xn--3xa69jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, V7] # ςك襾.ᢟ⒈ +ς\u0643襾.\u200Cᢟ\u200C1.; ; [B1, B5, C1]; xn--3xa69jux8r.xn--1-4ck691bba.; [B1, B5, C1, A4_2]; xn--4xa49jux8r.xn--1-4ck.; [B5, A4_2] # ςك襾.ᢟ1. +Σ\u0643襾.\u200Cᢟ\u200C1.; σ\u0643襾.\u200Cᢟ\u200C1.; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; [B1, B5, C1, A4_2]; xn--4xa49jux8r.xn--1-4ck.; [B5, A4_2] # σك襾.ᢟ1. +σ\u0643襾.\u200Cᢟ\u200C1.; ; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; [B1, B5, C1, A4_2]; xn--4xa49jux8r.xn--1-4ck.; [B5, A4_2] # σك襾.ᢟ1. +xn--4xa49jux8r.xn--1-4ck.; σ\u0643襾.ᢟ1.; [B5]; xn--4xa49jux8r.xn--1-4ck.; [B5, A4_2]; ; # σك襾.ᢟ1. +xn--4xa49jux8r.xn--1-4ck691bba.; σ\u0643襾.\u200Cᢟ\u200C1.; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; [B1, B5, C1, A4_2]; ; # σك襾.ᢟ1. +xn--3xa69jux8r.xn--1-4ck691bba.; ς\u0643襾.\u200Cᢟ\u200C1.; [B1, B5, C1]; xn--3xa69jux8r.xn--1-4ck691bba.; [B1, B5, C1, A4_2]; ; # ςك襾.ᢟ1. +Σ\u0643⾑.\u200Cᢟ\u200C⒈; σ\u0643襾.\u200Cᢟ\u200C⒈; [B1, B5, C1, V7]; xn--4xa49jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, V7] # σك襾.ᢟ⒈ +σ\u0643⾑.\u200Cᢟ\u200C⒈; σ\u0643襾.\u200Cᢟ\u200C⒈; [B1, B5, C1, V7]; xn--4xa49jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, V7] # σك襾.ᢟ⒈ +xn--4xa49jux8r.xn--pbf212d; σ\u0643襾.ᢟ⒈; [B5, V7]; xn--4xa49jux8r.xn--pbf212d; ; ; # σك襾.ᢟ⒈ +xn--4xa49jux8r.xn--pbf519aba607b; σ\u0643襾.\u200Cᢟ\u200C⒈; [B1, B5, C1, V7]; xn--4xa49jux8r.xn--pbf519aba607b; ; ; # σك襾.ᢟ⒈ +xn--3xa69jux8r.xn--pbf519aba607b; ς\u0643襾.\u200Cᢟ\u200C⒈; [B1, B5, C1, V7]; xn--3xa69jux8r.xn--pbf519aba607b; ; ; # ςك襾.ᢟ⒈ +ᡆ𑓝.𞵆; ᡆ𑓝.𞵆; [V7]; xn--57e0440k.xn--k86h; ; ; # ᡆ. +ᡆ𑓝.𞵆; ; [V7]; xn--57e0440k.xn--k86h; ; ; # ᡆ. +xn--57e0440k.xn--k86h; ᡆ𑓝.𞵆; [V7]; xn--57e0440k.xn--k86h; ; ; # ᡆ. +\u0A4D𦍓\u1DEE。\u200C\u08BD񝹲; \u0A4D𦍓\u1DEE.\u200C\u08BD񝹲; [B1, C1, V6, V7]; xn--ybc461hph93b.xn--jzb740j1y45h; ; xn--ybc461hph93b.xn--jzb29857e; [B1, B2, B3, V6, V7] # ੍𦍓ᷮ.ࢽ +\u0A4D𦍓\u1DEE。\u200C\u08BD񝹲; \u0A4D𦍓\u1DEE.\u200C\u08BD񝹲; [B1, C1, V6, V7]; xn--ybc461hph93b.xn--jzb740j1y45h; ; xn--ybc461hph93b.xn--jzb29857e; [B1, B2, B3, V6, V7] # ੍𦍓ᷮ.ࢽ +xn--ybc461hph93b.xn--jzb29857e; \u0A4D𦍓\u1DEE.\u08BD񝹲; [B1, B2, B3, V6, V7]; xn--ybc461hph93b.xn--jzb29857e; ; ; # ੍𦍓ᷮ.ࢽ +xn--ybc461hph93b.xn--jzb740j1y45h; \u0A4D𦍓\u1DEE.\u200C\u08BD񝹲; [B1, C1, V6, V7]; xn--ybc461hph93b.xn--jzb740j1y45h; ; ; # ੍𦍓ᷮ.ࢽ +\u062E\u0748񅪪-.\u200C먿; \u062E\u0748񅪪-.\u200C먿; [B1, B2, B3, C1, V3, V7]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, V3, V7] # خ݈-.먿 +\u062E\u0748񅪪-.\u200C먿; \u062E\u0748񅪪-.\u200C먿; [B1, B2, B3, C1, V3, V7]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, V3, V7] # خ݈-.먿 +\u062E\u0748񅪪-.\u200C먿; ; [B1, B2, B3, C1, V3, V7]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, V3, V7] # خ݈-.먿 +\u062E\u0748񅪪-.\u200C먿; \u062E\u0748񅪪-.\u200C먿; [B1, B2, B3, C1, V3, V7]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, V3, V7] # خ݈-.먿 +xn----dnc06f42153a.xn--v22b; \u062E\u0748񅪪-.먿; [B2, B3, V3, V7]; xn----dnc06f42153a.xn--v22b; ; ; # خ݈-.먿 +xn----dnc06f42153a.xn--0ug1581d; \u062E\u0748񅪪-.\u200C먿; [B1, B2, B3, C1, V3, V7]; xn----dnc06f42153a.xn--0ug1581d; ; ; # خ݈-.먿 +􋿦。ᠽ; 􋿦.ᠽ; [V7]; xn--j890g.xn--w7e; ; ; # .ᠽ +􋿦。ᠽ; 􋿦.ᠽ; [V7]; xn--j890g.xn--w7e; ; ; # .ᠽ +xn--j890g.xn--w7e; 􋿦.ᠽ; [V7]; xn--j890g.xn--w7e; ; ; # .ᠽ +嬃𝍌.\u200D\u0B44; 嬃𝍌.\u200D\u0B44; [C2]; xn--b6s0078f.xn--0ic557h; ; xn--b6s0078f.xn--0ic; [V6] # 嬃𝍌.ୄ +嬃𝍌.\u200D\u0B44; ; [C2]; xn--b6s0078f.xn--0ic557h; ; xn--b6s0078f.xn--0ic; [V6] # 嬃𝍌.ୄ +xn--b6s0078f.xn--0ic; 嬃𝍌.\u0B44; [V6]; xn--b6s0078f.xn--0ic; ; ; # 嬃𝍌.ୄ +xn--b6s0078f.xn--0ic557h; 嬃𝍌.\u200D\u0B44; [C2]; xn--b6s0078f.xn--0ic557h; ; ; # 嬃𝍌.ୄ +\u0602𝌪≯.𚋲򵁨; \u0602𝌪≯.𚋲򵁨; [B1, V7]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯. +\u0602𝌪>\u0338.𚋲򵁨; \u0602𝌪≯.𚋲򵁨; [B1, V7]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯. +\u0602𝌪≯.𚋲򵁨; ; [B1, V7]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯. +\u0602𝌪>\u0338.𚋲򵁨; \u0602𝌪≯.𚋲򵁨; [B1, V7]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯. +xn--kfb866llx01a.xn--wp1gm3570b; \u0602𝌪≯.𚋲򵁨; [B1, V7]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯. +򫾥\u08B7\u17CC\uA9C0.𞼠; ; [B5, V7]; xn--dzb638ewm4i1iy1h.xn--3m7h; ; ; # ࢷ៌꧀. +xn--dzb638ewm4i1iy1h.xn--3m7h; 򫾥\u08B7\u17CC\uA9C0.𞼠; [B5, V7]; xn--dzb638ewm4i1iy1h.xn--3m7h; ; ; # ࢷ៌꧀. +\u200C.񟛤; ; [C1, V7]; xn--0ug.xn--q823a; ; .xn--q823a; [V7, A4_2] # . +.xn--q823a; .񟛤; [V7, X4_2]; .xn--q823a; [V7, A4_2]; ; # . +xn--0ug.xn--q823a; \u200C.񟛤; [C1, V7]; xn--0ug.xn--q823a; ; ; # . +򺛕Ⴃ䠅.𐸑; 򺛕ⴃ䠅.𐸑; [V7]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅. +򺛕Ⴃ䠅.𐸑; 򺛕ⴃ䠅.𐸑; [V7]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅. +򺛕ⴃ䠅.𐸑; ; [V7]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅. +xn--ukju77frl47r.xn--yl0d; 򺛕ⴃ䠅.𐸑; [V7]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅. +򺛕ⴃ䠅.𐸑; 򺛕ⴃ䠅.𐸑; [V7]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅. +xn--bnd074zr557n.xn--yl0d; 򺛕Ⴃ䠅.𐸑; [V7]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅. +\u1BF1𐹳𐹵𞤚。𝟨Ⴅ; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +\u1BF1𐹳𐹵𞤚。6Ⴅ; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +\u1BF1𐹳𐹵𞤼。6ⴅ; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +\u1BF1𐹳𐹵𞤚。6ⴅ; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +xn--zzfy954hga2415t.xn--6-kvs; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +\u1BF1𐹳𐹵𞤼。𝟨ⴅ; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +\u1BF1𐹳𐹵𞤚。𝟨ⴅ; \u1BF1𐹳𐹵𞤼.6ⴅ; [B1, V6]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ +xn--zzfy954hga2415t.xn--6-h0g; \u1BF1𐹳𐹵𞤼.6Ⴅ; [B1, V6, V7]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ +-。︒; -.︒; [V3, V7]; -.xn--y86c; ; ; # -.︒ +-。。; -..; [V3, X4_2]; ; [V3, A4_2]; ; # -.. +-..; ; [V3, X4_2]; ; [V3, A4_2]; ; # -.. +-.xn--y86c; -.︒; [V3, V7]; -.xn--y86c; ; ; # -.︒ +\u07DBჀ。-⁵--; \u07DBⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5-- +\u07DBჀ。-5--; \u07DBⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5-- +\u07DBⴠ。-5--; \u07DBⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5-- +xn--2sb691q.-5--; \u07DBⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5-- +\u07DBⴠ。-⁵--; \u07DBⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5-- +xn--2sb866b.-5--; \u07DBჀ.-5--; [B1, B2, B3, V2, V3, V7]; xn--2sb866b.-5--; ; ; # ߛჀ.-5-- +≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +>\u0338?󠑕。𐹷𐹻>\u0338𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +>\u0338?󠑕。𐹷𐹻>\u0338𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +xn--?-ogo25661n.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +≯?󠑕.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +>\u0338?󠑕.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +>\u0338?󠑕.XN--HDH8283GDOAQA; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +≯?󠑕.XN--HDH8283GDOAQA; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +≯?󠑕.Xn--Hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +>\u0338?󠑕.Xn--Hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, V7, U1]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯ +㍔\u08E6\u077C\u200D。\u0346򁳊𝅶\u0604; ルーブル\u08E6\u077C\u200D.\u0346򁳊\u0604; [B1, B5, B6, C2, V6, V7]; xn--dqb73ec22c9kp8cb1j.xn--kua81lx7141a; ; xn--dqb73el09fncab4h.xn--kua81lx7141a; [B1, B5, B6, V6, V7] # ルーブルࣦݼ.͆ +ルーブル\u08E6\u077C\u200D。\u0346򁳊𝅶\u0604; ルーブル\u08E6\u077C\u200D.\u0346򁳊\u0604; [B1, B5, B6, C2, V6, V7]; xn--dqb73ec22c9kp8cb1j.xn--kua81lx7141a; ; xn--dqb73el09fncab4h.xn--kua81lx7141a; [B1, B5, B6, V6, V7] # ルーブルࣦݼ.͆ +ルーフ\u3099ル\u08E6\u077C\u200D。\u0346򁳊𝅶\u0604; ルーブル\u08E6\u077C\u200D.\u0346򁳊\u0604; [B1, B5, B6, C2, V6, V7]; xn--dqb73ec22c9kp8cb1j.xn--kua81lx7141a; ; xn--dqb73el09fncab4h.xn--kua81lx7141a; [B1, B5, B6, V6, V7] # ルーブルࣦݼ.͆ +xn--dqb73el09fncab4h.xn--kua81lx7141a; ルーブル\u08E6\u077C.\u0346򁳊\u0604; [B1, B5, B6, V6, V7]; xn--dqb73el09fncab4h.xn--kua81lx7141a; ; ; # ルーブルࣦݼ.͆ +xn--dqb73ec22c9kp8cb1j.xn--kua81lx7141a; ルーブル\u08E6\u077C\u200D.\u0346򁳊\u0604; [B1, B5, B6, C2, V6, V7]; xn--dqb73ec22c9kp8cb1j.xn--kua81lx7141a; ; ; # ルーブルࣦݼ.͆ +xn--dqb73el09fncab4h.xn--kua81ls548d3608b; ルーブル\u08E6\u077C.\u0346򁳊𝅶\u0604; [B1, B5, B6, V6, V7]; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; ; ; # ルーブルࣦݼ.͆ +xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ルーブル\u08E6\u077C\u200D.\u0346򁳊𝅶\u0604; [B1, B5, B6, C2, V6, V7]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; ; # ルーブルࣦݼ.͆ +\u200D.F; \u200D.f; [C2]; xn--1ug.f; ; .f; [A4_2] # .f +\u200D.f; ; [C2]; xn--1ug.f; ; .f; [A4_2] # .f +.f; ; [X4_2]; ; [A4_2]; ; # .f +xn--1ug.f; \u200D.f; [C2]; xn--1ug.f; ; ; # .f +f; ; ; ; ; ; # f +\u200D㨲。ß; \u200D㨲.ß; [C2]; xn--1ug914h.xn--zca; ; xn--9bm.ss; [] # 㨲.ß +\u200D㨲。ß; \u200D㨲.ß; [C2]; xn--1ug914h.xn--zca; ; xn--9bm.ss; [] # 㨲.ß +\u200D㨲。SS; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss +\u200D㨲。ss; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss +\u200D㨲。Ss; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss +xn--9bm.ss; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss +㨲.ss; ; ; xn--9bm.ss; ; ; # 㨲.ss +㨲.SS; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss +㨲.Ss; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss +xn--1ug914h.ss; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; ; # 㨲.ss +xn--1ug914h.xn--zca; \u200D㨲.ß; [C2]; xn--1ug914h.xn--zca; ; ; # 㨲.ß +\u200D㨲。SS; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss +\u200D㨲。ss; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss +\u200D㨲。Ss; \u200D㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss +\u0605\u067E。\u08A8; \u0605\u067E.\u08A8; [B1, V7]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ +\u0605\u067E。\u08A8; \u0605\u067E.\u08A8; [B1, V7]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ +xn--nfb6v.xn--xyb; \u0605\u067E.\u08A8; [B1, V7]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ +⾑\u0753𞤁。𐹵\u0682; 襾\u0753𞤣.𐹵\u0682; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ +襾\u0753𞤁。𐹵\u0682; 襾\u0753𞤣.𐹵\u0682; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ +襾\u0753𞤣。𐹵\u0682; 襾\u0753𞤣.𐹵\u0682; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ +xn--6ob9577deqwl.xn--7ib5526k; 襾\u0753𞤣.𐹵\u0682; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ +⾑\u0753𞤣。𐹵\u0682; 襾\u0753𞤣.𐹵\u0682; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ +񦴻ς-\u20EB。\u0754-ꡛ; 񦴻ς-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----xmb015tuo34l.xn----53c4874j; ; xn----zmb705tuo34l.xn----53c4874j; # ς-⃫.ݔ-ꡛ +񦴻ς-\u20EB。\u0754-ꡛ; 񦴻ς-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----xmb015tuo34l.xn----53c4874j; ; xn----zmb705tuo34l.xn----53c4874j; # ς-⃫.ݔ-ꡛ +񦴻Σ-\u20EB。\u0754-ꡛ; 񦴻σ-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ +񦴻σ-\u20EB。\u0754-ꡛ; 񦴻σ-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ +xn----zmb705tuo34l.xn----53c4874j; 񦴻σ-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ +xn----xmb015tuo34l.xn----53c4874j; 񦴻ς-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----xmb015tuo34l.xn----53c4874j; ; ; # ς-⃫.ݔ-ꡛ +񦴻Σ-\u20EB。\u0754-ꡛ; 񦴻σ-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ +񦴻σ-\u20EB。\u0754-ꡛ; 񦴻σ-\u20EB.\u0754-ꡛ; [B2, B3, B6, V7]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ +\u200D.􀸨; \u200D.􀸨; [C2, V7]; xn--1ug.xn--h327f; ; .xn--h327f; [V7, A4_2] # . +\u200D.􀸨; ; [C2, V7]; xn--1ug.xn--h327f; ; .xn--h327f; [V7, A4_2] # . +.xn--h327f; .􀸨; [V7, X4_2]; .xn--h327f; [V7, A4_2]; ; # . +xn--1ug.xn--h327f; \u200D.􀸨; [C2, V7]; xn--1ug.xn--h327f; ; ; # . +񣭻񌥁。≠𝟲; 񣭻񌥁.≠6; [V7]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6 +񣭻񌥁。=\u0338𝟲; 񣭻񌥁.≠6; [V7]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6 +񣭻񌥁。≠6; 񣭻񌥁.≠6; [V7]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6 +񣭻񌥁。=\u03386; 񣭻񌥁.≠6; [V7]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6 +xn--h79w4z99a.xn--6-tfo; 񣭻񌥁.≠6; [V7]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6 +󠅊ᡭ\u200D.𐥡; ᡭ\u200D.𐥡; [B6, C2, V7]; xn--98e810b.xn--om9c; ; xn--98e.xn--om9c; [V7] # ᡭ. +xn--98e.xn--om9c; ᡭ.𐥡; [V7]; xn--98e.xn--om9c; ; ; # ᡭ. +xn--98e810b.xn--om9c; ᡭ\u200D.𐥡; [B6, C2, V7]; xn--98e810b.xn--om9c; ; ; # ᡭ. +\u0C40\u0855𐥛𑄴.󭰵; \u0C40\u0855𐥛𑄴.󭰵; [B1, V6, V7]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴. +\u0C40\u0855𐥛𑄴.󭰵; ; [B1, V6, V7]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴. +xn--kwb91r5112avtg.xn--o580f; \u0C40\u0855𐥛𑄴.󭰵; [B1, V6, V7]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴. +𞤮。𑇊\u200C≯\u1CE6; 𞤮.𑇊\u200C≯\u1CE6; [B1, C1, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, V6] # 𞤮.𑇊≯᳦ +𞤮。𑇊\u200C>\u0338\u1CE6; 𞤮.𑇊\u200C≯\u1CE6; [B1, C1, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, V6] # 𞤮.𑇊≯᳦ +𞤌。𑇊\u200C>\u0338\u1CE6; 𞤮.𑇊\u200C≯\u1CE6; [B1, C1, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, V6] # 𞤮.𑇊≯᳦ +𞤌。𑇊\u200C≯\u1CE6; 𞤮.𑇊\u200C≯\u1CE6; [B1, C1, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, V6] # 𞤮.𑇊≯᳦ +xn--me6h.xn--z6fz8ueq2v; 𞤮.𑇊≯\u1CE6; [B1, V6]; xn--me6h.xn--z6fz8ueq2v; ; ; # 𞤮.𑇊≯᳦ +xn--me6h.xn--z6f16kn9b2642b; 𞤮.𑇊\u200C≯\u1CE6; [B1, C1, V6]; xn--me6h.xn--z6f16kn9b2642b; ; ; # 𞤮.𑇊≯᳦ +󠄀𝟕.𞤌񛗓Ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +󠄀7.𞤌񛗓Ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +󠄀7.𞤮񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +7.xn--0kjz523lv1vv; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +󠄀𝟕.𞤮񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +7.xn--hnd3403vv1vv; 7.𞤮񛗓Ⴉ; [B1, B2, B3, V7]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ +󠄀7.𞤌񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +󠄀𝟕.𞤌񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, V7]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ +閃9𝩍。Ↄ\u0669\u08B1\u0B4D; 閃9𝩍.ↄ\u0669\u08B1\u0B4D; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍ +閃9𝩍。ↄ\u0669\u08B1\u0B4D; 閃9𝩍.ↄ\u0669\u08B1\u0B4D; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍ +xn--9-3j6dk517f.xn--iib28ij3c4t9a; 閃9𝩍.ↄ\u0669\u08B1\u0B4D; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍ +xn--9-3j6dk517f.xn--iib28ij3c0t9a; 閃9𝩍.Ↄ\u0669\u08B1\u0B4D; [B5, B6, V7]; xn--9-3j6dk517f.xn--iib28ij3c0t9a; ; ; # 閃9𝩍.Ↄ٩ࢱ୍ +\uAAF6ᢏ\u0E3A2.𐋢\u0745\u0F9F︒; \uAAF6ᢏ\u0E3A2.𐋢\u0745\u0F9F︒; [V6, V7]; xn--2-2zf840fk16m.xn--sob093bj62sz9d; ; ; # ꫶ᢏฺ2.𐋢݅ྟ︒ +\uAAF6ᢏ\u0E3A2.𐋢\u0745\u0F9F。; \uAAF6ᢏ\u0E3A2.𐋢\u0745\u0F9F.; [V6]; xn--2-2zf840fk16m.xn--sob093b2m7s.; [V6, A4_2]; ; # ꫶ᢏฺ2.𐋢݅ྟ. +xn--2-2zf840fk16m.xn--sob093b2m7s.; \uAAF6ᢏ\u0E3A2.𐋢\u0745\u0F9F.; [V6]; xn--2-2zf840fk16m.xn--sob093b2m7s.; [V6, A4_2]; ; # ꫶ᢏฺ2.𐋢݅ྟ. +xn--2-2zf840fk16m.xn--sob093bj62sz9d; \uAAF6ᢏ\u0E3A2.𐋢\u0745\u0F9F︒; [V6, V7]; xn--2-2zf840fk16m.xn--sob093bj62sz9d; ; ; # ꫶ᢏฺ2.𐋢݅ྟ︒ +󅴧。≠-󠙄⾛; 󅴧.≠-󠙄走; [V7]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走 +󅴧。=\u0338-󠙄⾛; 󅴧.≠-󠙄走; [V7]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走 +󅴧。≠-󠙄走; 󅴧.≠-󠙄走; [V7]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走 +󅴧。=\u0338-󠙄走; 󅴧.≠-󠙄走; [V7]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走 +xn--gm57d.xn----tfo4949b3664m; 󅴧.≠-󠙄走; [V7]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走 +\u076E\u0604Ⴊ。-≠\u1160; \u076E\u0604ⴊ.-≠; [B1, B2, B3, V3, V7]; xn--mfb73ek93f.xn----ufo; ; ; # ݮⴊ.-≠ +\u076E\u0604Ⴊ。-=\u0338\u1160; \u076E\u0604ⴊ.-≠; [B1, B2, B3, V3, V7]; xn--mfb73ek93f.xn----ufo; ; ; # ݮⴊ.-≠ +\u076E\u0604ⴊ。-=\u0338\u1160; \u076E\u0604ⴊ.-≠; [B1, B2, B3, V3, V7]; xn--mfb73ek93f.xn----ufo; ; ; # ݮⴊ.-≠ +\u076E\u0604ⴊ。-≠\u1160; \u076E\u0604ⴊ.-≠; [B1, B2, B3, V3, V7]; xn--mfb73ek93f.xn----ufo; ; ; # ݮⴊ.-≠ +xn--mfb73ek93f.xn----ufo; \u076E\u0604ⴊ.-≠; [B1, B2, B3, V3, V7]; xn--mfb73ek93f.xn----ufo; ; ; # ݮⴊ.-≠ +xn--mfb73ek93f.xn----5bh589i; \u076E\u0604ⴊ.-≠\u1160; [B1, B2, B3, V3, V7]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠ +xn--mfb73ex6r.xn----5bh589i; \u076E\u0604Ⴊ.-≠\u1160; [B1, B2, B3, V3, V7]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠ +\uFB4F𐹧𝟒≯。\u200C; \u05D0\u05DC𐹧4≯.\u200C; [B1, B3, B4, C1]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, A4_2] # אל𐹧4≯. +\uFB4F𐹧𝟒>\u0338。\u200C; \u05D0\u05DC𐹧4≯.\u200C; [B1, B3, B4, C1]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, A4_2] # אל𐹧4≯. +\u05D0\u05DC𐹧4≯。\u200C; \u05D0\u05DC𐹧4≯.\u200C; [B1, B3, B4, C1]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, A4_2] # אל𐹧4≯. +\u05D0\u05DC𐹧4>\u0338。\u200C; \u05D0\u05DC𐹧4≯.\u200C; [B1, B3, B4, C1]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, A4_2] # אל𐹧4≯. +xn--4-zhc0by36txt0w.; \u05D0\u05DC𐹧4≯.; [B3, B4]; xn--4-zhc0by36txt0w.; [B3, B4, A4_2]; ; # אל𐹧4≯. +xn--4-zhc0by36txt0w.xn--0ug; \u05D0\u05DC𐹧4≯.\u200C; [B1, B3, B4, C1]; xn--4-zhc0by36txt0w.xn--0ug; ; ; # אל𐹧4≯. +𝟎。甯; 0.甯; ; 0.xn--qny; ; ; # 0.甯 +0。甯; 0.甯; ; 0.xn--qny; ; ; # 0.甯 +0.xn--qny; 0.甯; ; 0.xn--qny; ; ; # 0.甯 +0.甯; ; ; 0.xn--qny; ; ; # 0.甯 +-⾆.\uAAF6; -舌.\uAAF6; [V3, V6]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶ +-舌.\uAAF6; ; [V3, V6]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶ +xn----ef8c.xn--2v9a; -舌.\uAAF6; [V3, V6]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶ +-。ᢘ; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ +-。ᢘ; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ +-.xn--ibf; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ +🂴Ⴋ.≮; 🂴ⴋ.≮; ; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮ +🂴Ⴋ.<\u0338; 🂴ⴋ.≮; ; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮ +🂴ⴋ.<\u0338; 🂴ⴋ.≮; ; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮ +🂴ⴋ.≮; ; ; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮ +xn--2kj7565l.xn--gdh; 🂴ⴋ.≮; ; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮ +xn--jnd1986v.xn--gdh; 🂴Ⴋ.≮; [V7]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮ +璼𝨭。\u200C󠇟; 璼𝨭.\u200C; [C1]; xn--gky8837e.xn--0ug; ; xn--gky8837e.; [A4_2] # 璼𝨭. +璼𝨭。\u200C󠇟; 璼𝨭.\u200C; [C1]; xn--gky8837e.xn--0ug; ; xn--gky8837e.; [A4_2] # 璼𝨭. +xn--gky8837e.; 璼𝨭.; ; xn--gky8837e.; [A4_2]; ; # 璼𝨭. +璼𝨭.; ; ; xn--gky8837e.; [A4_2]; ; # 璼𝨭. +xn--gky8837e.xn--0ug; 璼𝨭.\u200C; [C1]; xn--gky8837e.xn--0ug; ; ; # 璼𝨭. +\u06698񂍽。-5🞥; \u06698񂍽.-5🞥; [B1, V3, V7]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥 +\u06698񂍽。-5🞥; \u06698񂍽.-5🞥; [B1, V3, V7]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥 +xn--8-qqc97891f.xn---5-rp92a; \u06698񂍽.-5🞥; [B1, V3, V7]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥 +\u200C.\u200C; ; [C1]; xn--0ug.xn--0ug; ; .; [A4_1, A4_2] # . +xn--0ug.xn--0ug; \u200C.\u200C; [C1]; xn--0ug.xn--0ug; ; ; # . +\u200D튛.\u0716; ; [B1, C2]; xn--1ug4441e.xn--gnb; ; xn--157b.xn--gnb; [] # 튛.ܖ +\u200D튛.\u0716; \u200D튛.\u0716; [B1, C2]; xn--1ug4441e.xn--gnb; ; xn--157b.xn--gnb; [] # 튛.ܖ +xn--157b.xn--gnb; 튛.\u0716; ; xn--157b.xn--gnb; ; ; # 튛.ܖ +튛.\u0716; ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ +튛.\u0716; 튛.\u0716; ; xn--157b.xn--gnb; ; ; # 튛.ܖ +xn--1ug4441e.xn--gnb; \u200D튛.\u0716; [B1, C2]; xn--1ug4441e.xn--gnb; ; ; # 튛.ܖ +ᡋ𐹰𞽳.\u0779ⴞ; ; [B2, B3, B5, B6, V7]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ +ᡋ𐹰𞽳.\u0779Ⴞ; ᡋ𐹰𞽳.\u0779ⴞ; [B2, B3, B5, B6, V7]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ +xn--b8e0417jocvf.xn--9pb883q; ᡋ𐹰𞽳.\u0779ⴞ; [B2, B3, B5, B6, V7]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ +xn--b8e0417jocvf.xn--9pb068b; ᡋ𐹰𞽳.\u0779Ⴞ; [B2, B3, B5, B6, V7]; xn--b8e0417jocvf.xn--9pb068b; ; ; # ᡋ𐹰.ݹႾ +𐷃\u0662𝅻𝟧.𐹮𐹬Ⴇ; 𐷃\u0662𝅻5.𐹮𐹬ⴇ; [B1, B4, V7]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ +𐷃\u0662𝅻5.𐹮𐹬Ⴇ; 𐷃\u0662𝅻5.𐹮𐹬ⴇ; [B1, B4, V7]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ +𐷃\u0662𝅻5.𐹮𐹬ⴇ; ; [B1, B4, V7]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ +xn--5-cqc8833rhv7f.xn--ykjz523efa; 𐷃\u0662𝅻5.𐹮𐹬ⴇ; [B1, B4, V7]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ +𐷃\u0662𝅻𝟧.𐹮𐹬ⴇ; 𐷃\u0662𝅻5.𐹮𐹬ⴇ; [B1, B4, V7]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ +xn--5-cqc8833rhv7f.xn--fnd3401kfa; 𐷃\u0662𝅻5.𐹮𐹬Ⴇ; [B1, B4, V7]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ +Ⴗ.\u05C2𑄴\uA9B7񘃨; ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +Ⴗ.𑄴\u05C2\uA9B7񘃨; ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +Ⴗ.𑄴\u05C2\uA9B7񘃨; ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +ⴗ.𑄴\u05C2\uA9B7񘃨; ; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +xn--flj.xn--qdb0605f14ycrms3c; ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +ⴗ.𑄴\u05C2\uA9B7񘃨; ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +ⴗ.\u05C2𑄴\uA9B7񘃨; ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ +xn--vnd.xn--qdb0605f14ycrms3c; Ⴗ.𑄴\u05C2\uA9B7񘃨; [V6, V7]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ +𝟾𾤘.򇕛\u066C; 8𾤘.򇕛\u066C; [B1, B5, B6, V7]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬ +8𾤘.򇕛\u066C; ; [B1, B5, B6, V7]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬ +xn--8-kh23b.xn--lib78461i; 8𾤘.򇕛\u066C; [B1, B5, B6, V7]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬ +⒈酫︒。\u08D6; ⒈酫︒.\u08D6; [V6, V7]; xn--tsh4490bfe8c.xn--8zb; ; ; # ⒈酫︒.ࣖ +1.酫。。\u08D6; 1.酫..\u08D6; [V6, X4_2]; 1.xn--8j4a..xn--8zb; [V6, A4_2]; ; # 1.酫..ࣖ +1.xn--8j4a..xn--8zb; 1.酫..\u08D6; [V6, X4_2]; 1.xn--8j4a..xn--8zb; [V6, A4_2]; ; # 1.酫..ࣖ +xn--tsh4490bfe8c.xn--8zb; ⒈酫︒.\u08D6; [V6, V7]; xn--tsh4490bfe8c.xn--8zb; ; ; # ⒈酫︒.ࣖ +\u2DE3\u200C≮\u1A6B.\u200C\u0E3A; ; [C1, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; xn--uof548an0j.xn--o4c; [V6] # ⷣ≮ᩫ.ฺ +\u2DE3\u200C<\u0338\u1A6B.\u200C\u0E3A; \u2DE3\u200C≮\u1A6B.\u200C\u0E3A; [C1, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; xn--uof548an0j.xn--o4c; [V6] # ⷣ≮ᩫ.ฺ +xn--uof548an0j.xn--o4c; \u2DE3≮\u1A6B.\u0E3A; [V6]; xn--uof548an0j.xn--o4c; ; ; # ⷣ≮ᩫ.ฺ +xn--uof63xk4bf3s.xn--o4c732g; \u2DE3\u200C≮\u1A6B.\u200C\u0E3A; [C1, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; ; # ⷣ≮ᩫ.ฺ +𞪂。ႷႽ¹\u200D; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [V7] # .ⴗⴝ1 +𞪂。ႷႽ1\u200D; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [V7] # .ⴗⴝ1 +𞪂。ⴗⴝ1\u200D; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [V7] # .ⴗⴝ1 +𞪂。Ⴗⴝ1\u200D; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [V7] # .ⴗⴝ1 +xn--co6h.xn--1-kwssa; 𞪂.ⴗⴝ1; [V7]; xn--co6h.xn--1-kwssa; ; ; # .ⴗⴝ1 +xn--co6h.xn--1-ugn710dya; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; ; # .ⴗⴝ1 +𞪂。ⴗⴝ¹\u200D; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [V7] # .ⴗⴝ1 +𞪂。Ⴗⴝ¹\u200D; 𞪂.ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [V7] # .ⴗⴝ1 +xn--co6h.xn--1-h1g429s; 𞪂.Ⴗⴝ1; [V7]; xn--co6h.xn--1-h1g429s; ; ; # .Ⴗⴝ1 +xn--co6h.xn--1-h1g398iewm; 𞪂.Ⴗⴝ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-h1g398iewm; ; ; # .Ⴗⴝ1 +xn--co6h.xn--1-h1gs; 𞪂.ႷႽ1; [V7]; xn--co6h.xn--1-h1gs; ; ; # .ႷႽ1 +xn--co6h.xn--1-h1gs597m; 𞪂.ႷႽ1\u200D; [B6, C2, V7]; xn--co6h.xn--1-h1gs597m; ; ; # .ႷႽ1 +𑄴𑄳2.𞳿󠀳-; ; [B1, B3, V3, V6, V7]; xn--2-h87ic.xn----s39r33498d; ; ; # 𑄴𑄳2.- +xn--2-h87ic.xn----s39r33498d; 𑄴𑄳2.𞳿󠀳-; [B1, B3, V3, V6, V7]; xn--2-h87ic.xn----s39r33498d; ; ; # 𑄴𑄳2.- +󠕲󟶶\u0665。񀁁𑄳𞤃\u0710; 󠕲󟶶\u0665.񀁁𑄳𞤥\u0710; [B1, B5, B6, V7]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ +󠕲󟶶\u0665。񀁁𑄳𞤃\u0710; 󠕲󟶶\u0665.񀁁𑄳𞤥\u0710; [B1, B5, B6, V7]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ +󠕲󟶶\u0665。񀁁𑄳𞤥\u0710; 󠕲󟶶\u0665.񀁁𑄳𞤥\u0710; [B1, B5, B6, V7]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ +xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; 󠕲󟶶\u0665.񀁁𑄳𞤥\u0710; [B1, B5, B6, V7]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ +󠕲󟶶\u0665。񀁁𑄳𞤥\u0710; 󠕲󟶶\u0665.񀁁𑄳𞤥\u0710; [B1, B5, B6, V7]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ +\u0720򲠽𐹢\u17BB。ςᢈ🝭\u200C; \u0720򲠽𐹢\u17BB.ςᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, V7] # ܠ𐹢ុ.ςᢈ🝭 +\u0720򲠽𐹢\u17BB。ςᢈ🝭\u200C; \u0720򲠽𐹢\u17BB.ςᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, V7] # ܠ𐹢ុ.ςᢈ🝭 +\u0720򲠽𐹢\u17BB。Σᢈ🝭\u200C; \u0720򲠽𐹢\u17BB.σᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, V7] # ܠ𐹢ុ.σᢈ🝭 +\u0720򲠽𐹢\u17BB。σᢈ🝭\u200C; \u0720򲠽𐹢\u17BB.σᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, V7] # ܠ𐹢ុ.σᢈ🝭 +xn--qnb616fis0qzt36f.xn--4xa847hli46a; \u0720򲠽𐹢\u17BB.σᢈ🝭; [B2, B6, V7]; xn--qnb616fis0qzt36f.xn--4xa847hli46a; ; ; # ܠ𐹢ុ.σᢈ🝭 +xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; \u0720򲠽𐹢\u17BB.σᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; ; # ܠ𐹢ុ.σᢈ🝭 +xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; \u0720򲠽𐹢\u17BB.ςᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; ; # ܠ𐹢ុ.ςᢈ🝭 +\u0720򲠽𐹢\u17BB。Σᢈ🝭\u200C; \u0720򲠽𐹢\u17BB.σᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, V7] # ܠ𐹢ុ.σᢈ🝭 +\u0720򲠽𐹢\u17BB。σᢈ🝭\u200C; \u0720򲠽𐹢\u17BB.σᢈ🝭\u200C; [B2, B6, C1, V7]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, V7] # ܠ𐹢ុ.σᢈ🝭 +\u200D--≮。𐹧; \u200D--≮.𐹧; [B1, C2]; xn-----l1tz1k.xn--fo0d; ; xn-----ujv.xn--fo0d; [B1, V3] # --≮.𐹧 +\u200D--<\u0338。𐹧; \u200D--≮.𐹧; [B1, C2]; xn-----l1tz1k.xn--fo0d; ; xn-----ujv.xn--fo0d; [B1, V3] # --≮.𐹧 +xn-----ujv.xn--fo0d; --≮.𐹧; [B1, V3]; xn-----ujv.xn--fo0d; ; ; # --≮.𐹧 +xn-----l1tz1k.xn--fo0d; \u200D--≮.𐹧; [B1, C2]; xn-----l1tz1k.xn--fo0d; ; ; # --≮.𐹧 +\uA806。𻚏\u0FB0⒕; \uA806.𻚏\u0FB0⒕; [V6, V7]; xn--l98a.xn--dgd218hhp28d; ; ; # ꠆.ྰ⒕ +\uA806。𻚏\u0FB014.; \uA806.𻚏\u0FB014.; [V6, V7]; xn--l98a.xn--14-jsj57880f.; [V6, V7, A4_2]; ; # ꠆.ྰ14. +xn--l98a.xn--14-jsj57880f.; \uA806.𻚏\u0FB014.; [V6, V7]; xn--l98a.xn--14-jsj57880f.; [V6, V7, A4_2]; ; # ꠆.ྰ14. +xn--l98a.xn--dgd218hhp28d; \uA806.𻚏\u0FB0⒕; [V6, V7]; xn--l98a.xn--dgd218hhp28d; ; ; # ꠆.ྰ⒕ +򮉂\u06BC.𑆺\u0669; 򮉂\u06BC.𑆺\u0669; [B1, B5, B6, V6, V7]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩ +򮉂\u06BC.𑆺\u0669; ; [B1, B5, B6, V6, V7]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩ +xn--vkb92243l.xn--iib9797k; 򮉂\u06BC.𑆺\u0669; [B1, B5, B6, V6, V7]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩ +󠁎\u06D0-。𞤴; 󠁎\u06D0-.𞤴; [B1, V3, V7]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴 +󠁎\u06D0-。𞤒; 󠁎\u06D0-.𞤴; [B1, V3, V7]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴 +xn----mwc72685y.xn--se6h; 󠁎\u06D0-.𞤴; [B1, V3, V7]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴 +𝟠4󠇗𝈻.\u200D𐋵⛧\u200D; 84𝈻.\u200D𐋵⛧\u200D; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; xn--84-s850a.xn--59h6326e; [] # 84𝈻.𐋵⛧ +84󠇗𝈻.\u200D𐋵⛧\u200D; 84𝈻.\u200D𐋵⛧\u200D; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; xn--84-s850a.xn--59h6326e; [] # 84𝈻.𐋵⛧ +xn--84-s850a.xn--59h6326e; 84𝈻.𐋵⛧; ; xn--84-s850a.xn--59h6326e; ; ; # 84𝈻.𐋵⛧ +84𝈻.𐋵⛧; ; ; xn--84-s850a.xn--59h6326e; ; ; # 84𝈻.𐋵⛧ +xn--84-s850a.xn--1uga573cfq1w; 84𝈻.\u200D𐋵⛧\u200D; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; ; # 84𝈻.𐋵⛧ +-\u0601。ᡪ; -\u0601.ᡪ; [B1, V3, V7]; xn----tkc.xn--68e; ; ; # -.ᡪ +-\u0601。ᡪ; -\u0601.ᡪ; [B1, V3, V7]; xn----tkc.xn--68e; ; ; # -.ᡪ +xn----tkc.xn--68e; -\u0601.ᡪ; [B1, V3, V7]; xn----tkc.xn--68e; ; ; # -.ᡪ +≮𝟕.謖ß≯; ≮7.謖ß≯; ; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯ +<\u0338𝟕.謖ß>\u0338; ≮7.謖ß≯; ; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯ +≮7.謖ß≯; ; ; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯ +<\u03387.謖ß>\u0338; ≮7.謖ß≯; ; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯ +<\u03387.謖SS>\u0338; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +≮7.謖SS≯; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +≮7.謖ss≯; ; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +<\u03387.謖ss>\u0338; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +<\u03387.謖Ss>\u0338; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +≮7.謖Ss≯; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +xn--7-mgo.xn--ss-xjvv174c; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +xn--7-mgo.xn--zca892oly5e; ≮7.謖ß≯; ; xn--7-mgo.xn--zca892oly5e; ; ; # ≮7.謖ß≯ +<\u0338𝟕.謖SS>\u0338; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +≮𝟕.謖SS≯; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +≮𝟕.謖ss≯; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +<\u0338𝟕.謖ss>\u0338; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +<\u0338𝟕.謖Ss>\u0338; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +≮𝟕.謖Ss≯; ≮7.謖ss≯; ; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯ +朶Ⴉ𞪡.𝨽\u0825📻-; 朶ⴉ𞪡.𝨽\u0825📻-; [B1, B5, B6, V3, V6, V7]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻- +朶ⴉ𞪡.𝨽\u0825📻-; ; [B1, B5, B6, V3, V6, V7]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻- +xn--0kjz47pd57t.xn----3gd37096apmwa; 朶ⴉ𞪡.𝨽\u0825📻-; [B1, B5, B6, V3, V6, V7]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻- +xn--hnd7245bd56p.xn----3gd37096apmwa; 朶Ⴉ𞪡.𝨽\u0825📻-; [B1, B5, B6, V3, V6, V7]; xn--hnd7245bd56p.xn----3gd37096apmwa; ; ; # 朶Ⴉ.𝨽ࠥ📻- +𐤎。󑿰\u200C≮\u200D; 𐤎.󑿰\u200C≮\u200D; [B6, C1, C2, V7]; xn--bk9c.xn--0ugc04p2u638c; ; xn--bk9c.xn--gdhx6802k; [B6, V7] # 𐤎.≮ +𐤎。󑿰\u200C<\u0338\u200D; 𐤎.󑿰\u200C≮\u200D; [B6, C1, C2, V7]; xn--bk9c.xn--0ugc04p2u638c; ; xn--bk9c.xn--gdhx6802k; [B6, V7] # 𐤎.≮ +xn--bk9c.xn--gdhx6802k; 𐤎.󑿰≮; [B6, V7]; xn--bk9c.xn--gdhx6802k; ; ; # 𐤎.≮ +xn--bk9c.xn--0ugc04p2u638c; 𐤎.󑿰\u200C≮\u200D; [B6, C1, C2, V7]; xn--bk9c.xn--0ugc04p2u638c; ; ; # 𐤎.≮ +񭜎⒈。\u200C𝟤; 񭜎⒈.\u200C2; [C1, V7]; xn--tsh94183d.xn--2-rgn; ; xn--tsh94183d.2; [V7] # ⒈.2 +񭜎1.。\u200C2; 񭜎1..\u200C2; [C1, V7, X4_2]; xn--1-ex54e..xn--2-rgn; [C1, V7, A4_2]; xn--1-ex54e..2; [V7, A4_2] # 1..2 +xn--1-ex54e..c; 񭜎1..c; [V7, X4_2]; xn--1-ex54e..c; [V7, A4_2]; ; # 1..c +xn--1-ex54e..xn--2-rgn; 񭜎1..\u200C2; [C1, V7, X4_2]; xn--1-ex54e..xn--2-rgn; [C1, V7, A4_2]; ; # 1..2 +xn--tsh94183d.c; 񭜎⒈.c; [V7]; xn--tsh94183d.c; ; ; # ⒈.c +xn--tsh94183d.xn--2-rgn; 񭜎⒈.\u200C2; [C1, V7]; xn--tsh94183d.xn--2-rgn; ; ; # ⒈.2 +󠟊𐹤\u200D.𐹳󙄵𐹶; 󠟊𐹤\u200D.𐹳󙄵𐹶; [B1, C2, V7]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; xn--co0d98977c.xn--ro0dga22807v; [B1, V7] # 𐹤.𐹳𐹶 +󠟊𐹤\u200D.𐹳󙄵𐹶; ; [B1, C2, V7]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; xn--co0d98977c.xn--ro0dga22807v; [B1, V7] # 𐹤.𐹳𐹶 +xn--co0d98977c.xn--ro0dga22807v; 󠟊𐹤.𐹳󙄵𐹶; [B1, V7]; xn--co0d98977c.xn--ro0dga22807v; ; ; # 𐹤.𐹳𐹶 +xn--1ugy994g7k93g.xn--ro0dga22807v; 󠟊𐹤\u200D.𐹳󙄵𐹶; [B1, C2, V7]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; ; # 𐹤.𐹳𐹶 +𞤴𐹻𑓂𐭝.\u094D\uFE07􉛯; 𞤴𐹻𑓂𐭝.\u094D􉛯; [B1, V6, V7]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.् +𞤴𐹻𑓂𐭝.\u094D\uFE07􉛯; 𞤴𐹻𑓂𐭝.\u094D􉛯; [B1, V6, V7]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.् +𞤒𐹻𑓂𐭝.\u094D\uFE07􉛯; 𞤴𐹻𑓂𐭝.\u094D􉛯; [B1, V6, V7]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.् +xn--609c96c09grp2w.xn--n3b28708s; 𞤴𐹻𑓂𐭝.\u094D􉛯; [B1, V6, V7]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.् +𞤒𐹻𑓂𐭝.\u094D\uFE07􉛯; 𞤴𐹻𑓂𐭝.\u094D􉛯; [B1, V6, V7]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.् +\u0668。𐹠𐹽񗮶; \u0668.𐹠𐹽񗮶; [B1, V7]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽 +\u0668。𐹠𐹽񗮶; \u0668.𐹠𐹽񗮶; [B1, V7]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽 +xn--hib.xn--7n0d2bu9196b; \u0668.𐹠𐹽񗮶; [B1, V7]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽 +\u1160񍀜.8򶾵\u069C; 񍀜.8򶾵\u069C; [B1, V7]; xn--mn1x.xn--8-otc61545t; ; ; # .8ڜ +xn--mn1x.xn--8-otc61545t; 񍀜.8򶾵\u069C; [B1, V7]; xn--mn1x.xn--8-otc61545t; ; ; # .8ڜ +xn--psd85033d.xn--8-otc61545t; \u1160񍀜.8򶾵\u069C; [B1, V7]; xn--psd85033d.xn--8-otc61545t; ; ; # .8ڜ +\u200D\u200C󠆪。ß𑓃; \u200D\u200C.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; .xn--ss-bh7o; [A4_2] # .ß𑓃 +\u200D\u200C󠆪。ß𑓃; \u200D\u200C.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; .xn--ss-bh7o; [A4_2] # .ß𑓃 +\u200D\u200C󠆪。SS𑓃; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃 +\u200D\u200C󠆪。ss𑓃; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃 +\u200D\u200C󠆪。Ss𑓃; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃 +.xn--ss-bh7o; .ss𑓃; [X4_2]; .xn--ss-bh7o; [A4_2]; ; # .ss𑓃 +xn--0ugb.xn--ss-bh7o; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; ; # .ss𑓃 +xn--0ugb.xn--zca0732l; \u200D\u200C.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; ; # .ß𑓃 +\u200D\u200C󠆪。SS𑓃; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃 +\u200D\u200C󠆪。ss𑓃; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃 +\u200D\u200C󠆪。Ss𑓃; \u200D\u200C.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃 +xn--ss-bh7o; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃 +ss𑓃; ; ; xn--ss-bh7o; ; ; # ss𑓃 +SS𑓃; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃 +Ss𑓃; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃 +︒\u200Cヶ䒩.ꡪ; ; [C1, V7]; xn--0ug287dj0or48o.xn--gd9a; ; xn--qekw60dns9k.xn--gd9a; [V7] # ︒ヶ䒩.ꡪ +。\u200Cヶ䒩.ꡪ; .\u200Cヶ䒩.ꡪ; [C1, X4_2]; .xn--0ug287dj0o.xn--gd9a; [C1, A4_2]; .xn--qekw60d.xn--gd9a; [A4_2] # .ヶ䒩.ꡪ +.xn--qekw60d.xn--gd9a; .ヶ䒩.ꡪ; [X4_2]; .xn--qekw60d.xn--gd9a; [A4_2]; ; # .ヶ䒩.ꡪ +.xn--0ug287dj0o.xn--gd9a; .\u200Cヶ䒩.ꡪ; [C1, X4_2]; .xn--0ug287dj0o.xn--gd9a; [C1, A4_2]; ; # .ヶ䒩.ꡪ +xn--qekw60dns9k.xn--gd9a; ︒ヶ䒩.ꡪ; [V7]; xn--qekw60dns9k.xn--gd9a; ; ; # ︒ヶ䒩.ꡪ +xn--0ug287dj0or48o.xn--gd9a; ︒\u200Cヶ䒩.ꡪ; [C1, V7]; xn--0ug287dj0or48o.xn--gd9a; ; ; # ︒ヶ䒩.ꡪ +xn--qekw60d.xn--gd9a; ヶ䒩.ꡪ; ; xn--qekw60d.xn--gd9a; ; ; # ヶ䒩.ꡪ +ヶ䒩.ꡪ; ; ; xn--qekw60d.xn--gd9a; ; ; # ヶ䒩.ꡪ +\u200C⒈𤮍.󢓋\u1A60; ; [C1, V7]; xn--0ug88o7471d.xn--jof45148n; ; xn--tshw462r.xn--jof45148n; [V7] # ⒈𤮍.᩠ +\u200C1.𤮍.󢓋\u1A60; ; [C1, V7]; xn--1-rgn.xn--4x6j.xn--jof45148n; ; 1.xn--4x6j.xn--jof45148n; [V7] # 1.𤮍.᩠ +1.xn--4x6j.xn--jof45148n; 1.𤮍.󢓋\u1A60; [V7]; 1.xn--4x6j.xn--jof45148n; ; ; # 1.𤮍.᩠ +xn--1-rgn.xn--4x6j.xn--jof45148n; \u200C1.𤮍.󢓋\u1A60; [C1, V7]; xn--1-rgn.xn--4x6j.xn--jof45148n; ; ; # 1.𤮍.᩠ +xn--tshw462r.xn--jof45148n; ⒈𤮍.󢓋\u1A60; [V7]; xn--tshw462r.xn--jof45148n; ; ; # ⒈𤮍.᩠ +xn--0ug88o7471d.xn--jof45148n; \u200C⒈𤮍.󢓋\u1A60; [C1, V7]; xn--0ug88o7471d.xn--jof45148n; ; ; # ⒈𤮍.᩠ +⒈\u200C𐫓󠀺。\u1A60񤰵\u200D; ⒈\u200C𐫓󠀺.\u1A60񤰵\u200D; [B1, C1, C2, V6, V7]; xn--0ug78ol75wzcx4i.xn--jof95xex98m; ; xn--tsh4435fk263g.xn--jofz5294e; [B1, V6, V7] # ⒈𐫓.᩠ +1.\u200C𐫓󠀺。\u1A60񤰵\u200D; 1.\u200C𐫓󠀺.\u1A60񤰵\u200D; [B1, C1, C2, V6, V7]; 1.xn--0ug8853gk263g.xn--jof95xex98m; ; 1.xn--8w9c40377c.xn--jofz5294e; [B1, B3, V6, V7] # 1.𐫓.᩠ +1.xn--8w9c40377c.xn--jofz5294e; 1.𐫓󠀺.\u1A60񤰵; [B1, B3, V6, V7]; 1.xn--8w9c40377c.xn--jofz5294e; ; ; # 1.𐫓.᩠ +1.xn--0ug8853gk263g.xn--jof95xex98m; 1.\u200C𐫓󠀺.\u1A60񤰵\u200D; [B1, C1, C2, V6, V7]; 1.xn--0ug8853gk263g.xn--jof95xex98m; ; ; # 1.𐫓.᩠ +xn--tsh4435fk263g.xn--jofz5294e; ⒈𐫓󠀺.\u1A60񤰵; [B1, V6, V7]; xn--tsh4435fk263g.xn--jofz5294e; ; ; # ⒈𐫓.᩠ +xn--0ug78ol75wzcx4i.xn--jof95xex98m; ⒈\u200C𐫓󠀺.\u1A60񤰵\u200D; [B1, C1, C2, V6, V7]; xn--0ug78ol75wzcx4i.xn--jof95xex98m; ; ; # ⒈𐫓.᩠ +𝅵。𝟫𞀈䬺⒈; .9𞀈䬺⒈; [V7, X4_2]; .xn--9-ecp936non25a; [V7, A4_2]; ; # .9𞀈䬺⒈ +𝅵。9𞀈䬺1.; .9𞀈䬺1.; [X4_2]; .xn--91-030c1650n.; [A4_2]; ; # .9𞀈䬺1. +.xn--91-030c1650n.; .9𞀈䬺1.; [X4_2]; .xn--91-030c1650n.; [A4_2]; ; # .9𞀈䬺1. +.xn--9-ecp936non25a; .9𞀈䬺⒈; [V7, X4_2]; .xn--9-ecp936non25a; [V7, A4_2]; ; # .9𞀈䬺⒈ +xn--3f1h.xn--91-030c1650n.; 𝅵.9𞀈䬺1.; [V7]; xn--3f1h.xn--91-030c1650n.; [V7, A4_2]; ; # .9𞀈䬺1. +xn--3f1h.xn--9-ecp936non25a; 𝅵.9𞀈䬺⒈; [V7]; xn--3f1h.xn--9-ecp936non25a; ; ; # .9𞀈䬺⒈ +򡼺≯。盚\u0635; 򡼺≯.盚\u0635; [B5, B6, V7]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص +򡼺>\u0338。盚\u0635; 򡼺≯.盚\u0635; [B5, B6, V7]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص +xn--hdh30181h.xn--0gb7878c; 򡼺≯.盚\u0635; [B5, B6, V7]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص +-񿰭\u05B4。-󠁊𐢸≯; -񿰭\u05B4.-󠁊𐢸≯; [B1, V3, V7]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯ +-񿰭\u05B4。-󠁊𐢸>\u0338; -񿰭\u05B4.-󠁊𐢸≯; [B1, V3, V7]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯ +xn----fgc06667m.xn----pgoy615he5y4i; -񿰭\u05B4.-󠁊𐢸≯; [B1, V3, V7]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯ +󿭓\u1B44\u200C\u0A4D.𐭛񳋔; 󿭓\u1B44\u200C\u0A4D.𐭛񳋔; [B2, B3, B6, V7]; xn--ybc997f6rd2n772c.xn--409c6100y; ; xn--ybc997fb5881a.xn--409c6100y; [B2, B3, V7] # ᭄੍.𐭛 +󿭓\u1B44\u200C\u0A4D.𐭛񳋔; ; [B2, B3, B6, V7]; xn--ybc997f6rd2n772c.xn--409c6100y; ; xn--ybc997fb5881a.xn--409c6100y; [B2, B3, V7] # ᭄੍.𐭛 +xn--ybc997fb5881a.xn--409c6100y; 󿭓\u1B44\u0A4D.𐭛񳋔; [B2, B3, V7]; xn--ybc997fb5881a.xn--409c6100y; ; ; # ᭄੍.𐭛 +xn--ybc997f6rd2n772c.xn--409c6100y; 󿭓\u1B44\u200C\u0A4D.𐭛񳋔; [B2, B3, B6, V7]; xn--ybc997f6rd2n772c.xn--409c6100y; ; ; # ᭄੍.𐭛 +⾇.\u067D𞤴\u06BB\u200D; 舛.\u067D𞤴\u06BB\u200D; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ +舛.\u067D𞤴\u06BB\u200D; ; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ +舛.\u067D𞤒\u06BB\u200D; 舛.\u067D𞤴\u06BB\u200D; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ +xn--8c1a.xn--2ib8jn539l; 舛.\u067D𞤴\u06BB; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ +舛.\u067D𞤴\u06BB; ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ +舛.\u067D𞤒\u06BB; 舛.\u067D𞤴\u06BB; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ +xn--8c1a.xn--2ib8jv19e6413b; 舛.\u067D𞤴\u06BB\u200D; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; ; # 舛.ٽ𞤴ڻ +⾇.\u067D𞤒\u06BB\u200D; 舛.\u067D𞤴\u06BB\u200D; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ +4򭆥。\u0767≯; 4򭆥.\u0767≯; [B1, B3, V7]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯ +4򭆥。\u0767>\u0338; 4򭆥.\u0767≯; [B1, B3, V7]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯ +xn--4-xn17i.xn--rpb459k; 4򭆥.\u0767≯; [B1, B3, V7]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯ +𲔏𞫨񺿂硲.\u06AD; 𲔏𞫨񺿂硲.\u06AD; [B5, V7]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ +𲔏𞫨񺿂硲.\u06AD; ; [B5, V7]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ +xn--lcz1610fn78gk609a.xn--gkb; 𲔏𞫨񺿂硲.\u06AD; [B5, V7]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ +\u200C.\uFE08\u0666Ⴆ℮; \u200C.\u0666ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; .xn--fib628k4li; [B1, A4_2] # .٦ⴆ℮ +\u200C.\uFE08\u0666ⴆ℮; \u200C.\u0666ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; .xn--fib628k4li; [B1, A4_2] # .٦ⴆ℮ +.xn--fib628k4li; .\u0666ⴆ℮; [B1, X4_2]; .xn--fib628k4li; [B1, A4_2]; ; # .٦ⴆ℮ +xn--0ug.xn--fib628k4li; \u200C.\u0666ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; ; # .٦ⴆ℮ +.xn--fib263c0yn; .\u0666Ⴆ℮; [B1, V7, X4_2]; .xn--fib263c0yn; [B1, V7, A4_2]; ; # .٦Ⴆ℮ +xn--0ug.xn--fib263c0yn; \u200C.\u0666Ⴆ℮; [B1, C1, V7]; xn--0ug.xn--fib263c0yn; ; ; # .٦Ⴆ℮ +\u06A3.\u0D4D\u200DϞ; \u06A3.\u0D4D\u200Dϟ; [B1, V6]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ +\u06A3.\u0D4D\u200DϞ; \u06A3.\u0D4D\u200Dϟ; [B1, V6]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ +\u06A3.\u0D4D\u200Dϟ; ; [B1, V6]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ +xn--5jb.xn--xya149b; \u06A3.\u0D4Dϟ; [B1, V6]; xn--5jb.xn--xya149b; ; ; # ڣ.്ϟ +xn--5jb.xn--xya149bpvp; \u06A3.\u0D4D\u200Dϟ; [B1, V6]; xn--5jb.xn--xya149bpvp; ; ; # ڣ.്ϟ +\u06A3.\u0D4D\u200Dϟ; \u06A3.\u0D4D\u200Dϟ; [B1, V6]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ +\u200C𞸇𑘿。\u0623𐮂-腍; \u200C\u062D𑘿.\u0623𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍 +\u200C𞸇𑘿。\u0627\u0654𐮂-腍; \u200C\u062D𑘿.\u0623𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍 +\u200C\u062D𑘿。\u0623𐮂-腍; \u200C\u062D𑘿.\u0623𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍 +\u200C\u062D𑘿。\u0627\u0654𐮂-腍; \u200C\u062D𑘿.\u0623𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍 +xn--sgb4140l.xn----qmc5075grs9e; \u062D𑘿.\u0623𐮂-腍; [B2, B3]; xn--sgb4140l.xn----qmc5075grs9e; ; ; # ح𑘿.أ𐮂-腍 +xn--sgb953kmi8o.xn----qmc5075grs9e; \u200C\u062D𑘿.\u0623𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; ; # ح𑘿.أ𐮂-腍 +-򭷙\u066B纛。𝟛񭤇🄅; -򭷙\u066B纛.3񭤇4,; [B1, V3, V7, U1]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34, +-򭷙\u066B纛。3񭤇4,; -򭷙\u066B纛.3񭤇4,; [B1, V3, V7, U1]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34, +xn----vqc8143g0tt4i.xn--34,-8787l; -򭷙\u066B纛.3񭤇4,; [B1, V3, V7, U1]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34, +xn----vqc8143g0tt4i.xn--3-os1sn476y; -򭷙\u066B纛.3񭤇🄅; [B1, V3, V7]; xn----vqc8143g0tt4i.xn--3-os1sn476y; ; ; # -٫纛.3🄅 +🔔.Ⴂ\u07CC\u0BCD𐋮; 🔔.ⴂ\u07CC\u0BCD𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮 +🔔.Ⴂ\u07CC\u0BCD𐋮; 🔔.ⴂ\u07CC\u0BCD𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮 +🔔.ⴂ\u07CC\u0BCD𐋮; ; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮 +xn--nv8h.xn--nsb46rvz1b222p; 🔔.ⴂ\u07CC\u0BCD𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮 +🔔.ⴂ\u07CC\u0BCD𐋮; 🔔.ⴂ\u07CC\u0BCD𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮 +xn--nv8h.xn--nsb46r83e8112a; 🔔.Ⴂ\u07CC\u0BCD𐋮; [B1, B5, V7]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮 +軥\u06B3.-𖬵; ; [B1, B5, B6, V3]; xn--mkb5480e.xn----6u5m; ; ; # 軥ڳ.-𖬵 +xn--mkb5480e.xn----6u5m; 軥\u06B3.-𖬵; [B1, B5, B6, V3]; xn--mkb5480e.xn----6u5m; ; ; # 軥ڳ.-𖬵 +𐹤\u07CA\u06B6.𐨂-; ; [B1, V3, V6]; xn--pkb56cn614d.xn----974i; ; ; # 𐹤ߊڶ.𐨂- +xn--pkb56cn614d.xn----974i; 𐹤\u07CA\u06B6.𐨂-; [B1, V3, V6]; xn--pkb56cn614d.xn----974i; ; ; # 𐹤ߊڶ.𐨂- +-󠅱0。\u17CF\u1DFD톇십; -0.\u17CF\u1DFD톇십; [V3, V6]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십 +-󠅱0。\u17CF\u1DFD톇십; -0.\u17CF\u1DFD톇십; [V3, V6]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십 +-󠅱0。\u17CF\u1DFD톇십; -0.\u17CF\u1DFD톇십; [V3, V6]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십 +-󠅱0。\u17CF\u1DFD톇십; -0.\u17CF\u1DFD톇십; [V3, V6]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십 +-0.xn--r4e872ah77nghm; -0.\u17CF\u1DFD톇십; [V3, V6]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십 +ꡰ︒--。\u17CC靈𐹢񘳮; ꡰ︒--.\u17CC靈𐹢񘳮; [B1, B6, V2, V3, V6, V7]; xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ; ; # ꡰ︒--.៌靈𐹢 +ꡰ。--。\u17CC靈𐹢񘳮; ꡰ.--.\u17CC靈𐹢񘳮; [B1, V3, V6, V7]; xn--md9a.--.xn--o4e6836dpxudz0v1c; ; ; # ꡰ.--.៌靈𐹢 +xn--md9a.--.xn--o4e6836dpxudz0v1c; ꡰ.--.\u17CC靈𐹢񘳮; [B1, V3, V6, V7]; xn--md9a.--.xn--o4e6836dpxudz0v1c; ; ; # ꡰ.--.៌靈𐹢 +xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ꡰ︒--.\u17CC靈𐹢񘳮; [B1, B6, V2, V3, V6, V7]; xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ; ; # ꡰ︒--.៌靈𐹢 +\u115FႿႵრ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +\u115FႿႵრ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +\u115Fⴟⴕრ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +\u115FႿႵᲠ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +xn--1od555l3a.xn--9ic; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +\u115Fⴟⴕრ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +\u115FႿႵᲠ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +xn--tndt4hvw.xn--9ic; \u115FႿႵრ.\u0B4D; [V6, V7]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍ +xn--1od7wz74eeb.xn--9ic; \u115Fⴟⴕრ.\u0B4D; [V6, V7]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍ +\u115FႿⴕრ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +xn--3nd0etsm92g.xn--9ic; \u115FႿⴕრ.\u0B4D; [V6, V7]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍ +\u115FႿⴕრ。\u0B4D; ⴟⴕრ.\u0B4D; [V6]; xn--1od555l3a.xn--9ic; ; ; # ⴟⴕრ.୍ +🄃𐹠.\u0664󠅇; 2,𐹠.\u0664; [B1, U1]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤ +2,𐹠.\u0664󠅇; 2,𐹠.\u0664; [B1, U1]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤ +xn--2,-5g3o.xn--dib; 2,𐹠.\u0664; [B1, U1]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤ +xn--7n0d1189a.xn--dib; 🄃𐹠.\u0664; [B1, V7]; xn--7n0d1189a.xn--dib; ; ; # 🄃𐹠.٤ +򻲼\u200C\uFC5B.\u07D2\u0848\u1BF3; 򻲼\u200C\u0630\u0670.\u07D2\u0848\u1BF3; [B2, B3, B5, B6, C1, V7]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; xn--vgb2kp1223g.xn--tsb0vz43c; [B2, B3, B5, B6, V7] # ذٰ.ߒࡈ᯳ +򻲼\u200C\u0630\u0670.\u07D2\u0848\u1BF3; ; [B2, B3, B5, B6, C1, V7]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; xn--vgb2kp1223g.xn--tsb0vz43c; [B2, B3, B5, B6, V7] # ذٰ.ߒࡈ᯳ +xn--vgb2kp1223g.xn--tsb0vz43c; 򻲼\u0630\u0670.\u07D2\u0848\u1BF3; [B2, B3, B5, B6, V7]; xn--vgb2kp1223g.xn--tsb0vz43c; ; ; # ذٰ.ߒࡈ᯳ +xn--vgb2kq00fl213y.xn--tsb0vz43c; 򻲼\u200C\u0630\u0670.\u07D2\u0848\u1BF3; [B2, B3, B5, B6, C1, V7]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; ; # ذٰ.ߒࡈ᯳ +\u200D\u200D𞵪\u200C。ᡘ𑲭\u17B5; \u200D\u200D𞵪\u200C.ᡘ𑲭; [B1, C1, C2, V7]; xn--0ugba05538b.xn--o8e4044k; ; xn--l96h.xn--o8e4044k; [V7] # .ᡘ𑲭 +xn--l96h.xn--o8e4044k; 𞵪.ᡘ𑲭; [V7]; xn--l96h.xn--o8e4044k; ; ; # .ᡘ𑲭 +xn--0ugba05538b.xn--o8e4044k; \u200D\u200D𞵪\u200C.ᡘ𑲭; [B1, C1, C2, V7]; xn--0ugba05538b.xn--o8e4044k; ; ; # .ᡘ𑲭 +xn--l96h.xn--03e93aq365d; 𞵪.ᡘ𑲭\u17B5; [V7]; xn--l96h.xn--03e93aq365d; ; ; # .ᡘ𑲭 +xn--0ugba05538b.xn--03e93aq365d; \u200D\u200D𞵪\u200C.ᡘ𑲭\u17B5; [B1, C1, C2, V7]; xn--0ugba05538b.xn--03e93aq365d; ; ; # .ᡘ𑲭 +𞷻。⚄񗑇𑁿; 𞷻.⚄񗑇𑁿; [B1, V7]; xn--qe7h.xn--c7h2966f7so4a; ; ; # .⚄𑁿 +xn--qe7h.xn--c7h2966f7so4a; 𞷻.⚄񗑇𑁿; [B1, V7]; xn--qe7h.xn--c7h2966f7so4a; ; ; # .⚄𑁿 +\uA8C4≠.𞠨\u0667; \uA8C4≠.𞠨\u0667; [B1, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧ +\uA8C4=\u0338.𞠨\u0667; \uA8C4≠.𞠨\u0667; [B1, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧ +\uA8C4≠.𞠨\u0667; ; [B1, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧ +\uA8C4=\u0338.𞠨\u0667; \uA8C4≠.𞠨\u0667; [B1, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧ +xn--1chy504c.xn--gib1777v; \uA8C4≠.𞠨\u0667; [B1, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧ +𝟛𝆪\uA8C4。\uA8EA-; 3\uA8C4𝆪.\uA8EA-; [V3, V6]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪- +𝟛\uA8C4𝆪。\uA8EA-; 3\uA8C4𝆪.\uA8EA-; [V3, V6]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪- +3\uA8C4𝆪。\uA8EA-; 3\uA8C4𝆪.\uA8EA-; [V3, V6]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪- +xn--3-sl4eu679e.xn----xn4e; 3\uA8C4𝆪.\uA8EA-; [V3, V6]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪- +\u075F\u1BA2\u103AႧ.e; \u075F\u1BA2\u103Aⴇ.e; [B2, B3]; xn--jpb846bjzj7pr.e; ; ; # ݟᮢ်ⴇ.e +\u075F\u1BA2\u103Aⴇ.e; ; [B2, B3]; xn--jpb846bjzj7pr.e; ; ; # ݟᮢ်ⴇ.e +\u075F\u1BA2\u103AႧ.E; \u075F\u1BA2\u103Aⴇ.e; [B2, B3]; xn--jpb846bjzj7pr.e; ; ; # ݟᮢ်ⴇ.e +xn--jpb846bjzj7pr.e; \u075F\u1BA2\u103Aⴇ.e; [B2, B3]; xn--jpb846bjzj7pr.e; ; ; # ݟᮢ်ⴇ.e +xn--jpb846bmjw88a.e; \u075F\u1BA2\u103AႧ.e; [B2, B3, V7]; xn--jpb846bmjw88a.e; ; ; # ݟᮢ်Ⴇ.e +ᄹ。\u0ECA򠯤󠄞; ᄹ.\u0ECA򠯤; [V6, V7]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊ +ᄹ。\u0ECA򠯤󠄞; ᄹ.\u0ECA򠯤; [V6, V7]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊ +xn--lrd.xn--s8c05302k; ᄹ.\u0ECA򠯤; [V6, V7]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊ +Ⴆ򻢩.󠆡\uFE09𞤍; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +Ⴆ򻢩.󠆡\uFE09𞤍; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +ⴆ򻢩.󠆡\uFE09𞤯; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +xn--xkjw3965g.xn--ne6h; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +ⴆ򻢩.󠆡\uFE09𞤯; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +xn--end82983m.xn--ne6h; Ⴆ򻢩.𞤯; [V7]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯 +ⴆ򻢩.󠆡\uFE09𞤍; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +ⴆ򻢩.󠆡\uFE09𞤍; ⴆ򻢩.𞤯; [V7]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯 +ß\u080B︒\u067B.帼F∬\u200C; ß\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, V7] # ßࠋ︒ٻ.帼f∫∫ +ß\u080B。\u067B.帼F∫∫\u200C; ß\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ßࠋ.ٻ.帼f∫∫ +ß\u080B。\u067B.帼f∫∫\u200C; ß\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ßࠋ.ٻ.帼f∫∫ +SS\u080B。\u067B.帼F∫∫\u200C; ss\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫ +ss\u080B。\u067B.帼f∫∫\u200C; ss\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫ +Ss\u080B。\u067B.帼F∫∫\u200C; ss\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫ +xn--ss-uze.xn--0ib.xn--f-tcoa9162d; ss\u080B.\u067B.帼f∫∫; [B5, B6]; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; ; ; # ssࠋ.ٻ.帼f∫∫ +xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ss\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; ; # ssࠋ.ٻ.帼f∫∫ +xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ß\u080B.\u067B.帼f∫∫\u200C; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; ; # ßࠋ.ٻ.帼f∫∫ +ß\u080B︒\u067B.帼f∬\u200C; ß\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, V7] # ßࠋ︒ٻ.帼f∫∫ +SS\u080B︒\u067B.帼F∬\u200C; ss\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, V7] # ssࠋ︒ٻ.帼f∫∫ +ss\u080B︒\u067B.帼f∬\u200C; ss\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, V7] # ssࠋ︒ٻ.帼f∫∫ +Ss\u080B︒\u067B.帼F∬\u200C; ss\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, V7] # ssࠋ︒ٻ.帼f∫∫ +xn--ss-k0d31nu121d.xn--f-tcoa9162d; ss\u080B︒\u067B.帼f∫∫; [B5, B6, V7]; xn--ss-k0d31nu121d.xn--f-tcoa9162d; ; ; # ssࠋ︒ٻ.帼f∫∫ +xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ss\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; ; # ssࠋ︒ٻ.帼f∫∫ +xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ß\u080B︒\u067B.帼f∫∫\u200C; [B5, B6, C1, V7]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; ; # ßࠋ︒ٻ.帼f∫∫ +󘪗。𐹴𞨌\u200D; 󘪗.𐹴𞨌\u200D; [B1, C2, V7]; xn--8l83e.xn--1ug4105gsxwf; ; xn--8l83e.xn--so0dw168a; [B1, V7] # .𐹴 +󘪗。𐹴𞨌\u200D; 󘪗.𐹴𞨌\u200D; [B1, C2, V7]; xn--8l83e.xn--1ug4105gsxwf; ; xn--8l83e.xn--so0dw168a; [B1, V7] # .𐹴 +xn--8l83e.xn--so0dw168a; 󘪗.𐹴𞨌; [B1, V7]; xn--8l83e.xn--so0dw168a; ; ; # .𐹴 +xn--8l83e.xn--1ug4105gsxwf; 󘪗.𐹴𞨌\u200D; [B1, C2, V7]; xn--8l83e.xn--1ug4105gsxwf; ; ; # .𐹴 +񗛨.򅟢𝟨\uA8C4; 񗛨.򅟢6\uA8C4; [V7]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄ +񗛨.򅟢6\uA8C4; ; [V7]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄ +xn--mi60a.xn--6-sl4es8023c; 񗛨.򅟢6\uA8C4; [V7]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄ +\u1AB2\uFD8E。-۹ႱႨ; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +\u1AB2\u0645\u062E\u062C。-۹ႱႨ; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +\u1AB2\u0645\u062E\u062C。-۹ⴑⴈ; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +xn--rgbd2e831i.xn----zyc3430a9a; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +\u1AB2\uFD8E。-۹ⴑⴈ; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +xn--rgbd2e831i.xn----zyc155e9a; \u1AB2\u0645\u062E\u062C.-۹ႱႨ; [B1, V3, V6, V7]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ +\u1AB2\u0645\u062E\u062C。-۹Ⴑⴈ; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +xn--rgbd2e831i.xn----zyc875efr3a; \u1AB2\u0645\u062E\u062C.-۹Ⴑⴈ; [B1, V3, V6, V7]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ +\u1AB2\uFD8E。-۹Ⴑⴈ; \u1AB2\u0645\u062E\u062C.-۹ⴑⴈ; [B1, V3, V6]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ +𞤤.-\u08A3︒; 𞤤.-\u08A3︒; [B1, V3, V7]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒ +𞤤.-\u08A3。; 𞤤.-\u08A3.; [B1, V3]; xn--ce6h.xn----cod.; [B1, V3, A4_2]; ; # 𞤤.-ࢣ. +𞤂.-\u08A3。; 𞤤.-\u08A3.; [B1, V3]; xn--ce6h.xn----cod.; [B1, V3, A4_2]; ; # 𞤤.-ࢣ. +xn--ce6h.xn----cod.; 𞤤.-\u08A3.; [B1, V3]; xn--ce6h.xn----cod.; [B1, V3, A4_2]; ; # 𞤤.-ࢣ. +𞤂.-\u08A3︒; 𞤤.-\u08A3︒; [B1, V3, V7]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒ +xn--ce6h.xn----cod7069p; 𞤤.-\u08A3︒; [B1, V3, V7]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒ +\u200C𐺨.\u0859--; ; [B1, C1, V3, V6]; xn--0ug7905g.xn-----h6e; ; xn--9p0d.xn-----h6e; [B1, V3, V6] # 𐺨.࡙-- +xn--9p0d.xn-----h6e; 𐺨.\u0859--; [B1, V3, V6]; xn--9p0d.xn-----h6e; ; ; # 𐺨.࡙-- +xn--0ug7905g.xn-----h6e; \u200C𐺨.\u0859--; [B1, C1, V3, V6]; xn--0ug7905g.xn-----h6e; ; ; # 𐺨.࡙-- +𐋸󮘋Ⴢ.Ⴁ; 𐋸󮘋ⴢ.ⴁ; [V7]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ +𐋸󮘋ⴢ.ⴁ; ; [V7]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ +𐋸󮘋Ⴢ.ⴁ; 𐋸󮘋ⴢ.ⴁ; [V7]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ +xn--qlj1559dr224h.xn--skj; 𐋸󮘋ⴢ.ⴁ; [V7]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ +xn--6nd5215jr2u0h.xn--skj; 𐋸󮘋Ⴢ.ⴁ; [V7]; xn--6nd5215jr2u0h.xn--skj; ; ; # 𐋸Ⴢ.ⴁ +xn--6nd5215jr2u0h.xn--8md; 𐋸󮘋Ⴢ.Ⴁ; [V7]; xn--6nd5215jr2u0h.xn--8md; ; ; # 𐋸Ⴢ.Ⴁ +񗑿\uA806₄򩞆。𲩧󠒹ς; 񗑿\uA8064򩞆.𲩧󠒹ς; [V7]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; # ꠆4.ς +񗑿\uA8064򩞆。𲩧󠒹ς; 񗑿\uA8064򩞆.𲩧󠒹ς; [V7]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; # ꠆4.ς +񗑿\uA8064򩞆。𲩧󠒹Σ; 񗑿\uA8064򩞆.𲩧󠒹σ; [V7]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ +񗑿\uA8064򩞆。𲩧󠒹σ; 񗑿\uA8064򩞆.𲩧󠒹σ; [V7]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ +xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; 񗑿\uA8064򩞆.𲩧󠒹σ; [V7]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ +xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; 񗑿\uA8064򩞆.𲩧󠒹ς; [V7]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; ; # ꠆4.ς +񗑿\uA806₄򩞆。𲩧󠒹Σ; 񗑿\uA8064򩞆.𲩧󠒹σ; [V7]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ +񗑿\uA806₄򩞆。𲩧󠒹σ; 񗑿\uA8064򩞆.𲩧󠒹σ; [V7]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ +󠆀\u0723。\u1DF4\u0775; \u0723.\u1DF4\u0775; [B1, V6]; xn--tnb.xn--5pb136i; ; ; # ܣ.ᷴݵ +xn--tnb.xn--5pb136i; \u0723.\u1DF4\u0775; [B1, V6]; xn--tnb.xn--5pb136i; ; ; # ܣ.ᷴݵ +𐹱\u0842𝪨。𬼖Ⴑ\u200D; 𐹱\u0842𝪨.𬼖ⴑ\u200D; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ +𐹱\u0842𝪨。𬼖Ⴑ\u200D; 𐹱\u0842𝪨.𬼖ⴑ\u200D; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ +𐹱\u0842𝪨。𬼖ⴑ\u200D; 𐹱\u0842𝪨.𬼖ⴑ\u200D; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ +xn--0vb1535kdb6e.xn--8kjz186s; 𐹱\u0842𝪨.𬼖ⴑ; [B1]; xn--0vb1535kdb6e.xn--8kjz186s; ; ; # 𐹱ࡂ𝪨.𬼖ⴑ +xn--0vb1535kdb6e.xn--1ug742c5714c; 𐹱\u0842𝪨.𬼖ⴑ\u200D; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; ; # 𐹱ࡂ𝪨.𬼖ⴑ +𐹱\u0842𝪨。𬼖ⴑ\u200D; 𐹱\u0842𝪨.𬼖ⴑ\u200D; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ +xn--0vb1535kdb6e.xn--pnd93707a; 𐹱\u0842𝪨.𬼖Ⴑ; [B1, V7]; xn--0vb1535kdb6e.xn--pnd93707a; ; ; # 𐹱ࡂ𝪨.𬼖Ⴑ +xn--0vb1535kdb6e.xn--pnd879eqy33c; 𐹱\u0842𝪨.𬼖Ⴑ\u200D; [B1, B6, C2, V7]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; ; # 𐹱ࡂ𝪨.𬼖Ⴑ +\u1714𐭪󠙘\u200D。-𐹴; \u1714𐭪󠙘\u200D.-𐹴; [B1, C2, V3, V6, V7]; xn--fze807bso0spy14i.xn----c36i; ; xn--fze4126jujt0g.xn----c36i; [B1, V3, V6, V7] # ᜔𐭪.-𐹴 +\u1714𐭪󠙘\u200D。-𐹴; \u1714𐭪󠙘\u200D.-𐹴; [B1, C2, V3, V6, V7]; xn--fze807bso0spy14i.xn----c36i; ; xn--fze4126jujt0g.xn----c36i; [B1, V3, V6, V7] # ᜔𐭪.-𐹴 +xn--fze4126jujt0g.xn----c36i; \u1714𐭪󠙘.-𐹴; [B1, V3, V6, V7]; xn--fze4126jujt0g.xn----c36i; ; ; # ᜔𐭪.-𐹴 +xn--fze807bso0spy14i.xn----c36i; \u1714𐭪󠙘\u200D.-𐹴; [B1, C2, V3, V6, V7]; xn--fze807bso0spy14i.xn----c36i; ; ; # ᜔𐭪.-𐹴 +𾢬。\u0729︒쯙𝟧; 𾢬.\u0729︒쯙5; [B2, V7]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5 +𾢬。\u0729︒쯙𝟧; 𾢬.\u0729︒쯙5; [B2, V7]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5 +𾢬。\u0729。쯙5; 𾢬.\u0729.쯙5; [V7]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5 +𾢬。\u0729。쯙5; 𾢬.\u0729.쯙5; [V7]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5 +xn--t92s.xn--znb.xn--5-y88f; 𾢬.\u0729.쯙5; [V7]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5 +xn--t92s.xn--5-p1c0712mm8rb; 𾢬.\u0729︒쯙5; [B2, V7]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5 +𞤟-。\u0762≮뻐; 𞥁-.\u0762≮뻐; [B2, B3, V3]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐 +𞤟-。\u0762<\u0338뻐; 𞥁-.\u0762≮뻐; [B2, B3, V3]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐 +𞥁-。\u0762<\u0338뻐; 𞥁-.\u0762≮뻐; [B2, B3, V3]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐 +𞥁-。\u0762≮뻐; 𞥁-.\u0762≮뻐; [B2, B3, V3]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐 +xn----1j8r.xn--mpb269krv4i; 𞥁-.\u0762≮뻐; [B2, B3, V3]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐 +𞥩-򊫠.\u08B4≠; 𞥩-򊫠.\u08B4≠; [B2, B3, V7]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠ +𞥩-򊫠.\u08B4=\u0338; 𞥩-򊫠.\u08B4≠; [B2, B3, V7]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠ +𞥩-򊫠.\u08B4≠; ; [B2, B3, V7]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠ +𞥩-򊫠.\u08B4=\u0338; 𞥩-򊫠.\u08B4≠; [B2, B3, V7]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠ +xn----cm8rp3609a.xn--9yb852k; 𞥩-򊫠.\u08B4≠; [B2, B3, V7]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠ +-񅂏ςႼ.\u0661; -񅂏ςⴜ.\u0661; [B1, V3, V7]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١ +-񅂏ςႼ.\u0661; -񅂏ςⴜ.\u0661; [B1, V3, V7]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١ +-񅂏ςⴜ.\u0661; ; [B1, V3, V7]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١ +-񅂏ΣႼ.\u0661; -񅂏σⴜ.\u0661; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +-񅂏σⴜ.\u0661; ; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +-񅂏Σⴜ.\u0661; -񅂏σⴜ.\u0661; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +xn----0mb9682aov12f.xn--9hb; -񅂏σⴜ.\u0661; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +xn----ymb2782aov12f.xn--9hb; -񅂏ςⴜ.\u0661; [B1, V3, V7]; xn----ymb2782aov12f.xn--9hb; ; ; # -ςⴜ.١ +-񅂏ςⴜ.\u0661; -񅂏ςⴜ.\u0661; [B1, V3, V7]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١ +-񅂏ΣႼ.\u0661; -񅂏σⴜ.\u0661; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +-񅂏σⴜ.\u0661; -񅂏σⴜ.\u0661; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +-񅂏Σⴜ.\u0661; -񅂏σⴜ.\u0661; [B1, V3, V7]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١ +xn----0mb770hun11i.xn--9hb; -񅂏σႼ.\u0661; [B1, V3, V7]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١ +xn----ymb080hun11i.xn--9hb; -񅂏ςႼ.\u0661; [B1, V3, V7]; xn----ymb080hun11i.xn--9hb; ; ; # -ςႼ.١ +\u17CA.\u200D𝟮𑀿; \u17CA.\u200D2𑀿; [C2, V6]; xn--m4e.xn--2-tgnv469h; ; xn--m4e.xn--2-ku7i; [V6] # ៊.2𑀿 +\u17CA.\u200D2𑀿; ; [C2, V6]; xn--m4e.xn--2-tgnv469h; ; xn--m4e.xn--2-ku7i; [V6] # ៊.2𑀿 +xn--m4e.xn--2-ku7i; \u17CA.2𑀿; [V6]; xn--m4e.xn--2-ku7i; ; ; # ៊.2𑀿 +xn--m4e.xn--2-tgnv469h; \u17CA.\u200D2𑀿; [C2, V6]; xn--m4e.xn--2-tgnv469h; ; ; # ៊.2𑀿 +≯𝟖。\u1A60𐫓򟇑; ≯8.\u1A60𐫓򟇑; [B1, V6, V7]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓 +>\u0338𝟖。\u1A60𐫓򟇑; ≯8.\u1A60𐫓򟇑; [B1, V6, V7]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓 +≯8。\u1A60𐫓򟇑; ≯8.\u1A60𐫓򟇑; [B1, V6, V7]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓 +>\u03388。\u1A60𐫓򟇑; ≯8.\u1A60𐫓򟇑; [B1, V6, V7]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓 +xn--8-ogo.xn--jof5303iv1z5d; ≯8.\u1A60𐫓򟇑; [B1, V6, V7]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓 +𑲫Ↄ\u0664。\u200C; 𑲫ↄ\u0664.\u200C; [B1, C1, V6]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V6, A4_2] # 𑲫ↄ٤. +𑲫Ↄ\u0664。\u200C; 𑲫ↄ\u0664.\u200C; [B1, C1, V6]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V6, A4_2] # 𑲫ↄ٤. +𑲫ↄ\u0664。\u200C; 𑲫ↄ\u0664.\u200C; [B1, C1, V6]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V6, A4_2] # 𑲫ↄ٤. +xn--dib100l8x1p.; 𑲫ↄ\u0664.; [B1, V6]; xn--dib100l8x1p.; [B1, V6, A4_2]; ; # 𑲫ↄ٤. +xn--dib100l8x1p.xn--0ug; 𑲫ↄ\u0664.\u200C; [B1, C1, V6]; xn--dib100l8x1p.xn--0ug; ; ; # 𑲫ↄ٤. +𑲫ↄ\u0664。\u200C; 𑲫ↄ\u0664.\u200C; [B1, C1, V6]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V6, A4_2] # 𑲫ↄ٤. +xn--dib999kcy1p.; 𑲫Ↄ\u0664.; [B1, V6, V7]; xn--dib999kcy1p.; [B1, V6, V7, A4_2]; ; # 𑲫Ↄ٤. +xn--dib999kcy1p.xn--0ug; 𑲫Ↄ\u0664.\u200C; [B1, C1, V6, V7]; xn--dib999kcy1p.xn--0ug; ; ; # 𑲫Ↄ٤. +\u0C00𝟵\u200D\uFC9D.\u200D\u0750⒈; \u0C009\u200D\u0628\u062D.\u200D\u0750⒈; [B1, C2, V6, V7]; xn--9-1mcp570dl51a.xn--3ob977jmfd; ; xn--9-1mcp570d.xn--3ob470m; [B1, V6, V7] # ఀ9بح.ݐ⒈ +\u0C009\u200D\u0628\u062D.\u200D\u07501.; ; [B1, C2, V6]; xn--9-1mcp570dl51a.xn--1-x3c211q.; [B1, C2, V6, A4_2]; xn--9-1mcp570d.xn--1-x3c.; [B1, V6, A4_2] # ఀ9بح.ݐ1. +xn--9-1mcp570d.xn--1-x3c.; \u0C009\u0628\u062D.\u07501.; [B1, V6]; xn--9-1mcp570d.xn--1-x3c.; [B1, V6, A4_2]; ; # ఀ9بح.ݐ1. +xn--9-1mcp570dl51a.xn--1-x3c211q.; \u0C009\u200D\u0628\u062D.\u200D\u07501.; [B1, C2, V6]; xn--9-1mcp570dl51a.xn--1-x3c211q.; [B1, C2, V6, A4_2]; ; # ఀ9بح.ݐ1. +xn--9-1mcp570d.xn--3ob470m; \u0C009\u0628\u062D.\u0750⒈; [B1, V6, V7]; xn--9-1mcp570d.xn--3ob470m; ; ; # ఀ9بح.ݐ⒈ +xn--9-1mcp570dl51a.xn--3ob977jmfd; \u0C009\u200D\u0628\u062D.\u200D\u0750⒈; [B1, C2, V6, V7]; xn--9-1mcp570dl51a.xn--3ob977jmfd; ; ; # ఀ9بح.ݐ⒈ +\uAAF6。嬶ß葽; \uAAF6.嬶ß葽; [V6]; xn--2v9a.xn--zca7637b14za; ; xn--2v9a.xn--ss-q40dp97m; # ꫶.嬶ß葽 +\uAAF6。嬶SS葽; \uAAF6.嬶ss葽; [V6]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽 +\uAAF6。嬶ss葽; \uAAF6.嬶ss葽; [V6]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽 +\uAAF6。嬶Ss葽; \uAAF6.嬶ss葽; [V6]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽 +xn--2v9a.xn--ss-q40dp97m; \uAAF6.嬶ss葽; [V6]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽 +xn--2v9a.xn--zca7637b14za; \uAAF6.嬶ß葽; [V6]; xn--2v9a.xn--zca7637b14za; ; ; # ꫶.嬶ß葽 +𑚶⒈。񞻡𐹺; 𑚶⒈.񞻡𐹺; [B5, B6, V6, V7]; xn--tshz969f.xn--yo0d5914s; ; ; # 𑚶⒈.𐹺 +𑚶1.。񞻡𐹺; 𑚶1..񞻡𐹺; [B5, B6, V6, V7, X4_2]; xn--1-3j0j..xn--yo0d5914s; [B5, B6, V6, V7, A4_2]; ; # 𑚶1..𐹺 +xn--1-3j0j..xn--yo0d5914s; 𑚶1..񞻡𐹺; [B5, B6, V6, V7, X4_2]; xn--1-3j0j..xn--yo0d5914s; [B5, B6, V6, V7, A4_2]; ; # 𑚶1..𐹺 +xn--tshz969f.xn--yo0d5914s; 𑚶⒈.񞻡𐹺; [B5, B6, V6, V7]; xn--tshz969f.xn--yo0d5914s; ; ; # 𑚶⒈.𐹺 +𑜤︒≮.񚕽\u05D8𞾩; 𑜤︒≮.񚕽\u05D8𞾩; [B1, B5, B6, V6, V7]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט +𑜤︒<\u0338.񚕽\u05D8𞾩; 𑜤︒≮.񚕽\u05D8𞾩; [B1, B5, B6, V6, V7]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט +𑜤。≮.񚕽\u05D8𞾩; 𑜤.≮.񚕽\u05D8𞾩; [B1, B5, B6, V6, V7]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט +𑜤。<\u0338.񚕽\u05D8𞾩; 𑜤.≮.񚕽\u05D8𞾩; [B1, B5, B6, V6, V7]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט +xn--ci2d.xn--gdh.xn--deb0091w5q9u; 𑜤.≮.񚕽\u05D8𞾩; [B1, B5, B6, V6, V7]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט +xn--gdh5267fdzpa.xn--deb0091w5q9u; 𑜤︒≮.񚕽\u05D8𞾩; [B1, B5, B6, V6, V7]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט +󠆋\u0603񏦤.⇁ς򏋈򺇥; \u0603񏦤.⇁ς򏋈򺇥; [B1, V7]; xn--lfb04106d.xn--3xa174mxv16m8moq; ; xn--lfb04106d.xn--4xa964mxv16m8moq; # .⇁ς +󠆋\u0603񏦤.⇁Σ򏋈򺇥; \u0603񏦤.⇁σ򏋈򺇥; [B1, V7]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ +󠆋\u0603񏦤.⇁σ򏋈򺇥; \u0603񏦤.⇁σ򏋈򺇥; [B1, V7]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ +xn--lfb04106d.xn--4xa964mxv16m8moq; \u0603񏦤.⇁σ򏋈򺇥; [B1, V7]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ +xn--lfb04106d.xn--3xa174mxv16m8moq; \u0603񏦤.⇁ς򏋈򺇥; [B1, V7]; xn--lfb04106d.xn--3xa174mxv16m8moq; ; ; # .⇁ς +ς𑐽𵢈𑜫。𞬩\u200C𐫄; ς𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [V7] # ς𑐽𑜫.𐫄 +ς𑐽𵢈𑜫。𞬩\u200C𐫄; ς𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [V7] # ς𑐽𑜫.𐫄 +Σ𑐽𵢈𑜫。𞬩\u200C𐫄; σ𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [V7] # σ𑐽𑜫.𐫄 +σ𑐽𵢈𑜫。𞬩\u200C𐫄; σ𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [V7] # σ𑐽𑜫.𐫄 +xn--4xa2260lk3b8z15g.xn--tw9ct349a; σ𑐽𵢈𑜫.𞬩𐫄; [V7]; xn--4xa2260lk3b8z15g.xn--tw9ct349a; ; ; # σ𑐽𑜫.𐫄 +xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; σ𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; ; # σ𑐽𑜫.𐫄 +xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ς𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; ; # ς𑐽𑜫.𐫄 +Σ𑐽𵢈𑜫。𞬩\u200C𐫄; σ𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [V7] # σ𑐽𑜫.𐫄 +σ𑐽𵢈𑜫。𞬩\u200C𐫄; σ𑐽𵢈𑜫.𞬩\u200C𐫄; [C1, V7]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [V7] # σ𑐽𑜫.𐫄 +-򵏽。-\uFC4C\u075B; -򵏽.-\u0646\u062D\u075B; [B1, V3, V7]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ +-򵏽。-\u0646\u062D\u075B; -򵏽.-\u0646\u062D\u075B; [B1, V3, V7]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ +xn----o452j.xn----cnc8e38c; -򵏽.-\u0646\u062D\u075B; [B1, V3, V7]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ +⺢򇺅𝟤。\u200D🚷; ⺢򇺅2.\u200D🚷; [C2, V7]; xn--2-4jtr4282f.xn--1ugz946p; ; xn--2-4jtr4282f.xn--m78h; [V7] # ⺢2.🚷 +⺢򇺅2。\u200D🚷; ⺢򇺅2.\u200D🚷; [C2, V7]; xn--2-4jtr4282f.xn--1ugz946p; ; xn--2-4jtr4282f.xn--m78h; [V7] # ⺢2.🚷 +xn--2-4jtr4282f.xn--m78h; ⺢򇺅2.🚷; [V7]; xn--2-4jtr4282f.xn--m78h; ; ; # ⺢2.🚷 +xn--2-4jtr4282f.xn--1ugz946p; ⺢򇺅2.\u200D🚷; [C2, V7]; xn--2-4jtr4282f.xn--1ugz946p; ; ; # ⺢2.🚷 +\u0CF8\u200D\u2DFE𐹲。򤐶; \u0CF8\u200D\u2DFE𐹲.򤐶; [B5, B6, C2, V7]; xn--hvc488g69j402t.xn--3e36c; ; xn--hvc220of37m.xn--3e36c; [B5, B6, V7] # ⷾ𐹲. +\u0CF8\u200D\u2DFE𐹲。򤐶; \u0CF8\u200D\u2DFE𐹲.򤐶; [B5, B6, C2, V7]; xn--hvc488g69j402t.xn--3e36c; ; xn--hvc220of37m.xn--3e36c; [B5, B6, V7] # ⷾ𐹲. +xn--hvc220of37m.xn--3e36c; \u0CF8\u2DFE𐹲.򤐶; [B5, B6, V7]; xn--hvc220of37m.xn--3e36c; ; ; # ⷾ𐹲. +xn--hvc488g69j402t.xn--3e36c; \u0CF8\u200D\u2DFE𐹲.򤐶; [B5, B6, C2, V7]; xn--hvc488g69j402t.xn--3e36c; ; ; # ⷾ𐹲. +𐹢.Ⴍ₉⁸; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98 +𐹢.Ⴍ98; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98 +𐹢.ⴍ98; ; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98 +xn--9n0d.xn--98-u61a; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98 +𐹢.ⴍ₉⁸; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98 +xn--9n0d.xn--98-7ek; 𐹢.Ⴍ98; [B1, V7]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98 +\u200C\u034F。ß\u08E2⒚≯; \u200C.ß\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--zca612bx9vo5b; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ß⒚≯ +\u200C\u034F。ß\u08E2⒚>\u0338; \u200C.ß\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--zca612bx9vo5b; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ß⒚≯ +\u200C\u034F。ß\u08E219.≯; \u200C.ß\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--19-fia813f.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ß19.≯ +\u200C\u034F。ß\u08E219.>\u0338; \u200C.ß\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--19-fia813f.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ß19.≯ +\u200C\u034F。SS\u08E219.>\u0338; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ss19.≯ +\u200C\u034F。SS\u08E219.≯; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ss19.≯ +\u200C\u034F。ss\u08E219.≯; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ss19.≯ +\u200C\u034F。ss\u08E219.>\u0338; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ss19.≯ +\u200C\u034F。Ss\u08E219.>\u0338; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ss19.≯ +\u200C\u034F。Ss\u08E219.≯; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2] # .ss19.≯ +.xn--ss19-w0i.xn--hdh; .ss\u08E219.≯; [B1, B5, V7, X4_2]; .xn--ss19-w0i.xn--hdh; [B1, B5, V7, A4_2]; ; # .ss19.≯ +xn--0ug.xn--ss19-w0i.xn--hdh; \u200C.ss\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--ss19-w0i.xn--hdh; ; ; # .ss19.≯ +xn--0ug.xn--19-fia813f.xn--hdh; \u200C.ß\u08E219.≯; [B1, B5, C1, V7]; xn--0ug.xn--19-fia813f.xn--hdh; ; ; # .ß19.≯ +\u200C\u034F。SS\u08E2⒚>\u0338; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ss⒚≯ +\u200C\u034F。SS\u08E2⒚≯; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ss⒚≯ +\u200C\u034F。ss\u08E2⒚≯; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ss⒚≯ +\u200C\u034F。ss\u08E2⒚>\u0338; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ss⒚≯ +\u200C\u034F。Ss\u08E2⒚>\u0338; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ss⒚≯ +\u200C\u034F。Ss\u08E2⒚≯; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2] # .ss⒚≯ +.xn--ss-9if872xjjc; .ss\u08E2⒚≯; [B5, B6, V7, X4_2]; .xn--ss-9if872xjjc; [B5, B6, V7, A4_2]; ; # .ss⒚≯ +xn--0ug.xn--ss-9if872xjjc; \u200C.ss\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--ss-9if872xjjc; ; ; # .ss⒚≯ +xn--0ug.xn--zca612bx9vo5b; \u200C.ß\u08E2⒚≯; [B1, B5, B6, C1, V7]; xn--0ug.xn--zca612bx9vo5b; ; ; # .ß⒚≯ +\u200C𞥍ᡌ.𣃔; \u200C𞥍ᡌ.𣃔; [B1, C1, V7]; xn--c8e180bqz13b.xn--od1j; ; xn--c8e5919u.xn--od1j; [B2, B3, V7] # ᡌ.𣃔 +\u200C𞥍ᡌ.𣃔; ; [B1, C1, V7]; xn--c8e180bqz13b.xn--od1j; ; xn--c8e5919u.xn--od1j; [B2, B3, V7] # ᡌ.𣃔 +xn--c8e5919u.xn--od1j; 𞥍ᡌ.𣃔; [B2, B3, V7]; xn--c8e5919u.xn--od1j; ; ; # ᡌ.𣃔 +xn--c8e180bqz13b.xn--od1j; \u200C𞥍ᡌ.𣃔; [B1, C1, V7]; xn--c8e180bqz13b.xn--od1j; ; ; # ᡌ.𣃔 +\u07D0򜬝-񡢬。\u0FA0Ⴛ𞷏𝆬; \u07D0򜬝-񡢬.\u0FA0ⴛ𞷏𝆬; [B1, B2, B3, V6, V7]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬 +\u07D0򜬝-񡢬。\u0FA0ⴛ𞷏𝆬; \u07D0򜬝-񡢬.\u0FA0ⴛ𞷏𝆬; [B1, B2, B3, V6, V7]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬 +xn----8bd11730jefvw.xn--wfd802mpm20agsxa; \u07D0򜬝-񡢬.\u0FA0ⴛ𞷏𝆬; [B1, B2, B3, V6, V7]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬 +xn----8bd11730jefvw.xn--wfd08cd265hgsxa; \u07D0򜬝-񡢬.\u0FA0Ⴛ𞷏𝆬; [B1, B2, B3, V6, V7]; xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ; ; # ߐ-.ྠႻ𝆬 +𝨥。⫟𑈾; 𝨥.⫟𑈾; [V6]; xn--n82h.xn--63iw010f; ; ; # 𝨥.⫟𑈾 +xn--n82h.xn--63iw010f; 𝨥.⫟𑈾; [V6]; xn--n82h.xn--63iw010f; ; ; # 𝨥.⫟𑈾 +⾛\u0753.Ⴕ𞠬\u0604\u200D; 走\u0753.ⴕ𞠬\u0604\u200D; [B5, B6, C2, V7]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, V7] # 走ݓ.ⴕ𞠬 +走\u0753.Ⴕ𞠬\u0604\u200D; 走\u0753.ⴕ𞠬\u0604\u200D; [B5, B6, C2, V7]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, V7] # 走ݓ.ⴕ𞠬 +走\u0753.ⴕ𞠬\u0604\u200D; ; [B5, B6, C2, V7]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, V7] # 走ݓ.ⴕ𞠬 +xn--6ob9779d.xn--mfb511rxu80a; 走\u0753.ⴕ𞠬\u0604; [B5, B6, V7]; xn--6ob9779d.xn--mfb511rxu80a; ; ; # 走ݓ.ⴕ𞠬 +xn--6ob9779d.xn--mfb444k5gjt754b; 走\u0753.ⴕ𞠬\u0604\u200D; [B5, B6, C2, V7]; xn--6ob9779d.xn--mfb444k5gjt754b; ; ; # 走ݓ.ⴕ𞠬 +⾛\u0753.ⴕ𞠬\u0604\u200D; 走\u0753.ⴕ𞠬\u0604\u200D; [B5, B6, C2, V7]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, V7] # 走ݓ.ⴕ𞠬 +xn--6ob9779d.xn--mfb785ck569a; 走\u0753.Ⴕ𞠬\u0604; [B5, B6, V7]; xn--6ob9779d.xn--mfb785ck569a; ; ; # 走ݓ.Ⴕ𞠬 +xn--6ob9779d.xn--mfb785czmm0y85b; 走\u0753.Ⴕ𞠬\u0604\u200D; [B5, B6, C2, V7]; xn--6ob9779d.xn--mfb785czmm0y85b; ; ; # 走ݓ.Ⴕ𞠬 +-ᢗ\u200C🄄.𑜢; -ᢗ\u200C3,.𑜢; [C1, V3, V6, U1]; xn---3,-3eu051c.xn--9h2d; ; xn---3,-3eu.xn--9h2d; [V3, V6, U1] # -ᢗ3,.𑜢 +-ᢗ\u200C3,.𑜢; ; [C1, V3, V6, U1]; xn---3,-3eu051c.xn--9h2d; ; xn---3,-3eu.xn--9h2d; [V3, V6, U1] # -ᢗ3,.𑜢 +xn---3,-3eu.xn--9h2d; -ᢗ3,.𑜢; [V3, V6, U1]; xn---3,-3eu.xn--9h2d; ; ; # -ᢗ3,.𑜢 +xn---3,-3eu051c.xn--9h2d; -ᢗ\u200C3,.𑜢; [C1, V3, V6, U1]; xn---3,-3eu051c.xn--9h2d; ; ; # -ᢗ3,.𑜢 +xn----pck1820x.xn--9h2d; -ᢗ🄄.𑜢; [V3, V6, V7]; xn----pck1820x.xn--9h2d; ; ; # -ᢗ🄄.𑜢 +xn----pck312bx563c.xn--9h2d; -ᢗ\u200C🄄.𑜢; [C1, V3, V6, V7]; xn----pck312bx563c.xn--9h2d; ; ; # -ᢗ🄄.𑜢 +≠𐸁𹏁\u200C.Ⴚ򳄠; ≠𐸁𹏁\u200C.ⴚ򳄠; [B1, C1, V7]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, V7] # ≠.ⴚ +=\u0338𐸁𹏁\u200C.Ⴚ򳄠; ≠𐸁𹏁\u200C.ⴚ򳄠; [B1, C1, V7]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, V7] # ≠.ⴚ +=\u0338𐸁𹏁\u200C.ⴚ򳄠; ≠𐸁𹏁\u200C.ⴚ򳄠; [B1, C1, V7]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, V7] # ≠.ⴚ +≠𐸁𹏁\u200C.ⴚ򳄠; ; [B1, C1, V7]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, V7] # ≠.ⴚ +xn--1ch2293gv3nr.xn--ilj23531g; ≠𐸁𹏁.ⴚ򳄠; [B1, V7]; xn--1ch2293gv3nr.xn--ilj23531g; ; ; # ≠.ⴚ +xn--0ug83gn618a21ov.xn--ilj23531g; ≠𐸁𹏁\u200C.ⴚ򳄠; [B1, C1, V7]; xn--0ug83gn618a21ov.xn--ilj23531g; ; ; # ≠.ⴚ +xn--1ch2293gv3nr.xn--ynd49496l; ≠𐸁𹏁.Ⴚ򳄠; [B1, V7]; xn--1ch2293gv3nr.xn--ynd49496l; ; ; # ≠.Ⴚ +xn--0ug83gn618a21ov.xn--ynd49496l; ≠𐸁𹏁\u200C.Ⴚ򳄠; [B1, C1, V7]; xn--0ug83gn618a21ov.xn--ynd49496l; ; ; # ≠.Ⴚ +\u0669。󠇀𑇊; \u0669.𑇊; [B1, V6]; xn--iib.xn--6d1d; ; ; # ٩.𑇊 +\u0669。󠇀𑇊; \u0669.𑇊; [B1, V6]; xn--iib.xn--6d1d; ; ; # ٩.𑇊 +xn--iib.xn--6d1d; \u0669.𑇊; [B1, V6]; xn--iib.xn--6d1d; ; ; # ٩.𑇊 +\u1086𞶀≯⒍。-; \u1086𞶀≯⒍.-; [B1, V3, V6, V7]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.- +\u1086𞶀>\u0338⒍。-; \u1086𞶀≯⒍.-; [B1, V3, V6, V7]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.- +\u1086𞶀≯6.。-; \u1086𞶀≯6..-; [B1, V3, V6, V7, X4_2]; xn--6-oyg968k7h74b..-; [B1, V3, V6, V7, A4_2]; ; # ႆ≯6..- +\u1086𞶀>\u03386.。-; \u1086𞶀≯6..-; [B1, V3, V6, V7, X4_2]; xn--6-oyg968k7h74b..-; [B1, V3, V6, V7, A4_2]; ; # ႆ≯6..- +xn--6-oyg968k7h74b..-; \u1086𞶀≯6..-; [B1, V3, V6, V7, X4_2]; xn--6-oyg968k7h74b..-; [B1, V3, V6, V7, A4_2]; ; # ႆ≯6..- +xn--hmd482gqqb8730g.-; \u1086𞶀≯⒍.-; [B1, V3, V6, V7]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.- +\u17B4.쮇-; .쮇-; [V3, X4_2]; .xn----938f; [V3, A4_2]; ; # .쮇- +\u17B4.쮇-; .쮇-; [V3, X4_2]; .xn----938f; [V3, A4_2]; ; # .쮇- +.xn----938f; .쮇-; [V3, X4_2]; .xn----938f; [V3, A4_2]; ; # .쮇- +xn--z3e.xn----938f; \u17B4.쮇-; [V3, V6, V7]; xn--z3e.xn----938f; ; ; # .쮇- +\u200C𑓂。⒈-􀪛; \u200C𑓂.⒈-􀪛; [C1, V7]; xn--0ugy057g.xn----dcp29674o; ; xn--wz1d.xn----dcp29674o; [V6, V7] # 𑓂.⒈- +\u200C𑓂。1.-􀪛; \u200C𑓂.1.-􀪛; [C1, V3, V7]; xn--0ugy057g.1.xn----rg03o; ; xn--wz1d.1.xn----rg03o; [V3, V6, V7] # 𑓂.1.- +xn--wz1d.1.xn----rg03o; 𑓂.1.-􀪛; [V3, V6, V7]; xn--wz1d.1.xn----rg03o; ; ; # 𑓂.1.- +xn--0ugy057g.1.xn----rg03o; \u200C𑓂.1.-􀪛; [C1, V3, V7]; xn--0ugy057g.1.xn----rg03o; ; ; # 𑓂.1.- +xn--wz1d.xn----dcp29674o; 𑓂.⒈-􀪛; [V6, V7]; xn--wz1d.xn----dcp29674o; ; ; # 𑓂.⒈- +xn--0ugy057g.xn----dcp29674o; \u200C𑓂.⒈-􀪛; [C1, V7]; xn--0ugy057g.xn----dcp29674o; ; ; # 𑓂.⒈- +⒈\uFEAE\u200C。\u20E9🖞\u200C𖬴; ⒈\u0631\u200C.\u20E9🖞\u200C𖬴; [B1, C1, V6, V7]; xn--wgb253kmfd.xn--0ugz6a8040fty5d; ; xn--wgb746m.xn--c1g6021kg18c; [B1, V6, V7] # ⒈ر.⃩🖞𖬴 +1.\u0631\u200C。\u20E9🖞\u200C𖬴; 1.\u0631\u200C.\u20E9🖞\u200C𖬴; [B1, B3, C1, V6]; 1.xn--wgb253k.xn--0ugz6a8040fty5d; ; 1.xn--wgb.xn--c1g6021kg18c; [B1, V6] # 1.ر.⃩🖞𖬴 +1.xn--wgb.xn--c1g6021kg18c; 1.\u0631.\u20E9🖞𖬴; [B1, V6]; 1.xn--wgb.xn--c1g6021kg18c; ; ; # 1.ر.⃩🖞𖬴 +1.xn--wgb253k.xn--0ugz6a8040fty5d; 1.\u0631\u200C.\u20E9🖞\u200C𖬴; [B1, B3, C1, V6]; 1.xn--wgb253k.xn--0ugz6a8040fty5d; ; ; # 1.ر.⃩🖞𖬴 +xn--wgb746m.xn--c1g6021kg18c; ⒈\u0631.\u20E9🖞𖬴; [B1, V6, V7]; xn--wgb746m.xn--c1g6021kg18c; ; ; # ⒈ر.⃩🖞𖬴 +xn--wgb253kmfd.xn--0ugz6a8040fty5d; ⒈\u0631\u200C.\u20E9🖞\u200C𖬴; [B1, C1, V6, V7]; xn--wgb253kmfd.xn--0ugz6a8040fty5d; ; ; # ⒈ر.⃩🖞𖬴 +󌭇。𝟐\u1BA8\u07D4; 󌭇.2\u1BA8\u07D4; [B1, V7]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ +󌭇。2\u1BA8\u07D4; 󌭇.2\u1BA8\u07D4; [B1, V7]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ +xn--xm89d.xn--2-icd143m; 󌭇.2\u1BA8\u07D4; [B1, V7]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ +\uFD8F򫳺.ς\u200D𐹷; \u0645\u062E\u0645򫳺.ς\u200D𐹷; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, V7] # مخم.ς𐹷 +\u0645\u062E\u0645򫳺.ς\u200D𐹷; ; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, V7] # مخم.ς𐹷 +\u0645\u062E\u0645򫳺.Σ\u200D𐹷; \u0645\u062E\u0645򫳺.σ\u200D𐹷; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, V7] # مخم.σ𐹷 +\u0645\u062E\u0645򫳺.σ\u200D𐹷; ; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, V7] # مخم.σ𐹷 +xn--tgb9bb64691z.xn--4xa6667k; \u0645\u062E\u0645򫳺.σ𐹷; [B2, B3, B5, B6, V7]; xn--tgb9bb64691z.xn--4xa6667k; ; ; # مخم.σ𐹷 +xn--tgb9bb64691z.xn--4xa895lrp7n; \u0645\u062E\u0645򫳺.σ\u200D𐹷; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; ; # مخم.σ𐹷 +xn--tgb9bb64691z.xn--3xa006lrp7n; \u0645\u062E\u0645򫳺.ς\u200D𐹷; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; ; # مخم.ς𐹷 +\uFD8F򫳺.Σ\u200D𐹷; \u0645\u062E\u0645򫳺.σ\u200D𐹷; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, V7] # مخم.σ𐹷 +\uFD8F򫳺.σ\u200D𐹷; \u0645\u062E\u0645򫳺.σ\u200D𐹷; [B2, B3, B5, B6, C2, V7]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, V7] # مخم.σ𐹷 +⒎\u06C1\u0605。\uAAF6۵𐇽; ⒎\u06C1\u0605.\uAAF6۵𐇽; [B1, V6, V7]; xn--nfb98ai25e.xn--imb3805fxt8b; ; ; # ⒎ہ.꫶۵𐇽 +7.\u06C1\u0605。\uAAF6۵𐇽; 7.\u06C1\u0605.\uAAF6۵𐇽; [B1, V6, V7]; 7.xn--nfb98a.xn--imb3805fxt8b; ; ; # 7.ہ.꫶۵𐇽 +7.xn--nfb98a.xn--imb3805fxt8b; 7.\u06C1\u0605.\uAAF6۵𐇽; [B1, V6, V7]; 7.xn--nfb98a.xn--imb3805fxt8b; ; ; # 7.ہ.꫶۵𐇽 +xn--nfb98ai25e.xn--imb3805fxt8b; ⒎\u06C1\u0605.\uAAF6۵𐇽; [B1, V6, V7]; xn--nfb98ai25e.xn--imb3805fxt8b; ; ; # ⒎ہ.꫶۵𐇽 +-ᡥ᠆󍲭。\u0605\u1A5D𐹡; -ᡥ᠆󍲭.\u0605\u1A5D𐹡; [B1, V3, V7]; xn----f3j6s87156i.xn--nfb035hoo2p; ; ; # -ᡥ᠆.ᩝ𐹡 +xn----f3j6s87156i.xn--nfb035hoo2p; -ᡥ᠆󍲭.\u0605\u1A5D𐹡; [B1, V3, V7]; xn----f3j6s87156i.xn--nfb035hoo2p; ; ; # -ᡥ᠆.ᩝ𐹡 +\u200D.\u06BD\u0663\u0596; ; [B1, C2]; xn--1ug.xn--hcb32bni; ; .xn--hcb32bni; [A4_2] # .ڽ٣֖ +.xn--hcb32bni; .\u06BD\u0663\u0596; [X4_2]; .xn--hcb32bni; [A4_2]; ; # .ڽ٣֖ +xn--1ug.xn--hcb32bni; \u200D.\u06BD\u0663\u0596; [B1, C2]; xn--1ug.xn--hcb32bni; ; ; # .ڽ٣֖ +xn--hcb32bni; \u06BD\u0663\u0596; ; xn--hcb32bni; ; ; # ڽ٣֖ +\u06BD\u0663\u0596; ; ; xn--hcb32bni; ; ; # ڽ٣֖ +㒧۱.Ⴚ\u0678\u200D; 㒧۱.ⴚ\u064A\u0674\u200D; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ +㒧۱.Ⴚ\u064A\u0674\u200D; 㒧۱.ⴚ\u064A\u0674\u200D; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ +㒧۱.ⴚ\u064A\u0674\u200D; ; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ +xn--emb715u.xn--mhb8fy26k; 㒧۱.ⴚ\u064A\u0674; [B5, B6]; xn--emb715u.xn--mhb8fy26k; ; ; # 㒧۱.ⴚيٴ +xn--emb715u.xn--mhb8f960g03l; 㒧۱.ⴚ\u064A\u0674\u200D; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; ; # 㒧۱.ⴚيٴ +㒧۱.ⴚ\u0678\u200D; 㒧۱.ⴚ\u064A\u0674\u200D; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ +xn--emb715u.xn--mhb8f817a; 㒧۱.Ⴚ\u064A\u0674; [B5, B6, V7]; xn--emb715u.xn--mhb8f817a; ; ; # 㒧۱.Ⴚيٴ +xn--emb715u.xn--mhb8f817ao2p; 㒧۱.Ⴚ\u064A\u0674\u200D; [B5, B6, C2, V7]; xn--emb715u.xn--mhb8f817ao2p; ; ; # 㒧۱.Ⴚيٴ +\u0F94ꡋ-.-𖬴; \u0F94ꡋ-.-𖬴; [V3, V6]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴 +\u0F94ꡋ-.-𖬴; ; [V3, V6]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴 +xn----ukg9938i.xn----4u5m; \u0F94ꡋ-.-𖬴; [V3, V6]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴 +񿒳-⋢\u200C.标-; 񿒳-⋢\u200C.标-; [C1, V3, V7]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [V3, V7] # -⋢.标- +񿒳-⊑\u0338\u200C.标-; 񿒳-⋢\u200C.标-; [C1, V3, V7]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [V3, V7] # -⋢.标- +񿒳-⋢\u200C.标-; ; [C1, V3, V7]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [V3, V7] # -⋢.标- +񿒳-⊑\u0338\u200C.标-; 񿒳-⋢\u200C.标-; [C1, V3, V7]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [V3, V7] # -⋢.标- +xn----9mo67451g.xn----qj7b; 񿒳-⋢.标-; [V3, V7]; xn----9mo67451g.xn----qj7b; ; ; # -⋢.标- +xn----sgn90kn5663a.xn----qj7b; 񿒳-⋢\u200C.标-; [C1, V3, V7]; xn----sgn90kn5663a.xn----qj7b; ; ; # -⋢.标- +\u0671.ς\u07DC; \u0671.ς\u07DC; [B5, B6]; xn--qib.xn--3xa41s; ; xn--qib.xn--4xa21s; # ٱ.ςߜ +\u0671.ς\u07DC; ; [B5, B6]; xn--qib.xn--3xa41s; ; xn--qib.xn--4xa21s; # ٱ.ςߜ +\u0671.Σ\u07DC; \u0671.σ\u07DC; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ +\u0671.σ\u07DC; ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ +xn--qib.xn--4xa21s; \u0671.σ\u07DC; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ +xn--qib.xn--3xa41s; \u0671.ς\u07DC; [B5, B6]; xn--qib.xn--3xa41s; ; ; # ٱ.ςߜ +\u0671.Σ\u07DC; \u0671.σ\u07DC; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ +\u0671.σ\u07DC; \u0671.σ\u07DC; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ +񼈶\u0605.\u08C1\u200D𑑂𱼱; 񼈶\u0605.\u08C1\u200D𑑂𱼱; [B2, B3, B5, B6, C2, V7]; xn--nfb17942h.xn--nzb240jv06otevq; ; xn--nfb17942h.xn--nzb6708kx3pn; [B2, B3, B5, B6, V7] # .ࣁ𑑂𱼱 +񼈶\u0605.\u08C1\u200D𑑂𱼱; ; [B2, B3, B5, B6, C2, V7]; xn--nfb17942h.xn--nzb240jv06otevq; ; xn--nfb17942h.xn--nzb6708kx3pn; [B2, B3, B5, B6, V7] # .ࣁ𑑂𱼱 +xn--nfb17942h.xn--nzb6708kx3pn; 񼈶\u0605.\u08C1𑑂𱼱; [B2, B3, B5, B6, V7]; xn--nfb17942h.xn--nzb6708kx3pn; ; ; # .ࣁ𑑂𱼱 +xn--nfb17942h.xn--nzb240jv06otevq; 񼈶\u0605.\u08C1\u200D𑑂𱼱; [B2, B3, B5, B6, C2, V7]; xn--nfb17942h.xn--nzb240jv06otevq; ; ; # .ࣁ𑑂𱼱 +𐹾𐋩𞵜。\u1BF2; 𐹾𐋩𞵜.\u1BF2; [B1, V6, V7]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲ +𐹾𐋩𞵜。\u1BF2; 𐹾𐋩𞵜.\u1BF2; [B1, V6, V7]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲ +xn--d97cn8rn44p.xn--0zf; 𐹾𐋩𞵜.\u1BF2; [B1, V6, V7]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲ +6\u1160\u1C33󠸧.򟜊锰\u072Cς; 6\u1C33󠸧.򟜊锰\u072Cς; [B1, B5, V7]; xn--6-iuly4983p.xn--3xa16ohw6pk078g; ; xn--6-iuly4983p.xn--4xa95ohw6pk078g; # 6ᰳ.锰ܬς +6\u1160\u1C33󠸧.򟜊锰\u072CΣ; 6\u1C33󠸧.򟜊锰\u072Cσ; [B1, B5, V7]; xn--6-iuly4983p.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ +6\u1160\u1C33󠸧.򟜊锰\u072Cσ; 6\u1C33󠸧.򟜊锰\u072Cσ; [B1, B5, V7]; xn--6-iuly4983p.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ +xn--6-iuly4983p.xn--4xa95ohw6pk078g; 6\u1C33󠸧.򟜊锰\u072Cσ; [B1, B5, V7]; xn--6-iuly4983p.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ +xn--6-iuly4983p.xn--3xa16ohw6pk078g; 6\u1C33󠸧.򟜊锰\u072Cς; [B1, B5, V7]; xn--6-iuly4983p.xn--3xa16ohw6pk078g; ; ; # 6ᰳ.锰ܬς +xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; 6\u1160\u1C33󠸧.򟜊锰\u072Cσ; [B1, B5, V7]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ +xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; 6\u1160\u1C33󠸧.򟜊锰\u072Cς; [B1, B5, V7]; xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; ; ; # 6ᰳ.锰ܬς +\u06B3\uFE04񅎦𝟽。𐹽; \u06B3񅎦7.𐹽; [B1, B2, V7]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽 +\u06B3\uFE04񅎦7。𐹽; \u06B3񅎦7.𐹽; [B1, B2, V7]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽 +xn--7-yuc34665f.xn--1o0d; \u06B3񅎦7.𐹽; [B1, B2, V7]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽 +𞮧.\u200C⫞; 𞮧.\u200C⫞; [B1, C1, V7]; xn--pw6h.xn--0ug283b; ; xn--pw6h.xn--53i; [B1, V7] # .⫞ +𞮧.\u200C⫞; ; [B1, C1, V7]; xn--pw6h.xn--0ug283b; ; xn--pw6h.xn--53i; [B1, V7] # .⫞ +xn--pw6h.xn--53i; 𞮧.⫞; [B1, V7]; xn--pw6h.xn--53i; ; ; # .⫞ +xn--pw6h.xn--0ug283b; 𞮧.\u200C⫞; [B1, C1, V7]; xn--pw6h.xn--0ug283b; ; ; # .⫞ +-񕉴.\u06E0ᢚ-; ; [V3, V6, V7]; xn----qi38c.xn----jxc827k; ; ; # -.۠ᢚ- +xn----qi38c.xn----jxc827k; -񕉴.\u06E0ᢚ-; [V3, V6, V7]; xn----qi38c.xn----jxc827k; ; ; # -.۠ᢚ- +⌁\u200D𑄴.\u200C𝟩\u066C; ⌁\u200D𑄴.\u200C7\u066C; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; xn--nhh5394g.xn--7-xqc; [B1] # ⌁𑄴.7٬ +⌁\u200D𑄴.\u200C7\u066C; ; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; xn--nhh5394g.xn--7-xqc; [B1] # ⌁𑄴.7٬ +xn--nhh5394g.xn--7-xqc; ⌁𑄴.7\u066C; [B1]; xn--nhh5394g.xn--7-xqc; ; ; # ⌁𑄴.7٬ +xn--1ug38i2093a.xn--7-xqc297q; ⌁\u200D𑄴.\u200C7\u066C; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; ; # ⌁𑄴.7٬ +︒\uFD05\u0E37\uFEFC。岓\u1BF2󠾃ᡂ; ︒\u0635\u0649\u0E37\u0644\u0627.岓\u1BF2󠾃ᡂ; [B1, V7]; xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ; ; # ︒صىืلا.岓᯲ᡂ +。\u0635\u0649\u0E37\u0644\u0627。岓\u1BF2󠾃ᡂ; .\u0635\u0649\u0E37\u0644\u0627.岓\u1BF2󠾃ᡂ; [V7, X4_2]; .xn--mgb1a7bt462h.xn--17e10qe61f9r71s; [V7, A4_2]; ; # .صىืلا.岓᯲ᡂ +.xn--mgb1a7bt462h.xn--17e10qe61f9r71s; .\u0635\u0649\u0E37\u0644\u0627.岓\u1BF2󠾃ᡂ; [V7, X4_2]; .xn--mgb1a7bt462h.xn--17e10qe61f9r71s; [V7, A4_2]; ; # .صىืلا.岓᯲ᡂ +xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ︒\u0635\u0649\u0E37\u0644\u0627.岓\u1BF2󠾃ᡂ; [B1, V7]; xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ; ; # ︒صىืلا.岓᯲ᡂ +𐹨。8𑁆; 𐹨.8𑁆; [B1]; xn--go0d.xn--8-yu7i; ; ; # 𐹨.8𑁆 +xn--go0d.xn--8-yu7i; 𐹨.8𑁆; [B1]; xn--go0d.xn--8-yu7i; ; ; # 𐹨.8𑁆 +𞀕\u0D43.ꡚ\u08FA𐹰\u0D44; 𞀕\u0D43.ꡚ\u08FA𐹰\u0D44; [B1, B5, B6, V6]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ +𞀕\u0D43.ꡚ\u08FA𐹰\u0D44; ; [B1, B5, B6, V6]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ +xn--mxc5210v.xn--90b01t8u2p1ltd; 𞀕\u0D43.ꡚ\u08FA𐹰\u0D44; [B1, B5, B6, V6]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ +󆩏𐦹\u0303。󠍅; 󆩏𐦹\u0303.󠍅; [B1, B5, B6, V7]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃. +󆩏𐦹\u0303。󠍅; 󆩏𐦹\u0303.󠍅; [B1, B5, B6, V7]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃. +xn--nsa1265kp9z9e.xn--xt36e; 󆩏𐦹\u0303.󠍅; [B1, B5, B6, V7]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃. +ᢌ.-\u085A; ᢌ.-\u085A; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚ +ᢌ.-\u085A; ; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚ +xn--59e.xn----5jd; ᢌ.-\u085A; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚ +𥛛𑘶。𐹬𐲸\u0BCD; 𥛛𑘶.𐹬𐲸\u0BCD; [B1, V7]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬் +𥛛𑘶。𐹬𐲸\u0BCD; 𥛛𑘶.𐹬𐲸\u0BCD; [B1, V7]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬் +xn--jb2dj685c.xn--xmc5562kmcb; 𥛛𑘶.𐹬𐲸\u0BCD; [B1, V7]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬் +Ⴐ\u077F.\u200C; ⴐ\u077F.\u200C; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6, A4_2] # ⴐݿ. +Ⴐ\u077F.\u200C; ⴐ\u077F.\u200C; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6, A4_2] # ⴐݿ. +ⴐ\u077F.\u200C; ; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6, A4_2] # ⴐݿ. +xn--gqb743q.; ⴐ\u077F.; [B5, B6]; xn--gqb743q.; [B5, B6, A4_2]; ; # ⴐݿ. +xn--gqb743q.xn--0ug; ⴐ\u077F.\u200C; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; ; # ⴐݿ. +ⴐ\u077F.\u200C; ⴐ\u077F.\u200C; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6, A4_2] # ⴐݿ. +xn--gqb918b.; Ⴐ\u077F.; [B5, B6, V7]; xn--gqb918b.; [B5, B6, V7, A4_2]; ; # Ⴐݿ. +xn--gqb918b.xn--0ug; Ⴐ\u077F.\u200C; [B1, B5, B6, C1, V7]; xn--gqb918b.xn--0ug; ; ; # Ⴐݿ. +🄅𑲞-⒈。\u200Dᠩ\u06A5; 4,𑲞-⒈.\u200Dᠩ\u06A5; [B1, C2, V7, U1]; xn--4,--je4aw745l.xn--7jb180gexf; ; xn--4,--je4aw745l.xn--7jb180g; [B1, B5, B6, V7, U1] # 4,𑲞-⒈.ᠩڥ +4,𑲞-1.。\u200Dᠩ\u06A5; 4,𑲞-1..\u200Dᠩ\u06A5; [B1, C2, U1, X4_2]; xn--4,-1-w401a..xn--7jb180gexf; [B1, C2, U1, A4_2]; xn--4,-1-w401a..xn--7jb180g; [B1, B5, B6, U1, A4_2] # 4,𑲞-1..ᠩڥ +xn--4,-1-w401a..xn--7jb180g; 4,𑲞-1..ᠩ\u06A5; [B1, B5, B6, U1, X4_2]; xn--4,-1-w401a..xn--7jb180g; [B1, B5, B6, U1, A4_2]; ; # 4,𑲞-1..ᠩڥ +xn--4,-1-w401a..xn--7jb180gexf; 4,𑲞-1..\u200Dᠩ\u06A5; [B1, C2, U1, X4_2]; xn--4,-1-w401a..xn--7jb180gexf; [B1, C2, U1, A4_2]; ; # 4,𑲞-1..ᠩڥ +xn--4,--je4aw745l.xn--7jb180g; 4,𑲞-⒈.ᠩ\u06A5; [B1, B5, B6, V7, U1]; xn--4,--je4aw745l.xn--7jb180g; ; ; # 4,𑲞-⒈.ᠩڥ +xn--4,--je4aw745l.xn--7jb180gexf; 4,𑲞-⒈.\u200Dᠩ\u06A5; [B1, C2, V7, U1]; xn--4,--je4aw745l.xn--7jb180gexf; ; ; # 4,𑲞-⒈.ᠩڥ +xn----ecp8796hjtvg.xn--7jb180g; 🄅𑲞-⒈.ᠩ\u06A5; [B1, B5, B6, V7]; xn----ecp8796hjtvg.xn--7jb180g; ; ; # 🄅𑲞-⒈.ᠩڥ +xn----ecp8796hjtvg.xn--7jb180gexf; 🄅𑲞-⒈.\u200Dᠩ\u06A5; [B1, C2, V7]; xn----ecp8796hjtvg.xn--7jb180gexf; ; ; # 🄅𑲞-⒈.ᠩڥ +񗀤。𞤪򮿋; 񗀤.𞤪򮿋; [B2, B3, V7]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪 +񗀤。𞤈򮿋; 񗀤.𞤪򮿋; [B2, B3, V7]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪 +xn--4240a.xn--ie6h83808a; 񗀤.𞤪򮿋; [B2, B3, V7]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪 +\u05C1۲。𐮊\u066C𝨊鄨; \u05C1۲.𐮊\u066C𝨊鄨; [B1, B2, B3, V6]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨 +\u05C1۲。𐮊\u066C𝨊鄨; \u05C1۲.𐮊\u066C𝨊鄨; [B1, B2, B3, V6]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨 +xn--pdb42d.xn--lib6412enztdwv6h; \u05C1۲.𐮊\u066C𝨊鄨; [B1, B2, B3, V6]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨 +𞭳-ꡁ。\u1A69\u0BCD-; 𞭳-ꡁ.\u1A69\u0BCD-; [B1, B2, B3, V3, V6, V7]; xn----be4e4276f.xn----lze333i; ; ; # -ꡁ.ᩩ்- +xn----be4e4276f.xn----lze333i; 𞭳-ꡁ.\u1A69\u0BCD-; [B1, B2, B3, V3, V6, V7]; xn----be4e4276f.xn----lze333i; ; ; # -ꡁ.ᩩ்- +\u1039-𚮭🞢.ß; \u1039-𚮭🞢.ß; [V6, V7]; xn----9tg11172akr8b.xn--zca; ; xn----9tg11172akr8b.ss; # ္-🞢.ß +\u1039-𚮭🞢.ß; ; [V6, V7]; xn----9tg11172akr8b.xn--zca; ; xn----9tg11172akr8b.ss; # ္-🞢.ß +\u1039-𚮭🞢.SS; \u1039-𚮭🞢.ss; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +\u1039-𚮭🞢.ss; ; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +\u1039-𚮭🞢.Ss; \u1039-𚮭🞢.ss; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +xn----9tg11172akr8b.ss; \u1039-𚮭🞢.ss; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +xn----9tg11172akr8b.xn--zca; \u1039-𚮭🞢.ß; [V6, V7]; xn----9tg11172akr8b.xn--zca; ; ; # ္-🞢.ß +\u1039-𚮭🞢.SS; \u1039-𚮭🞢.ss; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +\u1039-𚮭🞢.ss; \u1039-𚮭🞢.ss; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +\u1039-𚮭🞢.Ss; \u1039-𚮭🞢.ss; [V6, V7]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss +\uFCF2-\u200C。Ⴟ\u200C␣; \u0640\u064E\u0651-\u200C.ⴟ\u200C␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣ +\u0640\u064E\u0651-\u200C。Ⴟ\u200C␣; \u0640\u064E\u0651-\u200C.ⴟ\u200C␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣ +\u0640\u064E\u0651-\u200C。ⴟ\u200C␣; \u0640\u064E\u0651-\u200C.ⴟ\u200C␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣ +xn----eoc6bm.xn--xph904a; \u0640\u064E\u0651-.ⴟ␣; [B3, B6, V3]; xn----eoc6bm.xn--xph904a; ; ; # ـَّ-.ⴟ␣ +xn----eoc6bm0504a.xn--0ug13nd0j; \u0640\u064E\u0651-\u200C.ⴟ\u200C␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; ; # ـَّ-.ⴟ␣ +\uFCF2-\u200C。ⴟ\u200C␣; \u0640\u064E\u0651-\u200C.ⴟ\u200C␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣ +xn----eoc6bm.xn--3nd240h; \u0640\u064E\u0651-.Ⴟ␣; [B3, B6, V3, V7]; xn----eoc6bm.xn--3nd240h; ; ; # ـَّ-.Ⴟ␣ +xn----eoc6bm0504a.xn--3nd849e05c; \u0640\u064E\u0651-\u200C.Ⴟ\u200C␣; [B3, B6, C1, V7]; xn----eoc6bm0504a.xn--3nd849e05c; ; ; # ـَّ-.Ⴟ␣ +\u0D4D-\u200D\u200C。񥞧₅≠; \u0D4D-\u200D\u200C.񥞧5≠; [C1, C2, V6, V7]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [V3, V6, V7] # ്-.5≠ +\u0D4D-\u200D\u200C。񥞧₅=\u0338; \u0D4D-\u200D\u200C.񥞧5≠; [C1, C2, V6, V7]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [V3, V6, V7] # ്-.5≠ +\u0D4D-\u200D\u200C。񥞧5≠; \u0D4D-\u200D\u200C.񥞧5≠; [C1, C2, V6, V7]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [V3, V6, V7] # ്-.5≠ +\u0D4D-\u200D\u200C。񥞧5=\u0338; \u0D4D-\u200D\u200C.񥞧5≠; [C1, C2, V6, V7]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [V3, V6, V7] # ്-.5≠ +xn----jmf.xn--5-ufo50192e; \u0D4D-.񥞧5≠; [V3, V6, V7]; xn----jmf.xn--5-ufo50192e; ; ; # ്-.5≠ +xn----jmf215lda.xn--5-ufo50192e; \u0D4D-\u200D\u200C.񥞧5≠; [C1, C2, V6, V7]; xn----jmf215lda.xn--5-ufo50192e; ; ; # ്-.5≠ +锣。\u0A4D󠘻󠚆; 锣.\u0A4D󠘻󠚆; [V6, V7]; xn--gc5a.xn--ybc83044ppga; ; ; # 锣.੍ +xn--gc5a.xn--ybc83044ppga; 锣.\u0A4D󠘻󠚆; [V6, V7]; xn--gc5a.xn--ybc83044ppga; ; ; # 锣.੍ +\u063D𑈾.\u0649\u200D\uA92B; \u063D𑈾.\u0649\u200D\uA92B; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; xn--8gb2338k.xn--lhb0154f; [] # ؽ𑈾.ى꤫ +\u063D𑈾.\u0649\u200D\uA92B; ; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; xn--8gb2338k.xn--lhb0154f; [] # ؽ𑈾.ى꤫ +xn--8gb2338k.xn--lhb0154f; \u063D𑈾.\u0649\uA92B; ; xn--8gb2338k.xn--lhb0154f; ; ; # ؽ𑈾.ى꤫ +\u063D𑈾.\u0649\uA92B; ; ; xn--8gb2338k.xn--lhb0154f; ; ; # ؽ𑈾.ى꤫ +xn--8gb2338k.xn--lhb603k060h; \u063D𑈾.\u0649\u200D\uA92B; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; ; # ؽ𑈾.ى꤫ +\u0666⁴Ⴅ.\u08BD\u200C; \u06664ⴅ.\u08BD\u200C; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ +\u06664Ⴅ.\u08BD\u200C; \u06664ⴅ.\u08BD\u200C; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ +\u06664ⴅ.\u08BD\u200C; ; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ +xn--4-kqc6770a.xn--jzb; \u06664ⴅ.\u08BD; [B1]; xn--4-kqc6770a.xn--jzb; ; ; # ٦4ⴅ.ࢽ +xn--4-kqc6770a.xn--jzb840j; \u06664ⴅ.\u08BD\u200C; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; ; # ٦4ⴅ.ࢽ +\u0666⁴ⴅ.\u08BD\u200C; \u06664ⴅ.\u08BD\u200C; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ +xn--4-kqc489e.xn--jzb; \u06664Ⴅ.\u08BD; [B1, V7]; xn--4-kqc489e.xn--jzb; ; ; # ٦4Ⴅ.ࢽ +xn--4-kqc489e.xn--jzb840j; \u06664Ⴅ.\u08BD\u200C; [B1, B3, C1, V7]; xn--4-kqc489e.xn--jzb840j; ; ; # ٦4Ⴅ.ࢽ +ჁႱ6\u0318。ß\u1B03; ⴡⴑ6\u0318.ß\u1B03; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ +ⴡⴑ6\u0318。ß\u1B03; ⴡⴑ6\u0318.ß\u1B03; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ +ჁႱ6\u0318。SS\u1B03; ⴡⴑ6\u0318.ss\u1B03; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +ⴡⴑ6\u0318。ss\u1B03; ⴡⴑ6\u0318.ss\u1B03; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +Ⴡⴑ6\u0318。Ss\u1B03; ⴡⴑ6\u0318.ss\u1B03; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +xn--6-8cb7433a2ba.xn--ss-2vq; ⴡⴑ6\u0318.ss\u1B03; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +ⴡⴑ6\u0318.ss\u1B03; ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +ჁႱ6\u0318.SS\u1B03; ⴡⴑ6\u0318.ss\u1B03; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +Ⴡⴑ6\u0318.Ss\u1B03; ⴡⴑ6\u0318.ss\u1B03; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ +xn--6-8cb7433a2ba.xn--zca894k; ⴡⴑ6\u0318.ß\u1B03; ; xn--6-8cb7433a2ba.xn--zca894k; ; ; # ⴡⴑ6̘.ßᬃ +ⴡⴑ6\u0318.ß\u1B03; ; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ +xn--6-8cb306hms1a.xn--ss-2vq; Ⴡⴑ6\u0318.ss\u1B03; [V7]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ +xn--6-8cb555h2b.xn--ss-2vq; ჁႱ6\u0318.ss\u1B03; [V7]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ +xn--6-8cb555h2b.xn--zca894k; ჁႱ6\u0318.ß\u1B03; [V7]; xn--6-8cb555h2b.xn--zca894k; ; ; # ჁႱ6̘.ßᬃ +򋡐。≯𑋪; 򋡐.≯𑋪; [V7]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪 +򋡐。>\u0338𑋪; 򋡐.≯𑋪; [V7]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪 +򋡐。≯𑋪; 򋡐.≯𑋪; [V7]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪 +򋡐。>\u0338𑋪; 򋡐.≯𑋪; [V7]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪 +xn--eo08b.xn--hdh3385g; 򋡐.≯𑋪; [V7]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪 +\u065A۲。\u200C-\u1BF3\u08E2; \u065A۲.\u200C-\u1BF3\u08E2; [B1, C1, V6, V7]; xn--2hb81a.xn----xrd657l30d; ; xn--2hb81a.xn----xrd657l; [B1, V3, V6, V7] # ٚ۲.-᯳ +xn--2hb81a.xn----xrd657l; \u065A۲.-\u1BF3\u08E2; [B1, V3, V6, V7]; xn--2hb81a.xn----xrd657l; ; ; # ٚ۲.-᯳ +xn--2hb81a.xn----xrd657l30d; \u065A۲.\u200C-\u1BF3\u08E2; [B1, C1, V6, V7]; xn--2hb81a.xn----xrd657l30d; ; ; # ٚ۲.-᯳ +󠄏𖬴󠲽。\uFFA0; 𖬴󠲽.; [V6, V7]; xn--619ep9154c.; [V6, V7, A4_2]; ; # 𖬴. +󠄏𖬴󠲽。\u1160; 𖬴󠲽.; [V6, V7]; xn--619ep9154c.; [V6, V7, A4_2]; ; # 𖬴. +xn--619ep9154c.; 𖬴󠲽.; [V6, V7]; xn--619ep9154c.; [V6, V7, A4_2]; ; # 𖬴. +xn--619ep9154c.xn--psd; 𖬴󠲽.\u1160; [V6, V7]; xn--619ep9154c.xn--psd; ; ; # 𖬴. +xn--619ep9154c.xn--cl7c; 𖬴󠲽.\uFFA0; [V6, V7]; xn--619ep9154c.xn--cl7c; ; ; # 𖬴. +ß⒈\u0760\uD7AE.􉖲󠅄\u0605򉔯; ß⒈\u0760\uD7AE.􉖲\u0605򉔯; [B5, V7]; xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; # ß⒈ݠ. +ß1.\u0760\uD7AE.􉖲󠅄\u0605򉔯; ß1.\u0760\uD7AE.􉖲\u0605򉔯; [B2, B3, B5, V7]; xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; # ß1.ݠ. +SS1.\u0760\uD7AE.􉖲󠅄\u0605򉔯; ss1.\u0760\uD7AE.􉖲\u0605򉔯; [B2, B3, B5, V7]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ. +ss1.\u0760\uD7AE.􉖲󠅄\u0605򉔯; ss1.\u0760\uD7AE.􉖲\u0605򉔯; [B2, B3, B5, V7]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ. +Ss1.\u0760\uD7AE.􉖲󠅄\u0605򉔯; ss1.\u0760\uD7AE.􉖲\u0605򉔯; [B2, B3, B5, V7]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ. +ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ss1.\u0760\uD7AE.􉖲\u0605򉔯; [B2, B3, B5, V7]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ. +xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ß1.\u0760\uD7AE.􉖲\u0605򉔯; [B2, B3, B5, V7]; xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ß1.ݠ. +SS⒈\u0760\uD7AE.􉖲󠅄\u0605򉔯; ss⒈\u0760\uD7AE.􉖲\u0605򉔯; [B5, V7]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ. +ss⒈\u0760\uD7AE.􉖲󠅄\u0605򉔯; ss⒈\u0760\uD7AE.􉖲\u0605򉔯; [B5, V7]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ. +Ss⒈\u0760\uD7AE.􉖲󠅄\u0605򉔯; ss⒈\u0760\uD7AE.􉖲\u0605򉔯; [B5, V7]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ. +xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ss⒈\u0760\uD7AE.􉖲\u0605򉔯; [B5, V7]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ. +xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ß⒈\u0760\uD7AE.􉖲\u0605򉔯; [B5, V7]; xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ; ; # ß⒈ݠ. +󠭔.𐋱₂; 󠭔.𐋱2; [V7]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2 +󠭔.𐋱2; ; [V7]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2 +xn--vi56e.xn--2-w91i; 󠭔.𐋱2; [V7]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2 +\u0716\u0947。-ß\u06A5\u200C; \u0716\u0947.-ß\u06A5\u200C; [B1, C1, V3]; xn--gnb63i.xn----qfa845bhx4a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ßڥ +\u0716\u0947。-SS\u06A5\u200C; \u0716\u0947.-ss\u06A5\u200C; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ +\u0716\u0947。-ss\u06A5\u200C; \u0716\u0947.-ss\u06A5\u200C; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ +\u0716\u0947。-Ss\u06A5\u200C; \u0716\u0947.-ss\u06A5\u200C; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ +xn--gnb63i.xn---ss-4ef; \u0716\u0947.-ss\u06A5; [B1, V3]; xn--gnb63i.xn---ss-4ef; ; ; # ܖे.-ssڥ +xn--gnb63i.xn---ss-4ef9263a; \u0716\u0947.-ss\u06A5\u200C; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; ; # ܖे.-ssڥ +xn--gnb63i.xn----qfa845bhx4a; \u0716\u0947.-ß\u06A5\u200C; [B1, C1, V3]; xn--gnb63i.xn----qfa845bhx4a; ; ; # ܖे.-ßڥ +\u1BA9\u200D\u062A񡚈.\u1CD5䷉Ⴡ; \u1BA9\u200D\u062A񡚈.\u1CD5䷉ⴡ; [B1, C2, V6, V7]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, V6, V7] # ᮩت.᳕䷉ⴡ +\u1BA9\u200D\u062A񡚈.\u1CD5䷉Ⴡ; \u1BA9\u200D\u062A񡚈.\u1CD5䷉ⴡ; [B1, C2, V6, V7]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, V6, V7] # ᮩت.᳕䷉ⴡ +\u1BA9\u200D\u062A񡚈.\u1CD5䷉ⴡ; ; [B1, C2, V6, V7]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, V6, V7] # ᮩت.᳕䷉ⴡ +xn--pgb911izv33i.xn--i6f270etuy; \u1BA9\u062A񡚈.\u1CD5䷉ⴡ; [B1, V6, V7]; xn--pgb911izv33i.xn--i6f270etuy; ; ; # ᮩت.᳕䷉ⴡ +xn--pgb911imgdrw34r.xn--i6f270etuy; \u1BA9\u200D\u062A񡚈.\u1CD5䷉ⴡ; [B1, C2, V6, V7]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; ; # ᮩت.᳕䷉ⴡ +\u1BA9\u200D\u062A񡚈.\u1CD5䷉ⴡ; \u1BA9\u200D\u062A񡚈.\u1CD5䷉ⴡ; [B1, C2, V6, V7]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, V6, V7] # ᮩت.᳕䷉ⴡ +xn--pgb911izv33i.xn--5nd792dgv3b; \u1BA9\u062A񡚈.\u1CD5䷉Ⴡ; [B1, V6, V7]; xn--pgb911izv33i.xn--5nd792dgv3b; ; ; # ᮩت.᳕䷉Ⴡ +xn--pgb911imgdrw34r.xn--5nd792dgv3b; \u1BA9\u200D\u062A񡚈.\u1CD5䷉Ⴡ; [B1, C2, V6, V7]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; ; # ᮩت.᳕䷉Ⴡ +\u2DBF.ß\u200D; ; [C2, V7]; xn--7pj.xn--zca870n; ; xn--7pj.ss; [V7] # .ß +\u2DBF.SS\u200D; \u2DBF.ss\u200D; [C2, V7]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [V7] # .ss +\u2DBF.ss\u200D; ; [C2, V7]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [V7] # .ss +\u2DBF.Ss\u200D; \u2DBF.ss\u200D; [C2, V7]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [V7] # .ss +xn--7pj.ss; \u2DBF.ss; [V7]; xn--7pj.ss; ; ; # .ss +xn--7pj.xn--ss-n1t; \u2DBF.ss\u200D; [C2, V7]; xn--7pj.xn--ss-n1t; ; ; # .ss +xn--7pj.xn--zca870n; \u2DBF.ß\u200D; [C2, V7]; xn--7pj.xn--zca870n; ; ; # .ß +\u1BF3︒.\u062A≯ꡂ; ; [B2, B3, B6, V6, V7]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ +\u1BF3︒.\u062A>\u0338ꡂ; \u1BF3︒.\u062A≯ꡂ; [B2, B3, B6, V6, V7]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ +\u1BF3。.\u062A≯ꡂ; \u1BF3..\u062A≯ꡂ; [B2, B3, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, V6, A4_2]; ; # ᯳..ت≯ꡂ +\u1BF3。.\u062A>\u0338ꡂ; \u1BF3..\u062A≯ꡂ; [B2, B3, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, V6, A4_2]; ; # ᯳..ت≯ꡂ +xn--1zf..xn--pgb885lry5g; \u1BF3..\u062A≯ꡂ; [B2, B3, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, V6, A4_2]; ; # ᯳..ت≯ꡂ +xn--1zf8957g.xn--pgb885lry5g; \u1BF3︒.\u062A≯ꡂ; [B2, B3, B6, V6, V7]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ +≮≠񏻃。-𫠆\u06B7𐹪; ≮≠񏻃.-𫠆\u06B7𐹪; [B1, V3, V7]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪 +<\u0338=\u0338񏻃。-𫠆\u06B7𐹪; ≮≠񏻃.-𫠆\u06B7𐹪; [B1, V3, V7]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪 +≮≠񏻃。-𫠆\u06B7𐹪; ≮≠񏻃.-𫠆\u06B7𐹪; [B1, V3, V7]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪 +<\u0338=\u0338񏻃。-𫠆\u06B7𐹪; ≮≠񏻃.-𫠆\u06B7𐹪; [B1, V3, V7]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪 +xn--1ch1a29470f.xn----7uc5363rc1rn; ≮≠񏻃.-𫠆\u06B7𐹪; [B1, V3, V7]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪 +𐹡\u0777。ꡂ; 𐹡\u0777.ꡂ; [B1]; xn--7pb5275k.xn--bc9a; ; ; # 𐹡ݷ.ꡂ +xn--7pb5275k.xn--bc9a; 𐹡\u0777.ꡂ; [B1]; xn--7pb5275k.xn--bc9a; ; ; # 𐹡ݷ.ꡂ +Ⴉ𝆅񔻅\u0619.ß𐧦𐹳\u0775; ⴉ𝆅񔻅\u0619.ß𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; # ⴉؙ𝆅.ß𐧦𐹳ݵ +ⴉ𝆅񔻅\u0619.ß𐧦𐹳\u0775; ; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; # ⴉؙ𝆅.ß𐧦𐹳ݵ +Ⴉ𝆅񔻅\u0619.SS𐧦𐹳\u0775; ⴉ𝆅񔻅\u0619.ss𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ +ⴉ𝆅񔻅\u0619.ss𐧦𐹳\u0775; ; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ +Ⴉ𝆅񔻅\u0619.Ss𐧦𐹳\u0775; ⴉ𝆅񔻅\u0619.ss𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ +xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ⴉ𝆅񔻅\u0619.ss𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ +xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ⴉ𝆅񔻅\u0619.ß𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; ; # ⴉؙ𝆅.ß𐧦𐹳ݵ +xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; Ⴉ𝆅񔻅\u0619.ss𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ +xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; Ⴉ𝆅񔻅\u0619.ß𐧦𐹳\u0775; [B5, B6, V7]; xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; ; ; # Ⴉؙ𝆅.ß𐧦𐹳ݵ +\u200D\u0643𐧾↙.񊽡; ; [B1, C2, V7]; xn--fhb713k87ag053c.xn--7s4w; ; xn--fhb011lnp8n.xn--7s4w; [B3, V7] # ك𐧾↙. +xn--fhb011lnp8n.xn--7s4w; \u0643𐧾↙.񊽡; [B3, V7]; xn--fhb011lnp8n.xn--7s4w; ; ; # ك𐧾↙. +xn--fhb713k87ag053c.xn--7s4w; \u200D\u0643𐧾↙.񊽡; [B1, C2, V7]; xn--fhb713k87ag053c.xn--7s4w; ; ; # ك𐧾↙. +梉。\u200C; 梉.\u200C; [C1]; xn--7zv.xn--0ug; ; xn--7zv.; [A4_2] # 梉. +xn--7zv.; 梉.; ; xn--7zv.; [A4_2]; ; # 梉. +梉.; ; ; xn--7zv.; [A4_2]; ; # 梉. +xn--7zv.xn--0ug; 梉.\u200C; [C1]; xn--7zv.xn--0ug; ; ; # 梉. +ꡣ-≠.\u200D𞤗𐅢Ↄ; ꡣ-≠.\u200D𞤹𐅢ↄ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6] # ꡣ-≠.𞤹𐅢ↄ +ꡣ-=\u0338.\u200D𞤗𐅢Ↄ; ꡣ-≠.\u200D𞤹𐅢ↄ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6] # ꡣ-≠.𞤹𐅢ↄ +ꡣ-=\u0338.\u200D𞤹𐅢ↄ; ꡣ-≠.\u200D𞤹𐅢ↄ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6] # ꡣ-≠.𞤹𐅢ↄ +ꡣ-≠.\u200D𞤹𐅢ↄ; ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6] # ꡣ-≠.𞤹𐅢ↄ +ꡣ-≠.\u200D𞤗𐅢ↄ; ꡣ-≠.\u200D𞤹𐅢ↄ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6] # ꡣ-≠.𞤹𐅢ↄ +ꡣ-=\u0338.\u200D𞤗𐅢ↄ; ꡣ-≠.\u200D𞤹𐅢ↄ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6] # ꡣ-≠.𞤹𐅢ↄ +xn----ufo9661d.xn--r5gy929fhm4f; ꡣ-≠.𞤹𐅢ↄ; [B2, B3, B6]; xn----ufo9661d.xn--r5gy929fhm4f; ; ; # ꡣ-≠.𞤹𐅢ↄ +xn----ufo9661d.xn--1ug99cj620c71sh; ꡣ-≠.\u200D𞤹𐅢ↄ; [B1, B6, C2]; xn----ufo9661d.xn--1ug99cj620c71sh; ; ; # ꡣ-≠.𞤹𐅢ↄ +xn----ufo9661d.xn--q5g0929fhm4f; ꡣ-≠.𞤹𐅢Ↄ; [B2, B3, B6, V7]; xn----ufo9661d.xn--q5g0929fhm4f; ; ; # ꡣ-≠.𞤹𐅢Ↄ +xn----ufo9661d.xn--1ug79cm620c71sh; ꡣ-≠.\u200D𞤹𐅢Ↄ; [B1, B6, C2, V7]; xn----ufo9661d.xn--1ug79cm620c71sh; ; ; # ꡣ-≠.𞤹𐅢Ↄ +ς⒐𝆫⸵。𐱢🄊𝟳; ς⒐𝆫⸵.𐱢9,7; [B6, V7, U1]; xn--3xa019nwtghi25b.xn--9,7-r67t; ; xn--4xa809nwtghi25b.xn--9,7-r67t; # ς⒐𝆫⸵.9,7 +ς9.𝆫⸵。𐱢9,7; ς9.𝆫⸵.𐱢9,7; [B1, V6, V7, U1]; xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; # ς9.𝆫⸵.9,7 +Σ9.𝆫⸵。𐱢9,7; σ9.𝆫⸵.𐱢9,7; [B1, V6, V7, U1]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7 +σ9.𝆫⸵。𐱢9,7; σ9.𝆫⸵.𐱢9,7; [B1, V6, V7, U1]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7 +xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; σ9.𝆫⸵.𐱢9,7; [B1, V6, V7, U1]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7 +xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ς9.𝆫⸵.𐱢9,7; [B1, V6, V7, U1]; xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ; ; # ς9.𝆫⸵.9,7 +Σ⒐𝆫⸵。𐱢🄊𝟳; σ⒐𝆫⸵.𐱢9,7; [B6, V7, U1]; xn--4xa809nwtghi25b.xn--9,7-r67t; ; ; # σ⒐𝆫⸵.9,7 +σ⒐𝆫⸵。𐱢🄊𝟳; σ⒐𝆫⸵.𐱢9,7; [B6, V7, U1]; xn--4xa809nwtghi25b.xn--9,7-r67t; ; ; # σ⒐𝆫⸵.9,7 +xn--4xa809nwtghi25b.xn--9,7-r67t; σ⒐𝆫⸵.𐱢9,7; [B6, V7, U1]; xn--4xa809nwtghi25b.xn--9,7-r67t; ; ; # σ⒐𝆫⸵.9,7 +xn--3xa019nwtghi25b.xn--9,7-r67t; ς⒐𝆫⸵.𐱢9,7; [B6, V7, U1]; xn--3xa019nwtghi25b.xn--9,7-r67t; ; ; # ς⒐𝆫⸵.9,7 +xn--4xa809nwtghi25b.xn--7-075iy877c; σ⒐𝆫⸵.𐱢🄊7; [B6, V7]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7 +xn--3xa019nwtghi25b.xn--7-075iy877c; ς⒐𝆫⸵.𐱢🄊7; [B6, V7]; xn--3xa019nwtghi25b.xn--7-075iy877c; ; ; # ς⒐𝆫⸵.🄊7 +\u0853.\u200Cß; \u0853.\u200Cß; [B1, C1]; xn--iwb.xn--zca570n; ; xn--iwb.ss; [] # ࡓ.ß +\u0853.\u200Cß; ; [B1, C1]; xn--iwb.xn--zca570n; ; xn--iwb.ss; [] # ࡓ.ß +\u0853.\u200CSS; \u0853.\u200Css; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss +\u0853.\u200Css; ; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss +xn--iwb.ss; \u0853.ss; ; xn--iwb.ss; ; ; # ࡓ.ss +\u0853.ss; ; ; xn--iwb.ss; ; ; # ࡓ.ss +\u0853.SS; \u0853.ss; ; xn--iwb.ss; ; ; # ࡓ.ss +xn--iwb.xn--ss-i1t; \u0853.\u200Css; [B1, C1]; xn--iwb.xn--ss-i1t; ; ; # ࡓ.ss +xn--iwb.xn--zca570n; \u0853.\u200Cß; [B1, C1]; xn--iwb.xn--zca570n; ; ; # ࡓ.ß +\u0853.\u200CSS; \u0853.\u200Css; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss +\u0853.\u200Css; \u0853.\u200Css; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss +\u0853.\u200CSs; \u0853.\u200Css; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss +\u0853.\u200CSs; \u0853.\u200Css; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss +񯶣-.\u200D\u074E\uA94D󠻨; ; [B1, B6, C2, V3, V7]; xn----s116e.xn--1ob387jy90hq459k; ; xn----s116e.xn--1ob6504fmf40i; [B3, B6, V3, V7] # -.ݎꥍ +xn----s116e.xn--1ob6504fmf40i; 񯶣-.\u074E\uA94D󠻨; [B3, B6, V3, V7]; xn----s116e.xn--1ob6504fmf40i; ; ; # -.ݎꥍ +xn----s116e.xn--1ob387jy90hq459k; 񯶣-.\u200D\u074E\uA94D󠻨; [B1, B6, C2, V3, V7]; xn----s116e.xn--1ob387jy90hq459k; ; ; # -.ݎꥍ +䃚蟥-。-񽒘⒈; 䃚蟥-.-񽒘⒈; [V3, V7]; xn----n50a258u.xn----ecp33805f; ; ; # 䃚蟥-.-⒈ +䃚蟥-。-񽒘1.; 䃚蟥-.-񽒘1.; [V3, V7]; xn----n50a258u.xn---1-up07j.; [V3, V7, A4_2]; ; # 䃚蟥-.-1. +xn----n50a258u.xn---1-up07j.; 䃚蟥-.-񽒘1.; [V3, V7]; xn----n50a258u.xn---1-up07j.; [V3, V7, A4_2]; ; # 䃚蟥-.-1. +xn----n50a258u.xn----ecp33805f; 䃚蟥-.-񽒘⒈; [V3, V7]; xn----n50a258u.xn----ecp33805f; ; ; # 䃚蟥-.-⒈ +𐹸䚵-ꡡ。⺇; 𐹸䚵-ꡡ.⺇; [B1]; xn----bm3an932a1l5d.xn--xvj; ; ; # 𐹸䚵-ꡡ.⺇ +xn----bm3an932a1l5d.xn--xvj; 𐹸䚵-ꡡ.⺇; [B1]; xn----bm3an932a1l5d.xn--xvj; ; ; # 𐹸䚵-ꡡ.⺇ +𑄳。\u1ADC𐹻; 𑄳.\u1ADC𐹻; [B1, B5, B6, V6, V7]; xn--v80d.xn--2rf1154i; ; ; # 𑄳.𐹻 +xn--v80d.xn--2rf1154i; 𑄳.\u1ADC𐹻; [B1, B5, B6, V6, V7]; xn--v80d.xn--2rf1154i; ; ; # 𑄳.𐹻 +≮𐹻.⒎𑂵\u06BA\u0602; ; [B1, V7]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں +<\u0338𐹻.⒎𑂵\u06BA\u0602; ≮𐹻.⒎𑂵\u06BA\u0602; [B1, V7]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں +≮𐹻.7.𑂵\u06BA\u0602; ; [B1, V6, V7]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں +<\u0338𐹻.7.𑂵\u06BA\u0602; ≮𐹻.7.𑂵\u06BA\u0602; [B1, V6, V7]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں +xn--gdhx904g.7.xn--kfb18an307d; ≮𐹻.7.𑂵\u06BA\u0602; [B1, V6, V7]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں +xn--gdhx904g.xn--kfb18a325efm3s; ≮𐹻.⒎𑂵\u06BA\u0602; [B1, V7]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں +ᢔ≠􋉂.\u200D𐋢; ; [C2, V7]; xn--ebf031cf7196a.xn--1ug9540g; ; xn--ebf031cf7196a.xn--587c; [V7] # ᢔ≠.𐋢 +ᢔ=\u0338􋉂.\u200D𐋢; ᢔ≠􋉂.\u200D𐋢; [C2, V7]; xn--ebf031cf7196a.xn--1ug9540g; ; xn--ebf031cf7196a.xn--587c; [V7] # ᢔ≠.𐋢 +xn--ebf031cf7196a.xn--587c; ᢔ≠􋉂.𐋢; [V7]; xn--ebf031cf7196a.xn--587c; ; ; # ᢔ≠.𐋢 +xn--ebf031cf7196a.xn--1ug9540g; ᢔ≠􋉂.\u200D𐋢; [C2, V7]; xn--ebf031cf7196a.xn--1ug9540g; ; ; # ᢔ≠.𐋢 +𐩁≮񣊛≯.\u066C𞵕⳿; 𐩁≮񣊛≯.\u066C𞵕⳿; [B1, B2, B3, V7]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿ +𐩁<\u0338񣊛>\u0338.\u066C𞵕⳿; 𐩁≮񣊛≯.\u066C𞵕⳿; [B1, B2, B3, V7]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿ +𐩁≮񣊛≯.\u066C𞵕⳿; ; [B1, B2, B3, V7]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿ +𐩁<\u0338񣊛>\u0338.\u066C𞵕⳿; 𐩁≮񣊛≯.\u066C𞵕⳿; [B1, B2, B3, V7]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿ +xn--gdhc0519o0y27b.xn--lib468q0d21a; 𐩁≮񣊛≯.\u066C𞵕⳿; [B1, B2, B3, V7]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿ +-。⺐; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐ +-。⺐; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐ +-.xn--6vj; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐ +󠰩𑲬.\u065C; 󠰩𑲬.\u065C; [V6, V7]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ +󠰩𑲬.\u065C; ; [V6, V7]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ +xn--sn3d59267c.xn--4hb; 󠰩𑲬.\u065C; [V6, V7]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ +𐍺.񚇃\u200C; ; [C1, V6, V7]; xn--ie8c.xn--0ug03366c; ; xn--ie8c.xn--2g51a; [V6, V7] # 𐍺. +xn--ie8c.xn--2g51a; 𐍺.񚇃; [V6, V7]; xn--ie8c.xn--2g51a; ; ; # 𐍺. +xn--ie8c.xn--0ug03366c; 𐍺.񚇃\u200C; [C1, V6, V7]; xn--ie8c.xn--0ug03366c; ; ; # 𐍺. +\u063D\u06E3.𐨎; ; [B1, V6]; xn--8gb64a.xn--mr9c; ; ; # ؽۣ.𐨎 +xn--8gb64a.xn--mr9c; \u063D\u06E3.𐨎; [B1, V6]; xn--8gb64a.xn--mr9c; ; ; # ؽۣ.𐨎 +漦Ⴙς.񡻀𐴄; 漦ⴙς.񡻀𐴄; [B5, B6, V7]; xn--3xa972sl47b.xn--9d0d3162t; ; xn--4xa772sl47b.xn--9d0d3162t; # 漦ⴙς.𐴄 +漦ⴙς.񡻀𐴄; ; [B5, B6, V7]; xn--3xa972sl47b.xn--9d0d3162t; ; xn--4xa772sl47b.xn--9d0d3162t; # 漦ⴙς.𐴄 +漦ႹΣ.񡻀𐴄; 漦ⴙσ.񡻀𐴄; [B5, B6, V7]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄 +漦ⴙσ.񡻀𐴄; ; [B5, B6, V7]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄 +漦Ⴙσ.񡻀𐴄; 漦ⴙσ.񡻀𐴄; [B5, B6, V7]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄 +xn--4xa772sl47b.xn--9d0d3162t; 漦ⴙσ.񡻀𐴄; [B5, B6, V7]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄 +xn--3xa972sl47b.xn--9d0d3162t; 漦ⴙς.񡻀𐴄; [B5, B6, V7]; xn--3xa972sl47b.xn--9d0d3162t; ; ; # 漦ⴙς.𐴄 +xn--4xa947d717e.xn--9d0d3162t; 漦Ⴙσ.񡻀𐴄; [B5, B6, V7]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄 +xn--3xa157d717e.xn--9d0d3162t; 漦Ⴙς.񡻀𐴄; [B5, B6, V7]; xn--3xa157d717e.xn--9d0d3162t; ; ; # 漦Ⴙς.𐴄 +𐹫踧\u0CCD򫚇.󜀃⒈𝨤; ; [B1, V7]; xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; ; ; # 𐹫踧್.⒈𝨤 +𐹫踧\u0CCD򫚇.󜀃1.𝨤; ; [B1, V6, V7]; xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; ; ; # 𐹫踧್.1.𝨤 +xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; 𐹫踧\u0CCD򫚇.󜀃1.𝨤; [B1, V6, V7]; xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; ; ; # 𐹫踧್.1.𝨤 +xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; 𐹫踧\u0CCD򫚇.󜀃⒈𝨤; [B1, V7]; xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; ; ; # 𐹫踧್.⒈𝨤 +\u200D≮.󠟪𹫏-; \u200D≮.󠟪𹫏-; [C2, V3, V7]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [V3, V7] # ≮.- +\u200D<\u0338.󠟪𹫏-; \u200D≮.󠟪𹫏-; [C2, V3, V7]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [V3, V7] # ≮.- +\u200D≮.󠟪𹫏-; ; [C2, V3, V7]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [V3, V7] # ≮.- +\u200D<\u0338.󠟪𹫏-; \u200D≮.󠟪𹫏-; [C2, V3, V7]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [V3, V7] # ≮.- +xn--gdh.xn----cr99a1w710b; ≮.󠟪𹫏-; [V3, V7]; xn--gdh.xn----cr99a1w710b; ; ; # ≮.- +xn--1ug95g.xn----cr99a1w710b; \u200D≮.󠟪𹫏-; [C2, V3, V7]; xn--1ug95g.xn----cr99a1w710b; ; ; # ≮.- +\u200D\u200D襔。Ⴜ5ꡮ񵝏; \u200D\u200D襔.ⴜ5ꡮ񵝏; [C2, V7]; xn--1uga7691f.xn--5-uws5848bpf44e; ; xn--2u2a.xn--5-uws5848bpf44e; [V7] # 襔.ⴜ5ꡮ +\u200D\u200D襔。ⴜ5ꡮ񵝏; \u200D\u200D襔.ⴜ5ꡮ񵝏; [C2, V7]; xn--1uga7691f.xn--5-uws5848bpf44e; ; xn--2u2a.xn--5-uws5848bpf44e; [V7] # 襔.ⴜ5ꡮ +xn--2u2a.xn--5-uws5848bpf44e; 襔.ⴜ5ꡮ񵝏; [V7]; xn--2u2a.xn--5-uws5848bpf44e; ; ; # 襔.ⴜ5ꡮ +xn--1uga7691f.xn--5-uws5848bpf44e; \u200D\u200D襔.ⴜ5ꡮ񵝏; [C2, V7]; xn--1uga7691f.xn--5-uws5848bpf44e; ; ; # 襔.ⴜ5ꡮ +xn--2u2a.xn--5-r1g7167ipfw8d; 襔.Ⴜ5ꡮ񵝏; [V7]; xn--2u2a.xn--5-r1g7167ipfw8d; ; ; # 襔.Ⴜ5ꡮ +xn--1uga7691f.xn--5-r1g7167ipfw8d; \u200D\u200D襔.Ⴜ5ꡮ񵝏; [C2, V7]; xn--1uga7691f.xn--5-r1g7167ipfw8d; ; ; # 襔.Ⴜ5ꡮ +𐫜𑌼\u200D.婀; 𐫜𑌼\u200D.婀; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; xn--ix9c26l.xn--q0s; [] # 𐫜𑌼.婀 +𐫜𑌼\u200D.婀; ; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; xn--ix9c26l.xn--q0s; [] # 𐫜𑌼.婀 +xn--ix9c26l.xn--q0s; 𐫜𑌼.婀; ; xn--ix9c26l.xn--q0s; ; ; # 𐫜𑌼.婀 +𐫜𑌼.婀; ; ; xn--ix9c26l.xn--q0s; ; ; # 𐫜𑌼.婀 +xn--1ugx063g1if.xn--q0s; 𐫜𑌼\u200D.婀; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; ; # 𐫜𑌼.婀 +󠅽︒︒𐹯。⬳\u1A78; ︒︒𐹯.⬳\u1A78; [B1, V7]; xn--y86ca186j.xn--7of309e; ; ; # ︒︒𐹯.⬳᩸ +󠅽。。𐹯。⬳\u1A78; ..𐹯.⬳\u1A78; [B1, X4_2]; ..xn--no0d.xn--7of309e; [B1, A4_2]; ; # ..𐹯.⬳᩸ +..xn--no0d.xn--7of309e; ..𐹯.⬳\u1A78; [B1, X4_2]; ..xn--no0d.xn--7of309e; [B1, A4_2]; ; # ..𐹯.⬳᩸ +xn--y86ca186j.xn--7of309e; ︒︒𐹯.⬳\u1A78; [B1, V7]; xn--y86ca186j.xn--7of309e; ; ; # ︒︒𐹯.⬳᩸ +𝟖ß.󠄐-?Ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ +8ß.󠄐-?Ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ +8ß.󠄐-?ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ +8SS.󠄐-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8ss.󠄐-?ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8ss.󠄐-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8ss.xn---?-261a; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +xn--8-qfa.xn---?-261a; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ +𝟖ß.󠄐-?ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ +𝟖SS.󠄐-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +𝟖ss.󠄐-?ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +𝟖ss.󠄐-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8ss.xn---?-gfk; 8ss.-?Ⴏ; [V3, V7, U1]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ +xn--8-qfa.xn---?-gfk; 8ß.-?Ⴏ; [V3, V7, U1]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ +8ss.-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8ss.-?ⴏ; ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8SS.-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +xn--8-qfa.-?ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ +XN--8-QFA.-?Ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ +Xn--8-Qfa.-?Ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ +xn--8-qfa.-?Ⴏ; 8ß.-?ⴏ; [V3, U1]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ +𝟖Ss.󠄐-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +8Ss.󠄐-?Ⴏ; 8ss.-?ⴏ; [V3, U1]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ +-\u200D󠋟.\u200C𐹣Ⴅ; -\u200D󠋟.\u200C𐹣ⴅ; [B1, C1, C2, V3, V7]; xn----ugnv7071n.xn--0ugz32cgr0p; ; xn----s721m.xn--wkj1423e; [B1, V3, V7] # -.𐹣ⴅ +-\u200D󠋟.\u200C𐹣ⴅ; ; [B1, C1, C2, V3, V7]; xn----ugnv7071n.xn--0ugz32cgr0p; ; xn----s721m.xn--wkj1423e; [B1, V3, V7] # -.𐹣ⴅ +xn----s721m.xn--wkj1423e; -󠋟.𐹣ⴅ; [B1, V3, V7]; xn----s721m.xn--wkj1423e; ; ; # -.𐹣ⴅ +xn----ugnv7071n.xn--0ugz32cgr0p; -\u200D󠋟.\u200C𐹣ⴅ; [B1, C1, C2, V3, V7]; xn----ugnv7071n.xn--0ugz32cgr0p; ; ; # -.𐹣ⴅ +xn----s721m.xn--dnd9201k; -󠋟.𐹣Ⴅ; [B1, V3, V7]; xn----s721m.xn--dnd9201k; ; ; # -.𐹣Ⴅ +xn----ugnv7071n.xn--dnd999e4j4p; -\u200D󠋟.\u200C𐹣Ⴅ; [B1, C1, C2, V3, V7]; xn----ugnv7071n.xn--dnd999e4j4p; ; ; # -.𐹣Ⴅ +\uA9B9\u200D큷𻶡。₂; \uA9B9\u200D큷𻶡.2; [C2, V6, V7]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [V6, V7] # ꦹ큷.2 +\uA9B9\u200D큷𻶡。₂; \uA9B9\u200D큷𻶡.2; [C2, V6, V7]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [V6, V7] # ꦹ큷.2 +\uA9B9\u200D큷𻶡。2; \uA9B9\u200D큷𻶡.2; [C2, V6, V7]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [V6, V7] # ꦹ큷.2 +\uA9B9\u200D큷𻶡。2; \uA9B9\u200D큷𻶡.2; [C2, V6, V7]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [V6, V7] # ꦹ큷.2 +xn--0m9as84e2e21c.c; \uA9B9큷𻶡.c; [V6, V7]; xn--0m9as84e2e21c.c; ; ; # ꦹ큷.c +xn--1ug1435cfkyaoi04d.c; \uA9B9\u200D큷𻶡.c; [C2, V6, V7]; xn--1ug1435cfkyaoi04d.c; ; ; # ꦹ큷.c +?.🄄𞯘; ?.3,𞯘; [B1, V7, U1]; ?.xn--3,-tb22a; ; ; # ?.3, +?.3,𞯘; ; [B1, V7, U1]; ?.xn--3,-tb22a; ; ; # ?.3, +?.xn--3,-tb22a; ?.3,𞯘; [B1, V7, U1]; ?.xn--3,-tb22a; ; ; # ?.3, +?.xn--3x6hx6f; ?.🄄𞯘; [B1, V7, U1]; ?.xn--3x6hx6f; ; ; # ?.🄄 +𝨖𐩙。\u06DD󀡶\uA8C5⒈; 𝨖𐩙.\u06DD󀡶\uA8C5⒈; [B1, V6, V7]; xn--rt9cl956a.xn--tlb403mxv4g06s9i; ; ; # 𝨖.ꣅ⒈ +𝨖𐩙。\u06DD󀡶\uA8C51.; 𝨖𐩙.\u06DD󀡶\uA8C51.; [B1, V6, V7]; xn--rt9cl956a.xn--1-dxc8545j0693i.; [B1, V6, V7, A4_2]; ; # 𝨖.ꣅ1. +xn--rt9cl956a.xn--1-dxc8545j0693i.; 𝨖𐩙.\u06DD󀡶\uA8C51.; [B1, V6, V7]; xn--rt9cl956a.xn--1-dxc8545j0693i.; [B1, V6, V7, A4_2]; ; # 𝨖.ꣅ1. +xn--rt9cl956a.xn--tlb403mxv4g06s9i; 𝨖𐩙.\u06DD󀡶\uA8C5⒈; [B1, V6, V7]; xn--rt9cl956a.xn--tlb403mxv4g06s9i; ; ; # 𝨖.ꣅ⒈ +򒈣\u05E1\u06B8。Ⴈ\u200D; 򒈣\u05E1\u06B8.ⴈ\u200D; [B5, B6, C2, V7]; xn--meb44b57607c.xn--1ug232c; ; xn--meb44b57607c.xn--zkj; [B5, B6, V7] # סڸ.ⴈ +򒈣\u05E1\u06B8。ⴈ\u200D; 򒈣\u05E1\u06B8.ⴈ\u200D; [B5, B6, C2, V7]; xn--meb44b57607c.xn--1ug232c; ; xn--meb44b57607c.xn--zkj; [B5, B6, V7] # סڸ.ⴈ +xn--meb44b57607c.xn--zkj; 򒈣\u05E1\u06B8.ⴈ; [B5, B6, V7]; xn--meb44b57607c.xn--zkj; ; ; # סڸ.ⴈ +xn--meb44b57607c.xn--1ug232c; 򒈣\u05E1\u06B8.ⴈ\u200D; [B5, B6, C2, V7]; xn--meb44b57607c.xn--1ug232c; ; ; # סڸ.ⴈ +xn--meb44b57607c.xn--gnd; 򒈣\u05E1\u06B8.Ⴈ; [B5, B6, V7]; xn--meb44b57607c.xn--gnd; ; ; # סڸ.Ⴈ +xn--meb44b57607c.xn--gnd699e; 򒈣\u05E1\u06B8.Ⴈ\u200D; [B5, B6, C2, V7]; xn--meb44b57607c.xn--gnd699e; ; ; # סڸ.Ⴈ +󀚶𝨱\u07E6⒈.𑗝髯\u200C; 󀚶𝨱\u07E6⒈.𑗝髯\u200C; [B1, B5, C1, V6, V7]; xn--etb477lq931a1f58e.xn--0ugx259bocxd; ; xn--etb477lq931a1f58e.xn--uj6at43v; [B1, B5, V6, V7] # 𝨱ߦ⒈.𑗝髯 +󀚶𝨱\u07E61..𑗝髯\u200C; ; [B1, B5, C1, V6, V7, X4_2]; xn--1-idd62296a1fr6e..xn--0ugx259bocxd; [B1, B5, C1, V6, V7, A4_2]; xn--1-idd62296a1fr6e..xn--uj6at43v; [B1, B5, V6, V7, A4_2] # 𝨱ߦ1..𑗝髯 +xn--1-idd62296a1fr6e..xn--uj6at43v; 󀚶𝨱\u07E61..𑗝髯; [B1, B5, V6, V7, X4_2]; xn--1-idd62296a1fr6e..xn--uj6at43v; [B1, B5, V6, V7, A4_2]; ; # 𝨱ߦ1..𑗝髯 +xn--1-idd62296a1fr6e..xn--0ugx259bocxd; 󀚶𝨱\u07E61..𑗝髯\u200C; [B1, B5, C1, V6, V7, X4_2]; xn--1-idd62296a1fr6e..xn--0ugx259bocxd; [B1, B5, C1, V6, V7, A4_2]; ; # 𝨱ߦ1..𑗝髯 +xn--etb477lq931a1f58e.xn--uj6at43v; 󀚶𝨱\u07E6⒈.𑗝髯; [B1, B5, V6, V7]; xn--etb477lq931a1f58e.xn--uj6at43v; ; ; # 𝨱ߦ⒈.𑗝髯 +xn--etb477lq931a1f58e.xn--0ugx259bocxd; 󀚶𝨱\u07E6⒈.𑗝髯\u200C; [B1, B5, C1, V6, V7]; xn--etb477lq931a1f58e.xn--0ugx259bocxd; ; ; # 𝨱ߦ⒈.𑗝髯 +𐫀.\u0689𑌀; 𐫀.\u0689𑌀; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀 +𐫀.\u0689𑌀; ; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀 +xn--pw9c.xn--fjb8658k; 𐫀.\u0689𑌀; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀 +𑋪.𐳝; 𑋪.𐳝; [B1, V6]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝 +𑋪.𐳝; ; [B1, V6]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝 +𑋪.𐲝; 𑋪.𐳝; [B1, V6]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝 +xn--fm1d.xn--5c0d; 𑋪.𐳝; [B1, V6]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝 +𑋪.𐲝; 𑋪.𐳝; [B1, V6]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝 +≠膣。\u0F83; ≠膣.\u0F83; [V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ +=\u0338膣。\u0F83; ≠膣.\u0F83; [V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ +xn--1chy468a.xn--2ed; ≠膣.\u0F83; [V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ +񰀎-\u077D。ß; 񰀎-\u077D.ß; [B5, B6, V7]; xn----j6c95618k.xn--zca; ; xn----j6c95618k.ss; # -ݽ.ß +񰀎-\u077D。ß; 񰀎-\u077D.ß; [B5, B6, V7]; xn----j6c95618k.xn--zca; ; xn----j6c95618k.ss; # -ݽ.ß +񰀎-\u077D。SS; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +񰀎-\u077D。ss; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +񰀎-\u077D。Ss; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +xn----j6c95618k.ss; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +xn----j6c95618k.xn--zca; 񰀎-\u077D.ß; [B5, B6, V7]; xn----j6c95618k.xn--zca; ; ; # -ݽ.ß +񰀎-\u077D。SS; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +񰀎-\u077D。ss; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +񰀎-\u077D。Ss; 񰀎-\u077D.ss; [B5, B6, V7]; xn----j6c95618k.ss; ; ; # -ݽ.ss +ς𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V7]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; # ς𐹠ᡚ𑄳.靑𐹽𐫜 +ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; ; [B5, B6, V7]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; # ς𐹠ᡚ𑄳.靑𐹽𐫜 +Σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V7]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜 +σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; ; [B5, B6, V7]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜 +xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V7]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜 +xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V7]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; ; # ς𐹠ᡚ𑄳.靑𐹽𐫜 +Σ𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V7]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜 +σ𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V7]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜 +𐋷。\u200D; 𐋷.\u200D; [C2]; xn--r97c.xn--1ug; ; xn--r97c.; [A4_2] # 𐋷. +xn--r97c.; 𐋷.; ; xn--r97c.; [A4_2]; ; # 𐋷. +𐋷.; ; ; xn--r97c.; [A4_2]; ; # 𐋷. +xn--r97c.xn--1ug; 𐋷.\u200D; [C2]; xn--r97c.xn--1ug; ; ; # 𐋷. +𑰳𑈯。⥪; 𑰳𑈯.⥪; [V6]; xn--2g1d14o.xn--jti; ; ; # 𑰳𑈯.⥪ +xn--2g1d14o.xn--jti; 𑰳𑈯.⥪; [V6]; xn--2g1d14o.xn--jti; ; ; # 𑰳𑈯.⥪ +𑆀䁴񤧣.Ⴕ𝟜\u200C\u0348; 𑆀䁴񤧣.ⴕ4\u200C\u0348; [C1, V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [V6, V7] # 𑆀䁴.ⴕ4͈ +𑆀䁴񤧣.Ⴕ4\u200C\u0348; 𑆀䁴񤧣.ⴕ4\u200C\u0348; [C1, V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [V6, V7] # 𑆀䁴.ⴕ4͈ +𑆀䁴񤧣.ⴕ4\u200C\u0348; ; [C1, V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [V6, V7] # 𑆀䁴.ⴕ4͈ +xn--1mnx647cg3x1b.xn--4-zfb5123a; 𑆀䁴񤧣.ⴕ4\u0348; [V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb5123a; ; ; # 𑆀䁴.ⴕ4͈ +xn--1mnx647cg3x1b.xn--4-zfb502tlsl; 𑆀䁴񤧣.ⴕ4\u200C\u0348; [C1, V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; ; # 𑆀䁴.ⴕ4͈ +𑆀䁴񤧣.ⴕ𝟜\u200C\u0348; 𑆀䁴񤧣.ⴕ4\u200C\u0348; [C1, V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [V6, V7] # 𑆀䁴.ⴕ4͈ +xn--1mnx647cg3x1b.xn--4-zfb324h; 𑆀䁴񤧣.Ⴕ4\u0348; [V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb324h; ; ; # 𑆀䁴.Ⴕ4͈ +xn--1mnx647cg3x1b.xn--4-zfb324h32o; 𑆀䁴񤧣.Ⴕ4\u200C\u0348; [C1, V6, V7]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; ; # 𑆀䁴.Ⴕ4͈ +憡?\u200CႴ.𐋮\u200D≠; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [U1] # 憡?ⴔ.𐋮≠ +憡?\u200CႴ.𐋮\u200D=\u0338; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [U1] # 憡?ⴔ.𐋮≠ +憡?\u200Cⴔ.𐋮\u200D=\u0338; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [U1] # 憡?ⴔ.𐋮≠ +憡?\u200Cⴔ.𐋮\u200D≠; ; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [U1] # 憡?ⴔ.𐋮≠ +xn--?-fwsr13r.xn--1chz659f; 憡?ⴔ.𐋮≠; [U1]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠ +xn--?-sgn310doh5c.xn--1ug73gl146a; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠ +xn--?-c1g3623d.xn--1chz659f; 憡?Ⴔ.𐋮≠; [V7, U1]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠ +xn--?-c1g798iy27d.xn--1ug73gl146a; 憡?\u200CႴ.𐋮\u200D≠; [C1, C2, V7, U1]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠ +憡?ⴔ.xn--1chz659f; 憡?ⴔ.𐋮≠; [U1]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠ +憡?Ⴔ.XN--1CHZ659F; 憡?ⴔ.𐋮≠; [U1]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠ +憡?Ⴔ.xn--1chz659f; 憡?ⴔ.𐋮≠; [U1]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠ +憡?\u200Cⴔ.xn--1ug73gl146a; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1ug73gl146a; [C2, U1] # 憡?ⴔ.𐋮≠ +憡?\u200CႴ.XN--1UG73GL146A; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1ug73gl146a; [C2, U1] # 憡?ⴔ.𐋮≠ +憡?\u200CႴ.xn--1ug73gl146a; 憡?\u200Cⴔ.𐋮\u200D≠; [C1, C2, U1]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1ug73gl146a; [C2, U1] # 憡?ⴔ.𐋮≠ +xn--?-fwsr13r.xn--1ug73gl146a; 憡?ⴔ.𐋮\u200D≠; [C2, U1]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠ +xn--?-c1g3623d.xn--1ug73gl146a; 憡?Ⴔ.𐋮\u200D≠; [C2, V7, U1]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠ +憡?Ⴔ.xn--1ug73gl146a; 憡?ⴔ.𐋮\u200D≠; [C2, U1]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠ +憡?ⴔ.xn--1ug73gl146a; 憡?ⴔ.𐋮\u200D≠; [C2, U1]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠ +憡?Ⴔ.XN--1UG73GL146A; 憡?ⴔ.𐋮\u200D≠; [C2, U1]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠ diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/ReadMe.txt b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/ReadMe.txt new file mode 100644 index 00000000000000..7d8cf73e804fc5 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/ReadMe.txt @@ -0,0 +1,10 @@ +# Unicode IDNA Mapping and Test Data +# Date: 2024-08-25 +# © 2024 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use and license, see https://www.unicode.org/terms_of_use.html + +This directory contains final data files for version 16.0.0 of +UTS #46, Unicode IDNA Compatibility Processing. + +https://www.unicode.org/reports/tr46/ diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/Unicode_16_0_IdnaTest.cs b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/Unicode_16_0_IdnaTest.cs new file mode 100644 index 00000000000000..a3d52a37cfcd16 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/IdnMapping/Data/Unicode_16_0/Unicode_16_0_IdnaTest.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; +using Xunit; + +namespace System.Globalization.Tests +{ + /// + /// Class to read data obtained from http://www.unicode.org/Public/idna. For more information read the information + /// contained in Data\Unicode_16_0\IdnaTest_16.txt + /// + /// The structure of the data set is a semicolon delimited list with the following columns: + /// + /// Column 1: source - The source string to be tested + /// Column 2: toUnicode - The result of applying toUnicode to the source, + /// with Transitional_Processing=false. + /// A blank value means the same as the source value. + /// Column 3: toUnicodeStatus - A set of status codes, each corresponding to a particular test. + /// A blank value means [] (no errors). + /// Column 4: toAsciiN - The result of applying toASCII to the source, + /// with Transitional_Processing=false. + /// A blank value means the same as the toUnicode value. + /// Column 5: toAsciiNStatus - A set of status codes, each corresponding to a particular test. + /// A blank value means the same as the toUnicodeStatus value. + /// An explicit [] means no errors. + /// Column 6: toAsciiT - The result of applying toASCII to the source, + /// with Transitional_Processing=true. + /// A blank value means the same as the toAsciiN value. + /// Column 7: toAsciiTStatus - A set of status codes, each corresponding to a particular test. + /// A blank value means the same as the toAsciiNStatus value. + /// An explicit [] means no errors. + /// + /// If the value of toUnicode or toAsciiN is the same as source, the column will be blank. + /// + public class Unicode_16_0_IdnaTest : Unicode_IdnaTest + { + public Unicode_16_0_IdnaTest(string line, int lineNumber) + { + var split = line.Split(';'); + + Type = PlatformDetection.IsNlsGlobalization ? IdnType.Transitional : IdnType.Nontransitional; + + Source = EscapedToLiteralString(split[0], lineNumber); + + UnicodeResult = new ConformanceIdnaUnicodeTestResult(EscapedToLiteralString(split[1], lineNumber), Source, EscapedToLiteralString(split[2], lineNumber), string.Empty, Source); + ASCIIResult = new ConformanceIdnaTestResult(EscapedToLiteralString(split[3], lineNumber), UnicodeResult.Value, EscapedToLiteralString(split[4], lineNumber), UnicodeResult.StatusValue, Source); + + // NLS uses transitional IDN processing. + if (Type == IdnType.Transitional) + { + ASCIIResult = new ConformanceIdnaTestResult(EscapedToLiteralString(split[5], lineNumber), ASCIIResult.Value, EscapedToLiteralString(split[6], lineNumber), ASCIIResult.StatusValue); + } + + LineNumber = lineNumber; + } + } +} diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj index be4ecb41ab0089..96d80ab08eb02d 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj @@ -19,6 +19,8 @@ Link="IdnMapping\Data\Unicode_13_0\Unicode_13_0_IdnaTest.cs" /> + + NormalizationDataWin8 diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/System.Globalization.Extensions.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/System.Globalization.Extensions.Tests.csproj index b17d04299c5e0f..1472956185a6f2 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/System.Globalization.Extensions.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Extensions.Tests/System.Globalization.Extensions.Tests.csproj @@ -11,6 +11,7 @@ + @@ -30,6 +31,7 @@ + NormalizationDataWin8 diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/TypeInfoTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/TypeInfoTests.cs index f20d14dedc3fb3..231c6f1119bcdf 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/TypeInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/TypeInfoTests.cs @@ -940,6 +940,7 @@ public void GetMembers(BindingFlags bindingAttributes, int length) [Theory] [InlineData(typeof(MembersClass), new Type[] { typeof(TI_NonGenericInterface1), typeof(TI_NonGenericInterface2) })] [InlineData(typeof(TI_NonGenericInterface2), new Type[0])] + [InlineData(typeof(IntEnum), new Type[] { typeof(IComparable), typeof(ISpanFormattable), typeof(IFormattable), typeof(IConvertible) })] public void GetInterfaces(Type type, Type[] expected) { Assert.Equal(expected.OrderBy(t => t.Name), type.GetTypeInfo().GetInterfaces().OrderBy(t => t.Name)); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs index cb89e2343a4c39..e3c0a312eab3bb 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs @@ -262,15 +262,15 @@ public void ExecuteAssemblyByName() } // In Mono AOT, loading assemblies can happen, but they need to be AOT'd and registered on startup. That is not the case - // with TestAppOutsideOfTPA.exe + // with TestAppOutsideOfTPA.dll [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNonBundledAssemblyLoadingSupported))] public void ExecuteAssembly() { CopyTestAssemblies(); - string name = Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA.exe"); + string name = Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA.dll"); AssertExtensions.Throws("assemblyFile", () => AppDomain.CurrentDomain.ExecuteAssembly(null)); - Assert.Throws(() => AppDomain.CurrentDomain.ExecuteAssembly("NonExistentFile.exe")); + Assert.Throws(() => AppDomain.CurrentDomain.ExecuteAssembly("NonExistentFile.dll")); #pragma warning disable SYSLIB0003 // Code Access Security is not supported or honored by the runtime. Func executeAssembly = () => AppDomain.CurrentDomain.ExecuteAssembly(name, new string[2] { "2", "3" }, null, Configuration.Assemblies.AssemblyHashAlgorithm.SHA1); @@ -601,7 +601,7 @@ public void AssemblyResolve_RequestingAssembly() RemoteExecutor.Invoke(() => { // bool AssemblyResolveFlag = false; - Assembly a = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA.exe")); + Assembly a = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA.dll")); ResolveEventHandler handler = (sender, args) => { @@ -812,11 +812,11 @@ private void CopyTestAssemblies() File.Copy("AssemblyResolveTestApp.dll", destTestAssemblyPath, false); } - destTestAssemblyPath = Path.Combine(appOutsideTPAPath, "TestAppOutsideOfTPA.exe"); - if (!File.Exists(destTestAssemblyPath) && File.Exists("TestAppOutsideOfTPA.exe")) + destTestAssemblyPath = Path.Combine(appOutsideTPAPath, "TestAppOutsideOfTPA.dll"); + if (!File.Exists(destTestAssemblyPath) && File.Exists("TestAppOutsideOfTPA.dll")) { Directory.CreateDirectory(Path.GetDirectoryName(destTestAssemblyPath)); - File.Copy("TestAppOutsideOfTPA.exe", destTestAssemblyPath, false); + File.Copy("TestAppOutsideOfTPA.dll", destTestAssemblyPath, false); } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Environment.Exit.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Environment.Exit.cs index 063de534bf765b..193299ff3ec836 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Environment.Exit.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Environment.Exit.cs @@ -44,7 +44,7 @@ public static void ExitCode_Roundtrips(int exitCode) public static void ExitCode_VoidMainAppReturnsSetValue(int mode) { int expectedExitCode = 123; - const string AppName = "VoidMainWithExitCodeApp.exe"; + const string AppName = "VoidMainWithExitCodeApp.dll"; using (Process p = Process.Start(RemoteExecutor.HostRunner, new[] { AppName, expectedExitCode.ToString(), mode.ToString() })) { diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestApp/TestApp.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestApp/TestApp.csproj index 5383013fa26fd7..f4f95f422dc336 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestApp/TestApp.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestApp/TestApp.csproj @@ -1,12 +1,13 @@ + + $(NetCoreAppCurrent) Exe - - .exe true - $(NetCoreAppCurrent) + + \ No newline at end of file diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestAppOutsideOfTPA/TestAppOutsideOfTPA.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestAppOutsideOfTPA/TestAppOutsideOfTPA.csproj index f4d12b87a1127b..b037d6f38cb83c 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestAppOutsideOfTPA/TestAppOutsideOfTPA.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/TestAppOutsideOfTPA/TestAppOutsideOfTPA.csproj @@ -1,15 +1,17 @@ + + $(NetCoreAppCurrent) Exe - - .exe true - $(NetCoreAppCurrent) + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/VoidMainWithExitCodeApp/VoidMainWithExitCodeApp.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/VoidMainWithExitCodeApp/VoidMainWithExitCodeApp.csproj index 24d65de3594dbd..df54391bde7fbe 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/VoidMainWithExitCodeApp/VoidMainWithExitCodeApp.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/VoidMainWithExitCodeApp/VoidMainWithExitCodeApp.csproj @@ -1,12 +1,13 @@ + + $(NetCoreAppCurrent) Exe - - .exe true - $(NetCoreAppCurrent) + + \ No newline at end of file diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs index 3ed49c1ef14921..1cda74cfda28d6 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs @@ -730,9 +730,11 @@ private static void AssertEqual(string[] items, ReadOnlySpan source, Memor { Assert.True(enumerator.MoveNext()); Assert.Equal(item, source[enumerator.Current].ToString()); + Assert.Equal(source.ToString(), enumerator.Source.ToString()); } Assert.False(enumerator.MoveNext()); + Assert.Equal(source.ToString(), enumerator.Source.ToString()); } } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.Encrypt.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.Encrypt.cs index edd8c46558b1cd..a743af29524b6f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.Encrypt.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.Encrypt.cs @@ -265,7 +265,7 @@ private static CMSG_RECIPIENT_ENCODE_INFO EncodeRecipientInfo(CmsRecipient recip { if (recipient.Certificate.GetKeyAlgorithm() == Oids.RsaOaep) { - byte[] parameters = recipient.Certificate.GetKeyAlgorithmParameters(); + byte[]? parameters = recipient.Certificate.GetKeyAlgorithmParameters(); if (parameters == null || parameters.Length == 0) { diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj b/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj index 0be98d49649342..c4139f0c2c5484 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index 865209228719e6..e384759699b1e6 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) disable $(NoWarn);SYSLIB0057 diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs index 6006ee5ff6cb7c..4f9aa0c527e084 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -1795,6 +1795,49 @@ protected override void HashCore(System.ReadOnlySpan source) { } public override void Initialize() { } protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } } + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006")] + public abstract partial class MLKem : System.IDisposable + { + protected MLKem(System.Security.Cryptography.MLKemAlgorithm algorithm) { } + public System.Security.Cryptography.MLKemAlgorithm Algorithm { get { throw null; } } + public static bool IsSupported { get { throw null; } } + public void Decapsulate(System.ReadOnlySpan ciphertext, System.Span sharedSecret) { } + protected abstract void DecapsulateCore(System.ReadOnlySpan ciphertext, System.Span sharedSecret); + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + public void Encapsulate(System.Span ciphertext, System.Span sharedSecret) { } + protected abstract void EncapsulateCore(System.Span ciphertext, System.Span sharedSecret); + public void ExportDecapsulationKey(System.Span destination) { } + protected abstract void ExportDecapsulationKeyCore(System.Span destination); + public void ExportEncapsulationKey(System.Span destination) { } + protected abstract void ExportEncapsulationKeyCore(System.Span destination); + public void ExportPrivateSeed(System.Span destination) { } + protected abstract void ExportPrivateSeedCore(System.Span destination); + public static System.Security.Cryptography.MLKem GenerateKey(System.Security.Cryptography.MLKemAlgorithm algorithm) { throw null; } + public static System.Security.Cryptography.MLKem ImportDecapsulationKey(System.Security.Cryptography.MLKemAlgorithm algorithm, System.ReadOnlySpan source) { throw null; } + public static System.Security.Cryptography.MLKem ImportEncapsulationKey(System.Security.Cryptography.MLKemAlgorithm algorithm, System.ReadOnlySpan source) { throw null; } + public static System.Security.Cryptography.MLKem ImportPrivateSeed(System.Security.Cryptography.MLKemAlgorithm algorithm, System.ReadOnlySpan source) { throw null; } + protected void ThrowIfDisposed() { } + } + [System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006")] + public sealed partial class MLKemAlgorithm : System.IEquatable + { + internal MLKemAlgorithm() { } + public int CiphertextSizeInBytes { get { throw null; } } + public int DecapsulationKeySizeInBytes { get { throw null; } } + public int EncapsulationKeySizeInBytes { get { throw null; } } + public static System.Security.Cryptography.MLKemAlgorithm MLKem1024 { get { throw null; } } + public static System.Security.Cryptography.MLKemAlgorithm MLKem512 { get { throw null; } } + public static System.Security.Cryptography.MLKemAlgorithm MLKem768 { get { throw null; } } + public string Name { get { throw null; } } + public int PrivateSeedSizeInBytes { get { throw null; } } + public int SharedSecretSizeInBytes { get { throw null; } } + public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Security.Cryptography.MLKemAlgorithm? other) { throw null; } + public override int GetHashCode() { throw null; } + public static bool operator ==(System.Security.Cryptography.MLKemAlgorithm? left, System.Security.Cryptography.MLKemAlgorithm? right) { throw null; } + public static bool operator !=(System.Security.Cryptography.MLKemAlgorithm? left, System.Security.Cryptography.MLKemAlgorithm? right) { throw null; } + } public sealed partial class Oid { public Oid() { } @@ -2942,9 +2985,9 @@ public Pkcs12LoadLimitExceededException(string propertyName) { } public sealed partial class PublicKey { public PublicKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } - public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptography.AsnEncodedData parameters, System.Security.Cryptography.AsnEncodedData keyValue) { } + public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptography.AsnEncodedData? parameters, System.Security.Cryptography.AsnEncodedData keyValue) { } public System.Security.Cryptography.AsnEncodedData EncodedKeyValue { get { throw null; } } - public System.Security.Cryptography.AsnEncodedData EncodedParameters { get { throw null; } } + public System.Security.Cryptography.AsnEncodedData? EncodedParameters { get { throw null; } } [System.ObsoleteAttribute("PublicKey.Key is obsolete. Use the appropriate method to get the public key, such as GetRSAPublicKey.", DiagnosticId="SYSLIB0027", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] public System.Security.Cryptography.AsymmetricAlgorithm Key { get { throw null; } } public System.Security.Cryptography.Oid Oid { get { throw null; } } @@ -3165,8 +3208,8 @@ protected virtual void Dispose(bool disposing) { } [System.ObsoleteAttribute("X509Certificate.GetIssuerName has been deprecated. Use the Issuer property instead.")] public virtual string GetIssuerName() { throw null; } public virtual string GetKeyAlgorithm() { throw null; } - public virtual byte[] GetKeyAlgorithmParameters() { throw null; } - public virtual string GetKeyAlgorithmParametersString() { throw null; } + public virtual byte[]? GetKeyAlgorithmParameters() { throw null; } + public virtual string? GetKeyAlgorithmParametersString() { throw null; } [System.ObsoleteAttribute("X509Certificate.GetName has been deprecated. Use the Subject property instead.")] public virtual string GetName() { throw null; } public virtual byte[] GetPublicKey() { throw null; } diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index d32920cb808e0e..06accf08468337 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -93,6 +93,9 @@ Destination is too short. + + Destination must be exactly {0} bytes. + The value cannot be an empty string. @@ -123,6 +126,18 @@ Value was invalid. + + The specified ciphertext is not the correct length for the ML-KEM algorithm. + + + The specified decapsulation key is not the correct length for the ML-KEM algorithm. + + + The specified encapsulation key is not the correct length for the ML-KEM algorithm. + + + The specified private seed is not the correct length for the ML-KEM algorithm. + The specified signature context exceeds the maximum length of 255 bytes. @@ -516,6 +531,9 @@ The contents do not contain a PEM with a '{0}' label, or the content is malformed. + + The key contents are not retrievable. + Key is not a valid private key. @@ -546,6 +564,9 @@ Cannot open an invalid handle. + + One or more provided buffers overlap. + The owner of '{0}' is not the current user. diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index f0bd081b40ce66..8600fbb4bfa780 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -1,4 +1,4 @@ - + true @@ -7,6 +7,7 @@ $(NoWarn);CA5350;CA5351;CA5379;CA5384;SYSLIB0026 $(NoWarn);CS0809 + $(NoWarn);SYSLIB5006 false @@ -381,6 +382,10 @@ Link="Common\System\Security\Cryptography\MLDsaAlgorithm.cs" /> + + + + + + Link="Common\System\Security\Cryptography\Pkcs\Pkcs12IntegrityMode.cs" /> - + - - @@ -767,6 +776,10 @@ Link="Common\System\Security\Cryptography\SP800108HmacCounterKdfImplementationManaged.cs" /> + + @@ -857,8 +870,12 @@ Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.EVP.DigestAlgs.cs" /> + + + + @@ -1123,8 +1143,12 @@ Link="Common\System\Security\Cryptography\ECDsaAndroid.cs" /> + + @@ -1254,8 +1278,12 @@ Link="Common\System\Security\Cryptography\ECDsaSecurityTransforms.cs" /> + + + + - + diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AsymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AsymmetricAlgorithm.cs index 28e21bfef5c7dc..b5dfa0666927ce 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AsymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AsymmetricAlgorithm.cs @@ -18,9 +18,9 @@ public static AsymmetricAlgorithm Create() => throw new PlatformNotSupportedException(SR.Cryptography_DefaultAlgorithm_NotSupported); [Obsolete(Obsoletions.CryptoStringFactoryMessage, DiagnosticId = Obsoletions.CryptoStringFactoryDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresUnreferencedCode(CryptoConfigForwarder.CreateFromNameUnreferencedCodeMessage)] + [RequiresUnreferencedCode(CryptoConfig.CreateFromNameUnreferencedCodeMessage)] public static AsymmetricAlgorithm? Create(string algName) => - CryptoConfigForwarder.CreateFromName(algName); + CryptoConfig.CreateFromName(algName); public virtual int KeySize { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.Common.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.Common.cs deleted file mode 100644 index 950fd5282b4323..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.Common.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Security.Cryptography -{ - public partial class CryptoConfig - { - internal const string CreateFromNameUnreferencedCodeMessage = "The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead."; - - // .NET Core does not support AllowOnlyFipsAlgorithms - public static bool AllowOnlyFipsAlgorithms => false; - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs index c5a45f8ed76f88..1cbf5c0a861262 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs @@ -11,8 +11,13 @@ namespace System.Security.Cryptography { - public partial class CryptoConfig + public class CryptoConfig { + internal const string CreateFromNameUnreferencedCodeMessage = "The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead."; + + // .NET does not support AllowOnlyFipsAlgorithms + public static bool AllowOnlyFipsAlgorithms => false; + #if !BROWSER private const string AssemblyName_Pkcs = "System.Security.Cryptography.Pkcs"; @@ -493,6 +498,21 @@ public static void AddAlgorithm(Type algorithm, params string[] names) return CreateFromName(name, null); } + [RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)] + internal static T? CreateFromName(string name) where T : class + { + object? o = CreateFromName(name); + try + { + return (T?)o; + } + catch + { + (o as IDisposable)?.Dispose(); + throw; + } + } + [UnsupportedOSPlatform("browser")] public static void AddOID(string oid, params string[] names) { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfigForwarder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfigForwarder.cs deleted file mode 100644 index e734e4f65b9f00..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfigForwarder.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics.CodeAnalysis; -using System.Reflection; - -[assembly: UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Target = "M:System.Security.Cryptography.CryptoConfigForwarder.#cctor", - Scope = "member", - Justification = "The cctor caches the RequiresUnreferencedCode call in a delegate, and usage of that delegate is marked with RequiresUnreferencedCode.")] - -namespace System.Security.Cryptography -{ - internal static class CryptoConfigForwarder - { - internal const string CreateFromNameUnreferencedCodeMessage = "The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead."; - - // Suppressed for the ILLink by the assembly-level UnconditionalSuppressMessageAttribute - // https://github.com/dotnet/linker/issues/2648 -#pragma warning disable IL2026 - private static readonly Func s_createFromName = BindCreateFromName(); -#pragma warning restore IL2026 - - [RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)] - private static Func BindCreateFromName() - { - const string CryptoConfigTypeName = - "System.Security.Cryptography.CryptoConfig, System.Security.Cryptography.Algorithms"; - - const string CreateFromNameMethodName = "CreateFromName"; - - Type t = Type.GetType(CryptoConfigTypeName, throwOnError: true)!; - MethodInfo? createFromName = t.GetMethod(CreateFromNameMethodName, new[] { typeof(string) }); - - if (createFromName == null) - { - throw new MissingMethodException(t.FullName, CreateFromNameMethodName); - } - - return createFromName.CreateDelegate>(); - } - - [RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)] - internal static T? CreateFromName(string name) where T : class - { - object? o = s_createFromName(name); - try - { - return (T?)o; - } - catch - { - (o as IDisposable)?.Dispose(); - throw; - } - } - - internal static HashAlgorithm CreateDefaultHashAlgorithm() => - throw new PlatformNotSupportedException(SR.Cryptography_DefaultAlgorithm_NotSupported); - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMAC.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMAC.cs index d542ba3a5cf32b..796d07d6f315b3 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMAC.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMAC.cs @@ -23,9 +23,9 @@ protected HMAC() { } throw new PlatformNotSupportedException(SR.Cryptography_DefaultAlgorithm_NotSupported); [Obsolete(Obsoletions.CryptoStringFactoryMessage, DiagnosticId = Obsoletions.CryptoStringFactoryDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresUnreferencedCode(CryptoConfigForwarder.CreateFromNameUnreferencedCodeMessage)] + [RequiresUnreferencedCode(CryptoConfig.CreateFromNameUnreferencedCodeMessage)] public static new HMAC? Create(string algorithmName) => - CryptoConfigForwarder.CreateFromName(algorithmName); + CryptoConfig.CreateFromName(algorithmName); public string HashName { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithm.cs index 1f570eeb22fc5f..a27048d66b3e2f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithm.cs @@ -20,12 +20,12 @@ protected HashAlgorithm() { } [Obsolete(Obsoletions.DefaultCryptoAlgorithmsMessage, DiagnosticId = Obsoletions.DefaultCryptoAlgorithmsDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static HashAlgorithm Create() => - CryptoConfigForwarder.CreateDefaultHashAlgorithm(); + throw new PlatformNotSupportedException(SR.Cryptography_DefaultAlgorithm_NotSupported); [Obsolete(Obsoletions.CryptoStringFactoryMessage, DiagnosticId = Obsoletions.CryptoStringFactoryDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresUnreferencedCode(CryptoConfigForwarder.CreateFromNameUnreferencedCodeMessage)] + [RequiresUnreferencedCode(CryptoConfig.CreateFromNameUnreferencedCodeMessage)] public static HashAlgorithm? Create(string hashName) => - CryptoConfigForwarder.CreateFromName(hashName); + CryptoConfig.CreateFromName(hashName); public virtual int HashSize => HashSizeValue; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs index 10d1f50548c837..f5dad6061a3031 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Helpers.cs @@ -455,5 +455,15 @@ internal static void ThrowIfPasswordContainsNullCharacter(string? password) throw new ArgumentException(SR.Argument_PasswordNullChars, nameof(password)); } } + + internal static ReadOnlyMemory? ToNullableMemory(this byte[]? array) + { + if (array is null) + { + return default(ReadOnlyMemory?); + } + + return array; + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyedHashAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyedHashAlgorithm.cs index 7217e96d6b55e7..3da325913c0bde 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyedHashAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyedHashAlgorithm.cs @@ -15,9 +15,9 @@ protected KeyedHashAlgorithm() { } throw new PlatformNotSupportedException(SR.Cryptography_DefaultAlgorithm_NotSupported); [Obsolete(Obsoletions.CryptoStringFactoryMessage, DiagnosticId = Obsoletions.CryptoStringFactoryDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresUnreferencedCode(CryptoConfigForwarder.CreateFromNameUnreferencedCodeMessage)] + [RequiresUnreferencedCode(CryptoConfig.CreateFromNameUnreferencedCodeMessage)] public static new KeyedHashAlgorithm? Create(string algName) => - CryptoConfigForwarder.CreateFromName(algName); + CryptoConfig.CreateFromName(algName); public virtual byte[] Key { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MLKemImplementation.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MLKemImplementation.OpenSsl.cs new file mode 100644 index 00000000000000..1ce4ed9c1aecea --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/MLKemImplementation.OpenSsl.cs @@ -0,0 +1,117 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography +{ + internal sealed class MLKemImplementation : MLKem + { + private SafeEvpPKeyHandle _key; + + // OpenSSL is expected to give "all or none" support. + internal static new bool IsSupported => Interop.Crypto.EvpKemAlgs.MlKem512 is not null; + + private MLKemImplementation(MLKemAlgorithm algorithm, SafeEvpPKeyHandle key) : base(algorithm) + { + _key = key; + } + + internal static MLKem GenerateKeyImpl(MLKemAlgorithm algorithm) + { + Debug.Assert(IsSupported); + string kemName = MapAlgorithmToName(algorithm); + SafeEvpPKeyHandle key = Interop.Crypto.EvpKemGeneratePkey(kemName); + return new MLKemImplementation(algorithm, key); + } + + internal static MLKem ImportPrivateSeedImpl(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + Debug.Assert(IsSupported); + Debug.Assert(source.Length == algorithm.PrivateSeedSizeInBytes); + string kemName = MapAlgorithmToName(algorithm); + SafeEvpPKeyHandle key = Interop.Crypto.EvpKemGeneratePkey(kemName, source); + return new MLKemImplementation(algorithm, key); + } + + internal static MLKem ImportDecapsulationKeyImpl(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + Debug.Assert(IsSupported); + Debug.Assert(source.Length == algorithm.DecapsulationKeySizeInBytes); + string kemName = MapAlgorithmToName(algorithm); + SafeEvpPKeyHandle key = Interop.Crypto.EvpPKeyFromData(kemName, source, privateKey: true); + return new MLKemImplementation(algorithm, key); + } + + internal static MLKem ImportEncapsulationKeyImpl(MLKemAlgorithm algorithm, ReadOnlySpan source) + { + Debug.Assert(IsSupported); + Debug.Assert(source.Length == algorithm.EncapsulationKeySizeInBytes); + string kemName = MapAlgorithmToName(algorithm); + SafeEvpPKeyHandle key = Interop.Crypto.EvpPKeyFromData(kemName, source, privateKey: false); + return new MLKemImplementation(algorithm, key); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _key.Dispose(); + } + } + + protected override void DecapsulateCore(ReadOnlySpan ciphertext, Span sharedSecret) + { + Interop.Crypto.EvpKemDecapsulate(_key, ciphertext, sharedSecret); + } + + protected override void EncapsulateCore(Span ciphertext, Span sharedSecret) + { + Interop.Crypto.EvpKemEncapsulate(_key, ciphertext, sharedSecret); + } + + protected override void ExportPrivateSeedCore(Span destination) + { + Interop.Crypto.EvpKemExportPrivateSeed(_key, destination); + } + + protected override void ExportDecapsulationKeyCore(Span destination) + { + Interop.Crypto.EvpKemExportDecapsulationKey(_key, destination); + } + + protected override void ExportEncapsulationKeyCore(Span destination) + { + Interop.Crypto.EvpKemExportEncapsulationKey(_key, destination); + } + + private static string MapAlgorithmToName(MLKemAlgorithm algorithm) + { + string? name = null; + + if (algorithm == MLKemAlgorithm.MLKem512) + { + name = Interop.Crypto.EvpKemAlgs.MlKem512; + } + else if (algorithm == MLKemAlgorithm.MLKem768) + { + name = Interop.Crypto.EvpKemAlgs.MlKem768; + } + else if (algorithm == MLKemAlgorithm.MLKem1024) + { + name = Interop.Crypto.EvpKemAlgs.MlKem1024; + } + + if (name is null) + { + Debug.Fail("Unhandled ML-KEM algorithm or ML-KEM is not available."); + throw new CryptographicException(); + } + + return name; + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricAlgorithm.cs index 77664722cc2c36..277b0eab24db9e 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricAlgorithm.cs @@ -20,9 +20,9 @@ public static SymmetricAlgorithm Create() => throw new PlatformNotSupportedException(SR.Cryptography_DefaultAlgorithm_NotSupported); [Obsolete(Obsoletions.CryptoStringFactoryMessage, DiagnosticId = Obsoletions.CryptoStringFactoryDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresUnreferencedCode(CryptoConfigForwarder.CreateFromNameUnreferencedCodeMessage)] + [RequiresUnreferencedCode(CryptoConfig.CreateFromNameUnreferencedCodeMessage)] public static SymmetricAlgorithm? Create(string algName) => - CryptoConfigForwarder.CreateFromName(algName); + CryptoConfig.CreateFromName(algName); public virtual int FeedbackSize { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs index db48fe584c5e28..2eeb342907239a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AndroidCertificatePal.cs @@ -235,7 +235,7 @@ public string KeyAlgorithm } } - public byte[] KeyAlgorithmParameters + public byte[]? KeyAlgorithmParameters { get { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs index 769d4cc72e35f8..dbe1bc10e566d5 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.TempExportPal.cs @@ -33,7 +33,7 @@ public void Dispose() public string LegacySubject => _realPal.LegacySubject; public byte[] Thumbprint => _realPal.Thumbprint; public string KeyAlgorithm => _realPal.KeyAlgorithm; - public byte[] KeyAlgorithmParameters => _realPal.KeyAlgorithmParameters; + public byte[]? KeyAlgorithmParameters => _realPal.KeyAlgorithmParameters; public byte[] PublicKeyValue => _realPal.PublicKeyValue; public byte[] SerialNumber => _realPal.SerialNumber; public string SignatureAlgorithm => _realPal.SignatureAlgorithm; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs index 8b8e3e208f58e8..cf6fc63583e450 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs @@ -151,7 +151,7 @@ public string KeyAlgorithm } } - public byte[] KeyAlgorithmParameters + public byte[]? KeyAlgorithmParameters { get { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs index 2c7b5277f9bab5..c1d175e31e6fd7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateData.ManagedDecode.cs @@ -33,11 +33,11 @@ internal struct AlgorithmIdentifier public AlgorithmIdentifier(AlgorithmIdentifierAsn algorithmIdentifier) { AlgorithmId = algorithmIdentifier.Algorithm; - Parameters = algorithmIdentifier.Parameters?.ToArray() ?? Array.Empty(); + Parameters = algorithmIdentifier.Parameters?.ToArray(); } internal string? AlgorithmId; - internal byte[] Parameters; + internal byte[]? Parameters; } private CertificateAsn certificate; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs index c6d0b78119c35c..d53b2072c5ab67 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateExtensionsCommon.cs @@ -27,7 +27,7 @@ internal static class CertificateExtensionsCommon if (typeof(T) == typeof(RSA) || typeof(T) == typeof(DSA)) { byte[] rawEncodedKeyValue = publicKey.EncodedKeyValue.RawData; - byte[] rawEncodedParameters = publicKey.EncodedParameters.RawData; + byte[]? rawEncodedParameters = publicKey.EncodedParameters?.RawData; return (T)(X509Pal.Instance.DecodePublicKey(algorithmOid, rawEncodedKeyValue, rawEncodedParameters, certificate.Pal)); } else if (typeof(T) == typeof(ECDsa)) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs index 6f4e414001ca1e..44c46316138fc1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.cs @@ -87,7 +87,7 @@ public string KeyAlgorithm } } - public byte[] KeyAlgorithmParameters + public byte[]? KeyAlgorithmParameters { get { @@ -107,7 +107,7 @@ public byte[] KeyAlgorithmParameters { byte* NULL_ASN_TAG = (byte*)0x5; - byte[] keyAlgorithmParameters; + byte[]? keyAlgorithmParameters; if (algId == AlgId.CALG_DSS_SIGN && pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData == 0 @@ -121,7 +121,16 @@ public byte[] KeyAlgorithmParameters } else { - keyAlgorithmParameters = pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.ToByteArray(); + Interop.Crypt32.DATA_BLOB parametersBlob = pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters; + + if (parametersBlob.pbData == IntPtr.Zero) + { + keyAlgorithmParameters = null; + } + else + { + keyAlgorithmParameters = parametersBlob.ToByteArray(); + } } return keyAlgorithmParameters; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs index 8a4a6cc3585322..16c7c608e2a01b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs @@ -838,7 +838,7 @@ public X509Certificate2 Create( Algorithm = new AlgorithmIdentifierAsn { Algorithm = PublicKey.Oid!.Value!, - Parameters = PublicKey.EncodedParameters.RawData, + Parameters = PublicKey.EncodedParameters?.RawData.ToNullableMemory(), }, SubjectPublicKey = PublicKey.EncodedKeyValue.RawData, }, diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs index 906881dd97da05..7bc6e5a0655c0a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ICertificatePalCore.cs @@ -16,7 +16,7 @@ internal interface ICertificatePalCore : IDisposable string LegacySubject { get; } byte[] Thumbprint { get; } string KeyAlgorithm { get; } - byte[] KeyAlgorithmParameters { get; } + byte[]? KeyAlgorithmParameters { get; } byte[] PublicKeyValue { get; } byte[] SerialNumber { get; } string SignatureAlgorithm { get; } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs index 991986bd0eab16..9c52f4bff506d3 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/IX509Pal.cs @@ -5,7 +5,7 @@ namespace System.Security.Cryptography.X509Certificates { internal interface IX509Pal { - AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[] encodedParameters, ICertificatePal? certificatePal); + AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[]? encodedParameters, ICertificatePal? certificatePal); ECDsa DecodeECDsaPublicKey(ICertificatePal? certificatePal); ECDiffieHellman DecodeECDiffieHellmanPublicKey(ICertificatePal? certificatePal); string X500DistinguishedNameDecode(byte[] encodedDistinguishedName, X500DistinguishedNameFlags flag); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs index f2e1b2021db35a..5935531c02267b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs @@ -311,7 +311,7 @@ public string KeyAlgorithm } } - public byte[] KeyAlgorithmParameters + public byte[]? KeyAlgorithmParameters { get { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs index 8966b760df1f0a..961fec8cfd6897 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509Encoder.cs @@ -6,6 +6,7 @@ using System.IO; using System.Security.Cryptography.Asn1; using Microsoft.Win32.SafeHandles; +using Internal.Cryptography; namespace System.Security.Cryptography.X509Certificates { @@ -28,7 +29,7 @@ public ECDiffieHellman DecodeECDiffieHellmanPublicKey(ICertificatePal? certifica } - public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[] encodedParameters, ICertificatePal? certificatePal) + public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[]? encodedParameters, ICertificatePal? certificatePal) { switch (oid.Value) { @@ -167,11 +168,15 @@ private static RSAOpenSsl BuildRsaPublicKey(byte[] encodedData) return rsa; } - private static DSAOpenSsl BuildDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters) + private static DSAOpenSsl BuildDsaPublicKey(byte[] encodedKeyValue, byte[]? encodedParameters) { SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn { - Algorithm = new AlgorithmIdentifierAsn { Algorithm = Oids.Dsa, Parameters = encodedParameters }, + Algorithm = new AlgorithmIdentifierAsn + { + Algorithm = Oids.Dsa, + Parameters = encodedParameters.ToNullableMemory(), + }, SubjectPublicKey = encodedKeyValue, }; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs index 24b7ee5dfafb21..2f970b6cbe3ae2 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs @@ -52,7 +52,11 @@ internal byte[] ToPkcs10Request(X509SignatureGenerator signatureGenerator, HashA } SubjectPublicKeyInfoAsn spki = default; - spki.Algorithm = new AlgorithmIdentifierAsn { Algorithm = PublicKey.Oid!.Value!, Parameters = PublicKey.EncodedParameters.RawData }; + spki.Algorithm = new AlgorithmIdentifierAsn + { + Algorithm = PublicKey.Oid!.Value!, + Parameters = PublicKey.EncodedParameters?.RawData.ToNullableMemory(), + }; spki.SubjectPublicKey = PublicKey.EncodedKeyValue.RawData; var attributes = new AttributeAsn[Attributes.Count]; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs index 589e548fc85e02..3355547715a9fa 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography.Asn1; +using Internal.Cryptography; namespace System.Security.Cryptography.X509Certificates { @@ -14,12 +15,12 @@ public sealed class PublicKey private readonly Oid _oid; private AsymmetricAlgorithm? _key; - public PublicKey(Oid oid, AsnEncodedData parameters, AsnEncodedData keyValue) + public PublicKey(Oid oid, AsnEncodedData? parameters, AsnEncodedData keyValue) : this(oid, parameters, keyValue, skipCopy: false) { } - internal PublicKey(Oid oid, AsnEncodedData parameters, AsnEncodedData keyValue, bool skipCopy) + internal PublicKey(Oid oid, AsnEncodedData? parameters, AsnEncodedData keyValue, bool skipCopy) { _oid = oid; @@ -30,7 +31,7 @@ internal PublicKey(Oid oid, AsnEncodedData parameters, AsnEncodedData keyValue, } else { - EncodedParameters = new AsnEncodedData(parameters); + EncodedParameters = parameters is null ? null : new AsnEncodedData(parameters); EncodedKeyValue = new AsnEncodedData(keyValue); } } @@ -57,7 +58,7 @@ public PublicKey(AsymmetricAlgorithm key) DecodeSubjectPublicKeyInfo( subjectPublicKey, out Oid localOid, - out AsnEncodedData localParameters, + out AsnEncodedData? localParameters, out AsnEncodedData localKeyValue); _oid = localOid; @@ -70,7 +71,7 @@ public PublicKey(AsymmetricAlgorithm key) public AsnEncodedData EncodedKeyValue { get; } - public AsnEncodedData EncodedParameters { get; } + public AsnEncodedData? EncodedParameters { get; } [Obsolete(Obsoletions.PublicKeyPropertyMessage, DiagnosticId = Obsoletions.PublicKeyPropertyDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public AsymmetricAlgorithm Key @@ -83,7 +84,7 @@ public AsymmetricAlgorithm Key { case Oids.Rsa: case Oids.Dsa: - _key = X509Pal.Instance.DecodePublicKey(_oid, EncodedKeyValue.RawData, EncodedParameters.RawData, null); + _key = X509Pal.Instance.DecodePublicKey(_oid, EncodedKeyValue.RawData, EncodedParameters?.RawData, null); break; default: @@ -146,7 +147,7 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan source int read = DecodeSubjectPublicKeyInfo( source, out Oid localOid, - out AsnEncodedData localParameters, + out AsnEncodedData? localParameters, out AsnEncodedData localKeyValue); bytesRead = read; @@ -279,7 +280,7 @@ internal AsnWriter EncodeSubjectPublicKeyInfo() Algorithm = new AlgorithmIdentifierAsn { Algorithm = _oid.Value ?? string.Empty, - Parameters = EncodedParameters.RawData, + Parameters = EncodedParameters?.RawData.ToNullableMemory(), }, SubjectPublicKey = EncodedKeyValue.RawData, }; @@ -292,7 +293,7 @@ internal AsnWriter EncodeSubjectPublicKeyInfo() private static unsafe int DecodeSubjectPublicKeyInfo( ReadOnlySpan source, out Oid oid, - out AsnEncodedData parameters, + out AsnEncodedData? parameters, out AsnEncodedData keyValue) { fixed (byte* ptr = &MemoryMarshal.GetReference(source)) @@ -323,7 +324,7 @@ internal static PublicKey DecodeSubjectPublicKeyInfo(ref SubjectPublicKeyInfoAsn DecodeSubjectPublicKeyInfo( ref spki, out Oid oid, - out AsnEncodedData parameters, + out AsnEncodedData? parameters, out AsnEncodedData keyValue); return new PublicKey(oid, parameters, keyValue, skipCopy: true); @@ -332,13 +333,16 @@ internal static PublicKey DecodeSubjectPublicKeyInfo(ref SubjectPublicKeyInfoAsn private static void DecodeSubjectPublicKeyInfo( ref SubjectPublicKeyInfoAsn spki, out Oid oid, - out AsnEncodedData parameters, + out AsnEncodedData? parameters, out AsnEncodedData keyValue) { oid = new Oid(spki.Algorithm.Algorithm, null); - parameters = new AsnEncodedData(spki.Algorithm.Parameters.GetValueOrDefault().Span); keyValue = new AsnEncodedData(spki.SubjectPublicKey.Span); + parameters = spki.Algorithm.Parameters switch + { + ReadOnlyMemory algParameters => new AsnEncodedData(algParameters.Span), + _ => null, + }; } - } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs index 97addaca1c7020..4fa73a0b8f4b35 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs @@ -23,6 +23,7 @@ public partial class X509Certificate : IDisposable, IDeserializationCallback, IS private volatile byte[]? _lazyKeyAlgorithmParameters; private volatile byte[]? _lazyPublicKey; private volatile byte[]? _lazyRawData; + private volatile bool _lazyKeyAlgorithmParametersCreated; private DateTime _lazyNotBefore = DateTime.MinValue; private DateTime _lazyNotAfter = DateTime.MinValue; @@ -38,6 +39,7 @@ public virtual void Reset() _lazyRawData = null; _lazyNotBefore = DateTime.MinValue; _lazyNotAfter = DateTime.MinValue; + _lazyKeyAlgorithmParametersCreated = false; ICertificatePalCore? pal = Pal; if (pal != null) @@ -520,20 +522,25 @@ public virtual string GetKeyAlgorithm() return _lazyKeyAlgorithm ??= Pal.KeyAlgorithm; } - public virtual byte[] GetKeyAlgorithmParameters() + public virtual byte[]? GetKeyAlgorithmParameters() { ThrowIfInvalid(); - byte[] keyAlgorithmParameters = _lazyKeyAlgorithmParameters ??= Pal.KeyAlgorithmParameters; - return keyAlgorithmParameters.CloneByteArray(); + if (!_lazyKeyAlgorithmParametersCreated) + { + _lazyKeyAlgorithmParameters = Pal.KeyAlgorithmParameters; + _lazyKeyAlgorithmParametersCreated = true; + } + + return _lazyKeyAlgorithmParameters.CloneByteArray(); } - public virtual string GetKeyAlgorithmParametersString() + public virtual string? GetKeyAlgorithmParametersString() { ThrowIfInvalid(); - byte[] keyAlgorithmParameters = GetKeyAlgorithmParameters(); - return keyAlgorithmParameters.ToHexStringUpper(); + byte[]? keyAlgorithmParameters = GetKeyAlgorithmParameters(); + return keyAlgorithmParameters?.ToHexStringUpper(); } public virtual byte[] GetPublicKey() diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs index d1bd2a7f4c9119..46999ed5d7b367 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs @@ -318,11 +318,15 @@ public PublicKey PublicKey if (publicKey == null) { string keyAlgorithmOid = GetKeyAlgorithm(); - byte[] parameters = Pal.KeyAlgorithmParameters; + byte[]? parameters = Pal.KeyAlgorithmParameters; byte[] keyValue = Pal.PublicKeyValue; Oid oid = new Oid(keyAlgorithmOid); // PublicKey can use skipCopy because AsnEncodedData creates a defensive copy of the values. - publicKey = _lazyPublicKey = new PublicKey(oid, new AsnEncodedData(oid, parameters), new AsnEncodedData(oid, keyValue), skipCopy: true); + publicKey = _lazyPublicKey = new PublicKey( + oid, + parameters is null ? null : new AsnEncodedData(oid, parameters), + new AsnEncodedData(oid, keyValue), + skipCopy: true); } return publicKey; @@ -591,7 +595,11 @@ public override string ToString(bool verbose) sb.Append(" "); sb.Append("Parameters: "); - sb.Append(pubKey.EncodedParameters.Format(true)); + + if (pubKey.EncodedParameters is AsnEncodedData parameters) + { + sb.Append(parameters.Format(true)); + } } catch (CryptographicException) { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Unix.cs index f851d163fc8fcb..3d4b144e834738 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Unix.cs @@ -472,7 +472,7 @@ private static bool PublicKeyMatches( return false; } - byte[] certKeyParameters = cert.KeyAlgorithmParameters; + byte[]? certKeyParameters = cert.KeyAlgorithmParameters; switch (certAlgorithm) { @@ -488,6 +488,7 @@ private static bool PublicKeyMatches( case Oids.EcDiffieHellman: return publicKeyInfo.Algorithm.Parameters.HasValue && + certKeyParameters is not null && publicKeyInfo.Algorithm.Parameters.Value.Span.SequenceEqual(certKeyParameters); } @@ -497,7 +498,8 @@ private static bool PublicKeyMatches( return (certKeyParameters?.Length ?? 0) == 0; } - return publicKeyInfo.Algorithm.Parameters.Value.Span.SequenceEqual(certKeyParameters); + return certKeyParameters is not null && + publicKeyInfo.Algorithm.Parameters.Value.Span.SequenceEqual(certKeyParameters); } private static void ExtractPublicKey( diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs index 715d602b0d67bb..30131d70c9f3a1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Android.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.Asn1; +using Internal.Cryptography; namespace System.Security.Cryptography.X509Certificates { @@ -36,7 +37,7 @@ public ECDiffieHellman DecodeECDiffieHellmanPublicKey(ICertificatePal? certifica return new ECDiffieHellmanImplementation.ECDiffieHellmanAndroid(DecodeECPublicKey(certificatePal)); } - public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[] encodedParameters, + public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[]? encodedParameters, ICertificatePal? certificatePal) { switch (oid.Value) @@ -144,11 +145,15 @@ private static RSA DecodeRsaPublicKey(byte[] encodedKeyValue) } } - private static DSA DecodeDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters) + private static DSA DecodeDsaPublicKey(byte[] encodedKeyValue, byte[]? encodedParameters) { SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn { - Algorithm = new AlgorithmIdentifierAsn { Algorithm = Oids.Dsa, Parameters = encodedParameters }, + Algorithm = new AlgorithmIdentifierAsn + { + Algorithm = Oids.Dsa, + Parameters = encodedParameters.ToNullableMemory(), + }, SubjectPublicKey = encodedKeyValue, }; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs index 397aab8bca82cb..e3fdceb4446690 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.Windows.PublicKey.cs @@ -46,7 +46,7 @@ public ECDiffieHellman DecodeECDiffieHellmanPublicKey(ICertificatePal? certifica throw new NotSupportedException(SR.NotSupported_KeyAlgorithm); } - public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[] encodedParameters, ICertificatePal? certificatePal) + public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[]? encodedParameters, ICertificatePal? certificatePal) { int algId = Interop.Crypt32.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_OID_KEY, oid.Value!, OidGroup.PublicKeyAlgorithm, fallBackToAllGroups: true).AlgId; switch (algId) @@ -211,8 +211,13 @@ private static byte[] DecodeKeyBlob(CryptDecodeObjectStructType lpszStructType, return keyBlob; } - private static byte[] ConstructDSSPublicKeyCspBlob(byte[] encodedKeyValue, byte[] encodedParameters) + private static byte[] ConstructDSSPublicKeyCspBlob(byte[] encodedKeyValue, byte[]? encodedParameters) { + if (encodedParameters is null) + { + throw ErrorCode.NTE_BAD_PUBLIC_KEY.ToCryptographicException(); + } + byte[] decodedKeyValue = DecodeDssKeyValue(encodedKeyValue)!; byte[] p, q, g; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs index 4b2a317f08c7e5..d7ed8dafa04031 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.iOS.cs @@ -15,7 +15,7 @@ private static partial IX509Pal BuildSingleton() private sealed partial class AppleX509Pal : IX509Pal { - public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[] encodedParameters, + public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[]? encodedParameters, ICertificatePal? certificatePal) { if (oid.Value != Oids.Rsa) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs index d1b3a584f8d1bb..54f8ff0a90889f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Pal.macOS.cs @@ -7,6 +7,7 @@ using System.Security.Cryptography.Apple; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.Asn1.Pkcs12; +using Internal.Cryptography; namespace System.Security.Cryptography.X509Certificates { @@ -19,7 +20,7 @@ private static partial IX509Pal BuildSingleton() private sealed partial class AppleX509Pal : IX509Pal { - public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[] encodedParameters, + public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte[]? encodedParameters, ICertificatePal? certificatePal) { AppleCertificatePal? applePal = certificatePal as AppleCertificatePal; @@ -73,11 +74,15 @@ private static RSA DecodeRsaPublicKey(byte[] encodedKeyValue) } } - private static DSA DecodeDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters) + private static DSA DecodeDsaPublicKey(byte[] encodedKeyValue, byte[]? encodedParameters) { SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn { - Algorithm = new AlgorithmIdentifierAsn { Algorithm = Oids.Dsa, Parameters = encodedParameters }, + Algorithm = new AlgorithmIdentifierAsn + { + Algorithm = Oids.Dsa, + Parameters = encodedParameters.ToNullableMemory(), + }, SubjectPublicKey = encodedKeyValue, }; diff --git a/src/libraries/System.Security.Cryptography/tests/OpenSslNamedKeysTests.manual.cs b/src/libraries/System.Security.Cryptography/tests/OpenSslNamedKeysTests.manual.cs index e2396634c79a04..298543d710c073 100644 --- a/src/libraries/System.Security.Cryptography/tests/OpenSslNamedKeysTests.manual.cs +++ b/src/libraries/System.Security.Cryptography/tests/OpenSslNamedKeysTests.manual.cs @@ -5,6 +5,7 @@ using System.Text; using Test.Cryptography; using Xunit; +using Microsoft.DotNet.XUnitExtensions; using TempFileHolder = System.Security.Cryptography.X509Certificates.Tests.TempFileHolder; namespace System.Security.Cryptography.Tests @@ -12,58 +13,6 @@ namespace System.Security.Cryptography.Tests // See osslplugins/README.md for instructions on how to build and install the test engine and setup for TPM tests. public class OpenSslNamedKeysTests { - private const string EnvVarPrefix = "DOTNET_CRYPTOGRAPHY_TESTS_"; - - private const string EngineEnvVarPrefix = EnvVarPrefix + "ENGINE_"; - private const string TestEngineEnabledEnvVarName = EngineEnvVarPrefix + "ENABLE"; - - private const string TpmEnvVarPrefix = EnvVarPrefix + "TPM_"; - private const string TpmEcDsaKeyHandleEnvVarName = TpmEnvVarPrefix + "ECDSA_KEY_HANDLE"; - private const string TpmEcDhKeyHandleEnvVarName = TpmEnvVarPrefix + "ECDH_KEY_HANDLE"; - private const string TpmRsaSignKeyHandleEnvVarName = TpmEnvVarPrefix + "RSA_SIGN_KEY_HANDLE"; - private const string TpmRsaDecryptKeyHandleEnvVarName = TpmEnvVarPrefix + "RSA_DECRYPT_KEY_HANDLE"; - - private const string NonExistingEngineName = "dntestnonexisting"; - private const string NonExistingEngineOrProviderKeyName = "nonexisting"; - - private const string TestEngineName = "dntest"; - private const string TestEngineKeyId = "first"; - private const string TpmTssEngineName = "tpm2tss"; - - private const string Tpm2ProviderName = "tpm2"; - - private static string TpmEcDsaKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmEcDsaKeyHandleEnvVarName); - private static string TpmEcDsaKeyHandleUri { get; } = GetHandleKeyUri(TpmEcDsaKeyHandle); - - private static string TpmEcDhKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmEcDhKeyHandleEnvVarName); - private static string TpmEcDhKeyHandleUri { get; } = GetHandleKeyUri(TpmEcDhKeyHandle); - - private static string TpmRsaSignKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmRsaSignKeyHandleEnvVarName); - private static string TpmRsaSignKeyHandleUri { get; } = GetHandleKeyUri(TpmRsaSignKeyHandle); - - private static string TpmRsaDecryptKeyHandle { get; } = Environment.GetEnvironmentVariable(TpmRsaDecryptKeyHandleEnvVarName); - private static string TpmRsaDecryptKeyHandleUri { get; } = GetHandleKeyUri(TpmRsaDecryptKeyHandle); - - public static bool ShouldRunEngineTests { get; } = PlatformDetection.OpenSslPresentOnSystem && StringToBool(Environment.GetEnvironmentVariable(TestEngineEnabledEnvVarName)); - - public static bool ProvidersSupported { get; } = PlatformDetection.IsOpenSsl3; - public static bool ProvidersNotSupported => !ProvidersSupported; - public static bool ShouldRunProviderEcDsaTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmEcDsaKeyHandleUri); - public static bool ShouldRunProviderEcDhTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmEcDhKeyHandleUri); - public static bool ShouldRunProviderRsaSignTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmRsaSignKeyHandleUri); - public static bool ShouldRunProviderRsaDecryptTests { get; } = ProvidersSupported && !string.IsNullOrEmpty(TpmRsaDecryptKeyHandleUri); - public static bool ShouldRunAnyProviderTests => ShouldRunProviderEcDsaTests || ShouldRunProviderEcDhTests || ShouldRunProviderRsaSignTests || ShouldRunProviderRsaDecryptTests; - - public static bool ShouldRunTpmTssTests => ShouldRunEngineTests && !string.IsNullOrEmpty(TpmEcDsaKeyHandle); - - private static readonly string AnyProviderKeyUri = TpmEcDsaKeyHandleUri ?? TpmEcDhKeyHandleUri ?? TpmRsaSignKeyHandleUri ?? TpmRsaDecryptKeyHandleUri ?? "test"; - - private static bool StringToBool(string? value) - => "true".Equals(value, StringComparison.OrdinalIgnoreCase) || value == "1"; - - private static string GetHandleKeyUri(string handle) - => handle != null ? $"handle:{handle}" : null; - // PKCS#1 format private static readonly byte[] s_rsaPrivateKey = ( "3082025C02010002818100BF67168485215A6AB89BCAB9331F6F5F360F4300BE5CF282F77042957E" + @@ -93,16 +42,16 @@ private static string GetHandleKeyUri(string handle) [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.OpenSslNotPresentOnSystem))] public static void EngineNotSupported_ThrowsPlatformNotSupported() { - Assert.Throws(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(TestEngineName, TestEngineKeyId)); - Assert.Throws(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(TestEngineName, TestEngineKeyId)); + Assert.Throws(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.TestEngineKeyId)); + Assert.Throws(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.TestEngineKeyId)); } - [ConditionalFact(nameof(ProvidersNotSupported))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ProvidersNotSupported))] public static void ProvidersNotSupported_ThrowsPlatformNotSupported() { try { - using SafeEvpPKeyHandle key = SafeEvpPKeyHandle.OpenKeyFromProvider("default", NonExistingEngineOrProviderKeyName); + using SafeEvpPKeyHandle key = SafeEvpPKeyHandle.OpenKeyFromProvider("default", OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName); Assert.Fail("We expected an exception to be thrown"); } catch (PlatformNotSupportedException) @@ -120,14 +69,14 @@ public static void ProvidersNotSupported_ThrowsPlatformNotSupported() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.OpenSslPresentOnSystem))] public static void NullArguments() { - Assert.Throws("engineName", () => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(null, TestEngineKeyId)); - Assert.Throws("keyId", () => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(TestEngineName, null)); + Assert.Throws("engineName", () => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(null, OpenSslNamedKeysHelpers.TestEngineKeyId)); + Assert.Throws("keyId", () => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, null)); - Assert.Throws("engineName", () => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(null, TestEngineKeyId)); - Assert.Throws("keyId", () => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(TestEngineName, null)); + Assert.Throws("engineName", () => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(null, OpenSslNamedKeysHelpers.TestEngineKeyId)); + Assert.Throws("keyId", () => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, null)); - Assert.Throws(() => SafeEvpPKeyHandle.OpenKeyFromProvider(null, AnyProviderKeyUri)); - Assert.Throws(() => SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, null)); + Assert.Throws(() => SafeEvpPKeyHandle.OpenKeyFromProvider(null, OpenSslNamedKeysHelpers.AnyProviderKeyUri)); + Assert.Throws(() => SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, null)); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.OpenSslPresentOnSystem))] @@ -136,13 +85,13 @@ public static void EmptyNameThroughNullCharacter() Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine("\0", "foo")); Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine("\0", "foo")); - if (ProvidersSupported) + if (OpenSslNamedKeysHelpers.ProvidersSupported) { Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenKeyFromProvider("\0", "foo")); } } - [ConditionalFact(nameof(ProvidersSupported))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ProvidersSupported))] public static void EmptyUriThroughNullCharacter() { Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenKeyFromProvider("default", "\0")); @@ -151,30 +100,30 @@ public static void EmptyUriThroughNullCharacter() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.OpenSslPresentOnSystem))] public static void Engine_NonExisting() { - Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(NonExistingEngineOrProviderKeyName, TestEngineKeyId)); - Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(NonExistingEngineOrProviderKeyName, TestEngineKeyId)); + Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName, OpenSslNamedKeysHelpers.TestEngineKeyId)); + Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName, OpenSslNamedKeysHelpers.TestEngineKeyId)); } - [ConditionalFact(nameof(ProvidersSupported))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ProvidersSupported))] public static void Provider_NonExisting() { - Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenKeyFromProvider(NonExistingEngineOrProviderKeyName, AnyProviderKeyUri)); + Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName, OpenSslNamedKeysHelpers.AnyProviderKeyUri)); } - [ConditionalFact(nameof(ShouldRunEngineTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunEngineTests))] public static void Engine_NonExistingKey() { - Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(TestEngineName, NonExistingEngineOrProviderKeyName)); - Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(TestEngineName, NonExistingEngineOrProviderKeyName)); + Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName)); + Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenPublicKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName)); } - [ConditionalFact(nameof(ShouldRunAnyProviderTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunAnyProviderTests))] public static void Provider_NonExistingKey() { - Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, NonExistingEngineOrProviderKeyName)); + Assert.ThrowsAny(() => SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.NonExistingEngineOrProviderKeyName)); } - [ConditionalFact(nameof(ProvidersSupported))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ProvidersSupported))] public static void Provider_Default_RSASignAndDecrypt() { using RSA originalKey = RSA.Create(); @@ -194,7 +143,7 @@ public static void Provider_Default_RSASignAndDecrypt() Assert.Equal(data, decrypted); } - [ConditionalFact(nameof(ProvidersSupported))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ProvidersSupported))] public static void Provider_Default_ECDsaSignAndVerify() { using ECDsa originalKey = ECDsa.Create(); @@ -210,7 +159,7 @@ public static void Provider_Default_ECDsaSignAndVerify() Assert.True(originalKey.VerifyData(data, signature, HashAlgorithmName.SHA256), "signature does not verify with the right key"); } - [ConditionalFact(nameof(ProvidersSupported))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ProvidersSupported))] public static void Provider_Default_ECDHKeyExchange() { using ECDiffieHellman originalAliceKey = ECDiffieHellman.Create(); @@ -231,20 +180,20 @@ public static void Provider_Default_ECDHKeyExchange() Assert.Equal(sharedSecret1, sharedSecret3); } - [ConditionalFact(nameof(ShouldRunEngineTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunEngineTests))] public static void Engine_OpenExistingPrivateKey() { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(TestEngineName, TestEngineKeyId); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.TestEngineKeyId); using RSA priKey = new RSAOpenSsl(priKeyHandle); RSAParameters rsaParams = priKey.ExportParameters(includePrivateParameters: true); Assert.NotNull(rsaParams.D); Assert.Equal(s_rsaPubKey, priKey.ExportRSAPublicKey()); } - [ConditionalFact(nameof(ShouldRunEngineTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunEngineTests))] public static void Engine_OpenExistingPublicKey() { - using SafeEvpPKeyHandle pubKeyHandle = SafeEvpPKeyHandle.OpenPublicKeyFromEngine(TestEngineName, TestEngineKeyId); + using SafeEvpPKeyHandle pubKeyHandle = SafeEvpPKeyHandle.OpenPublicKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.TestEngineKeyId); using RSA pubKey = new RSAOpenSsl(pubKeyHandle); Assert.ThrowsAny(() => pubKey.ExportParameters(includePrivateParameters: true)); RSAParameters rsaParams = pubKey.ExportParameters(includePrivateParameters: false); @@ -252,10 +201,10 @@ public static void Engine_OpenExistingPublicKey() Assert.Equal(s_rsaPubKey, pubKey.ExportRSAPublicKey()); } - [ConditionalFact(nameof(ShouldRunEngineTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunEngineTests))] public static void Engine_UsePrivateKey() { - using (SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(TestEngineName, TestEngineKeyId)) + using (SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.TestEngineKeyId)) using (RSA rsaPri = new RSAOpenSsl(priKeyHandle)) using (RSA rsaPub = RSA.Create()) { @@ -278,10 +227,10 @@ public static void Engine_UsePrivateKey() } } - [ConditionalFact(nameof(ShouldRunEngineTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunEngineTests))] public static void Engine_UsePublicKey() { - using (SafeEvpPKeyHandle pubKeyHandle = SafeEvpPKeyHandle.OpenPublicKeyFromEngine(TestEngineName, TestEngineKeyId)) + using (SafeEvpPKeyHandle pubKeyHandle = SafeEvpPKeyHandle.OpenPublicKeyFromEngine(OpenSslNamedKeysHelpers.TestEngineName, OpenSslNamedKeysHelpers.TestEngineKeyId)) using (RSA rsaPub = new RSAOpenSsl(pubKeyHandle)) using (RSA rsaPri = RSA.Create()) { @@ -304,10 +253,10 @@ public static void Engine_UsePublicKey() } } - [ConditionalFact(nameof(ShouldRunTpmTssTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunTpmTssTests))] public static void Engine_OpenExistingTPMPrivateKey() { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(TpmTssEngineName, TpmEcDsaKeyHandle); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine(OpenSslNamedKeysHelpers.TpmTssEngineName, OpenSslNamedKeysHelpers.TpmEcDsaKeyHandle); using ECDsa ecdsaPri = new ECDsaOpenSsl(priKeyHandle); using ECDsa ecdsaBad = ECDsa.Create(); ecdsaBad.KeySize = ecdsaPri.KeySize; @@ -321,10 +270,10 @@ public static void Engine_OpenExistingTPMPrivateKey() Assert.False(ecdsaPri.VerifyData(data, badSignature, HashAlgorithmName.SHA256)); } - [ConditionalFact(nameof(ShouldRunProviderEcDsaTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderEcDsaTests))] public static void Provider_TPM2ECDSA() { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmEcDsaKeyHandleUri); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmEcDsaKeyHandleUri); using ECDsa ecdsaPri = new ECDsaOpenSsl(priKeyHandle); byte[] data = new byte[] { 1, 2, 3, 1, 1, 2, 3 }; @@ -359,10 +308,10 @@ public static void Provider_TPM2ECDSA() Assert.ThrowsAny(() => ecdsaPri.ExportParameters(includePrivateParameters: true)); } - [ConditionalFact(nameof(ShouldRunProviderEcDsaTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderEcDsaTests))] public static void Provider_TPM2ECDSA_ExportParameters() { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmEcDsaKeyHandleUri); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmEcDsaKeyHandleUri); using ECDsa ecdsaPri = new ECDsaOpenSsl(priKeyHandle); ECDsa ecdsaPub = ECDsa.Create(); @@ -374,10 +323,10 @@ public static void Provider_TPM2ECDSA_ExportParameters() Assert.True(ecdsaPub.VerifyData(data, signature, HashAlgorithmName.SHA256)); } - [ConditionalFact(nameof(ShouldRunProviderEcDsaTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderEcDsaTests))] public static void Provider_TPM2ECDSA_ExportExplicitParameters() { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmEcDsaKeyHandleUri); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmEcDsaKeyHandleUri); using ECDsa ecdsaPri = new ECDsaOpenSsl(priKeyHandle); ECDsa ecdsaPub = ECDsa.Create(); @@ -389,10 +338,10 @@ public static void Provider_TPM2ECDSA_ExportExplicitParameters() Assert.True(ecdsaPub.VerifyData(data, signature, HashAlgorithmName.SHA256)); } - [ConditionalFact(nameof(ShouldRunProviderEcDhTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderEcDhTests))] public static void Provider_TPM2ECDH() { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmEcDhKeyHandleUri); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmEcDhKeyHandleUri); using ECDiffieHellman alicePri = new ECDiffieHellmanOpenSsl(priKeyHandle); using ECDiffieHellman alicePub = ECDiffieHellman.Create(); @@ -426,13 +375,18 @@ public static void Provider_TPM2ECDH() } } - [ConditionalFact(nameof(ShouldRunProviderRsaSignTests))] - [ActiveIssue("https://github.com/tpm2-software/tpm2-openssl/issues/115")] - // or a workaround API proposal - [ActiveIssue("https://github.com/dotnet/runtime/issues/104080")] - public static void Provider_TPM2SignRsa() + [ConditionalTheory(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderRsaTests))] + [MemberData(nameof(OpenSslNamedKeysHelpers.RSASignaturePaddingValues), MemberType = typeof(OpenSslNamedKeysHelpers))] + public static void Provider_TPM2SignRsa(RSASignaturePadding signaturePadding) { - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmRsaSignKeyHandleUri); + if (signaturePadding == RSASignaturePadding.Pss) + { + //[ActiveIssue("https://github.com/dotnet/runtime/issues/104080")] + //[ActiveIssue("https://github.com/tpm2-software/tpm2-openssl/issues/115")] + throw new SkipTestException("Salt Length is ignored by tpm2 provider and differs from .NET defaults"); + } + + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmRsaKeyHandleUri); using RSA rsaPri = new RSAOpenSsl(priKeyHandle); byte[] rsaPubBytes = rsaPri.ExportSubjectPublicKeyInfo(); RSA rsaPub = RSA.Create(); @@ -443,26 +397,26 @@ public static void Provider_TPM2SignRsa() rsaBad.KeySize = rsaPri.KeySize; byte[] data = new byte[] { 1, 2, 3, 1, 1, 2, 3 }; - byte[] badSignature = rsaBad.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); + byte[] badSignature = rsaBad.SignData(data, HashAlgorithmName.SHA256, signaturePadding); // can use same key more than once for (int i = 0; i < 10; i++) { data[0] = (byte)i; - byte[] signature = rsaPri.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); - Assert.True(rsaPub.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss), "signature does not verify with the right key"); - Assert.False(rsaPub.VerifyData(data, badSignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss), "signature should not verify with the wrong key"); + byte[] signature = rsaPri.SignData(data, HashAlgorithmName.SHA256, signaturePadding); + Assert.True(rsaPub.VerifyData(data, signature, HashAlgorithmName.SHA256, signaturePadding), "signature does not verify with the right key"); + Assert.False(rsaPub.VerifyData(data, badSignature, HashAlgorithmName.SHA256, signaturePadding), "signature should not verify with the wrong key"); signature[12] ^= 1; - Assert.False(rsaPub.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss), "tampered signature should not verify"); + Assert.False(rsaPub.VerifyData(data, signature, HashAlgorithmName.SHA256, signaturePadding), "tampered signature should not verify"); // TPM key is intended for sign only, we could theoretically make verify work without needing to export/import by forcing 'default' provider // for this operation it's most likely misusage on user part and tpm2 provider intentionally didn't allow it so we will follow this logic. - Assert.ThrowsAny(() => rsaPri.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss)); + Assert.ThrowsAny(() => rsaPri.VerifyData(data, signature, HashAlgorithmName.SHA256, signaturePadding)); } } - [ConditionalTheory(nameof(ShouldRunProviderRsaDecryptTests))] + [ConditionalTheory(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderRsaTests))] [InlineData(RSAEncryptionPaddingMode.Pkcs1)] [InlineData(RSAEncryptionPaddingMode.Oaep)] public static void Provider_TPM2DecryptRsa(RSAEncryptionPaddingMode mode) @@ -481,7 +435,7 @@ public static void Provider_TPM2DecryptRsa(RSAEncryptionPaddingMode mode) throw new ArgumentOutOfRangeException(nameof(mode)); } - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmRsaDecryptKeyHandleUri); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmRsaKeyHandleUri); using RSA rsaPri = new RSAOpenSsl(priKeyHandle); byte[] rsaPubBytes = rsaPri.ExportSubjectPublicKeyInfo(); RSA rsaPub = RSA.Create(); @@ -517,13 +471,13 @@ public static void Provider_TPM2DecryptRsa(RSAEncryptionPaddingMode mode) } } - [ConditionalFact(nameof(ShouldRunProviderRsaDecryptTests))] + [ConditionalFact(typeof(OpenSslNamedKeysHelpers), nameof(OpenSslNamedKeysHelpers.ShouldRunProviderRsaTests))] public static void Provider_TPM2DecryptRsa_ExportParameters() { // TPM2 OAEP support was added in the second half of 2023 therefore we only test Pkcs1 padding // See: https://github.com/tpm2-software/tpm2-openssl/issues/89 RSAEncryptionPadding padding = RSAEncryptionPadding.Pkcs1; - using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(Tpm2ProviderName, TpmRsaDecryptKeyHandleUri); + using SafeEvpPKeyHandle priKeyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider(OpenSslNamedKeysHelpers.Tpm2ProviderName, OpenSslNamedKeysHelpers.TpmRsaKeyHandleUri); using RSA rsaPri = new RSAOpenSsl(priKeyHandle); RSA rsaPub = RSA.Create(); diff --git a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj index 2c39cd9284a3a5..401199911c1906 100644 --- a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj +++ b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj @@ -4,6 +4,7 @@ true true $(NoWarn);SYSLIB0021;SYSLIB0026;SYSLIB0027;SYSLIB0028;SYSLIB0057 + $(NoWarn);SYSLIB5006 true @@ -150,6 +151,16 @@ Link="ProductionCode\Common\System\Net\MultiArrayBuffer.cs" /> + + + + + + diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs index 8c434619d72eb0..4824610078bb04 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; +using RsaTestData = System.Security.Cryptography.Rsa.Tests.TestData; using Test.Cryptography; using Xunit; @@ -1119,6 +1120,77 @@ public static void CreateSelfSigned_CurveNameIsCaseInsensitive(string curveName, } } + [Fact] + public static void Create_SubjectCertificateNullKeyParameters() + { + + using (RSA rootKey = RSA.Create(RsaTestData.RSA2048Params)) + using (X509Certificate2 cert = X509Certificate2.CreateFromPem(TestData.RsaNoParametersCertificate)) + { + CertificateRequest rootReq = new("CN=Root", rootKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); + rootReq.CertificateExtensions.Add(X509BasicConstraintsExtension.CreateForCertificateAuthority()); + + using (X509Certificate2 root = rootReq.CreateSelfSigned( + DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1))) + { + PublicKey publicKey = cert.PublicKey; + Assert.Null(publicKey.EncodedParameters); + + CertificateRequest req = new( + cert.SubjectName, + publicKey, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pss); + byte[] serial = RandomNumberGenerator.GetBytes(8); + + using (X509Certificate2 issued = req.Create(root, root.NotBefore, root.NotAfter.AddDays(-1), serial)) + { + Assert.Null(issued.GetKeyAlgorithmParameters()); + } + } + } + } + + [Fact] + public static void CreateSigningRequest_SubjectCertificateNullKeyParameters() + { + + using (RSA rootKey = RSA.Create(RsaTestData.RSA2048Params)) + using (RSA leafKey = RSA.Create(2048)) + { + CertificateRequest rootReq = new("CN=Root", rootKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); + rootReq.CertificateExtensions.Add(X509BasicConstraintsExtension.CreateForCertificateAuthority()); + + using (X509Certificate2 root = rootReq.CreateSelfSigned( + DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1))) + { + PublicKey publicKey = new(leafKey); + PublicKey parameterlessPublicKey = new(publicKey.Oid, null, publicKey.EncodedKeyValue); + + CertificateRequest req = new( + new X500DistinguishedName("CN=My Cert"), + parameterlessPublicKey, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pss); + + X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(leafKey, RSASignaturePadding.Pss); + byte[] reqBytes = req.CreateSigningRequest(generator); + + CertificateRequest reloaded = CertificateRequest.LoadSigningRequest( + reqBytes, + HashAlgorithmName.SHA256, + signerSignaturePadding: RSASignaturePadding.Pss); + + byte[] serial = RandomNumberGenerator.GetBytes(8); + + using (X509Certificate2 issued = req.Create(root, root.NotBefore, root.NotAfter.AddDays(-1), serial)) + { + Assert.Null(issued.GetKeyAlgorithmParameters()); + } + } + } + } + private class InvalidSignatureGenerator : X509SignatureGenerator { private readonly byte[] _signatureAlgBytes; diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/PropsTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/PropsTests.cs index d6396a65114e6f..0f7408a58c85e3 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/PropsTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/PropsTests.cs @@ -172,42 +172,10 @@ public static void GetPublicKey_X509Signature_NoParameters() // This certificate has omitted the parameters section completely, // which while RFC compliant (it's labelled OPTIONAL) isn't what everyone // else does. So this test ensures that we can read such a cert. - const string PemEncodedCert = @" ------BEGIN CERTIFICATE----- -MIIE4jCCAsygAwIBAgIEMTI0NjALBgkqhkiG9w0BAQUwgZgxCzAJBgNVBAYTAlVT -MQswCQYDVQQIDAJOWTEbMBkGA1UECgwSUVogSW5kdXN0cmllcywgTExDMRswGQYD -VQQLDBJRWiBJbmR1c3RyaWVzLCBMTEMxGTAXBgNVBAMMEHF6aW5kdXN0cmllcy5j -b20xJzAlBgkqhkiG9w0BCQEWGHN1cHBvcnRAcXppbmR1c3RyaWVzLmNvbTAeFw0x -NjA0MDYyMTAwMDBaFw0xNzA0MDcyMTAwMDBaMIGtMQswCQYDVQQGDAJDWjEXMBUG -A1UECAwOQ3plY2ggUmVwdWJsaWMxDTALBgNVBAcMBEJybm8xGTAXBgNVBAoMEHNt -c3RpY2tldCBzLnIuby4xGTAXBgNVBAsMEHNtc3RpY2tldCBzLnIuby4xHjAcBgNV -BAMMFXBva2xhZG5hLnNtc3RpY2tldC5jejEgMB4GCSqGSIb3DQEJAQwRaW5mb0Bz -bXN0aWNrZXQuY3owggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIBCgKCAQEAsDh05CAX -Wp29GTbjk3gzeCCe/1t7V3aNTwbtzkUtLZnbS9tge/+Iaqsz10IOWk3SndLhPIfa -KUvX/pnkq5CXIVyTTyRoFpyYrDfNoRmZ/3uTmMG50urk0Rg/+e4f2k32BfFTfB0W -3V169+QQ6Xvvuoyh62cppfi1msgFJ6WGmEF1r73Q6tK1vxfuA9wJfMWTl4Sg8nEf -9NXsTc9VAwGKRJbmTUN1b0xsqFvlFbxvaxPGwxNM29lXWlez5KEsh0sfUyTGQuTB -tu5JMC57TGvL0/TwgwrtOxQL5+N4lJAWnUQ+z3XXL694eSsuKlgw2yasO2ZwWnyz -eap2vnN/CifUgwIDAQABoyMwITAfBgNVHSMEGDAWgBSQplC3hNS56l/yBYQTeEXo -qXVUXDALBgkqhkiG9w0BAQUDggIBAHMNLagyKZYla3gR0KOhxiUWuFG2gU7uB2v+ -zeqmIh6XxG4/39r6SJgUIimZ2aVQjYLa/fgrn5FRXhDqMumLJ3rWp8GB05evmdWl -WMQrb6E39jsFXuCzev6mCjiHxzGC2I7SRvFmnCj5fvOF81V5dLjU2PnCNqPym9Aw -XbEHVXTxpM9okSeq/EoeuTA5NHl/EySwYiGoexz0Ia51M5cw5W5go2Abmtqs4bbz -7OFeZKP9fd1p+C/ZnekgKq+3SJ9qbEiJxoPir3rG2N0mw7iI5pwvbCixY9irZh5o -Lrc5RvH4hdpygNSm4MYEuBykEW0tizkcVanGCUmGdjxM22Y9XdPgKitS04rVk/2U -C1Gszv9KvtmQ2P3/HWWWiOQgljc3SFqBltt6TqJTGCtLEbWRw6V+sw3SALoafvLg -tIsyWUsjM5LunRkUQ+HIsmKo42943TmgUvgRuuo0nsEFI5TS7Jh0iC/2gQEt7XGh -wzOTZ0HzM3oNnTphlXFLBwL9MUgWKbhu5Fg486dDMeQmZmhztW/+F/uHHYFisk+1 -tmr2prSh5i4fD71t4p+EGJJQxM4wCiXRLzggIVGUAIrzynxO2vjYiMQxAUH3tdsX -JI6fq+e/mFZOE2XQmYu3/hQEw8/2F6usF1lyvwMZt2TgQZF1/g8gFVQUY2mGLM1z -Wry5FNNo ------END CERTIFICATE-----"; - - byte[] bytes = System.Text.Encoding.ASCII.GetBytes(PemEncodedCert); - - using (X509Certificate2 cert = new X509Certificate2(bytes)) + using (X509Certificate2 cert = X509Certificate2.CreateFromPem(TestData.RsaNoParametersCertificate)) { - Assert.Equal(Array.Empty(), cert.GetKeyAlgorithmParameters()); + Assert.Null(cert.GetKeyAlgorithmParameters()); + Assert.Null(cert.GetKeyAlgorithmParametersString()); Assert.Equal("1.2.840.113549.1.1.1", cert.GetKeyAlgorithm()); } } diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/PublicKeyTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/PublicKeyTests.cs index 5d3077ebde1e9b..171e810f2554cb 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/PublicKeyTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/PublicKeyTests.cs @@ -275,6 +275,25 @@ public static void TestEncodedParameters_ECDH() Assert.Equal(expectedParametersHex, pk.EncodedParameters.RawData.ByteArrayToHex()); } + [Fact] + public static void TestEncodedParameters_None() + { + using (X509Certificate2 cert = X509Certificate2.CreateFromPem(TestData.RsaNoParametersCertificate)) + { + PublicKey key = cert.PublicKey; + Assert.Null(key.EncodedParameters); + + using (AsymmetricAlgorithm alg = key.Key) + { + Assert.NotNull(alg); + } + + byte[] spki = key.ExportSubjectPublicKeyInfo(); + PublicKey imported = PublicKey.CreateFromSubjectPublicKeyInfo(spki, out _); + Assert.Null(imported.EncodedParameters); + } + } + [Fact] public static void TestKey_RSA() { diff --git a/src/libraries/System.Security.Cryptography/tests/osslplugins/README.md b/src/libraries/System.Security.Cryptography/tests/osslplugins/README.md index 37f27a7b17ee99..95a01e862b2b36 100644 --- a/src/libraries/System.Security.Cryptography/tests/osslplugins/README.md +++ b/src/libraries/System.Security.Cryptography/tests/osslplugins/README.md @@ -133,12 +133,7 @@ In order to run provider tests you need to have TPM handles and set one or more # Handle values are just an example - refer to 'Getting TPM handle' section for instructions on how to create or get them export DOTNET_CRYPTOGRAPHY_TESTS_TPM_ECDSA_KEY_HANDLE=0x81000007 export DOTNET_CRYPTOGRAPHY_TESTS_TPM_ECDH_KEY_HANDLE=0x8100000d -export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_DECRYPT_KEY_HANDLE=0x8100000c - -# RSA-PSS tests will always fail due to following issues but they can be run still -# https://github.com/dotnet/runtime/issues/104080 -# https://github.com/tpm2-software/tpm2-openssl/issues/115 -export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_SIGN_KEY_HANDLE=0x8100000a +export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_KEY_HANDLE=0x81000003 ``` # Getting TPM handle @@ -172,6 +167,26 @@ You can also extract public key like this if needed: tpm2_readpublic -c 0x81000007 -o /tmp/key.pub ``` +## Creating specific persistent handle + +After you create a `ctx` file you can assign it to a specific handle rather than random: + +```bash +tpm2_evictcontrol -C o -c primary.ctx 0x8100000c +``` + +For how to create `ctx` files see further `Creating keys and handles` section. + +## Removing (evicting) persistent handles + +Handle can be removed with `tpm2_evictcontrol -C o -c `, for example: + +```bash +tpm2_evictcontrol -C o -c 0x81000001 +``` + +Note that this command looks identical to the one for assigning handle but it has different effect when handle rather than `ctx` file is provided. + ### Testing handle with OpenSSL CLI In case you find issues with your handle you can test it using OpenSSL CLI, for example `0x81000004` can be tested like following: @@ -197,7 +212,33 @@ openssl pkeyutl -verify -in testdata.dgst -sigfile testdata.sig -inkey testkey.p ## Creating keys and handles -### ECDSA key +### Quick recipe for creating handles + +Disclaimer: You should run this only on a test environment + +```bash +# Create ECDSA, ECDH, RSA sign and RSA decrypt keys respectively +tpm2_createprimary -C o -g sha256 -G ecc256:ecdsa-sha256:null -c ecdsa.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|sign' +tpm2_createprimary -C o -g sha256 -G ecc256 -c ecdh.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|decrypt' +tpm2_createprimary -C o -g sha256 -G rsa2048 -c rsa.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|sign|decrypt' + +# Create persistent handles for them +tpm2_evictcontrol -C o -c ecdsa.ctx 0x81000007 +tpm2_evictcontrol -C o -c ecdh.ctx 0x8100000d +tpm2_evictcontrol -C o -c rsa.ctx 0x81000003 +``` + +#### Quick recipe for setup testing environments + +If you've used quick recipe for creating you can setup your environment variables like following: + +```bash +export DOTNET_CRYPTOGRAPHY_TESTS_TPM_ECDSA_KEY_HANDLE=0x81000007 +export DOTNET_CRYPTOGRAPHY_TESTS_TPM_ECDH_KEY_HANDLE=0x8100000d +export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_KEY_HANDLE=0x81000003 +``` + +### ECDSA key (SHA256) ```bash tpm2_createprimary -C o -g sha256 -G ecc256:ecdsa-sha256:null -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|sign' @@ -206,7 +247,7 @@ tpm2_createprimary -C o -g sha256 -G ecc256:ecdsa-sha256:null -c primary.ctx -a tpm2_evictcontrol -C o -c primary.ctx ``` -### ECDH key +### ECDH key (SHA256) ```bash tpm2_createprimary -C o -g sha256 -G ecc256 -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|decrypt' @@ -215,13 +256,17 @@ tpm2_createprimary -C o -g sha256 -G ecc256 -c primary.ctx -a 'fixedtpm|fixedpar tpm2_evictcontrol -C o -c primary.ctx ``` -### RSA key (RSAPSS + SHA256) +### RSA key (signing or decryption + SHA256) -This is not used by tests but if needed for further testing: +In order to restrict key to only sign or decrypt remove the appropriate flag. +In our tests some TLS scenarios RSA cert might still need decrypt operation for key exchange therefore we create RSA key that can do both. ```bash # To create key -tpm2_createprimary -C o -g sha256 -G rsa2048:rsapss:null -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|sign' +tpm2_createprimary -C o -g sha256 -G rsa2048 -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|sign|decrypt' + +# To restrict handle to i.e. only PSS following command can be used: +# tpm2_createprimary -C o -g sha256 -G rsa2048:rsapss:null -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|sign' # To create permenent handle and print it: tpm2_evictcontrol -C o -c primary.ctx @@ -229,8 +274,6 @@ tpm2_evictcontrol -C o -c primary.ctx ### RSA key (decryption) -This is not used by tests but if needed for further testing: - ```bash # To create key tpm2_createprimary -C o -g sha256 -G rsa2048 -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|decrypt' diff --git a/src/libraries/System.Security.Cryptography/tests/osslplugins/test.sh b/src/libraries/System.Security.Cryptography/tests/osslplugins/test.sh index 7c8cd686c31bbe..ab87eca40b2b18 100755 --- a/src/libraries/System.Security.Cryptography/tests/osslplugins/test.sh +++ b/src/libraries/System.Security.Cryptography/tests/osslplugins/test.sh @@ -45,24 +45,12 @@ if [ -z "$DOTNET_CRYPTOGRAPHY_TESTS_TPM_ECDH_KEY_HANDLE" ]; then echo fi -if [ -z "$DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_SIGN_KEY_HANDLE" ]; then - echo 'WARNING: [ActiveIssue("https://github.com/tpm2-software/tpm2-openssl/issues/115")]' - echo 'WARNING: [ActiveIssue("https://github.com/dotnet/runtime/issues/104080")]' - echo "WARNING: TPM RSA sign tests will not be run" +if [ -z "$DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_KEY_HANDLE" ]; then + echo "WARNING: TPM RSA sign and decrypt tests will not be run" echo "WARNING: Use following environmental variable to enable them:" - echo "WARNING: export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_SIGN_KEY_HANDLE=YourHandleHere" + echo "WARNING: export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_KEY_HANDLE=YourHandleHere" echo "WARNING: For example:" - echo "WARNING: export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_SIGN_KEY_HANDLE=0x8100000a" - echo "WARNING: Refer to README.md for more information on how to get handle." - echo -fi - -if [ -z "$DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_DECRYPT_KEY_HANDLE" ]; then - echo "WARNING: TPM RSA decrypt tests will not be run" - echo "WARNING: Use following environmental variable to enable them:" - echo "WARNING: export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_DECRYPT_KEY_HANDLE=YourHandleHere" - echo "WARNING: For example:" - echo "WARNING: export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_DECRYPT_KEY_HANDLE=0x8100000c" + echo "WARNING: export DOTNET_CRYPTOGRAPHY_TESTS_TPM_RSA_KEY_HANDLE=0x81000003" echo "WARNING: Refer to README.md for more information on how to get handle." echo fi @@ -76,5 +64,11 @@ cd "$ssc_src_path" $dotnet build cd "$ssc_tests_path" - $dotnet test --filter "FullyQualifiedName~System.Security.Cryptography.Tests.OpenSslNamedKeysTests." + +# TLS tests are in System.Net.Security +cd "$libsrc_path/System.Net.Security/src" +$dotnet build + +cd "$libsrc_path/System.Net.Security/tests/FunctionalTests" +$dotnet test --filter "FullyQualifiedName~System.Net.Security.Tests.SslStreamOpenSslNamedKeys." diff --git a/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj b/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj index 2441afcdf6bdd0..14896f075d72aa 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj +++ b/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj @@ -96,8 +96,8 @@ Link="Common\Interop\Interop.IsWellKnownSid.cs" /> - + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj index 728247e88b334f..9cc71eee22f1b6 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj @@ -2,7 +2,7 @@ true Exe - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.Tests.csproj b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.Tests.csproj index 1039fad47f499f..5c8f2bf3ce8014 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.Tests.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) diff --git a/src/libraries/System.Text.Encoding.CodePages/tests/System.Text.Encoding.CodePages.Tests.csproj b/src/libraries/System.Text.Encoding.CodePages/tests/System.Text.Encoding.CodePages.Tests.csproj index 8ebf6a6f81d912..12fdc3f8ae3bc8 100644 --- a/src/libraries/System.Text.Encoding.CodePages/tests/System.Text.Encoding.CodePages.Tests.csproj +++ b/src/libraries/System.Text.Encoding.CodePages/tests/System.Text.Encoding.CodePages.Tests.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Text.Encodings.Web/tests/System.Text.Encodings.Web.Tests.csproj b/src/libraries/System.Text.Encodings.Web/tests/System.Text.Encodings.Web.Tests.csproj index 95511e07478a9d..7e14229268e289 100644 --- a/src/libraries/System.Text.Encodings.Web/tests/System.Text.Encodings.Web.Tests.csproj +++ b/src/libraries/System.Text.Encodings.Web/tests/System.Text.Encodings.Web.Tests.csproj @@ -1,16 +1,19 @@ + + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) 16.0 $(NoWarn);CS3021 + False + @@ -42,11 +45,13 @@ + + @@ -57,8 +62,9 @@ + - + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs index 3a0e32900ad6e8..3f5965f5b7775d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs @@ -169,7 +169,6 @@ rootValue is not null && try { isFinalBlock = EffectiveConverter.WriteCore(writer, rootValue, Options, ref state); - writer.Flush(); if (state.SuppressFlush) { @@ -179,6 +178,7 @@ rootValue is not null && } else { + writer.Flush(); FlushResult result = await pipeWriter.FlushAsync(cancellationToken).ConfigureAwait(false); if (result.IsCanceled || result.IsCompleted) { @@ -230,6 +230,9 @@ rootValue is not null && } catch { + // Reset the writer in exception cases as we don't want the writer.Dispose() call to flush any pending bytes. + writer.Reset(); + writer.Dispose(); // On exception, walk the WriteStack for any orphaned disposables and try to dispose them. await state.DisposePendingDisposablesOnExceptionAsync().ConfigureAwait(false); throw; diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets index a18436db4388c9..455a99709805da 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets index ff591bb4136401..c7932f9855e9e6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true 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 a0a8167ec328c9..972aef40796120 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 @@ -886,11 +886,13 @@ private int ReadExactlyFromSource(byte[] buffer, int offset, int count) } // TODO: Deserialize to use PipeReader overloads once implemented - private class AsyncPipelinesSerializerWrapper : JsonSerializerWrapper + private class AsyncPipelinesSerializerWrapper : StreamingJsonSerializerWrapper { public override JsonSerializerOptions DefaultOptions => JsonSerializerOptions.Default; public override bool SupportsNullValueOnDeserialize => true; + public override bool IsAsyncSerializer => true; + public override async Task DeserializeWrapper(string json, JsonSerializerOptions options = null) { return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), options); @@ -915,6 +917,31 @@ public override async Task DeserializeWrapper(string json, Type type, Js return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), type, context); } + public override Task DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions? options = null) + { + return JsonSerializer.DeserializeAsync(utf8Json, returnType, options).AsTask(); + } + + public override Task DeserializeWrapper(Stream utf8Json, JsonSerializerOptions? options = null) + { + return JsonSerializer.DeserializeAsync(utf8Json, options).AsTask(); + } + + public override Task DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerContext context) + { + return JsonSerializer.DeserializeAsync(utf8Json, returnType, context).AsTask(); + } + + public override Task DeserializeWrapper(Stream utf8Json, JsonTypeInfo jsonTypeInfo) + { + return JsonSerializer.DeserializeAsync(utf8Json, jsonTypeInfo).AsTask(); + } + + public override Task DeserializeWrapper(Stream utf8Json, JsonTypeInfo jsonTypeInfo) + { + return JsonSerializer.DeserializeAsync(utf8Json, jsonTypeInfo).AsTask(); + } + public override async Task SerializeWrapper(object value, Type inputType, JsonSerializerOptions options = null) { Pipe pipe = new Pipe(); @@ -969,6 +996,71 @@ public override async Task SerializeWrapper(object value, JsonTypeInfo j pipe.Reader.AdvanceTo(result.Buffer.End); return stringResult; } + + public override async Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerOptions? options = null) + { + var writer = PipeWriter.Create(stream); + try + { + await JsonSerializer.SerializeAsync(writer, value, inputType, options); + } + finally + { + await writer.FlushAsync(); + } + } + + public override async Task SerializeWrapper(Stream stream, T value, JsonSerializerOptions? options = null) + { + var writer = PipeWriter.Create(stream); + try + { + await JsonSerializer.SerializeAsync(writer, value, options); + } + finally + { + await writer.FlushAsync(); + } + } + + public override async Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerContext context) + { + var writer = PipeWriter.Create(stream); + try + { + await JsonSerializer.SerializeAsync(writer, value, inputType, context); + } + finally + { + await writer.FlushAsync(); + } + } + + public override async Task SerializeWrapper(Stream stream, T value, JsonTypeInfo jsonTypeInfo) + { + var writer = PipeWriter.Create(stream); + try + { + await JsonSerializer.SerializeAsync(writer, value, jsonTypeInfo); + } + finally + { + await writer.FlushAsync(); + } + } + + public override async Task SerializeWrapper(Stream stream, object value, JsonTypeInfo jsonTypeInfo) + { + var writer = PipeWriter.Create(stream); + try + { + await JsonSerializer.SerializeAsync(writer, value, jsonTypeInfo); + } + finally + { + await writer.FlushAsync(); + } + } } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj index 9225d8944bd2df..201b569a9eecb0 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true diff --git a/src/libraries/System.Threading.AccessControl/tests/System.Threading.AccessControl.Tests.csproj b/src/libraries/System.Threading.AccessControl/tests/System.Threading.AccessControl.Tests.csproj index 3b9e105954d70f..e70e57b309c763 100644 --- a/src/libraries/System.Threading.AccessControl/tests/System.Threading.AccessControl.Tests.csproj +++ b/src/libraries/System.Threading.AccessControl/tests/System.Threading.AccessControl.Tests.csproj @@ -1,7 +1,9 @@ + - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent)-windows;$(NetFrameworkCurrent) + @@ -14,7 +16,9 @@ + + diff --git a/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj b/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj index 06e639f472a3ce..55ef0e463ca130 100644 --- a/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj +++ b/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj @@ -1,8 +1,10 @@ + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true + @@ -14,7 +16,8 @@ - + + @@ -22,7 +25,9 @@ Private="true" SetTargetFramework="TargetFramework=$(NetCoreAppMinimum)" /> - + + + diff --git a/src/libraries/System.Threading.RateLimiting/tests/System.Threading.RateLimiting.Tests.csproj b/src/libraries/System.Threading.RateLimiting/tests/System.Threading.RateLimiting.Tests.csproj index 03d8eb2051e08c..8d1e0c48959af4 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/System.Threading.RateLimiting.Tests.csproj +++ b/src/libraries/System.Threading.RateLimiting/tests/System.Threading.RateLimiting.Tests.csproj @@ -1,7 +1,9 @@ + - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) + @@ -14,10 +16,9 @@ + - - - + diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj b/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj index 1162f2ea07cea5..0c3df0b16a7e95 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj @@ -1,8 +1,10 @@ + + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true - $(NetCoreAppCurrent);$(NetFrameworkMinimum) + @@ -26,13 +28,16 @@ + + + diff --git a/src/libraries/System.Threading.Thread/tests/DefaultApartmentStateMain/DefaultApartmentStateMain.csproj b/src/libraries/System.Threading.Thread/tests/DefaultApartmentStateMain/DefaultApartmentStateMain.csproj index e7e4668a5bf3ac..c3b331ee0fd8ba 100644 --- a/src/libraries/System.Threading.Thread/tests/DefaultApartmentStateMain/DefaultApartmentStateMain.csproj +++ b/src/libraries/System.Threading.Thread/tests/DefaultApartmentStateMain/DefaultApartmentStateMain.csproj @@ -1,12 +1,13 @@ + + $(NetCoreAppCurrent) Exe - - .exe true - $(NetCoreAppCurrent) + + \ No newline at end of file diff --git a/src/libraries/System.Threading.Thread/tests/MTAMain/MTAMain.csproj b/src/libraries/System.Threading.Thread/tests/MTAMain/MTAMain.csproj index fab048a7e1ecbb..ce571bdd34a3c8 100644 --- a/src/libraries/System.Threading.Thread/tests/MTAMain/MTAMain.csproj +++ b/src/libraries/System.Threading.Thread/tests/MTAMain/MTAMain.csproj @@ -1,12 +1,13 @@ + + $(NetCoreAppCurrent) Exe - - .exe true - $(NetCoreAppCurrent) + + \ No newline at end of file diff --git a/src/libraries/System.Threading.Thread/tests/STAMain/STAMain.csproj b/src/libraries/System.Threading.Thread/tests/STAMain/STAMain.csproj index 5db12bc94a9223..8a1e90f111cb35 100644 --- a/src/libraries/System.Threading.Thread/tests/STAMain/STAMain.csproj +++ b/src/libraries/System.Threading.Thread/tests/STAMain/STAMain.csproj @@ -1,12 +1,13 @@ + + $(NetCoreAppCurrent) Exe - - .exe true - $(NetCoreAppCurrent) + + \ No newline at end of file diff --git a/src/libraries/System.Threading.Thread/tests/ThreadTests.cs b/src/libraries/System.Threading.Thread/tests/ThreadTests.cs index faad4bebd6af19..908d690e7e207d 100644 --- a/src/libraries/System.Threading.Thread/tests/ThreadTests.cs +++ b/src/libraries/System.Threading.Thread/tests/ThreadTests.cs @@ -159,14 +159,14 @@ public static IEnumerable ApartmentStateTest_MemberData() } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotMobile), nameof(PlatformDetection.HasHostExecutable))] - [InlineData("STAMain.exe", "GetApartmentStateTest")] - [InlineData("STAMain.exe", "SetApartmentStateTest")] - [InlineData("STAMain.exe", "WaitAllNotSupportedOnSta_Test0")] - [InlineData("STAMain.exe", "WaitAllNotSupportedOnSta_Test1")] - [InlineData("MTAMain.exe", "GetApartmentStateTest")] - [InlineData("MTAMain.exe", "SetApartmentStateTest")] - [InlineData("DefaultApartmentStateMain.exe", "GetApartmentStateTest")] - [InlineData("DefaultApartmentStateMain.exe", "SetApartmentStateTest")] + [InlineData("STAMain.dll", "GetApartmentStateTest")] + [InlineData("STAMain.dll", "SetApartmentStateTest")] + [InlineData("STAMain.dll", "WaitAllNotSupportedOnSta_Test0")] + [InlineData("STAMain.dll", "WaitAllNotSupportedOnSta_Test1")] + [InlineData("MTAMain.dll", "GetApartmentStateTest")] + [InlineData("MTAMain.dll", "SetApartmentStateTest")] + [InlineData("DefaultApartmentStateMain.dll", "GetApartmentStateTest")] + [InlineData("DefaultApartmentStateMain.dll", "SetApartmentStateTest")] [ActiveIssue("https://github.com/dotnet/runtime/issues/34543", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [ActiveIssue("https://github.com/dotnet/runtime/issues/86722", typeof(PlatformDetection), nameof(PlatformDetection.IsReadyToRunCompiled))] public static void ApartmentState_AttributePresent(string appName, string testName) diff --git a/src/libraries/System.Threading/ref/System.Threading.cs b/src/libraries/System.Threading/ref/System.Threading.cs index ed4d52aa5d8fa9..18436238c58a52 100644 --- a/src/libraries/System.Threading/ref/System.Threading.cs +++ b/src/libraries/System.Threading/ref/System.Threading.cs @@ -212,13 +212,19 @@ public partial class EventWaitHandle : System.Threading.WaitHandle { public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode) { } public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode, string? name) { } + public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode, string? name, System.Threading.NamedWaitHandleOptions options) { } public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode, string? name, out bool createdNew) { throw null; } + public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode, string? name, System.Threading.NamedWaitHandleOptions options, out bool createdNew) { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static System.Threading.EventWaitHandle OpenExisting(string name) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Threading.EventWaitHandle OpenExisting(string name, System.Threading.NamedWaitHandleOptions options) { throw null; } public bool Reset() { throw null; } public bool Set() { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static bool TryOpenExisting(string name, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Threading.EventWaitHandle? result) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static bool TryOpenExisting(string name, System.Threading.NamedWaitHandleOptions options, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Threading.EventWaitHandle? result) { throw null; } } public sealed partial class ExecutionContext : System.IDisposable, System.Runtime.Serialization.ISerializable { @@ -418,11 +424,21 @@ public sealed partial class Mutex : System.Threading.WaitHandle { public Mutex() { } public Mutex(bool initiallyOwned) { } + public Mutex(string? name, System.Threading.NamedWaitHandleOptions options) { throw null; } public Mutex(bool initiallyOwned, string? name) { } + public Mutex(bool initiallyOwned, string? name, System.Threading.NamedWaitHandleOptions options) { throw null; } public Mutex(bool initiallyOwned, string? name, out bool createdNew) { throw null; } + public Mutex(bool initiallyOwned, string? name, System.Threading.NamedWaitHandleOptions options, out bool createdNew) { throw null; } public static System.Threading.Mutex OpenExisting(string name) { throw null; } + public static System.Threading.Mutex OpenExisting(string name, System.Threading.NamedWaitHandleOptions options) { throw null; } public void ReleaseMutex() { } public static bool TryOpenExisting(string name, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Threading.Mutex? result) { throw null; } + public static bool TryOpenExisting(string name, System.Threading.NamedWaitHandleOptions options, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out Mutex? result) { throw null; } + } + public struct NamedWaitHandleOptions + { + public bool CurrentUserOnly { get { throw null; } set { } } + public bool CurrentSessionOnly { get { throw null; } set { } } } public partial class ReaderWriterLockSlim : System.IDisposable { @@ -457,13 +473,19 @@ public sealed partial class Semaphore : System.Threading.WaitHandle { public Semaphore(int initialCount, int maximumCount) { } public Semaphore(int initialCount, int maximumCount, string? name) { } + public Semaphore(int initialCount, int maximumCount, string? name, System.Threading.NamedWaitHandleOptions options) { } public Semaphore(int initialCount, int maximumCount, string? name, out bool createdNew) { throw null; } + public Semaphore(int initialCount, int maximumCount, string? name, System.Threading.NamedWaitHandleOptions options, out bool createdNew) { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static System.Threading.Semaphore OpenExisting(string name) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static System.Threading.Semaphore OpenExisting(string name, System.Threading.NamedWaitHandleOptions options) { throw null; } public int Release() { throw null; } public int Release(int releaseCount) { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static bool TryOpenExisting(string name, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Threading.Semaphore? result) { throw null; } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + public static bool TryOpenExisting(string name, System.Threading.NamedWaitHandleOptions options, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Threading.Semaphore? result) { throw null; } } public partial class SemaphoreFullException : System.SystemException { diff --git a/src/libraries/System.Threading/tests/EventWaitHandleTests.cs b/src/libraries/System.Threading/tests/EventWaitHandleTests.cs index 0d75df65177ec2..33c7cd32e9cd8b 100644 --- a/src/libraries/System.Threading/tests/EventWaitHandleTests.cs +++ b/src/libraries/System.Threading/tests/EventWaitHandleTests.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.Security; using Microsoft.DotNet.RemoteExecutor; using Xunit; @@ -32,7 +34,7 @@ public void Ctor_InvalidMode() public void Ctor_ValidNames(string name) { bool createdNew; - using (var ewh = new EventWaitHandle(true, EventResetMode.AutoReset, name, out createdNew)) + using (var ewh = new EventWaitHandle(true, EventResetMode.AutoReset, name, options: default, out createdNew)) { Assert.True(createdNew); } @@ -43,8 +45,9 @@ public void Ctor_ValidNames(string name) public void Ctor_NamesArentSupported_Unix() { Assert.Throws(() => new EventWaitHandle(false, EventResetMode.AutoReset, "anything")); - bool createdNew; - Assert.Throws(() => new EventWaitHandle(false, EventResetMode.AutoReset, "anything", out createdNew)); + Assert.Throws(() => new EventWaitHandle(false, EventResetMode.AutoReset, "anything", options: default)); + Assert.Throws(() => new EventWaitHandle(false, EventResetMode.AutoReset, "anything", out _)); + Assert.Throws(() => new EventWaitHandle(false, EventResetMode.AutoReset, "anything", options: default, out _)); } [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix @@ -57,25 +60,31 @@ public void Ctor_StateModeNameCreatedNew_Windows(bool initialState, EventResetMo { string name = Guid.NewGuid().ToString("N"); bool createdNew; - using (var ewh = new EventWaitHandle(initialState, mode, name, out createdNew)) + using (var ewh = new EventWaitHandle(initialState, mode, name, options: default, out createdNew)) { Assert.True(createdNew); - using (new EventWaitHandle(initialState, mode, name, out createdNew)) + using (new EventWaitHandle(initialState, mode, name, options: default, out createdNew)) { Assert.False(createdNew); } } } - [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix [Theory] - [InlineData(EventResetMode.AutoReset)] - [InlineData(EventResetMode.ManualReset)] - public void Ctor_NameUsedByOtherSynchronizationPrimitive_Windows(EventResetMode mode) + [MemberData(nameof(MutexTests.NameOptionCombinations_MemberData), MemberType = typeof(MutexTests))] + public void NameUsedByOtherSynchronizationPrimitive_Windows(bool currentUserOnly, bool currentSessionOnly) { string name = Guid.NewGuid().ToString("N"); - using (Mutex m = new Mutex(false, name)) - Assert.Throws(() => new EventWaitHandle(false, mode, name)); + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + using (Mutex m = new Mutex(name, options)) + { + Assert.Throws(() => new EventWaitHandle(false, EventResetMode.AutoReset, name, options)); + Assert.Throws(() => new EventWaitHandle(false, EventResetMode.ManualReset, name, options)); + Assert.Throws(() => EventWaitHandle.OpenExisting(name, options)); + Assert.False(EventWaitHandle.TryOpenExisting(name, options, out _)); + } } [Fact] @@ -116,12 +125,12 @@ public void SetReset() public void OpenExisting_Windows(string name) { EventWaitHandle resultHandle; - Assert.False(EventWaitHandle.TryOpenExisting(name, out resultHandle)); + Assert.False(EventWaitHandle.TryOpenExisting(name, options: default, out resultHandle)); Assert.Null(resultHandle); - using (EventWaitHandle are1 = new EventWaitHandle(false, EventResetMode.AutoReset, name)) + using (EventWaitHandle are1 = new EventWaitHandle(false, EventResetMode.AutoReset, name, options: default)) { - using (EventWaitHandle are2 = EventWaitHandle.OpenExisting(name)) + using (EventWaitHandle are2 = EventWaitHandle.OpenExisting(name, options: default)) { are1.Set(); Assert.True(are2.WaitOne(0)); @@ -134,7 +143,7 @@ public void OpenExisting_Windows(string name) Assert.False(are1.WaitOne(0)); } - Assert.True(EventWaitHandle.TryOpenExisting(name, out resultHandle)); + Assert.True(EventWaitHandle.TryOpenExisting(name, options: default, out resultHandle)); Assert.NotNull(resultHandle); resultHandle.Dispose(); } @@ -145,8 +154,9 @@ public void OpenExisting_Windows(string name) public void OpenExisting_NotSupported_Unix() { Assert.Throws(() => EventWaitHandle.OpenExisting("anything")); - EventWaitHandle ewh; - Assert.Throws(() => EventWaitHandle.TryOpenExisting("anything", out ewh)); + Assert.Throws(() => EventWaitHandle.OpenExisting("anything", options: default)); + Assert.Throws(() => EventWaitHandle.TryOpenExisting("anything", out _)); + Assert.Throws(() => EventWaitHandle.TryOpenExisting("anything", options: default, out _)); } [PlatformSpecific(TestPlatforms.Windows)] // OpenExisting not supported on Unix @@ -154,7 +164,9 @@ public void OpenExisting_NotSupported_Unix() public void OpenExisting_InvalidNames_Windows() { AssertExtensions.Throws("name", () => EventWaitHandle.OpenExisting(null)); + AssertExtensions.Throws("name", () => EventWaitHandle.OpenExisting(null, options: default)); AssertExtensions.Throws("name", null, () => EventWaitHandle.OpenExisting(string.Empty)); + AssertExtensions.Throws("name", null, () => EventWaitHandle.OpenExisting(string.Empty, options: default)); } [PlatformSpecific(TestPlatforms.Windows)] // OpenExisting not supported on Unix @@ -162,44 +174,173 @@ public void OpenExisting_InvalidNames_Windows() public void OpenExisting_UnavailableName_Windows() { string name = Guid.NewGuid().ToString("N"); - Assert.Throws(() => EventWaitHandle.OpenExisting(name)); + Assert.Throws(() => EventWaitHandle.OpenExisting(name, options: default)); EventWaitHandle e; - Assert.False(EventWaitHandle.TryOpenExisting(name, out e)); + Assert.False(EventWaitHandle.TryOpenExisting(name, options: default, out e)); Assert.Null(e); - using (e = new EventWaitHandle(false, EventResetMode.AutoReset, name)) { } - Assert.Throws(() => EventWaitHandle.OpenExisting(name)); - Assert.False(EventWaitHandle.TryOpenExisting(name, out e)); + using (e = new EventWaitHandle(false, EventResetMode.AutoReset, name, options: default)) { } + Assert.Throws(() => EventWaitHandle.OpenExisting(name, options: default)); + Assert.False(EventWaitHandle.TryOpenExisting(name, options: default, out e)); Assert.Null(e); } - [PlatformSpecific(TestPlatforms.Windows)] // OpenExisting not supported on Unix - [Fact] - public void OpenExisting_NameUsedByOtherSynchronizationPrimitive_Windows() + [Theory] + [MemberData(nameof(MutexTests.NamePrefixes_MemberData), MemberType = typeof(MutexTests))] + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix + public void NameOptionsApiCompatibilityTest(string namePrefix) { string name = Guid.NewGuid().ToString("N"); - using (Mutex mtx = new Mutex(true, name)) + string prefixedName = namePrefix + name; + bool currentSessionOnly = namePrefix != @"Global\"; + + using (var e = + new EventWaitHandle(initialState: false, EventResetMode.AutoReset, prefixedName, out bool createdNew)) { - Assert.Throws(() => EventWaitHandle.OpenExisting(name)); - EventWaitHandle ignored; - Assert.False(EventWaitHandle.TryOpenExisting(name, out ignored)); + Assert.True(createdNew); + + new EventWaitHandle( + initialState: false, + EventResetMode.AutoReset, + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out createdNew).Dispose(); + Assert.False(createdNew); + + EventWaitHandle.OpenExisting( + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }).Dispose(); + + Assert.True( + EventWaitHandle.TryOpenExisting( + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out EventWaitHandle e2)); + e2.Dispose(); + } + + using (var e = + new EventWaitHandle( + initialState: false, + EventResetMode.AutoReset, + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out bool createdNew)) + { + Assert.True(createdNew); + + new EventWaitHandle(initialState: false, EventResetMode.AutoReset, prefixedName, out createdNew).Dispose(); + Assert.False(createdNew); + + EventWaitHandle.OpenExisting(prefixedName).Dispose(); + + Assert.True(EventWaitHandle.TryOpenExisting(prefixedName, out EventWaitHandle e2)); + e2.Dispose(); + } + } + + [Theory] + [MemberData(nameof(MutexTests.NamePrefixAndOptionsCompatibilityTest_MemberData), MemberType = typeof(MutexTests))] + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix + public void NamePrefixAndOptionsCompatibilityTest(bool currentUserOnly, bool currentSessionOnly, string namePrefix) + { + string name = namePrefix + Guid.NewGuid().ToString("N"); + bool currentSessionOnlyBasedOnPrefix = namePrefix != @"Global\"; + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + + if (string.IsNullOrEmpty(namePrefix) || currentSessionOnlyBasedOnPrefix == currentSessionOnly) + { + new EventWaitHandle(initialState: false, EventResetMode.AutoReset, name, options).Dispose(); + } + else + { + AssertExtensions.Throws("name", + () => new EventWaitHandle(initialState: false, EventResetMode.AutoReset, name, options)); + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore))] // Windows Nano Server and Server Core apparently use the same namespace for the Local\ and Global\ prefixes + [MemberData(nameof(MutexTests.NameNamespaceTests_MemberData), MemberType = typeof(MutexTests))] + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix + public void NameNamespaceTest( + bool create_currentUserOnly, + bool create_currentSessionOnly, + bool open_currentUserOnly, + bool open_currentSessionOnly) + { + string name = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions createOptions = + new() { CurrentUserOnly = create_currentUserOnly, CurrentSessionOnly = create_currentSessionOnly }; + NamedWaitHandleOptions openOptions = + new() { CurrentUserOnly = open_currentUserOnly, CurrentSessionOnly = open_currentSessionOnly }; + + using (var e = new EventWaitHandle(initialState: false, EventResetMode.AutoReset, name, createOptions)) + { + if (PlatformDetection.IsWindows && + openOptions.CurrentSessionOnly == createOptions.CurrentSessionOnly && + !createOptions.CurrentUserOnly && + openOptions.CurrentUserOnly) + { + Assert.Throws( + () => new EventWaitHandle(initialState: false, EventResetMode.AutoReset, name, openOptions)); + Assert.Throws(() => EventWaitHandle.OpenExisting(name, openOptions)); + Assert.False(EventWaitHandle.TryOpenExisting(name, openOptions, out _)); + return; + } + + bool sameOptions = + openOptions.CurrentUserOnly == createOptions.CurrentUserOnly && + openOptions.CurrentSessionOnly == createOptions.CurrentSessionOnly; + bool expectedCreatedNew = + !sameOptions && + (!PlatformDetection.IsWindows || openOptions.CurrentSessionOnly != createOptions.CurrentSessionOnly); + + new EventWaitHandle( + initialState: false, + EventResetMode.AutoReset, + name, + openOptions, + out bool createdNew).Dispose(); + Assert.Equal(expectedCreatedNew, createdNew); + + if (expectedCreatedNew) + { + Assert.Throws(() => EventWaitHandle.OpenExisting(name, openOptions)); + } + else + { + EventWaitHandle.OpenExisting(name, openOptions).Dispose(); + } + + Assert.Equal(!expectedCreatedNew, EventWaitHandle.TryOpenExisting(name, openOptions, out EventWaitHandle e2)); + e2?.Dispose(); } } [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [InlineData(EventResetMode.ManualReset)] - [InlineData(EventResetMode.AutoReset)] - public void PingPong(EventResetMode mode) + [MemberData(nameof(NameOptionsAndEventResetModeCombinations_MemberData))] + public void PingPong(bool currentUserOnly, bool currentSessionOnly, EventResetMode mode) { // Create names for the two events string outboundName = Guid.NewGuid().ToString("N"); string inboundName = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + // Create the two events and the other process with which to synchronize - using (var inbound = new EventWaitHandle(true, mode, inboundName)) - using (var outbound = new EventWaitHandle(false, mode, outboundName)) - using (var remote = RemoteExecutor.Invoke(PingPong_OtherProcess, mode.ToString(), outboundName, inboundName)) + using (var inbound = new EventWaitHandle(true, mode, inboundName, options)) + using (var outbound = new EventWaitHandle(false, mode, outboundName, options)) + using (var remote = + RemoteExecutor.Invoke( + PingPong_OtherProcess, + mode.ToString(), + outboundName, + inboundName, + options.CurrentUserOnly ? "1" : "0", + options.CurrentSessionOnly ? "1" : "0")) { // Repeatedly wait for one event and then set the other for (int i = 0; i < 10; i++) @@ -214,13 +355,24 @@ public void PingPong(EventResetMode mode) } } - private static void PingPong_OtherProcess(string modeName, string inboundName, string outboundName) + private static void PingPong_OtherProcess( + string modeName, + string inboundName, + string outboundName, + string currentUserOnlyStr, + string currentSessionOnlyStr) { EventResetMode mode = (EventResetMode)Enum.Parse(typeof(EventResetMode), modeName); + NamedWaitHandleOptions options = + new() + { + CurrentUserOnly = int.Parse(currentUserOnlyStr) != 0, + CurrentSessionOnly = int.Parse(currentSessionOnlyStr) != 0 + }; // Open the two events - using (var inbound = EventWaitHandle.OpenExisting(inboundName)) - using (var outbound = EventWaitHandle.OpenExisting(outboundName)) + using (var inbound = EventWaitHandle.OpenExisting(inboundName, options)) + using (var outbound = EventWaitHandle.OpenExisting(outboundName, options)) { // Repeatedly wait for one event and then set the other for (int i = 0; i < 10; i++) @@ -242,5 +394,16 @@ public static TheoryData GetValidNames() return names; } + + public static IEnumerable NameOptionsAndEventResetModeCombinations_MemberData() + { + foreach (NamedWaitHandleOptions options in MutexTests.GetNameOptionCombinations()) + { + foreach (EventResetMode mode in Enum.GetValues()) + { + yield return new object[] { options.CurrentUserOnly, options.CurrentSessionOnly, mode }; + } + } + } } } diff --git a/src/libraries/System.Threading/tests/MutexTests.cs b/src/libraries/System.Threading/tests/MutexTests.cs index 6d769c4297fae5..b83cfd571fa203 100644 --- a/src/libraries/System.Threading/tests/MutexTests.cs +++ b/src/libraries/System.Threading/tests/MutexTests.cs @@ -231,7 +231,7 @@ public void MutualExclusionTest() [PlatformSpecific(TestPlatforms.AnyUnix)] public void Ctor_InvalidNames_Unix() { - AssertExtensions.Throws("name", null, () => new Mutex(false, new string('a', 1000), out bool createdNew)); + AssertExtensions.Throws("name", null, () => new Mutex(new string('a', 1000), options: default)); } [Theory] @@ -239,10 +239,10 @@ public void Ctor_InvalidNames_Unix() public void Ctor_ValidName(string name) { bool createdNew; - using (Mutex m1 = new Mutex(false, name, out createdNew)) + using (Mutex m1 = new Mutex(false, name, options: default, out createdNew)) { Assert.True(createdNew); - using (Mutex m2 = new Mutex(false, name, out createdNew)) + using (Mutex m2 = new Mutex(false, name, options: default, out createdNew)) { Assert.False(createdNew); } @@ -250,39 +250,69 @@ public void Ctor_ValidName(string name) } [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix - [Fact] - public void Ctor_NameUsedByOtherSynchronizationPrimitive_Windows() + [Theory] + [MemberData(nameof(NameOptionCombinations_MemberData))] + public void NameUsedByOtherSynchronizationPrimitive_Windows(bool currentUserOnly, bool currentSessionOnly) { string name = Guid.NewGuid().ToString("N"); - using (Semaphore s = new Semaphore(1, 1, name)) + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + using (Semaphore s = new Semaphore(1, 1, name, options)) { - Assert.Throws(() => new Mutex(false, name)); + Assert.Throws(() => new Mutex(name, options)); + Assert.Throws(() => Mutex.OpenExisting(name, options)); + Assert.False(Mutex.TryOpenExisting(name, options, out _)); } } [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInAppContainer))] // Can't create global objects in appcontainer - public void Ctor_ImpersonateAnonymousAndTryCreateGlobalMutexTest() + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInAppContainer))] // Can't create global objects in appcontainer + [MemberData(nameof(NameOptionCombinations_MemberData))] + public void Ctor_ImpersonateAnonymousAndTryCreateGlobalMutexTest(bool currentUserOnly, bool currentSessionOnly) { ThreadTestHelpers.RunTestInBackgroundThread(() => { + string initiallyCreatedName = Guid.NewGuid().ToString("N"); + string name = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + + using var m = new Mutex(initiallyCreatedName, options); + if (!ImpersonateAnonymousToken(GetCurrentThread())) { // Impersonation is not allowed in the current context, this test is inappropriate in such a case return; } - Assert.Throws(() => new Mutex(false, $"Global\\{Guid.NewGuid():N}")); - Assert.True(RevertToSelf()); + bool reverted; + try + { + Assert.Throws(() => new Mutex(name, options)); + Assert.Throws(() => new Mutex(initiallyCreatedName, options)); + Assert.Throws(() => new Mutex(initiallyCreatedName, options)); + Assert.Throws(() => Mutex.OpenExisting(initiallyCreatedName, options)); + Assert.Throws( + () => Mutex.TryOpenExisting(initiallyCreatedName, options, out _)); + } + finally + { + reverted = RevertToSelf(); + } + + Assert.True(reverted); }); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsInAppContainer))] // Can't create global objects in appcontainer + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsInAppContainer))] // Can't create global objects in appcontainer + [MemberData(nameof(NameOptionCombinations_MemberData))] [PlatformSpecific(TestPlatforms.Windows)] - public void Ctor_TryCreateGlobalMutexTest_Uwp() + public void Ctor_TryCreateGlobalMutexTest_Uwp(bool currentUserOnly, bool currentSessionOnly) { + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; ThreadTestHelpers.RunTestInBackgroundThread(() => - Assert.Throws(() => new Mutex(false, $"Global\\{Guid.NewGuid():N}"))); + Assert.Throws(() => new Mutex(Guid.NewGuid().ToString("N"), options))); } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] @@ -290,11 +320,11 @@ public void Ctor_TryCreateGlobalMutexTest_Uwp() public void OpenExisting(string name) { Mutex resultHandle; - Assert.False(Mutex.TryOpenExisting(name, out resultHandle)); + Assert.False(Mutex.TryOpenExisting(name, options: default, out resultHandle)); - using (Mutex m1 = new Mutex(false, name)) + using (Mutex m1 = new Mutex(name, options: default)) { - using (Mutex m2 = Mutex.OpenExisting(name)) + using (Mutex m2 = Mutex.OpenExisting(name, options: default)) { m1.CheckedWait(); Assert.False(Task.Factory.StartNew(() => m2.WaitOne(0), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Result); @@ -305,7 +335,7 @@ public void OpenExisting(string name) m2.ReleaseMutex(); } - Assert.True(Mutex.TryOpenExisting(name, out resultHandle)); + Assert.True(Mutex.TryOpenExisting(name, options: default, out resultHandle)); Assert.NotNull(resultHandle); resultHandle.Dispose(); } @@ -315,50 +345,186 @@ public void OpenExisting(string name) [ActiveIssue("https://github.com/mono/mono/issues/15158", TestRuntimes.Mono)] public void OpenExisting_InvalidNames() { - AssertExtensions.Throws("name", () => Mutex.OpenExisting(null)); - AssertExtensions.Throws("name", null, () => Mutex.OpenExisting(string.Empty)); + AssertExtensions.Throws("name", () => Mutex.OpenExisting(null, options: default)); + AssertExtensions.Throws("name", null, () => Mutex.OpenExisting(string.Empty, options: default)); } [Fact] public void OpenExisting_UnavailableName() { string name = Guid.NewGuid().ToString("N"); - Assert.Throws(() => Mutex.OpenExisting(name)); + Assert.Throws(() => Mutex.OpenExisting(name, options: default)); Mutex m; - Assert.False(Mutex.TryOpenExisting(name, out m)); + Assert.False(Mutex.TryOpenExisting(name, options: default, out m)); Assert.Null(m); - using (m = new Mutex(false, name)) { } - Assert.Throws(() => Mutex.OpenExisting(name)); - Assert.False(Mutex.TryOpenExisting(name, out m)); + using (m = new Mutex(name, options: default)) { } + Assert.Throws(() => Mutex.OpenExisting(name, options: default)); + Assert.False(Mutex.TryOpenExisting(name, options: default, out m)); Assert.Null(m); } - [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix + public enum WaitHandleWaitType + { + WaitOne, + WaitAny, + WaitAll + } + [Fact] - public void OpenExisting_NameUsedByOtherSynchronizationPrimitive_Windows() + public void NamedWaitHandleOptionsTest() + { + NamedWaitHandleOptions options = default; + Assert.True(options.CurrentUserOnly); + Assert.True(options.CurrentSessionOnly); + + options.CurrentUserOnly = false; + Assert.False(options.CurrentUserOnly); + options.CurrentSessionOnly = false; + Assert.False(options.CurrentSessionOnly); + } + + [Theory] + [MemberData(nameof(NamePrefixes_MemberData))] + public void NameOptionsApiCompatibilityTest(string namePrefix) { string name = Guid.NewGuid().ToString("N"); - using (Semaphore sema = new Semaphore(1, 1, name)) + string prefixedName = namePrefix + name; + bool currentSessionOnly = namePrefix != @"Global\"; + + using (var m = new Mutex(initiallyOwned: false, prefixedName, out bool createdNew)) { - Assert.Throws(() => Mutex.OpenExisting(name)); - Mutex ignored; - Assert.False(Mutex.TryOpenExisting(name, out ignored)); + Assert.True(createdNew); + + new Mutex( + initiallyOwned: false, + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out createdNew).Dispose(); + Assert.False(createdNew); + + Mutex.OpenExisting( + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }).Dispose(); + + Assert.True( + Mutex.TryOpenExisting( + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out Mutex m2)); + m2.Dispose(); + } + + using (var m = + new Mutex( + initiallyOwned: false, + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out bool createdNew)) + { + Assert.True(createdNew); + + new Mutex(initiallyOwned: false, prefixedName, out createdNew).Dispose(); + Assert.False(createdNew); + + Mutex.OpenExisting(prefixedName).Dispose(); + + Assert.True(Mutex.TryOpenExisting(prefixedName, out Mutex m2)); + m2.Dispose(); } } - public enum WaitHandleWaitType + public static IEnumerable NamePrefixAndOptionsCompatibilityTest_MemberData() { - WaitOne, - WaitAny, - WaitAll + foreach (NamedWaitHandleOptions options in GetNameOptionCombinations()) + { + foreach (string namePrefix in GetNamePrefixes()) + { + yield return new object[] { options.CurrentUserOnly, options.CurrentSessionOnly, namePrefix }; + } + } } - private static IEnumerable GetNamePrefixes() + [Theory] + [MemberData(nameof(NamePrefixAndOptionsCompatibilityTest_MemberData))] + public void NamePrefixAndOptionsCompatibilityTest(bool currentUserOnly, bool currentSessionOnly, string namePrefix) { - yield return string.Empty; - yield return "Local\\"; - yield return "Global\\"; + string name = namePrefix + Guid.NewGuid().ToString("N"); + bool currentSessionOnlyBasedOnPrefix = namePrefix != @"Global\"; + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + + if (string.IsNullOrEmpty(namePrefix) || currentSessionOnlyBasedOnPrefix == currentSessionOnly) + { + new Mutex(name, options).Dispose(); + } + else + { + AssertExtensions.Throws("name", () => new Mutex(name, options)); + } + } + + public static IEnumerable NameNamespaceTests_MemberData() + { + foreach (NamedWaitHandleOptions o in GetNameOptionCombinations()) + { + foreach (NamedWaitHandleOptions o2 in GetNameOptionCombinations()) + { + yield return + new object[] { o.CurrentUserOnly, o.CurrentSessionOnly, o2.CurrentUserOnly, o2.CurrentSessionOnly }; + } + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore))] // Windows Nano Server and Server Core apparently use the same namespace for the Local\ and Global\ prefixes + [MemberData(nameof(NameNamespaceTests_MemberData))] + public void NameNamespaceTest( + bool create_currentUserOnly, + bool create_currentSessionOnly, + bool open_currentUserOnly, + bool open_currentSessionOnly) + { + string name = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions createOptions = + new() { CurrentUserOnly = create_currentUserOnly, CurrentSessionOnly = create_currentSessionOnly }; + NamedWaitHandleOptions openOptions = + new() { CurrentUserOnly = open_currentUserOnly, CurrentSessionOnly = open_currentSessionOnly }; + + using (var m = new Mutex(name, createOptions)) + { + if (PlatformDetection.IsWindows && + openOptions.CurrentSessionOnly == createOptions.CurrentSessionOnly && + !createOptions.CurrentUserOnly && + openOptions.CurrentUserOnly) + { + Assert.Throws(() => new Mutex(name, openOptions)); + Assert.Throws(() => Mutex.OpenExisting(name, openOptions)); + Assert.False(Mutex.TryOpenExisting(name, openOptions, out _)); + return; + } + + bool sameOptions = + openOptions.CurrentUserOnly == createOptions.CurrentUserOnly && + openOptions.CurrentSessionOnly == createOptions.CurrentSessionOnly; + bool expectedCreatedNew = + !sameOptions && + (!PlatformDetection.IsWindows || openOptions.CurrentSessionOnly != createOptions.CurrentSessionOnly); + + new Mutex(initiallyOwned: false, name, openOptions, out bool createdNew).Dispose(); + Assert.Equal(expectedCreatedNew, createdNew); + + if (expectedCreatedNew) + { + Assert.Throws(() => Mutex.OpenExisting(name, openOptions)); + } + else + { + Mutex.OpenExisting(name, openOptions).Dispose(); + } + + Assert.Equal(!expectedCreatedNew, Mutex.TryOpenExisting(name, openOptions, out Mutex m2)); + m2?.Dispose(); + } } public static IEnumerable AbandonExisting_MemberData() @@ -385,7 +551,9 @@ public static IEnumerable AbandonExisting_MemberData() waitCount, notAbandonedWaitIndex, false, // isNotAbandonedWaitObjectSignaled - abandonDuringWait + abandonDuringWait, + true, // currentUserOnly + true // currentSessionOnly }; bool includeArgsForSignaledNotAbandonedWaitObject = @@ -401,10 +569,12 @@ public static IEnumerable AbandonExisting_MemberData() if (waitCount == 1 || PlatformDetection.IsWindows) { - foreach (var namePrefix in GetNamePrefixes()) + foreach (NamedWaitHandleOptions options in GetNameOptionCombinations()) { var newArgs = (object[])args.Clone(); - newArgs[0] = namePrefix + nameGuidStr; + newArgs[0] = nameGuidStr; + newArgs[6] = options.CurrentUserOnly; + newArgs[7] = options.CurrentSessionOnly; yield return newArgs; if (includeArgsForSignaledNotAbandonedWaitObject) { @@ -428,12 +598,17 @@ public void AbandonExisting( int waitCount, int notAbandonedWaitIndex, bool isNotAbandonedWaitObjectSignaled, - bool abandonDuringWait) + bool abandonDuringWait, + bool currentUserOnly, + bool currentSessionOnly) { ThreadTestHelpers.RunTestInBackgroundThread(() => { - using (var m = new Mutex(false, name)) - using (Mutex m2 = waitCount == 1 ? null : new Mutex(false, name == null ? null : name + "_2")) + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + + using (var m = new Mutex(name, options)) + using (Mutex m2 = waitCount == 1 ? null : new Mutex(name == null ? null : name + "_2", options)) using (ManualResetEvent e = waitCount == 1 ? null : new ManualResetEvent(isNotAbandonedWaitObjectSignaled)) using (ManualResetEvent threadReadyForAbandon = abandonDuringWait ? new ManualResetEvent(false) : null) using (ManualResetEvent abandonSoon = abandonDuringWait ? new ManualResetEvent(false) : null) @@ -587,41 +762,49 @@ public void AbandonExisting( }); } - public static IEnumerable CrossProcess_NamedMutex_ProtectedFileAccessAtomic_MemberData() - { - foreach (var namePrefix in GetNamePrefixes()) - { - yield return new object[] { namePrefix }; - } - } - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36307", TestRuntimes.Mono)] - [MemberData(nameof(CrossProcess_NamedMutex_ProtectedFileAccessAtomic_MemberData))] - public void CrossProcess_NamedMutex_ProtectedFileAccessAtomic(string prefix) + [MemberData(nameof(NameOptionCombinations_MemberData))] + public void CrossProcess_NamedMutex_ProtectedFileAccessAtomic(bool currentUserOnly, bool currentSessionOnly) { string fileName = GetTestFilePath(); try { ThreadTestHelpers.RunTestInBackgroundThread(() => { - string mutexName = prefix + Guid.NewGuid().ToString("N"); + string mutexName = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; - Action otherProcess = (m, f) => - { - using (var mutex = Mutex.OpenExisting(m)) + Action otherProcess = + (mutexName, fileName, currentUserOnlyStr, currentSessionOnlyStr) => { - mutex.CheckedWait(); - try - { File.WriteAllText(f, "0"); } - finally { mutex.ReleaseMutex(); } + NamedWaitHandleOptions options = + new() + { + CurrentUserOnly = int.Parse(currentUserOnlyStr) != 0, + CurrentSessionOnly = int.Parse(currentSessionOnlyStr) != 0 + }; - IncrementValueInFileNTimes(mutex, f, 10); - } - }; + using (var mutex = Mutex.OpenExisting(mutexName, options)) + { + mutex.CheckedWait(); + try + { File.WriteAllText(fileName, "0"); } + finally { mutex.ReleaseMutex(); } - using (var mutex = new Mutex(false, mutexName)) - using (var remote = RemoteExecutor.Invoke(otherProcess, mutexName, fileName)) + IncrementValueInFileNTimes(mutex, fileName, 10); + } + }; + + using (var mutex = new Mutex(mutexName, options)) + using (var remote = + RemoteExecutor.Invoke( + otherProcess, + mutexName, + fileName, + options.CurrentUserOnly ? "1" : "0", + options.CurrentSessionOnly ? "1" : "0")) { SpinWait.SpinUntil( () => @@ -665,10 +848,11 @@ private static void IncrementValueInFileNTimes(Mutex mutex, string fileName, int public void NamedMutex_ThreadExitDisposeRaceTest() { var mutexName = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions options = new() { CurrentUserOnly = false, CurrentSessionOnly = true }; for (int i = 0; i < 1000; ++i) { - var m = new Mutex(false, mutexName); + var m = new Mutex(mutexName, options); var startParallelTest = new ManualResetEvent(false); var t0Ready = new AutoResetEvent(false); @@ -683,7 +867,7 @@ public void NamedMutex_ThreadExitDisposeRaceTest() var t1Ready = new AutoResetEvent(false); Thread t1 = ThreadTestHelpers.CreateGuardedThread(out Action waitForT1, () => { - using (var m2 = Mutex.OpenExisting(mutexName)) + using (var m2 = Mutex.OpenExisting(mutexName, options)) { m.Dispose(); t1Ready.Set(); @@ -709,7 +893,7 @@ public void NamedMutex_ThreadExitDisposeRaceTest() // destroyed and created new again. SpinWait.SpinUntil(() => { - using (m = new Mutex(true, mutexName, out bool createdNew)) + using (m = new Mutex(true, mutexName, options, out bool createdNew)) { if (createdNew) { @@ -726,6 +910,7 @@ public void NamedMutex_DisposeWhenLockedRaceTest() { var mutexName = Guid.NewGuid().ToString("N"); var mutex2Name = mutexName + "_2"; + NamedWaitHandleOptions options = new() { CurrentUserOnly = false, CurrentSessionOnly = true }; var waitsForThread = new Action[Environment.ProcessorCount]; for (int i = 0; i < waitsForThread.Length; ++i) @@ -740,10 +925,10 @@ public void NamedMutex_DisposeWhenLockedRaceTest() // then release the last reference to the mutex. On some implementations T1 may not be able to destroy // the mutex when it is still locked by T0, or there may be potential for races in the sequence. This // test only looks for errors from race conditions. - using (var mutex = new Mutex(true, mutexName)) + using (var mutex = new Mutex(true, mutexName, options)) { } - using (var mutex = new Mutex(true, mutex2Name)) + using (var mutex = new Mutex(true, mutex2Name, options)) { } } @@ -768,6 +953,37 @@ public static TheoryData GetValidNames() return names; } + private static IEnumerable GetNamePrefixes() + { + yield return string.Empty; + yield return "Local\\"; + yield return "Global\\"; + } + + public static IEnumerable NamePrefixes_MemberData() + { + foreach (var namePrefix in GetNamePrefixes()) + { + yield return new object[] { namePrefix }; + } + } + + public static IEnumerable GetNameOptionCombinations() + { + yield return new NamedWaitHandleOptions() { CurrentUserOnly = false, CurrentSessionOnly = false }; + yield return new NamedWaitHandleOptions() { CurrentUserOnly = false, CurrentSessionOnly = true }; + yield return new NamedWaitHandleOptions() { CurrentUserOnly = true, CurrentSessionOnly = false }; + yield return new NamedWaitHandleOptions() { CurrentUserOnly = true, CurrentSessionOnly = true }; + } + + public static IEnumerable NameOptionCombinations_MemberData() + { + foreach (NamedWaitHandleOptions options in GetNameOptionCombinations()) + { + yield return new object[] { options.CurrentUserOnly, options.CurrentSessionOnly }; + } + } + [DllImport("kernel32.dll")] private static extern IntPtr GetCurrentThread(); diff --git a/src/libraries/System.Threading/tests/SemaphoreTests.cs b/src/libraries/System.Threading/tests/SemaphoreTests.cs index 200728cfb9406f..0be16cee5af633 100644 --- a/src/libraries/System.Threading/tests/SemaphoreTests.cs +++ b/src/libraries/System.Threading/tests/SemaphoreTests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Security; using System.Threading.Tasks; using Microsoft.DotNet.RemoteExecutor; using Xunit; @@ -190,12 +192,12 @@ public void Ctor_InitialAndMax(int initialCount, int maximumCount) [MemberData(nameof(GetValidNames))] public void Ctor_ValidName_Windows(string name) { - new Semaphore(0, 1, name).Dispose(); + new Semaphore(0, 1, name, options: default).Dispose(); bool createdNew; - using var s = new Semaphore(0, 1, name, out createdNew); + using var s = new Semaphore(0, 1, name, options: default, out createdNew); Assert.True(createdNew); - new Semaphore(0, 1, name, out createdNew).Dispose(); + new Semaphore(0, 1, name, options: default, out createdNew).Dispose(); Assert.False(createdNew); } @@ -204,15 +206,10 @@ public void Ctor_ValidName_Windows(string name) [Fact] public void Ctor_NamesArentSupported_Unix() { - string name = Guid.NewGuid().ToString("N"); - - Assert.Throws(() => new Semaphore(0, 1, name)); - - Assert.Throws(() => - { - bool createdNew; - new Semaphore(0, 1, name, out createdNew).Dispose(); - }); + Assert.Throws(() => new Semaphore(0, 1, "anything")); + Assert.Throws(() => new Semaphore(0, 1, "anything", options: default)); + Assert.Throws(() => new Semaphore(0, 1, "anything", out _)); + Assert.Throws(() => new Semaphore(0, 1, "anything", options: default, out _)); } [Fact] @@ -225,15 +222,15 @@ public void Ctor_InvalidArguments() AssertExtensions.Throws("maximumCount", () => new Semaphore(0, 0)); AssertExtensions.Throws(null, () => new Semaphore(2, 1)); - AssertExtensions.Throws("initialCount", () => new Semaphore(-1, 1, null)); - AssertExtensions.Throws("initialCount", () => new Semaphore(-2, 1, null)); - AssertExtensions.Throws("maximumCount", () => new Semaphore(0, 0, null)); + AssertExtensions.Throws("initialCount", () => new Semaphore(-1, 1, null, options: default)); + AssertExtensions.Throws("initialCount", () => new Semaphore(-2, 1, null, options: default)); + AssertExtensions.Throws("maximumCount", () => new Semaphore(0, 0, null, options: default)); AssertExtensions.Throws(null, () => new Semaphore(2, 1, null)); - AssertExtensions.Throws("initialCount", () => new Semaphore(-1, 1, "CtorSemaphoreTest", out createdNew)); - AssertExtensions.Throws("initialCount", () => new Semaphore(-2, 1, "CtorSemaphoreTest", out createdNew)); - AssertExtensions.Throws("maximumCount", () => new Semaphore(0, 0, "CtorSemaphoreTest", out createdNew)); - AssertExtensions.Throws(null, () => new Semaphore(2, 1, "CtorSemaphoreTest", out createdNew)); + AssertExtensions.Throws("initialCount", () => new Semaphore(-1, 1, "CtorSemaphoreTest", options: default, out createdNew)); + AssertExtensions.Throws("initialCount", () => new Semaphore(-2, 1, "CtorSemaphoreTest", options: default, out createdNew)); + AssertExtensions.Throws("maximumCount", () => new Semaphore(0, 0, "CtorSemaphoreTest", options: default, out createdNew)); + AssertExtensions.Throws(null, () => new Semaphore(2, 1, "CtorSemaphoreTest", options: default, out createdNew)); } [Fact] @@ -300,16 +297,19 @@ public void AnonymousProducerConsumer() } [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix - [Fact] - public void NamedProducerConsumer() + [Theory] + [MemberData(nameof(MutexTests.NameOptionCombinations_MemberData), MemberType = typeof(MutexTests))] + public void NamedProducerConsumer(bool currentUserOnly, bool currentSessionOnly) { string name = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; const int NumItems = 5; var b = new Barrier(2); Task.WaitAll( Task.Factory.StartNew(() => { - using (var s = new Semaphore(0, int.MaxValue, name)) + using (var s = new Semaphore(0, int.MaxValue, name, options)) { Assert.True(b.SignalAndWait(FailedWaitTimeout)); for (int i = 0; i < NumItems; i++) @@ -319,7 +319,7 @@ public void NamedProducerConsumer() }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default), Task.Factory.StartNew(() => { - using (var s = new Semaphore(0, int.MaxValue, name)) + using (var s = new Semaphore(0, int.MaxValue, name, options)) { Assert.True(b.SignalAndWait(FailedWaitTimeout)); for (int i = 0; i < NumItems; i++) @@ -333,11 +333,10 @@ public void NamedProducerConsumer() [Fact] public void OpenExisting_NotSupported_Unix() { - Assert.Throws(() => Semaphore.OpenExisting(null)); - Assert.Throws(() => Semaphore.OpenExisting(string.Empty)); Assert.Throws(() => Semaphore.OpenExisting("anything")); - Semaphore semaphore; - Assert.Throws(() => Semaphore.TryOpenExisting("anything", out semaphore)); + Assert.Throws(() => Semaphore.OpenExisting("anything", options: default)); + Assert.Throws(() => Semaphore.TryOpenExisting("anything", out _)); + Assert.Throws(() => Semaphore.TryOpenExisting("anything", options: default, out _)); } [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix @@ -345,7 +344,9 @@ public void OpenExisting_NotSupported_Unix() public void OpenExisting_InvalidNames_Windows() { AssertExtensions.Throws("name", () => Semaphore.OpenExisting(null)); + AssertExtensions.Throws("name", () => Semaphore.OpenExisting(null, options: default)); AssertExtensions.Throws("name", null, () => Semaphore.OpenExisting(string.Empty)); + AssertExtensions.Throws("name", null, () => Semaphore.OpenExisting(string.Empty, options: default)); } [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix @@ -353,27 +354,30 @@ public void OpenExisting_InvalidNames_Windows() public void OpenExisting_UnavailableName_Windows() { string name = Guid.NewGuid().ToString("N"); - Assert.Throws(() => Semaphore.OpenExisting(name)); + Assert.Throws(() => Semaphore.OpenExisting(name, options: default)); Semaphore s; - Assert.False(Semaphore.TryOpenExisting(name, out s)); + Assert.False(Semaphore.TryOpenExisting(name, options: default, out s)); Assert.Null(s); - using (s = new Semaphore(0, 1, name)) { } - Assert.Throws(() => Semaphore.OpenExisting(name)); - Assert.False(Semaphore.TryOpenExisting(name, out s)); + using (s = new Semaphore(0, 1, name, options: default)) { } + Assert.Throws(() => Semaphore.OpenExisting(name, options: default)); + Assert.False(Semaphore.TryOpenExisting(name, options: default, out s)); Assert.Null(s); } [PlatformSpecific(TestPlatforms.Windows)] // named semaphores aren't supported on Unix - [Fact] - public void OpenExisting_NameUsedByOtherSynchronizationPrimitive_Windows() + [Theory] + [MemberData(nameof(MutexTests.NameOptionCombinations_MemberData), MemberType = typeof(MutexTests))] + public void NameUsedByOtherSynchronizationPrimitive_Windows(bool currentUserOnly, bool currentSessionOnly) { string name = Guid.NewGuid().ToString("N"); - using (Mutex mtx = new Mutex(true, name)) + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + using (Mutex mtx = new Mutex(true, name, options)) { - Assert.Throws(() => Semaphore.OpenExisting(name)); - Semaphore ignored; - Assert.False(Semaphore.TryOpenExisting(name, out ignored)); + Assert.Throws(() => new Semaphore(initialCount: 1, maximumCount: 1, name, options)); + Assert.Throws(() => Semaphore.OpenExisting(name, options)); + Assert.False(Semaphore.TryOpenExisting(name, options, out _)); } } @@ -383,11 +387,11 @@ public void OpenExisting_NameUsedByOtherSynchronizationPrimitive_Windows() public void OpenExisting_SameAsOriginal_Windows(string name) { bool createdNew; - using (Semaphore s1 = new Semaphore(0, int.MaxValue, name, out createdNew)) + using (Semaphore s1 = new Semaphore(0, int.MaxValue, name, options: default, out createdNew)) { Assert.True(createdNew); - using (Semaphore s2 = Semaphore.OpenExisting(name)) + using (Semaphore s2 = Semaphore.OpenExisting(name, options: default)) { Assert.False(s1.WaitOne(0)); Assert.False(s2.WaitOne(0)); @@ -400,7 +404,7 @@ public void OpenExisting_SameAsOriginal_Windows(string name) } Semaphore s3; - Assert.True(Semaphore.TryOpenExisting(name, out s3)); + Assert.True(Semaphore.TryOpenExisting(name, options: default, out s3)); using (s3) { Assert.False(s1.WaitOne(0)); @@ -415,18 +419,155 @@ public void OpenExisting_SameAsOriginal_Windows(string name) } } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [Theory] + [MemberData(nameof(MutexTests.NamePrefixes_MemberData), MemberType = typeof(MutexTests))] + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix + public void NameOptionsApiCompatibilityTest(string namePrefix) + { + string name = Guid.NewGuid().ToString("N"); + string prefixedName = namePrefix + name; + bool currentSessionOnly = namePrefix != @"Global\"; + + using (var s = new Semaphore(initialCount: 1, maximumCount: 1, prefixedName, out bool createdNew)) + { + Assert.True(createdNew); + + new Semaphore( + initialCount: 1, + maximumCount: 1, + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out createdNew).Dispose(); + Assert.False(createdNew); + + Semaphore.OpenExisting( + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }).Dispose(); + + Assert.True( + Semaphore.TryOpenExisting( + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out Semaphore s2)); + s2.Dispose(); + } + + using (var s = + new Semaphore( + initialCount: 1, + maximumCount: 1, + name, + new() { CurrentUserOnly = false, CurrentSessionOnly = currentSessionOnly }, + out bool createdNew)) + { + Assert.True(createdNew); + + new Semaphore(initialCount: 1, maximumCount: 1, prefixedName, out createdNew).Dispose(); + Assert.False(createdNew); + + Semaphore.OpenExisting(prefixedName).Dispose(); + + Assert.True(Semaphore.TryOpenExisting(prefixedName, out Semaphore s2)); + s2.Dispose(); + } + } + + [Theory] + [MemberData(nameof(MutexTests.NamePrefixAndOptionsCompatibilityTest_MemberData), MemberType = typeof(MutexTests))] + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix + public void NamePrefixAndOptionsCompatibilityTest(bool currentUserOnly, bool currentSessionOnly, string namePrefix) + { + string name = namePrefix + Guid.NewGuid().ToString("N"); + bool currentSessionOnlyBasedOnPrefix = namePrefix != @"Global\"; + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + + if (string.IsNullOrEmpty(namePrefix) || currentSessionOnlyBasedOnPrefix == currentSessionOnly) + { + new Semaphore(initialCount: 1, maximumCount: 1, name, options).Dispose(); + } + else + { + AssertExtensions.Throws("name", + () => new Semaphore(initialCount: 1, maximumCount: 1, name, options)); + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore))] // Windows Nano Server and Server Core apparently use the same namespace for the Local\ and Global\ prefixes + [MemberData(nameof(MutexTests.NameNamespaceTests_MemberData), MemberType = typeof(MutexTests))] + [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix + public void NameNamespaceTest( + bool create_currentUserOnly, + bool create_currentSessionOnly, + bool open_currentUserOnly, + bool open_currentSessionOnly) + { + string name = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions createOptions = + new() { CurrentUserOnly = create_currentUserOnly, CurrentSessionOnly = create_currentSessionOnly }; + NamedWaitHandleOptions openOptions = + new() { CurrentUserOnly = open_currentUserOnly, CurrentSessionOnly = open_currentSessionOnly }; + + using (var s = new Semaphore(initialCount: 1, maximumCount: 1, name, createOptions)) + { + if (PlatformDetection.IsWindows && + openOptions.CurrentSessionOnly == createOptions.CurrentSessionOnly && + !createOptions.CurrentUserOnly && + openOptions.CurrentUserOnly) + { + Assert.Throws( + () => new Semaphore(initialCount: 1, maximumCount: 1, name, openOptions)); + Assert.Throws(() => Semaphore.OpenExisting(name, openOptions)); + Assert.False(Semaphore.TryOpenExisting(name, openOptions, out _)); + return; + } + + bool sameOptions = + openOptions.CurrentUserOnly == createOptions.CurrentUserOnly && + openOptions.CurrentSessionOnly == createOptions.CurrentSessionOnly; + bool expectedCreatedNew = + !sameOptions && + (!PlatformDetection.IsWindows || openOptions.CurrentSessionOnly != createOptions.CurrentSessionOnly); + + new Semaphore(initialCount: 1, maximumCount: 1, name, openOptions, out bool createdNew).Dispose(); + Assert.Equal(expectedCreatedNew, createdNew); + + if (expectedCreatedNew) + { + Assert.Throws(() => Semaphore.OpenExisting(name, openOptions)); + } + else + { + Semaphore.OpenExisting(name, openOptions).Dispose(); + } + + Assert.Equal(!expectedCreatedNew, Semaphore.TryOpenExisting(name, openOptions, out Semaphore s2)); + s2?.Dispose(); + } + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(nameof(MutexTests.NameOptionCombinations_MemberData), MemberType = typeof(MutexTests))] [PlatformSpecific(TestPlatforms.Windows)] // names aren't supported on Unix - public void PingPong() + public void PingPong(bool currentUserOnly, bool currentSessionOnly) { // Create names for the two semaphores string outboundName = Guid.NewGuid().ToString("N"); string inboundName = Guid.NewGuid().ToString("N"); + NamedWaitHandleOptions options = + new() { CurrentUserOnly = currentUserOnly, CurrentSessionOnly = currentSessionOnly }; + // Create the two semaphores and the other process with which to synchronize - using (var inbound = new Semaphore(1, 1, inboundName)) - using (var outbound = new Semaphore(0, 1, outboundName)) - using (var remote = RemoteExecutor.Invoke(new Action(PingPong_OtherProcess), outboundName, inboundName)) + using (var inbound = new Semaphore(1, 1, inboundName, options)) + using (var outbound = new Semaphore(0, 1, outboundName, options)) + using (var remote = + RemoteExecutor.Invoke( + PingPong_OtherProcess, + outboundName, + inboundName, + options.CurrentUserOnly ? "1" : "0", + options.CurrentSessionOnly ? "1" : "0")) { // Repeatedly wait for count in one semaphore and then release count into the other for (int i = 0; i < 10; i++) @@ -437,11 +578,22 @@ public void PingPong() } } - private static void PingPong_OtherProcess(string inboundName, string outboundName) + private static void PingPong_OtherProcess( + string inboundName, + string outboundName, + string currentUserOnlyStr, + string currentSessionOnlyStr) { + NamedWaitHandleOptions options = + new() + { + CurrentUserOnly = int.Parse(currentUserOnlyStr) != 0, + CurrentSessionOnly = int.Parse(currentSessionOnlyStr) != 0 + }; + // Open the two semaphores - using (var inbound = Semaphore.OpenExisting(inboundName)) - using (var outbound = Semaphore.OpenExisting(outboundName)) + using (var inbound = Semaphore.OpenExisting(inboundName, options)) + using (var outbound = Semaphore.OpenExisting(outboundName, options)) { // Repeatedly wait for count in one semaphore and then release count into the other for (int i = 0; i < 10; i++) diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index f0160b4974df59..834c4881aac512 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -882,7 +882,6 @@ endif() ### End of OS specific checks include_directories("${CLR_SRC_NATIVE_DIR}") -add_subdirectory(${CLR_SRC_NATIVE_DIR}/minipal minipal) if(NOT DISABLE_LIBS) set(INSTALL_MONO_API 1) diff --git a/src/mono/browser/browser.proj b/src/mono/browser/browser.proj index b6aa196282dc46..e01f3e613c2798 100644 --- a/src/mono/browser/browser.proj +++ b/src/mono/browser/browser.proj @@ -19,6 +19,7 @@ $([MSBuild]::NormalizeDirectory('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'browser-wasm', 'native', 'lib')) $([MSBuild]::NormalizeDirectory('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'browser-wasm-threads', 'native', 'lib')) false + true false true false @@ -335,6 +336,7 @@ "PropertiesThatTriggerRelinking": [ { "identity": "InvariantTimezone", "defaultValueInRuntimePack": "$(InvariantTimezone)" }, { "identity": "InvariantGlobalization", "defaultValueInRuntimePack": "$(InvariantGlobalization)" }, + { "identity": "WasmEnableStreamingResponse", "defaultValueInRuntimePack": "$(WasmEnableStreamingResponse)" }, { "identity": "WasmNativeStrip", "defaultValueInRuntimePack": "$(WasmNativeStrip)" }, { "identity": "WasmSingleFileBundle", "defaultValueInRuntimePack": "$(WasmSingleFileBundle)" }, { "identity": "WasmEnableSIMD", "defaultValueInRuntimePack": "$(WasmEnableSIMD)" }, diff --git a/src/mono/browser/build/BrowserWasmApp.targets b/src/mono/browser/build/BrowserWasmApp.targets index 10fae70c3dac1c..ddd612cdbedbaf 100644 --- a/src/mono/browser/build/BrowserWasmApp.targets +++ b/src/mono/browser/build/BrowserWasmApp.targets @@ -5,6 +5,7 @@ $(WasmEnableExceptionHandling) false + true @@ -58,8 +59,18 @@ <_WasmDefaultFlags Condition="'$(WasmEnableSIMD)' == 'true'">-msimd128 <_WasmOutputFileName Condition="'$(WasmSingleFileBundle)' != 'true'">dotnet.native.wasm + + true + + + + + @@ -129,16 +140,21 @@ <_WasmPThreadPoolInitialSize Condition="'$(_WasmPThreadPoolInitialSize)' == ''">-1 <_WasmPThreadPoolUnusedSize Condition="'$(_WasmPThreadPoolUnusedSize)' == ''">-1 <_WasmIsPublishing Condition="'$(_WasmIsPublishing)' == '' and '$(_IsPublishing)' != ''">$(_IsPublishing) + + <_WasmAppBuilderBootConfigFileName>$(WasmBootConfigFileName) + <_WasmAppBuilderBootConfigFileName Condition="'$(_WasmAppBuilderBootConfigFileName)' == ''">dotnet.boot.js + !runtimeHelpers.emscriptenBuildOptions.enablePerfTracing, "mono_jiterp_prof_enter", "void", ["number", "number"]], - [() => !runtimeHelpers.emscriptenBuildOptions.enablePerfTracing, "mono_jiterp_prof_samplepoint", "void", ["number", "number"]], - [() => !runtimeHelpers.emscriptenBuildOptions.enablePerfTracing, "mono_jiterp_prof_leave", "void", ["number", "number"]], + [() => !runtimeHelpers.emscriptenBuildOptions.enablePerfTracing && !runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler, "mono_jiterp_prof_enter", "void", ["number", "number"]], + [() => !runtimeHelpers.emscriptenBuildOptions.enablePerfTracing && !runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler, "mono_jiterp_prof_samplepoint", "void", ["number", "number"]], + [() => !runtimeHelpers.emscriptenBuildOptions.enablePerfTracing && !runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler, "mono_jiterp_prof_leave", "void", ["number", "number"]], ...threading_cwraps, ]; diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index 9dad722fbb047c..0cd2872d719113 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -58,11 +58,11 @@ declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Arra interface DotnetHostBuilder { /** * @param config default values for the runtime configuration. It will be merged with the default values. - * Note that if you provide resources and don't provide custom configSrc URL, the blazor.boot.json will be downloaded and applied by default. + * Note that if you provide resources and don't provide custom configSrc URL, the dotnet.boot.js will be downloaded and applied by default. */ withConfig(config: MonoConfig): DotnetHostBuilder; /** - * @param configSrc URL to the configuration file. ./blazor.boot.json is a default config file location. + * @param configSrc URL to the configuration file. ./dotnet.boot.js is a default config file location. */ withConfigSrc(configSrc: string): DotnetHostBuilder; /** @@ -376,7 +376,7 @@ type SingleAssetBehaviors = */ | "js-module-native" /** - * Typically blazor.boot.json + * Typically dotnet.boot.js */ | "manifest" /** diff --git a/src/mono/browser/runtime/es6/dotnet.es6.lib.js b/src/mono/browser/runtime/es6/dotnet.es6.lib.js index 3d8591c64965e8..0fadbb29d84e99 100644 --- a/src/mono/browser/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/browser/runtime/es6/dotnet.es6.lib.js @@ -78,22 +78,20 @@ function createWasmImportStubsFrom(collection) { // we will replace them with the real implementation in replace_linker_placeholders function injectDependencies() { createWasmImportStubsFrom(methodIndexByName.mono_wasm_imports); - if (WASM_PERFTRACING) createWasmImportStubsFrom(methodIndexByName.mono_wasm_diagnostic_imports); #if USE_PTHREADS createWasmImportStubsFrom(methodIndexByName.mono_wasm_threads_imports); #endif DotnetSupportLib["$DOTNET__postset"] = `DOTNET.setup({ ` + - `wasmEnableSIMD: ${WASM_ENABLE_SIMD ? "true" : "false"},` + - `wasmEnableEH: ${WASM_ENABLE_EH ? "true" : "false"},` + - `enablePerfTracing: ${WASM_PERFTRACING ? "true" : "false"}, ` + - `enableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` + - `enableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}, ` + - `enablePerfTracing: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}, ` + - `enableLogProfiler: ${ENABLE_LOG_PROFILER ? "true" : "false"}, ` + - `runAOTCompilation: ${RUN_AOT_COMPILATION ? "true" : "false"}, ` + - `wasmEnableThreads: ${USE_PTHREADS ? "true" : "false"}, ` + + `wasmEnableSIMD: ${WASM_ENABLE_SIMD},` + + `wasmEnableEH: ${WASM_ENABLE_EH},` + + `enableAotProfiler: ${ENABLE_AOT_PROFILER}, ` + + `enableBrowserProfiler: ${ENABLE_BROWSER_PROFILER}, ` + + `enableLogProfiler: ${ENABLE_LOG_PROFILER}, ` + + `enablePerfTracing: ${WASM_PERFTRACING}, ` + + `runAOTCompilation: ${RUN_AOT_COMPILATION}, ` + + `wasmEnableThreads: ${!!USE_PTHREADS}, ` + `gitHash: "${gitHash}", ` + `});`; diff --git a/src/mono/browser/runtime/exports-binding.ts b/src/mono/browser/runtime/exports-binding.ts index d7175ac9ee634a..31a050bd82f0cb 100644 --- a/src/mono/browser/runtime/exports-binding.ts +++ b/src/mono/browser/runtime/exports-binding.ts @@ -50,15 +50,6 @@ export const mono_wasm_threads_imports = !WasmEnableThreads ? [] : [ mono_wasm_warn_about_blocking_wait, ]; -export const mono_wasm_diagnostic_imports = [ - //event pipe - ds_rt_websocket_create, - ds_rt_websocket_send, - ds_rt_websocket_poll, - ds_rt_websocket_recv, - ds_rt_websocket_close, -]; - export const mono_wasm_imports = [ // mini-wasm.c mono_wasm_schedule_timer, @@ -101,13 +92,18 @@ export const mono_wasm_imports = [ mono_wasm_resolve_or_reject_promise, mono_wasm_cancel_promise, mono_wasm_get_locale_info, + + //event pipe + ds_rt_websocket_create, + ds_rt_websocket_send, + ds_rt_websocket_poll, + ds_rt_websocket_recv, + ds_rt_websocket_close, ]; // !!! Keep in sync with exports-linker.ts const wasmImports: Function[] = [ ...mono_wasm_imports, - // diagnostic server exports, when enabled - ...mono_wasm_diagnostic_imports, // threading exports, if threading is enabled ...mono_wasm_threads_imports, ]; diff --git a/src/mono/browser/runtime/exports-linker.ts b/src/mono/browser/runtime/exports-linker.ts index 5c24cc97b0b9f8..b1d5c0234f565d 100644 --- a/src/mono/browser/runtime/exports-linker.ts +++ b/src/mono/browser/runtime/exports-linker.ts @@ -1,14 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { mono_wasm_diagnostic_imports, mono_wasm_imports, mono_wasm_threads_imports } from "./exports-binding"; +import { mono_wasm_imports, mono_wasm_threads_imports } from "./exports-binding"; import gitHash from "consts:gitHash"; export function export_linker_indexes_as_code (): string { const indexByName: any = { mono_wasm_imports: {}, mono_wasm_threads_imports: {}, - mono_wasm_diagnostic_imports: {}, }; let idx = 0; for (const wi of mono_wasm_imports) { @@ -19,10 +18,6 @@ export function export_linker_indexes_as_code (): string { indexByName.mono_wasm_threads_imports[wi.name] = idx; idx++; } - for (const wi of mono_wasm_diagnostic_imports) { - indexByName.mono_wasm_diagnostic_imports[wi.name] = idx; - idx++; - } return ` var gitHash = "${gitHash}"; var methodIndexByName = ${JSON.stringify(indexByName, null, 2)}; diff --git a/src/mono/browser/runtime/http.ts b/src/mono/browser/runtime/http.ts index 74f86f88791c4d..149c3c05a473f6 100644 --- a/src/mono/browser/runtime/http.ts +++ b/src/mono/browser/runtime/http.ts @@ -26,11 +26,7 @@ function commonAsserts (controller: HttpController) { mono_assert(controller, "expected controller"); } -let http_wasm_supports_streaming_request_cached: boolean | undefined; export function http_wasm_supports_streaming_request (): boolean { - if (http_wasm_supports_streaming_request_cached !== undefined) { - return http_wasm_supports_streaming_request_cached; - } // Detecting streaming request support works like this: // If the browser doesn't support a particular body type, it calls toString() on the object and uses the result as the body. // So, if the browser doesn't support request streams, the request body becomes the string "[object ReadableStream]". @@ -48,20 +44,13 @@ export function http_wasm_supports_streaming_request (): boolean { return "half"; }, } as RequestInit /* https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1483 */).headers.has("Content-Type"); - http_wasm_supports_streaming_request_cached = duplexAccessed && !hasContentType; - } else { - http_wasm_supports_streaming_request_cached = false; + return duplexAccessed && !hasContentType; } - return http_wasm_supports_streaming_request_cached; + return false; } -let http_wasm_supports_streaming_response_cached: boolean | undefined; export function http_wasm_supports_streaming_response (): boolean { - if (http_wasm_supports_streaming_response_cached !== undefined) { - return http_wasm_supports_streaming_response_cached; - } - http_wasm_supports_streaming_response_cached = typeof Response !== "undefined" && "body" in Response.prototype && typeof ReadableStream === "function"; - return http_wasm_supports_streaming_response_cached; + return typeof Response !== "undefined" && "body" in Response.prototype && typeof ReadableStream === "function"; } export function http_wasm_create_controller (): HttpController { diff --git a/src/mono/browser/runtime/jiterpreter.ts b/src/mono/browser/runtime/jiterpreter.ts index 80da42e655f6ad..55b46e882a42f0 100644 --- a/src/mono/browser/runtime/jiterpreter.ts +++ b/src/mono/browser/runtime/jiterpreter.ts @@ -299,7 +299,7 @@ function getTraceImports () { if (nullCheckValidation) traceImports.push(importDef("notnull", assert_not_null)); - if (runtimeHelpers.emscriptenBuildOptions.enablePerfTracing) { + if (runtimeHelpers.emscriptenBuildOptions.enablePerfTracing || runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler) { traceImports.push(importDef("prof_enter", getRawCwrap("mono_jiterp_prof_enter"))); traceImports.push(importDef("prof_samplepoint", getRawCwrap("mono_jiterp_prof_samplepoint"))); traceImports.push(importDef("prof_leave", getRawCwrap("mono_jiterp_prof_leave"))); diff --git a/src/mono/browser/runtime/loader/config.ts b/src/mono/browser/runtime/loader/config.ts index 33500995aa5ee1..8b79a2d14bbf58 100644 --- a/src/mono/browser/runtime/loader/config.ts +++ b/src/mono/browser/runtime/loader/config.ts @@ -240,10 +240,7 @@ export async function mono_wasm_load_config (module: DotnetModuleInternal): Prom try { if (!module.configSrc && (!loaderHelpers.config || Object.keys(loaderHelpers.config).length === 0 || (!loaderHelpers.config.assets && !loaderHelpers.config.resources))) { // if config file location nor assets are provided - // Temporal way for tests to opt-in for using boot.js - module.configSrc = (globalThis as any)["__DOTNET_INTERNAL_BOOT_CONFIG_SRC"] - ?? globalThis.window?.document?.documentElement?.getAttribute("data-dotnet_internal_boot_config_src") - ?? "blazor.boot.json"; + module.configSrc = "dotnet.boot.js"; } configFilePath = module.configSrc; @@ -336,6 +333,16 @@ async function loadBootConfig (module: DotnetModuleInternal): Promise { loaderHelpers.config.applicationEnvironment = "Production"; } + if (loaderHelpers.config.debugLevel !== 0 && document.querySelector("script[src*='aspnetcore-browser-refresh']")) { + loaderHelpers.config.environmentVariables = loaderHelpers.config.environmentVariables || {}; + if (!loaderHelpers.config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"]) { + loaderHelpers.config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; + } + if (!loaderHelpers.config.environmentVariables["__ASPNETCORE_BROWSER_TOOLS"]) { + loaderHelpers.config.environmentVariables["__ASPNETCORE_BROWSER_TOOLS"] = "true"; + } + } + function fetchBootConfig (url: string): Promise { return loaderHelpers.fetch_like(url, { method: "GET", diff --git a/src/mono/browser/runtime/profiler.ts b/src/mono/browser/runtime/profiler.ts index 223fea908c77ff..7cd570ee07d0e7 100644 --- a/src/mono/browser/runtime/profiler.ts +++ b/src/mono/browser/runtime/profiler.ts @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import type { CharPtr, VoidPtr } from "./types/emscripten"; - import { ENVIRONMENT_IS_WEB, mono_assert, runtimeHelpers } from "./globals"; import { MonoMethod, AOTProfilerOptions, BrowserProfilerOptions, LogProfilerOptions } from "./types/internal"; import { profiler_c_functions as cwraps } from "./cwraps"; @@ -46,7 +44,14 @@ export function mono_wasm_init_browser_profiler (options: BrowserProfilerOptions export function mono_wasm_init_log_profiler (options: LogProfilerOptions): void { mono_assert(runtimeHelpers.emscriptenBuildOptions.enableLogProfiler, "Log profiler is not enabled, please use log; in your project file."); mono_assert(options.takeHeapshot, "Log profiler is not enabled, the takeHeapshot method must be defined in LogProfilerOptions.takeHeapshot"); - cwraps.mono_wasm_profiler_init_log( (options.configuration || "log:alloc,output=output.mlpd") + `,take-heapshot-method=${options.takeHeapshot}`); + if (!options.configuration) { + options.configuration = "log:alloc,output=output.mlpd"; + } + if (options.takeHeapshot) { + cwraps.mono_wasm_profiler_init_log(`${options.configuration},take-heapshot-method=${options.takeHeapshot}`); + } else { + cwraps.mono_wasm_profiler_init_log(options.configuration); + } } export const enum MeasuredBlock { @@ -114,24 +119,3 @@ export function mono_wasm_profiler_record (method: MonoMethod, start: number): v } globalThis.performance.measure(methodName, options); } - -/* eslint-disable @typescript-eslint/no-unused-vars */ -export function ds_rt_websocket_create (urlPtr :CharPtr):number { - throw new Error("TODO"); -} - -export function ds_rt_websocket_send (client_socket :number, buffer:VoidPtr, bytes_to_write:number):number { - throw new Error("TODO"); -} - -export function ds_rt_websocket_poll (client_socket :number):number { - throw new Error("TODO"); -} - -export function ds_rt_websocket_recv (client_socket :number, buffer:VoidPtr, bytes_to_read:number):number { - throw new Error("TODO"); -} - -export function ds_rt_websocket_close (client_socket :number):number { - throw new Error("TODO"); -} diff --git a/src/mono/browser/runtime/rollup.config.js b/src/mono/browser/runtime/rollup.config.js index 20f1d1710d49de..ec1de7d67b0f75 100644 --- a/src/mono/browser/runtime/rollup.config.js +++ b/src/mono/browser/runtime/rollup.config.js @@ -20,7 +20,6 @@ const nativeBinDir = process.env.NativeBinDir ? process.env.NativeBinDir.replace const wasmObjDir = process.env.WasmObjDir ? process.env.WasmObjDir.replace(/"/g, "") : "obj"; const wasmEnableThreads = process.env.WasmEnableThreads === "true" ? true : false; const wasmEnableSIMD = process.env.WASM_ENABLE_SIMD === "1" ? true : false; -const wasmEnablePerfTracing = process.env.WASM_PERFTRACING === "1" ? true : false; const wasmEnableExceptionHandling = process.env.WASM_ENABLE_EH === "1" ? true : false; const wasmEnableJsInteropByValue = process.env.ENABLE_JS_INTEROP_BY_VALUE == "1" ? true : false; // because of stack walk at src/mono/browser/debugger/BrowserDebugProxy/MonoProxy.cs @@ -114,7 +113,6 @@ const envConstants = { configuration, wasmEnableThreads, wasmEnableSIMD, - wasmEnablePerfTracing, wasmEnableExceptionHandling, gitHash, wasmEnableJsInteropByValue, diff --git a/src/mono/browser/runtime/startup.ts b/src/mono/browser/runtime/startup.ts index 12402cbb238114..5874334a846325 100644 --- a/src/mono/browser/runtime/startup.ts +++ b/src/mono/browser/runtime/startup.ts @@ -526,9 +526,10 @@ async function ensureUsedWasmFeatures () { export async function start_runtime () { try { const mark = startMeasure(); + const environmentVariables = runtimeHelpers.config.environmentVariables || {}; mono_log_debug("Initializing mono runtime"); - for (const k in runtimeHelpers.config.environmentVariables) { - const v = runtimeHelpers.config.environmentVariables![k]; + for (const k in environmentVariables) { + const v = environmentVariables![k]; if (typeof (v) === "string") mono_wasm_setenv(k, v); else @@ -537,14 +538,20 @@ export async function start_runtime () { if (runtimeHelpers.config.runtimeOptions) mono_wasm_set_runtime_options(runtimeHelpers.config.runtimeOptions); - if (runtimeHelpers.config.aotProfilerOptions) - mono_wasm_init_aot_profiler(runtimeHelpers.config.aotProfilerOptions); - - if (runtimeHelpers.config.browserProfilerOptions) - mono_wasm_init_browser_profiler(runtimeHelpers.config.browserProfilerOptions); - - if (runtimeHelpers.config.logProfilerOptions) - mono_wasm_init_log_profiler(runtimeHelpers.config.logProfilerOptions); + if (runtimeHelpers.emscriptenBuildOptions.enablePerfTracing) { + const diagnosticPorts = "DOTNET_DiagnosticPorts"; + const jsReady = "js://ready"; + if (!environmentVariables[diagnosticPorts]) { + environmentVariables[diagnosticPorts] = jsReady; + mono_wasm_setenv(diagnosticPorts, jsReady); + } + } else if (runtimeHelpers.emscriptenBuildOptions.enableAotProfiler) { + mono_wasm_init_aot_profiler(runtimeHelpers.config.aotProfilerOptions || {}); + } else if (runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler) { + mono_wasm_init_browser_profiler(runtimeHelpers.config.browserProfilerOptions || {}); + } else if (runtimeHelpers.emscriptenBuildOptions.enableLogProfiler) { + mono_wasm_init_log_profiler(runtimeHelpers.config.logProfilerOptions || {}); + } mono_wasm_load_runtime(); diff --git a/src/mono/browser/runtime/types/index.ts b/src/mono/browser/runtime/types/index.ts index b52eba91bd35d0..e2653cc0d54580 100644 --- a/src/mono/browser/runtime/types/index.ts +++ b/src/mono/browser/runtime/types/index.ts @@ -6,11 +6,11 @@ import type { EmscriptenModule, NativePointer } from "./emscripten"; export interface DotnetHostBuilder { /** * @param config default values for the runtime configuration. It will be merged with the default values. - * Note that if you provide resources and don't provide custom configSrc URL, the blazor.boot.json will be downloaded and applied by default. + * Note that if you provide resources and don't provide custom configSrc URL, the dotnet.boot.js will be downloaded and applied by default. */ withConfig(config: MonoConfig): DotnetHostBuilder; /** - * @param configSrc URL to the configuration file. ./blazor.boot.json is a default config file location. + * @param configSrc URL to the configuration file. ./dotnet.boot.js is a default config file location. */ withConfigSrc(configSrc: string): DotnetHostBuilder; /** @@ -256,7 +256,7 @@ export interface LoadingResource { response: Promise; } -// Types of assets that can be in the _framework/blazor.boot.json file (taken from /src/tasks/WasmAppBuilder/WasmAppBuilder.cs) +// Types of assets that can be in the _framework/dotnet.boot.js file (taken from /src/tasks/WasmAppBuilder/WasmAppBuilder.cs) export interface AssetEntry { /** * the name of the asset, including extension. @@ -335,7 +335,7 @@ export type SingleAssetBehaviors = */ | "js-module-native" /** - * Typically blazor.boot.json + * Typically dotnet.boot.js */ | "manifest" /** diff --git a/src/mono/browser/test-main.js b/src/mono/browser/test-main.js index 4029323393e1ef..cb213323892a94 100644 --- a/src/mono/browser/test-main.js +++ b/src/mono/browser/test-main.js @@ -117,7 +117,7 @@ function initRunArgs(runArgs) { runArgs.enableGC = runArgs.enableGC === undefined ? true : runArgs.enableGC; runArgs.diagnosticTracing = runArgs.diagnosticTracing === undefined ? false : runArgs.diagnosticTracing; runArgs.debugging = runArgs.debugging === undefined ? false : runArgs.debugging; - runArgs.configSrc = runArgs.configSrc === undefined ? './_framework/blazor.boot.json' : runArgs.configSrc; + runArgs.configSrc = runArgs.configSrc === undefined ? './_framework/dotnet.boot.js' : runArgs.configSrc; // default'ing to true for tests, unless debugging runArgs.forwardConsole = runArgs.forwardConsole === undefined ? !runArgs.debugging : runArgs.forwardConsole; runArgs.interpreterPgo = runArgs.interpreterPgo === undefined ? false : runArgs.interpreterPgo; diff --git a/src/mono/llvm/llvm-init.proj b/src/mono/llvm/llvm-init.proj index 6e1445dd817f23..cce72ce0a59f94 100644 --- a/src/mono/llvm/llvm-init.proj +++ b/src/mono/llvm/llvm-init.proj @@ -13,7 +13,7 @@ $(runtimelinuxmuslx64MicrosoftNETCoreRuntimeMonoLLVMToolsVersion) $(runtimewinx64MicrosoftNETCoreRuntimeMonoLLVMToolsVersion) $(runtimeosxx64MicrosoftNETCoreRuntimeMonoLLVMToolsVersion) - .Debug + .Debug diff --git a/src/mono/mono/CMakeLists.txt b/src/mono/mono/CMakeLists.txt index c59470996f5825..9368f312502d0e 100644 --- a/src/mono/mono/CMakeLists.txt +++ b/src/mono/mono/CMakeLists.txt @@ -1,6 +1,7 @@ project(mono) set(subdirs + minipal eglib utils sgen diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c index 5273c91f40108a..d91281d3c92499 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c @@ -1184,31 +1184,27 @@ ep_rt_mono_walk_managed_stack_for_thread ( stack_walk_data.safe_point_frame = false; stack_walk_data.runtime_invoke_frame = false; - bool restore_async_context = FALSE; - bool prevent_profiler_event_recursion = FALSE; + bool prevent_profiler_event_recursion = false; + MonoUnwindOptions unwind_options = MONO_UNWIND_NONE; EventPipeMonoThreadData *thread_data = ep_rt_mono_thread_data_get_or_create (); if (thread_data) { prevent_profiler_event_recursion = thread_data->prevent_profiler_event_recursion; - if (prevent_profiler_event_recursion && !mono_thread_info_is_async_context ()) { + if (prevent_profiler_event_recursion) { // Running stackwalk in async context mode is currently the only way to prevent // unwinder to NOT load additional classes during stackwalk, making it signal unsafe and // potential triggering uncontrolled recursion in profiler class loading event. - mono_thread_info_set_is_async_context (TRUE); - restore_async_context = TRUE; + unwind_options = MONO_UNWIND_SIGNAL_SAFE; } - thread_data->prevent_profiler_event_recursion = TRUE; + thread_data->prevent_profiler_event_recursion = true; } if (thread == ep_rt_thread_get_handle () && mono_get_eh_callbacks ()->mono_walk_stack_with_ctx) - mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (walk_managed_stack_for_thread_callback, NULL, MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data); + mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (walk_managed_stack_for_thread_callback, NULL, unwind_options, &stack_walk_data); else if (mono_get_eh_callbacks ()->mono_walk_stack_with_state) - mono_get_eh_callbacks ()->mono_walk_stack_with_state (walk_managed_stack_for_thread_callback, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data); + mono_get_eh_callbacks ()->mono_walk_stack_with_state (walk_managed_stack_for_thread_callback, mono_thread_info_get_suspend_state (thread), unwind_options, &stack_walk_data); - if (thread_data) { - if (restore_async_context) - mono_thread_info_set_is_async_context (FALSE); + if (thread_data) thread_data->prevent_profiler_event_recursion = prevent_profiler_event_recursion; - } return true; } @@ -1236,10 +1232,10 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads ( mono_stop_world (MONO_THREAD_INFO_FLAGS_NO_GC); - bool restore_async_context = FALSE; + bool restore_async_context = false; if (!mono_thread_info_is_async_context ()) { mono_thread_info_set_is_async_context (TRUE); - restore_async_context = TRUE; + restore_async_context = true; } // Record all info needed in sample events while runtime is suspended, must be async safe. @@ -1361,7 +1357,7 @@ method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *c data->stack_walk_data.runtime_invoke_frame = false; ep_stack_contents_reset (&data->stack_contents); - mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (sample_profiler_walk_managed_stack_for_thread_callback, &ctx->context, MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data); + mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (sample_profiler_walk_managed_stack_for_thread_callback, &ctx->context, MONO_UNWIND_NONE, &stack_walk_data); if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && (data->stack_walk_data.safe_point_frame || data->stack_walk_data.runtime_invoke_frame)) { data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED; } @@ -2504,7 +2500,7 @@ write_event_exception_thrown (MonoObject *obj) exception_message = g_strdup (""); if (mono_get_eh_callbacks ()->mono_walk_stack_with_ctx) - mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (get_exception_ip_func, NULL, MONO_UNWIND_SIGNAL_SAFE, (void *)&ip); + mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (get_exception_ip_func, NULL, MONO_UNWIND_NONE, (void *)&ip); type_name = mono_type_get_name_full (m_class_get_byval_arg (mono_object_class (obj)), MONO_TYPE_NAME_FORMAT_IL); @@ -3024,13 +3020,13 @@ class_loading_callback ( MonoProfiler *prof, MonoClass *klass) { - bool prevent_profiler_event_recursion = FALSE; + bool prevent_profiler_event_recursion = false; EventPipeMonoThreadData *thread_data = ep_rt_mono_thread_data_get_or_create (); if (thread_data) { // Prevent additional class loading to happen recursively as part of fire TypeLoadStart event. // Additional class loading can happen as part of capturing callstack for TypeLoadStart event. prevent_profiler_event_recursion = thread_data->prevent_profiler_event_recursion; - thread_data->prevent_profiler_event_recursion = TRUE; + thread_data->prevent_profiler_event_recursion = true; } write_event_type_load_start (m_class_get_byval_arg (klass)); diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 624fd9989efe4f..33f545e01768f3 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -3964,21 +3964,15 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) if (iface) array_ifaces [interface_count ++] = iface; } - int mult = klass->element_class->enumtype ? 2 : 1; - interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count * mult); + interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count ); int itf_idx = 0; args [0] = m_class_get_byval_arg (m_class_get_element_class (klass)); for (int i = 0; i < interface_count; ++i) interfaces [itf_idx++] = mono_class_bind_generic_parameters (array_ifaces [i], 1, args, FALSE); - if (klass->element_class->enumtype) { - args [0] = mono_class_enum_basetype_internal (klass->element_class); - for (int i = 0; i < interface_count; ++i) - interfaces [itf_idx++] = mono_class_bind_generic_parameters (array_ifaces [i], 1, args, FALSE); - } - interface_count *= mult; g_assert (itf_idx == interface_count); + } else if (mono_class_is_ginst (klass)) { MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 7b453e88d237a5..56408f3387c019 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -6806,6 +6806,8 @@ mono_object_handle_isinst (MonoObjectHandle obj, MonoClass *klass, MonoError *er { error_init (error); + g_assert (klass); + if (!m_class_is_inited (klass)) mono_class_init_internal (klass); diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index 11fb393d770676..f641c393dd785c 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -2941,20 +2941,13 @@ collect_frame (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data) return FALSE; } -/* This needs to be async safe */ static SuspendThreadResult get_thread_dump (MonoThreadInfo *info, gpointer ud) { ThreadDumpUserData *user_data = (ThreadDumpUserData *)ud; MonoInternalThread *thread = user_data->thread; -#if 0 -/* This no longer works with remote unwinding */ - g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread); - mono_thread_internal_describe (thread, text); - g_string_append (text, "\n"); -#endif - + /* This needs to be async safe */ if (thread == mono_thread_internal_current ()) mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (collect_frame, NULL, MONO_UNWIND_SIGNAL_SAFE, ud); else @@ -4107,9 +4100,8 @@ mono_thread_info_get_last_managed (MonoThreadInfo *info) * The suspended thread might be holding runtime locks. Make sure we don't try taking * any runtime locks while unwinding. */ - mono_thread_info_set_is_async_context (TRUE); mono_get_eh_callbacks ()->mono_walk_stack_with_state (last_managed, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, &ji); - mono_thread_info_set_is_async_context (FALSE); + return ji; } diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index f98cc584b8dea5..ec92602456e16f 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -190,6 +190,12 @@ emit_common_simd_operations (TransformData *td, int id, int atype, int vector_si for (int i = 0; i < vector_size / arg_size; i++) data [i] = 1.0f; return TRUE; + } else if (atype == MONO_TYPE_R8) { + interp_add_ins (td, MINT_SIMD_V128_LDC); + double *data = (double*)&td->last_ins->data [0]; + for (int i = 0; i < vector_size / arg_size; i++) + data [i] = 1.0; + return TRUE; } break; case SN_get_Zero: @@ -308,6 +314,8 @@ get_common_simd_info (MonoClass *vector_klass, MonoMethodSignature *csignature, if (!m_class_is_simd_type (vector_klass)) return FALSE; + if (!mono_class_is_ginst (vector_klass)) + return FALSE; MonoType *arg_type = mono_class_get_context (vector_klass)->class_inst->type_argv [0]; if (!mono_type_is_primitive (arg_type)) return FALSE; @@ -443,7 +451,7 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature if (csignature->ret->type == MONO_TYPE_GENERICINST) { vector_klass = mono_class_from_mono_type_internal (csignature->ret); - } else if (csignature->params [0]->type == MONO_TYPE_GENERICINST) { + } else if (csignature->param_count && csignature->params [0]->type == MONO_TYPE_GENERICINST) { vector_klass = mono_class_from_mono_type_internal (csignature->params [0]); } else { return FALSE; @@ -506,6 +514,9 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature simd_intrins = INTERP_SIMD_INTRINSIC_V128_CONDITIONAL_SELECT; break; case SN_Create: + if (!is_element_type_primitive (csignature->ret)) + return FALSE; + if (csignature->param_count == 1 && atype == csignature->params [0]->type) { simd_opcode = MINT_SIMD_INTRINS_P_P; if (arg_size == 1) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I1_CREATE; @@ -679,20 +690,25 @@ static gboolean emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature, gboolean newobj) { const char *cmethod_name = cmethod->name; + bool explicitly_implemented = false; - if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector,T>.", 67) == 0) { // We want explicitly implemented ISimdVector APIs to still be expanded where possible // but, they all prefix the qualified name of the interface first, so we'll check for that and // skip the prefix before trying to resolve the method. - if (strncmp(cmethod_name + 70, ",T>.", 7) == 0) { - cmethod_name += 77; - } + cmethod_name += 67; + explicitly_implemented = true; } int id = lookup_intrins (sn_vector_t_methods, sizeof (sn_vector_t_methods), cmethod_name); - if (id == -1) - return FALSE; + if (id == -1) { + if (explicitly_implemented) { + return emit_sri_vector128 (td, cmethod, csignature); + } else { + return FALSE; + } + } gint16 simd_opcode = -1; gint16 simd_intrins = -1; @@ -1067,7 +1083,9 @@ interp_emit_simd_intrinsics (TransformData *td, MonoMethod *cmethod, MonoMethodS else if (!strcmp (class_name, "Vector128`1")) return emit_sri_vector128_t (td, cmethod, csignature); } else if (!strcmp (class_ns, "System.Numerics")) { - if (!strcmp (class_name, "Vector`1")) + if (!strcmp (class_name, "Vector")) + return emit_sri_vector128 (td, cmethod, csignature); + else if (!strcmp (class_name, "Vector`1")) return emit_sn_vector_t (td, cmethod, csignature, newobj); else if (!strcmp (class_name, "Vector4")) return emit_sn_vector4 (td, cmethod, csignature, newobj); diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 046dfa79e5b0a7..6b8e8642259826 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -2396,19 +2396,21 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign !strncmp ("System.Runtime.Intrinsics", cmethod_klass_name_space, 25))) { const char* cmethod_name = cmethod->name; - if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible - // but, they all prefix the qualified name of the interface first, so we'll check for that and - // skip the prefix before trying to resolve the method. - - if (strncmp(cmethod_name + 70, ",T>.", 7) == 0) { - cmethod_name += 77; - } else if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { - cmethod_name += 79; - } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { - cmethod_name += 80; + if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible + // but, they all prefix the qualified name of the interface first, so we'll check for that and + // skip the prefix before trying to resolve the method. + + if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { + cmethod_name += 79; + } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { + cmethod_name += 80; + } + } else if (strncmp(cmethod_name + 45, "Numerics.Vector,T>.", 22) == 0) { + cmethod_name += 67; } } diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index df7c332f8fcd4c..a62f6959f2b2b7 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -1702,7 +1702,7 @@ mono_throw_type_load (MonoClass* klass) mono_error_set_type_load_class (error, klass, "Attempting to load invalid type '%s'.", klass_name); g_free (klass_name); } - + mono_error_set_pending_exception (error); } @@ -1743,6 +1743,11 @@ mini_init_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, MonoGSharedMeth mono_method_get_context (m), m->klass); g_assert (data); + // we need a barrier before publishing data via mrgctx->infos [i] because the contents of data may not + // have been published to all cores and another thread may read zeroes or partially initialized data + // out of it, even though we have a barrier before publication of entries in mrgctx->entries below + mono_memory_barrier(); + /* The first few entries are stored inline, the rest are stored in mrgctx->entries */ if (i < ninline) mrgctx->infos [i] = data; diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index 4fce6945132167..1a689f34a82cd2 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -126,7 +126,7 @@ static MonoFtnPtrEHCallback ftnptr_eh_callback; */ int mono_llvmonly_do_unwind_flag; -static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data, gboolean crash_context); +static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data); static void mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx); static void mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data); static gboolean mono_current_thread_has_handle_block_guard (void); @@ -160,7 +160,7 @@ static gpointer mono_thread_get_managed_sp (void) { gpointer addr = NULL; - mono_walk_stack (first_managed, MONO_UNWIND_SIGNAL_SAFE, &addr); + mono_walk_stack (first_managed, MONO_UNWIND_NONE, &addr); return addr; } @@ -1224,7 +1224,7 @@ mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnw start_ctx = &extra_ctx; } - mono_walk_stack_full (func, start_ctx, thread->jit_data, mono_get_lmf (), unwind_options, user_data, FALSE); + mono_walk_stack_full (func, start_ctx, thread->jit_data, mono_get_lmf (), unwind_options, user_data); } /** @@ -1241,8 +1241,9 @@ void mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data) { MonoThreadUnwindState extra_state; + if (!state) { - g_assert (!mono_thread_info_is_async_context ()); + g_assert (!(unwind_options & MONO_UNWIND_SIGNAL_SAFE) && !mono_thread_info_is_async_context ()); if (!mono_thread_state_init_from_current (&extra_state)) return; state = &extra_state; @@ -1258,7 +1259,7 @@ mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, &state->ctx, (MonoJitTlsData *)state->unwind_data [MONO_UNWIND_DATA_JIT_TLS], (MonoLMF *)state->unwind_data [MONO_UNWIND_DATA_LMF], - unwind_options, user_data, FALSE); + unwind_options, user_data); } void @@ -1270,22 +1271,49 @@ mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_da mono_walk_stack_with_state (func, &state, options, user_data); } -/** - * mono_walk_stack_full: - * \param func callback to call for each stack frame - * \param unwind_options what extra information the unwinder should gather - * \param start_ctx starting state of the stack walk, can be NULL. - * \param thread the thread whose stack to walk, can be NULL to use the current thread - * \param lmf the LMF of \p thread, can be NULL to use the LMF of the current thread - * \param user_data data passed to the callback - * \param crash_context tells us that we're in a context where it's not safe to lock or allocate - * This function walks the stack of a thread, starting from the state - * represented by \p start_ctx. For each frame the callback - * function is called with the relevant info. The walk ends when no more - * managed stack frames are found or when the callback returns a TRUE value. - */ +#ifndef TARGET_WASM static void -mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data, gboolean crash_context) +walk_stack_full_llvm_only(MonoJitStackWalk func, MonoContext* start_ctx, MonoJitTlsData* jit_tls, MonoLMF* lmf, MonoUnwindOptions unwind_options, gpointer user_data) +{ + GSList *l, *ips; + StackFrameInfo frame; + + g_assert(mono_llvm_only); + + memset (&frame, 0, sizeof (StackFrameInfo)); + + // TODO: Fix async support. + if (mono_thread_info_is_async_context ()) + return; + + ips = get_unwind_backtrace (); + for (l = ips; l; l = l->next) { + guint8 *ip = (guint8*)l->data; + memset (&frame, 0, sizeof (StackFrameInfo)); + frame.ji = mini_jit_info_table_find (ip); + if (!frame.ji || frame.ji->is_trampoline) + continue; + frame.type = FRAME_TYPE_MANAGED; + frame.method = jinfo_get_method (frame.ji); + // FIXME: Cannot lookup the actual method + frame.actual_method = frame.method; + if (frame.type == FRAME_TYPE_MANAGED) { + if (!frame.method->wrapper_type || frame.method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) + frame.managed = TRUE; + } + frame.native_offset = GPTRDIFF_TO_INT (ip - (guint8*)frame.ji->code_start); + frame.il_offset = -1; + + if (func (&frame, NULL, user_data)) + break; + } + g_slist_free (ips); + return; +} +#endif + +static void +walk_stack_full(MonoJitStackWalk func, MonoContext* start_ctx, MonoJitTlsData* jit_tls, MonoLMF* lmf, MonoUnwindOptions unwind_options, gpointer user_data) { gint il_offset; MonoContext ctx, new_ctx; @@ -1299,39 +1327,6 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsD memset (&frame, 0, sizeof (StackFrameInfo)); -#ifndef TARGET_WASM - if (mono_llvm_only) { - GSList *l, *ips; - - if (async) - return; - - ips = get_unwind_backtrace (); - for (l = ips; l; l = l->next) { - guint8 *ip = (guint8*)l->data; - memset (&frame, 0, sizeof (StackFrameInfo)); - frame.ji = mini_jit_info_table_find (ip); - if (!frame.ji || frame.ji->is_trampoline) - continue; - frame.type = FRAME_TYPE_MANAGED; - frame.method = jinfo_get_method (frame.ji); - // FIXME: Cannot lookup the actual method - frame.actual_method = frame.method; - if (frame.type == FRAME_TYPE_MANAGED) { - if (!frame.method->wrapper_type || frame.method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) - frame.managed = TRUE; - } - frame.native_offset = GPTRDIFF_TO_INT (ip - (guint8*)frame.ji->code_start); - frame.il_offset = -1; - - if (func (&frame, NULL, user_data)) - break; - } - g_slist_free (ips); - return; - } -#endif - if (!start_ctx) { g_warning ("start_ctx required for stack walk"); return; @@ -1372,7 +1367,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsD MonoDebugSourceLocation *source = NULL; // Don't do this when we can be in a signal handler - if (!crash_context) + if (!async) source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, NULL); if (source) { il_offset = source->il_offset; @@ -1380,7 +1375,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsD MonoSeqPointInfo *seq_points = NULL; // It's more reliable to look into the global cache if possible - if (crash_context) + if (async) seq_points = (MonoSeqPointInfo *) frame.ji->seq_points; else seq_points = mono_get_seq_points (jinfo_get_method (frame.ji)); @@ -1422,6 +1417,41 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsD } } +/** + * mono_walk_stack_full: + * \param func callback to call for each stack frame + * \param unwind_options what extra information the unwinder should gather + * \param start_ctx starting state of the stack walk, can be NULL. + * \param thread the thread whose stack to walk, can be NULL to use the current thread + * \param lmf the LMF of \p thread, can be NULL to use the LMF of the current thread + * \param user_data data passed to the callback + * This function walks the stack of a thread, starting from the state + * represented by \p start_ctx. For each frame the callback + * function is called with the relevant info. The walk ends when no more + * managed stack frames are found or when the callback returns a TRUE value. + */ +static void +mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data) +{ + gboolean restore_async_context = FALSE; + if ((unwind_options & MONO_UNWIND_SIGNAL_SAFE) && !mono_thread_info_is_async_context ()) { + mono_thread_info_set_is_async_context (TRUE); + restore_async_context = TRUE; + } + +#ifndef TARGET_WASM + if (mono_llvm_only) + walk_stack_full_llvm_only (func, start_ctx, jit_tls, lmf, unwind_options, user_data); + else + walk_stack_full (func, start_ctx, jit_tls, lmf, unwind_options, user_data); +#else + walk_stack_full (func, start_ctx, jit_tls, lmf, unwind_options, user_data); +#endif + + if (restore_async_context) + mono_thread_info_set_is_async_context (FALSE); +} + MonoBoolean mono_get_frame_info (gint32 skip, MonoMethod **out_method, @@ -2976,7 +3006,8 @@ mono_handle_native_crash (const char *signal, MonoContext *mctx, MONO_SIG_HANDLE g_async_safe_printf ("\tManaged Stacktrace:\n"); g_async_safe_printf ("=================================================================\n"); - mono_walk_stack_full (print_stack_frame_signal_safe, mctx, jit_tls, mono_get_lmf (), MONO_UNWIND_LOOKUP_IL_OFFSET, NULL, TRUE); + mono_walk_stack_full (print_stack_frame_signal_safe, mctx, jit_tls, mono_get_lmf (), MONO_UNWIND_LOOKUP_IL_OFFSET | MONO_UNWIND_SIGNAL_SAFE, NULL); + g_async_safe_printf ("=================================================================\n"); } @@ -3146,15 +3177,13 @@ mono_install_handler_block_guard (MonoThreadUnwindState *ctx) MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS]; /* Guard against a null MonoJitTlsData. This can happens if the thread receives the - * interrupt signal before the JIT has time to initialize its TLS data for the given thread. + * interrupt signal before the JIT has time to initialize its TLS data for the given thread. */ if (!jit_tls || jit_tls->handler_block) return FALSE; /* Do an async safe stack walk */ - mono_thread_info_set_is_async_context (TRUE); - mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data); - mono_thread_info_set_is_async_context (FALSE); + mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_SIGNAL_SAFE, &data); if (!data.ji) return FALSE; diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index fd8b480e5362dc..15b2b441eafb4f 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -291,11 +291,16 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler) int hp_save_index = mono_hazard_pointer_save_for_signal_handler (); - mono_thread_info_set_is_async_context (TRUE); + gboolean restore_async_context = FALSE; + if (!mono_thread_info_is_async_context ()) { + mono_thread_info_set_is_async_context (TRUE); + restore_async_context = TRUE; + } MONO_PROFILER_RAISE (sample_hit, ((const mono_byte*)mono_arch_ip_from_context (ctx), ctx)); - mono_thread_info_set_is_async_context (FALSE); + if (restore_async_context) + mono_thread_info_set_is_async_context (FALSE); mono_hazard_pointer_restore_for_signal_handler (hp_save_index); diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index d5303b4f9542be..f9d8d4b59ef559 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1906,19 +1906,21 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi { const char *cmethod_name = cmethod->name; - if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible // but, they all prefix the qualified name of the interface first, so we'll check for that and // skip the prefix before trying to resolve the method. - if (strncmp(cmethod_name + 70, ",T>.", 7) == 0) { - cmethod_name += 77; - } else if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { - cmethod_name += 79; - } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { - cmethod_name += 80; + if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { + cmethod_name += 79; + } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { + cmethod_name += 80; + } + } else if (strncmp(cmethod_name + 45, "Numerics.Vector,T>.", 22) == 0) { + cmethod_name += 67; } } @@ -2437,7 +2439,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi const char *klass_name = m_class_get_name (klass); - if (!strcmp (klass_name, "Vector4")) { + if (strcmp (m_class_get_name_space (klass), "System.Runtime.Intrinsics") != 0) { klass_name = "Vector128`1"; } arg_class = create_class_instance ("System.Runtime.Intrinsics", klass_name, m_class_get_byval_arg (cast_class)); @@ -3371,21 +3373,23 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f const char *cmethod_name = cmethod->name; bool explicitly_implemented = false; - if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible - // but, they all prefix the qualified name of the interface first, so we'll check for that and - // skip the prefix before trying to resolve the method. - - if (strncmp(cmethod_name + 70, ",T>.", 7) == 0) { - cmethod_name += 77; - explicitly_implemented = true; - } else if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { - cmethod_name += 79; - explicitly_implemented = true; - } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { - cmethod_name += 80; + if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible + // but, they all prefix the qualified name of the interface first, so we'll check for that and + // skip the prefix before trying to resolve the method. + + if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { + cmethod_name += 79; + explicitly_implemented = true; + } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { + cmethod_name += 80; + explicitly_implemented = true; + } + } else if (strncmp(cmethod_name + 45, "Numerics.Vector,T>.", 22) == 0) { + cmethod_name += 67; explicitly_implemented = true; } } diff --git a/src/mono/mono/mini/type-checking.c b/src/mono/mono/mini/type-checking.c index a847cb8e720d27..6f453f88610ff4 100644 --- a/src/mono/mono/mini/type-checking.c +++ b/src/mono/mono/mini/type-checking.c @@ -40,6 +40,7 @@ emit_cached_check_args (MonoCompile *cfg, MonoInst *obj, MonoClass *klass, int c } else { int idx; + g_assert (klass); EMIT_NEW_CLASSCONST (cfg, args [1], klass); /* klass */ idx = get_castclass_cache_idx (cfg); /* inline cache*/ diff --git a/src/mono/mono/minipal/CMakeLists.txt b/src/mono/mono/minipal/CMakeLists.txt new file mode 100644 index 00000000000000..2b862bd623b3e3 --- /dev/null +++ b/src/mono/mono/minipal/CMakeLists.txt @@ -0,0 +1,10 @@ + +if (HOST_WIN32) + add_definitions(-DHOST_WINDOWS) +endif (HOST_WIN32) + +if (HOST_DARWIN OR HOST_ANDROID OR HOST_LINUX OR HOST_FREEBSD OR HOST_SOLARIS OR HOST_HAIKU OR HOST_BROWSER) + add_definitions(-DHOST_UNIX) +endif (HOST_DARWIN OR HOST_ANDROID OR HOST_LINUX OR HOST_FREEBSD OR HOST_SOLARIS OR HOST_HAIKU OR HOST_BROWSER) + +add_subdirectory(${CLR_SRC_NATIVE_DIR}/minipal minipal) diff --git a/src/mono/mono/utils/mono-stack-unwinding.h b/src/mono/mono/utils/mono-stack-unwinding.h index 66931c6defc040..895c7934ecd69b 100644 --- a/src/mono/mono/utils/mono-stack-unwinding.h +++ b/src/mono/mono/utils/mono-stack-unwinding.h @@ -48,8 +48,8 @@ typedef enum { * callback. */ MONO_UNWIND_REG_LOCATIONS = 0x4, + MONO_UNWIND_SIGNAL_SAFE = 0x8, MONO_UNWIND_DEFAULT = MONO_UNWIND_LOOKUP_ACTUAL_METHOD, - MONO_UNWIND_SIGNAL_SAFE = MONO_UNWIND_NONE, MONO_UNWIND_LOOKUP_ALL = MONO_UNWIND_LOOKUP_IL_OFFSET | MONO_UNWIND_LOOKUP_ACTUAL_METHOD, } MonoUnwindOptions; diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index eb3e1b93bb2fb3..0b35b8a5472973 100644 --- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -171,6 +171,7 @@ Copyright (c) .NET Foundation. All rights reserved. <_TargetingNET90OrLater>false <_TargetingNET80OrLater Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '8.0'))">true <_TargetingNET90OrLater Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '9.0'))">true + <_TargetingNET100OrLater Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '10.0'))">true <_BlazorEnableTimeZoneSupport>$(BlazorEnableTimeZoneSupport) <_BlazorEnableTimeZoneSupport Condition="'$(_BlazorEnableTimeZoneSupport)' == ''">true @@ -193,7 +194,11 @@ Copyright (c) .NET Foundation. All rights reserved. <_WasmFingerprintDotnetJs>$(WasmFingerprintDotnetJs) <_WasmFingerprintDotnetJs Condition="'$(_WasmFingerprintDotnetJs)' == ''">$(WriteImportMapToHtml) <_WasmFingerprintDotnetJs Condition="'$(_WasmFingerprintDotnetJs)' == ''">false + <_WasmFingerprintBootConfig>$(WasmFingerprintBootConfig) + <_WasmFingerprintBootConfig Condition="'$(_WasmFingerprintBootConfig)' == ''">$(WriteImportMapToHtml) + <_WasmFingerprintBootConfig Condition="'$(_WasmFingerprintBootConfig)' == ''">false <_WasmBootConfigFileName>$(WasmBootConfigFileName) + <_WasmBootConfigFileName Condition="'$(_WasmBootConfigFileName)' == '' and '$(_TargetingNET100OrLater)' == 'true'">dotnet.boot.js <_WasmBootConfigFileName Condition="'$(_WasmBootConfigFileName)' == ''">blazor.boot.json <_WasmPublishBootConfigFileName>publish.$(_WasmBootConfigFileName) @@ -316,9 +321,9 @@ Copyright (c) .NET Foundation. All rights reserved. - + - + @@ -378,6 +383,7 @@ Copyright (c) .NET Foundation. All rights reserved. Jiterpreter="$(_BlazorWebAssemblyJiterpreter)" RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)" Extensions="@(WasmBootConfigExtension)" + EnvVariables="@(WasmEnvironmentVariable)" TargetFrameworkVersion="$(TargetFrameworkVersion)" ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)" ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" @@ -390,18 +396,18 @@ Copyright (c) .NET Foundation. All rights reserved. - - <_WasmBuildBootJsonPath>$(IntermediateOutputPath)$(_WasmBootConfigFileName) - - - <_BuildWasmBootJson + <_WasmBuildBootConfigCandidate Include="$(_WasmBuildBootJsonPath)" RelativePath="_framework/$(_WasmBootConfigFileName)" /> + + <_WasmBuildBootConfigFingerprintPatterns Include="WasmBootConfigFiles" Pattern="*%(_WasmBuildBootConfigCandidate.Extension)" Expression="#[.{fingerprint}]!" /> - + - + @@ -586,14 +592,19 @@ Copyright (c) .NET Foundation. All rights reserved. + - <_PublishWasmBootJson + <_WasmPublishBootConfigCandidate Include="$(IntermediateOutputPath)$(_WasmPublishBootConfigFileName)" RelativePath="_framework/$(_WasmBootConfigFileName)" /> + + <_WasmPublishBootConfigFingerprintPatterns Include="WasmBootConfigFiles" Pattern="*%(_WasmPublishBootConfigCandidate.Extension)" Expression="#[.{fingerprint}]!" /> - + @@ -671,6 +682,7 @@ Copyright (c) .NET Foundation. All rights reserved. StartupMemoryCache="$(_BlazorWebAssemblyStartupMemoryCache)" Jiterpreter="$(_BlazorWebAssemblyJiterpreter)" RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)" + EnvVariables="@(WasmEnvironmentVariable)" Extensions="@(WasmBootConfigExtension)" TargetFrameworkVersion="$(TargetFrameworkVersion)" ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)" diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WasmFeatures.props b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WasmFeatures.props index 289b8c503a39fc..84b0ab729466b0 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WasmFeatures.props +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WasmFeatures.props @@ -8,5 +8,6 @@ false false false + true diff --git a/src/mono/sample/wasm/Directory.Build.targets b/src/mono/sample/wasm/Directory.Build.targets index 18e1b711da80fa..ed1372de5c9103 100644 --- a/src/mono/sample/wasm/Directory.Build.targets +++ b/src/mono/sample/wasm/Directory.Build.targets @@ -1,5 +1,8 @@ + + true + @@ -18,9 +21,23 @@ <_ServeMimeTypes>$(_ServeMimeTypes) --mime .cjs=text/javascript <_ServeMimeTypes>$(_ServeMimeTypes) --mime .js=text/javascript <_ServeMimeTypes>$(_ServeMimeTypes) --mime .webcil=application/octet-stream - true + + + + + + + + + + + + + + + $(TargetFileName) - - - - - - - - + - + - - - - <_WasmMainJSFileName>$([System.IO.Path]::GetFileName('$(WasmMainJSPath)')) - + + + + + + diff --git a/src/mono/sample/wasm/browser-advanced/index.html b/src/mono/sample/wasm/browser-advanced/index.html index 24d51ea29672d6..86647178c9a28a 100644 --- a/src/mono/sample/wasm/browser-advanced/index.html +++ b/src/mono/sample/wasm/browser-advanced/index.html @@ -10,7 +10,7 @@ - + diff --git a/src/mono/sample/wasm/browser-advanced/main.js b/src/mono/sample/wasm/browser-advanced/main.js index 94598646652fc7..0bb31d8648cb07 100644 --- a/src/mono/sample/wasm/browser-advanced/main.js +++ b/src/mono/sample/wasm/browser-advanced/main.js @@ -46,7 +46,7 @@ try { } }) .withModuleConfig({ - configSrc: "./blazor.boot.json", + configSrc: "./dotnet.boot.js", onConfigLoaded: (config) => { // This is called during emscripten `dotnet.wasm` instantiation, after we fetched config. console.log('user code Module.onConfigLoaded'); diff --git a/src/mono/sample/wasm/browser-bench/appstart-frame.html b/src/mono/sample/wasm/browser-bench/appstart-frame.html index e7d6d03a08f6b7..196f12fa1cef69 100644 --- a/src/mono/sample/wasm/browser-bench/appstart-frame.html +++ b/src/mono/sample/wasm/browser-bench/appstart-frame.html @@ -9,7 +9,7 @@ - + diff --git a/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj b/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj index 365ba7276cb0b9..b04e2750836feb 100644 --- a/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj +++ b/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj @@ -1,5 +1,8 @@ + + false + diff --git a/src/mono/wasm/Wasm.Build.Tests/DiagnosticsTests.cs b/src/mono/wasm/Wasm.Build.Tests/DiagnosticsTests.cs index 2815e2bd1efa31..a42e358260e618 100644 --- a/src/mono/wasm/Wasm.Build.Tests/DiagnosticsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/DiagnosticsTests.cs @@ -21,15 +21,15 @@ public DiagnosticsTests(ITestOutputHelper output, SharedBuildPerTestClassFixture } [Fact] - public async Task RunSimpleAppWithProfiler() + public async Task RunSimpleAppWithLogProfiler() { Configuration config = Configuration.Release; - ProjectInfo info = CopyTestAsset(config, false, TestAsset.WasmBasicTestApp, "ProfilerTest"); - // are are linking all 3 profilers, but below we only initialize log profiler and test it - string extraArgs = $"-p:WasmProfilers=\"aot+browser+log\""; + ProjectInfo info = CopyTestAsset(config, false, TestAsset.WasmBasicTestApp, "LogProfilerTest"); + + string extraArgs = $"-p:WasmProfilers=\"log\""; BuildProject(info, config, new BuildOptions(ExtraMSBuildArgs: extraArgs, AssertAppBundle: false, WasmPerfTracing: true), isNativeBuild: true); - var result = await RunForBuildWithDotnetRun(new BrowserRunOptions(Configuration: config, TestScenario: "ProfilerTest")); + var result = await RunForBuildWithDotnetRun(new BrowserRunOptions(Configuration: config, TestScenario: "LogProfilerTest")); Regex regex = new Regex(@"Profile data of size (\d+) bytes"); var match = result.TestOutput .Select(line => regex.Match(line)) @@ -41,4 +41,17 @@ public async Task RunSimpleAppWithProfiler() } Assert.True(fileSize >= 10 * 1024, $"Profile file size is less than 10KB. Actual size: {fileSize} bytes."); } + + [Fact] + public async Task RunSimpleAppWithBrowserProfiler() + { + Configuration config = Configuration.Release; + ProjectInfo info = CopyTestAsset(config, false, TestAsset.WasmBasicTestApp, "BrowserProfilerTest"); + + string extraArgs = $"-p:WasmProfilers=\"browser\""; + BuildProject(info, config, new BuildOptions(ExtraMSBuildArgs: extraArgs, AssertAppBundle: false, WasmPerfTracing: true), isNativeBuild: true); + + var result = await RunForBuildWithDotnetRun(new BrowserRunOptions(Configuration: config, TestScenario: "BrowserProfilerTest")); + Assert.Contains("performance.measure: TestMeaning", result.TestOutput); + } } diff --git a/src/mono/wasm/Wasm.Build.Tests/EnvVariablesTests.cs b/src/mono/wasm/Wasm.Build.Tests/EnvVariablesTests.cs new file mode 100644 index 00000000000000..0237ff544f78c9 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/EnvVariablesTests.cs @@ -0,0 +1,35 @@ +// 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.Linq; +using System.Threading.Tasks; +using System.Text.RegularExpressions; +using Xunit.Abstractions; +using Xunit; + +#nullable enable + +namespace Wasm.Build.Tests; + +public class EnvVariablesTests : WasmTemplateTestsBase +{ + public EnvVariablesTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [Fact] + public async Task RunSimpleAppEnvVariables() + { + Configuration config = Configuration.Release; + ProjectInfo info = CopyTestAsset(config, false, TestAsset.WasmBasicTestApp, "EnvVariablesTest"); + + BuildProject(info, config, new BuildOptions(AssertAppBundle: false), isNativeBuild: false); + + var result = await RunForBuildWithDotnetRun(new BrowserRunOptions(Configuration: config, TestScenario: "EnvVariablesTest")); + Assert.Contains("foo=bar", result.TestOutput); + Assert.Contains("baz=boo", result.TestOutput); + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs index bd7e983cbe2d95..92de2c1ca0cf72 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs @@ -80,28 +80,11 @@ public ProjectInfo CreateWasmTemplateProject( .ExecuteWithCapturedOutput($"new {template.ToString().ToLower()} {extraArgs}") .EnsureSuccessful(); - UpdateBootJsInHtmlFiles(); - string projectFilePath = Path.Combine(_projectDir, $"{projectName}.csproj"); UpdateProjectFile(projectFilePath, runAnalyzers, extraProperties, extraItems, insertAtEnd); return new ProjectInfo(projectName, projectFilePath, logPath, nugetDir); } - protected void UpdateBootJsInHtmlFiles() - { - foreach (var filePath in Directory.EnumerateFiles(_projectDir, "*.html", SearchOption.AllDirectories)) - { - UpdateBootJsInHtmlFile(filePath); - } - } - - protected void UpdateBootJsInHtmlFile(string filePath) - { - string fileContent = File.ReadAllText(filePath); - fileContent = StringReplaceWithAssert(fileContent, "", ""); - File.WriteAllText(filePath, fileContent); - } - protected ProjectInfo CopyTestAsset( Configuration config, bool aot, @@ -180,7 +163,11 @@ public virtual (string projectDir, string buildOutput) BuildProject( buildOptions.ExtraBuildEnvironmentVariables["TreatPreviousAsCurrent"] = "false"; - buildOptions = buildOptions with { ExtraMSBuildArgs = $"{buildOptions.ExtraMSBuildArgs} -p:WasmBootConfigFileName={buildOptions.BootConfigFileName}" }; + if (buildOptions.BootConfigFileName != "dotnet.boot.js") + { + // Omit implicit default + buildOptions = buildOptions with { ExtraMSBuildArgs = $"{buildOptions.ExtraMSBuildArgs} -p:WasmBootConfigFileName={buildOptions.BootConfigFileName}" }; + } (CommandResult res, string logFilePath) = BuildProjectWithoutAssert(configuration, info.ProjectName, buildOptions); diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs index 78341a12a93d49..dff25e88424d45 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs @@ -38,8 +38,6 @@ public async void RunOutOfAppBundle(Configuration config, bool aot) File.WriteAllText(indexHtmlPath, html); } - UpdateBootJsInHtmlFile(indexHtmlPath); - RunResult result = await RunForPublishWithWebServer(new BrowserRunOptions( config, TestScenario: "DotnetRun", diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index d37350ecf80ad8..84c034605a9ffd 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -92,7 +92,8 @@ - @(WasmFilesToIncludeInFileSystem) - Files to include in the vfs - @(WasmNativeAsset) - Native files to be added to `NativeAssets` in the bundle. - - @(WasmExtraConfig) - json elements to add to `_framework/blazor.boot.json` + - @(WasmEnvironmentVariable) - adds environment variables to `_framework/dotnet.boot.js` + - @(WasmExtraConfig) - json elements to add to `_framework/dotnet.boot.js` Eg. - Value attribute can have a number, bool, quoted string, or json string diff --git a/src/mono/wasm/features.md b/src/mono/wasm/features.md index ec00eff02e3d6a..b26eeec720e26c 100644 --- a/src/mono/wasm/features.md +++ b/src/mono/wasm/features.md @@ -55,6 +55,14 @@ Because web browsers do not expose direct access to sockets, we are unable to pr A prominent limitation is that your application must obey `Cross-Origin Resource Sharing` (CORS) rules in order to perform network requests successfully - see [CORS on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for more information. +Since Net 10 Preview 3 the HTTP client supports [streaming HTTP response](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams#consuming_a_fetch_as_a_stream) by default because all evergreen browsers now support it. + +This is a breaking change because the `response.Content.ReadAsStreamAsync()` is no longer `MemoryStream` but `BrowserHttpReadStream` which doesn't support synchronous operations like `Stream.Read(Span)`. If your code uses synchronous operations, you can disable the feature or copy the stream into `MemoryStream` yourself. + +If you need to disable it, you can use `false` or `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` env variable to do it for all HTTP requests. + +Or you can use `request.Options.Set(new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"), false);` for individual request. + ### WebSocket Applications using the [WebSocketClient](https://learn.microsoft.com/dotnet/api/system.net.websockets.clientwebsocket) managed API will require the browser to support the [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) API. @@ -166,7 +174,7 @@ Note: You can replace the location of `AppBundle` directory by `../ - `dotnet.js` - is the main entrypoint with the [JavaScript API](#JavaScript-API). It will load the rest of the runtime. - `dotnet.native.js` - is posix emulation layer provided by the [Emscripten](https://github.com/emscripten-core/emscripten) project - `dotnet.runtime.js` - is integration of the dotnet with the browser -- `blazor.boot.json` - contains list of all other assets and their integrity hash and also various configuration flags. +- `dotnet.boot.js` - contains list of all other assets and their integrity hash and also various configuration flags. - `dotnet.native.wasm` - is the compiled binary of the dotnet (Mono) runtime. - `System.Private.CoreLib.*` - is NET assembly with the core implementation of dotnet runtime and class library - `*.wasm` - are .NET assemblies stored in `WebCIL` format (for better compatibility with firewalls and virus scanners). @@ -202,7 +210,7 @@ Adding too many files into prefetch could be counterproductive. Please benchmark your startup performance on real target devices and with realistic network conditions. ```html - + ``` diff --git a/src/mono/wasm/testassets/BlazorBasicTestApp/App/wwwroot/index.html b/src/mono/wasm/testassets/BlazorBasicTestApp/App/wwwroot/index.html index e1fac0eedb6722..d9b7c48fe9435a 100644 --- a/src/mono/wasm/testassets/BlazorBasicTestApp/App/wwwroot/index.html +++ b/src/mono/wasm/testassets/BlazorBasicTestApp/App/wwwroot/index.html @@ -26,7 +26,6 @@ Reload 🗙 - diff --git a/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html b/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html index 6c357fe7bd0d7e..c18dfd76732e2c 100644 --- a/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html +++ b/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html @@ -7,7 +7,6 @@ tmp - diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/BrowserProfilerTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/BrowserProfilerTest.cs new file mode 100644 index 00000000000000..bae98205072ade --- /dev/null +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/BrowserProfilerTest.cs @@ -0,0 +1,19 @@ +// 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 System.Runtime.InteropServices.JavaScript; + +public partial class BrowserProfilerTest +{ + [JSExport] + public static int TestMeaning() + { + for(int i=0; i<100; i++){ + var r = new int[1000]; + } + + return 42; + } +} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/EnvVariablesTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/EnvVariablesTest.cs new file mode 100644 index 00000000000000..32cf52b1268a66 --- /dev/null +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/EnvVariablesTest.cs @@ -0,0 +1,21 @@ +// 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 System.Runtime.InteropServices.JavaScript; + +public partial class EnvVariablesTest +{ + [JSExport] + public static int DumpVariables() + { + // enumerate all environment variables + foreach (string key in Environment.GetEnvironmentVariables().Keys) + { + Console.WriteLine($"{key}={Environment.GetEnvironmentVariable(key)}"); + } + + return 42; + } +} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/ProfilerTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/LogProfilerTest.cs similarity index 85% rename from src/mono/wasm/testassets/WasmBasicTestApp/App/ProfilerTest.cs rename to src/mono/wasm/testassets/WasmBasicTestApp/App/LogProfilerTest.cs index ef3fa75dc92b19..4271800d6e2440 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/ProfilerTest.cs +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/LogProfilerTest.cs @@ -5,11 +5,11 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices.JavaScript; -public partial class ProfilerTest +public partial class LogProfilerTest { [JSExport] [MethodImpl(MethodImplOptions.NoInlining)] - public static void TakeHeapshot() { } + public static void TakeHeapshot() { } [JSExport] public static int TestMeaning() diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj b/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj index a6a75bbab5efce..a28793a3a7a1e0 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj @@ -19,6 +19,7 @@ + diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html index a204c2c76ab051..f0429391614fb3 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html @@ -7,7 +7,6 @@ WasmLazyLoading - diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index 500fcc22a3708d..b4a5b04d5af5c6 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -30,10 +30,12 @@ const logLevel = params.get("MONO_LOG_LEVEL"); const logMask = params.get("MONO_LOG_MASK"); if (logLevel !== null && logMask !== null) { dotnet.withDiagnosticTracing(true); // enable JavaScript tracing - dotnet.withConfig({environmentVariables: { - "MONO_LOG_LEVEL": logLevel, - "MONO_LOG_MASK": logMask, - }}); + dotnet.withConfig({ + environmentVariables: { + "MONO_LOG_LEVEL": logLevel, + "MONO_LOG_MASK": logMask, + } + }); } // Modify runtime start based on test case @@ -153,14 +155,19 @@ switch (testCase) { } }) break; - case "ProfilerTest": + case "LogProfilerTest": dotnet.withConfig({ logProfilerOptions: { - takeHeapshot: "ProfilerTest::TakeHeapshot", + takeHeapshot: "LogProfilerTest::TakeHeapshot", configuration: "log:alloc,output=output.mlpd" } }) break; + case "EnvVariablesTest": + dotnet.withEnvironmentVariable("foo", "bar"); + break; + case "BrowserProfilerTest": + break; case "OverrideBootConfigName": dotnet.withConfigSrc("boot.json"); break; @@ -249,14 +256,24 @@ try { exports.MemoryTest.Run(); exit(0); break; - case "ProfilerTest": + case "EnvVariablesTest": console.log("not ready yet") - const myExports = await getAssemblyExports(config.mainAssemblyName); - const testMeaning = myExports.ProfilerTest.TestMeaning; - const takeHeapshot = myExports.ProfilerTest.TakeHeapshot; + const myExportsEnv = await getAssemblyExports(config.mainAssemblyName); + const dumpVariables = myExportsEnv.EnvVariablesTest.DumpVariables; console.log("ready"); - dotnet.run(); + const retVars = dumpVariables(); + document.getElementById("out").innerHTML = retVars; + console.debug(`ret: ${retVars}`); + + exit(retVars == 42 ? 0 : 1); + break; + case "LogProfilerTest": + console.log("not ready yet") + const myExports = await getAssemblyExports(config.mainAssemblyName); + const testMeaning = myExports.LogProfilerTest.TestMeaning; + const takeHeapshot = myExports.LogProfilerTest.TakeHeapshot; + console.log("ready"); const ret = testMeaning(); document.getElementById("out").innerHTML = ret; @@ -267,6 +284,24 @@ try { let exit_code = ret == 42 ? 0 : 1; exit(exit_code); + break; + case "BrowserProfilerTest": + console.log("not ready yet") + const origMeasure = globalThis.performance.measure + globalThis.performance.measure = (method, options) => { + console.log(`performance.measure: ${method}`); + origMeasure(method, options); + }; + const myExportsB = await getAssemblyExports(config.mainAssemblyName); + const testMeaningB = myExportsB.BrowserProfilerTest.TestMeaning; + console.log("ready"); + + const retB = testMeaningB(); + document.getElementById("out").innerHTML = retB; + console.debug(`ret: ${retB}`); + + exit(retB == 42 ? 0 : 1); + break; case "OverrideBootConfigName": testOutput("ConfigSrc: " + Module.configSrc); diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html index ec9e52f5fa58fe..f911682fdf48bb 100644 --- a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html @@ -16,7 +16,6 @@ Reload 🗙 - diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html index 6b2d7b87691ac4..86bc345d2e23ad 100644 --- a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html @@ -7,7 +7,6 @@ WasmBrowser - diff --git a/src/native/corehost/fxr/framework_info.cpp b/src/native/corehost/fxr/framework_info.cpp index 8a3dc0802a3433..631fdb4f1516d4 100644 --- a/src/native/corehost/fxr/framework_info.cpp +++ b/src/native/corehost/fxr/framework_info.cpp @@ -39,7 +39,7 @@ bool compare_by_name_and_version(const framework_info &a, const framework_info & std::vector* framework_infos) { std::vector hive_dir; - get_framework_and_sdk_locations(own_dir, disable_multilevel_lookup, &hive_dir); + get_framework_locations(own_dir, disable_multilevel_lookup, &hive_dir); int32_t hive_depth = 0; diff --git a/src/native/corehost/fxr/fx_muxer.cpp b/src/native/corehost/fxr/fx_muxer.cpp index 642e26e923482f..e40fe66ca0f342 100644 --- a/src/native/corehost/fxr/fx_muxer.cpp +++ b/src/native/corehost/fxr/fx_muxer.cpp @@ -1041,7 +1041,8 @@ int fx_muxer_t::handle_cli( // sdk_resolver resolver = sdk_resolver::from_nearest_global_file(); - auto sdk_dotnet = resolver.resolve(host_info.dotnet_root, false /*print_errors*/); + pal::string_t sdk_root; + pal::string_t sdk_dotnet = resolver.resolve(host_info.dotnet_root, false /*print_errors*/, &sdk_root); if (sdk_dotnet.empty()) { assert(argc > 1); @@ -1073,6 +1074,11 @@ int fx_muxer_t::handle_cli( append_path(&sdk_dotnet, SDK_DOTNET_DLL); assert(pal::file_exists(sdk_dotnet)); + // Use the root path from the resolved SDK to run the SDK dll + host_startup_info_t host_info_local = pal::strcmp(sdk_root.c_str(), host_info.dotnet_root.c_str()) == 0 + ? host_info + : host_startup_info_t(host_info.host_path.c_str(), sdk_root.c_str(), host_info.app_path.c_str()); + // Transform dotnet [command] [args] -> dotnet dotnet.dll [command] [args] std::vector new_argv; @@ -1086,13 +1092,13 @@ int fx_muxer_t::handle_cli( int new_argoff; pal::string_t sdk_app_candidate; opt_map_t opts; - int result = command_line::parse_args_for_sdk_command(host_info, (int32_t)new_argv.size(), new_argv.data(), &new_argoff, sdk_app_candidate, opts); + int result = command_line::parse_args_for_sdk_command(host_info_local, (int32_t)new_argv.size(), new_argv.data(), &new_argoff, sdk_app_candidate, opts); if (!result) { // Transform dotnet [exec] [--additionalprobingpath path] [--depsfile file] [dll] [args] -> dotnet [dll] [args] result = handle_exec_host_command( pal::string_t{} /*host_command*/, - host_info, + host_info_local, sdk_app_candidate, opts, (int32_t)new_argv.size(), diff --git a/src/native/corehost/fxr/fx_resolver.cpp b/src/native/corehost/fxr/fx_resolver.cpp index c109fa257121c7..af970d7c56b204 100644 --- a/src/native/corehost/fxr/fx_resolver.cpp +++ b/src/native/corehost/fxr/fx_resolver.cpp @@ -203,7 +203,7 @@ namespace fx_ref.get_fx_name().c_str(), fx_ref.get_fx_version().c_str()); std::vector hive_dir; - get_framework_and_sdk_locations(dotnet_dir, disable_multilevel_lookup, &hive_dir); + get_framework_locations(dotnet_dir, disable_multilevel_lookup, &hive_dir); pal::string_t selected_fx_dir; pal::string_t selected_fx_version; diff --git a/src/native/corehost/fxr/sdk_info.cpp b/src/native/corehost/fxr/sdk_info.cpp index 9d68fbc8bc690c..af704021fdc2e6 100644 --- a/src/native/corehost/fxr/sdk_info.cpp +++ b/src/native/corehost/fxr/sdk_info.cpp @@ -4,6 +4,7 @@ #include #include "pal.h" #include "sdk_info.h" +#include "sdk_resolver.h" #include "trace.h" #include "utils.h" @@ -74,14 +75,13 @@ void sdk_info::enumerate_sdk_paths( } void sdk_info::get_all_sdk_infos( - const pal::string_t& own_dir, + const pal::string_t& dotnet_dir, std::vector* sdk_infos) { - std::vector hive_dir; - get_framework_and_sdk_locations(own_dir, /*disable_multilevel_lookup*/ true, &hive_dir); + sdk_resolver resolver = sdk_resolver::from_nearest_global_file(); + std::vector hive_dir = resolver.get_search_paths(dotnet_dir); int32_t hive_depth = 0; - for (pal::string_t dir : hive_dir) { trace::verbose(_X("Gathering SDK locations in [%s]"), dir.c_str()); @@ -103,10 +103,10 @@ void sdk_info::get_all_sdk_infos( std::sort(sdk_infos->begin(), sdk_infos->end(), compare_by_version_ascending_then_hive_depth_descending); } -/*static*/ bool sdk_info::print_all_sdks(const pal::string_t& own_dir, const pal::string_t& leading_whitespace) +/*static*/ bool sdk_info::print_all_sdks(const pal::string_t& dotnet_dir, const pal::string_t& leading_whitespace) { std::vector sdk_infos; - get_all_sdk_infos(own_dir, &sdk_infos); + get_all_sdk_infos(dotnet_dir, &sdk_infos); for (sdk_info info : sdk_infos) { trace::println(_X("%s%s [%s]"), leading_whitespace.c_str(), info.version.as_str().c_str(), info.base_path.c_str()); diff --git a/src/native/corehost/fxr/sdk_info.h b/src/native/corehost/fxr/sdk_info.h index 936209b6f688fc..b7e4d2f5a25469 100644 --- a/src/native/corehost/fxr/sdk_info.h +++ b/src/native/corehost/fxr/sdk_info.h @@ -22,10 +22,10 @@ struct sdk_info std::function callback); static void get_all_sdk_infos( - const pal::string_t& own_dir, + const pal::string_t& dotnet_dir, std::vector* sdk_infos); - static bool print_all_sdks(const pal::string_t& own_dir, const pal::string_t& leading_whitespace); + static bool print_all_sdks(const pal::string_t& dotnet_dir, const pal::string_t& leading_whitespace); pal::string_t base_path; pal::string_t full_path; diff --git a/src/native/corehost/fxr/sdk_resolver.cpp b/src/native/corehost/fxr/sdk_resolver.cpp index 5f512982e5266a..417a6463e979ed 100644 --- a/src/native/corehost/fxr/sdk_resolver.cpp +++ b/src/native/corehost/fxr/sdk_resolver.cpp @@ -28,15 +28,16 @@ namespace }; } -sdk_resolver::sdk_resolver(bool allow_prerelease) : - sdk_resolver({}, sdk_roll_forward_policy::latest_major, allow_prerelease) +sdk_resolver::sdk_resolver(bool allow_prerelease) + : sdk_resolver({}, sdk_roll_forward_policy::latest_major, allow_prerelease) { } -sdk_resolver::sdk_resolver(fx_ver_t version, sdk_roll_forward_policy roll_forward, bool allow_prerelease) : - requested_version(std::move(version)), - roll_forward(roll_forward), - allow_prerelease(allow_prerelease) +sdk_resolver::sdk_resolver(fx_ver_t version, sdk_roll_forward_policy roll_forward, bool allow_prerelease) + : requested_version(std::move(version)) + , roll_forward(roll_forward) + , allow_prerelease(allow_prerelease) + , has_custom_paths(false) { } @@ -50,7 +51,7 @@ const fx_ver_t& sdk_resolver::get_requested_version() const return requested_version; } -pal::string_t sdk_resolver::resolve(const pal::string_t& dotnet_root, bool print_errors) const +pal::string_t sdk_resolver::resolve(const pal::string_t& dotnet_root, bool print_errors, pal::string_t* out_resolved_root) const { if (trace::is_enabled()) { @@ -60,20 +61,39 @@ pal::string_t sdk_resolver::resolve(const pal::string_t& dotnet_root, bool print requested.empty() ? _X("latest") : requested.c_str(), to_policy_name(roll_forward), allow_prerelease ? _X("true") : _X("false")); + if (has_custom_paths) + { + trace::verbose(_X(" paths = [")); + for (const pal::string_t& path : paths) + { + trace::verbose(_X(" %s"), path.c_str()); + } + trace::verbose(_X(" ]")); + } } pal::string_t resolved_sdk_path; fx_ver_t resolved_version; - vector locations; - get_framework_and_sdk_locations(dotnet_root, /*disable_multilevel_lookup*/ true, &locations); - + std::vector locations = get_search_paths(dotnet_root); for (auto&& dir : locations) { append_path(&dir, _X("sdk")); + if (!pal::fullpath(&dir, true)) + { + trace::verbose(_X("SDK path [%s] does not exist"), dir.c_str()); + continue; + } + // Search paths are in priority order. We take the first match and do not + // look in any remaining locations. if (resolve_sdk_path_and_version(dir, resolved_sdk_path, resolved_version)) { + if (out_resolved_root != nullptr) + { + out_resolved_root->assign(get_directory(dir)); + } + break; } } @@ -90,8 +110,50 @@ pal::string_t sdk_resolver::resolve(const pal::string_t& dotnet_root, bool print return {}; } +std::vector sdk_resolver::get_search_paths(const pal::string_t& dotnet_root) const +{ + std::vector locations; + if (!has_custom_paths) + { + if (!dotnet_root.empty()) + locations.push_back(dotnet_root); + } + else + { + // Use custom paths specified in the global.json + pal::string_t json_dir = get_directory(global_file); + for (const pal::string_t& path : paths) + { + if (path == _X("$host$")) + { + locations.push_back(dotnet_root); + } + else if (pal::is_path_rooted(path)) + { + locations.push_back(path); + } + else + { + // Path is relative to the global.json + pal::string_t full_path = json_dir; + append_path(&full_path, path.c_str()); + locations.push_back(full_path); + } + } + } + + return locations; +} + void sdk_resolver::print_resolution_error(const pal::string_t& dotnet_root, const pal::char_t *main_error_prefix) const { + if (!error_message.empty()) + { + // Custom error message specified in the global.json + trace::error(_X("%s%s"), main_error_prefix, error_message.c_str()); + return; + } + bool sdk_exists = false; const pal::char_t *no_sdk_message = _X("No .NET SDKs were found."); if (!requested_version.is_empty()) @@ -106,7 +168,17 @@ void sdk_resolver::print_resolution_error(const pal::string_t& dotnet_root, cons bool has_global_file = !global_file.empty(); if (has_global_file) + { trace::error(_X("global.json file: %s"), global_file.c_str()); + if (has_custom_paths) + { + trace::error(_X(" Search paths:")); + for (const pal::string_t& path : paths) + { + trace::error(_X(" %s"), path.c_str()); + } + } + } trace::error(_X("\nInstalled SDKs:")); sdk_exists = sdk_info::print_all_sdks(dotnet_root, _X("")); @@ -126,6 +198,10 @@ void sdk_resolver::print_resolution_error(const pal::string_t& dotnet_root, cons else { trace::error(_X("%s%s"), main_error_prefix, no_sdk_message); + if (has_custom_paths && paths.empty()) + { + trace::error(_X("%sEmpty search paths specified in global.json file: %s"), main_error_prefix, global_file.c_str()); + } } if (!sdk_exists) @@ -353,6 +429,43 @@ bool sdk_resolver::parse_global_file(pal::string_t global_file_path) } } + const auto& paths_value = sdk->value.FindMember(_X("paths")); + if (paths_value != sdk->value.MemberEnd() && !paths_value->value.IsNull()) + { + if (!paths_value->value.IsArray()) + { + trace::warning(_X("Expected an array for 'sdk/paths' value in [%s]"), global_file_path.c_str()); + return false; + } + + has_custom_paths = true; + const auto& paths_array = paths_value->value.GetArray(); + paths.reserve(paths_array.Size()); + for (uint32_t i = 0; i < paths_array.Size(); ++i) + { + const auto& path = paths_array[i]; + if (!path.IsString()) + { + trace::warning(_X("Ignoring non-string 'sdk/paths[%d]' value in [%s]"), global_file_path.c_str()); + continue; + } + + paths.push_back(path.GetString()); + } + } + + const auto& error_message_value = sdk->value.FindMember(_X("errorMessage")); + if (error_message_value != sdk->value.MemberEnd() && !error_message_value->value.IsNull()) + { + if (!error_message_value->value.IsString()) + { + trace::warning(_X("Expected a string for the 'sdk/errorMessage' value in [%s]"), global_file_path.c_str()); + return false; + } + + error_message = error_message_value->value.GetString(); + } + global_file = std::move(global_file_path); return true; } @@ -481,13 +594,11 @@ bool sdk_resolver::resolve_sdk_path_and_version(const pal::string_t& dir, pal::s } } + // No match - we did not find an exact match and roll forward is disabled if (roll_forward == sdk_roll_forward_policy::disable) - { - // Not yet fully resolved return false; - } - bool changed = false; + bool found = false; pal::string_t resolved_version_str = resolved_version.is_empty() ? pal::string_t{} : resolved_version.as_str(); sdk_info::enumerate_sdk_paths( dir, @@ -519,17 +630,16 @@ bool sdk_resolver::resolve_sdk_path_and_version(const pal::string_t& dir, pal::s resolved_version_str.empty() ? _X("none") : resolved_version_str.c_str() ); - changed = true; + found = true; resolved_version = version; resolved_version_str = std::move(version_str); }); - if (changed) + if (found) { sdk_path = dir; append_path(&sdk_path, resolved_version_str.c_str()); } - // Not yet fully resolved - return false; + return found; } diff --git a/src/native/corehost/fxr/sdk_resolver.h b/src/native/corehost/fxr/sdk_resolver.h index 064f22b4567cf8..d8724acd03b5b4 100644 --- a/src/native/corehost/fxr/sdk_resolver.h +++ b/src/native/corehost/fxr/sdk_resolver.h @@ -41,7 +41,9 @@ class sdk_resolver const fx_ver_t& get_requested_version() const; - pal::string_t resolve(const pal::string_t& dotnet_root, bool print_errors = true) const; + pal::string_t resolve(const pal::string_t& dotnet_root, bool print_errors = true, pal::string_t* out_resolved_root = nullptr) const; + + std::vector get_search_paths(const pal::string_t& dotnet_root) const; void print_resolution_error(const pal::string_t& dotnet_root, const pal::char_t *prefix) const; @@ -60,10 +62,15 @@ class sdk_resolver bool is_better_match(const fx_ver_t& current, const fx_ver_t& previous) const; bool exact_match_preferred() const; bool is_policy_use_latest() const; + + // Returns true and sets sdk_path/resolved_version if a matching SDK was found bool resolve_sdk_path_and_version(const pal::string_t& dir, pal::string_t& sdk_path, fx_ver_t& resolved_version) const; pal::string_t global_file; fx_ver_t requested_version; sdk_roll_forward_policy roll_forward; bool allow_prerelease; + bool has_custom_paths; + std::vector paths; + pal::string_t error_message; }; diff --git a/src/native/corehost/hostmisc/utils.cpp b/src/native/corehost/hostmisc/utils.cpp index 7326f3b8b8ae17..dd351434a2da9a 100644 --- a/src/native/corehost/hostmisc/utils.cpp +++ b/src/native/corehost/hostmisc/utils.cpp @@ -277,7 +277,7 @@ bool multilevel_lookup_enabled() return multilevel_lookup; } -void get_framework_and_sdk_locations(const pal::string_t& dotnet_dir, const bool disable_multilevel_lookup, std::vector* locations) +void get_framework_locations(const pal::string_t& dotnet_dir, const bool disable_multilevel_lookup, std::vector* locations) { bool multilevel_lookup = disable_multilevel_lookup ? false : multilevel_lookup_enabled(); diff --git a/src/native/corehost/hostmisc/utils.h b/src/native/corehost/hostmisc/utils.h index 52c6754d290a7f..124eb1100775fe 100644 --- a/src/native/corehost/hostmisc/utils.h +++ b/src/native/corehost/hostmisc/utils.h @@ -91,7 +91,7 @@ pal::string_t get_runtime_id(); bool try_get_runtime_id_from_env(pal::string_t& out_rid); bool multilevel_lookup_enabled(); -void get_framework_and_sdk_locations(const pal::string_t& dotnet_dir, const bool disable_multilevel_lookup, std::vector* locations); +void get_framework_locations(const pal::string_t& dotnet_dir, const bool disable_multilevel_lookup, std::vector* locations); bool get_file_path_from_env(const pal::char_t* env_key, pal::string_t* recv); size_t index_of_non_numeric(const pal::string_t& str, size_t i); bool try_stou(const pal::string_t& str, unsigned* num); diff --git a/src/native/external/llvm-libunwind-version.txt b/src/native/external/llvm-libunwind-version.txt index f833dd0c83fb59..118dfa206d0323 100644 --- a/src/native/external/llvm-libunwind-version.txt +++ b/src/native/external/llvm-libunwind-version.txt @@ -1,5 +1,4 @@ -v18.1.5 -https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.5 - -Apply https://github.com/dotnet/runtime/commit/a53805790a49f5bf52776dc81c1c83ec7f21ebce +v20.1.0 +https://github.com/llvm/llvm-project/releases/tag/llvmorg-20.1.0 +Apply https://github.com/dotnet/runtime/commit/d03d1ba7835fdf9e2a6bb537d49fb5ff6584697b diff --git a/src/native/external/llvm-libunwind/CMakeLists.txt b/src/native/external/llvm-libunwind/CMakeLists.txt index 806d5a783ec39c..3c8499fd334649 100644 --- a/src/native/external/llvm-libunwind/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/CMakeLists.txt @@ -3,6 +3,7 @@ #=============================================================================== cmake_minimum_required(VERSION 3.20.0) +set(LLVM_SUBPROJECT_TITLE "libunwind") set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") @@ -23,6 +24,11 @@ set(LIBUNWIND_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH include(GNUInstallDirs) include(CheckSymbolExists) +if (MSVC) + message(FATAL_ERROR "Libunwind doesn't build for MSVC targets, and that is almost certainly not what you want to do " + "anyway since libunwind is tied to the Itanium C++ ABI, and MSVC targets must use the MS C++ ABI.") +endif() + #=============================================================================== # Setup CMake Options #=============================================================================== @@ -30,12 +36,8 @@ include(CMakeDependentOption) include(HandleCompilerRT) # Define options. -option(LIBUNWIND_BUILD_32_BITS "Build 32 bit multilib libunwind. This option is not supported anymore when building the runtimes. Please specify a full triple instead." ${LLVM_BUILD_32_BITS}) -if (LIBUNWIND_BUILD_32_BITS) - message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS is not supported anymore when building the runtimes, please specify a full triple instead.") -endif() - option(LIBUNWIND_ENABLE_CET "Build libunwind with CET enabled." OFF) +option(LIBUNWIND_ENABLE_GCS "Build libunwind with GCS enabled." OFF) option(LIBUNWIND_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON) option(LIBUNWIND_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) option(LIBUNWIND_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) @@ -64,8 +66,18 @@ cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY "Install the shared libunwind library." ON "LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF) +set(LIBUNWIND_LIBRARY_VERSION "1.0" CACHE STRING + "Version of libunwind. This will be reflected in the name of the shared library produced. + For example, -DLIBUNWIND_LIBRARY_VERSION=x.y will result in the library being named + libunwind.x.y.dylib, along with the usual symlinks pointing to that. On Apple platforms, + this also controls the linker's 'current_version' property.") + if(MINGW) - set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-mingw.cfg.in") + if (LIBUNWIND_ENABLE_SHARED) + set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-shared-mingw.cfg.in") + else() + set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-static-mingw.cfg.in") + endif() elseif (LIBUNWIND_ENABLE_SHARED) set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-shared.cfg.in") else() @@ -129,13 +141,14 @@ set(LIBUNWIND_SHARED_OUTPUT_NAME "unwind" CACHE STRING "Output name for the shar set(LIBUNWIND_STATIC_OUTPUT_NAME "unwind" CACHE STRING "Output name for the static libunwind runtime library.") if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING - "Path where built libunwind libraries should be installed.") - if(LIBCXX_LIBDIR_SUBDIR) - string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) - string(APPEND LIBUNWIND_INSTALL_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) + set(LIBUNWIND_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE}) + if(LIBUNWIND_LIBDIR_SUBDIR) + string(APPEND LIBUNWIND_TARGET_SUBDIR /${LIBUNWIND_LIBDIR_SUBDIR}) endif() + set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LIBUNWIND_TARGET_SUBDIR}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LIBUNWIND_TARGET_SUBDIR} CACHE STRING + "Path where built libunwind libraries should be installed.") + unset(LIBUNWIND_TARGET_SUBDIR) else() if(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) @@ -154,8 +167,7 @@ set(LIBUNWIND_C_FLAGS "") set(LIBUNWIND_CXX_FLAGS "") set(LIBUNWIND_COMPILE_FLAGS "") set(LIBUNWIND_LINK_FLAGS "") -set(LIBUNWIND_ADDITIONAL_COMPILE_FLAGS "" CACHE STRING - "Additional Compile only flags which can be provided in cache") +set(LIBUNWIND_ADDITIONAL_COMPILE_FLAGS "" CACHE STRING "See documentation for LIBCXX_ADDITIONAL_COMPILE_FLAGS") set(LIBUNWIND_ADDITIONAL_LIBRARIES "" CACHE STRING "Additional libraries libunwind is linked to which can be provided in cache") @@ -186,6 +198,13 @@ if (LIBUNWIND_ENABLE_CET) endif() endif() +if (LIBUNWIND_ENABLE_GCS) + add_compile_flags_if_supported(-mbranch-protection=standard) + if (NOT CXX_SUPPORTS_MBRANCH_PROTECTION_EQ_STANDARD_FLAG) + message(SEND_ERROR "Compiler doesn't support GCS -mbranch-protection option!") + endif() +endif() + if (WIN32) # The headers lack matching dllexport attributes (_LIBUNWIND_EXPORT); # silence the warning instead of cluttering the headers (which aren't diff --git a/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst b/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst index 79166b4769c617..8b4f1207d4ba99 100644 --- a/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst +++ b/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst @@ -16,7 +16,7 @@ On Mac OS, the easiest way to get this library is to link with -lSystem. However if you want to build tip-of-trunk from here (getting the bleeding edge), read on. -The basic steps needed to build libc++ are: +The basic steps needed to build libunwind are: #. Checkout LLVM, libunwind, and related projects: @@ -50,23 +50,6 @@ The basic steps needed to build libc++ are: * ``make install-unwind`` --- Will install the libraries and the headers -It is sometimes beneficial to build outside of the LLVM tree. An out-of-tree -build would look like this: - -.. code-block:: bash - - $ cd where-you-want-libunwind-to-live - $ # Check out llvm, and libunwind - $ ``svn co https://llvm.org/svn/llvm-project/llvm/trunk llvm`` - $ ``svn co https://llvm.org/svn/llvm-project/libunwind/trunk libunwind`` - $ cd where-you-want-to-build - $ mkdir build && cd build - $ export CC=clang CXX=clang++ - $ cmake -DLLVM_PATH=path/to/llvm \ - path/to/libunwind - $ make - - .. _CMake Options: CMake Options diff --git a/src/native/external/llvm-libunwind/docs/index.rst b/src/native/external/llvm-libunwind/docs/index.rst index 7126d02abd2960..03542464011461 100644 --- a/src/native/external/llvm-libunwind/docs/index.rst +++ b/src/native/external/llvm-libunwind/docs/index.rst @@ -78,14 +78,13 @@ and `Getting started with LLVM `__. If you think you've found a bug in libunwind, please report it using the `LLVM bug tracker`_. If you're not sure, you -can ask for support on the `Runtimes forum`_ or on IRC. +can ask for support on the `Runtimes forum`_ or on Discord. Please use the tag "libunwind" for new threads. **Patches** -If you want to contribute a patch to libunwind, the best place for that is -`Phabricator `_. Please include [libunwind] in the subject and -add `cfe-commits` as a subscriber. Also make sure you are subscribed to the `cfe-commits mailing list`_. +If you want to contribute a patch to libunwind, please start by reading the LLVM +`documentation about contributing `__. **Discussion and Questions** diff --git a/src/native/external/llvm-libunwind/include/CMakeLists.txt b/src/native/external/llvm-libunwind/include/CMakeLists.txt index 51065d68afd4ea..6796d67a3354ff 100644 --- a/src/native/external/llvm-libunwind/include/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/include/CMakeLists.txt @@ -3,7 +3,6 @@ set(files libunwind.h libunwind.modulemap mach-o/compact_unwind_encoding.h - mach-o/compact_unwind_encoding.modulemap unwind_arm_ehabi.h unwind_itanium.h unwind.h diff --git a/src/native/external/llvm-libunwind/include/__libunwind_config.h b/src/native/external/llvm-libunwind/include/__libunwind_config.h index 39d48af424f5f6..35e5a73de03dc2 100644 --- a/src/native/external/llvm-libunwind/include/__libunwind_config.h +++ b/src/native/external/llvm-libunwind/include/__libunwind_config.h @@ -53,6 +53,9 @@ # else # define _LIBUNWIND_CURSOR_SIZE 66 # endif +# elif defined(__ILP32__) +# define _LIBUNWIND_CONTEXT_SIZE 21 +# define _LIBUNWIND_CURSOR_SIZE 28 # else # define _LIBUNWIND_CONTEXT_SIZE 38 # define _LIBUNWIND_CURSOR_SIZE 50 @@ -185,6 +188,10 @@ #endif #define _LIBUNWIND_HIGHEST_DWARF_REGISTER \ _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH +#elif defined(__wasm__) +// Unused +#define _LIBUNWIND_CONTEXT_SIZE 0 +#define _LIBUNWIND_CURSOR_SIZE 0 # else # error "Unsupported architecture." # endif diff --git a/src/native/external/llvm-libunwind/include/mach-o/compact_unwind_encoding.modulemap b/src/native/external/llvm-libunwind/include/mach-o/compact_unwind_encoding.modulemap deleted file mode 100644 index 6eae657d31b5c5..00000000000000 --- a/src/native/external/llvm-libunwind/include/mach-o/compact_unwind_encoding.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module MachO.compact_unwind_encoding [system] { - header "compact_unwind_encoding.h" - export * -} diff --git a/src/native/external/llvm-libunwind/src/CMakeLists.txt b/src/native/external/llvm-libunwind/src/CMakeLists.txt index 780430ba70ba60..ecbd019bb29ea8 100644 --- a/src/native/external/llvm-libunwind/src/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/src/CMakeLists.txt @@ -20,7 +20,12 @@ set(LIBUNWIND_C_SOURCES ) set_source_files_properties(${LIBUNWIND_C_SOURCES} PROPERTIES - COMPILE_FLAGS "-std=c99") + # We need to set `-fexceptions` here so that key + # unwinding functions, like + # _UNWIND_RaiseException, are not marked as + # `nounwind`, which breaks LTO builds of + # libunwind. See #56825 and #120657 for context. + COMPILE_FLAGS "-std=c99 -fexceptions") set(LIBUNWIND_ASM_SOURCES UnwindRegistersRestore.S @@ -105,15 +110,6 @@ if (LIBUNWIND_ENABLE_SHARED AND "on C++ ABI library is not supported.") endif() -if (APPLE) - add_compile_flags("-U__STRICT_ANSI__") - add_link_flags("-compatibility_version 1" "-install_name /usr/lib/libunwind.1.dylib") - - if (CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.6") - add_link_flags("-current_version ${LIBUNWIND_VERSION}" "/usr/lib/libSystem.B.dylib") - endif () -endif () - if (HAIKU) add_library_flags_if(LIBUNWIND_HAS_ROOT_LIB root) @@ -122,6 +118,22 @@ if (HAIKU) add_compile_flags("-D_DEFAULT_SOURCE") add_compile_flags("-DPT_GNU_EH_FRAME=PT_EH_FRAME") + + find_path(LIBUNWIND_HAIKU_PRIVATE_HEADERS + "commpage_defs.h" + PATHS ${CMAKE_SYSTEM_INCLUDE_PATH} + PATH_SUFFIXES "/private/system" + NO_DEFAULT_PATH + REQUIRED) + + include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}") + if (LIBUNWIND_TARGET_TRIPLE) + if (${LIBUNWIND_TARGET_TRIPLE} MATCHES "^x86_64") + include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}/arch/x86_64") + endif() + else() + include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}/arch/${CMAKE_SYSTEM_PROCESSOR}") + endif() endif () string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}") @@ -162,22 +174,23 @@ if (CMAKE_POSITION_INDEPENDENT_CODE OR NOT DEFINED CMAKE_POSITION_INDEPENDENT_CO set_target_properties(unwind_shared_objects PROPERTIES POSITION_INDEPENDENT_CODE ON) # must set manually because it's an object library endif() -if (LIBUNWIND_ENABLE_SHARED) - add_library(unwind_shared SHARED) - target_link_libraries(unwind_shared PUBLIC unwind_shared_objects) - set_target_properties(unwind_shared - PROPERTIES - LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}" - LINKER_LANGUAGE C - OUTPUT_NAME "${LIBUNWIND_SHARED_OUTPUT_NAME}" - VERSION "1.0" - SOVERSION "1" - ) +add_library(unwind_shared SHARED) +target_link_libraries(unwind_shared PUBLIC unwind_shared_objects) +set_target_properties(unwind_shared + PROPERTIES + EXCLUDE_FROM_ALL "$,FALSE,TRUE>" + LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}" + LINKER_LANGUAGE C + OUTPUT_NAME "${LIBUNWIND_SHARED_OUTPUT_NAME}" + VERSION "${LIBUNWIND_LIBRARY_VERSION}" + SOVERSION "1" +) +if (LIBUNWIND_ENABLE_SHARED) list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared") - if (LIBUNWIND_INSTALL_SHARED_LIBRARY) - list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared") - endif() +endif() +if (LIBUNWIND_INSTALL_SHARED_LIBRARY) + list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared") endif() # Build the static library. @@ -208,20 +221,21 @@ if(LIBUNWIND_HIDE_SYMBOLS) target_compile_definitions(unwind_static_objects PRIVATE _LIBUNWIND_HIDE_SYMBOLS) endif() -if (LIBUNWIND_ENABLE_STATIC) - add_library(unwind_static STATIC) - target_link_libraries(unwind_static PUBLIC unwind_static_objects) - set_target_properties(unwind_static - PROPERTIES - LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}" - LINKER_LANGUAGE C - OUTPUT_NAME "${LIBUNWIND_STATIC_OUTPUT_NAME}" - ) +add_library(unwind_static STATIC) +target_link_libraries(unwind_static PUBLIC unwind_static_objects) +set_target_properties(unwind_static + PROPERTIES + EXCLUDE_FROM_ALL "$,FALSE,TRUE>" + LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}" + LINKER_LANGUAGE C + OUTPUT_NAME "${LIBUNWIND_STATIC_OUTPUT_NAME}" +) +if (LIBUNWIND_ENABLE_STATIC) list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static") - if (LIBUNWIND_INSTALL_STATIC_LIBRARY) - list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static") - endif() +endif() +if (LIBUNWIND_INSTALL_STATIC_LIBRARY) + list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static") endif() # Add a meta-target for both libraries. diff --git a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp index a4e75755e5b4d2..32112839042b58 100644 --- a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp @@ -75,8 +75,10 @@ class DwarfInstructions { __builtin_unreachable(); } #if defined(_LIBUNWIND_TARGET_AARCH64) - static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa, - PrologInfo &prolog); + static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa, + PrologInfo &prolog); + static bool isReturnAddressSignedWithPC(A &addressSpace, R registers, + pint_t cfa, PrologInfo &prolog); #endif }; @@ -178,8 +180,9 @@ v128 DwarfInstructions::getSavedVectorRegister( } #if defined(_LIBUNWIND_TARGET_AARCH64) template -bool DwarfInstructions::getRA_SIGN_STATE(A &addressSpace, R registers, - pint_t cfa, PrologInfo &prolog) { +bool DwarfInstructions::isReturnAddressSigned(A &addressSpace, + R registers, pint_t cfa, + PrologInfo &prolog) { pint_t raSignState; pint_t location; auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; @@ -191,6 +194,23 @@ bool DwarfInstructions::getRA_SIGN_STATE(A &addressSpace, R registers, // Only bit[0] is meaningful. return raSignState & 0x01; } + +template +bool DwarfInstructions::isReturnAddressSignedWithPC(A &addressSpace, + R registers, + pint_t cfa, + PrologInfo &prolog) { + pint_t raSignState; + pint_t location; + auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; + if (regloc.location == CFI_Parser::kRegisterUnused) + raSignState = static_cast(regloc.value); + else + raSignState = getSavedRegister(addressSpace, registers, cfa, regloc, location); + + // Only bit[1] is meaningful. + return raSignState & 0x02; +} #endif template @@ -253,9 +273,10 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, pint_t returnAddress = 0; pint_t returnAddressLocation = 0; - const int lastReg = R::lastDwarfRegNum(); - assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= lastReg && - "register range too large"); + constexpr int lastReg = R::lastDwarfRegNum(); + static_assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= + lastReg, + "register range too large"); assert(lastReg >= (int)cieInfo.returnAddressRegister && "register range does not contain return address register"); for (int i = 0; i <= lastReg; ++i) { @@ -304,7 +325,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // restored. autia1716 is used instead of autia as autia1716 assembles // to a NOP on pre-v8.3a architectures. if ((R::getArch() == REGISTERS_ARM64) && - getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) && + isReturnAddressSigned(addressSpace, registers, cfa, prolog) && returnAddress != 0) { #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) return UNW_ECROSSRASIGNING; @@ -312,13 +333,29 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, register unsigned long long x17 __asm("x17") = returnAddress; register unsigned long long x16 __asm("x16") = cfa; - // These are the autia1716/autib1716 instructions. The hint instructions - // are used here as gcc does not assemble autia1716/autib1716 for pre - // armv8.3a targets. - if (cieInfo.addressesSignedWithBKey) - asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 - else - asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 + // We use the hint versions of the authentication instructions below to + // ensure they're assembled by the compiler even for targets with no + // FEAT_PAuth/FEAT_PAuth_LR support. + if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) { + register unsigned long long x15 __asm("x15") = + prolog.ptrAuthDiversifier; + if (cieInfo.addressesSignedWithBKey) { + asm("hint 0x27\n\t" // pacm + "hint 0xe" + : "+r"(x17) + : "r"(x16), "r"(x15)); // autib1716 + } else { + asm("hint 0x27\n\t" // pacm + "hint 0xc" + : "+r"(x17) + : "r"(x16), "r"(x15)); // autia1716 + } + } else { + if (cieInfo.addressesSignedWithBKey) + asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 + else + asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 + } returnAddress = x17; #endif } @@ -380,7 +417,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, #endif // Return address is address after call site instruction, so setting IP to - // that does simualates a return. + // that does simulates a return. newRegisters.setIP(returnAddress, returnAddressLocation); // Simulate the step by replacing the register set with the new ones. diff --git a/src/native/external/llvm-libunwind/src/DwarfParser.hpp b/src/native/external/llvm-libunwind/src/DwarfParser.hpp index 0407a3dc8615e9..a18b7397b996cb 100644 --- a/src/native/external/llvm-libunwind/src/DwarfParser.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfParser.hpp @@ -91,6 +91,9 @@ class CFI_Parser { int64_t cfaExpression; // CFA = expression uint32_t spExtraArgSize; RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; +#if defined(_LIBUNWIND_TARGET_AARCH64) + pint_t ptrAuthDiversifier; +#endif enum class InitializeTime { kLazy, kNormal }; // When saving registers, this data structure is lazily initialized. @@ -799,6 +802,24 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, } break; +#if defined(_LIBUNWIND_TARGET_AARCH64) + case DW_CFA_AARCH64_negate_ra_state_with_pc: { + int64_t value = + results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; + results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, + initialState); + // When calculating the value of the PC, it is assumed that the CFI + // instruction is placed before the signing instruction, however it is + // placed after. Because of this, we need to take into account the CFI + // instruction is one instruction call later than expected, and reduce + // the PC value by 4 bytes to compensate. + results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4; + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", + static_cast(results->ptrAuthDiversifier)); + } break; +#endif + #else (void)arch; #endif diff --git a/src/native/external/llvm-libunwind/src/Registers.hpp b/src/native/external/llvm-libunwind/src/Registers.hpp index 600c56bb92ff39..5daa35a3241885 100644 --- a/src/native/external/llvm-libunwind/src/Registers.hpp +++ b/src/native/external/llvm-libunwind/src/Registers.hpp @@ -1950,6 +1950,13 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { /// process. class _LIBUNWIND_HIDDEN Registers_arm64; extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); + +#if defined(_LIBUNWIND_USE_GCS) +extern "C" void *__libunwind_cet_get_jump_target() { + return reinterpret_cast(&__libunwind_Registers_arm64_jumpto); +} +#endif + class _LIBUNWIND_HIDDEN Registers_arm64 { public: Registers_arm64(); diff --git a/src/native/external/llvm-libunwind/src/Unwind-sjlj.c b/src/native/external/llvm-libunwind/src/Unwind-sjlj.c index 7e8faf098fe14b..a3551b328950d1 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-sjlj.c +++ b/src/native/external/llvm-libunwind/src/Unwind-sjlj.c @@ -408,7 +408,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) " - "=> 0x%" PRIuPTR, + "=> 0x%" PRIxPTR, (void *)context, ufc->lsda); return ufc->lsda; } diff --git a/src/native/external/llvm-libunwind/src/Unwind-wasm.c b/src/native/external/llvm-libunwind/src/Unwind-wasm.c index f7f39d38b59c18..b18b32c5d17847 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-wasm.c +++ b/src/native/external/llvm-libunwind/src/Unwind-wasm.c @@ -14,7 +14,7 @@ #include "config.h" -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ #include "unwind.h" #include @@ -120,4 +120,4 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) { return 0; } -#endif // defined(__USING_WASM_EXCEPTIONS__) +#endif // defined(__WASM_EXCEPTIONS__) diff --git a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp index 0920b2e5e0a795..1b1f032baf22fd 100644 --- a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp +++ b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 #endif @@ -231,8 +230,8 @@ void DwarfFDECache::iterateCacheEntries(void (*func)( } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - -#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) +#define arrayoffsetof(type, index, field) \ + (sizeof(type) * (index) + offsetof(type, field)) #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template class UnwindSectionHeader { @@ -475,7 +474,7 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor { } #endif -#if defined(_LIBUNWIND_USE_CET) +#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) virtual void *get_registers() { _LIBUNWIND_ABORT("get_registers not implemented"); } @@ -960,7 +959,7 @@ class UnwindCursor : public AbstractUnwindCursor{ virtual uintptr_t getDataRelBase(); #endif -#if defined(_LIBUNWIND_USE_CET) +#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) virtual void *get_registers() { return &_registers; } #endif @@ -1017,6 +1016,9 @@ class UnwindCursor : public AbstractUnwindCursor{ template int stepThroughSigReturn(Registers &) { return UNW_STEP_END; } +#elif defined(_LIBUNWIND_TARGET_HAIKU) + bool setInfoForSigReturn(); + int stepThroughSigReturn(); #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) @@ -1322,7 +1324,8 @@ class UnwindCursor : public AbstractUnwindCursor{ unw_proc_info_t _info; bool _unwindInfoMissing; bool _isSignalFrame; -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + defined(_LIBUNWIND_TARGET_HAIKU) bool _isSigReturn = false; #endif }; @@ -2059,7 +2062,6 @@ typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action, uint64_t, _Unwind_Exception *, struct _Unwind_Context *); -__attribute__((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0; } static __xlcxx_personality_v0_t *xlcPersonalityV0; @@ -2152,42 +2154,35 @@ bool UnwindCursor::getInfoFromTBTable(pint_t pc, R ®isters) { // function __xlcxx_personality_v0(), which is the personality for the state // table and is exported from libc++abi, is directly assigned as the // handler here. When a legacy XLC++ frame is encountered, the symbol - // is resolved dynamically using dlopen() to avoid hard dependency from - // libunwind on libc++abi. + // is resolved dynamically using dlopen() to avoid a hard dependency of + // libunwind on libc++abi in cases such as non-C++ applications. // Resolve the function pointer to the state table personality if it has - // not already. + // not already been done. if (xlcPersonalityV0 == NULL) { xlcPersonalityV0InitLock.lock(); if (xlcPersonalityV0 == NULL) { - // If libc++abi is statically linked in, symbol __xlcxx_personality_v0 - // has been resolved at the link time. - xlcPersonalityV0 = &__xlcxx_personality_v0; + // Resolve __xlcxx_personality_v0 using dlopen(). + const char *libcxxabi = "libc++abi.a(libc++abi.so.1)"; + void *libHandle; + // The AIX dlopen() sets errno to 0 when it is successful, which + // clobbers the value of errno from the user code. This is an AIX + // bug because according to POSIX it should not set errno to 0. To + // workaround before AIX fixes the bug, errno is saved and restored. + int saveErrno = errno; + libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW); + if (libHandle == NULL) { + _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno); + assert(0 && "dlopen() failed"); + } + xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>( + dlsym(libHandle, "__xlcxx_personality_v0")); if (xlcPersonalityV0 == NULL) { - // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0 - // using dlopen(). - const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)"; - void *libHandle; - // The AIX dlopen() sets errno to 0 when it is successful, which - // clobbers the value of errno from the user code. This is an AIX - // bug because according to POSIX it should not set errno to 0. To - // workaround before AIX fixes the bug, errno is saved and restored. - int saveErrno = errno; - libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW); - if (libHandle == NULL) { - _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", - errno); - assert(0 && "dlopen() failed"); - } - xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>( - dlsym(libHandle, "__xlcxx_personality_v0")); - if (xlcPersonalityV0 == NULL) { - _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno); - assert(0 && "dlsym() failed"); - } + _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno); dlclose(libHandle); - errno = saveErrno; + assert(0 && "dlsym() failed"); } + errno = saveErrno; } xlcPersonalityV0InitLock.unlock(); } @@ -2441,7 +2436,7 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, } // Reset LR in the current context. - newRegisters.setLR(NULL); + newRegisters.setLR(static_cast(NULL)); _LIBUNWIND_TRACE_UNWINDING( "Extract info from lastStack=%p, returnAddress=%p", @@ -2583,7 +2578,8 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, template void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + defined(_LIBUNWIND_TARGET_HAIKU) _isSigReturn = false; #endif @@ -2615,6 +2611,15 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { --pc; #endif +#if !(defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)) && \ + !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) + // In case of this is frame of signal handler, the IP saved in the signal + // handler points to first non-executed instruction, while FDE/CIE expects IP + // to be after the first non-executed instruction. + if (_isSignalFrame) + ++pc; +#endif + // Ask address space object to find unwind sections for this pc. UnwindInfoSections sects; if (_addressSpace.findUnwindSections(pc, sects)) { @@ -2698,7 +2703,8 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { } #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + defined(_LIBUNWIND_TARGET_HAIKU) if (setInfoForSigReturn()) return; #endif @@ -2774,6 +2780,63 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) { _isSignalFrame = true; return UNW_STEP_SUCCESS; } + +#elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) +#include +#include + +extern "C" { +extern void *__gCommPageAddress; +} + +template +bool UnwindCursor::setInfoForSigReturn() { +#if defined(_LIBUNWIND_TARGET_X86_64) + addr_t signal_handler = + (((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] + + (addr_t)__gCommPageAddress); + addr_t signal_handler_ret = signal_handler + 45; +#endif + pint_t pc = static_cast(this->getReg(UNW_REG_IP)); + if (pc == signal_handler_ret) { + _info = {}; + _info.start_ip = signal_handler; + _info.end_ip = signal_handler_ret; + _isSigReturn = true; + return true; + } + return false; +} + +template +int UnwindCursor::stepThroughSigReturn() { + _isSignalFrame = true; + pint_t sp = _registers.getSP(); +#if defined(_LIBUNWIND_TARGET_X86_64) + vregs *regs = (vregs *)(sp + 0x70); + + _registers.setRegister(UNW_REG_IP, regs->rip); + _registers.setRegister(UNW_REG_SP, regs->rsp); + _registers.setRegister(UNW_X86_64_RAX, regs->rax); + _registers.setRegister(UNW_X86_64_RDX, regs->rdx); + _registers.setRegister(UNW_X86_64_RCX, regs->rcx); + _registers.setRegister(UNW_X86_64_RBX, regs->rbx); + _registers.setRegister(UNW_X86_64_RSI, regs->rsi); + _registers.setRegister(UNW_X86_64_RDI, regs->rdi); + _registers.setRegister(UNW_X86_64_RBP, regs->rbp); + _registers.setRegister(UNW_X86_64_R8, regs->r8); + _registers.setRegister(UNW_X86_64_R9, regs->r9); + _registers.setRegister(UNW_X86_64_R10, regs->r10); + _registers.setRegister(UNW_X86_64_R11, regs->r11); + _registers.setRegister(UNW_X86_64_R12, regs->r12); + _registers.setRegister(UNW_X86_64_R13, regs->r13); + _registers.setRegister(UNW_X86_64_R14, regs->r14); + _registers.setRegister(UNW_X86_64_R15, regs->r15); + // TODO: XMM +#endif + + return UNW_STEP_SUCCESS; +} #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && // defined(_LIBUNWIND_TARGET_AARCH64) @@ -2942,7 +3005,8 @@ template int UnwindCursor::step(bool stage2) { // Use unwinding info to modify register set as if function returned. int result; -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + defined(_LIBUNWIND_TARGET_HAIKU) if (_isSigReturn) { result = this->stepThroughSigReturn(); } else @@ -3022,7 +3086,7 @@ bool UnwindCursor::isReadableAddr(const pint_t addr) const { } #endif -#if defined(_LIBUNWIND_USE_CET) +#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->get_registers(); diff --git a/src/native/external/llvm-libunwind/src/UnwindLevel1.c b/src/native/external/llvm-libunwind/src/UnwindLevel1.c index 05d0f2cb0a0a7a..7e785f4d31e716 100644 --- a/src/native/external/llvm-libunwind/src/UnwindLevel1.c +++ b/src/native/external/llvm-libunwind/src/UnwindLevel1.c @@ -31,7 +31,8 @@ #include "libunwind_ext.h" #include "unwind.h" -#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ + !defined(__wasm__) #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND @@ -43,7 +44,7 @@ // _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we // directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using // a regular function call to avoid pushing to CET shadow stack again. -#if !defined(_LIBUNWIND_USE_CET) +#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS) #define __unw_phase2_resume(cursor, fn) \ do { \ (void)fn; \ @@ -71,6 +72,19 @@ __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ "d"(cetJumpAddress)); \ } while (0) +#elif defined(_LIBUNWIND_TARGET_AARCH64) +#define __cet_ss_step_size 8 +#define __unw_phase2_resume(cursor, fn) \ + do { \ + _LIBUNWIND_POP_CET_SSP((fn)); \ + void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ + void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + __asm__ volatile("mov x0, %0\n\t" \ + "br %1\n\t" \ + : \ + : "r"(cetRegContext), "r"(cetJumpAddress) \ + : "x0"); \ + } while (0) #endif static _Unwind_Reason_Code @@ -169,6 +183,10 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except } extern int __unw_step_stage2(unw_cursor_t *); +#if defined(_LIBUNWIND_USE_GCS) +// Enable the GCS target feature to permit gcspop instructions to be used. +__attribute__((target("gcs"))) +#endif static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { __unw_init_local(cursor, uc); @@ -179,8 +197,12 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except // uc is initialized by __unw_getcontext in the parent frame. The first stack // frame walked is unwind_phase2. unsigned framesWalked = 1; -#ifdef _LIBUNWIND_USE_CET +#if defined(_LIBUNWIND_USE_CET) unsigned long shadowStackTop = _get_ssp(); +#elif defined(_LIBUNWIND_USE_GCS) + unsigned long shadowStackTop = 0; + if (__chkfeat(_CHKFEAT_GCS)) + shadowStackTop = (unsigned long)__gcspr(); #endif // Walk each frame until we reach where search phase said to stop. while (true) { @@ -237,7 +259,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except // against return address stored in CET shadow stack, if the 2 addresses don't // match, it means return address in normal stack has been corrupted, we return // _URC_FATAL_PHASE2_ERROR. -#ifdef _LIBUNWIND_USE_CET +#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) if (shadowStackTop != 0) { unw_word_t retInNormalStack; __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack); @@ -305,6 +327,10 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE2_ERROR; } +#if defined(_LIBUNWIND_USE_GCS) +// Enable the GCS target feature to permit gcspop instructions to be used. +__attribute__((target("gcs"))) +#endif static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object, diff --git a/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S b/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S index 42c2488fc7cf7a..1702d016c368ba 100644 --- a/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S +++ b/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S @@ -20,7 +20,7 @@ .text #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #if defined(__i386__) DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) @@ -629,6 +629,10 @@ Lnovec: #elif defined(__aarch64__) +#if defined(__ARM_FEATURE_GCS_DEFAULT) +.arch_extension gcs +#endif + // // extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); // @@ -654,7 +658,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) ldp x26,x27, [x0, #0x0D0] ldp x28,x29, [x0, #0x0E0] ldr x30, [x0, #0x100] // restore pc into lr - +#if defined(__ARM_FP) && __ARM_FP != 0 ldp d0, d1, [x0, #0x110] ldp d2, d3, [x0, #0x120] ldp d4, d5, [x0, #0x130] @@ -672,7 +676,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) ldp d28,d29, [x0, #0x1F0] ldr d30, [x0, #0x200] ldr d31, [x0, #0x208] - +#endif // Finally, restore sp. This must be done after the last read from the // context struct, because it is allocated on the stack, and an exception // could clobber the de-allocated portion of the stack after sp has been @@ -680,6 +684,16 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) ldr x16, [x0, #0x0F8] ldp x0, x1, [x0, #0x000] // restore x0,x1 mov sp,x16 // restore sp +#if defined(__ARM_FEATURE_GCS_DEFAULT) + // If GCS is enabled we need to push the address we're returning to onto the + // GCS stack. We can't just return using br, as there won't be a BTI landing + // pad instruction at the destination. + mov x16, #1 + chkfeat x16 + cbnz x16, Lnogcs + gcspushm x30 +Lnogcs: +#endif ret x30 // jump to pc #elif defined(__arm__) && !defined(__APPLE__) @@ -1169,7 +1183,11 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) ILOAD x\i, (RISCV_ISIZE * \i)(a0) .endr // skip a0 for now +#if defined(__riscv_32e) + .irp i,11,12,13,14,15 +#else .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 +#endif ILOAD x\i, (RISCV_ISIZE * \i)(a0) .endr ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 @@ -1232,7 +1250,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) #endif -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ NO_EXEC_STACK_DIRECTIVE diff --git a/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S b/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S index 19a0e87d683cee..a489a8ba6df159 100644 --- a/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S +++ b/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S @@ -20,7 +20,7 @@ .text #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #if defined(__i386__) @@ -746,6 +746,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) str x1, [x0, #0x0F8] str x30, [x0, #0x100] // store return address as pc // skip cpsr +#if defined(__ARM_FP) && __ARM_FP != 0 stp d0, d1, [x0, #0x110] stp d2, d3, [x0, #0x120] stp d4, d5, [x0, #0x130] @@ -763,6 +764,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stp d28,d29, [x0, #0x1F0] str d30, [x0, #0x200] str d31, [x0, #0x208] +#endif mov x0, #0 // return UNW_ESUCCESS ret @@ -1108,7 +1110,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc +#if defined(__riscv_32e) + .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 +#else .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 +#endif ISTORE x\i, (RISCV_ISIZE * \i)(a0) .endr @@ -1177,6 +1183,6 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) WEAK_ALIAS(__unw_getcontext, unw_getcontext) -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ NO_EXEC_STACK_DIRECTIVE diff --git a/src/native/external/llvm-libunwind/src/assembly.h b/src/native/external/llvm-libunwind/src/assembly.h index fb07d04071af3d..f8e83e138eff50 100644 --- a/src/native/external/llvm-libunwind/src/assembly.h +++ b/src/native/external/llvm-libunwind/src/assembly.h @@ -82,7 +82,22 @@ #define PPC64_OPD2 #endif -#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT) +#if defined(__aarch64__) +#if defined(__ARM_FEATURE_GCS_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT) +// Set BTI, PAC, and GCS gnu property bits +#define GNU_PROPERTY 7 +// We indirectly branch to __libunwind_Registers_arm64_jumpto from +// __unw_phase2_resume, so we need to use bti jc. +#define AARCH64_BTI bti jc +#elif defined(__ARM_FEATURE_GCS_DEFAULT) +// Set GCS gnu property bit +#define GNU_PROPERTY 4 +#elif defined(__ARM_FEATURE_BTI_DEFAULT) +// Set BTI and PAC gnu property bits +#define GNU_PROPERTY 3 +#define AARCH64_BTI bti c +#endif +#ifdef GNU_PROPERTY .pushsection ".note.gnu.property", "a" SEPARATOR \ .balign 8 SEPARATOR \ .long 4 SEPARATOR \ @@ -91,12 +106,12 @@ .asciz "GNU" SEPARATOR \ .long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \ .long 4 SEPARATOR \ - .long 3 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_BTI AND */ \ - /* GNU_PROPERTY_AARCH64_FEATURE_1_PAC */ \ + .long GNU_PROPERTY SEPARATOR \ .long 0 SEPARATOR \ .popsection SEPARATOR -#define AARCH64_BTI bti c -#else +#endif +#endif +#if !defined(AARCH64_BTI) #define AARCH64_BTI #endif diff --git a/src/native/external/llvm-libunwind/src/cet_unwind.h b/src/native/external/llvm-libunwind/src/cet_unwind.h index c364ed3e12feb3..47d7616a7322c3 100644 --- a/src/native/external/llvm-libunwind/src/cet_unwind.h +++ b/src/native/external/llvm-libunwind/src/cet_unwind.h @@ -35,6 +35,28 @@ } while (0) #endif +// On AArch64 we use _LIBUNWIND_USE_GCS to indicate that GCS is supported. We +// need to guard any use of GCS instructions with __chkfeat though, as GCS may +// not be enabled. +#if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT) +#include + +// We can only use GCS if arm_acle.h defines the GCS intrinsics. +#ifdef _CHKFEAT_GCS +#define _LIBUNWIND_USE_GCS 1 +#endif + +#define _LIBUNWIND_POP_CET_SSP(x) \ + do { \ + if (__chkfeat(_CHKFEAT_GCS)) { \ + unsigned tmp = (x); \ + while (tmp--) \ + __gcspopm(); \ + } \ + } while (0) + +#endif + extern void *__libunwind_cet_get_registers(unw_cursor_t *); extern void *__libunwind_cet_get_jump_target(void); diff --git a/src/native/external/llvm-libunwind/src/dwarf2.h b/src/native/external/llvm-libunwind/src/dwarf2.h index 174277d5a79508..68ad882347203c 100644 --- a/src/native/external/llvm-libunwind/src/dwarf2.h +++ b/src/native/external/llvm-libunwind/src/dwarf2.h @@ -18,43 +18,43 @@ // DWARF unwind instructions enum { - DW_CFA_nop = 0x0, - DW_CFA_set_loc = 0x1, - DW_CFA_advance_loc1 = 0x2, - DW_CFA_advance_loc2 = 0x3, - DW_CFA_advance_loc4 = 0x4, - DW_CFA_offset_extended = 0x5, - DW_CFA_restore_extended = 0x6, - DW_CFA_undefined = 0x7, - DW_CFA_same_value = 0x8, - DW_CFA_register = 0x9, - DW_CFA_remember_state = 0xA, - DW_CFA_restore_state = 0xB, - DW_CFA_def_cfa = 0xC, - DW_CFA_def_cfa_register = 0xD, - DW_CFA_def_cfa_offset = 0xE, - DW_CFA_def_cfa_expression = 0xF, - DW_CFA_expression = 0x10, + DW_CFA_nop = 0x0, + DW_CFA_set_loc = 0x1, + DW_CFA_advance_loc1 = 0x2, + DW_CFA_advance_loc2 = 0x3, + DW_CFA_advance_loc4 = 0x4, + DW_CFA_offset_extended = 0x5, + DW_CFA_restore_extended = 0x6, + DW_CFA_undefined = 0x7, + DW_CFA_same_value = 0x8, + DW_CFA_register = 0x9, + DW_CFA_remember_state = 0xA, + DW_CFA_restore_state = 0xB, + DW_CFA_def_cfa = 0xC, + DW_CFA_def_cfa_register = 0xD, + DW_CFA_def_cfa_offset = 0xE, + DW_CFA_def_cfa_expression = 0xF, + DW_CFA_expression = 0x10, DW_CFA_offset_extended_sf = 0x11, - DW_CFA_def_cfa_sf = 0x12, - DW_CFA_def_cfa_offset_sf = 0x13, - DW_CFA_val_offset = 0x14, - DW_CFA_val_offset_sf = 0x15, - DW_CFA_val_expression = 0x16, - DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta - DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register - DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta + DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register + DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register // GNU extensions - DW_CFA_GNU_window_save = 0x2D, - DW_CFA_GNU_args_size = 0x2E, + DW_CFA_GNU_window_save = 0x2D, + DW_CFA_GNU_args_size = 0x2E, DW_CFA_GNU_negative_offset_extended = 0x2F, // AARCH64 extensions - DW_CFA_AARCH64_negate_ra_state = 0x2D + DW_CFA_AARCH64_negate_ra_state_with_pc = 0x2C, + DW_CFA_AARCH64_negate_ra_state = 0x2D }; - // FSF exception handling Pointer-Encoding constants // Used in CFI augmentation by GCC enum { diff --git a/src/native/external/llvm-libunwind/src/libunwind.cpp b/src/native/external/llvm-libunwind/src/libunwind.cpp index 96e4343a2cc67a..fec5fe8799f91b 100644 --- a/src/native/external/llvm-libunwind/src/libunwind.cpp +++ b/src/native/external/llvm-libunwind/src/libunwind.cpp @@ -26,7 +26,7 @@ #include #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #include "AddressSpace.hpp" #include "UnwindCursor.hpp" @@ -362,8 +362,7 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && - // !defined(__USING_WASM_EXCEPTIONS__) +#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #ifdef __APPLE__ diff --git a/src/native/external/llvm-libunwind/test/CMakeLists.txt b/src/native/external/llvm-libunwind/test/CMakeLists.txt index 21dfbb0a84f0a8..c222c0bdbf5af1 100644 --- a/src/native/external/llvm-libunwind/test/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/test/CMakeLists.txt @@ -8,13 +8,30 @@ macro(pythonize_bool var) endif() endmacro() +set(LIBUNWIND_TESTING_INSTALL_PREFIX "${LIBUNWIND_BINARY_DIR}/test-suite-install") +add_custom_target(libunwind-install-unwind-for-testing + DEPENDS unwind-headers + unwind + COMMAND ${CMAKE_COMMAND} -E make_directory "${LIBUNWIND_TESTING_INSTALL_PREFIX}" + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=unwind-headers + -DCMAKE_INSTALL_PREFIX="${LIBUNWIND_TESTING_INSTALL_PREFIX}" + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=unwind + -DCMAKE_INSTALL_PREFIX="${LIBUNWIND_TESTING_INSTALL_PREFIX}" + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + pythonize_bool(LIBUNWIND_ENABLE_CET) +pythonize_bool(LIBUNWIND_ENABLE_GCS) pythonize_bool(LIBUNWIND_ENABLE_THREADS) pythonize_bool(LIBUNWIND_USES_ARM_EHABI) set(AUTO_GEN_COMMENT "## Autogenerated by libunwind configuration.\n# Do not edit!") set(SERIALIZED_LIT_PARAMS "# Lit parameters serialized here for llvm-lit to pick them up\n") +serialize_lit_string_param(SERIALIZED_LIT_PARAMS compiler "${CMAKE_CXX_COMPILER}") + if (LIBUNWIND_EXECUTOR) message(DEPRECATION "LIBUNWIND_EXECUTOR is deprecated, please add executor=... to LIBUNWIND_TEST_PARAMS") serialize_lit_string_param(SERIALIZED_LIT_PARAMS executor "${LIBUNWIND_EXECUTOR}") @@ -45,4 +62,4 @@ configure_lit_site_cfg( add_lit_testsuite(check-unwind "Running libunwind tests" ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS unwind ${LIBUNWIND_TEST_DEPS}) + DEPENDS libunwind-install-unwind-for-testing) diff --git a/src/native/external/llvm-libunwind/test/aix_runtime_link.pass.cpp b/src/native/external/llvm-libunwind/test/aix_runtime_link.pass.cpp new file mode 100644 index 00000000000000..deb192c07981eb --- /dev/null +++ b/src/native/external/llvm-libunwind/test/aix_runtime_link.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Test that libunwind loads successfully independently of libc++abi with +// runtime linking on AIX. + +// REQUIRES: target={{.+}}-aix{{.*}} +// ADDITIONAL_COMPILE_FLAGS: -Wl,-brtl + +#include +extern "C" int printf(const char *, ...); +int main(void) { + void *fp = (void *)&_Unwind_Backtrace; + printf("%p\n", fp); +} diff --git a/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S b/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S index 9ca18e9481f4fc..2c0cf140fe2672 100644 --- a/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S +++ b/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S @@ -10,7 +10,7 @@ // a correct traceback when the function raising the signal does not save // the link register or does not store the stack back chain. -// REQUIRES: target=powerpc{{(64)?}}-ibm-aix +// REQUIRES: target={{.+}}-aix{{.*}} // Test when the function raising the signal does not save the link register // RUN: %{cxx} -x c++ %s -o %t.exe -DCXX_CODE %{flags} %{compile_flags} diff --git a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in deleted file mode 100644 index 4484573801bd2b..00000000000000 --- a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in +++ /dev/null @@ -1,66 +0,0 @@ -# Testing configuration for back-deployment against older Apple system libunwind. -# -# Under this configuration, we compile and link all the test suite against the latest libunwind, -# however we run against the libunwind on a different platform. This emulates the workflow of -# a developer building their application using recent tools but with the goal of deploying -# on existing devices running an older OS (and hence an older dylib). - -import os, site -site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) -import libcxx.test.params, libcxx.test.config, libcxx.test.dsl - -lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') - -BACKDEPLOYMENT_PARAMETERS = [ - libcxx.test.dsl.Parameter(name='cxx_runtime_root', type=str, - actions=lambda root: [libcxx.test.dsl.AddSubstitution('%{cxx-runtime-root}', root)], - help=""" - The simulated root of the system (for libc++) when running tests. - - This should be a directory hierarchy under which the libc++ dylib can be found. - The dylib in that hierarchy is the one that will be used at runtime when running - the tests. - """), - libcxx.test.dsl.Parameter(name='abi_runtime_root', type=str, - actions=lambda root: [libcxx.test.dsl.AddSubstitution('%{abi-runtime-root}', root)], - help=""" - The simulated root of the system (for libc++abi) when running tests. - - This should be a directory hierarchy under which the libc++abi dylib can be found. - The dylib in that hierarchy is the one that will be used at runtime when running - the tests. - """), - libcxx.test.dsl.Parameter(name='unwind_runtime_root', type=str, - actions=lambda root: [libcxx.test.dsl.AddSubstitution('%{unwind-runtime-root}', root)], - help=""" - The simulated root of the system (for libunwind) when running tests. - - This should be a directory hierarchy under which the libunwind dylib can be found. - The dylib in that hierarchy is the one that will be used at runtime when running - the tests. - """), -] - -config.substitutions.append(('%{flags}', - '-isysroot {}'.format('@CMAKE_OSX_SYSROOT@') if '@CMAKE_OSX_SYSROOT@' else '' -)) -config.substitutions.append(('%{compile_flags}', - '-nostdinc++ -I %{include}' -)) -config.substitutions.append(('%{link_flags}', - '-nostdlib++ -L %{lib} -lc++ -lc++abi -lunwind' -)) -config.substitutions.append(('%{exec}', - '%{executor} --execdir %T --env DYLD_LIBRARY_PATH="%{cxx-runtime-root}:%{abi-runtime-root}:%{unwind-runtime-root}" -- ' -)) - -config.stdlib = 'apple-libc++' - -import os, site -import libcxx.test.params, libcxx.test.config -libcxx.test.config.configure( - libcxx.test.params.DEFAULT_PARAMETERS + BACKDEPLOYMENT_PARAMETERS, - libcxx.test.features.DEFAULT_FEATURES, - config, - lit_config -) diff --git a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in new file mode 100644 index 00000000000000..e5a7c983562a60 --- /dev/null +++ b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in @@ -0,0 +1,41 @@ +# Testing configuration for back-deployment against the system-provided libunwind. +# +# Under this configuration, we compile and link all the test suite against the just-built +# libunwind, but we run against the system libunwind. + +import os, site +site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) +import libcxx.test.params, libcxx.test.config, libcxx.test.dsl + +lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') + +config.substitutions.append(('%{flags}', + '-isysroot {}'.format('@CMAKE_OSX_SYSROOT@') if '@CMAKE_OSX_SYSROOT@' else '' +)) +config.substitutions.append(('%{compile_flags}', + '-nostdinc++ -I %{include}' +)) +config.substitutions.append(('%{link_flags}', + '-nostdlib++ -L %{lib} -lc++ -lunwind' +)) +config.substitutions.append(('%{exec}', + '%{executor} --execdir %T -- ' +)) + +config.stdlib = 'apple-libc++' +config.using_system_stdlib = True + +# TODO: This is a giant hack, but we need to change the install_name of libunwind.dylib because the +# upstream configuration can't currently produce a libunwind.dylib that is compatible with the +# Apple system one. +import subprocess +subprocess.check_call(['install_name_tool', '-id', '/usr/lib/system/libunwind.dylib', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/lib/libunwind.dylib']) + +import os, site +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( + libcxx.test.params.DEFAULT_PARAMETERS, + libcxx.test.features.DEFAULT_FEATURES, + config, + lit_config +) diff --git a/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in b/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in index c5f34c87abb92a..b804c210f0bbc0 100644 --- a/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in @@ -20,7 +20,7 @@ config.name = os.path.basename('@LIBUNWIND_TEST_CONFIG@') config.test_source_root = os.path.join('@LIBUNWIND_SOURCE_DIR@', 'test') config.test_format = libcxx.test.format.CxxStandardLibraryTest() config.recursiveExpansionLimit = 10 -config.test_exec_root = os.path.join('@CMAKE_BINARY_DIR@', 'test') +config.test_exec_root = os.path.join('@LIBUNWIND_BINARY_DIR@', 'test') # Add a few features that are common to all the configurations if @LIBUNWIND_USES_ARM_EHABI@: @@ -29,7 +29,7 @@ if not @LIBUNWIND_ENABLE_THREADS@: config.available_features.add('libunwind-no-threads') # Add substitutions for bootstrapping the test suite configuration -import shlex -config.substitutions.append(('%{cxx}', shlex.quote('@CMAKE_CXX_COMPILER@'))) -config.substitutions.append(('%{include}', '@LIBUNWIND_SOURCE_DIR@/include')) -config.substitutions.append(('%{lib}', '@LIBUNWIND_LIBRARY_DIR@')) +config.substitutions.append(('%{install-prefix}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@')) +config.substitutions.append(('%{include}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/include')) +config.substitutions.append(('%{lib}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/@LIBUNWIND_INSTALL_LIBRARY_DIR@')) +config.substitutions.append(('%{benchmark_flags}', '')) diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in index 38b79840c9fe28..fafe12962b428f 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in @@ -11,6 +11,9 @@ link_flags = [] if @LIBUNWIND_ENABLE_CET@: compile_flags.append('-fcf-protection=full') +if @LIBUNWIND_ENABLE_GCS@: + compile_flags.append('-mbranch-protection=standard') + # On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker. if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'): link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@') diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in new file mode 100644 index 00000000000000..b29d83fbab3053 --- /dev/null +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in @@ -0,0 +1,25 @@ +# This testing configuration handles running the test suite against LLVM's libunwind +# using a DLL with MinGW/Clang on Windows. + +lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') + +config.substitutions.append(('%{flags}', '')) +config.substitutions.append(('%{compile_flags}', + '-nostdinc++ -I %{include} -funwind-tables' +)) +config.substitutions.append(('%{link_flags}', + '-L %{lib} -lunwind' +)) +config.substitutions.append(('%{exec}', + '%{executor} --execdir %T --prepend_env PATH=%{install-prefix}/bin -- ' +)) + +import os, site +site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( + libcxx.test.params.DEFAULT_PARAMETERS, + libcxx.test.features.DEFAULT_FEATURES, + config, + lit_config +) diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in index 13896aeb13bc4a..f3e40928b525da 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in @@ -10,6 +10,9 @@ link_flags = [] if @LIBUNWIND_ENABLE_CET@: compile_flags.append('-fcf-protection=full') +if @LIBUNWIND_ENABLE_GCS@: + compile_flags.append('-mbranch-protection=standard') + # On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker. if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'): link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@') diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in similarity index 91% rename from src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in rename to src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in index 33d061a3efc6fc..437c53bea2f06b 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in @@ -1,5 +1,5 @@ # This testing configuration handles running the test suite against LLVM's libunwind -# using either a DLL or a static library, with MinGW/Clang on Windows. +# using a static library with MinGW/Clang on Windows. lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in index 50b64dc665a5af..a3a65ae82591b1 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in @@ -13,6 +13,9 @@ if @LIBUNWIND_ENABLE_THREADS@: if @LIBUNWIND_ENABLE_CET@: compile_flags.append('-fcf-protection=full') +if @LIBUNWIND_ENABLE_GCS@: + compile_flags.append('-mbranch-protection=standard') + # On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker. if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'): link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@') diff --git a/src/native/external/llvm-libunwind/test/floatregister.pass.cpp b/src/native/external/llvm-libunwind/test/floatregister.pass.cpp index 64107e6d490b70..ce4481bdf8287e 100644 --- a/src/native/external/llvm-libunwind/test/floatregister.pass.cpp +++ b/src/native/external/llvm-libunwind/test/floatregister.pass.cpp @@ -11,20 +11,27 @@ // Basic test for float registers number are accepted. -#include #include #include #include +// Using __attribute__((section("main_func"))) is ELF specific, but then +// this entire test is marked as requiring Linux, so we should be good. +// +// We don't use dladdr() because on musl it's a no-op when statically linked. +extern char __start_main_func; +extern char __stop_main_func; + _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx, void *arg) { (void)arg; - Dl_info info = {0, 0, 0, 0}; - // Unwind util the main is reached, above frames depend on the platform and + // Unwind until the main is reached, above frames depend on the platform and // architecture. - if (dladdr(reinterpret_cast(_Unwind_GetIP(ctx)), &info) && - info.dli_sname && !strcmp("main", info.dli_sname)) + uintptr_t ip = _Unwind_GetIP(ctx); + if (ip >= (uintptr_t)&__start_main_func && + ip < (uintptr_t)&__stop_main_func) { _Exit(0); + } return _URC_NO_REASON; } @@ -45,7 +52,7 @@ __attribute__((noinline)) void foo() { _Unwind_Backtrace(frame_handler, NULL); } -int main() { +__attribute__((section("main_func"))) int main() { foo(); return -2; } diff --git a/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp b/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp index db499d8bc30894..344034e1ea5f5e 100644 --- a/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp +++ b/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp @@ -17,7 +17,6 @@ #undef NDEBUG #include -#include #include #include #include @@ -27,6 +26,13 @@ #include #include +// Using __attribute__((section("main_func"))) is Linux specific, but then +// this entire test is marked as requiring Linux, so we should be good. +// +// We don't use dladdr() because on musl it's a no-op when statically linked. +extern char __start_main_func; +extern char __stop_main_func; + void foo(); _Unwind_Exception ex; @@ -41,14 +47,14 @@ _Unwind_Reason_Code stop(int version, _Unwind_Action actions, assert(exceptionObject == &ex); assert(stop_parameter == &foo); - Dl_info info = {0, 0, 0, 0}; - - // Unwind util the main is reached, above frames depend on the platform and + // Unwind until the main is reached, above frames depend on the platform and // architecture. - if (dladdr(reinterpret_cast(_Unwind_GetIP(context)), &info) && - info.dli_sname && !strcmp("main", info.dli_sname)) { + uintptr_t ip = _Unwind_GetIP(context); + if (ip >= (uintptr_t)&__start_main_func && + ip < (uintptr_t)&__stop_main_func) { _Exit(0); } + return _URC_NO_REASON; } @@ -66,7 +72,7 @@ __attribute__((noinline)) void foo() { _Unwind_ForcedUnwind(e, stop, (void *)&foo); } -int main() { +__attribute__((section("main_func"))) int main() { foo(); return -2; } diff --git a/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp b/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp index 96f12d1fc39374..838df6b5897204 100644 --- a/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp +++ b/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // TODO: Investigate this failure on x86_64 macOS back deployment -// XFAIL: stdlib=apple-libc++ && target=x86_64-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// XFAIL: stdlib=system && target=x86_64-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan diff --git a/src/native/external/llvm-libunwind/test/lit.cfg.py b/src/native/external/llvm-libunwind/test/lit.cfg.py index ea4a9a75b4fdb8..51e85e489db01f 100644 --- a/src/native/external/llvm-libunwind/test/lit.cfg.py +++ b/src/native/external/llvm-libunwind/test/lit.cfg.py @@ -7,5 +7,6 @@ lit_config.fatal( "You seem to be running Lit directly -- you should be running Lit through " "/bin/llvm-lit, which will ensure that the right Lit configuration " - "file is used." + "file is used. See https://libcxx.llvm.org/TestingLibcxx.html#usage for " + "how to run the libunwind tests." ) diff --git a/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp b/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp index 954a5d4ba3db10..1c1566415a4d4b 100644 --- a/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp +++ b/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp @@ -13,9 +13,15 @@ // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan +// Note: this test fails on musl because: +// +// (a) musl disables emission of unwind information for its build, and +// (b) musl's signal trampolines don't include unwind information +// +// XFAIL: target={{.*}}-musl + #undef NDEBUG #include -#include #include #include #include @@ -24,16 +30,24 @@ #include #include +// Using __attribute__((section("main_func"))) is ELF specific, but then +// this entire test is marked as requiring Linux, so we should be good. +// +// We don't use dladdr() because on musl it's a no-op when statically linked. +extern char __start_main_func; +extern char __stop_main_func; + _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) { (void)arg; - Dl_info info = { 0, 0, 0, 0 }; - // Unwind util the main is reached, above frames depend on the platform and + // Unwind until the main is reached, above frames depend on the platform and // architecture. - if (dladdr(reinterpret_cast(_Unwind_GetIP(ctx)), &info) && - info.dli_sname && !strcmp("main", info.dli_sname)) { + uintptr_t ip = _Unwind_GetIP(ctx); + if (ip >= (uintptr_t)&__start_main_func && + ip < (uintptr_t)&__stop_main_func) { _Exit(0); } + return _URC_NO_REASON; } @@ -43,7 +57,7 @@ void signal_handler(int signum) { _Exit(-1); } -int main(int, char**) { +__attribute__((section("main_func"))) int main(int, char **) { signal(SIGUSR1, signal_handler); kill(getpid(), SIGUSR1); return -2; diff --git a/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp b/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp index 112a5968247a42..98de7dc43260c2 100644 --- a/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp @@ -13,9 +13,15 @@ // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan +// Note: this test fails on musl because: +// +// (a) musl disables emission of unwind information for its build, and +// (b) musl's signal trampolines don't include unwind information +// +// XFAIL: target={{.*}}-musl + #undef NDEBUG #include -#include #include #include #include @@ -24,16 +30,24 @@ #include #include +// Using __attribute__((section("main_func"))) is ELF specific, but then +// this entire test is marked as requiring Linux, so we should be good. +// +// We don't use dladdr() because on musl it's a no-op when statically linked. +extern char __start_main_func; +extern char __stop_main_func; + _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) { (void)arg; - Dl_info info = { 0, 0, 0, 0 }; // Unwind until the main is reached, above frames depend on the platform and // architecture. - if (dladdr(reinterpret_cast(_Unwind_GetIP(ctx)), &info) && - info.dli_sname && !strcmp("main", info.dli_sname)) { + uintptr_t ip = _Unwind_GetIP(ctx); + if (ip >= (uintptr_t)&__start_main_func && + ip < (uintptr_t)&__stop_main_func) { _Exit(0); } + return _URC_NO_REASON; } @@ -56,7 +70,7 @@ __attribute__((noinline)) void crashing_leaf_func(int do_trap) { __builtin_trap(); } -int main(int, char**) { +__attribute__((section("main_func"))) int main(int, char **) { signal(SIGTRAP, signal_handler); signal(SIGILL, signal_handler); crashing_leaf_func(1); diff --git a/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt b/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt index 4a1d2e9e5e8e61..d2cf45fa17df8f 100644 --- a/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt +++ b/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt @@ -33,6 +33,7 @@ set(NATIVECRYPTO_SOURCES pal_evp.c pal_evp_cipher.c pal_evp_kdf.c + pal_evp_kem.c pal_evp_mac.c pal_evp_pkey.c pal_evp_pkey_dsa.c diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h index 29bec2f1d4dc1c..26f9470be3c18a 100644 --- a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h @@ -8,6 +8,7 @@ typedef struct evp_kdf_st EVP_KDF; typedef struct evp_kdf_ctx_st EVP_KDF_CTX; +typedef struct evp_kem_st EVP_KEM; typedef struct evp_mac_st EVP_MAC; typedef struct evp_mac_ctx_st EVP_MAC_CTX; diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index 7d59afc0d33d1b..3045c21c4cd959 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -16,6 +16,7 @@ #include "pal_evp.h" #include "pal_evp_cipher.h" #include "pal_evp_kdf.h" +#include "pal_evp_kem.h" #include "pal_evp_mac.h" #include "pal_evp_pkey.h" #include "pal_evp_pkey_dsa.h" @@ -145,6 +146,13 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_KbkdfHmacOneShot) DllImportEntry(CryptoNative_EvpKdfFetch) DllImportEntry(CryptoNative_EvpKdfFree) + DllImportEntry(CryptoNative_EvpKemAvailable) + DllImportEntry(CryptoNative_EvpKemEncapsulate) + DllImportEntry(CryptoNative_EvpKemDecapsulate) + DllImportEntry(CryptoNative_EvpKemExportDecapsulationKey) + DllImportEntry(CryptoNative_EvpKemExportEncapsulationKey) + DllImportEntry(CryptoNative_EvpKemExportPrivateSeed) + DllImportEntry(CryptoNative_EvpKemGeneratePkey) DllImportEntry(CryptoNative_EvpMacCtxDup) DllImportEntry(CryptoNative_EvpMacCtxNew) DllImportEntry(CryptoNative_EvpMacCtxFree) @@ -165,11 +173,15 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_EvpPKeyCreateRsa) DllImportEntry(CryptoNative_EvpPKeyDeriveSecretAgreement) DllImportEntry(CryptoNative_EvpPkeyDestroy) + DllImportEntry(CryptoNative_EvpPKeyFromData) DllImportEntry(CryptoNative_EvpPkeyGetDsa) DllImportEntry(CryptoNative_EvpPkeyGetEcKey) DllImportEntry(CryptoNative_EvpPkeySetDsa) DllImportEntry(CryptoNative_EvpPkeySetEcKey) DllImportEntry(CryptoNative_EvpPKeyBits) + DllImportEntry(CryptoNative_EvpPKeyGetEcKeyParameters) + DllImportEntry(CryptoNative_EvpPKeyGetEcGroupNid) + DllImportEntry(CryptoNative_EvpPKeyGetEcCurveParameters) DllImportEntry(CryptoNative_EvpRC2Cbc) DllImportEntry(CryptoNative_EvpRC2Ecb) DllImportEntry(CryptoNative_EvpSha1) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index f752da891b287c..26a850c520224a 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -263,6 +263,7 @@ parameters to the algorithm used by the certificate public key Return values: 0: Invalid X509 pointer 1: Data was copied +2: No data exists. Any negative value: The input buffer size was reported as insufficient. A buffer of size ABS(return) is required. */ int32_t CryptoNative_GetX509PublicKeyParameterBytes(X509* x509, uint8_t* pBuf, int32_t cBuf) @@ -292,9 +293,9 @@ int32_t CryptoNative_GetX509PublicKeyParameterBytes(X509* x509, uint8_t* pBuf, i if (!parameter) { - // If pBuf is NULL we're asking for the length, so return 0 (which is negative-zero) - // If pBuf is non-NULL we're asking to fill the data, in which case we return 1. - return pBuf != NULL; + // Callers should not attempt to get the value if it was originally reported there is missing data. + assert(pBuf == NULL); + return 2; } int len = i2d_ASN1_TYPE(parameter, NULL); diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 400ecf9275b6d3..b4518fe98106a6 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -132,6 +132,30 @@ c_static_assert(EVP_KDF_HKDF_MODE_EXTRACT_ONLY == 1); c_static_assert(EVP_KDF_HKDF_MODE_EXPAND_ONLY == 2); #endif +#ifndef OSSL_PKEY_PARAM_ML_KEM_SEED +#define OSSL_PKEY_PARAM_ML_KEM_SEED "seed" +#endif + +#ifndef OSSL_PKEY_PARAM_PUB_KEY +#define OSSL_PKEY_PARAM_PUB_KEY "pub" +#endif + +#ifndef OSSL_PKEY_PARAM_PRIV_KEY +#define OSSL_PKEY_PARAM_PRIV_KEY "priv" +#endif + +#ifndef EVP_PKEY_KEYPAIR +#define EVP_PKEY_KEYPAIR 135 +#else +c_static_assert(EVP_PKEY_KEYPAIR == 135); +#endif + +#ifndef EVP_PKEY_PUBLIC_KEY +#define EVP_PKEY_PUBLIC_KEY 134 +#else +c_static_assert(EVP_PKEY_PUBLIC_KEY == 134); +#endif + #if defined FEATURE_DISTRO_AGNOSTIC_SSL || OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_3_0_RTM #include "apibridge_30_rev.h" #endif @@ -354,8 +378,10 @@ extern bool g_libSslUses32BitTime; REQUIRED_FUNCTION(EC_GROUP_get_degree) \ REQUIRED_FUNCTION(EC_GROUP_get_order) \ REQUIRED_FUNCTION(EC_GROUP_get_seed_len) \ + LIGHTUP_FUNCTION(EC_GROUP_get_field_type) \ REQUIRED_FUNCTION(EC_GROUP_method_of) \ REQUIRED_FUNCTION(EC_GROUP_new) \ + LIGHTUP_FUNCTION(EC_GROUP_new_by_curve_name) \ REQUIRED_FUNCTION(EC_GROUP_set_curve_GFp) \ REQUIRED_FUNCTION(EC_GROUP_set_generator) \ REQUIRED_FUNCTION(EC_GROUP_set_seed) \ @@ -378,6 +404,7 @@ extern bool g_libSslUses32BitTime; REQUIRED_FUNCTION(EC_POINT_mul) \ REQUIRED_FUNCTION(EC_POINT_new) \ REQUIRED_FUNCTION(EC_POINT_set_affine_coordinates_GFp) \ + LIGHTUP_FUNCTION(EC_POINT_oct2point) \ LIGHTUP_FUNCTION(ENGINE_by_id) \ LIGHTUP_FUNCTION(ENGINE_finish) \ LIGHTUP_FUNCTION(ENGINE_free) \ @@ -447,6 +474,8 @@ extern bool g_libSslUses32BitTime; LIGHTUP_FUNCTION(EVP_KDF_derive) \ LIGHTUP_FUNCTION(EVP_KDF_fetch) \ LIGHTUP_FUNCTION(EVP_KDF_free) \ + LIGHTUP_FUNCTION(EVP_KEM_fetch) \ + LIGHTUP_FUNCTION(EVP_KEM_free) \ LIGHTUP_FUNCTION(EVP_MAC_fetch) \ LIGHTUP_FUNCTION(EVP_MAC_final) \ LIGHTUP_FUNCTION(EVP_MAC_free) \ @@ -471,23 +500,32 @@ extern bool g_libSslUses32BitTime; REQUIRED_FUNCTION(EVP_PKEY_CTX_get0_pkey) \ REQUIRED_FUNCTION(EVP_PKEY_CTX_new) \ REQUIRED_FUNCTION(EVP_PKEY_CTX_new_id) \ + LIGHTUP_FUNCTION(EVP_PKEY_CTX_new_from_name) \ LIGHTUP_FUNCTION(EVP_PKEY_CTX_new_from_pkey) \ + LIGHTUP_FUNCTION(EVP_PKEY_CTX_set_params) \ FALLBACK_FUNCTION(EVP_PKEY_CTX_set_rsa_keygen_bits) \ FALLBACK_FUNCTION(EVP_PKEY_CTX_set_rsa_oaep_md) \ FALLBACK_FUNCTION(EVP_PKEY_CTX_set_rsa_padding) \ FALLBACK_FUNCTION(EVP_PKEY_CTX_set_rsa_pss_saltlen) \ FALLBACK_FUNCTION(EVP_PKEY_CTX_set_signature_md) \ FALLBACK_FUNCTION(EVP_PKEY_check) \ + LIGHTUP_FUNCTION(EVP_PKEY_decapsulate) \ + LIGHTUP_FUNCTION(EVP_PKEY_decapsulate_init) \ REQUIRED_FUNCTION(EVP_PKEY_decrypt) \ REQUIRED_FUNCTION(EVP_PKEY_decrypt_init) \ REQUIRED_FUNCTION(EVP_PKEY_derive_set_peer) \ REQUIRED_FUNCTION(EVP_PKEY_derive_init) \ REQUIRED_FUNCTION(EVP_PKEY_derive) \ + LIGHTUP_FUNCTION(EVP_PKEY_encapsulate) \ + LIGHTUP_FUNCTION(EVP_PKEY_encapsulate_init) \ REQUIRED_FUNCTION(EVP_PKEY_encrypt) \ REQUIRED_FUNCTION(EVP_PKEY_encrypt_init) \ REQUIRED_FUNCTION(EVP_PKEY_free) \ + LIGHTUP_FUNCTION(EVP_PKEY_fromdata) \ + LIGHTUP_FUNCTION(EVP_PKEY_fromdata_init) \ RENAMED_FUNCTION(EVP_PKEY_get_base_id, EVP_PKEY_base_id) \ RENAMED_FUNCTION(EVP_PKEY_get_bits, EVP_PKEY_bits) \ + LIGHTUP_FUNCTION(EVP_PKEY_get_octet_string_param) \ FALLBACK_FUNCTION(EVP_PKEY_get0_RSA) \ REQUIRED_FUNCTION(EVP_PKEY_get1_DSA) \ REQUIRED_FUNCTION(EVP_PKEY_get1_EC_KEY) \ @@ -504,6 +542,9 @@ extern bool g_libSslUses32BitTime; FALLBACK_FUNCTION(EVP_PKEY_up_ref) \ REQUIRED_FUNCTION(EVP_PKEY_verify) \ REQUIRED_FUNCTION(EVP_PKEY_verify_init) \ + LIGHTUP_FUNCTION(EVP_PKEY_get_bn_param) \ + LIGHTUP_FUNCTION(EVP_PKEY_get_utf8_string_param) \ + LIGHTUP_FUNCTION(EVP_PKEY_get_octet_string_param) \ LIGHTUP_FUNCTION(EVP_rc2_cbc) \ LIGHTUP_FUNCTION(EVP_rc2_ecb) \ REQUIRED_FUNCTION(EVP_sha1) \ @@ -903,8 +944,10 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define EC_GROUP_get_degree EC_GROUP_get_degree_ptr #define EC_GROUP_get_order EC_GROUP_get_order_ptr #define EC_GROUP_get_seed_len EC_GROUP_get_seed_len_ptr +#define EC_GROUP_get_field_type EC_GROUP_get_field_type_ptr #define EC_GROUP_method_of EC_GROUP_method_of_ptr #define EC_GROUP_new EC_GROUP_new_ptr +#define EC_GROUP_new_by_curve_name EC_GROUP_new_by_curve_name_ptr #define EC_GROUP_set_curve_GFp EC_GROUP_set_curve_GFp_ptr #define EC_GROUP_set_generator EC_GROUP_set_generator_ptr #define EC_GROUP_set_seed EC_GROUP_set_seed_ptr @@ -927,6 +970,7 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define EC_POINT_mul EC_POINT_mul_ptr #define EC_POINT_new EC_POINT_new_ptr #define EC_POINT_set_affine_coordinates_GFp EC_POINT_set_affine_coordinates_GFp_ptr +#define EC_POINT_oct2point EC_POINT_oct2point_ptr #define ENGINE_by_id ENGINE_by_id_ptr #define ENGINE_finish ENGINE_finish_ptr #define ENGINE_free ENGINE_free_ptr @@ -997,6 +1041,8 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define EVP_KDF_derive EVP_KDF_derive_ptr #define EVP_KDF_fetch EVP_KDF_fetch_ptr #define EVP_KDF_free EVP_KDF_free_ptr +#define EVP_KEM_fetch EVP_KEM_fetch_ptr +#define EVP_KEM_free EVP_KEM_free_ptr #define EVP_MAC_fetch EVP_MAC_fetch_ptr #define EVP_MAC_final EVP_MAC_final_ptr #define EVP_MAC_free EVP_MAC_free_ptr @@ -1020,22 +1066,30 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define EVP_PKEY_CTX_get0_pkey EVP_PKEY_CTX_get0_pkey_ptr #define EVP_PKEY_CTX_new EVP_PKEY_CTX_new_ptr #define EVP_PKEY_CTX_new_id EVP_PKEY_CTX_new_id_ptr +#define EVP_PKEY_CTX_set_params EVP_PKEY_CTX_set_params_ptr #define EVP_PKEY_CTX_set_rsa_keygen_bits EVP_PKEY_CTX_set_rsa_keygen_bits_ptr #define EVP_PKEY_CTX_set_rsa_oaep_md EVP_PKEY_CTX_set_rsa_oaep_md_ptr #define EVP_PKEY_CTX_set_rsa_padding EVP_PKEY_CTX_set_rsa_padding_ptr #define EVP_PKEY_CTX_set_rsa_pss_saltlen EVP_PKEY_CTX_set_rsa_pss_saltlen_ptr #define EVP_PKEY_CTX_set_signature_md EVP_PKEY_CTX_set_signature_md_ptr #define EVP_PKEY_check EVP_PKEY_check_ptr +#define EVP_PKEY_decapsulate EVP_PKEY_decapsulate_ptr +#define EVP_PKEY_decapsulate_init EVP_PKEY_decapsulate_init_ptr #define EVP_PKEY_decrypt_init EVP_PKEY_decrypt_init_ptr #define EVP_PKEY_decrypt EVP_PKEY_decrypt_ptr #define EVP_PKEY_derive_set_peer EVP_PKEY_derive_set_peer_ptr #define EVP_PKEY_derive_init EVP_PKEY_derive_init_ptr #define EVP_PKEY_derive EVP_PKEY_derive_ptr +#define EVP_PKEY_encapsulate EVP_PKEY_encapsulate_ptr +#define EVP_PKEY_encapsulate_init EVP_PKEY_encapsulate_init_ptr #define EVP_PKEY_encrypt_init EVP_PKEY_encrypt_init_ptr #define EVP_PKEY_encrypt EVP_PKEY_encrypt_ptr #define EVP_PKEY_free EVP_PKEY_free_ptr +#define EVP_PKEY_fromdata EVP_PKEY_fromdata_ptr +#define EVP_PKEY_fromdata_init EVP_PKEY_fromdata_init_ptr #define EVP_PKEY_get_base_id EVP_PKEY_get_base_id_ptr #define EVP_PKEY_get_bits EVP_PKEY_get_bits_ptr +#define EVP_PKEY_get_octet_string_param EVP_PKEY_get_octet_string_param_ptr #define EVP_PKEY_get0_RSA EVP_PKEY_get0_RSA_ptr #define EVP_PKEY_get1_DSA EVP_PKEY_get1_DSA_ptr #define EVP_PKEY_get1_EC_KEY EVP_PKEY_get1_EC_KEY_ptr @@ -1043,6 +1097,7 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define EVP_PKEY_keygen EVP_PKEY_keygen_ptr #define EVP_PKEY_keygen_init EVP_PKEY_keygen_init_ptr #define EVP_PKEY_new EVP_PKEY_new_ptr +#define EVP_PKEY_CTX_new_from_name EVP_PKEY_CTX_new_from_name_ptr #define EVP_PKEY_CTX_new_from_pkey EVP_PKEY_CTX_new_from_pkey_ptr #define EVP_PKEY_public_check EVP_PKEY_public_check_ptr #define EVP_PKEY_set1_DSA EVP_PKEY_set1_DSA_ptr @@ -1053,6 +1108,9 @@ extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr; #define EVP_PKEY_up_ref EVP_PKEY_up_ref_ptr #define EVP_PKEY_verify_init EVP_PKEY_verify_init_ptr #define EVP_PKEY_verify EVP_PKEY_verify_ptr +#define EVP_PKEY_get_bn_param EVP_PKEY_get_bn_param_ptr +#define EVP_PKEY_get_utf8_string_param EVP_PKEY_get_utf8_string_param_ptr +#define EVP_PKEY_get_octet_string_param EVP_PKEY_get_octet_string_param_ptr #define EVP_rc2_cbc EVP_rc2_cbc_ptr #define EVP_rc2_ecb EVP_rc2_ecb_ptr #define EVP_sha1 EVP_sha1_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h b/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h index 1609afd2a003bd..9d841ea110f5da 100644 --- a/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h @@ -24,6 +24,18 @@ #define OSSL_MAC_PARAM_XOF "xof" #define OSSL_MAC_PARAM_SIZE "size" +#define OSSL_PKEY_PARAM_GROUP_NAME "group" +#define OSSL_PKEY_PARAM_PRIV_KEY "priv" +#define OSSL_PKEY_PARAM_EC_PUB_X "qx" +#define OSSL_PKEY_PARAM_EC_PUB_Y "qy" +#define OSSL_PKEY_PARAM_EC_P "p" +#define OSSL_PKEY_PARAM_EC_A "a" +#define OSSL_PKEY_PARAM_EC_B "b" +#define OSSL_PKEY_PARAM_EC_GENERATOR "generator" +#define OSSL_PKEY_PARAM_EC_ORDER "order" +#define OSSL_PKEY_PARAM_EC_COFACTOR "cofactor" +#define OSSL_PKEY_PARAM_EC_SEED "seed" + #define OSSL_STORE_INFO_PKEY 4 #define OSSL_STORE_INFO_PUBKEY 3 @@ -54,6 +66,9 @@ EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf); void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx); int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, const OSSL_PARAM params[]); +EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties); +void EVP_KEM_free(EVP_KEM *kem); + int EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[]); EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac); void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx); @@ -66,15 +81,39 @@ void EVP_MAC_free(EVP_MAC *mac); EVP_MD* EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties); int EVP_MD_get_size(const EVP_MD* md); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx, const char *name, const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey, const char *propquery); +int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params); int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX* ctx, int bits); int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX* ctx, const EVP_MD* md); int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX* ctx, int pad_mode); int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX* ctx, int saltlen); int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX* ctx, const EVP_MD* md); +int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, + unsigned char *unwrapped, + size_t *unwrappedlen, + const unsigned char *wrapped, + size_t wrappedlen); +int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); +int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); +int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, + unsigned char *wrappedkey, + size_t *wrappedkeylen, + unsigned char *genkey, + size_t *genkeylen); +int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, + EVP_PKEY **ppkey, + int selection, + OSSL_PARAM params[]); int EVP_PKEY_get_base_id(const EVP_PKEY* pkey); int EVP_PKEY_get_bits(const EVP_PKEY* pkey); -EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey( - OSSL_LIB_CTX *libctx, EVP_PKEY *pkey, const char *propquery); +int EVP_PKEY_get_bn_param(const EVP_PKEY *pkey, const char *key_name, BIGNUM **bn); +int EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey, const char *key_name, char *str, size_t max_buf_sz, size_t *out_len); +int EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey, const char *key_name, unsigned char *buf, size_t max_buf_sz, size_t *out_len); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, + EVP_PKEY *pkey, + const char *propquery); OSSL_PARAM OSSL_PARAM_construct_end(void); OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf); @@ -98,3 +137,5 @@ OSSL_STORE_CTX* OSSL_STORE_open_ex( const char*, OSSL_LIB_CTX*, const char*, const UI_METHOD*, void*, const OSSL_PARAM*, OSSL_STORE_post_process_info_fn post_process, void*); X509* SSL_get1_peer_certificate(const SSL* ssl); + +int EC_GROUP_get_field_type(const EC_GROUP *group); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c b/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c index 99b2a58817d034..8f7bc880cfb74d 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.c @@ -49,6 +49,28 @@ static ECCurveType EcKeyGetCurveType( return MethodToCurveType(method); } +static int EcPointGetAffineCoordinates(const EC_GROUP *group, ECCurveType curveType, const EC_POINT *p, BIGNUM *x, BIGNUM *y) +{ +#if HAVE_OPENSSL_EC2M + if (API_EXISTS(EC_POINT_get_affine_coordinates_GF2m) && (curveType == Characteristic2)) + { + if (!EC_POINT_get_affine_coordinates_GF2m(group, p, x, y, NULL)) + return 0; + } + else +#endif + { + if (!EC_POINT_get_affine_coordinates_GFp(group, p, x, y, NULL)) + return 0; + } + +#if !HAVE_OPENSSL_EC2M + (void)curveType; +#endif + + return 1; +} + int32_t CryptoNative_GetECKeyParameters( const EC_KEY* key, int32_t includePrivate, @@ -82,18 +104,8 @@ int32_t CryptoNative_GetECKeyParameters( if (!xBn || !yBn) goto error; -#if HAVE_OPENSSL_EC2M - if (API_EXISTS(EC_POINT_get_affine_coordinates_GF2m) && (curveType == Characteristic2)) - { - if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, xBn, yBn, NULL)) - goto error; - } - else -#endif - { - if (!EC_POINT_get_affine_coordinates_GFp(group, Q, xBn, yBn, NULL)) - goto error; - } + if (!EcPointGetAffineCoordinates(group, curveType, Q, xBn, yBn)) + goto error; // Success; assign variables *qx = xBn; *cbQx = BN_num_bytes(xBn); @@ -412,6 +424,118 @@ int32_t CryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key, const char* oid, u return ret; } +int32_t CryptoNative_EvpPKeyGetEcGroupNid(const EVP_PKEY *pkey, int32_t* nidName) +{ + if (!nidName) + return 0; + + *nidName = NID_undef; + + if (!pkey || EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC) + return 0; + +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL + if (!API_EXISTS(EVP_PKEY_get_utf8_string_param)) + { + return 0; + } +#endif + +#ifdef NEED_OPENSSL_3_0 + // Retrieve the textual name of the EC group (e.g., "prime256v1") + // In all known cases this should be exactly 10 characters + 1 null byte but leaving some room in case it changes in the future + // versions of OpenSSL. This length also matches with what OpenSSL uses in their demo code: + // https://github.com/openssl/openssl/blob/ac80e1e15dcd13c61392a706170c427250c7bb69/demos/pkey/EVP_PKEY_EC_keygen.c#L88 + char curveName[80] = {0}; + + if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, curveName, sizeof(curveName), NULL)) + return 0; + + *nidName = OBJ_txt2nid(curveName); + return 1; +#else + return 0; +#endif +} + +int32_t CryptoNative_EvpPKeyGetEcKeyParameters( + const EVP_PKEY* pkey, + int32_t includePrivate, + BIGNUM** qx, int32_t* cbQx, + BIGNUM** qy, int32_t* cbQy, + BIGNUM** d, int32_t* cbD) +{ + assert(qx != NULL); + assert(cbQx != NULL); + assert(qy != NULL); + assert(cbQy != NULL); + assert(d != NULL); + assert(cbD != NULL); + +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL + if (!API_EXISTS(EVP_PKEY_get_bn_param)) + { + *cbQx = *cbQy = 0; + *qx = *qy = 0; + if (d) *d = NULL; + if (cbD) *cbD = 0; + return 0; + } +#endif + + int rc = 0; + BIGNUM *xBn = NULL; + BIGNUM *yBn = NULL; + BIGNUM *dBn = NULL; + +#ifdef NEED_OPENSSL_3_0 + // Ensure we have an EC key + if (EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC) + goto error; + + ERR_clear_error(); + + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &xBn)) + goto error; + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &yBn)) + goto error; + + *qx = xBn; + *cbQx = BN_num_bytes(xBn); + *qy = yBn; + *cbQy = BN_num_bytes(yBn); + + if (includePrivate) + { + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &dBn)) + goto error; + + *d = dBn; + *cbD = BN_num_bytes(dBn); + } + else + { + *d = NULL; + *cbD = 0; + } + + // success + return 1; + +error: +#else + (void)pkey; + (void)includePrivate; +#endif + *cbQx = *cbQy = 0; + *qx = *qy = 0; + if (d) *d = NULL; + if (cbD) *cbD = 0; + if (xBn) BN_free(xBn); + if (yBn) BN_free(yBn); + return rc; +} + EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( ECCurveType curveType, uint8_t* qx, int32_t qxLength, @@ -592,3 +716,225 @@ EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( return ret; } + +static ECCurveType NIDToCurveType(int fieldType) +{ + if (fieldType == NID_X9_62_characteristic_two_field) + return Characteristic2; + + if (fieldType == NID_X9_62_prime_field) + return PrimeShortWeierstrass; + + return Unspecified; +} + +int32_t CryptoNative_EvpPKeyGetEcCurveParameters( + const EVP_PKEY* pkey, + int32_t includePrivate, + ECCurveType* curveType, + BIGNUM** qx, int32_t* cbQx, + BIGNUM** qy, int32_t* cbQy, + BIGNUM** d, int32_t* cbD, + BIGNUM** p, int32_t* cbP, + BIGNUM** a, int32_t* cbA, + BIGNUM** b, int32_t* cbB, + BIGNUM** gx, int32_t* cbGx, + BIGNUM** gy, int32_t* cbGy, + BIGNUM** order, int32_t* cbOrder, + BIGNUM** cofactor, int32_t* cbCofactor, + BIGNUM** seed, int32_t* cbSeed) +{ + assert(p != NULL); + assert(cbP != NULL); + assert(a != NULL); + assert(cbA != NULL); + assert(b != NULL); + assert(cbB != NULL); + assert(gx != NULL); + assert(cbGx != NULL); + assert(gy != NULL); + assert(cbGy != NULL); + assert(order != NULL); + assert(cbOrder != NULL); + assert(cofactor != NULL); + assert(cbCofactor != NULL); + assert(seed != NULL); + assert(cbSeed != NULL); + +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL + if (!API_EXISTS(EC_GROUP_new_by_curve_name) || + !API_EXISTS(EC_GROUP_get_field_type) || + !API_EXISTS(EVP_PKEY_get_octet_string_param) || + !API_EXISTS(EC_POINT_oct2point)) + { + return 0; + } +#endif + +#ifdef NEED_OPENSSL_3_0 + ERR_clear_error(); + + // Get the public key parameters first in case any of its 'out' parameters are not initialized + int32_t rc = CryptoNative_EvpPKeyGetEcKeyParameters(pkey, includePrivate, qx, cbQx, qy, cbQy, d, cbD); + + EC_POINT* G = NULL; + BIGNUM* xBn = BN_new(); + BIGNUM* yBn = BN_new(); + BIGNUM* pBn = NULL; + BIGNUM* aBn = NULL; + BIGNUM* bBn = NULL; + BIGNUM* orderBn = NULL; + BIGNUM* cofactorBn = NULL; + size_t sufficientSeedBufferSize = 0; + unsigned char* seedBuffer = NULL; + EC_GROUP* group = NULL; + size_t generatorBufferSize = 0; + unsigned char* generatorBuffer = NULL; + + // Exit if CryptoNative_EvpPKeyGetEcKeyParameters failed + if (rc != 1) + goto error; + + if (!xBn || !yBn) + goto error; + + int curveTypeNID; + if (!CryptoNative_EvpPKeyGetEcGroupNid(pkey, &curveTypeNID) || !curveTypeNID) + goto error; + + // Extract p, a, b + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_P, &pBn)) + goto error; + + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_A, &aBn)) + goto error; + + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_B, &bBn)) + goto error; + + // curveTypeNID will be always NID_X9_62_characteristic_two_field or NID_X9_62_prime_field + group = EC_GROUP_new_by_curve_name(curveTypeNID); + + // In some cases EVP_PKEY_get_field_type can return NID_undef + // and some providers seem to be ignoring OSSL_PKEY_PARAM_EC_FIELD_TYPE. + // This is specifically true for tpm2 provider. + // We can reliably get the field type from the EC_GROUP. + int fieldTypeNID = EC_GROUP_get_field_type(group); + + *curveType = NIDToCurveType(fieldTypeNID); + if (*curveType == Unspecified) + goto error; + + if (!group) + goto error; + + if (!EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0, &generatorBufferSize)) + goto error; + + generatorBuffer = (unsigned char*)OPENSSL_malloc(generatorBufferSize); + if (!EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_EC_GENERATOR, generatorBuffer, generatorBufferSize, &generatorBufferSize)) + goto error; + + G = EC_POINT_new(group); + + if (!G) + goto error; + + if (!EC_POINT_oct2point(group, G, generatorBuffer, generatorBufferSize, NULL)) + goto error; + + if (!EcPointGetAffineCoordinates(group, *curveType, G, xBn, yBn)) + goto error; + + // Extract order (n) + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_ORDER, &orderBn)) + goto error; + + // Extract cofactor (h) + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_COFACTOR, &cofactorBn)) + goto error; + + // Extract seed (optional) + if (!seed || !EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_EC_SEED, NULL, 0, &sufficientSeedBufferSize)) + { + *seed = NULL; + *cbSeed = 0; + } + else + { + seedBuffer = (unsigned char*)OPENSSL_malloc(sufficientSeedBufferSize); + size_t actualSeedSize; + if (EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_EC_SEED, seedBuffer, sufficientSeedBufferSize, &actualSeedSize)) + { + *cbSeed = SizeTToInt32(actualSeedSize); + *seed = BN_bin2bn(seedBuffer, *cbSeed, NULL); + + if (!*seed) + { + *cbSeed = 0; + } + } + else + { + *seed = NULL; + *cbSeed = 0; + } + } + + // Success; assign variables + *gx = xBn; *cbGx = BN_num_bytes(xBn); + *gy = yBn; *cbGy = BN_num_bytes(yBn); + *p = pBn; *cbP = BN_num_bytes(pBn); + *a = aBn; *cbA = BN_num_bytes(aBn); + *b = bBn; *cbB = BN_num_bytes(bBn); + *order = orderBn; *cbOrder = BN_num_bytes(orderBn); + *cofactor = cofactorBn; *cbCofactor = BN_num_bytes(cofactorBn); + + rc = 1; + goto exit; + +error: + // Clear out variables from CryptoNative_EvpPKeyGetEcKeyParameters + if (*qx) BN_free((BIGNUM*)*qx); + if (*qy) BN_free(*qy); + if (d && *d) BN_clear_free(*d); + + *cbQx = *cbQy = 0; + *qx = *qy = NULL; + if (d) *d = NULL; + if (cbD) *cbD = 0; + + // Clear our out variables + *curveType = Unspecified; + *cbP = *cbA = *cbB = *cbGx = *cbGy = *cbOrder = *cbCofactor = *cbSeed = 0; + *p = *a = *b = *gx = *gy = *order = *cofactor = *seed = NULL; + + if (xBn) BN_free(xBn); + if (yBn) BN_free(yBn); + if (pBn) BN_free(pBn); + if (aBn) BN_free(aBn); + if (bBn) BN_free(bBn); + if (orderBn) BN_free(orderBn); + if (cofactorBn) BN_free(cofactorBn); + +exit: + // Clear out temporary variables + if (group) EC_GROUP_free(group); + if (generatorBuffer) OPENSSL_free(generatorBuffer); + if (G) EC_POINT_free(G); + if (seedBuffer) OPENSSL_free(seedBuffer); + + return rc; +#else + (void)pkey; + (void)includePrivate; + *cbQx = *cbQy = 0; + *qx = *qy = NULL; + if (d) *d = NULL; + if (cbD) *cbD = 0; + *curveType = Unspecified; + *cbP = *cbA = *cbB = *cbGx = *cbGy = *cbOrder = *cbCofactor = *cbSeed = 0; + *p = *a = *b = *gx = *gy = *order = *cofactor = *seed = NULL; + return 0; +#endif +} diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.h b/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.h index f8287f6fa49aaa..ba16b5450c80c8 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ecc_import_export.h @@ -55,6 +55,23 @@ PALEXPORT int32_t CryptoNative_EcKeyCreateByKeyParameters( uint8_t* qy, int32_t qyLength, uint8_t* d, int32_t dLength); +/* +Gets the NID of the curve name as an oid value for the specified EVP_PKEY. + +Returns 1 upon success, otherwise 0. +*/ +PALEXPORT int32_t CryptoNative_EvpPKeyGetEcGroupNid(const EVP_PKEY *pkey, int32_t* nidName); + +/* +Returns the EC curve type of the given EVP_PKEY. +*/ +PALEXPORT int32_t CryptoNative_EvpPKeyGetEcKeyParameters( + const EVP_PKEY* pkey, + int32_t includePrivate, + BIGNUM** qx, int32_t* cbQx, + BIGNUM** qy, int32_t* cbQy, + BIGNUM** d, int32_t* cbD); + /* Returns the new EC_KEY instance using the explicit parameters. */ @@ -71,3 +88,22 @@ PALEXPORT EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters( uint8_t* order, int32_t nLength, uint8_t* cofactor, int32_t hLength, uint8_t* seed, int32_t sLength); + +/* +Returns the ECC curve parameters of the given EVP_PKEY. +*/ +PALEXPORT int32_t CryptoNative_EvpPKeyGetEcCurveParameters( + const EVP_PKEY* pkey, + int32_t includePrivate, + ECCurveType* curveType, + BIGNUM** qx, int32_t* cbQx, + BIGNUM** qy, int32_t* cbQy, + BIGNUM** d, int32_t* cbD, + BIGNUM** p, int32_t* cbP, + BIGNUM** a, int32_t* cbA, + BIGNUM** b, int32_t* cbB, + BIGNUM** gx, int32_t* cbGx, + BIGNUM** gy, int32_t* cbGy, + BIGNUM** order, int32_t* cbOrder, + BIGNUM** cofactor, int32_t* cbCofactor, + BIGNUM** seed, int32_t* cbSeed); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_kem.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_kem.c new file mode 100644 index 00000000000000..909e7a76e80e29 --- /dev/null +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_kem.c @@ -0,0 +1,292 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "openssl.h" +#include "pal_evp_kem.h" +#include "pal_utilities.h" + +#include + +static int32_t GetKeyOctetStringParam(const EVP_PKEY* pKey, + const char* name, + uint8_t* destination, + int32_t destinationLength) +{ + assert(pKey); + assert(destination); + assert(name); + +#ifdef NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_PKEY_get_octet_string_param)) + { + ERR_clear_error(); + + size_t destinationLengthT = Int32ToSizeT(destinationLength); + size_t outLength = 0; + + int ret = EVP_PKEY_get_octet_string_param(pKey, name, NULL, 0, &outLength); + + if (ret != 1) + { + return -1; + } + + ret = EVP_PKEY_get_octet_string_param(pKey, name, (unsigned char*)destination, destinationLengthT, &outLength); + + if (ret != 1) + { + return 0; + } + + if (outLength != destinationLengthT) + { + return -2; + } + + return 1; + } +#else + (void)pKey; + (void)name; + (void)destination; + (void)destinationLength; +#endif + + return 0; +} + +int32_t CryptoNative_EvpKemAvailable(const char* algorithm) +{ +#ifdef NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_KEM_fetch)) + { + assert(API_EXISTS(EVP_KEM_free)); + ERR_clear_error(); + EVP_KEM* kem = EVP_KEM_fetch(NULL, algorithm, NULL); + + if (kem) + { + EVP_KEM_free(kem); + return 1; + } + } +#else + (void)algorithm; +#endif + + return 0; +} + +EVP_PKEY* CryptoNative_EvpKemGeneratePkey(const char* kemName, uint8_t* seed, int32_t seedLength) +{ + assert(kemName); + assert((seed == NULL) == (seedLength == 0)); + +#ifdef NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_PKEY_CTX_new_from_name)) + { + assert( + API_EXISTS(OSSL_PARAM_construct_octet_string) && + API_EXISTS(OSSL_PARAM_construct_end) && + API_EXISTS(EVP_PKEY_CTX_set_params)); + + ERR_clear_error(); + + EVP_PKEY_CTX* ctx = NULL; + EVP_PKEY* key = NULL; + ctx = EVP_PKEY_CTX_new_from_name(NULL, kemName, NULL); + + if (ctx == NULL) + { + goto done; + } + + if (EVP_PKEY_keygen_init(ctx) != 1) + { + goto done; + } + + if (seed && seedLength > 0) + { + size_t seedLengthT = Int32ToSizeT(seedLength); + OSSL_PARAM params[] = + { + OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ML_KEM_SEED, (void*)seed, seedLengthT), + OSSL_PARAM_construct_end(), + }; + + if (EVP_PKEY_CTX_set_params(ctx, params) != 1) + { + goto done; + } + } + + if (EVP_PKEY_keygen(ctx, &key) != 1) + { + if (key != NULL) + { + EVP_PKEY_free(key); + key = NULL; + } + + goto done; + } +done: + if (ctx) + { + EVP_PKEY_CTX_free(ctx); + } + + return key; + } +#else + (void)kemName; + (void)seed; + (void)seedLength; +#endif + + return NULL; +} + +int32_t CryptoNative_EvpKemEncapsulate(EVP_PKEY* pKey, + uint8_t* ciphertext, + int32_t ciphertextLength, + uint8_t* sharedSecret, + int32_t sharedSecretLength) +{ + assert(pKey); + assert(ciphertext); + assert(sharedSecret); + +#ifdef NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_PKEY_encapsulate_init)) + { + assert(API_EXISTS(EVP_PKEY_CTX_new_from_pkey) && API_EXISTS(EVP_PKEY_encapsulate)); + ERR_clear_error(); + + EVP_PKEY_CTX* ctx = NULL; + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pKey, NULL); + int32_t ret = 0; + + if (ctx == NULL) + { + goto done; + } + + if (EVP_PKEY_encapsulate_init(ctx, NULL) != 1) + { + goto done; + } + + size_t ciphertextLengthT = Int32ToSizeT(ciphertextLength); + size_t sharedSecretLengthT = Int32ToSizeT(sharedSecretLength); + + if (EVP_PKEY_encapsulate(ctx, ciphertext, &ciphertextLengthT, sharedSecret, &sharedSecretLengthT) != 1) + { + goto done; + } + + if (ciphertextLengthT != Int32ToSizeT(ciphertextLength) || + sharedSecretLengthT != Int32ToSizeT(sharedSecretLength)) + { + ret = -1; + } + + ret = 1; + +done: + if (ctx != NULL) + { + EVP_PKEY_CTX_free(ctx); + } + + return ret; + } +#endif + + (void)pKey; + (void)ciphertext; + (void)ciphertextLength; + (void)sharedSecret; + (void)sharedSecretLength; + return 0; +} + +int32_t CryptoNative_EvpKemDecapsulate(EVP_PKEY* pKey, + const uint8_t* ciphertext, + int32_t ciphertextLength, + uint8_t* sharedSecret, + int32_t sharedSecretLength) +{ + assert(pKey); + assert(ciphertext); + assert(sharedSecret); + +#ifdef NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_PKEY_decapsulate_init)) + { + assert(API_EXISTS(EVP_PKEY_CTX_new_from_pkey) && API_EXISTS(EVP_PKEY_decapsulate)); + ERR_clear_error(); + + EVP_PKEY_CTX* ctx = NULL; + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pKey, NULL); + int32_t ret = 0; + + if (ctx == NULL) + { + goto done; + } + + if (EVP_PKEY_decapsulate_init(ctx, NULL) != 1) + { + goto done; + } + + size_t ciphertextLengthT = Int32ToSizeT(ciphertextLength); + size_t sharedSecretLengthT = Int32ToSizeT(sharedSecretLength); + + if (EVP_PKEY_decapsulate(ctx, sharedSecret, &sharedSecretLengthT, ciphertext, ciphertextLengthT) != 1) + { + goto done; + } + + if (sharedSecretLengthT != Int32ToSizeT(sharedSecretLength)) + { + ret = -1; + goto done; + } + + ret = 1; + +done: + if (ctx != NULL) + { + EVP_PKEY_CTX_free(ctx); + } + + return ret; + } +#endif + + (void)pKey; + (void)ciphertext; + (void)ciphertextLength; + (void)sharedSecret; + (void)sharedSecretLength; + return 0; +} + +int32_t CryptoNative_EvpKemExportPrivateSeed(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength) +{ + return GetKeyOctetStringParam(pKey, OSSL_PKEY_PARAM_ML_KEM_SEED, destination, destinationLength); +} + +int32_t CryptoNative_EvpKemExportDecapsulationKey(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength) +{ + return GetKeyOctetStringParam(pKey, OSSL_PKEY_PARAM_PRIV_KEY, destination, destinationLength); +} + +int32_t CryptoNative_EvpKemExportEncapsulationKey(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength) +{ + return GetKeyOctetStringParam(pKey, OSSL_PKEY_PARAM_PUB_KEY, destination, destinationLength); +} diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_kem.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp_kem.h new file mode 100644 index 00000000000000..fb8e324f99f2de --- /dev/null +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_kem.h @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal_compiler.h" +#include +#include "opensslshim.h" + +PALEXPORT int32_t CryptoNative_EvpKemAvailable(const char* algorithm); +PALEXPORT EVP_PKEY* CryptoNative_EvpKemGeneratePkey(const char* kemName, uint8_t* seed, int32_t seedLength); +PALEXPORT int32_t CryptoNative_EvpKemExportPrivateSeed(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength); +PALEXPORT int32_t CryptoNative_EvpKemExportDecapsulationKey(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength); +PALEXPORT int32_t CryptoNative_EvpKemExportEncapsulationKey(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength); +PALEXPORT int32_t CryptoNative_EvpKemEncapsulate(EVP_PKEY* pKey, + uint8_t* ciphertext, + int32_t ciphertextLength, + uint8_t* sharedSecret, + int32_t sharedSecretLength); +PALEXPORT int32_t CryptoNative_EvpKemDecapsulate(EVP_PKEY* pKey, + const uint8_t* ciphertext, + int32_t ciphertextLength, + uint8_t* sharedSecret, + int32_t sharedSecretLength); +PALEXPORT EVP_PKEY* CryptoNative_EvpKemImportKey(const char* kemName, uint8_t* key, int32_t keyLength, int32_t privateKey); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c index 14b4f1eaa49ee6..3b498a433a5d87 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c @@ -775,3 +775,65 @@ EVP_PKEY_CTX* EvpPKeyCtxCreateFromPKey(EVP_PKEY* pkey, void* extraHandle) return EVP_PKEY_CTX_new(pkey, NULL); } } + +EVP_PKEY* CryptoNative_EvpPKeyFromData(const char* algorithmName, uint8_t* key, int32_t keyLength, int32_t privateKey) +{ + assert(algorithmName); + assert(key); + assert(keyLength > 0); + +#ifdef NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_PKEY_CTX_new_from_name)) + { + ERR_clear_error(); + EVP_PKEY_CTX* ctx = NULL; + EVP_PKEY* pkey = NULL; + ctx = EVP_PKEY_CTX_new_from_name(NULL, algorithmName, NULL); + + if (ctx == NULL) + { + goto done; + } + + if (EVP_PKEY_fromdata_init(ctx) != 1) + { + goto done; + } + + const char* paramName = privateKey == 0 ? OSSL_PKEY_PARAM_PUB_KEY : OSSL_PKEY_PARAM_PRIV_KEY; + int selection = privateKey == 0 ? EVP_PKEY_PUBLIC_KEY : EVP_PKEY_KEYPAIR; + size_t keyLengthT = Int32ToSizeT(keyLength); + + OSSL_PARAM params[] = + { + OSSL_PARAM_construct_octet_string(paramName, (void*)key, keyLengthT), + OSSL_PARAM_construct_end(), + }; + + if (EVP_PKEY_fromdata(ctx, &pkey, selection, params) != 1) + { + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + + goto done; + } + +done: + if (ctx) + { + EVP_PKEY_CTX_free(ctx); + } + + return pkey; + } +#endif + + (void)algorithmName; + (void)key; + (void)keyLength; + (void)privateKey; + return NULL; +} diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h index f71b64cb07c091..81bb2121b1b8e8 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h @@ -119,6 +119,11 @@ until the EVP_PKEY is destroyed. */ PALEXPORT EVP_PKEY* CryptoNative_LoadKeyFromProvider(const char* providerName, const char* keyUri, void** extraHandle, int32_t* haveProvider); +/* +Loads a key using EVP_PKEY_fromdata_init and EVP_PKEY_fromdata. +*/ +PALEXPORT EVP_PKEY* CryptoNative_EvpPKeyFromData(const char* algorithmName, uint8_t* key, int32_t keyLength, int32_t privateKey); + /* It's a wrapper for EVP_PKEY_CTX_new_from_pkey and EVP_PKEY_CTX_new which handles extraHandle. diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs index b1cb058483ca01..b2fe34f80ee48c 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs @@ -57,6 +57,7 @@ public enum DataType PrecodeMachineDescriptor, StubPrecodeData, FixupPrecodeData, + ThisPtrRetBufPrecodeData, Array, SyncBlock, SyncTableEntry, @@ -89,8 +90,17 @@ public enum DataType MethodImpl, NativeCodeSlot, GCCoverageInfo, + TransitionBlock, + DebuggerEval, + CalleeSavedRegisters, + HijackArgs, Frame, InlinedCallFrame, SoftwareExceptionFrame, + FramedMethodFrame, + FuncEvalFrame, + ResumableFrame, + FaultingExceptionFrame, + HijackFrame, } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubsFactory.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubsFactory.cs index b5dca81d5636b6..2687e1d361fe96 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubsFactory.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubsFactory.cs @@ -16,6 +16,7 @@ IPrecodeStubs IContractFactory.CreateContract(Target target, int return version switch { 1 => new PrecodeStubs_1(target, precodeMachineDescriptor, codePointerFlags), + 2 => new PrecodeStubs_2(target, precodeMachineDescriptor, codePointerFlags), _ => default(PrecodeStubs), }; } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_1.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_1.cs index 4dbb9a9a111ede..1fec6033ad9e9f 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_1.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_1.cs @@ -6,190 +6,34 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; -internal readonly struct PrecodeStubs_1 : IPrecodeStubs +internal struct PrecodeStubs_1_Impl : IPrecodeStubsContractCommonApi { - private readonly Target _target; - private readonly CodePointerFlags _codePointerFlags; - internal readonly Data.PrecodeMachineDescriptor MachineDescriptor; - - internal enum KnownPrecodeType - { - Stub = 1, - PInvokeImport, // also known as NDirectImport in the runtime - Fixup, - ThisPtrRetBuf, - } - - internal abstract class ValidPrecode - { - public TargetPointer InstrPointer { get; } - public KnownPrecodeType PrecodeType { get; } - - protected ValidPrecode(TargetPointer instrPointer, KnownPrecodeType precodeType) - { - InstrPointer = instrPointer; - PrecodeType = precodeType; - } - - internal abstract TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor); - - } - - internal class StubPrecode : ValidPrecode + public static TargetPointer StubPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) { - internal StubPrecode(TargetPointer instrPointer, KnownPrecodeType type = KnownPrecodeType.Stub) : base(instrPointer, type) { } - - internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) - { - TargetPointer stubPrecodeDataAddress = InstrPointer + precodeMachineDescriptor.StubCodePageSize; - Data.StubPrecodeData stubPrecodeData = target.ProcessedData.GetOrAdd(stubPrecodeDataAddress); - return stubPrecodeData.MethodDesc; - } - } - - public sealed class PInvokeImportPrecode : StubPrecode - { - internal PInvokeImportPrecode(TargetPointer instrPointer) : base(instrPointer, KnownPrecodeType.PInvokeImport) { } - } - - public sealed class FixupPrecode : ValidPrecode - { - internal FixupPrecode(TargetPointer instrPointer) : base(instrPointer, KnownPrecodeType.Fixup) { } - internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) - { - TargetPointer fixupPrecodeDataAddress = InstrPointer + precodeMachineDescriptor.StubCodePageSize; - Data.FixupPrecodeData fixupPrecodeData = target.ProcessedData.GetOrAdd(fixupPrecodeDataAddress); - return fixupPrecodeData.MethodDesc; - - } + TargetPointer stubPrecodeDataAddress = instrPointer + precodeMachineDescriptor.StubCodePageSize; + Data.StubPrecodeData_1 stubPrecodeData = target.ProcessedData.GetOrAdd(stubPrecodeDataAddress); + return stubPrecodeData.MethodDesc; } - public sealed class ThisPtrRetBufPrecode : ValidPrecode + public static TargetPointer FixupPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) { - internal ThisPtrRetBufPrecode(TargetPointer instrPointer) : base(instrPointer, KnownPrecodeType.ThisPtrRetBuf) { } - - internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) - { - throw new NotImplementedException(); // TODO(cdac) - } + TargetPointer fixupPrecodeDataAddress = instrPointer + precodeMachineDescriptor.StubCodePageSize; + Data.FixupPrecodeData fixupPrecodeData = target.ProcessedData.GetOrAdd(fixupPrecodeDataAddress); + return fixupPrecodeData.MethodDesc; } - private bool IsAlignedInstrPointer(TargetPointer instrPointer) => _target.IsAlignedToPointerSize(instrPointer); - - private byte ReadPrecodeType(TargetPointer instrPointer) + public static TargetPointer ThisPtrRetBufPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) { - if (MachineDescriptor.ReadWidthOfPrecodeType == 1) - { - byte precodeType = _target.Read(instrPointer + MachineDescriptor.OffsetOfPrecodeType); - return (byte)(precodeType >> MachineDescriptor.ShiftOfPrecodeType); - } - else if (MachineDescriptor.ReadWidthOfPrecodeType == 2) - { - ushort precodeType = _target.Read(instrPointer + MachineDescriptor.OffsetOfPrecodeType); - return (byte)(precodeType >> MachineDescriptor.ShiftOfPrecodeType); - } - else - { - throw new InvalidOperationException($"Invalid precode type width {MachineDescriptor.ReadWidthOfPrecodeType}"); - } + throw new NotImplementedException(); // TODO(cdac) } - private Data.StubPrecodeData GetStubPrecodeData(TargetPointer stubInstrPointer) + public static byte StubPrecodeData_GetType(Data.StubPrecodeData_1 stubPrecodeData) { - TargetPointer stubPrecodeDataAddress = stubInstrPointer + MachineDescriptor.StubCodePageSize; - return _target.ProcessedData.GetOrAdd(stubPrecodeDataAddress); - } - - private KnownPrecodeType? TryGetKnownPrecodeType(TargetPointer instrAddress) - { - // We get the precode type in two phases: - // 1. Read the precode type from the intruction address. - // 2. If it's "stub", look at the stub data and get the actual precode type - it could be stub, - // but it could also be a pinvoke precode - // precode.h Precode::GetType() - byte approxPrecodeType = ReadPrecodeType(instrAddress); - byte exactPrecodeType; - if (approxPrecodeType == MachineDescriptor.StubPrecodeType) - { - // get the actual type from the StubPrecodeData - Data.StubPrecodeData stubPrecodeData = GetStubPrecodeData(instrAddress); - exactPrecodeType = stubPrecodeData.Type; - } - else - { - exactPrecodeType = approxPrecodeType; - } - - if (exactPrecodeType == MachineDescriptor.StubPrecodeType) - { - return KnownPrecodeType.Stub; - } - else if (MachineDescriptor.PInvokeImportPrecodeType is byte ndType && exactPrecodeType == ndType) - { - return KnownPrecodeType.PInvokeImport; - } - else if (MachineDescriptor.FixupPrecodeType is byte fixupType && exactPrecodeType == fixupType) - { - return KnownPrecodeType.Fixup; - } - else if (MachineDescriptor.ThisPointerRetBufPrecodeType is byte thisPtrRetBufType && exactPrecodeType == thisPtrRetBufType) - { - return KnownPrecodeType.ThisPtrRetBuf; - } - else - { - return null; - } - } - - internal TargetPointer CodePointerReadableInstrPointer(TargetCodePointer codePointer) - { - if (_codePointerFlags.HasFlag(CodePointerFlags.HasArm32ThumbBit)) - { - return codePointer.AsTargetPointer & ~1ul; - } - if (_codePointerFlags.HasFlag(CodePointerFlags.HasArm64PtrAuth)) - { - throw new NotImplementedException("CodePointerReadableInstrPointer for ARM64 with pointer authentication"); - } - Debug.Assert(_codePointerFlags == 0); - return codePointer.AsTargetPointer; - } - - - internal ValidPrecode GetPrecodeFromEntryPoint(TargetCodePointer entryPoint) - { - TargetPointer instrPointer = CodePointerReadableInstrPointer(entryPoint); - if (IsAlignedInstrPointer(instrPointer) && TryGetKnownPrecodeType(instrPointer) is KnownPrecodeType precodeType) - { - switch (precodeType) - { - case KnownPrecodeType.Stub: - return new StubPrecode(instrPointer); - case KnownPrecodeType.Fixup: - return new FixupPrecode(instrPointer); - case KnownPrecodeType.PInvokeImport: - return new PInvokeImportPrecode(instrPointer); - case KnownPrecodeType.ThisPtrRetBuf: - return new ThisPtrRetBufPrecode(instrPointer); - default: - break; - } - } - throw new InvalidOperationException($"Invalid precode type 0x{instrPointer:x16}"); - } - public PrecodeStubs_1(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor, CodePointerFlags codePointerFlags) - { - _target = target; - MachineDescriptor = precodeMachineDescriptor; - _codePointerFlags = codePointerFlags; - } - - TargetPointer IPrecodeStubs.GetMethodDescFromStubAddress(TargetCodePointer entryPoint) - { - ValidPrecode precode = GetPrecodeFromEntryPoint(entryPoint); - - return precode.GetMethodDesc(_target, MachineDescriptor); + return stubPrecodeData.Type; } +} +internal sealed class PrecodeStubs_1 : PrecodeStubsCommon +{ + public PrecodeStubs_1(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor, CodePointerFlags codePointerFlags) : base(target, precodeMachineDescriptor, codePointerFlags) { } } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_2.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_2.cs new file mode 100644 index 00000000000000..37d73a2df7b288 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_2.cs @@ -0,0 +1,41 @@ +// 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.Diagnostics; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +internal struct PrecodeStubs_2_Impl : IPrecodeStubsContractCommonApi +{ + public static TargetPointer StubPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) + { + TargetPointer stubPrecodeDataAddress = instrPointer + precodeMachineDescriptor.StubCodePageSize; + Data.StubPrecodeData_2 stubPrecodeData = target.ProcessedData.GetOrAdd(stubPrecodeDataAddress); + return stubPrecodeData.SecretParam; + } + + public static TargetPointer FixupPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) + { + // Version 2 of this contract behaves just like version 1 + return PrecodeStubs_1_Impl.FixupPrecode_GetMethodDesc(instrPointer, target, precodeMachineDescriptor); + } + + public static TargetPointer ThisPtrRetBufPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) + { + TargetPointer stubPrecodeDataAddress = instrPointer + precodeMachineDescriptor.StubCodePageSize; + Data.StubPrecodeData_2 stubPrecodeData = target.ProcessedData.GetOrAdd(stubPrecodeDataAddress); + Data.ThisPtrRetBufPrecodeData thisPtrRetBufPrecodeData = target.ProcessedData.GetOrAdd(stubPrecodeData.SecretParam); + return thisPtrRetBufPrecodeData.MethodDesc; + } + + public static byte StubPrecodeData_GetType(Data.StubPrecodeData_2 stubPrecodeData) + { + return stubPrecodeData.Type; + } +} + +internal sealed class PrecodeStubs_2 : PrecodeStubsCommon +{ + public PrecodeStubs_2(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor, CodePointerFlags codePointerFlags) : base(target, precodeMachineDescriptor, codePointerFlags) { } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_Common.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_Common.cs new file mode 100644 index 00000000000000..aeb97ab7a522cd --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/PrecodeStubs_Common.cs @@ -0,0 +1,199 @@ +// 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.Diagnostics; +using Microsoft.Diagnostics.DataContractReader.Data; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +// Interface used to abstract behavior which may be different between multiple versions of the precode stub implementations +internal interface IPrecodeStubsContractCommonApi +{ + public static abstract TargetPointer StubPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor); + public static abstract TargetPointer ThisPtrRetBufPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor); + public static abstract TargetPointer FixupPrecode_GetMethodDesc(TargetPointer instrPointer, Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor); + public static abstract byte StubPrecodeData_GetType(TStubPrecodeData stubPrecodeData); +} + +internal class PrecodeStubsCommon : IPrecodeStubs where TPrecodeStubsImplementation : IPrecodeStubsContractCommonApi where TStubPrecodeData : IData +{ + private readonly Target _target; + private readonly CodePointerFlags _codePointerFlags; + internal readonly Data.PrecodeMachineDescriptor MachineDescriptor; + + internal enum KnownPrecodeType + { + Stub = 1, + PInvokeImport, // also known as NDirectImport in the runtime + Fixup, + ThisPtrRetBuf, + } + + internal abstract class ValidPrecode + { + public TargetPointer InstrPointer { get; } + public KnownPrecodeType PrecodeType { get; } + + protected ValidPrecode(TargetPointer instrPointer, KnownPrecodeType precodeType) + { + InstrPointer = instrPointer; + PrecodeType = precodeType; + } + + internal abstract TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor); + + } + + internal class StubPrecode : ValidPrecode + { + internal StubPrecode(TargetPointer instrPointer, KnownPrecodeType type = KnownPrecodeType.Stub) : base(instrPointer, type) { } + + internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) + { + return TPrecodeStubsImplementation.StubPrecode_GetMethodDesc(InstrPointer, target, precodeMachineDescriptor); + } + } + + public sealed class PInvokeImportPrecode : StubPrecode + { + internal PInvokeImportPrecode(TargetPointer instrPointer) : base(instrPointer, KnownPrecodeType.PInvokeImport) { } + } + + public sealed class FixupPrecode : ValidPrecode + { + internal FixupPrecode(TargetPointer instrPointer) : base(instrPointer, KnownPrecodeType.Fixup) { } + internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) + { + return TPrecodeStubsImplementation.FixupPrecode_GetMethodDesc(InstrPointer, target, precodeMachineDescriptor); + } + } + + public sealed class ThisPtrRetBufPrecode : ValidPrecode + { + internal ThisPtrRetBufPrecode(TargetPointer instrPointer) : base(instrPointer, KnownPrecodeType.ThisPtrRetBuf) { } + + internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor) + { + return TPrecodeStubsImplementation.ThisPtrRetBufPrecode_GetMethodDesc(InstrPointer, target, precodeMachineDescriptor); + } + } + + private bool IsAlignedInstrPointer(TargetPointer instrPointer) => _target.IsAlignedToPointerSize(instrPointer); + + private byte ReadPrecodeType(TargetPointer instrPointer) + { + if (MachineDescriptor.ReadWidthOfPrecodeType == 1) + { + byte precodeType = _target.Read(instrPointer + MachineDescriptor.OffsetOfPrecodeType); + return (byte)(precodeType >> MachineDescriptor.ShiftOfPrecodeType); + } + else if (MachineDescriptor.ReadWidthOfPrecodeType == 2) + { + ushort precodeType = _target.Read(instrPointer + MachineDescriptor.OffsetOfPrecodeType); + return (byte)(precodeType >> MachineDescriptor.ShiftOfPrecodeType); + } + else + { + throw new InvalidOperationException($"Invalid precode type width {MachineDescriptor.ReadWidthOfPrecodeType}"); + } + } + + private TStubPrecodeData GetStubPrecodeData(TargetPointer stubInstrPointer) + { + TargetPointer stubPrecodeDataAddress = stubInstrPointer + MachineDescriptor.StubCodePageSize; + return _target.ProcessedData.GetOrAdd(stubPrecodeDataAddress); + } + + private KnownPrecodeType? TryGetKnownPrecodeType(TargetPointer instrAddress) + { + // We get the precode type in two phases: + // 1. Read the precode type from the intruction address. + // 2. If it's "stub", look at the stub data and get the actual precode type - it could be stub, + // but it could also be a pinvoke precode or a ThisPtrRetBufPrecode + // precode.h Precode::GetType() + byte approxPrecodeType = ReadPrecodeType(instrAddress); + byte exactPrecodeType; + if (approxPrecodeType == MachineDescriptor.StubPrecodeType) + { + // get the actual type from the StubPrecodeData + TStubPrecodeData stubPrecodeData = GetStubPrecodeData(instrAddress); + exactPrecodeType = TPrecodeStubsImplementation.StubPrecodeData_GetType(stubPrecodeData); + } + else + { + exactPrecodeType = approxPrecodeType; + } + + if (exactPrecodeType == MachineDescriptor.StubPrecodeType) + { + return KnownPrecodeType.Stub; + } + else if (MachineDescriptor.PInvokeImportPrecodeType is byte ndType && exactPrecodeType == ndType) + { + return KnownPrecodeType.PInvokeImport; + } + else if (MachineDescriptor.FixupPrecodeType is byte fixupType && exactPrecodeType == fixupType) + { + return KnownPrecodeType.Fixup; + } + else if (MachineDescriptor.ThisPointerRetBufPrecodeType is byte thisPtrRetBufType && exactPrecodeType == thisPtrRetBufType) + { + return KnownPrecodeType.ThisPtrRetBuf; + } + else + { + return null; + } + } + + internal TargetPointer CodePointerReadableInstrPointer(TargetCodePointer codePointer) + { + if (_codePointerFlags.HasFlag(CodePointerFlags.HasArm32ThumbBit)) + { + return codePointer.AsTargetPointer & ~1ul; + } + if (_codePointerFlags.HasFlag(CodePointerFlags.HasArm64PtrAuth)) + { + throw new NotImplementedException("CodePointerReadableInstrPointer for ARM64 with pointer authentication"); + } + Debug.Assert(_codePointerFlags == 0); + return codePointer.AsTargetPointer; + } + + + internal ValidPrecode GetPrecodeFromEntryPoint(TargetCodePointer entryPoint) + { + TargetPointer instrPointer = CodePointerReadableInstrPointer(entryPoint); + if (IsAlignedInstrPointer(instrPointer) && TryGetKnownPrecodeType(instrPointer) is KnownPrecodeType precodeType) + { + switch (precodeType) + { + case KnownPrecodeType.Stub: + return new StubPrecode(instrPointer); + case KnownPrecodeType.Fixup: + return new FixupPrecode(instrPointer); + case KnownPrecodeType.PInvokeImport: + return new PInvokeImportPrecode(instrPointer); + case KnownPrecodeType.ThisPtrRetBuf: + return new ThisPtrRetBufPrecode(instrPointer); + default: + break; + } + } + throw new InvalidOperationException($"Invalid precode type 0x{instrPointer:x16}"); + } + public PrecodeStubsCommon(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor, CodePointerFlags codePointerFlags) + { + _target = target; + MachineDescriptor = precodeMachineDescriptor; + _codePointerFlags = codePointerFlags; + } + + TargetPointer IPrecodeStubs.GetMethodDescFromStubAddress(TargetCodePointer entryPoint) + { + ValidPrecode precode = GetPrecodeFromEntryPoint(entryPoint); + + return precode.GetMethodDesc(_target, MachineDescriptor); + } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/AMD64Context.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/AMD64Context.cs index a56fc168d9b73b..23c54aa48b2d72 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/AMD64Context.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/AMD64Context.cs @@ -25,6 +25,8 @@ public enum ContextFlagsValues : uint CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS, CONTEXT_XSTATE = CONTEXT_AMD | 0x40, CONTEXT_KERNEL_CET = CONTEXT_AMD | 0x80, + + CONTEXT_AREA_MASK = 0xFFFF, } public readonly uint Size => 0x4d0; diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ARM64Context.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ARM64Context.cs index 6be29853aa6f47..5ab9258755d00d 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ARM64Context.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ARM64Context.cs @@ -21,8 +21,11 @@ public enum ContextFlagsValues : uint CONTEXT_FLOATING_POINT = CONTEXT_ARM64 | 0x4, CONTEXT_DEBUG_REGISTERS = CONTEXT_ARM64 | 0x8, CONTEXT_X18 = CONTEXT_ARM64 | 0x10, + CONTEXT_XSTATE = CONTEXT_ARM64 | 0x20, CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT, CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_X18, + + CONTEXT_AREA_MASK = 0xFFFF, } public readonly uint Size => 0x390; diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ContextHolder.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ContextHolder.cs index b5d194d0824fc2..3e9091533e6da7 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ContextHolder.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ContextHolder.cs @@ -2,11 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Runtime.InteropServices; namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; -public class CotnextHolder : IPlatformAgnosticContext where T : unmanaged, IPlatformContext +public class ContextHolder<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T> : IPlatformAgnosticContext, IEquatable> + where T : unmanaged, IPlatformContext { public T Context; @@ -42,7 +45,58 @@ public unsafe byte[] GetBytes() Span byteSpan = MemoryMarshal.AsBytes(structSpan); return byteSpan.ToArray(); } - public IPlatformAgnosticContext Clone() => new CotnextHolder() { Context = Context }; + public IPlatformAgnosticContext Clone() => new ContextHolder() { Context = Context }; public void Clear() => Context = default; public void Unwind(Target target) => Context.Unwind(target); + + public bool TrySetRegister(Target target, string fieldName, TargetNUInt value) + { + if (typeof(T).GetField(fieldName) is not FieldInfo field) return false; + switch (field.FieldType) + { + case Type t when t == typeof(ulong) && target.PointerSize == sizeof(ulong): + field.SetValueDirect(__makeref(Context), value.Value); + return true; + case Type t when t == typeof(uint) && target.PointerSize == sizeof(uint): + field.SetValueDirect(__makeref(Context), (uint)value.Value); + return true; + default: + return false; + } + } + + public bool TryReadRegister(Target target, string fieldName, out TargetNUInt value) + { + value = default; + if (typeof(T).GetField(fieldName) is not FieldInfo field) return false; + object? fieldValue = field.GetValue(Context); + if (fieldValue is ulong ul && target.PointerSize == sizeof(ulong)) + { + value = new(ul); + return true; + } + if (fieldValue is uint ui && target.PointerSize == sizeof(uint)) + { + value = new(ui); + return true; + } + return false; + } + + public bool Equals(ContextHolder? other) + { + if (GetType() != other?.GetType()) + { + return false; + } + + return Context.Equals(other.Context); + } + + public override bool Equals(object? obj) + { + return Equals(obj as ContextHolder); + } + + public override int GetHashCode() => Context.GetHashCode(); } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformAgnosticContext.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformAgnosticContext.cs index 7cb0db6ea79a54..8a82caf4cb2abd 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformAgnosticContext.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformAgnosticContext.cs @@ -19,6 +19,8 @@ public interface IPlatformAgnosticContext public abstract void FillFromBuffer(Span buffer); public abstract byte[] GetBytes(); public abstract IPlatformAgnosticContext Clone(); + public abstract bool TrySetRegister(Target target, string fieldName, TargetNUInt value); + public abstract bool TryReadRegister(Target target, string fieldName, out TargetNUInt value); public abstract void Unwind(Target target); public static IPlatformAgnosticContext GetContextForPlatform(Target target) @@ -28,10 +30,10 @@ public static IPlatformAgnosticContext GetContextForPlatform(Target target) case Target.CorDebugPlatform.CORDB_PLATFORM_WINDOWS_AMD64: case Target.CorDebugPlatform.CORDB_PLATFORM_POSIX_AMD64: case Target.CorDebugPlatform.CORDB_PLATFORM_MAC_AMD64: - return new CotnextHolder(); + return new ContextHolder(); case Target.CorDebugPlatform.CORDB_PLATFORM_POSIX_ARM64: case Target.CorDebugPlatform.CORDB_PLATFORM_WINDOWS_ARM64: - return new CotnextHolder(); + return new ContextHolder(); default: throw new InvalidOperationException($"Unsupported platform {target.Platform}"); } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IContext.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformContext.cs similarity index 99% rename from src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IContext.cs rename to src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformContext.cs index 7a8c3bf1ebacb3..cee2c4fe9fce42 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IContext.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformContext.cs @@ -11,5 +11,6 @@ public interface IPlatformContext public TargetPointer StackPointer { get; set; } public TargetPointer InstructionPointer { get; set; } public TargetPointer FramePointer { get; set; } + public abstract void Unwind(Target target); } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/Unwinder.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/Unwinder.cs index b977d1d263a731..925d8d75d8ba0c 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/Unwinder.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/Unwinder.cs @@ -104,12 +104,17 @@ private void Dispose(bool disposing) [UnmanagedCallersOnly] private static unsafe int ReadFromTarget(ulong address, void* pBuffer, int bufferSize, void* context) { - if (GCHandle.FromIntPtr((IntPtr)context).Target is not CallbackContext callbackContext) + CallbackContext callbackContext = (CallbackContext)GCHandle.FromIntPtr((IntPtr)context).Target!; + Span span = new Span(pBuffer, bufferSize); + try { + callbackContext.Target.ReadBuffer(address, span); + } + catch (InvalidOperationException) + { + // if the read fails, the unwinder behavior changes. Return failing HR instead of throwing return -1; } - Span span = new Span(pBuffer, bufferSize); - callbackContext.Target.ReadBuffer(address, span); return 0; } @@ -119,10 +124,7 @@ private static unsafe int ReadFromTarget(ulong address, void* pBuffer, int buffe [UnmanagedCallersOnly] private static unsafe int GetAllocatedBuffer(int bufferSize, void** ppBuffer, void* context) { - if (GCHandle.FromIntPtr((IntPtr)context).Target is not CallbackContext callbackContext) - { - return -1; - } + CallbackContext callbackContext = (CallbackContext)GCHandle.FromIntPtr((IntPtr)context).Target!; *ppBuffer = NativeMemory.Alloc((nuint)bufferSize); callbackContext.AllocatedRegions.Add((IntPtr)(*ppBuffer)); return 0; @@ -137,10 +139,7 @@ private static unsafe void GetStackWalkInfo(ulong controlPC, void* pUnwindInfoBa if ((nuint)pUnwindInfoBase != 0) *(nuint*)pUnwindInfoBase = 0; if ((nuint)pFuncEntry != 0) *(nuint*)pFuncEntry = 0; - if (GCHandle.FromIntPtr((IntPtr)context).Target is not CallbackContext callbackContext) - { - return; - } + CallbackContext callbackContext = (CallbackContext)GCHandle.FromIntPtr((IntPtr)context).Target!; IExecutionManager eman = callbackContext.Target.Contracts.ExecutionManager; try diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs new file mode 100644 index 00000000000000..d5649e2a861994 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs @@ -0,0 +1,47 @@ +// 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 Microsoft.Diagnostics.DataContractReader.Data; +using static Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers.AMD64Context; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; + +internal class AMD64FrameHandler(Target target, ContextHolder contextHolder) : BaseFrameHandler(target, contextHolder), IPlatformFrameHandler +{ + private readonly ContextHolder _holder = contextHolder; + + void IPlatformFrameHandler.HandleFaultingExceptionFrame(FaultingExceptionFrame frame) + { + if (frame.TargetContext is not TargetPointer targetContext) + { + throw new InvalidOperationException("Unexpected null context pointer on FaultingExceptionFrame"); + } + _holder.ReadFromAddress(_target, targetContext); + + // Clear the CONTEXT_XSTATE, since the AMD64Context contains just plain CONTEXT structure + // that does not support holding any extended state. + _holder.Context.ContextFlags &= ~(uint)(ContextFlagsValues.CONTEXT_XSTATE & ContextFlagsValues.CONTEXT_AREA_MASK); + } + + void IPlatformFrameHandler.HandleHijackFrame(HijackFrame frame) + { + HijackArgsAMD64 args = _target.ProcessedData.GetOrAdd(frame.HijackArgsPtr); + + _holder.InstructionPointer = frame.ReturnAddress; + if (args.Rsp is TargetPointer rsp) + { + // Windows case, Rsp is passed directly + _holder.StackPointer = rsp; + } + else + { + // Non-Windows case, the stack pointer is the address immediately following HijacksArgs + uint hijackArgsSize = _target.GetTypeInfo(DataType.HijackArgs).Size ?? throw new InvalidOperationException("HijackArgs size is not set"); + _holder.StackPointer = frame.HijackArgsPtr + hijackArgsSize; + } + + Data.CalleeSavedRegisters calleeSavedRegisters = _target.ProcessedData.GetOrAdd(args.CalleeSavedRegisters); + UpdateFromRegisterDict(calleeSavedRegisters.Registers); + } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs new file mode 100644 index 00000000000000..59d8b055ba5078 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs @@ -0,0 +1,44 @@ +// 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.Diagnostics; +using Microsoft.Diagnostics.DataContractReader.Data; +using static Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers.ARM64Context; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; + +internal class ARM64FrameHandler(Target target, ContextHolder contextHolder) : BaseFrameHandler(target, contextHolder), IPlatformFrameHandler +{ + private readonly ContextHolder _holder = contextHolder; + + void IPlatformFrameHandler.HandleFaultingExceptionFrame(FaultingExceptionFrame frame) + { + if (frame.TargetContext is not TargetPointer targetContext) + { + throw new InvalidOperationException("Unexpected null context pointer on FaultingExceptionFrame"); + } + _holder.ReadFromAddress(_target, targetContext); + + // Clear the CONTEXT_XSTATE, since the ARM64Context contains just plain CONTEXT structure + // that does not support holding any extended state. + _holder.Context.ContextFlags &= ~(uint)(ContextFlagsValues.CONTEXT_XSTATE & ContextFlagsValues.CONTEXT_AREA_MASK); + } + + void IPlatformFrameHandler.HandleHijackFrame(HijackFrame frame) + { + HijackArgsARM64 args = _target.ProcessedData.GetOrAdd(frame.HijackArgsPtr); + + _holder.InstructionPointer = frame.ReturnAddress; + + // The stack pointer is the address immediately following HijacksArgs + uint hijackArgsSize = _target.GetTypeInfo(DataType.HijackArgs).Size ?? throw new InvalidOperationException("HijackArgs size is not set"); + Debug.Assert(hijackArgsSize % 8 == 0, "HijackArgs contains register values and should be a multiple of 8"); + // The stack must be multiple of 16. So if hijackArgsSize is not multiple of 16 then there must be padding of 8 bytes + hijackArgsSize += hijackArgsSize % 16; + _holder.StackPointer = frame.HijackArgsPtr + hijackArgsSize; + + UpdateFromRegisterDict(args.Registers); + } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/BaseFrameHandler.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/BaseFrameHandler.cs new file mode 100644 index 00000000000000..31e912bdc5fa09 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/BaseFrameHandler.cs @@ -0,0 +1,100 @@ +// 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 Microsoft.Diagnostics.DataContractReader.Data; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; + +/// +/// Abstract base class providing platform agnostic functionality for handling frames. +/// +internal abstract class BaseFrameHandler(Target target, IPlatformAgnosticContext context) +{ + protected readonly Target _target = target; + private readonly IPlatformAgnosticContext _context = context; + + public virtual void HandleInlinedCallFrame(InlinedCallFrame inlinedCallFrame) + { + // if the caller return address is 0, then the call is not active + // and we should not update the context + if (inlinedCallFrame.CallerReturnAddress == 0) + { + return; + } + + _context.InstructionPointer = inlinedCallFrame.CallerReturnAddress; + _context.StackPointer = inlinedCallFrame.CallSiteSP; + _context.FramePointer = inlinedCallFrame.CalleeSavedFP; + } + + public virtual void HandleSoftwareExceptionFrame(SoftwareExceptionFrame softwareExceptionFrame) + { + IPlatformAgnosticContext otherContextHolder = IPlatformAgnosticContext.GetContextForPlatform(_target); + otherContextHolder.ReadFromAddress(_target, softwareExceptionFrame.TargetContext); + + UpdateCalleeSavedRegistersFromOtherContext(otherContextHolder); + + _context.InstructionPointer = otherContextHolder.InstructionPointer; + _context.StackPointer = otherContextHolder.StackPointer; + } + + public virtual void HandleTransitionFrame(FramedMethodFrame framedMethodFrame) + { + Data.TransitionBlock transitionBlock = _target.ProcessedData.GetOrAdd(framedMethodFrame.TransitionBlockPtr); + if (_target.GetTypeInfo(DataType.TransitionBlock).Size is not uint transitionBlockSize) + { + throw new InvalidOperationException("TransitionBlock size is not set"); + } + + _context.InstructionPointer = transitionBlock.ReturnAddress; + _context.StackPointer = framedMethodFrame.TransitionBlockPtr + transitionBlockSize; + + Data.CalleeSavedRegisters calleeSavedRegisters = _target.ProcessedData.GetOrAdd(transitionBlock.CalleeSavedRegisters); + UpdateFromRegisterDict(calleeSavedRegisters.Registers); + } + + public virtual void HandleFuncEvalFrame(FuncEvalFrame funcEvalFrame) + { + Data.DebuggerEval debuggerEval = _target.ProcessedData.GetOrAdd(funcEvalFrame.DebuggerEvalPtr); + + // No context to update if we're doing a func eval from within exception processing. + if (debuggerEval.EvalDuringException) + { + return; + } + _context.ReadFromAddress(_target, debuggerEval.TargetContext); + } + + public virtual void HandleResumableFrame(ResumableFrame frame) + { + _context.ReadFromAddress(_target, frame.TargetContextPtr); + } + + protected void UpdateFromRegisterDict(IReadOnlyDictionary registers) + { + foreach ((string name, TargetNUInt value) in registers) + { + if (!_context.TrySetRegister(_target, name, value)) + { + throw new InvalidOperationException($"Unexpected register {name} found when trying to update context"); + } + } + } + + protected void UpdateCalleeSavedRegistersFromOtherContext(IPlatformAgnosticContext otherContext) + { + foreach (string name in _target.GetTypeInfo(DataType.CalleeSavedRegisters).Fields.Keys) + { + if (!otherContext.TryReadRegister(_target, name, out TargetNUInt value)) + { + throw new InvalidOperationException($"Unexpected register {name} in callee saved registers"); + } + if (!_context.TrySetRegister(_target, name, value)) + { + throw new InvalidOperationException($"Unexpected register {name} in callee saved registers"); + } + } + } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs new file mode 100644 index 00000000000000..b48a9e9b5433a9 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs @@ -0,0 +1,164 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; + +internal sealed class FrameIterator +{ + private enum FrameType + { + Unknown, + + InlinedCallFrame, + SoftwareExceptionFrame, + + /* TransitionFrame Types */ + FramedMethodFrame, + CLRToCOMMethodFrame, + PInvokeCalliFrame, + PrestubMethodFrame, + StubDispatchFrame, + CallCountingHelperFrame, + ExternalMethodFrame, + DynamicHelperFrame, + + FuncEvalFrame, + + /* ResumableFrame Types */ + ResumableFrame, + RedirectedThreadFrame, + + FaultingExceptionFrame, + + HijackFrame, + } + + private readonly Target target; + private readonly TargetPointer terminator; + private TargetPointer currentFramePointer; + + internal Data.Frame CurrentFrame => target.ProcessedData.GetOrAdd(currentFramePointer); + + public TargetPointer CurrentFrameAddress => currentFramePointer; + + public FrameIterator(Target target, ThreadData threadData) + { + this.target = target; + terminator = new TargetPointer(target.PointerSize == 8 ? ulong.MaxValue : uint.MaxValue); + currentFramePointer = threadData.Frame; + } + + public bool IsValid() + { + return currentFramePointer != terminator; + } + + public bool Next() + { + if (currentFramePointer == terminator) + return false; + + currentFramePointer = CurrentFrame.Next; + return currentFramePointer != terminator; + } + + public void UpdateContextFromFrame(IPlatformAgnosticContext context) + { + switch (GetFrameType(CurrentFrame)) + { + case FrameType.InlinedCallFrame: + Data.InlinedCallFrame inlinedCallFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleInlinedCallFrame(inlinedCallFrame); + return; + + case FrameType.SoftwareExceptionFrame: + Data.SoftwareExceptionFrame softwareExceptionFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleSoftwareExceptionFrame(softwareExceptionFrame); + return; + + // TransitionFrame type frames + case FrameType.FramedMethodFrame: + case FrameType.CLRToCOMMethodFrame: + case FrameType.PInvokeCalliFrame: + case FrameType.PrestubMethodFrame: + case FrameType.StubDispatchFrame: + case FrameType.CallCountingHelperFrame: + case FrameType.ExternalMethodFrame: + case FrameType.DynamicHelperFrame: + // FrameMethodFrame is the base type for all transition Frames + Data.FramedMethodFrame framedMethodFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleTransitionFrame(framedMethodFrame); + return; + + case FrameType.FuncEvalFrame: + Data.FuncEvalFrame funcEvalFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleFuncEvalFrame(funcEvalFrame); + return; + + // ResumableFrame type frames + case FrameType.ResumableFrame: + case FrameType.RedirectedThreadFrame: + Data.ResumableFrame resumableFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleResumableFrame(resumableFrame); + return; + + case FrameType.FaultingExceptionFrame: + Data.FaultingExceptionFrame faultingExceptionFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleFaultingExceptionFrame(faultingExceptionFrame); + return; + + case FrameType.HijackFrame: + Data.HijackFrame hijackFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); + GetFrameHandler(context).HandleHijackFrame(hijackFrame); + return; + default: + // Unknown Frame type. This could either be a Frame that we don't know how to handle, + // or a Frame that does not update the context. + return; + } + } + + public bool IsInlineCallFrameWithActiveCall() + { + if (GetFrameType(CurrentFrame) != FrameType.InlinedCallFrame) + { + return false; + } + Data.InlinedCallFrame inlinedCallFrame = target.ProcessedData.GetOrAdd(currentFramePointer); + return inlinedCallFrame.CallerReturnAddress != 0; + } + + private FrameType GetFrameType(Data.Frame frame) + { + foreach (FrameType frameType in Enum.GetValues()) + { + TargetPointer typeVptr; + try + { + // not all Frames are in all builds, so we need to catch the exception + typeVptr = target.ReadGlobalPointer(frameType.ToString() + "Identifier"); + if (frame.Identifier == typeVptr) + { + return frameType; + } + } + catch (InvalidOperationException) + { + } + } + + return FrameType.Unknown; + } + + private IPlatformFrameHandler GetFrameHandler(IPlatformAgnosticContext context) + { + return context switch + { + ContextHolder contextHolder => new AMD64FrameHandler(target, contextHolder), + ContextHolder contextHolder => new ARM64FrameHandler(target, contextHolder), + _ => throw new InvalidOperationException("Unsupported context type"), + }; + } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/IPlatformFrameHandler.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/IPlatformFrameHandler.cs new file mode 100644 index 00000000000000..28e40d281763d2 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/IPlatformFrameHandler.cs @@ -0,0 +1,21 @@ +// 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 Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; + +/// +/// Interface for handling platform-specific frames. +/// +internal interface IPlatformFrameHandler +{ + void HandleInlinedCallFrame(Data.InlinedCallFrame frame); + void HandleSoftwareExceptionFrame(Data.SoftwareExceptionFrame frame); + void HandleTransitionFrame(Data.FramedMethodFrame frame); + void HandleFuncEvalFrame(Data.FuncEvalFrame frame); + void HandleResumableFrame(Data.ResumableFrame frame); + void HandleFaultingExceptionFrame(Data.FaultingExceptionFrame frame); + void HandleHijackFrame(Data.HijackFrame frame); +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameIterator.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameIterator.cs deleted file mode 100644 index 3ef20699a973c5..00000000000000 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameIterator.cs +++ /dev/null @@ -1,97 +0,0 @@ -// 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 Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; - -namespace Microsoft.Diagnostics.DataContractReader.Contracts; - -internal sealed class FrameIterator -{ - private static readonly DataType[] SupportedFrameTypes = - [ - DataType.InlinedCallFrame, - DataType.SoftwareExceptionFrame - ]; - - private readonly Target target; - private readonly TargetPointer terminator; - private TargetPointer currentFramePointer; - - internal Data.Frame CurrentFrame => target.ProcessedData.GetOrAdd(currentFramePointer); - - public TargetPointer CurrentFrameAddress => currentFramePointer; - - public FrameIterator(Target target, ThreadData threadData) - { - this.target = target; - terminator = new TargetPointer(target.PointerSize == 8 ? ulong.MaxValue : uint.MaxValue); - currentFramePointer = threadData.Frame; - } - - public bool IsValid() - { - return currentFramePointer != terminator; - } - - public bool Next() - { - if (currentFramePointer == terminator) - return false; - - currentFramePointer = CurrentFrame.Next; - return true; - } - - public bool TryUpdateContext(IPlatformAgnosticContext context) - { - switch (GetFrameType(CurrentFrame)) - { - case DataType.InlinedCallFrame: - Data.InlinedCallFrame inlinedCallFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); - context.Clear(); - context.InstructionPointer = inlinedCallFrame.CallerReturnAddress; - context.StackPointer = inlinedCallFrame.CallSiteSP; - context.FramePointer = inlinedCallFrame.CalleeSavedFP; - return true; - case DataType.SoftwareExceptionFrame: - Data.SoftwareExceptionFrame softwareExceptionFrame = target.ProcessedData.GetOrAdd(CurrentFrame.Address); - context.ReadFromAddress(target, softwareExceptionFrame.TargetContext); - return true; - default: - return false; - } - } - - public bool IsInlineCallFrameWithActiveCall() - { - if (GetFrameType(CurrentFrame) != DataType.InlinedCallFrame) - { - return false; - } - Data.InlinedCallFrame inlinedCallFrame = target.ProcessedData.GetOrAdd(currentFramePointer); - return inlinedCallFrame.CallerReturnAddress != 0; - } - - private DataType GetFrameType(Data.Frame frame) - { - foreach (DataType frameType in SupportedFrameTypes) - { - TargetPointer typeVptr; - try - { - // not all Frames are in all builds, so we need to catch the exception - typeVptr = target.ReadGlobalPointer(frameType.ToString() + "Identifier"); - if (frame.VPtr == typeVptr) - { - return frameType; - } - } - catch (InvalidOperationException) - { - } - } - - return DataType.Unknown; - } -} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/StackWalk_1.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/StackWalk_1.cs index 24f0c9c19e5908..b5939c9a6b78c9 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/StackWalk_1.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/StackWalk_1.cs @@ -82,7 +82,7 @@ private bool Next(StackWalkData handle) handle.FrameIter.Next(); break; case StackWalkState.SW_FRAME: - handle.FrameIter.TryUpdateContext(handle.Context); + handle.FrameIter.UpdateContextFromFrame(handle.Context); if (!handle.FrameIter.IsInlineCallFrameWithActiveCall()) { handle.FrameIter.Next(); diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/CalleeSavedRegisters.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/CalleeSavedRegisters.cs new file mode 100644 index 00000000000000..d826f505c00c38 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/CalleeSavedRegisters.cs @@ -0,0 +1,26 @@ +// 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; + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class CalleeSavedRegisters : IData +{ + static CalleeSavedRegisters IData.Create(Target target, TargetPointer address) + => new CalleeSavedRegisters(target, address); + + public CalleeSavedRegisters(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.CalleeSavedRegisters); + Dictionary registers = new Dictionary(type.Fields.Count); + foreach ((string name, Target.FieldInfo field) in type.Fields) + { + TargetNUInt value = target.ReadNUInt(address + (ulong)field.Offset); + registers.Add(name, value); + } + Registers = registers; + } + + public IReadOnlyDictionary Registers { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/DebuggerEval.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/DebuggerEval.cs new file mode 100644 index 00000000000000..31352b4cc6880a --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/DebuggerEval.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. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class DebuggerEval : IData +{ + static DebuggerEval IData.Create(Target target, TargetPointer address) + => new DebuggerEval(target, address); + + public DebuggerEval(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.DebuggerEval); + TargetContext = address + (ulong)type.Fields[nameof(TargetContext)].Offset; + EvalDuringException = target.Read(address + (ulong)type.Fields[nameof(EvalDuringException)].Offset) != 0; + Address = address; + } + + public TargetPointer Address { get; } + public TargetPointer TargetContext { get; } + public bool EvalDuringException { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs new file mode 100644 index 00000000000000..a205b59f78bb41 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class FaultingExceptionFrame : IData +{ + static FaultingExceptionFrame IData.Create(Target target, TargetPointer address) + => new FaultingExceptionFrame(target, address); + + public FaultingExceptionFrame(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.FaultingExceptionFrame); + + // TargetContextPtr only exists when FEATURE_EH_FUNCLETS is defined + if (type.Fields.ContainsKey(nameof(TargetContext))) + { + TargetContext = address + (ulong)type.Fields[nameof(TargetContext)].Offset; + } + Address = address; + } + + public TargetPointer Address { get; } + public TargetPointer? TargetContext { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/Frame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/Frame.cs index b6939f9d70b3bc..cee27f37f723ad 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/Frame.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/Frame.cs @@ -1,9 +1,6 @@ // 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; - namespace Microsoft.Diagnostics.DataContractReader.Data; internal sealed class Frame : IData @@ -16,10 +13,10 @@ public Frame(Target target, TargetPointer address) Address = address; Target.TypeInfo type = target.GetTypeInfo(DataType.Frame); Next = target.ReadPointer(address + (ulong)type.Fields[nameof(Next)].Offset); - VPtr = target.ReadPointer(address); + Identifier = target.ReadPointer(address); } public TargetPointer Address { get; init; } - public TargetPointer VPtr { get; init; } + public TargetPointer Identifier { get; init; } public TargetPointer Next { get; init; } } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FramedMethodFrame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FramedMethodFrame.cs new file mode 100644 index 00000000000000..66d7ec86274bcb --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FramedMethodFrame.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class FramedMethodFrame : IData +{ + static FramedMethodFrame IData.Create(Target target, TargetPointer address) + => new FramedMethodFrame(target, address); + + public FramedMethodFrame(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.FramedMethodFrame); + TransitionBlockPtr = target.ReadPointer(address + (ulong)type.Fields[nameof(TransitionBlockPtr)].Offset); + Address = address; + } + + public TargetPointer Address { get; } + public TargetPointer TransitionBlockPtr { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FuncEvalFrame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FuncEvalFrame.cs new file mode 100644 index 00000000000000..65379d77d35f49 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FuncEvalFrame.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +/// +/// Only exists if DEBUGGING_SUPPORTED defined in the target runtime. +/// +internal class FuncEvalFrame : IData +{ + static FuncEvalFrame IData.Create(Target target, TargetPointer address) + => new FuncEvalFrame(target, address); + + public FuncEvalFrame(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.FuncEvalFrame); + DebuggerEvalPtr = target.ReadPointer(address + (ulong)type.Fields[nameof(DebuggerEvalPtr)].Offset); + Address = address; + } + + public TargetPointer Address { get; } + public TargetPointer DebuggerEvalPtr { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgsAMD64.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgsAMD64.cs new file mode 100644 index 00000000000000..e6428549a154bd --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgsAMD64.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class HijackArgsAMD64 : IData +{ + static HijackArgsAMD64 IData.Create(Target target, TargetPointer address) + => new HijackArgsAMD64(target, address); + + public HijackArgsAMD64(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.HijackArgs); + CalleeSavedRegisters = address + (ulong)type.Fields[nameof(CalleeSavedRegisters)].Offset; + + // On Windows, Rsp is present + if (type.Fields.ContainsKey(nameof(Rsp))) + { + Rsp = target.ReadPointer(address + (ulong)type.Fields[nameof(Rsp)].Offset); + } + } + + public TargetPointer CalleeSavedRegisters { get; } + public TargetPointer? Rsp { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgsARM64.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgsARM64.cs new file mode 100644 index 00000000000000..73168fd286c7c7 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgsARM64.cs @@ -0,0 +1,27 @@ +// 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; + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class HijackArgsARM64 : IData +{ + static HijackArgsARM64 IData.Create(Target target, TargetPointer address) + => new HijackArgsARM64(target, address); + + public HijackArgsARM64(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.HijackArgs); + + Dictionary registers = new Dictionary(type.Fields.Count); + foreach ((string name, Target.FieldInfo field) in type.Fields) + { + TargetNUInt value = target.ReadNUInt(address + (ulong)field.Offset); + registers.Add(name, value); + } + Registers = registers; + } + + public IReadOnlyDictionary Registers { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackFrame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackFrame.cs new file mode 100644 index 00000000000000..db5061ed271bb0 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackFrame.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. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class HijackFrame : IData +{ + static HijackFrame IData.Create(Target target, TargetPointer address) + => new HijackFrame(target, address); + + public HijackFrame(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.HijackFrame); + ReturnAddress = target.ReadPointer(address + (ulong)type.Fields[nameof(ReturnAddress)].Offset); + HijackArgsPtr = target.ReadPointer(address + (ulong)type.Fields[nameof(HijackArgsPtr)].Offset); + Address = address; + } + + public TargetPointer Address { get; } + public TargetPointer ReturnAddress { get; } + public TargetPointer HijackArgsPtr { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/InlinedCallFrame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/InlinedCallFrame.cs index 78af563e607985..4cdd72e1ab8a09 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/InlinedCallFrame.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/InlinedCallFrame.cs @@ -17,7 +17,7 @@ public InlinedCallFrame(Target target, TargetPointer address) Address = address; } - public TargetPointer Address { get;} + public TargetPointer Address { get; } public TargetPointer CallSiteSP { get; } public TargetPointer CallerReturnAddress { get; } public TargetPointer CalleeSavedFP { get; } diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/ResumableFrame.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/ResumableFrame.cs new file mode 100644 index 00000000000000..3faa26701b2102 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/ResumableFrame.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class ResumableFrame : IData +{ + static ResumableFrame IData.Create(Target target, TargetPointer address) + => new ResumableFrame(target, address); + + public ResumableFrame(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.ResumableFrame); + TargetContextPtr = target.ReadPointer(address + (ulong)type.Fields[nameof(TargetContextPtr)].Offset); + Address = address; + } + + public TargetPointer Address { get; } + public TargetPointer TargetContextPtr { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/TransitionBlock.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/TransitionBlock.cs new file mode 100644 index 00000000000000..b6a0d9c666b67e --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/TransitionBlock.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal class TransitionBlock : IData +{ + static TransitionBlock IData.Create(Target target, TargetPointer address) + => new TransitionBlock(target, address); + + public TransitionBlock(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.TransitionBlock); + ReturnAddress = target.ReadPointer(address + (ulong)type.Fields[nameof(ReturnAddress)].Offset); + CalleeSavedRegisters = address + (ulong)type.Fields[nameof(CalleeSavedRegisters)].Offset; + } + + public TargetPointer ReturnAddress { get; } + public TargetPointer CalleeSavedRegisters { get; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubPrecodeData.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubPrecodeData.cs index 320795b41d5424..442d3067c83f24 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubPrecodeData.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubPrecodeData.cs @@ -3,12 +3,12 @@ namespace Microsoft.Diagnostics.DataContractReader.Data; -internal sealed class StubPrecodeData : IData +internal sealed class StubPrecodeData_1 : IData { - static StubPrecodeData IData.Create(Target target, TargetPointer address) - => new StubPrecodeData(target, address); + static StubPrecodeData_1 IData.Create(Target target, TargetPointer address) + => new StubPrecodeData_1(target, address); - public StubPrecodeData(Target target, TargetPointer address) + public StubPrecodeData_1(Target target, TargetPointer address) { Target.TypeInfo type = target.GetTypeInfo(DataType.StubPrecodeData); MethodDesc = target.ReadPointer(address + (ulong)type.Fields[nameof(MethodDesc)].Offset); @@ -18,3 +18,19 @@ public StubPrecodeData(Target target, TargetPointer address) public TargetPointer MethodDesc { get; init; } public byte Type { get; init; } } + +internal sealed class StubPrecodeData_2 : IData +{ + static StubPrecodeData_2 IData.Create(Target target, TargetPointer address) + => new StubPrecodeData_2(target, address); + + public StubPrecodeData_2(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.StubPrecodeData); + SecretParam = target.ReadPointer(address + (ulong)type.Fields[nameof(SecretParam)].Offset); + Type = target.Read(address + (ulong)type.Fields[nameof(Type)].Offset); + } + + public TargetPointer SecretParam { get; init; } + public byte Type { get; init; } +} diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ThisPtrRetBufPrecodeData.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ThisPtrRetBufPrecodeData.cs new file mode 100644 index 00000000000000..1468ec622ecf78 --- /dev/null +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ThisPtrRetBufPrecodeData.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal sealed class ThisPtrRetBufPrecodeData : IData +{ + static ThisPtrRetBufPrecodeData IData.Create(Target target, TargetPointer address) + => new ThisPtrRetBufPrecodeData(target, address); + + public ThisPtrRetBufPrecodeData(Target target, TargetPointer address) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.ThisPtrRetBufPrecodeData); + MethodDesc = target.ReadPointer(address + (ulong)type.Fields[nameof(MethodDesc)].Offset); + } + + public TargetPointer MethodDesc { get; init; } +} diff --git a/src/native/managed/cdacreader/src/Legacy/ClrDataStackWalk.cs b/src/native/managed/cdacreader/src/Legacy/ClrDataStackWalk.cs index c351796c33c8c3..615e7123029a82 100644 --- a/src/native/managed/cdacreader/src/Legacy/ClrDataStackWalk.cs +++ b/src/native/managed/cdacreader/src/Legacy/ClrDataStackWalk.cs @@ -65,9 +65,7 @@ int IXCLRDataStackWalk.GetContext(uint contextFlags, uint contextBufSize, uint* contextStruct.FillFromBuffer(contextBuf); localContextStruct.FillFromBuffer(localContextBuf); - Debug.Assert(contextStruct.InstructionPointer == localContextStruct.InstructionPointer, $"cDAC IP: {contextStruct.InstructionPointer:x}, DAC IP: {localContextStruct.InstructionPointer:x}"); - Debug.Assert(contextStruct.StackPointer == localContextStruct.StackPointer, $"cDAC SP: {contextStruct.StackPointer:x}, DAC SP: {localContextStruct.StackPointer:x}"); - Debug.Assert(contextStruct.FramePointer == localContextStruct.FramePointer, $"cDAC FP: {contextStruct.FramePointer:x}, DAC FP: {localContextStruct.FramePointer:x}"); + Debug.Assert(contextStruct.Equals(localContextStruct)); } #endif diff --git a/src/native/managed/cdacreader/tests/MockMemorySpace.cs b/src/native/managed/cdacreader/tests/MockMemorySpace.cs index 364a43b6c3ddb8..f5125fba8b766b 100644 --- a/src/native/managed/cdacreader/tests/MockMemorySpace.cs +++ b/src/native/managed/cdacreader/tests/MockMemorySpace.cs @@ -58,11 +58,21 @@ public Builder AddHeapFragment(HeapFragment fragment) if (fragment.Data is null || fragment.Data.Length == 0) throw new InvalidOperationException($"Fragment '{fragment.Name}' data is empty"); if (!FragmentFits(fragment)) - throw new InvalidOperationException($"Fragment '{fragment.Name}' does not fit in the address space"); + throw new InvalidOperationException($"Fragment '{fragment.Name}' does not fit in the address space. Overlaps with existing fragments.\n{GetHeapFragmentsDescription()}"); _heapFragments.Add(fragment); return this; } + private string GetHeapFragmentsDescription() + { + StringBuilder builder = new(); + foreach (var fragment in _heapFragments) + { + builder.AppendLine($"Fragment '{fragment.Name}' at 0x{fragment.Address:x} with length {fragment.Data.Length}"); + } + return builder.ToString(); + } + public Builder AddHeapFragments(IEnumerable fragments) { foreach (var f in fragments) diff --git a/src/native/managed/cdacreader/tests/PrecodeStubsTests.cs b/src/native/managed/cdacreader/tests/PrecodeStubsTests.cs index 3d007d2a6bf5d7..0abc27271481ed 100644 --- a/src/native/managed/cdacreader/tests/PrecodeStubsTests.cs +++ b/src/native/managed/cdacreader/tests/PrecodeStubsTests.cs @@ -51,6 +51,7 @@ public class PrecodeTestDescriptor { // #endif // TARGET_AMD64 public required byte StubPrecode { get; init; } public required int StubPrecodeSize { get; init; } + public byte ThisPtrRetBufPrecode => 0x08; public PrecodeTestDescriptor(string name) { Name = name; } @@ -156,6 +157,15 @@ public static IEnumerable PrecodeTestDescriptorData() }}; } + public static IEnumerable PrecodeTestDescriptorDataWithContractVersion() + { + foreach (var data in PrecodeTestDescriptorData()) + { + yield return new object[]{data[0], 1}; // Test v1 of the contract + yield return new object[]{data[0], 2}; // Test v2 of the contract + } + } + internal struct AllocationRange { public ulong PrecodeDescriptorStart; @@ -184,10 +194,13 @@ internal class PrecodeBuilder { public TargetPointer MachineDescriptorAddress; public CodePointerFlags CodePointerFlags {get; private set;} - public PrecodeBuilder(MockTarget.Architecture arch) : this(DefaultAllocationRange, new MockMemorySpace.Builder(new TargetTestHelpers(arch))) { + + public int PrecodesVersion { get; } + public PrecodeBuilder(MockTarget.Architecture arch, int precodesVersion) : this(DefaultAllocationRange, new MockMemorySpace.Builder(new TargetTestHelpers(arch)), precodesVersion) { } - public PrecodeBuilder(AllocationRange allocationRange, MockMemorySpace.Builder builder, Dictionary? typeInfoCache = null) { + public PrecodeBuilder(AllocationRange allocationRange, MockMemorySpace.Builder builder, int precodesVersion, Dictionary? typeInfoCache = null) { Builder = builder; + PrecodesVersion = precodesVersion; PrecodeAllocator = builder.CreateAllocator(allocationRange.PrecodeDescriptorStart, allocationRange.PrecodeDescriptorEnd); StubDataPageAllocator = builder.CreateAllocator(allocationRange.StubDataPageStart, allocationRange.StubDataPageEnd); Types = typeInfoCache ?? GetTypes(Builder.TargetTestHelpers); @@ -210,14 +223,33 @@ public PrecodeBuilder(AllocationRange allocationRange, MockMemorySpace.Builder b Fields = layout.Fields, Size = layout.Stride, }; - layout = targetTestHelpers.LayoutFields([ - new(nameof(Data.StubPrecodeData.Type), DataType.uint8), - new(nameof(Data.StubPrecodeData.MethodDesc), DataType.pointer), - ]); + + if (PrecodesVersion == 1) { + layout = targetTestHelpers.LayoutFields([ + new(nameof(Data.StubPrecodeData_1.Type), DataType.uint8), + new(nameof(Data.StubPrecodeData_1.MethodDesc), DataType.pointer), + ]); + } else { + layout = targetTestHelpers.LayoutFields([ + new(nameof(Data.StubPrecodeData_2.Type), DataType.uint8), + new(nameof(Data.StubPrecodeData_2.SecretParam), DataType.pointer), + ]); + } types[DataType.StubPrecodeData] = new Target.TypeInfo() { Fields = layout.Fields, Size = layout.Stride, }; + + if (PrecodesVersion >= 2) + { + layout = targetTestHelpers.LayoutFields([ + new(nameof(Data.ThisPtrRetBufPrecodeData.MethodDesc), DataType.pointer), + ]); + types[DataType.ThisPtrRetBufPrecodeData] = new Target.TypeInfo() { + Fields = layout.Fields, + Size = layout.Stride, + }; + } return types; } @@ -241,6 +273,7 @@ public void AddPlatformMetadata(PrecodeTestDescriptor descriptor) { Builder.TargetTestHelpers.Write(desc.Slice(typeInfo.Fields[nameof(Data.PrecodeMachineDescriptor.ShiftOfPrecodeType)].Offset, sizeof(byte)), (byte)descriptor.ShiftOfPrecodeType); Builder.TargetTestHelpers.Write(desc.Slice(typeInfo.Fields[nameof(Data.PrecodeMachineDescriptor.StubCodePageSize)].Offset, sizeof(uint)), descriptor.StubCodePageSize); Builder.TargetTestHelpers.Write(desc.Slice(typeInfo.Fields[nameof(Data.PrecodeMachineDescriptor.StubPrecodeType)].Offset, sizeof(byte)), descriptor.StubPrecode); + Builder.TargetTestHelpers.Write(desc.Slice(typeInfo.Fields[nameof(Data.PrecodeMachineDescriptor.ThisPointerRetBufPrecodeType)].Offset, sizeof(byte)), descriptor.ThisPtrRetBufPrecode); // FIXME: set the other fields } @@ -248,7 +281,7 @@ public TargetCodePointer AddStubPrecodeEntry(string name, PrecodeTestDescriptor // TODO[cdac]: allow writing other kinds of stub precode subtypes ulong stubCodeSize = (ulong)test.StubPrecodeSize; var stubDataTypeInfo = Types[DataType.StubPrecodeData]; - MockMemorySpace.HeapFragment stubDataFragment = StubDataPageAllocator.Allocate((ulong)stubDataTypeInfo.Size, $"Stub data for {name} on {test.Name}"); + MockMemorySpace.HeapFragment stubDataFragment = StubDataPageAllocator.Allocate(Math.Max((ulong)stubDataTypeInfo.Size, (ulong)stubCodeSize), $"Stub data for {name} on {test.Name}"); Builder.AddHeapFragment(stubDataFragment); // allocate the code one page before the stub data ulong stubCodeStart = stubDataFragment.Address - test.StubCodePageSize; @@ -261,8 +294,49 @@ public TargetCodePointer AddStubPrecodeEntry(string name, PrecodeTestDescriptor Builder.AddHeapFragment(stubCodeFragment); Span stubData = Builder.BorrowAddressRange(stubDataFragment.Address, (int)stubDataTypeInfo.Size); - Builder.TargetTestHelpers.Write(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData.Type)].Offset, sizeof(byte)), test.StubPrecode); - Builder.TargetTestHelpers.WritePointer(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData.MethodDesc)].Offset, Builder.TargetTestHelpers.PointerSize), methodDesc); + if (PrecodesVersion == 1) { + Builder.TargetTestHelpers.Write(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData_1.Type)].Offset, sizeof(byte)), test.StubPrecode); + Builder.TargetTestHelpers.WritePointer(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData_1.MethodDesc)].Offset, Builder.TargetTestHelpers.PointerSize), methodDesc); + } else { + Builder.TargetTestHelpers.Write(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData_2.Type)].Offset, sizeof(byte)), test.StubPrecode); + Builder.TargetTestHelpers.WritePointer(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData_2.SecretParam)].Offset, Builder.TargetTestHelpers.PointerSize), methodDesc); + } + TargetCodePointer address = stubCodeFragment.Address; + if (test.IsThumb) { + address = new TargetCodePointer(address.Value | 1); + } + return address; + } + + public TargetCodePointer AddThisPtrRetBufPrecodeEntry(string name, PrecodeTestDescriptor test, TargetPointer methodDesc) { + ulong stubCodeSize = (ulong)test.StubPrecodeSize; + var stubDataTypeInfo = Types[DataType.StubPrecodeData]; + MockMemorySpace.HeapFragment stubDataFragment = StubDataPageAllocator.Allocate(Math.Max((ulong)stubDataTypeInfo.Size, (ulong)stubCodeSize), $"Stub data for {name} on {test.Name}"); + Builder.AddHeapFragment(stubDataFragment); + + var thisPtrRetBufDataTypeInfo = Types[DataType.ThisPtrRetBufPrecodeData]; + MockMemorySpace.HeapFragment thisPtrRetBufStubDataFragment = StubDataPageAllocator.Allocate((ulong)thisPtrRetBufDataTypeInfo.Size, $"ThisPtrRetBufData stub data for {name} on {test.Name}"); + Builder.AddHeapFragment(thisPtrRetBufStubDataFragment); + + // allocate the code one page before the stub data + ulong stubCodeStart = stubDataFragment.Address - test.StubCodePageSize; + MockMemorySpace.HeapFragment stubCodeFragment = new MockMemorySpace.HeapFragment { + Address = stubCodeStart, + Data = new byte[stubCodeSize], + Name = $"Stub code for {name} on {test.Name} with data at 0x{stubDataFragment.Address:x}", + }; + test.WritePrecodeType(test.StubPrecode, Builder.TargetTestHelpers, stubCodeFragment.Data); + Builder.AddHeapFragment(stubCodeFragment); + + Span thisPtrStubData = Builder.BorrowAddressRange(thisPtrRetBufStubDataFragment.Address, (int)thisPtrRetBufDataTypeInfo.Size); + + Builder.TargetTestHelpers.WritePointer(thisPtrStubData.Slice(thisPtrRetBufDataTypeInfo.Fields[nameof(Data.ThisPtrRetBufPrecodeData.MethodDesc)].Offset, Builder.TargetTestHelpers.PointerSize), methodDesc); + + Span stubData = Builder.BorrowAddressRange(stubDataFragment.Address, (int)stubDataTypeInfo.Size); + + Builder.TargetTestHelpers.Write(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData_2.Type)].Offset, sizeof(byte)), test.ThisPtrRetBufPrecode); + Builder.TargetTestHelpers.WritePointer(stubData.Slice(stubDataTypeInfo.Fields[nameof(Data.StubPrecodeData_2.SecretParam)].Offset, Builder.TargetTestHelpers.PointerSize), thisPtrRetBufStubDataFragment.Address); + TargetCodePointer address = stubCodeFragment.Address; if (test.IsThumb) { address = new TargetCodePointer(address.Value | 1); @@ -288,21 +362,23 @@ private static Target CreateTarget(PrecodeBuilder precodeBuilder) // to set it up such that it will only be created after the target's targets are set up Mock reg = new(); reg.SetupGet(c => c.PlatformMetadata).Returns(platformMetadata.Object); - reg.SetupGet(c => c.PrecodeStubs).Returns(() => precodeFactory.CreateContract(target, 1)); + reg.SetupGet(c => c.PrecodeStubs).Returns(() => precodeFactory.CreateContract(target, precodeBuilder.PrecodesVersion)); target.SetContracts(reg.Object); return target; } [Theory] - [MemberData(nameof(PrecodeTestDescriptorData))] - public void TestPrecodeStubPrecodeExpectedMethodDesc(PrecodeTestDescriptor test) + [MemberData(nameof(PrecodeTestDescriptorDataWithContractVersion))] + public void TestPrecodeStubPrecodeExpectedMethodDesc(PrecodeTestDescriptor test, int contractVersion) { - var builder = new PrecodeBuilder(test.Arch); + var builder = new PrecodeBuilder(test.Arch, contractVersion); builder.AddPlatformMetadata(test); TargetPointer expectedMethodDesc = new TargetPointer(0xeeee_eee0u); // arbitrary TargetCodePointer stub1 = builder.AddStubPrecodeEntry("Stub 1", test, expectedMethodDesc); + TargetPointer expectedMethodDesc2 = new TargetPointer(0xfafa_eee0u); // arbitrary + TargetCodePointer stub2 = contractVersion >= 2 ? builder.AddThisPtrRetBufPrecodeEntry("Stub 2", test, expectedMethodDesc2) : new TargetCodePointer(expectedMethodDesc2.Value); var target = CreateTarget(builder); Assert.NotNull(target); @@ -313,5 +389,12 @@ public void TestPrecodeStubPrecodeExpectedMethodDesc(PrecodeTestDescriptor test) var actualMethodDesc = precodeContract.GetMethodDescFromStubAddress(stub1); Assert.Equal(expectedMethodDesc, actualMethodDesc); + + if (contractVersion >= 2) + { + // Implementation of this type of precode is only handled correctly in contract version 2 and higher + var actualMethodDesc2 = precodeContract.GetMethodDescFromStubAddress(stub2); + Assert.Equal(expectedMethodDesc2, actualMethodDesc2); + } } } diff --git a/src/native/minipal/CMakeLists.txt b/src/native/minipal/CMakeLists.txt index 8ebacd8cd6f404..f27ad0d5fea50e 100644 --- a/src/native/minipal/CMakeLists.txt +++ b/src/native/minipal/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES unicodedata.c utf8.c xoshiro128pp.c + log.c ) # Provide an object library for scenarios where we ship static libraries @@ -36,6 +37,10 @@ endif() add_library(minipal STATIC) target_link_libraries(minipal PRIVATE minipal_objects) +if(CLR_CMAKE_HOST_ANDROID) + target_link_libraries(minipal PRIVATE log) +endif(CLR_CMAKE_HOST_ANDROID) + add_library(minipal_sanitizer_support OBJECT sansupport.c) # Exclude this target from the default build as we may not have sanitzer headers available diff --git a/src/native/minipal/configure.cmake b/src/native/minipal/configure.cmake index 8a5dd2346a0e02..448b03ba7a250c 100644 --- a/src/native/minipal/configure.cmake +++ b/src/native/minipal/configure.cmake @@ -2,18 +2,16 @@ include(CheckFunctionExists) include(CheckIncludeFiles) include(CheckSymbolExists) +check_include_files("windows.h" HAVE_WINDOWS_H) +check_include_files("windows.h;bcrypt.h" HAVE_BCRYPT_H) check_include_files("sys/auxv.h;asm/hwcap.h" HAVE_AUXV_HWCAP_H) + check_function_exists(sysctlbyname HAVE_SYSCTLBYNAME) +check_function_exists(fsync HAVE_FSYNC) check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM_BUF) check_symbol_exists(O_CLOEXEC fcntl.h HAVE_O_CLOEXEC) -check_include_files("windows.h" HAVE_WINDOWS_H) -check_include_files("windows.h;bcrypt.h" HAVE_BCRYPT_H) - -check_symbol_exists( - clock_gettime_nsec_np - time.h - HAVE_CLOCK_GETTIME_NSEC_NP) +check_symbol_exists(clock_gettime_nsec_np time.h HAVE_CLOCK_GETTIME_NSEC_NP) if(CMAKE_C_BYTE_ORDER STREQUAL "BIG_ENDIAN") set(BIGENDIAN 1) diff --git a/src/native/minipal/guid.c b/src/native/minipal/guid.c index a3620c10783c3a..8169e738bb6acf 100644 --- a/src/native/minipal/guid.c +++ b/src/native/minipal/guid.c @@ -8,6 +8,7 @@ #include #ifdef HOST_WINDOWS #include +#include #endif // See RFC-4122 section 4.4 on creation of random GUID. diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c new file mode 100644 index 00000000000000..29ff23262e7676 --- /dev/null +++ b/src/native/minipal/log.c @@ -0,0 +1,329 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "minipalconfig.h" +#include "log.h" +#include +#include +#include + +#ifndef MINIPAL_LOG_RUNTIME_TAG +#define MINIPAL_LOG_RUNTIME_TAG "DOTNET" +#endif + +#ifdef HOST_ANDROID +#include +#include + +// Android defines its LOGGER_ENTRY_MAX_PAYLOAD to 4068 bytes. +// Use 4000 bytes to include some slack for future changes to LOGGER_ENTRY_MAX_PAYLOAD. +#define MINIPAL_LOG_MAX_PAYLOAD 4000 + +// Android defines its internal log buffer used in __android_log_vprint to 1024 bytes. +// Use same internal stack buffer size avoiding dynamic memory allocation for majority of logging. +#define MINIPAL_LOG_BUF_SIZE 1024 + +static int android_log_flag(minipal_log_flags flags) +{ + switch(flags) + { + case minipal_log_flags_fatal: + return ANDROID_LOG_FATAL; + case minipal_log_flags_error: + return ANDROID_LOG_ERROR; + case minipal_log_flags_warning: + return ANDROID_LOG_WARN; + case minipal_log_flags_info: + return ANDROID_LOG_INFO; + case minipal_log_flags_debug: + return ANDROID_LOG_DEBUG; + case minipal_log_flags_verbose: + return ANDROID_LOG_VERBOSE; + default: + return ANDROID_LOG_UNKNOWN; + } +} + +static size_t log_write(minipal_log_flags flags, const char* msg, size_t msg_len) +{ + if (msg_len == 1 && msg[0] == '\n') + return 0; + + return __android_log_write(android_log_flag(flags), MINIPAL_LOG_RUNTIME_TAG, msg) == 1 ? msg_len : 0; +} + +int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + int bytes_written = minipal_log_vprint(flags, fmt, args); + va_end(args); + return bytes_written; +} + +int minipal_log_vprint(minipal_log_flags flags, const char* fmt, va_list args) +{ + char stack_buffer[MINIPAL_LOG_BUF_SIZE]; + int bytes_written = 0; + va_list args_copy; + + va_copy(args_copy, args); + + int len = vsnprintf(stack_buffer, sizeof(stack_buffer), fmt, args_copy); + if (len < sizeof(stack_buffer)) + { + bytes_written = minipal_log_write(flags, stack_buffer); + } + else + { + char* dyn_buffer = (char*)malloc(len + 1); + if (dyn_buffer != NULL) + { + vsnprintf(dyn_buffer, len + 1, fmt, args); + bytes_written = minipal_log_write(flags, dyn_buffer); + free(dyn_buffer); + } + } + + va_end(args_copy); + return bytes_written; +} + +void minipal_log_flush(minipal_log_flags flags) +{ +} + +void minipal_log_flush_all(void) +{ +} + +static size_t log_write_line(minipal_log_flags flags, const char* msg, size_t msg_len) +{ + char buffer[MINIPAL_LOG_MAX_PAYLOAD]; + if (msg_len < MINIPAL_LOG_MAX_PAYLOAD) + { + strncpy(buffer, msg, msg_len); + buffer[msg_len] = '\0'; + return log_write(flags, buffer, msg_len); + } + + const char* msg_end = msg + msg_len; + size_t bytes_written = 0; + while (msg < msg_end) + { + ptrdiff_t chunk_size = MINIPAL_LOG_MAX_PAYLOAD - 1; + if (msg_end - msg < chunk_size) + { + chunk_size = msg_end - msg; + } + + strncpy(buffer, msg, chunk_size); + buffer[chunk_size] = '\0'; + bytes_written += log_write(flags, buffer, chunk_size); + msg += chunk_size; + } + + return bytes_written; +} + +int minipal_log_write(minipal_log_flags flags, const char* msg) +{ + assert(msg != NULL && msg[0] != '\0'); + + size_t msg_len = strlen(msg); + const char* msg_end = msg + msg_len; + + if (msg_len < MINIPAL_LOG_MAX_PAYLOAD) + return (int)log_write(flags, msg, msg_len); + + const char* next_msg = NULL; + size_t bytes_written = 0; + for (next_msg = msg; next_msg < msg_end;) + { + const char* next_line_break = strchr(next_msg, '\n'); + if (next_line_break == NULL && (msg_end - next_msg < MINIPAL_LOG_MAX_PAYLOAD)) + { + bytes_written += log_write(flags, next_msg, msg_end - next_msg); + break; + } + else if (next_line_break == NULL) + { + bytes_written += log_write_line(flags, next_msg, msg_end - next_msg); + break; + } + else + { + bytes_written += log_write_line(flags, next_msg, next_line_break - next_msg); + next_msg = next_line_break + 1; + } + } + + return (int)bytes_written; +} + +void minipal_log_sync(minipal_log_flags flags) +{ +} + +void minipal_log_sync_all(void) +{ +} +#else +#include +#include + +#define MINIPAL_LOG_MAX_PAYLOAD 32767 + +static FILE * get_std_file(minipal_log_flags flags) +{ + switch(flags) + { + case minipal_log_flags_fatal: + case minipal_log_flags_error: + return stderr; + case minipal_log_flags_warning: + case minipal_log_flags_info: + case minipal_log_flags_debug: + case minipal_log_flags_verbose: + default: + return stdout; + } +} + +int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + int status = vfprintf(get_std_file(flags), fmt, args); + va_end(args); + return status; +} + +int minipal_log_vprint(minipal_log_flags flags, const char* fmt, va_list args) +{ + return vfprintf(get_std_file(flags), fmt, args); +} + +void minipal_log_flush(minipal_log_flags flags) +{ + FILE* file = get_std_file(flags); + if (file != NULL) + fflush(file); +} + +void minipal_log_flush_all(void) +{ + minipal_log_flush(minipal_log_flags_error); + minipal_log_flush(minipal_log_flags_info); +} + +#ifdef HOST_WINDOWS +#include +#include +static int sync_file(minipal_log_flags flags) +{ + switch(flags) + { + case minipal_log_flags_fatal: + case minipal_log_flags_error: + FlushFileBuffers(GetStdHandle(STD_ERROR_HANDLE)); + break; + case minipal_log_flags_warning: + case minipal_log_flags_info: + case minipal_log_flags_debug: + case minipal_log_flags_verbose: + default: + FlushFileBuffers(GetStdHandle(STD_OUTPUT_HANDLE)); + break; + } + + return 0; +} +#define fileno _fileno +#define write _write +#elif defined(__APPLE__) +#include +#include +static int sync_file(minipal_log_flags flags) +{ + if (fcntl(fileno(get_std_file(flags)), F_FULLFSYNC) != -1) + return 0; + + return errno; +} +#elif HAVE_FSYNC +#include +static int sync_file(minipal_log_flags flags) +{ + if (fsync(fileno(get_std_file(flags))) == 0) + return 0; + + return errno; +} +#else +#include +static int sync_file(minipal_log_flags flags) +{ + sync(); + return 0; +} +#endif + +static int write_file(int fd, const char* msg, size_t bytes_to_write) +{ + if (fd == -1) + return 0; + + assert(msg != NULL && msg[0] != '\0'); + assert(bytes_to_write < INT_MAX); + + return write(fd, msg, (int)bytes_to_write); +} + +int minipal_log_write(minipal_log_flags flags, const char* msg) +{ + assert(msg != NULL && msg[0] != '\0'); + + size_t bytes_to_write = strlen(msg); + size_t bytes_written = 0; + + int fd = fileno(get_std_file(flags)); + while (bytes_to_write > 0) + { + size_t chunk_to_write = bytes_to_write < MINIPAL_LOG_MAX_PAYLOAD ? bytes_to_write : MINIPAL_LOG_MAX_PAYLOAD; + size_t chunk_written = write_file(fd, msg, chunk_to_write); + + if (chunk_written == 0) + break; + + msg = msg + chunk_written; + bytes_to_write -= chunk_written; + bytes_written += chunk_written; + } + + return (int)bytes_written; +} + +void minipal_log_sync(minipal_log_flags flags) +{ + bool retry = false; + do + { + switch (sync_file(flags)) + { + case EINTR: + retry = true; + break; + default: + retry = false; + break; + } + } while (retry); +} + +void minipal_log_sync_all(void) +{ + minipal_log_sync(minipal_log_flags_error); + minipal_log_sync(minipal_log_flags_info); +} +#endif diff --git a/src/native/minipal/log.h b/src/native/minipal/log.h new file mode 100644 index 00000000000000..e23b3efd4598d7 --- /dev/null +++ b/src/native/minipal/log.h @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef HAVE_MINIPAL_LOG_H +#define HAVE_MINIPAL_LOG_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef enum +{ + minipal_log_flags_fatal = 1 << 1, + minipal_log_flags_error = 1 << 2, + minipal_log_flags_warning = 1 << 3, + minipal_log_flags_info = 1 << 4, + minipal_log_flags_debug = 1 << 5, + minipal_log_flags_verbose = 1 << 6 +} minipal_log_flags; + +#define minipal_log_print_fatal(...) minipal_log_print(minipal_log_flags_fatal, __VA_ARGS__) +#define minipal_log_print_error(...) minipal_log_print(minipal_log_flags_error, __VA_ARGS__) +#define minipal_log_print_info(...) minipal_log_print(minipal_log_flags_info, __VA_ARGS__) +#define minipal_log_print_verbose(...) minipal_log_print(minipal_log_flags_verbose, __VA_ARGS__) +int minipal_log_print(minipal_log_flags flags, const char* fmt, ... ); + +#define minipal_log_vprint_fatal(...) minipal_log_vprint(minipal_log_flags_fatal, __VA_ARGS__) +#define minipal_log_vprint_error(...) minipal_log_vprint(minipal_log_flags_error, __VA_ARGS__) +#define minipal_log_vprint_info(...) minipal_log_vprint(minipal_log_flags_info, __VA_ARGS__) +#define minipal_log_vprint_verbose(...) minipal_log_vprint(minipal_log_flags_verbose, __VA_ARGS__) +int minipal_log_vprint(minipal_log_flags flags, const char* fmt,va_list args); + +#define minipal_log_flush_fatal() minipal_log_flush(minipal_log_flags_fatal) +#define minipal_log_flush_error() minipal_log_flush(minipal_log_flags_error) +#define minipal_log_flush_info() minipal_log_flush(minipal_log_flags_info) +#define minipal_log_flush_verbose() minipal_log_flush(minipal_log_flags_verbose) +void minipal_log_flush(minipal_log_flags flags); +void minipal_log_flush_all(void); + +// None crt, async safe log write. +#define minipal_log_write_fatal(msg) minipal_log_write(minipal_log_flags_fatal, msg) +#define minipal_log_write_error(msg) minipal_log_write(minipal_log_flags_error, msg) +#define minipal_log_write_info(msg) minipal_log_write(minipal_log_flags_info, msg) +#define minipal_log_write_verbose(msg) minipal_log_write(minipal_log_flags_verbose, msg) +int minipal_log_write(minipal_log_flags flags, const char* msg); + +// None crt, async safe log sync. +#define minipal_log_sync_fatal() minipal_log_sync(minipal_log_flags_fatal) +#define minipal_log_sync_error() minipal_log_sync(minipal_log_flags_error) +#define minipal_log_sync_info() minipal_log_sync(minipal_log_flags_info) +#define minipal_log_sync_verbose() minipal_log_sync(minipal_log_flags_verbose) +void minipal_log_sync(minipal_log_flags flags); +void minipal_log_sync_all(void); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* HAVE_MINIPAL_LOG_H */ diff --git a/src/native/minipal/minipalconfig.h.in b/src/native/minipal/minipalconfig.h.in index 00764722ef1b86..7310b2f6962cd9 100644 --- a/src/native/minipal/minipalconfig.h.in +++ b/src/native/minipal/minipalconfig.h.in @@ -9,5 +9,6 @@ #cmakedefine01 BIGENDIAN #cmakedefine01 HAVE_BCRYPT_H #cmakedefine01 HAVE_WINDOWS_H +#cmakedefine01 HAVE_FSYNC #endif diff --git a/src/native/minipal/utils.h b/src/native/minipal/utils.h index 768de9e48b4b28..de25c457341e4f 100644 --- a/src/native/minipal/utils.h +++ b/src/native/minipal/utils.h @@ -9,6 +9,12 @@ // Number of characters in a string literal. Excludes terminating NULL. #define STRING_LENGTH(str) (ARRAY_SIZE(str) - 1) +#ifdef __clang_analyzer__ +#define ANALYZER_NORETURN __attribute((analyzer_noreturn)) +#else +#define ANALYZER_NORETURN +#endif + #ifndef __has_builtin #define __has_builtin(x) 0 #endif diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index fd3f6eb8134100..de72f50ce8e39e 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -448,7 +448,20 @@ public ApkBuilder(TaskLoggingHelper logger) } else { - dynamicLibs.AddRange(Directory.GetFiles(AppDir, "*.so").Where(file => Path.GetFileName(file) != "libmonodroid.so")); + var excludedLibs = new HashSet { "libmonodroid.so" }; + if (IsCoreCLR) + { + // exclude standalone GC libs + excludedLibs.Add("libclrgc.so"); + excludedLibs.Add("libclrgcexp.so"); + if (StripDebugSymbols) + { + // exclude debugger support libs + excludedLibs.Add("libmscordbi.so"); + excludedLibs.Add("libmscordaccore.so"); + } + } + dynamicLibs.AddRange(Directory.GetFiles(AppDir, "*.so").Where(file => !excludedLibs.Contains(Path.GetFileName(file)))); } // add all *.so files to lib/%abi%/ diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj b/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj index 2a5fce2048862e..05f1b8a49aceb0 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/tasks/Directory.Build.targets b/src/tasks/Directory.Build.targets index 5d73f8f7d5f8e6..9df25607a0766d 100644 --- a/src/tasks/Directory.Build.targets +++ b/src/tasks/Directory.Build.targets @@ -13,12 +13,12 @@ - + - + diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs index 2077fb40d6e0fe..7b5f03d2cccd24 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs @@ -6,6 +6,9 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Build.Utilities; namespace Microsoft.NET.Sdk.WebAssembly @@ -25,6 +28,13 @@ public class BootJsonBuilderHelper(TaskLoggingHelper Log, string DebugLevel, boo "System.Collections.Concurrent", ]; + public static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions() + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + WriteIndented = true + }; + public bool IsCoreAssembly(string fileName) { var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); @@ -37,6 +47,18 @@ public bool IsCoreAssembly(string fileName) return false; } + public void WriteConfigToFile(BootJsonData config, string outputPath, string? outputFileExtension = null) + { + var output = JsonSerializer.Serialize(config, JsonOptions); + + outputFileExtension ??= Path.GetExtension(outputPath); + Log.LogMessage($"Write config in format '{outputFileExtension}'"); + if (outputFileExtension == ".js") + output = $"export const config = /*json-start*/{output}/*json-end*/;"; + + File.WriteAllText(outputPath, output); + } + public void ComputeResourcesHash(BootJsonData bootConfig) { var sb = new StringBuilder(); diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs index c0ef0132d71998..f8c0761c76494b 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs @@ -103,7 +103,7 @@ public class BootJsonData /// /// Gets or sets environment variables. /// - public object environmentVariables { get; set; } + public System.Collections.Generic.Dictionary environmentVariables { get; set; } /// /// Gets or sets diagnostic tracing. diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs index 604422c9a852d0..be14ff5ad8d8d7 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -56,6 +56,8 @@ public class GenerateWasmBootJson : Task public ITaskItem[] ConfigurationFiles { get; set; } + public ITaskItem[] EnvVariables { get; set; } + public ITaskItem[] Extensions { get; set; } public string StartupMemoryCache { get; set; } @@ -408,13 +410,16 @@ private void WriteBootConfig(string entryAssemblyName) } } - var jsonOptions = new JsonSerializerOptions() - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, - WriteIndented = true - }; + if (EnvVariables != null && EnvVariables.Length > 0) + { + result.environmentVariables = new Dictionary(); + foreach (var env in EnvVariables) + { + string name = env.ItemSpec; + result.environmentVariables[name] = env.GetMetadata("Value"); + } + } if (Extensions != null && Extensions.Length > 0) { result.extensions = new Dictionary>(); @@ -422,24 +427,13 @@ private void WriteBootConfig(string entryAssemblyName) { var key = configExtension.GetMetadata("key"); using var fs = File.OpenRead(configExtension.ItemSpec); - var config = JsonSerializer.Deserialize>(fs, jsonOptions); + var config = JsonSerializer.Deserialize>(fs, BootJsonBuilderHelper.JsonOptions); result.extensions[key] = config; } } helper.ComputeResourcesHash(result); - - if (Path.GetExtension(OutputPath) == ".js") - { - var jsonOutput = JsonSerializer.Serialize(result, jsonOptions); - var jsOutput = $"export const config = /*json-start*/{jsonOutput}/*json-end*/;"; - File.WriteAllText(OutputPath, jsOutput); - } - else - { - using var output = File.Create(OutputPath); - JsonSerializer.Serialize(output, result, jsonOptions); - } + helper.WriteConfigToFile(result, OutputPath); void AddResourceToList(ITaskItem resource, ResourceHashesByNameDictionary resourceList, string resourceKey) { diff --git a/src/tasks/MobileBuildTasks/MobileBuildTasks.csproj b/src/tasks/MobileBuildTasks/MobileBuildTasks.csproj index a1fd7dbeb86962..8aa1faf0f8f788 100644 --- a/src/tasks/MobileBuildTasks/MobileBuildTasks.csproj +++ b/src/tasks/MobileBuildTasks/MobileBuildTasks.csproj @@ -15,11 +15,11 @@ - + - + diff --git a/src/tasks/WasmAppBuilder/ForceMSBuildGC.cs b/src/tasks/WasmAppBuilder/ForceMSBuildGC.cs index 8ddf5d46bfefd5..b833556af7dfe5 100644 --- a/src/tasks/WasmAppBuilder/ForceMSBuildGC.cs +++ b/src/tasks/WasmAppBuilder/ForceMSBuildGC.cs @@ -7,6 +7,8 @@ namespace Microsoft.WebAssembly.Build.Tasks { + // because on docker instance without swap file, MSBuild nodes need to make some room for LLVM + // https://github.com/dotnet/runtime/issues/113724 public class ForceMSBuildGC : Task { public override bool Execute() diff --git a/src/tasks/WasmAppBuilder/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/InterpToNativeGenerator.cs index 4890b2b708d308..c231e70be88f1c 100644 --- a/src/tasks/WasmAppBuilder/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/InterpToNativeGenerator.cs @@ -42,7 +42,7 @@ public void Generate(IEnumerable cookies, string outputPath) private static void Emit(StreamWriter w, IEnumerable cookies) { - // Use OrderBy because Order() is not available in net472 + // Use OrderBy because Order() is not available on .NET Framework var signatures = cookies.OrderBy(c => c).Distinct().ToArray(); Array.Sort(signatures, StringComparer.Ordinal); diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index b6eaa0e170141c..c50afb1589120c 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -35,13 +35,8 @@ public class WasmAppBuilder : WasmAppBuilderBaseTask public bool IsAot { get; set; } public bool IsMultiThreaded { get; set; } - private static readonly JsonSerializerOptions s_jsonOptions = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, - WriteIndented = true - }; - + [Required] + public string ConfigFileName { get; set; } = default!; // // Extra json elements to add to _framework/blazor.boot.json @@ -57,6 +52,11 @@ public class WasmAppBuilder : WasmAppBuilderBaseTask // public ITaskItem[]? ExtraConfig { get; set; } + /// + /// Environment variables to set in the boot.json file. + /// + public ITaskItem[]? EnvVariables { get; set; } + protected override bool ValidateArguments() { if (!base.ValidateArguments()) @@ -388,7 +388,12 @@ protected override bool ExecuteInternal() if (string.Equals(name, nameof(BootJsonData.environmentVariables), StringComparison.OrdinalIgnoreCase)) { - bootConfig.environmentVariables = valueObject; + bootConfig.environmentVariables ??= new(); + var envs = (JsonElement)valueObject!; + foreach (var env in envs.EnumerateObject()) + { + bootConfig.environmentVariables[env.Name] = env.Value.GetString(); + } } else if (string.Equals(name, nameof(BootJsonData.diagnosticTracing), StringComparison.OrdinalIgnoreCase)) { @@ -403,6 +408,13 @@ protected override bool ExecuteInternal() } } + foreach (ITaskItem env in EnvVariables ?? Enumerable.Empty()) + { + bootConfig.environmentVariables ??= new(); + string name = env.ItemSpec; + bootConfig.environmentVariables[name] = env.GetMetadata("Value"); + } + if (extraConfiguration.Count > 0) { bootConfig.extensions = new() @@ -411,17 +423,14 @@ protected override bool ExecuteInternal() }; } - using TempFileName tmpMonoConfigPath = new(); - using (var sw = File.CreateText(tmpMonoConfigPath.Path)) + using TempFileName tmpConfigPath = new(); { helper.ComputeResourcesHash(bootConfig); - - var json = JsonSerializer.Serialize(bootConfig, s_jsonOptions); - sw.Write(json); + helper.WriteConfigToFile(bootConfig, tmpConfigPath.Path, Path.GetExtension(ConfigFileName)); } - string monoConfigPath = Path.Combine(runtimeAssetsPath, "blazor.boot.json"); // TODO: Unify with Wasm SDK - Utils.CopyIfDifferent(tmpMonoConfigPath.Path, monoConfigPath, useHash: false); + string monoConfigPath = Path.Combine(runtimeAssetsPath, ConfigFileName); + Utils.CopyIfDifferent(tmpConfigPath.Path, monoConfigPath, useHash: false); _fileWrites.Add(monoConfigPath); foreach (ITaskItem item in ExtraFilesToDeploy!) diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj index b98c2bd0657b8f..addcf203c6a2eb 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -36,14 +36,14 @@ - + - + diff --git a/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj b/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj index 67e092c8b4fa13..5723bff0220091 100644 --- a/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj +++ b/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/tasks/tasks.proj b/src/tasks/tasks.proj index 4a59eac822a156..9b9f7098294585 100644 --- a/src/tasks/tasks.proj +++ b/src/tasks/tasks.proj @@ -1,4 +1,5 @@ + @@ -58,4 +59,5 @@ + diff --git a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs index 5662db6d9f88b2..302f00c565d0e1 100644 --- a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs +++ b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs @@ -488,5 +488,37 @@ public static void ExecuteAndUnload(string assemblyPath, string typeName, string Assert.False(alcWeakRef.IsAlive); } + + [StructLayout(LayoutKind.Sequential)] + public struct RLimit + { + public ulong rlim_cur; // Soft limit + public ulong rlim_max; // Hard limit + } + + public const int RLIMIT_CORE = 4; // Core file size + + [DllImport("libc", SetLastError = true)] + public static extern int setrlimit(int resource, ref RLimit rlim); + + // Ensure that the OS doesn't generate core dump for the current process + public static void DisableOSCoreDump() + { + // At present, RLimit is defined in a way where the fields are always 64-bit. + // Before adding support for a new platform, its definition of rlimit should be confirmed. + if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) + { + RLimit rlimit = new RLimit + { + rlim_cur = 0, + rlim_max = 0 + }; + + if (setrlimit(RLIMIT_CORE, ref rlimit) != 0) + { + throw new Exception($"Failed to disable core dump, error {Marshal.GetLastPInvokeError()} - {Marshal.GetLastPInvokeErrorMessage()}."); + } + } + } } } diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index 433ef1b7898bc4..1569ec4c8ea8f6 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -137,7 +137,8 @@ - + + @@ -248,7 +249,6 @@ - diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/gRPC/grpc-dotnet/test/Shared/HttpEventSourceListener.cs b/src/tests/FunctionalTests/Android/Device_Emulator/gRPC/grpc-dotnet/test/Shared/HttpEventSourceListener.cs index d03fe0dc2b7501..8029aaf05548d9 100755 --- a/src/tests/FunctionalTests/Android/Device_Emulator/gRPC/grpc-dotnet/test/Shared/HttpEventSourceListener.cs +++ b/src/tests/FunctionalTests/Android/Device_Emulator/gRPC/grpc-dotnet/test/Shared/HttpEventSourceListener.cs @@ -73,7 +73,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) _messageBuilder.Append(" - "); _messageBuilder.Append(eventData.EventName); _messageBuilder.Append(" : "); -#if !NET472 +#if NET _messageBuilder.AppendJoin(',', eventData.Payload!); #else _messageBuilder.Append(string.Join(",", eventData.Payload!.ToArray())); diff --git a/src/tests/Interop/DllImportAttribute/DllImportPath/DllImportPathNative.cpp b/src/tests/Interop/DllImportAttribute/DllImportPath/DllImportPathNative.cpp index 01860fef6ad677..0337138c0c13ed 100644 --- a/src/tests/Interop/DllImportAttribute/DllImportPath/DllImportPathNative.cpp +++ b/src/tests/Interop/DllImportAttribute/DllImportPath/DllImportPathNative.cpp @@ -10,7 +10,7 @@ extern "C" DLL_EXPORT int STDMETHODCALLTYPE GetZero() #ifdef EXE -extern "C" int __cdecl main(int argc, char **argv) +int __cdecl main(int argc, char **argv) { return 0; } diff --git a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorB.cs b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorB.cs index 3c733b6cfd0fe0..c6270319831da3 100644 --- a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorB.cs +++ b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorB.cs @@ -69,7 +69,12 @@ public unsafe partial class GenericsTest [ActiveIssue("https://github.com/dotnet/runtimelab/issues/177", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static void TestVectorB() { - if (Vector.Count == 32) + if (Vector.Count == 64) + { + // TODO: P/Invoke tests do not yet handle 512-bit Vector + return; + } + else if (Vector.Count == 32) { TestVectorB256(); } diff --git a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorC.cs b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorC.cs index 7f78d30fca6d3f..3753aad056294c 100644 --- a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorC.cs +++ b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorC.cs @@ -69,7 +69,12 @@ public unsafe partial class GenericsTest [ActiveIssue("https://github.com/dotnet/runtimelab/issues/177", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static void TestVectorC() { - if (Vector.Count == 16) + if (Vector.Count == 32) + { + // TODO: P/Invoke tests do not yet handle 512-bit Vector + return; + } + else if (Vector.Count == 16) { TestVectorC256(); } diff --git a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorD.cs b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorD.cs index a8638a7213d531..c3ce7b1d1a3e82 100644 --- a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorD.cs +++ b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorD.cs @@ -69,7 +69,12 @@ public unsafe partial class GenericsTest [ActiveIssue("https://github.com/dotnet/runtimelab/issues/177", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static void TestVectorD() { - if (Vector.Count == 4) + if (Vector.Count == 8) + { + // TODO: P/Invoke tests do not yet handle 512-bit Vector + return; + } + else if (Vector.Count == 4) { TestVectorD256(); } diff --git a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorF.cs b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorF.cs index abae129e978fc6..743d28ad715f86 100644 --- a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorF.cs +++ b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorF.cs @@ -69,7 +69,12 @@ public unsafe partial class GenericsTest [ActiveIssue("https://github.com/dotnet/runtimelab/issues/177", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static void TestVectorF() { - if (Vector.Count == 8) + if (Vector.Count == 16) + { + // TODO: P/Invoke tests do not yet handle 512-bit Vector + return; + } + else if (Vector.Count == 8) { TestVectorF256(); } diff --git a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorL.cs b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorL.cs index df1743cc4aa0f7..56080a40ce2d7d 100644 --- a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorL.cs +++ b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorL.cs @@ -69,7 +69,12 @@ public unsafe partial class GenericsTest [ActiveIssue("https://github.com/dotnet/runtimelab/issues/177", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static void TestVectorL() { - if (Vector.Count == 4) + if (Vector.Count == 8) + { + // TODO: P/Invoke tests do not yet handle 512-bit Vector + return; + } + else if (Vector.Count == 4) { TestVectorL256(); } diff --git a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorU.cs b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorU.cs index dbbb00991ddd55..fe7863513b3d32 100644 --- a/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorU.cs +++ b/src/tests/Interop/PInvoke/Generics/GenericsTest.VectorU.cs @@ -69,7 +69,12 @@ public unsafe partial class GenericsTest [ActiveIssue("https://github.com/dotnet/runtimelab/issues/177", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static void TestVectorU() { - if (Vector.Count == 8) + if (Vector.Count == 16) + { + // TODO: P/Invoke tests do not yet handle 512-bit Vector + return; + } + else if (Vector.Count == 8) { TestVectorU256(); } diff --git a/src/tests/JIT/HardwareIntrinsics/General/ConstantFolding/StaticReadonlySimd.cs b/src/tests/JIT/HardwareIntrinsics/General/ConstantFolding/StaticReadonlySimd.cs index df3b79a5077748..fff5bdbb5f8bd7 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/ConstantFolding/StaticReadonlySimd.cs +++ b/src/tests/JIT/HardwareIntrinsics/General/ConstantFolding/StaticReadonlySimd.cs @@ -24,8 +24,8 @@ public static void TestEntryPoint() static readonly Vector2 v1 = new Vector2(-1.0f, 2.0f); static readonly Vector3 v2 = new Vector3(-1.0f, 2.0f, -0.0f); static readonly Vector4 v3 = new Vector4(-1.0f, 2.0f, -3.0f, 4.0f); - static readonly Vector v4 = new Vector(new long[] { 1,2,3,4 }); - static readonly Vector v5 = new Vector(new float[] { 1,2,3,4,5,6,7,8 }); + static readonly Vector v4 = Vector.CreateSequence(1L, 1); + static readonly Vector v5 = Vector.CreateSequence(1.0f, 1); static readonly Vector64 v6 = Vector64.Create(-3.14f); static readonly Vector64 v7 = Vector64.Create((long)42); static readonly Vector128 v8 = Vector128.Create((ulong)1111111111,2222222222); @@ -39,8 +39,8 @@ static void Test() AssertEquals(v1, new Vector2(-1.0f, 2.0f)); AssertEquals(v2, new Vector3(-1.0f, 2.0f, -0.0f)); AssertEquals(v3, new Vector4(-1.0f, 2.0f, -3.0f, 4.0f)); - AssertEquals(v4, new Vector(new long[] { 1,2,3,4 })); - AssertEquals(v5, new Vector(new float[] { 1,2,3,4,5,6,7,8 })); + AssertEquals(v4, Vector.CreateSequence(1L, 1)); + AssertEquals(v5, Vector.CreateSequence(1.0f, 1)); AssertEquals(v6, Vector64.Create(-3.14f)); AssertEquals(v7, Vector64.Create((long)42)); AssertEquals(v8, Vector128.Create((ulong)1111111111, 2222222222)); diff --git a/src/tests/JIT/HardwareIntrinsics/X86/General/IsSupported.cs b/src/tests/JIT/HardwareIntrinsics/X86/General/IsSupported.cs index 18241d9ecfc40d..c1769def972831 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/General/IsSupported.cs +++ b/src/tests/JIT/HardwareIntrinsics/X86/General/IsSupported.cs @@ -19,6 +19,11 @@ public static void IsSupported() if (Sse.IsSupported && int.TryParse(Environment.GetEnvironmentVariable("DOTNET_EnableIncompleteISAClass"), out var enableIncompleteIsa) && (enableIncompleteIsa != 0)) { // X86 platforms + if (Vector.Count == 64 && !Avx512F.IsSupported) + { + result = false; + } + if (Vector.Count == 32 && !Avx2.IsSupported) { result = false; diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs index d7c3e1aee3af89..aeeb847495fd5a 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs @@ -381,25 +381,21 @@ public unsafe static void CpuId() testResult = Fail; } - if (Vector.Count == 16) + int vectorTByteLength = 16; + int maxVectorTBitWidth = (GetDotnetEnvVar("MaxVectorTBitWidth", defaultValue: 0) / 128) * 128; + + if ((maxVectorTBitWidth >= 512) && !isAvx512HierarchyDisabled) { - if (!isAvx2HierarchyDisabled) - { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned 16 but the hardware returned 32"); - testResult = Fail; - } + vectorTByteLength = int.Min(64, preferredVectorByteLength); } - else if (Vector.Count == 32) + else if ((maxVectorTBitWidth is 0 or >= 256) && !isAvx2HierarchyDisabled) { - if (isAvx2HierarchyDisabled) - { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned 32 but the hardware returned 16"); - testResult = Fail; - } + vectorTByteLength = int.Min(32, preferredVectorByteLength); } - else + + if (Vector.Count != vectorTByteLength) { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned {Vector.Count} which is unexpected"); + Console.WriteLine($"{typeof(Vector).FullName}.Count returned {Vector.Count}. The expected value was {vectorTByteLength}."); testResult = Fail; } diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.cs b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.cs deleted file mode 100644 index 30c2a11b0b9e4a..00000000000000 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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.Globalization; -using Xunit; - -namespace DefaultNamespace -{ - public class bug - { - [Fact] - public static void TestEntryPoint() - { - CultureInfo ci = new CultureInfo("en-us"); - } - } -} diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.cs b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.cs deleted file mode 100644 index 3b92856e0cfda4..00000000000000 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Globalization; -using System; -using Xunit; - -namespace DefaultNamespace -{ - public class Bug - { - internal virtual void runTest() - { - CultureInfo en = new CultureInfo("en-US"); - Double d = Convert.ToDouble("1.0E19", en.NumberFormat); - Console.WriteLine("Expected value==" + d.ToString("E", en.NumberFormat)); - UInt64 l = (UInt64)d; - Console.WriteLine("Returned value==" + l.ToString("E", en.NumberFormat)); - if (d.ToString("E", en.NumberFormat).Equals(l.ToString("E", en.NumberFormat))) - Console.WriteLine("Test passed"); - else - Console.WriteLine("Test FAiLED"); - } - - [Fact] - public static void TestEntryPoint() - { - new Bug().runTest(); - } - } -} diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.cs b/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.cs index 63807ab0f64032..1b68ed8f3eb972 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.cs +++ b/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.cs @@ -44,11 +44,11 @@ internal void NarrowDouble() internal static double[] GenerateSource1() { - return new double[4] { 5.1, 5.2, 5.3, 5.4 }; + return new double[] { 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8 }; } internal static double[] GenerateSource2() { - return new double[4] { 6.1, 6.2, 6.3, 6.4 }; + return new double[] { 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8 }; } } } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_113486/Runtime_113486.cs b/src/tests/JIT/Regression/JitBlue/Runtime_113486/Runtime_113486.cs new file mode 100644 index 00000000000000..735aeb3004594b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_113486/Runtime_113486.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. + +// Generated by Fuzzlyn v2.5 on 2025-03-13 04:40:20 +// Run on Arm Linux +// Seed: 13401882525903110030 +// Reduced from 421.9 KiB to 1.1 KiB in 00:03:35 +// Hits JIT assert in Release: +// Assertion failed '!"Detected conflicting incoming edges when homing parameter registers"' in 'Program:M42(S0,byte,byte):S0' during 'Generate code' (IL size 83; hash 0x8f48ed9b; FullOpts) +// +// File: /__w/1/s/src/coreclr/jit/codegencommon.cpp Line: 3225 +// +using System; +using Xunit; + +public class Runtime_113486 +{ + static IRuntime s_rt; + static S0[,, ] s_14; + static sbyte[][] s_44 = new sbyte[][] + { + new sbyte[] + { + 0 + } + }; + + [Fact] + public static void TestEntryPoint() + { + try + { + var vr5 = new S0(); + var vr6 = s_44[0][0]; + M42(vr5, vr6, 0); + } + catch + { + } + } + + static S0 M42(S0 arg0, sbyte arg2, sbyte arg3) + { + for (int var0 = 0; var0 < 1; var0++) + { + ushort var1 = (ushort)(-M44()); + arg0.F0 = var1++; + s_rt.WriteLine("c_223", var1); + } + + arg3 = arg2; + arg0.F1 = arg0.F0; + s_rt.WriteLine("c_231", arg3); + return arg0; + } + + static ushort M44() + { + return s_14[0, 0, 0].F1--; + } + + struct S0 + { + public ushort F0; + public ushort F1; + } + + interface IRuntime + { + void WriteLine(string site, T value); + } + + class Runtime : IRuntime + { + public void WriteLine(string site, T value) => System.Console.WriteLine(value); + } +} + + diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_113486/Runtime_113486.csproj similarity index 58% rename from src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj rename to src/tests/JIT/Regression/JitBlue/Runtime_113486/Runtime_113486.csproj index e3c43ccd560571..de6d5e08882e86 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_113486/Runtime_113486.csproj @@ -1,9 +1,6 @@ - 1 - - - PdbOnly + True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.cs b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.cs new file mode 100644 index 00000000000000..7e501802f43021 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v2.5 on 2025-03-13 04:54:06 +// Run on X64 Linux +// Seed: 15128240988293741626-vectort,vector128,vector256,x86aes,x86avx,x86avx2,x86bmi1,x86bmi1x64,x86bmi2,x86bmi2x64,x86fma,x86lzcnt,x86lzcntx64,x86pclmulqdq,x86popcnt,x86popcntx64,x86sse,x86ssex64,x86sse2,x86sse2x64,x86sse3,x86sse41,x86sse41x64,x86sse42,x86sse42x64,x86ssse3,x86x86base +// Reduced from 188.7 KiB to 0.8 KiB in 00:01:09 +// Debug: Outputs 0 +// Release: Outputs 1 +using System; +using System.Numerics; +using System.Runtime.Intrinsics; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_113488 +{ + [Fact] + public static int TestEntryPoint() + { + S0 vr0 = default(S0); + return M4(vr0, Vector256.Create(vr0.M7())); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int M4(S0 arg0, Vector256 arg1) + { + return arg0.F0 == 0 ? 100 : 101; + } + + private struct S0 + { + public uint F0; + [MethodImpl(MethodImplOptions.NoInlining)] + public ushort M7() + { + this.F0 = 1; + return 0; + } + } +} diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.csproj similarity index 58% rename from src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj rename to src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.csproj index e3c43ccd560571..de6d5e08882e86 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.csproj @@ -1,9 +1,6 @@ - 1 - - - PdbOnly + True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs index e1c9dfab2e2cca..484740c3063505 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs @@ -715,7 +715,9 @@ static bool ValidateVectorT() if (Avx2IsSupported) { succeeded &= VectorIsHardwareAccelerated; - succeeded &= VectorByteCount == 32; + // MaxVectorTBitWidth env variable can be used to change Vector size. + // We can only assume it is at least 16 bytes. + succeeded &= VectorByteCount >= 16; } else if (Sse2IsSupported) { diff --git a/src/tests/JIT/SIMD/BitwiseOperations.cs b/src/tests/JIT/SIMD/BitwiseOperations.cs index 5d87fdfeb3d01f..fe59c06406efc1 100644 --- a/src/tests/JIT/SIMD/BitwiseOperations.cs +++ b/src/tests/JIT/SIMD/BitwiseOperations.cs @@ -24,12 +24,22 @@ static float NextFloat(Random random) return (float)(mantissa * exponent); } + static double[] GenerateDoubleArray(int size, Random random) + { + double[] arr = new double[size]; + for (int i = 0; i < size; ++i) + { + arr[i] = NextFloat(random); + } + return arr; + } + [Fact] public static int TestDouble() { Random random = new Random(Seed); - double[] arr1 = new double[] { NextFloat(random), NextFloat(random), NextFloat(random), NextFloat(random) }; - double[] arr2 = new double[] { NextFloat(random), NextFloat(random), NextFloat(random), NextFloat(random) }; + double[] arr1 = GenerateDoubleArray(System.Numerics.Vector.Count, random); + double[] arr2 = GenerateDoubleArray(System.Numerics.Vector.Count, random); var a = new System.Numerics.Vector(arr1); var b = new System.Numerics.Vector(arr2); var xorR = a ^ b; @@ -81,8 +91,8 @@ static byte[] GenerateByteArray(int size, Random random) public static int TestBool() { Random random = new Random(Seed); - byte[] arr1 = GenerateByteArray(64, random); - byte[] arr2 = GenerateByteArray(64, random); + byte[] arr1 = GenerateByteArray(System.Numerics.Vector.Count, random); + byte[] arr2 = GenerateByteArray(System.Numerics.Vector.Count, random); var a = new System.Numerics.Vector(arr1); var b = new System.Numerics.Vector(arr2); diff --git a/src/tests/JIT/SIMD/VectorGet.cs b/src/tests/JIT/SIMD/VectorGet.cs index 51c78f292664af..6e2ae799a8cfa3 100644 --- a/src/tests/JIT/SIMD/VectorGet.cs +++ b/src/tests/JIT/SIMD/VectorGet.cs @@ -106,6 +106,41 @@ public static int VectorGet(T value, int index) if (!CheckValue(A[30], value)) returnVal = Fail; if (!CheckValue(A[31], value)) returnVal = Fail; } + if (Vector.Count >= 64) + { + if (!CheckValue(A[32], value)) returnVal = Fail; + if (!CheckValue(A[33], value)) returnVal = Fail; + if (!CheckValue(A[34], value)) returnVal = Fail; + if (!CheckValue(A[35], value)) returnVal = Fail; + if (!CheckValue(A[36], value)) returnVal = Fail; + if (!CheckValue(A[37], value)) returnVal = Fail; + if (!CheckValue(A[38], value)) returnVal = Fail; + if (!CheckValue(A[39], value)) returnVal = Fail; + if (!CheckValue(A[40], value)) returnVal = Fail; + if (!CheckValue(A[41], value)) returnVal = Fail; + if (!CheckValue(A[42], value)) returnVal = Fail; + if (!CheckValue(A[43], value)) returnVal = Fail; + if (!CheckValue(A[44], value)) returnVal = Fail; + if (!CheckValue(A[45], value)) returnVal = Fail; + if (!CheckValue(A[46], value)) returnVal = Fail; + if (!CheckValue(A[47], value)) returnVal = Fail; + if (!CheckValue(A[48], value)) returnVal = Fail; + if (!CheckValue(A[49], value)) returnVal = Fail; + if (!CheckValue(A[50], value)) returnVal = Fail; + if (!CheckValue(A[51], value)) returnVal = Fail; + if (!CheckValue(A[52], value)) returnVal = Fail; + if (!CheckValue(A[53], value)) returnVal = Fail; + if (!CheckValue(A[54], value)) returnVal = Fail; + if (!CheckValue(A[55], value)) returnVal = Fail; + if (!CheckValue(A[56], value)) returnVal = Fail; + if (!CheckValue(A[57], value)) returnVal = Fail; + if (!CheckValue(A[58], value)) returnVal = Fail; + if (!CheckValue(A[59], value)) returnVal = Fail; + if (!CheckValue(A[60], value)) returnVal = Fail; + if (!CheckValue(A[61], value)) returnVal = Fail; + if (!CheckValue(A[62], value)) returnVal = Fail; + if (!CheckValue(A[63], value)) returnVal = Fail; + } return returnVal; } @@ -129,6 +164,7 @@ public static int VectorGetIndexerOutOfRange(T value, int index) case 8: check = A[8]; break; case 16: check = A[16]; break; case 32: check = A[32]; break; + case 64: check = A[64]; break; } } catch (ArgumentOutOfRangeException) diff --git a/src/tests/JIT/interpreter/Interpreter.cs b/src/tests/JIT/interpreter/Interpreter.cs index 0dc20964fc6a50..d26415da5a4d12 100644 --- a/src/tests/JIT/interpreter/Interpreter.cs +++ b/src/tests/JIT/interpreter/Interpreter.cs @@ -15,7 +15,61 @@ static int Main(string[] args) [MethodImpl(MethodImplOptions.NoInlining)] public static void RunInterpreterTests() { -// Console.WriteLine("Run interp tests"); +// Console.WriteLine("Run interp tests"); + if (SumN(50) != 1275) + Environment.FailFast(null); + if (Mul4(53, 24, 13, 131) != 2166216) + Environment.FailFast(null); + + TestSwitch(); + + if (!PowLoop(20, 10, 1661992960)) + Environment.FailFast(null); + } + + public static int Mul4(int a, int b, int c, int d) + { + return a * b * c * d; } + public static long SumN(int n) + { + if (n == 1) + return 1; + return (long)SumN(n - 1) + n; + } + + public static int SwitchOp(int a, int b, int op) + { + switch (op) + { + case 0: + return a + b; + case 1: + return a - b; + case 2: + return a * b; + default: + return 42; + } + } + + public static void TestSwitch() + { + int n0 = SwitchOp (20, 6, 0); // 26 + int n1 = SwitchOp (20, 6, 1); // 14 + int n2 = SwitchOp (20, 6, 2); // 120 + int n3 = SwitchOp (20, 6, 3); // 42 + + if ((n0 + n1 + n2 + n3) != 202) + Environment.FailFast(null); + } + + public static bool PowLoop(int n, long nr, int expected) + { + long ret = 1; + for (int i = 0; i < n; i++) + ret *= nr; + return (int)ret == expected; + } } diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i00.il b/src/tests/JIT/jit64/mcc/interop/mcc_i00.il index 024e980485dd04..643fd60e6cc5df 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i00.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i00.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i00' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType0 res, @@ -67,7 +81,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i00.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i00.ilproj index 0ad72187bbe3f5..c58e15136b4e67 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i00.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i00.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i01.il b/src/tests/JIT/jit64/mcc/interop/mcc_i01.il index 7f4206cb4684c2..96706942d693d0 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i01.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i01.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i01' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType0 res, @@ -67,7 +81,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i01.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i01.ilproj index e1d3e1854212c7..43ce9abf2bef40 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i01.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i01.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i02.il b/src/tests/JIT/jit64/mcc/interop/mcc_i02.il index 1545c86e36413c..8fa5946d0ddc87 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i02.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i02.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i02' {} @@ -65,6 +66,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -87,7 +101,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i02.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i02.ilproj index 579b27b0825b5a..ae81c030f373f0 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i02.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i02.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i03.il b/src/tests/JIT/jit64/mcc/interop/mcc_i03.il index 2d9cc5750b9152..b7fe944ac8d96b 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i03.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i03.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i03' {} @@ -69,6 +70,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -91,7 +105,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i03.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i03.ilproj index 63ddf111d25dd5..62873a0d070815 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i03.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i03.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i04.il b/src/tests/JIT/jit64/mcc/interop/mcc_i04.il index 4713ed519a0bf5..513f97e5b15a0f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i04.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i04.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i04' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType0 res, @@ -64,7 +78,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i04.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i04.ilproj index d087100bc7ce6f..54625880fe0bb8 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i04.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i04.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i05.il b/src/tests/JIT/jit64/mcc/interop/mcc_i05.il index 36a5a474f5b439..371e7658f61378 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i05.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i05.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i05' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType0 res, @@ -64,7 +78,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i05.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i05.ilproj index f0d04d22c8e2bf..077d709e91c83c 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i05.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i05.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i06.il b/src/tests/JIT/jit64/mcc/interop/mcc_i06.il index 93e1d347d64553..c97bec796c6dea 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i06.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i06.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i06' {} @@ -62,6 +63,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -84,7 +98,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i06.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i06.ilproj index f4137f59255f0d..dc5876559331b0 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i06.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i06.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i07.il b/src/tests/JIT/jit64/mcc/interop/mcc_i07.il index 693baa38d1bd41..011f657a0d05e5 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i07.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i07.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i07' {} @@ -66,6 +67,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -88,7 +102,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i07.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i07.ilproj index 9f14b87091e430..4c5369290d734f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i07.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i07.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i10.il b/src/tests/JIT/jit64/mcc/interop/mcc_i10.il index 195dd48deedac5..bf6de645fbb8b2 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i10.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i10.il @@ -4,6 +4,7 @@ .assembly extern mscorlib {} .assembly extern xunit.core {} +.assembly extern TestLibrary {} .assembly 'mcc_i10' {} @@ -21,6 +22,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType1 res, @@ -65,7 +79,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i10.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i10.ilproj index 62c716a9b27457..6699fe8d46215e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i10.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i10.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i11.il b/src/tests/JIT/jit64/mcc/interop/mcc_i11.il index 66dca4d4deffa6..352f365f78fea3 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i11.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i11.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i11' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType1 res, @@ -67,7 +81,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i11.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i11.ilproj index 13f35e3c4f4641..7d72c6308ac44e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i11.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i11.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i12.il b/src/tests/JIT/jit64/mcc/interop/mcc_i12.il index 0f64a7276e904c..ec944a090fdbe1 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i12.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i12.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i12' {} @@ -65,6 +66,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -87,7 +101,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i12.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i12.ilproj index f4fe0071354300..5ef63ea4740672 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i12.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i12.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i13.il b/src/tests/JIT/jit64/mcc/interop/mcc_i13.il index e81aa911725668..a01f8cea8c032c 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i13.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i13.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i13' {} @@ -69,6 +70,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -91,7 +105,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i13.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i13.ilproj index c50b908df1f353..b907cf3e9380aa 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i13.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i13.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i14.il b/src/tests/JIT/jit64/mcc/interop/mcc_i14.il index a1ee5a04dbef75..87c150a7a4c171 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i14.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i14.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i14' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType1 res, @@ -64,7 +78,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i14.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i14.ilproj index d2b249fe4536eb..8f5bda38998597 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i14.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i14.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i15.il b/src/tests/JIT/jit64/mcc/interop/mcc_i15.il index 6db8691e703d23..c514bfd3180bd6 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i15.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i15.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i15' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType1 res, @@ -64,7 +78,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i15.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i15.ilproj index 44d32823e6b758..927f7972ec5351 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i15.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i15.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i16.il b/src/tests/JIT/jit64/mcc/interop/mcc_i16.il index a4e1fc3229a716..601a54a495e372 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i16.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i16.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i16' {} @@ -62,6 +63,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -84,7 +98,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i16.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i16.ilproj index 6fba00cebe3112..20d34b93bedb29 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i16.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i16.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i17.il b/src/tests/JIT/jit64/mcc/interop/mcc_i17.il index fa45cf93b8bb0b..fada771dd937d8 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i17.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i17.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i17' {} @@ -66,6 +67,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -88,7 +102,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i17.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i17.ilproj index 879847d2460291..e12d913939eb9e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i17.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i17.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i30.il b/src/tests/JIT/jit64/mcc/interop/mcc_i30.il index cc2a4796eadf7d..7628d38e8943d3 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i30.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i30.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i30' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType3 res, @@ -110,7 +124,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i30.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i30.ilproj index 3a8fa8fbad2d6e..98a31bed6f2b98 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i30.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i30.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i31.il b/src/tests/JIT/jit64/mcc/interop/mcc_i31.il index 3f6e9353db4eb7..29840bbb675c5e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i31.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i31.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i31' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType3 res, @@ -111,7 +125,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i31.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i31.ilproj index b220adc4cea58e..98ada555714949 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i31.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i31.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i32.il b/src/tests/JIT/jit64/mcc/interop/mcc_i32.il index 0eaadcf885a778..7324c5f0250331 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i32.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i32.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i32' {} @@ -111,6 +112,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -133,7 +147,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i32.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i32.ilproj index caecb62df65ef2..ee6b62f899e75e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i32.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i32.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i33.il b/src/tests/JIT/jit64/mcc/interop/mcc_i33.il index ae71b3592b8aa8..493cc18e4e6156 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i33.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i33.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i33' {} @@ -115,6 +116,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -137,7 +151,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i33.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i33.ilproj index 1f0c4c71f98216..443cbb3bc3eaf0 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i33.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i33.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i34.il b/src/tests/JIT/jit64/mcc/interop/mcc_i34.il index 743c33028a9b09..587acbd136d71a 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i34.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i34.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i34' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType3 res, @@ -119,7 +133,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i34.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i34.ilproj index f964dbdc6ca024..4d14fa4111efba 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i34.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i34.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i35.il b/src/tests/JIT/jit64/mcc/interop/mcc_i35.il index 50cbb5aefe991b..f33a66db338caa 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i35.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i35.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i35' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType3 res, @@ -123,7 +137,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i35.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i35.ilproj index 4f4b8c0cefcfdd..eaee8585d46d02 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i35.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i35.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i36.il b/src/tests/JIT/jit64/mcc/interop/mcc_i36.il index e04ab1ec7a372a..a36196f959cfaf 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i36.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i36.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i36' {} @@ -120,6 +121,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -142,7 +156,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i36.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i36.ilproj index 53f0bc38a885a4..3c007857ad1e8f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i36.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i36.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i37.il b/src/tests/JIT/jit64/mcc/interop/mcc_i37.il index 85956df45f6d1c..fe6c1f80052b14 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i37.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i37.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i37' {} @@ -130,6 +131,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -152,7 +166,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i37.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i37.ilproj index 06d495a4edcdea..9dae201ba3f53f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i37.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i37.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i50.il b/src/tests/JIT/jit64/mcc/interop/mcc_i50.il index bab75bcb13ac92..db16aa6ccacb47 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i50.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i50.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i50' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType5 res, @@ -110,7 +124,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i50.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i50.ilproj index 8f3b5897b22954..f10402760fe6dd 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i50.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i50.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i51.il b/src/tests/JIT/jit64/mcc/interop/mcc_i51.il index 5a3250ce3c339f..3d83449738121d 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i51.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i51.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i51' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType5 res, @@ -111,7 +125,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i51.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i51.ilproj index c128264f48ac22..87391689bcffbc 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i51.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i51.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i52.il b/src/tests/JIT/jit64/mcc/interop/mcc_i52.il index e13c785097a1ea..dbd1afb3cc818f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i52.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i52.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i52' {} @@ -111,6 +112,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -133,7 +147,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i52.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i52.ilproj index 1732f034a90120..1cb2b1e6f80313 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i52.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i52.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i53.il b/src/tests/JIT/jit64/mcc/interop/mcc_i53.il index 26891b32e101ce..2f89500eaf3d88 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i53.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i53.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i53' {} @@ -115,6 +116,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -137,7 +151,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i53.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i53.ilproj index b5749e8fa181b8..67fd7642e8a00f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i53.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i53.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i54.il b/src/tests/JIT/jit64/mcc/interop/mcc_i54.il index 838aa86b074fce..6f4cd1d1bcbd8e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i54.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i54.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i54' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType5 res, @@ -119,7 +133,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i54.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i54.ilproj index 08ff8844498373..c104c160fe5822 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i54.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i54.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i55.il b/src/tests/JIT/jit64/mcc/interop/mcc_i55.il index 667f20c36d5c16..e09d51a2d47a6c 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i55.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i55.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i55' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType5 res, @@ -123,7 +137,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i55.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i55.ilproj index e154b195f64d33..2693aad2c281cd 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i55.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i55.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i56.il b/src/tests/JIT/jit64/mcc/interop/mcc_i56.il index fc8dc54004df33..82682029c634f6 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i56.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i56.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i56' {} @@ -120,6 +121,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -142,7 +156,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i56.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i56.ilproj index d050e4748d1df9..7c471a550f8077 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i56.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i56.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i57.il b/src/tests/JIT/jit64/mcc/interop/mcc_i57.il index df6294d7dde3b7..7beabc95f2336c 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i57.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i57.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i57' {} @@ -130,6 +131,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -152,7 +166,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i57.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i57.ilproj index e3c11ac3b68353..8ebc6d5c7f13ba 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i57.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i57.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i60.il b/src/tests/JIT/jit64/mcc/interop/mcc_i60.il index 5f5f9b7fae1ee6..8cfae191d1d85b 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i60.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i60.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i60' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType6 res, @@ -110,7 +124,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i60.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i60.ilproj index 8b62e64956e225..1148d1bc834696 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i60.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i60.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i61.il b/src/tests/JIT/jit64/mcc/interop/mcc_i61.il index 1b27b1f2fda4a3..6a87acf43cd29f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i61.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i61.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i61' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType6 res, @@ -111,7 +125,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i61.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i61.ilproj index 0f5fad33d275f6..042e51cbe97b00 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i61.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i61.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i62.il b/src/tests/JIT/jit64/mcc/interop/mcc_i62.il index f5bfc4ba9859be..da06069bc5e402 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i62.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i62.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i62' {} @@ -111,6 +112,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -133,7 +147,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i62.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i62.ilproj index 3af6de1a79214b..d81f2bd3413dfa 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i62.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i62.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i63.il b/src/tests/JIT/jit64/mcc/interop/mcc_i63.il index 3a08f300540a7b..4dc777b0a9c666 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i63.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i63.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i63' {} @@ -115,6 +116,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -137,7 +151,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i63.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i63.ilproj index f9e8e399952be1..8cdbe8a2450d7f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i63.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i63.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i64.il b/src/tests/JIT/jit64/mcc/interop/mcc_i64.il index 09b031b5a3268e..10b8699edfeb9d 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i64.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i64.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i64' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType6 res, @@ -119,7 +133,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i64.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i64.ilproj index 6e2f9a8ee2a8c1..37ebe4def03ac9 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i64.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i64.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i65.il b/src/tests/JIT/jit64/mcc/interop/mcc_i65.il index 300f87bd1bb2cc..f98ed7062720cc 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i65.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i65.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i65' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType6 res, @@ -123,7 +137,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i65.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i65.ilproj index 46007f4d37f03f..f094081f2781fe 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i65.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i65.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i66.il b/src/tests/JIT/jit64/mcc/interop/mcc_i66.il index 2235c56ffbbd65..1a27a1ce6074f5 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i66.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i66.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i66' {} @@ -120,6 +121,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -142,7 +156,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i66.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i66.ilproj index 8cb73b07658114..0245c82c70fa45 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i66.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i66.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i67.il b/src/tests/JIT/jit64/mcc/interop/mcc_i67.il index 3edaa17fd7ac7c..aca5300c2f62c5 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i67.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i67.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i67' {} @@ -130,6 +131,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -152,7 +166,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i67.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i67.ilproj index 2c9b7bb209289c..c904066f8bd31f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i67.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i67.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i70.il b/src/tests/JIT/jit64/mcc/interop/mcc_i70.il index 804b2e362509af..d9d2b8d53769db 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i70.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i70.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i70' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType7 res, @@ -110,7 +124,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i70.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i70.ilproj index fecb2dd11a5823..114aaa135cf938 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i70.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i70.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i71.il b/src/tests/JIT/jit64/mcc/interop/mcc_i71.il index ff00b492a9629b..17796525ca82db 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i71.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i71.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i71' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType7 res, @@ -111,7 +125,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i71.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i71.ilproj index f10d7a624eee61..d01b2017d8735f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i71.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i71.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i72.il b/src/tests/JIT/jit64/mcc/interop/mcc_i72.il index 624a226f57ac57..9f740b097830d6 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i72.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i72.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i72' {} @@ -111,6 +112,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -133,7 +147,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i72.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i72.ilproj index 676bd5f9789999..da8c88d45b2860 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i72.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i72.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i73.il b/src/tests/JIT/jit64/mcc/interop/mcc_i73.il index 3678eb207e88d8..1ac742b793fed1 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i73.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i73.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i73' {} @@ -115,6 +116,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -137,7 +151,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i73.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i73.ilproj index cceffd8161b6d1..06bc3293ba8f1d 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i73.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i73.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i74.il b/src/tests/JIT/jit64/mcc/interop/mcc_i74.il index be8b55b09afc9f..766f212a8c655e 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i74.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i74.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i74' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType7 res, @@ -119,7 +133,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i74.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i74.ilproj index 7efcfd1588b8d6..2f1f69f1787530 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i74.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i74.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i75.il b/src/tests/JIT/jit64/mcc/interop/mcc_i75.il index dd4f19dde81102..49bffbb179c67f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i75.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i75.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i75' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType7 res, @@ -123,7 +137,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i75.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i75.ilproj index cf5708ca2b3aef..ed2ab7686c8e29 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i75.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i75.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i76.il b/src/tests/JIT/jit64/mcc/interop/mcc_i76.il index a2410942540ea7..d5c720cd8d23af 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i76.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i76.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i76' {} @@ -120,6 +121,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -142,7 +156,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i76.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i76.ilproj index 7e9f22a734ac93..3e738559059529 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i76.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i76.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i77.il b/src/tests/JIT/jit64/mcc/interop/mcc_i77.il index d1f022724653af..cfd861ad5a9138 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i77.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i77.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i77' {} @@ -130,6 +131,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -152,7 +166,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i77.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i77.ilproj index 942a1865b890f6..78c818ed17882f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i77.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i77.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i80.il b/src/tests/JIT/jit64/mcc/interop/mcc_i80.il index 41b8a915083d99..812103323ac463 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i80.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i80.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i80' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType8 res, @@ -110,7 +124,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i80.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i80.ilproj index 2b141ea4669dd2..6db3740e8a2091 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i80.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i80.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i81.il b/src/tests/JIT/jit64/mcc/interop/mcc_i81.il index ecafc9dbb62c47..730ebe71e76ad5 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i81.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i81.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i81' {} @@ -23,6 +24,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType8 res, @@ -111,7 +125,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i81.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i81.ilproj index 1c3db38870921a..cf8adea61d53b0 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i81.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i81.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i82.il b/src/tests/JIT/jit64/mcc/interop/mcc_i82.il index cc4a55192db2d5..5bb8ca33de683b 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i82.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i82.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i82' {} @@ -111,6 +112,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -133,7 +147,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i82.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i82.ilproj index 381bba53461e8d..b1fdd28b2ef02d 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i82.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i82.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i83.il b/src/tests/JIT/jit64/mcc/interop/mcc_i83.il index ceaef9b1ae16bd..6566c1a04214c3 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i83.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i83.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i83' {} @@ -115,6 +116,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -137,7 +151,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i83.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i83.ilproj index 450cfd3c5ed7d4..ae9daead51cf7f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i83.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i83.ilproj @@ -12,6 +12,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i84.il b/src/tests/JIT/jit64/mcc/interop/mcc_i84.il index a14541690a5e76..09eadbc50fcd1f 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i84.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i84.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i84' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType8 res, diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i84.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i84.ilproj index feb4cf521617a3..5d2030356fa121 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i84.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i84.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i85.il b/src/tests/JIT/jit64/mcc/interop/mcc_i85.il index 675190deb3dac3..3a628060547575 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i85.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i85.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i85' {} @@ -26,6 +27,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] valuetype MCCTest.VType8 res, @@ -123,7 +137,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i85.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i85.ilproj index 7e76d42cb22ff8..7896212c3ad2cb 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i85.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i85.ilproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i86.il b/src/tests/JIT/jit64/mcc/interop/mcc_i86.il index dec6bb9e9994ea..e9131915832a69 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i86.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i86.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i86' {} @@ -120,6 +121,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -142,7 +156,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i86.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i86.ilproj index 6d654f79b00594..af93240f2c634a 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i86.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i86.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i87.il b/src/tests/JIT/jit64/mcc/interop/mcc_i87.il index f10cb26ece1310..12fd408f02efe4 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i87.il +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i87.il @@ -5,6 +5,7 @@ .assembly extern System.Runtime.Extensions { auto } .assembly extern xunit.core {} .assembly extern mscorlib { auto } +.assembly extern TestLibrary {} .assembly 'mcc_i87' {} @@ -130,6 +131,19 @@ 01 00 00 00 ) .entrypoint + .maxstack 1 + call bool [TestLibrary]TestLibrary.PlatformDetection::get_IsWindows() + brtrue.s DoTest + ldc.i4 100 + ret + + DoTest: + call int32 MCCTest.MyClass::Test() + ret + } + + .method public static int32 Test() + { .maxstack 64 .locals init ( [0] class MCCTest.MyClass me, @@ -152,7 +166,7 @@ ldloc.s rc ret - } // end of method MyClass::Main + } // end of method MyClass::Test } // end of class MyClass diff --git a/src/tests/JIT/jit64/mcc/interop/mcc_i87.ilproj b/src/tests/JIT/jit64/mcc/interop/mcc_i87.ilproj index e9142f641e23af..a236bf2a73220c 100644 --- a/src/tests/JIT/jit64/mcc/interop/mcc_i87.ilproj +++ b/src/tests/JIT/jit64/mcc/interop/mcc_i87.ilproj @@ -7,6 +7,7 @@ + diff --git a/src/tests/JIT/opt/Cloning/loops_with_eh.cs b/src/tests/JIT/opt/Cloning/loops_with_eh.cs index 13b161f6558440..7cebcf9f7e4a7e 100644 --- a/src/tests/JIT/opt/Cloning/loops_with_eh.cs +++ b/src/tests/JIT/opt/Cloning/loops_with_eh.cs @@ -17,6 +17,7 @@ // g - giant finally (TF will remain try finally) // p - regions are serial, not nested // TFi - try finally with what follows in the finally +// I - inlining // // x: we currently cannot clone loops where the try is the first thing // as the header and preheader are different regions @@ -1127,5 +1128,141 @@ public static int Sum_TFiTFxL(int[] data, int n) return sum; } + + [Fact] + public static int Test_LTFiTF() => Sum_LTFiTF(data, n) - 130; + + public static int Sum_LTFiTF(int[] data, int n) + { + int sum = 0; + + for (int i = 0; i < n; i++) + { + sum += data[i]; + try + { + SideEffect(); + } + finally + { + try + { + SideEffect(); + } + finally + { + sum += 1; + } + + sum += 1; + } + } + + return sum; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SomeEH() + { + int sum = 0; + + try + { + SideEffect(); + } + finally + { + try + { + SideEffect(); + } + finally + { + sum += 1; + } + + sum += 1; + } + + return sum; + } + + [Fact] + public static int Test_LITFiTF() => Sum_LITFiTF(data, n) - 130; + + public static int Sum_LITFiTF(int[] data, int n) + { + int sum = 0; + + for (int i = 0; i < n; i++) + { + sum += data[i]; + sum += SomeEH(); + } + + return sum; + } + + [Fact] + public static int Test_TFLTFiTF() => Sum_TFLTFiTF(data, n) - 131; + + public static int Sum_TFLTFiTF(int[] data, int n) + { + int sum = 0; + + try + { + for (int i = 0; i < n; i++) + { + sum += data[i]; + try + { + SideEffect(); + } + finally + { + try + { + SideEffect(); + } + finally + { + sum += 1; + } + + sum += 1; + } + } + } + finally + { + SideEffect(); + sum += 1; + } + return sum; + } + + public static int Test_TFLITFiTF() => Sum_TFLITFiTF(data, n) - 131; + + public static int Sum_TFLITFiTF(int[] data, int n) + { + int sum = 0; + + try + { + for (int i = 0; i < n; i++) + { + sum += data[i]; + sum += SomeEH(); + } + } + finally + { + SideEffect(); + sum += 1; + } + + return sum; + } } diff --git a/src/tests/baseservices/exceptions/simple/ParallelCrash.cs b/src/tests/baseservices/exceptions/simple/ParallelCrash.cs index 0232e7690ae909..6869597b6511ce 100644 --- a/src/tests/baseservices/exceptions/simple/ParallelCrash.cs +++ b/src/tests/baseservices/exceptions/simple/ParallelCrash.cs @@ -7,6 +7,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using TestLibrary; // Runtime stability in the presence of concurrent fatal errors @@ -20,6 +21,9 @@ public class ParallelCrash public static int Main(string[] args) { + // Ensure that the OS doesn't generate core dump for this intentionally crashing process + Utilities.DisableOSCoreDump(); + s_crashMainThread = true; s_crashWorkerThreads = true; if (args.Length > 0) diff --git a/src/tests/baseservices/exceptions/simple/ParallelCrash.csproj b/src/tests/baseservices/exceptions/simple/ParallelCrash.csproj index 1dd852e59d8a2e..9dfc0c2fa19cca 100644 --- a/src/tests/baseservices/exceptions/simple/ParallelCrash.csproj +++ b/src/tests/baseservices/exceptions/simple/ParallelCrash.csproj @@ -8,4 +8,7 @@ + + + diff --git a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.cs b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.cs index 8249f4bbb44aca..9d000fa2856d0c 100644 --- a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.cs +++ b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.cs @@ -3,6 +3,8 @@ using System; using System.Threading; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using TestLibrary; namespace TestStackOverflow { @@ -136,6 +138,9 @@ static void SecondaryThreadsTest(bool smallframe) static void Main(string[] args) { + // Ensure that the OS doesn't generate core dump for this intentionally crashing process + Utilities.DisableOSCoreDump(); + bool smallframe = (args[0] == "smallframe"); if (args[1] == "secondary") { diff --git a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.csproj b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.csproj index e75283a0f2d0f8..ce01196c8aa523 100644 --- a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.csproj +++ b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow.csproj @@ -10,5 +10,8 @@ + + + diff --git a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.cs b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.cs index c833bae8afc15a..af840cb34d030c 100644 --- a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.cs +++ b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.cs @@ -1,6 +1,8 @@ // 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.InteropServices; +using TestLibrary; namespace TestStackOverflow3 { @@ -11,6 +13,9 @@ class Program public static void Main() { + // Ensure that the OS doesn't generate core dump for this intentionally crashing process + Utilities.DisableOSCoreDump(); + Program ex = new Program(); ex.Execute(); } diff --git a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.csproj b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.csproj index d805f0b4c7ecb2..b2f23e18dd934e 100644 --- a/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.csproj +++ b/src/tests/baseservices/exceptions/stackoverflow/stackoverflow3.csproj @@ -11,5 +11,8 @@ + + + diff --git a/src/tests/baseservices/exceptions/unhandled/unhandled.cs b/src/tests/baseservices/exceptions/unhandled/unhandled.cs index a5c91702556442..ee2e8f18649bdd 100644 --- a/src/tests/baseservices/exceptions/unhandled/unhandled.cs +++ b/src/tests/baseservices/exceptions/unhandled/unhandled.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using TestLibrary; namespace TestUnhandledException { @@ -40,6 +41,9 @@ private static void SetDllResolver() static void Main(string[] args) { + // Ensure that the OS doesn't generate core dump for this intentionally crashing process + Utilities.DisableOSCoreDump(); + if (args[0] == "main") { throw new Exception("Test"); diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/Program.cs b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/Program.cs index 8ec15aed2ff2fd..92e8f656f681af 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/Program.cs +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/Program.cs @@ -194,6 +194,8 @@ static int Main() int byteVectorLength = 16; #elif VECTORT256_INTRINSICS int byteVectorLength = 32; +#elif VECTORT512_INTRINSICS + int byteVectorLength = 64; #else #error Who dis? #endif diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512_VectorT512.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512_VectorT512.csproj new file mode 100644 index 00000000000000..94084aebc41e6b --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512_VectorT512.csproj @@ -0,0 +1,44 @@ + + + Exe + 0 + true + + true + + true + true + $(DefineConstants);AVX512_INTRINSICS;VECTORT512_INTRINSICS + true + false + + + + + + + + + /dev/null | grep -q __AVX512; then + echo No support for AVX512, test not applicable. + exit 0 + fi +]]> + + + + + + + + + diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index a0c6dc36b9e254..6c78e478e35b89 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -73,6 +73,7 @@ private static int Main() TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run(); TestCompilerGeneratedCode.Run(); Test105034Regression.Run(); + TestMethodsNeededFromNativeLayout.Run(); // @@ -93,6 +94,7 @@ private static int Main() TestBaseOnlyUsedFromCode.Run(); TestEntryPoint.Run(); TestGenericAttributesOnEnum.Run(); + TestLdtokenWithSignaturesDifferingInModifiers.Run(); return 100; } @@ -755,6 +757,82 @@ static void Wrap() } } + class TestMethodsNeededFromNativeLayout + { + class MyAttribute : Attribute; + + class GenericClass where T : class + { + [MethodImpl(MethodImplOptions.NoInlining)] + [My] + public static void GenericMethod([My] string namedParameter = "Hello") { } + + public GenericClass() => GenericMethod(null); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Type GetObjectType() => typeof(object); + + public static void Run() + { + // This tests that limited reflection metadata (that was only needed for native layout) + // works within the reflection stack. + Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(GetObjectType())); + + // This should succeed because of the Activator + Type testType = GetTestType(nameof(TestMethodsNeededFromNativeLayout), "GenericClass`1"); + + // This should succeed because native layout forces the metadata. + // If this ever starts breaking, replace this pattern with something else that forces limited method metadata. + MethodInfo mi = testType.GetMethod(nameof(GenericClass.GenericMethod)); + + // We got a MethodInfo that is limited, check the reflection APIs work fine with it + if (mi.Name != nameof(GenericClass.GenericMethod)) + throw new Exception("Name"); + + // Unless we're doing REFLECTION_FROM_USAGE, we don't expect to see attributes +#if !REFLECTION_FROM_USAGE + if (mi.GetCustomAttributes(inherit: true).Length != 0) + throw new Exception("Attributes"); +#endif + + // Unless we're doing REFLECTION_FROM_USAGE, we don't expect to be able to reflection-invoke + var mi2 = (MethodInfo)typeof(GenericClass).GetMemberWithSameMetadataDefinitionAs(mi); +#if !REFLECTION_FROM_USAGE + try +#endif + { + + mi2.MakeGenericMethod(typeof(string)).Invoke(null, [ null ]); +#if !REFLECTION_FROM_USAGE + throw new Exception("Invoke"); +#endif + } +#if !REFLECTION_FROM_USAGE + catch (NotSupportedException) + { + } +#endif + + // Parameter count should match no matter what + var parameters = mi.GetParameters(); + if (parameters.Length != 1) + throw new Exception("ParamCount"); + + // But parameter names, default values, attributes should only work in REFLECTION_FROM_USAGE +#if !REFLECTION_FROM_USAGE + if (parameters[0].Name != null) + throw new Exception("ParamName"); + + if (parameters[0].HasDefaultValue) + throw new Exception("DefaultValue"); + + if (parameters[0].GetCustomAttributes(inherit: true).Length != 0) + throw new Exception("Attributes"); +#endif + } + } + class TestCreateDelegate { internal class Greeter @@ -2781,6 +2859,26 @@ public static void Run() } } + unsafe class TestLdtokenWithSignaturesDifferingInModifiers + { + delegate string StdcallDelegate(delegate* unmanaged[Stdcall][] p); + delegate string CdeclDelegate(delegate* unmanaged[Cdecl][] p); + + static string Method(delegate* unmanaged[Stdcall][] p) => "Stdcall"; + static string Method(delegate* unmanaged[Cdecl][] p) => "Cdecl"; + + public static void Run() + { + Expression stdcall = x => Method(x); + if (stdcall.Compile()(null) != "Stdcall") + throw new Exception(); + + Expression cdecl = x => Method(x); + if (cdecl.Compile()(null) != "Cdecl") + throw new Exception(); + } + } + #region Helpers private static Type SecretGetType(string testName, string typeName) diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs index 0e302c54a5bc07..e42a781d37df4c 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs +++ b/src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs @@ -63,6 +63,7 @@ public static int Run() TestDefaultDynamicStaticGeneric.Run(); TestDynamicStaticGenericVirtualMethods.Run(); TestRuntime109496Regression.Run(); + TestRuntime113664Regression.Run(); return Pass; } @@ -1977,4 +1978,72 @@ public static void Run() throw new Exception(); } } + + class TestRuntime113664Regression + { + class Unit; + class Atom1; + class Atom2; + + class Gen; + + interface IFoo + { + static abstract string Frob(); + } + + class ImplementedDirectly : IFoo + { + static string IFoo.Frob() => $"ImplementedDirectly: {typeof(T).Name}-{typeof(U).Name}"; + } + + class Base + { + public static string Frob() => $"Base: {typeof(T).Name}<{typeof(T).GetGenericArguments()[0].Name}>-{typeof(U).Name}"; + } + + class ImplementedInBase : Base>, IFoo + { + } + + public static void Run() + { + if (Frob, Atom1, Unit>() != "ImplementedDirectly: Atom1-Unit") + throw new Exception(); + + if (Frob, Atom1, Unit>() != "Base: Gen`1-Unit") + throw new Exception(); + + [MethodImpl(MethodImplOptions.NoInlining)] + static Type GetAtom2() => typeof(Atom2); + + { + MethodInfo mi = typeof(TestRuntime113664Regression).GetMethod(nameof(FrobDirectWrapper)).MakeGenericMethod(GetAtom2(), typeof(Unit)); + if ((string)mi.Invoke(null, []) != "ImplementedDirectly: Atom2-Unit") + throw new Exception(); + } + + { + MethodInfo mi = typeof(TestRuntime113664Regression).GetMethod(nameof(FrobBaseWrapper)).MakeGenericMethod(GetAtom2(), typeof(Unit)); + if ((string)mi.Invoke(null, []) != "Base: Gen`1-Unit") + throw new Exception(); + } + } + + public static string FrobDirectWrapper() where T : class where U : class + { + return Frob, T, U>(); + } + + public static string FrobBaseWrapper() where T : class where U : class + { + return Frob, T, U>(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static string Frob() where T : class, IFoo where U : class where V : class + { + return T.Frob(); + } + } } diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId.cs b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId.cs deleted file mode 100644 index 722edc429d613b..00000000000000 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId.cs +++ /dev/null @@ -1,453 +0,0 @@ -// 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.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; -using System.Runtime.Intrinsics; -using System.Reflection; -using Xunit; - -namespace XarchHardwareIntrinsicTest._CpuId -{ - public class Program - { - const int Pass = 100; - const int Fail = 0; - - [Fact] - public unsafe static int TestEntryPoint() - { - int testResult = Pass; - - if (!X86Base.IsSupported) - { - return testResult; - } - - (int eax, int ebx, int ecx, int edx) = X86Base.CpuId(0x00000000, 0x00000000); - - bool isAuthenticAmd = (ebx == 0x68747541) && (ecx == 0x444D4163) && (edx == 0x69746E65); - bool isGenuineIntel = (ebx == 0x756E6547) && (ecx == 0x6C65746E) && (edx == 0x49656E69); - bool isVirtualCPU = (ebx == 0x74726956) && (ecx == 0x20555043) && (edx == 0x206C6175); - - if (!isAuthenticAmd && !isGenuineIntel && !isVirtualCPU) - { - // CPUID checks are vendor specific and aren't guaranteed to match up, even across Intel/AMD - // as such, we limit ourselves to just AuthenticAMD, GenuineIntel and "Virtual CPU" right now. Any other - // vendors would need to be validated against the checks below and added to the list as necessary. - - // An example of a difference is Intel/AMD for LZCNT. While the same underlying bit is used to - // represent presence of the LZCNT instruction, AMD began using this bit around 2007 for its - // ABM instruction set, which indicates LZCNT and POPCNT. Intel introduced a separate bit for - // POPCNT and didn't actually implement LZCNT and begin using the LZCNT bit until 2013. So - // while everything happens to line up today, it doesn't always and may not always do so. - - Console.WriteLine($"Unrecognized CPU vendor: EBX: {ebx:X8}, ECX: {ecx:X8}, EDX: {edx:X8}"); - testResult = Fail; - } - - uint maxFunctionId = (uint)eax; - - if (maxFunctionId < 0x00000001) - { - return testResult; - } - - bool isX86BaseDisabled = !GetDotnetEnable("HWINTRINSIC"); - bool isHierarchyDisabled = isX86BaseDisabled; - - (eax, ebx, ecx, edx) = X86Base.CpuId(0x00000001, 0x00000000); - - int xarchCpuInfo = eax; - - if (IsBitIncorrect(edx, 25, typeof(Sse), Sse.IsSupported, "SSE", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(edx, 26, typeof(Sse2), Sse2.IsSupported, "SSE2", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - bool isSse2HierarchyDisabled = isHierarchyDisabled; - - if (IsBitIncorrect(ecx, 25, typeof(Aes), Aes.IsSupported, "AES", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - isHierarchyDisabled = isSse2HierarchyDisabled; - - if (IsBitIncorrect(ecx, 1, typeof(Pclmulqdq), Pclmulqdq.IsSupported, "PCLMULQDQ", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - isHierarchyDisabled = isSse2HierarchyDisabled | !GetDotnetEnable("SSE3_4"); - - if (IsBitIncorrect(ecx, 0, typeof(Sse3), Sse3.IsSupported, "SSE3", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ecx, 9, typeof(Ssse3), Ssse3.IsSupported, "SSSE3", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ecx, 19, typeof(Sse41), Sse41.IsSupported, "SSE41", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ecx, 20, typeof(Sse42), Sse42.IsSupported, "SSE42", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - bool isSse42HierarchyDisabled = isHierarchyDisabled; - - if (IsBitIncorrect(ecx, 23, typeof(Popcnt), Popcnt.IsSupported, "POPCNT", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - isHierarchyDisabled = isSse42HierarchyDisabled; - - if (IsBitIncorrect(ecx, 28, typeof(Avx), Avx.IsSupported, "AVX", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - bool isAvxHierarchyDisabled = isHierarchyDisabled; - - if (IsBitIncorrect(ecx, 12, typeof(Fma), Fma.IsSupported, "FMA", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - bool isFmaHierarchyDisabled = isHierarchyDisabled; - - if (maxFunctionId < 0x00000007) - { - return testResult; - } - - (eax, ebx, ecx, edx) = X86Base.CpuId(0x00000007, 0x00000000); - - isHierarchyDisabled = isAvxHierarchyDisabled; - - if (IsBitIncorrect(ebx, 5, typeof(Avx2), Avx2.IsSupported, "AVX2", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - bool isAvx2HierarchyDisabled = isHierarchyDisabled; - - isHierarchyDisabled = isAvxHierarchyDisabled; - - if (IsBitIncorrect(ebx, 3, typeof(Bmi1), Bmi1.IsSupported, "BMI1", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - isHierarchyDisabled = isAvxHierarchyDisabled; - - if (IsBitIncorrect(ebx, 8, typeof(Bmi2), Bmi2.IsSupported, "BMI2", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - isHierarchyDisabled = isAvx2HierarchyDisabled | isFmaHierarchyDisabled | OperatingSystem.IsMacOS(); - - for (int i = 0; i < 2; i++) - { - // The runtime currently requires that all of F + BW + CD + DQ + VL be supported together or none - // are supported. To handle this we simple check them all twice so that if any of them are disabled - // the first time around, we'll then assert that they are all actually disabled the second time around - - if (IsBitIncorrect(ebx, 16, typeof(Avx512F), Avx512F.IsSupported, "AVX512F", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 31, typeof(Avx512F.VL), Avx512F.VL.IsSupported, "AVX512F_VL", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 30, typeof(Avx512BW), Avx512BW.IsSupported, "AVX512BW", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 30, typeof(Avx512BW.VL), Avx512BW.VL.IsSupported, "AVX512BW_VL", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 28, typeof(Avx512CD), Avx512CD.IsSupported, "AVX512CD", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 28, typeof(Avx512CD.VL), Avx512CD.VL.IsSupported, "AVX512CD_VL", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 17, typeof(Avx512DQ), Avx512DQ.IsSupported, "AVX512DQ", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ebx, 17, typeof(Avx512DQ.VL), Avx512DQ.VL.IsSupported, "AVX512DQ_VL", ref isHierarchyDisabled)) - { - testResult = Fail; - } - } - - bool isAvx512HierarchyDisabled = isHierarchyDisabled; - - int preferredVectorBitWidth = (GetDotnetEnvVar("PreferredVectorBitWidth", defaultValue: 0) / 128) * 128; - int preferredVectorByteLength = preferredVectorBitWidth / 8; - - if (preferredVectorByteLength == 0) - { - bool isVector512Throttling = false; - - if (isGenuineIntel) - { - int steppingId = xarchCpuInfo & 0b1111; - int model = (xarchCpuInfo >> 4) & 0b1111; - int familyID = (xarchCpuInfo >> 8) & 0b1111; - int extendedModelID = (xarchCpuInfo >> 16) & 0b1111; - - if (familyID == 0x06) - { - if (extendedModelID == 0x05) - { - if (model == 0x05) - { - // * Skylake (Server) - // * Cascade Lake - // * Cooper Lake - - isVector512Throttling = true; - } - } - else if (extendedModelID == 0x06) - { - if (model == 0x06) - { - // * Cannon Lake - - isVector512Throttling = true; - } - } - } - } - - if (isAvx512HierarchyDisabled || isVector512Throttling) - { - preferredVectorByteLength = 256 / 8; - } - else - { - preferredVectorByteLength = 512 / 8; - } - } - - if (IsBitIncorrect(ecx, 1, typeof(Avx512Vbmi), Avx512Vbmi.IsSupported, "AVX512VBMI", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsBitIncorrect(ecx, 1, typeof(Avx512Vbmi.VL), Avx512Vbmi.VL.IsSupported, "AVX512VBMI_VL", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - isHierarchyDisabled = isX86BaseDisabled; - - if (IsBitIncorrect(edx, 14, typeof(X86Serialize), X86Serialize.IsSupported, "SERIALIZE", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - (eax, ebx, ecx, edx) = X86Base.CpuId(0x00000007, 0x00000001); - - isHierarchyDisabled = isAvx2HierarchyDisabled; - -#pragma warning disable CA2252 // No need to opt into preview feature for an internal test - if (IsBitIncorrect(eax, 4, typeof(AvxVnni), AvxVnni.IsSupported, "AVXVNNI", ref isHierarchyDisabled)) - { - testResult = Fail; - } -#pragma warning restore CA2252 - - (eax, ebx, ecx, edx) = X86Base.CpuId(unchecked((int)0x80000000), 0x00000000); - - uint maxFunctionIdEx = (uint)eax; - - if (maxFunctionIdEx < 0x00000001) - { - return testResult; - } - - (eax, ebx, ecx, edx) = X86Base.CpuId(unchecked((int)0x80000001), 0x00000000); - - isHierarchyDisabled = isX86BaseDisabled; - - if (IsBitIncorrect(ecx, 5, typeof(Lzcnt), Lzcnt.IsSupported, "LZCNT", ref isHierarchyDisabled)) - { - testResult = Fail; - } - - if (IsIncorrect(typeof(Vector64), Vector64.IsHardwareAccelerated, isHierarchyDisabled: true)) - { - testResult = Fail; - } - - if (IsIncorrect(typeof(Vector128), Vector128.IsHardwareAccelerated, isSse2HierarchyDisabled)) - { - testResult = Fail; - } - - if (IsIncorrect(typeof(Vector256), Vector256.IsHardwareAccelerated, isAvx2HierarchyDisabled || (preferredVectorByteLength < 32))) - { - testResult = Fail; - } - - if (IsIncorrect(typeof(Vector512), Vector512.IsHardwareAccelerated, isAvx512HierarchyDisabled || (preferredVectorByteLength < 64))) - { - testResult = Fail; - } - - if (IsIncorrect(typeof(Vector), Vector.IsHardwareAccelerated, isSse2HierarchyDisabled)) - { - testResult = Fail; - } - - if (Vector.Count == 16) - { - if (!isAvx2HierarchyDisabled) - { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned 16 but the hardware returned 32"); - testResult = Fail; - } - } - else if (Vector.Count == 32) - { - if (isAvx2HierarchyDisabled) - { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned 32 but the hardware returned 16"); - testResult = Fail; - } - } - else - { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned {Vector.Count} which is unexpected"); - testResult = Fail; - } - - if (Vector.Count != (int)typeof(Vector).GetProperty("Count")!.GetValue(null)!) - { - Console.WriteLine($"{typeof(Vector).FullName}.Count returned a different result when called via reflection"); - testResult = Fail; - } - - return testResult; - } - - static bool IsBitIncorrect(int register, int bitNumber, Type isa, bool isSupported, string name, ref bool isHierarchyDisabled) - { - bool isSupportedByHardware = (register & (1 << bitNumber)) != 0; - isHierarchyDisabled |= (!isSupported || !GetDotnetEnable(name)); - - if (isSupported) - { - if (!isSupportedByHardware) - { - Console.WriteLine($"{isa.FullName}.IsSupported returned true but the hardware returned false"); - return true; - } - - if (isHierarchyDisabled) - { - Console.WriteLine($"{isa.FullName}.IsSupported returned true but the runtime returned false"); - return true; - } - } - else if (isSupportedByHardware) - { - if (!isHierarchyDisabled) - { - Console.WriteLine($"{isa.FullName}.IsSupported returned false but the hardware and runtime returned true"); - return true; - } - } - else - { - // The IsSupported query returned false and the hardware - // says its unsupported, so we're all good - } - - if (isSupported != (bool)isa.GetProperty("IsSupported")!.GetValue(null)!) - { - Console.WriteLine($"{isa.FullName}.IsSupported returned a different result when called via reflection"); - return true; - } - - return false; - } - - static bool IsIncorrect(Type isa, bool isHardwareAccelerated, bool isHierarchyDisabled) - { - if (isHardwareAccelerated) - { - if (isHierarchyDisabled) - { - Console.WriteLine($"{isa.FullName}.IsHardwareAccelerated returned true but the runtime returned false"); - return true; - } - } - else if (!isHierarchyDisabled) - { - Console.WriteLine($"{isa.FullName}.IsHardwareAccelerated returned false but the hardware and runtime returned true"); - return true; - } - - if (isHardwareAccelerated != (bool)isa.GetProperty("IsHardwareAccelerated")!.GetValue(null)!) - { - Console.WriteLine($"{isa.FullName}.IsHardwareAccelerated returned a different result when called via reflection"); - return true; - } - - return false; - } - - static bool GetDotnetEnable(string name) - { - // Hardware Intrinsic configuration knobs default to true - return GetDotnetEnvVar($"Enable{name}", defaultValue: 1) != 0; - } - - static int GetDotnetEnvVar(string name, int defaultValue) - { - string? stringValue = Environment.GetEnvironmentVariable($"DOTNET_{name}"); - - if ((stringValue is null) || !int.TryParse(stringValue, out int value)) - { - return defaultValue; - } - - return value; - } - } -} diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx.csproj b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx.csproj index 1bc209963a25b1..0357e6e60be285 100644 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx.csproj +++ b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx.csproj @@ -17,6 +17,6 @@ - + diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx2.csproj b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx2.csproj index 67381af11a88a2..e3ec99a8ff24a3 100644 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx2.csproj +++ b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx2.csproj @@ -17,6 +17,6 @@ - + diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx512.csproj b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx512.csproj index a28a93f0f16d61..f0d2f45a2e120f 100644 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx512.csproj +++ b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx512.csproj @@ -17,6 +17,6 @@ - + diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx_NoAvx2.csproj b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx_NoAvx2.csproj index 6c6f2278d69527..893f58cc177167 100644 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx_NoAvx2.csproj +++ b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Avx_NoAvx2.csproj @@ -17,6 +17,6 @@ - + diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Baseline.csproj b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Baseline.csproj index 419c5e21f2e62f..df43d1cbeb8286 100644 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Baseline.csproj +++ b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Baseline.csproj @@ -13,6 +13,6 @@ - + diff --git a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Sse42.csproj b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Sse42.csproj index fca78ef4941a72..43fa033f3708f8 100644 --- a/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Sse42.csproj +++ b/src/tests/readytorun/HardwareIntrinsics/X86/CpuId_R2R_Sse42.csproj @@ -17,6 +17,6 @@ - + diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs index cf2c018b098752..2d6bc8afc221e5 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs @@ -58,7 +58,7 @@ class GenericMethodNoReference [Kept] static void GenericMethod () { } - [Kept] + [Kept (By = Tool.Trimmer)] class TargetTypeForNothing { public int PublicField; @@ -89,7 +89,7 @@ class GenericMethodCallReference [Kept] static void GenericMethod (T value) where T : IUse { value.Use (); } - [Kept] + [Kept (By = Tool.Trimmer)] [KeptInterfaceAttribute (typeof (IUse), By = Tool.Trimmer)] class TargetTypeForNothing : IUse { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs index 790db571d13705..7ccf4928e9a378 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs @@ -107,11 +107,11 @@ static Nested () class Complex { - [Kept] + [Kept (By = Tool.Trimmer)] public struct S { } - [Kept] + [Kept (By = Tool.Trimmer)] public class A { } - [Kept] + [Kept (By = Tool.Trimmer)] public class G { } [Kept]