diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-11-09 03:20:39 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-09 03:20:39 +0300 |
commit | 162cead08753e6440d7e90ec4fb453a1a651785a (patch) | |
tree | dbb0478e51bd5b376386e6d0a38df7037fe51526 | |
parent | 2bc2edc1e2b1b0e835366668b53ccfc48ece0949 (diff) | |
parent | 0566d28cd25fb5a8b708b94dd9ba7960a75e3b07 (diff) |
Merge pull request #4894 from dotnet/master
Merge master to nmirror
50 files changed, 7647 insertions, 660 deletions
diff --git a/Documentation/cross-building.md b/Documentation/cross-building.md index afc0f07c9..247f933ac 100644 --- a/Documentation/cross-building.md +++ b/Documentation/cross-building.md @@ -1,7 +1,7 @@ Cross Compilation for ARM on Linux ================================== -Through cross compilation, on Linux it is possible to build CoreCLR for arm or arm64. +Through cross compilation, on Linux it is possible to build CoreRT for arm or arm64. Requirements ------------ @@ -21,7 +21,7 @@ and conversely for arm64: Generating the rootfs --------------------- -The `cross\build-rootfs.sh` script can be used to download the files needed for cross compilation. It will generate an Ubuntu 14.04 rootfs as this is what CoreCLR targets. +The `cross\build-rootfs.sh` script can be used to download the files needed for cross compilation. It will generate an Ubuntu 14.04 rootfs as this is what CoreRT targets. Usage: build-rootfs.sh [BuildArch] BuildArch can be: arm, arm64 @@ -38,7 +38,7 @@ and if you wanted to generate the rootfs elsewhere: Cross compiling CoreCLR ----------------------- -Once the rootfs has been generated, it will be possible to cross compile CoreCLR. If `ROOTFS_DIR` was set when generating the rootfs, then it must also be set when running `build.sh`. +Once the rootfs has been generated, it will be possible to cross compile CoreRT. If `ROOTFS_DIR` was set when generating the rootfs, then it must also be set when running `build.sh`. So, without `ROOTFS_DIR`: @@ -49,3 +49,66 @@ And with: $ ROOTFS_DIR=~/coreclr-cross/arm ./build.sh arm debug verbose clean cross As usual the resulting binaries will be found in `bin/Product/BuildOS.BuildArch.BuildType/` + +Using CoreRT for cross compiling under arm on x86 host +----------------------- +It is possible to use CoreRT for compiling under arm/armel on x86 host (or on x64 machine using roots). + +1. Build CoreCLR for x86 (`checked` version) +``` +sudo ./cross/build-rootfs.sh x86 xenial +./build.sh clang3.9 x86 checked verbose cross skiptests +``` + +2. Build CoreFX (`Debug` version) +3. Build CoreRT for armel, x64, x86 +``` +sudo ./cross/build-rootfs.sh armel tizen +sudo ./cross/build-rootfs.sh x86 xenial +./build.sh clang3.9 armel debug verbose cross +./build.sh debug verbose skiptests +./build.sh clang3.9 x86 debug verbose cross skiptests +``` + +4. Copy necessary binaries to working directory (in x86 rootfs) +``` +cp ${CORECLR}/bin/Product/Linux.x86.Checked ${WORKING_DIR} +cp ${CORERT}/bin/Linux.x86.Debug/tools/ilc.dll ${WORKING_DIR} +cp ${CORERT}/bin/Linux.x86.Debug/tools/ILCompiler.* ${WORKING_DIR} +cp ${CORERT}/bin/Linux.x86.Debug/tools/System.CommandLine.dll ${WORKING_DIR} +cp ${CORERT}/bin/Linux.x86.Debug/tools/Microsoft.DiaSymReader.dll ${WORKING_DIR} +cp ${CORERT}/bin/Linux.x86.Debug/tools/jitinterface.so ${WORKING_DIR} +cp -r ${CORERT}/bin/Linux.x86.Debug/framework ${WORKING_DIR} + +# Copy CoreRT sdk binaries from target (armel) output folder +cp -r ${CORERT}/bin/Linux.armel.Debug/sdk ${WORKING_DIR} +``` + +5. Rename RyuJIT compiler library +``` +# Use cross-compiler library as default for ILC +cp ${WORKING_DIR}/libarmelnonjit.so ${WORKING_DIR}/libclrjitilc.so + +# ... or ARM version instead if it's needed +# cp ${WORKING_DIR}/libprotojit.so ${WORKING_DIR}/libclrjitilc.so +``` + +6. Build libobjwriter. You have to compile it on x86 chroot. Before compiling put coreclr/bin/Product/Linux.x86.Debug/ to some folder on x86 chroot as well. Versions which to used are mentioned on GitHub: +https://github.com/dotnet/corert/issues/3776#issuecomment-337682166 + + And apply patch: +https://gist.github.com/alpencolt/ec75fcc05d8c4ffbf143a052f7c115a8 +``` +mkdir build +cd build +cmake ../ -DWITH_CORECLR=../../coreclr/bin/Product/Linux.x86.Debug/ -DLLVM_TARGET_ARCH="ARM;X86" -DLLVM_TARGETS_TO_BUILD="ARM;X86" -DLLVM_DEFAULT_TARGET_TRIPLE=thumbv7-linux-gnueabi -DCMAKE_BUILD_TYPE=Release -DLLVM_BUILD_LLVM_DYLIB=1 -DLLVM_LINK_LLVM_DYLIB=1 -DLLVM_OPTIMIZED_TABLEGEN=1 -DHAVE_POSIX_SPAWN=0 -DLLVM_ENABLE_PIC=1 -DLLVM_BUILD_TESTS=0 -DLLVM_ENABLE_DOXYGEN=0 -DLLVM_INCLUDE_DOCS=0 -DLLVM_INCLUDE_TESTS=0 -DLLVM_BINUTILS_INCDIR=/usr/include +make -j8 objwriter +``` + +7. And to execute use: +``` +./corerun ilc.dll --verbose @Hello.ilc.rsp + +# For linking +clang-3.9 -target arm-linux-gnueabi --sysroot=corert/cross/rootfs/armel -Bcorert/cross/rootfs/armel/usr/lib/gcc/armv7l-tizen-linux-gnueabi/6.2.1 -Lcorert/cross/rootfs/armel/usr/lib/gcc/armv7l-tizen-linux-gnueabi/6.2.1 Hello.o -o Hello corert/bin/Linux.armel.Debug/sdk/libbootstrapper.a corert/bin/Linux.armel.Debug/sdk/libRuntime.a corert/bin/Linux.armel.Debug/sdk/libSystem.Private.CoreLib.Native.a corert/bin/Linux.armel.Debug/framework/System.Native.a corert/bin/Linux.armel.Debug/framework/libSystem.Globalization.Native.a -g -Wl,-rpath,'$ORIGIN' -pthread -lstdc++ -ldl -lm -luuid -lrt -fPIC +``` diff --git a/Documentation/how-to-build-ObjectWriter.md b/Documentation/how-to-build-ObjectWriter.md new file mode 100644 index 000000000..a848a02ce --- /dev/null +++ b/Documentation/how-to-build-ObjectWriter.md @@ -0,0 +1,40 @@ +# Build ObjectWriter library # + +ObjWriter is based on LLVM, so it requires recent CMake and GCC/Clang to build LLVM. +See http://llvm.org/docs/GettingStarted.html#requirements for more details. + +1. Clone LLVM from official LLVM mirror github git repository: + + ``` + $ git clone -b release_50 https://github.com/llvm-mirror/llvm.git + ``` + +2. Copy ObjWriter directory from CoreRT into LLVM tree + + ``` + $ cp -r CoreRT/src/Native/ObjWriter llvm/tools/ + ``` + +3. Apply the patch to LLVM: + + ``` + $ cd llvm + $ git apply tools/ObjWriter/llvm.patch + ``` + +4. Configure and build LLVM with ObjWriter: + + ``` + $ mkdir build + $ cd build + $ cmake ../ -DCMAKE_BUILD_TYPE=Release -DLLVM_OPTIMIZED_TABLEGEN=1 -DHAVE_POSIX_SPAWN=0 -DLLVM_ENABLE_PIC=1 -DLLVM_BUILD_TESTS=0 -DLLVM_ENABLE_DOXYGEN=0 -DLLVM_INCLUDE_DOCS=0 -DLLVM_INCLUDE_TESTS=0 + $ make -j10 objwriter + $ cd .. + ``` + +* You can change the building type(CMAKE_BUILD_TYPE) to the debugging type(Debug), if necessary to debug ObjWriter. +* Also, you can do this under chroot to building ObjWriter for other platforms. + +5. Get ObjWriter: + + If all goes well, the build will complete in the previous step and you will get ObjWriter library as llvm/build/lib/libobjwriter.so diff --git a/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md b/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md index baf53f154..48b1f3b47 100644 --- a/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md +++ b/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md @@ -51,8 +51,6 @@ You should now be able to use the `dotnet` commands of the CLI tools. * Please [open an issue](https://github.com/dotnet/corert/issues) if these instructions do not work anymore. - * Projects with references to other projects or packages require workaround described in https://github.com/dotnet/corert/issues/2619#issuecomment-276095878 - ## Using RyuJIT ## This approach uses the same code-generator (RyuJIT), as [CoreCLR](https://github.com/dotnet/coreclr), for compiling the application. Linking is done using the platform specific linker. @@ -60,10 +58,10 @@ This approach uses the same code-generator (RyuJIT), as [CoreCLR](https://github From the shell/command prompt, issue the following commands, from the folder containing your project, to generate the native executable ``` - dotnet build /t:LinkNative + dotnet publish -r win-x64|linux-x64|osx-x64 ``` -Native executable will be dropped in `./bin/[configuration]/native/` folder and will have the same name as the folder in which your source file is present. +Native executable will be dropped in `./bin/x64/[configuration]/netcoreapp2.0/publish/` folder and will have the same name as the folder in which your source file is present. ## Using CPP Code Generator ## @@ -72,11 +70,15 @@ This approach uses [transpiler](https://en.wikipedia.org/wiki/Source-to-source_c From the shell/command prompt, issue the following commands to generate the native executable: ``` - dotnet build /t:LinkNative /p:NativeCodeGen=cpp + dotnet publish /p:NativeCodeGen=cpp -r win-x64|linux-x64|osx-x64 ``` For CoreRT debug build on Windows, add an extra `/p:AdditionalCppCompilerFlags=/MTd` argument. +## Disabling Native Compilation + +Native compilation can be disabled during publishing by adding an extra `/p:NativeCompilationDuringPublish=false` argument. + ## Workarounds for build errors on Windows ## If you are seeing errors such as: diff --git a/src/BuildIntegration/BuildFrameworkNativeObjects.proj b/src/BuildIntegration/BuildFrameworkNativeObjects.proj index 3a1f2db03..806b087f4 100644 --- a/src/BuildIntegration/BuildFrameworkNativeObjects.proj +++ b/src/BuildIntegration/BuildFrameworkNativeObjects.proj @@ -1,7 +1,7 @@ <Project DefaultTargets="CreateLib" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> - <IlcCompileDependsOn>BuildOneFrameworkLibrary</IlcCompileDependsOn> + <IlcCompileDependsOn>ComputeIlcCompileInputs;BuildOneFrameworkLibrary</IlcCompileDependsOn> <CreateLibDependsOn>BuildAllFrameworkLibrariesAsSingleLib</CreateLibDependsOn> <IlcMultiModule>true</IlcMultiModule> <NativeIntermediateOutputPath Condition="'$(FrameworkObjPath)' != ''">$(FrameworkObjPath)\</NativeIntermediateOutputPath> @@ -11,12 +11,12 @@ <Import Project="Microsoft.NETCore.Native.targets" /> <Target Name="BuildAllFrameworkLibraries" - Inputs="@(IlcReference)" - Outputs="@(IlcReference->'$(NativeIntermediateOutputPath)\%(Filename)$(NativeObjectExt)')"> + Inputs="@(DefaultFrameworkAssemblies)" + Outputs="@(DefaultFrameworkAssemblies->'$(NativeIntermediateOutputPath)\%(Filename)$(NativeObjectExt)')"> <ItemGroup> <ProjectToBuild Include="$(MSBuildProjectFullPath)"> <AdditionalProperties> - LibraryToCompile=%(IlcReference.Identity) + LibraryToCompile=%(DefaultFrameworkAssemblies.Identity) </AdditionalProperties> </ProjectToBuild> </ItemGroup> diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets new file mode 100644 index 000000000..755aa647f --- /dev/null +++ b/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets @@ -0,0 +1,61 @@ +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + + <PropertyGroup> + <BuildTasksPath Condition="'$(BuildTasksPath)' == ''">$(MSBuildThisFileDirectory)..\tools\ILCompiler.Build.Tasks.dll</BuildTasksPath> + + <!-- + Prevent dotnet CLI from deploying the CoreCLR shim executable since we produce + a native executable. + --> + <DeployAppHost>false</DeployAppHost> + </PropertyGroup> + + <Target Name="_ComputeIlcCompileInputs" + BeforeTargets="ComputeIlcCompileInputs"> + <ItemGroup> + <IlcReference Include="@(_ManagedResolvedAssembliesToPublish)" /> + </ItemGroup> + </Target> + + <!-- + This target hooks into the dotnet CLI publish pipeline. That pipeline has + a target called ComputeFilesToPublish which produces the ItemGroup + ResolvedFileToPublish based on the inputs of @(IntermediateAssembly) + and @(ResolvedAssembliesToPublish). We modify those two item groups + to control what gets published after CoreRT optimizes the application. + --> + <Target Name="ComputeLinkedFilesToPublish" + BeforeTargets="ComputeFilesToPublish" + DependsOnTargets="_ComputeAssembliesToCompileToNative;LinkNative"> + + <ItemGroup> + <ResolvedAssembliesToPublish Remove="@(_AssembliesToSkipPublish)" /> + <ResolvedAssembliesToPublish Include="@(_LinkedResolvedAssemblies)" /> + </ItemGroup> + + <ItemGroup> + <_NativeIntermediateAssembly Include="@(IntermediateAssembly->'$(NativeOutputPath)%(Filename)$(NativeBinaryExt)')" /> + <IntermediateAssembly Remove="@(IntermediateAssembly)" /> + <IntermediateAssembly Include="@(_NativeIntermediateAssembly)" /> + </ItemGroup> + </Target> + + <!-- + Filter the input publish file list selecting managed assemblies for compilation. + Also produces _AssembliesToSkipPublish which chops out things from the publish + pipeline we don't want to see in the output (native images, CoreCLR artifacts) + until we get a proper AOT NetCore app package. + --> + <UsingTask TaskName="ComputeManagedAssemblies" AssemblyFile="$(BuildTasksPath)" /> + <Target Name="_ComputeAssembliesToCompileToNative"> + + <ComputeManagedAssemblies Assemblies="@(ResolvedAssembliesToPublish)" + DotNetAppHostExecutableName="$(_DotNetAppHostExecutableName)" DotNetHostFxrLibraryName="$(_DotNetHostFxrLibraryName)" DotNetHostPolicyLibraryName="$(_DotNetHostPolicyLibraryName)" + SdkAssemblies="@(PrivateSdkAssemblies)" FrameworkAssemblies="@(FrameworkAssemblies)"> + <Output TaskParameter="ManagedAssemblies" ItemName="_ManagedResolvedAssembliesToPublish" /> + <Output TaskParameter="AssembliesToSkipPublish" ItemName="_AssembliesToSkipPublish" /> + </ComputeManagedAssemblies> + + </Target> + +</Project> diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.targets b/src/BuildIntegration/Microsoft.NETCore.Native.targets index 6e522fe48..22dd34fb0 100644 --- a/src/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/BuildIntegration/Microsoft.NETCore.Native.targets @@ -19,6 +19,7 @@ See the LICENSE file in the project root for more information. <PropertyGroup> <NativeIntermediateOutputPath Condition="'$(NativeIntermediateOutputPath)' == ''">$(IntermediateOutputPath)native\</NativeIntermediateOutputPath> <NativeOutputPath Condition="'$(NativeOutputPath)' == ''">$(OutputPath)native\</NativeOutputPath> + <NativeCompilationDuringPublish Condition="'$(NativeCompilationDuringPublish)' == ''">true</NativeCompilationDuringPublish> <!-- Workaround for lack of current host OS detection - https://github.com/Microsoft/msbuild/issues/539 --> <TargetOS Condition="'$(TargetOS)' == '' and '$(OS)' == 'Unix' and Exists('/Applications')">OSX</TargetOS> <TargetOS Condition="'$(TargetOS)' == ''">$(OS)</TargetOS> @@ -60,20 +61,23 @@ See the LICENSE file in the project root for more information. <SharedLibrary Condition="'$(OS)' != 'Windows_NT'">$(FrameworkLibPath)\libframework$(LibFileExt)</SharedLibrary> </PropertyGroup> - <ItemGroup Condition="$(BuildingFrameworkLibrary) != 'true'"> - <ManagedBinary Include="$(IntermediateOutputPath)$(TargetName)$(TargetExt)" /> - </ItemGroup> + <PropertyGroup Condition="'$(IlcCompileDependsOn)'=='' and '$(NativeCompilationDuringPublish)' != 'false'"> + <IlcCompileDependsOn Condition="'$(BuildingFrameworkLibrary)' != 'true'">Compile;ComputeIlcCompileInputs</IlcCompileDependsOn> + <IlcCompileDependsOn Condition="'$(IlcMultiModule)' == 'true' and '$(BuildingFrameworkLibrary)' != 'true'">$(IlcCompileDependsOn);BuildFrameworkLib</IlcCompileDependsOn> + </PropertyGroup> <ItemGroup> - <IlcCompileInput Include="@(ManagedBinary)" /> - <IlcReference Include="$(IlcPath)\sdk\*.dll" /> - <IlcReference Include="$(IlcPath)\framework\*.dll" /> + <DefaultFrameworkAssemblies Include="$(IlcPath)\sdk\*.dll" /> + <DefaultFrameworkAssemblies Include="$(IlcPath)\framework\*.dll" /> </ItemGroup> - <PropertyGroup Condition="'$(IlcCompileDependsOn)'==''"> - <IlcCompileDependsOn Condition="'$(BuildingFrameworkLibrary)' != 'true'">Compile</IlcCompileDependsOn> - <IlcCompileDependsOn Condition="'$(IlcMultiModule)' == 'true' and '$(BuildingFrameworkLibrary)' != 'true'">$(IlcCompileDependsOn);BuildFrameworkLib</IlcCompileDependsOn> - </PropertyGroup> + <Target Name="ComputeIlcCompileInputs"> + <ItemGroup> + <ManagedBinary Condition="$(BuildingFrameworkLibrary) != 'true'" Include="$(IntermediateOutputPath)$(TargetName)$(TargetExt)" /> + <IlcCompileInput Include="@(ManagedBinary)" /> + <IlcReference Include="@(DefaultFrameworkAssemblies)" /> + </ItemGroup> + </Target> <!-- BuildFrameworkLib is invoked before IlcCompile in multi-module builds to @@ -107,6 +111,7 @@ See the LICENSE file in the project root for more information. <IlcArg Condition="$(Optimize) == 'true'" Include="-O" /> <IlcArg Condition="$(DebugSymbols) == 'true'" Include="-g" /> <IlcArg Condition="$(IlcGenerateMapFile) == 'true'" Include="--map:$(NativeIntermediateOutputPath)%(ManagedBinary.Filename).map.xml" /> + <IlcArg Condition="$(RdXmlFile) != ''" Include="--rdxml:$(RdXmlFile)" /> </ItemGroup> <MakeDir Directories="$(NativeIntermediateOutputPath)" /> @@ -178,4 +183,7 @@ See the LICENSE file in the project root for more information. <Exec Command="$(CppLibCreator) @"$(NativeIntermediateOutputPath)lib.rsp"" Condition="'$(OS)' == 'Windows_NT'" /> <Exec Command="$(CppLibCreator) @(CustomLibArg, ' ')" Condition="'$(OS)' != 'Windows_NT'" /> </Target> + + <Import Project="$(MSBuildThisFileDirectory)\Microsoft.NETCore.Native.Publish.targets" Condition="'$(NativeCompilationDuringPublish)' != 'false'" /> + </Project> diff --git a/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs index 08458b899..00954908a 100644 --- a/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -96,15 +96,6 @@ namespace Internal.TypeSystem.Interop if (forceLazyResolution.HasValue) return forceLazyResolution.Value; - // In multi-module library mode, the WinRT p/invokes in System.Private.Interop cause linker failures - // since we don't link against the OS libraries containing those APIs. Force them to be lazy. - // See https://github.com/dotnet/corert/issues/2601 - string assemblySimpleName = ((IAssemblyDesc)((MetadataType)method.OwningType).Module).GetName().Name; - if (assemblySimpleName == "System.Private.Interop") - { - return true; - } - // Determine whether this call should be made through a lazy resolution or a static reference // Eventually, this should be controlled by a custom attribute (or an extension to the metadata format). if (importModule == "[MRT]" || importModule == "*") diff --git a/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs b/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs new file mode 100644 index 000000000..0e4998ece --- /dev/null +++ b/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs @@ -0,0 +1,168 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; + + + +namespace Build.Tasks +{ + public class ComputeManagedAssemblies : Task + { + [Required] + public ITaskItem[] Assemblies + { + get; + set; + } + + /// <summary> + /// The CoreRT-specific System.Private.* assemblies that must be used instead of the netcoreapp2.0 versions. + /// </summary> + [Required] + public ITaskItem[] SdkAssemblies + { + get; + set; + } + + /// <summary> + /// The set of AOT-specific framework assemblies we currently need to use which will replace the same-named ones + /// in the app's closure. + /// </summary> + [Required] + public ITaskItem[] FrameworkAssemblies + { + get; + set; + } + + /// <summary> + /// The native apphost (whose name ends up colliding with the CoreRT output binary) + /// </summary> + [Required] + public string DotNetAppHostExecutableName + { + get; + set; + } + + /// <summary> + /// The CoreCLR dotnet host fixer library that can be skipped during publish + /// </summary> + [Required] + public string DotNetHostFxrLibraryName + { + get; + set; + } + + /// <summary> + /// The CoreCLR dotnet host policy library that can be skipped during publish + /// </summary> + [Required] + public string DotNetHostPolicyLibraryName + { + get; + set; + } + + [Output] + public ITaskItem[] ManagedAssemblies + { + get; + set; + } + + [Output] + public ITaskItem[] AssembliesToSkipPublish + { + get; + set; + } + + public override bool Execute() + { + var list = new List<ITaskItem>(); + var assembliesToSkipPublish = new List<ITaskItem>(); + + var coreRTFrameworkAssembliesToUse = new HashSet<string>(); + + foreach (ITaskItem taskItem in SdkAssemblies) + { + coreRTFrameworkAssembliesToUse.Add(Path.GetFileName(taskItem.ItemSpec)); + } + + foreach (ITaskItem taskItem in FrameworkAssemblies) + { + coreRTFrameworkAssembliesToUse.Add(Path.GetFileName(taskItem.ItemSpec)); + } + + foreach (ITaskItem taskItem in Assemblies) + { + // In the case of disk-based assemblies, this holds the file path + string itemSpec = taskItem.ItemSpec; + + // Skip the native apphost (whose name ends up colliding with the CoreRT output binary) and supporting libraries + if (itemSpec.EndsWith(DotNetAppHostExecutableName, StringComparison.OrdinalIgnoreCase) || itemSpec.Contains(DotNetHostFxrLibraryName) || itemSpec.Contains(DotNetHostPolicyLibraryName)) + { + assembliesToSkipPublish.Add(taskItem); + continue; + } + + // Prototype aid - remove the native CoreCLR runtime pieces from the publish folder + if (itemSpec.Contains("microsoft.netcore.app") && (itemSpec.Contains("\\native\\") || itemSpec.Contains("/native/"))) + { + assembliesToSkipPublish.Add(taskItem); + continue; + } + + // Remove any assemblies whose implementation we want to come from CoreRT's package. + // Currently that's System.Private.* SDK assemblies and a bunch of framework assemblies. + if (coreRTFrameworkAssembliesToUse.Contains(Path.GetFileName(itemSpec))) + { + assembliesToSkipPublish.Add(taskItem); + continue; + } + + try + { + using (FileStream moduleStream = File.OpenRead(itemSpec)) + using (var module = new PEReader(moduleStream)) + { + if (module.HasMetadata) + { + MetadataReader moduleMetadataReader = module.GetMetadataReader(); + if (moduleMetadataReader.IsAssembly) + { + string culture = moduleMetadataReader.GetString(moduleMetadataReader.GetAssemblyDefinition().Culture); + + if (culture == "" || culture.Equals("neutral", StringComparison.OrdinalIgnoreCase)) + { + // CoreRT doesn't consume resource assemblies yet so skip them + assembliesToSkipPublish.Add(taskItem); + list.Add(taskItem); + } + } + } + } + } + catch (BadImageFormatException) + { + } + } + + ManagedAssemblies = list.ToArray(); + AssembliesToSkipPublish = assembliesToSkipPublish.ToArray(); + + return true; + } + } +} diff --git a/src/ILCompiler.Build.Tasks/src/ILCompiler.Build.Tasks.csproj b/src/ILCompiler.Build.Tasks/src/ILCompiler.Build.Tasks.csproj new file mode 100644 index 000000000..808a4de4c --- /dev/null +++ b/src/ILCompiler.Build.Tasks/src/ILCompiler.Build.Tasks.csproj @@ -0,0 +1,25 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" Condition="'$(IsProjectNLibrary)' != 'true'" /> + <PropertyGroup> + <OutputType>Library</OutputType> + <RootNamespace>ILCompiler</RootNamespace> + <AssemblyName>ILCompiler.Build.Tasks</AssemblyName> + <TargetFramework>netstandard1.3</TargetFramework> + <OutputPath>$(BaseOutputPath)$(OSPlatformConfig)/tools</OutputPath> + </PropertyGroup> + <ItemGroup> + <Compile Include="ComputeManagedAssemblies.cs" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Microsoft.Build.Framework"> + <Version>15.3.409</Version> + </PackageReference> + <PackageReference Include="Microsoft.Build.Utilities.Core"> + <Version>15.3.409</Version> + </PackageReference> + <PackageReference Include="System.Reflection.Metadata"> + <Version>1.4.2</Version> + </PackageReference> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" Condition="'$(IsProjectNLibrary)' != 'true'" /> +</Project> diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs b/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs index 98f862c54..2821420a9 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs @@ -9,6 +9,7 @@ using ILCompiler.Compiler.CppCodeGen; using Internal.TypeSystem; using LLVMSharp; using ILCompiler.CodeGen; +using System.Collections.Generic; namespace Internal.IL { @@ -86,7 +87,7 @@ namespace Internal.IL /// <param name="pos">Position where to insert <paramref name="v"/></param> public void InsertAt(T v, int pos) { - Debug.Assert(pos < _top, "Invalid insertion point"); + Debug.Assert(pos <= _top, "Invalid insertion point"); if (_top >= _stack.Length) { @@ -181,18 +182,51 @@ namespace Internal.IL /// </summary> public TypeDesc Type { get; } - public LLVMValueRef LLVMValue { get; set; } + public LLVMValueRef ValueAsType(LLVMTypeRef type, LLVMBuilderRef builder) + { + return ValueAsTypeInternal(type, builder, false); + } + + public LLVMValueRef ValueAsType(TypeDesc type, LLVMBuilderRef builder) + { + return ValueAsType(ILImporter.GetLLVMTypeForTypeDesc(type), builder); + } + + public LLVMValueRef ValueForStackKind(StackValueKind kind, LLVMBuilderRef builder, bool signExtend) + { + if (kind == StackValueKind.Int32) + return ValueAsInt32(builder, signExtend); + else if (kind == StackValueKind.Int64) + return ValueAsInt64(builder, signExtend); + else if (kind == StackValueKind.Float) + return ValueAsType(LLVM.FloatType(), builder); + else if (kind == StackValueKind.NativeInt || kind == StackValueKind.ByRef || kind == StackValueKind.ObjRef) + return ValueAsInt32(builder, false); + else + throw new NotImplementedException(); + } + + public LLVMValueRef ValueAsInt32(LLVMBuilderRef builder, bool signExtend) + { + return ValueAsTypeInternal(LLVM.Int32Type(), builder, signExtend); + } + + public LLVMValueRef ValueAsInt64(LLVMBuilderRef builder, bool signExtend) + { + return ValueAsTypeInternal(LLVM.Int32Type(), builder, signExtend); + } + + protected abstract LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend); /// <summary> /// Initializes a new instance of StackEntry. /// </summary> /// <param name="kind">Kind of entry.</param> /// <param name="type">Type if any of entry.</param> - protected StackEntry(StackValueKind kind, LLVMValueRef llvmValue, TypeDesc type = null) + protected StackEntry(StackValueKind kind, TypeDesc type = null) { Kind = kind; Type = type; - LLVMValue = llvmValue; } /// <summary> @@ -206,45 +240,6 @@ namespace Internal.IL /// </summary> /// <returns>A new instance of the same type as the current entry.</returns> public abstract StackEntry Duplicate(); - - /// <summary> - /// Overridden and sealed to force descendants to override <see cref="BuildRepresentation"/>. - /// </summary> - /// <returns>String representation of current entry</returns> - public override sealed string ToString() - { - StringBuilder s = new StringBuilder(); - BuildRepresentation(s); - return s.ToString(); - } - - /// <summary> - /// Build a representation of current entry in <paramref name="s"/>. - /// </summary> - /// <param name="s">StringBuilder where representation will be saved.</param> - protected virtual void BuildRepresentation(StringBuilder s) - { - Debug.Assert(s != null, "StringBuilder is null."); - if (Type != null) - { - s.Append(Type); - if (Kind != StackValueKind.Unknown) - { - s.Append('('); - s.Append(Kind); - s.Append(')'); - } - } - else if (Kind != StackValueKind.Unknown) - { - if (Kind != StackValueKind.Unknown) - { - s.Append('('); - s.Append(Kind); - s.Append(')'); - } - } - } } /// <summary> @@ -252,7 +247,7 @@ namespace Internal.IL /// </summary> internal abstract class ConstantEntry : StackEntry { - protected ConstantEntry(StackValueKind kind, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, llvmValue, type) + protected ConstantEntry(StackValueKind kind, TypeDesc type = null) : base(kind, type) { } @@ -271,26 +266,36 @@ namespace Internal.IL { public T Value { get; } - protected ConstantEntry(StackValueKind kind, T value, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, llvmValue, type) + protected ConstantEntry(StackValueKind kind, T value, TypeDesc type = null) : base(kind, type) { Value = value; } - - protected override void BuildRepresentation(StringBuilder s) - { - base.BuildRepresentation(s); - if (s.Length > 0) - { - s.Append(' '); - } - s.Append(Value); - } } internal class Int32ConstantEntry : ConstantEntry<int> { - public Int32ConstantEntry(int value, TypeDesc type = null) : base(StackValueKind.Int32, value, LLVM.ConstInt(LLVM.Int32Type(), (ulong)value, LLVMMisc.False), type) + public Int32ConstantEntry(int value, TypeDesc type = null) : base(StackValueKind.Int32, value, type) + { + } + + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) { + if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value == 0) + { + return LLVM.ConstPointerNull(type); + } + else if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value != 0) + { + return LLVM.ConstIntToPtr(LLVM.ConstInt(LLVM.Int32Type(), (ulong)Value, LLVMMisc.False), type); + } + else if (type.TypeKind != LLVMTypeKind.LLVMIntegerTypeKind) + { + throw new NotImplementedException(); + } + else + { + return LLVM.ConstInt(type, (ulong)Value, LLVMMisc.False); + } } public override StackEntry Duplicate() @@ -324,7 +329,7 @@ namespace Internal.IL internal class Int64ConstantEntry : ConstantEntry<long> { - public Int64ConstantEntry(long value, TypeDesc type = null) : base(StackValueKind.Int64, value, LLVM.ConstInt(LLVM.Int64Type(), (ulong)value, LLVMMisc.False), type) + public Int64ConstantEntry(long value, TypeDesc type = null) : base(StackValueKind.Int64, value, type) { } @@ -333,6 +338,26 @@ namespace Internal.IL return new Int64ConstantEntry(Value, Type); } + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) + { + if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value == 0) + { + return LLVM.ConstPointerNull(type); + } + else if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value != 0) + { + return LLVM.ConstIntToPtr(LLVM.ConstInt(LLVM.Int64Type(), (ulong)Value, LLVMMisc.False), type); + } + else if (type.TypeKind != LLVMTypeKind.LLVMIntegerTypeKind) + { + throw new NotImplementedException(); + } + else + { + return LLVM.ConstInt(type, (ulong)Value, LLVMMisc.False); + } + } + public override bool IsCastNecessary(TypeDesc destType) { switch (destType.UnderlyingType.Category) @@ -363,10 +388,15 @@ namespace Internal.IL internal class FloatConstantEntry : ConstantEntry<double> { - public FloatConstantEntry(double value, TypeDesc type = null) : base(StackValueKind.Float, value, LLVM.ConstReal(LLVM.FloatType(), value), type) + public FloatConstantEntry(double value, TypeDesc type = null) : base(StackValueKind.Float, value, type) { } + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) + { + return LLVM.ConstReal(type, Value); + } + public override StackEntry Duplicate() { return new FloatConstantEntry(Value, Type); @@ -382,34 +412,77 @@ namespace Internal.IL /// String representation of current expression /// </summary> public string Name { get; set; } - + public LLVMValueRef RawLLVMValue { get; set; } /// <summary> /// Initializes new instance of ExpressionEntry /// </summary> /// <param name="kind">Kind of entry</param> /// <param name="name">String representation of entry</param> /// <param name="type">Type if any of entry</param> - public ExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, llvmValue, type) + public ExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, type) { Name = name; + RawLLVMValue = llvmValue; } public override StackEntry Duplicate() { - return new ExpressionEntry(Kind, Name, LLVMValue, Type); + return new ExpressionEntry(Kind, Name, RawLLVMValue, Type); } - protected override void BuildRepresentation(StringBuilder s) + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) { - base.BuildRepresentation(s); - if (s.Length > 0) - { - s.Append(' '); - } - s.Append(Name); + //TODO: deal with sign extension here + return ILImporter.CastIfNecessary(builder, RawLLVMValue, type); + } + } + + internal class LoadExpressionEntry : ExpressionEntry + { + /// <summary> + /// Initializes new instance of ExpressionEntry + /// </summary> + /// <param name="kind">Kind of entry</param> + /// <param name="name">String representation of entry</param> + /// <param name="type">Type if any of entry</param> + public LoadExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, name, llvmValue, type) + { + } + + public override StackEntry Duplicate() + { + return new LoadExpressionEntry(Kind, Name, RawLLVMValue, Type); + } + + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) + { + return ILImporter.LoadValue(builder, RawLLVMValue, Type, type, signExtend); + } + } + + internal class AddressExpressionEntry : ExpressionEntry + { + /// <summary> + /// Initializes new instance of ExpressionEntry + /// </summary> + /// <param name="kind">Kind of entry</param> + /// <param name="name">String representation of entry</param> + /// <param name="type">Type if any of entry</param> + public AddressExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, name, llvmValue, type) + { + } + + public override StackEntry Duplicate() + { + return new LoadExpressionEntry(Kind, Name, RawLLVMValue, Type); + } + + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) + { + return ILImporter.CastIfNecessary(builder, RawLLVMValue, type); } } - + /// <summary> /// Entry representing some token (either of TypeDesc, MethodDesc or FieldDesc) along with its string representation /// </summary> @@ -417,21 +490,19 @@ namespace Internal.IL { public T LdToken { get; } - public LdTokenEntry(StackValueKind kind, string name, T token, LLVMValueRef value, TypeDesc type = null) : base(kind, name, value, type) + public LdTokenEntry(StackValueKind kind, string name, T token, TypeDesc type = null) : base(kind, name, default(LLVMValueRef), type) { LdToken = token; } public override StackEntry Duplicate() { - return new LdTokenEntry<T>(Kind, Name, LdToken, LLVMValue, Type); + return new LdTokenEntry<T>(Kind, Name, LdToken, Type); } - protected override void BuildRepresentation(StringBuilder s) + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) { - base.BuildRepresentation(s); - s.Append(' '); - s.Append(LdToken); + return ILImporter.CastIfNecessary(builder, RawLLVMValue, type); } } @@ -442,7 +513,7 @@ namespace Internal.IL /// </summary> public static InvalidEntry Entry = new InvalidEntry(); - protected InvalidEntry() : base(StackValueKind.Unknown, default(LLVMValueRef), null) + protected InvalidEntry() : base(StackValueKind.Unknown, null) { } @@ -451,9 +522,33 @@ namespace Internal.IL return this; } - protected override void BuildRepresentation(StringBuilder s) + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) + { + throw new InvalidOperationException(); + } + } + + /// <summary> + /// Entry representing a writable sharable stack entry that can survive from one basic block to another + /// </summary> + internal class SpilledExpressionEntry : ExpressionEntry + { + public int LocalIndex; + private ILImporter _importer; + public SpilledExpressionEntry(StackValueKind kind, string name, TypeDesc type, int localIndex, ILImporter importer) : base(kind, name, new LLVMValueRef(IntPtr.Zero), type) + { + LocalIndex = localIndex; + _importer = importer; + } + + protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend) + { + return _importer.LoadTemp(LocalIndex, type); + } + + public override StackEntry Duplicate() { - s.Append("Invalid Entry"); + return new SpilledExpressionEntry(Kind, Name, Type, LocalIndex, _importer); } } } diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs index 8c7886288..745dd0d20 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs @@ -19,6 +19,13 @@ namespace Internal.IL // backend before the actual compilation happens to gain insights into the code. partial class ILImporter { + public enum LocalVarKind + { + Argument, + Local, + Temp + } + ArrayBuilder<object> _dependencies = new ArrayBuilder<object>(); public IEnumerable<object> GetDependencies() { @@ -35,6 +42,7 @@ namespace Internal.IL private LLVMBasicBlockRef _curBasicBlock; private LLVMBuilderRef _builder; private readonly LocalVariableDefinition[] _locals; + private List<SpilledExpressionEntry> _spilledExpressions = new List<SpilledExpressionEntry>(); private readonly byte[] _ilBytes; @@ -154,6 +162,30 @@ namespace Internal.IL return llvmFunction; } + private LLVMValueRef GetOrCreateLLVMFunction(string mangledName, LLVMTypeRef functionType) + { + LLVMValueRef llvmFunction = LLVM.GetNamedFunction(Module, mangledName); + + if (llvmFunction.Pointer == IntPtr.Zero) + { + return LLVM.AddFunction(Module, mangledName, functionType); + } + return llvmFunction; + } + + private void ImportCallMemset(LLVMValueRef targetPointer, byte value, int length) + { + LLVMValueRef objectSizeValue = BuildConstInt32(length); + var memsetSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.Int8Type(), LLVM.Int32Type(), LLVM.Int32Type(), LLVM.Int1Type() }, false); + LLVM.BuildCall(_builder, GetOrCreateLLVMFunction("llvm.memset.p0i8.i32", memsetSignature), new LLVMValueRef[] { targetPointer, BuildConstInt8(value), objectSizeValue, BuildConstInt32(1), BuildConstInt1(0) }, String.Empty); + } + + private void PushLoadExpression(StackValueKind kind, string name, LLVMValueRef rawLLVMValue, TypeDesc type) + { + Debug.Assert(kind != StackValueKind.Unknown, "Unknown stack kind"); + _stack.Push(new LoadExpressionEntry(kind, name, rawLLVMValue, type)); + } + /// <summary> /// Push an expression named <paramref name="name"/> of kind <paramref name="kind"/>. /// </summary> @@ -194,45 +226,6 @@ namespace Internal.IL _stack.Push(new ExpressionEntry(kind, name, llvmValue, type)); } - - - /// <summary> - /// Generate a cast in case the stack type of source is not identical or compatible with destination type. - /// </summary> - /// <param name="destType">Type of destination</param> - /// <param name="srcEntry">Source entry from stack</param> - private void AppendCastIfNecessary(TypeDesc destType, StackEntry srcEntry) - { - ConstantEntry constant = srcEntry as ConstantEntry; - if ((constant != null) && (constant.IsCastNecessary(destType)) || !destType.IsValueType || destType != srcEntry.Type) - { - throw new NotImplementedException(); - /* - Append("("); - Append(GetSignatureTypeNameAndAddReference(destType)); - Append(")");*/ - } - } - - private void AppendCastIfNecessary(StackValueKind dstType, TypeDesc srcType) - { - if (dstType == StackValueKind.ByRef) - { - - throw new NotImplementedException(); - /* - Append("("); - Append(GetSignatureTypeNameAndAddReference(srcType)); - Append(")");*/ - } - else - if (srcType.IsPointer) - { - throw new NotImplementedException(); - //Append("(intptr_t)"); - } - } - private void MarkInstructionBoundary() { @@ -281,6 +274,8 @@ namespace Internal.IL var terminator = basicBlock.Block.GetBasicBlockTerminator(); if (terminator.Pointer == IntPtr.Zero) { + if (_basicBlocks[_currentOffset].StartOffset == 0) + throw new InvalidProgramException(); LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(_basicBlocks[_currentOffset])); } } @@ -304,13 +299,72 @@ namespace Internal.IL private void ImportLoadVar(int index, bool argument) { + LLVMValueRef typedLoadLocation = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out TypeDesc type); + PushLoadExpression(GetStackValueKind(type), "ld" + (argument ? "arg" : "loc") + index + "_", typedLoadLocation, type); + } + + private LLVMValueRef LoadTemp(int index) + { + LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type); + return LLVM.BuildLoad(_builder, CastToPointerToTypeDesc(address, type), "ldtemp"); + } + + internal LLVMValueRef LoadTemp(int index, LLVMTypeRef asType) + { + LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type); + return LLVM.BuildLoad(_builder, CastIfNecessary(address, LLVM.PointerType(asType, 0)), "ldtemp"); + } + + private void StoreTemp(int index, LLVMValueRef value) + { + LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type); + LLVM.BuildStore(_builder, CastToTypeDesc(value, type), CastToPointerToTypeDesc(address, type)); + } + + internal static LLVMValueRef LoadValue(LLVMBuilderRef builder, LLVMValueRef address, TypeDesc sourceType, LLVMTypeRef targetType, bool signExtend) + { + if (targetType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind && sourceType.IsPrimitive && !sourceType.IsPointer) + { + var sourceLLVMType = ILImporter.GetLLVMTypeForTypeDesc(sourceType); + var typedAddress = CastIfNecessary(builder, address, LLVM.PointerType(sourceLLVMType, 0)); + return CastIntValue(builder, LLVM.BuildLoad(builder, typedAddress, "ldvalue"), targetType, signExtend); + } + else + { + var typedAddress = CastIfNecessary(builder, address, LLVM.PointerType(targetType, 0)); + return LLVM.BuildLoad(builder, typedAddress, "ldvalue"); + } + } + + private static LLVMValueRef CastIntValue(LLVMBuilderRef builder, LLVMValueRef value, LLVMTypeRef type, bool signExtend) + { + if (LLVM.TypeOf(value).Pointer == type.Pointer) + { + return value; + } + else if (LLVM.TypeOf(value).TypeKind == LLVMTypeKind.LLVMPointerTypeKind) + { + return LLVM.BuildPtrToInt(builder, value, type, "intcast"); + } + else if (signExtend && type.GetIntTypeWidth() > LLVM.TypeOf(value).GetIntTypeWidth()) + { + return LLVM.BuildSExtOrBitCast(builder, value, type, "SExtOrBitCast"); + } + else + { + Debug.Assert(LLVM.TypeOf(value).TypeKind == LLVMTypeKind.LLVMIntegerTypeKind); + return LLVM.BuildIntCast(builder, value, type, "intcast"); + } + } + + private LLVMValueRef LoadVarAddress(int index, LocalVarKind kind, out TypeDesc type) + { int varBase; int varCountBase; int varOffset; LLVMTypeRef valueType; - TypeDesc type; - if (argument) + if (kind == LocalVarKind.Argument) { varCountBase = 0; varBase = 0; @@ -335,21 +389,25 @@ namespace Internal.IL } valueType = GetLLVMTypeForTypeDesc(type); } - else + else if (kind == LocalVarKind.Local) { varBase = GetTotalParameterOffset(); GetLocalSizeAndOffsetAtIndex(index, out int localSize, out varOffset); valueType = GetLLVMTypeForTypeDesc(_locals[index].Type); type = _locals[index].Type; } + else + { + varBase = GetTotalRealLocalOffset(); + GetSpillSizeAndOffsetAtIndex(index, out int localSize, out varOffset); + valueType = GetLLVMTypeForTypeDesc(_spilledExpressions[index].Type); + type = _spilledExpressions[index].Type; + } - var loadLocation = LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction), + return LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction), new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (uint)(varBase + varOffset), LLVMMisc.False) }, String.Empty); - var typedLoadLocation = LLVM.BuildPointerCast(_builder, loadLocation, LLVM.PointerType(valueType, 0), "typedLoadLocation"); - var loadResult = LLVM.BuildLoad(_builder, typedLoadLocation, "ld" + (argument ? "arg" : "loc") + index + "_"); - PushExpression(GetStackValueKind(type), String.Empty, loadResult, type); } private StackValueKind GetStackValueKind(TypeDesc type) @@ -395,24 +453,16 @@ namespace Internal.IL private void ImportStoreVar(int index, bool argument) { - if(argument) - { - throw new NotImplementedException("storing to argument"); - } - - GetLocalSizeAndOffsetAtIndex(index, out int localSize, out int localOffset); - - LLVMValueRef toStore = _stack.Pop().LLVMValue; - - LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_locals[index].Type); - - ImportStoreHelper(toStore, valueType, LLVM.GetFirstParam(_llvmFunction), (uint)(GetTotalParameterOffset() + localOffset)); + TypeDesc varType; + StackEntry toStore = _stack.Pop(); + LLVMValueRef varAddress = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out varType); + CastingStore(varAddress, toStore, varType); } private void ImportStoreHelper(LLVMValueRef toStore, LLVMTypeRef valueType, LLVMValueRef basePtr, uint offset) { LLVMValueRef typedToStore = CastIfNecessary(toStore, valueType); - + var storeLocation = LLVM.BuildGEP(_builder, basePtr, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), offset, LLVMMisc.False) }, String.Empty); @@ -420,8 +470,34 @@ namespace Internal.IL LLVM.BuildStore(_builder, typedToStore, typedStoreLocation); } + private LLVMValueRef CastToRawPointer(LLVMValueRef source) + { + return CastIfNecessary(source, LLVM.PointerType(LLVM.Int8Type(), 0)); + } + + private LLVMValueRef CastToTypeDesc(LLVMValueRef source, TypeDesc type) + { + return CastIfNecessary(source, GetLLVMTypeForTypeDesc(type)); + } + + private LLVMValueRef CastToPointerToTypeDesc(LLVMValueRef source, TypeDesc type) + { + return CastIfNecessary(source, LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0)); + } + + private void CastingStore(LLVMValueRef address, StackEntry value, TypeDesc targetType) + { + var typedStoreLocation = CastToPointerToTypeDesc(address, targetType); + LLVM.BuildStore(_builder, value.ValueAsType(targetType, _builder), typedStoreLocation); + } + private LLVMValueRef CastIfNecessary(LLVMValueRef source, LLVMTypeRef valueType) { + return CastIfNecessary(_builder, source, valueType); + } + + internal static LLVMValueRef CastIfNecessary(LLVMBuilderRef builder, LLVMValueRef source, LLVMTypeRef valueType) + { LLVMTypeRef sourceType = LLVM.TypeOf(source); if (sourceType.Pointer == valueType.Pointer) return source; @@ -432,11 +508,19 @@ namespace Internal.IL LLVMValueRef typedToStore = source; if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind) { - typedToStore = LLVM.BuildPointerCast(_builder, source, valueType, "CastIfNecessaryPtr"); + typedToStore = LLVM.BuildPointerCast(builder, source, valueType, "CastIfNecessaryPtr"); } else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMIntegerTypeKind) { - typedToStore = LLVM.BuildPtrToInt(_builder, source, valueType, "CastIfNecessaryInt"); + typedToStore = LLVM.BuildPtrToInt(builder, source, valueType, "CastIfNecessaryInt"); + } + else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMArrayTypeKind) + { + typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0)), "CastIfNecessaryArrayLoad"); + } + else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMArrayTypeKind) + { + typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0)), "CastIfNecessaryArrayLoad"); } else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind != LLVMTypeKind.LLVMIntegerTypeKind) { @@ -444,7 +528,7 @@ namespace Internal.IL } else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind) { - typedToStore = LLVM.BuildIntToPtr(_builder, source, valueType, "CastIfNecessaryPtr"); + typedToStore = LLVM.BuildIntToPtr(builder, source, valueType, "CastIfNecessaryPtr"); } else if (toStoreKind != LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind) { @@ -457,13 +541,21 @@ namespace Internal.IL else if (toStoreKind == valueTypeKind && toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind) { Debug.Assert(toStoreKind != LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind != LLVMTypeKind.LLVMPointerTypeKind); - typedToStore = LLVM.BuildIntCast(_builder, source, valueType, "CastIfNecessaryInt"); + typedToStore = LLVM.BuildIntCast(builder, source, valueType, "CastIfNecessaryInt"); + } + else if (toStoreKind == LLVMTypeKind.LLVMFloatTypeKind && valueTypeKind != LLVMTypeKind.LLVMFloatTypeKind) + { + typedToStore = LLVM.BuildIntCast(builder, source, valueType, "CastIfNecessaryFloat"); + } + else if (toStoreKind != LLVMTypeKind.LLVMFloatTypeKind && valueTypeKind == LLVMTypeKind.LLVMFloatTypeKind) + { + typedToStore = LLVM.BuildFPCast(builder, source, valueType, "CastIfNecessaryFloat"); } return typedToStore; } - private LLVMTypeRef GetLLVMTypeForTypeDesc(TypeDesc type) + internal static LLVMTypeRef GetLLVMTypeForTypeDesc(TypeDesc type) { switch (type.Category) { @@ -481,9 +573,9 @@ namespace Internal.IL case TypeFlags.Int32: case TypeFlags.UInt32: + return LLVM.Int32Type(); case TypeFlags.IntPtr: case TypeFlags.UIntPtr: - return LLVM.Int32Type(); case TypeFlags.Array: case TypeFlags.SzArray: case TypeFlags.ByRef: @@ -492,7 +584,7 @@ namespace Internal.IL return LLVM.PointerType(LLVM.Int8Type(), 0); case TypeFlags.Pointer: - return LLVM.PointerType(GetLLVMTypeForTypeDesc(type.GetParameterType()), 0); + return LLVM.PointerType(type.GetParameterType().IsVoid ? LLVM.Int8Type() : GetLLVMTypeForTypeDesc(type.GetParameterType()), 0); case TypeFlags.Int64: case TypeFlags.UInt64: @@ -521,6 +613,16 @@ namespace Internal.IL private int GetTotalLocalOffset() { + int offset = GetTotalRealLocalOffset(); + for (int i = 0; i < _spilledExpressions.Count; i++) + { + offset += _spilledExpressions[i].Type.GetElementSize().AsInt; + } + return offset; + } + + private int GetTotalRealLocalOffset() + { int offset = 0; for (int i = 0; i < _locals.Length; i++) { @@ -592,22 +694,23 @@ namespace Internal.IL } } - private void ImportAddressOfVar(int index, bool argument) + private void GetSpillSizeAndOffsetAtIndex(int index, out int size, out int offset) { - if (argument) + SpilledExpressionEntry spill = _spilledExpressions[index]; + size = spill.Type.GetElementSize().AsInt; + + offset = 0; + for (int i = 0; i < index; i++) { - throw new NotImplementedException("ldarga"); + offset += _spilledExpressions[i].Type.GetElementSize().AsInt; } + } - int localOffset = GetTotalParameterOffset(); - GetLocalSizeAndOffsetAtIndex(index, out int size, out int offset); - localOffset += offset; - - var localPtr = LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction), - new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (uint)localOffset, LLVMMisc.False) }, "ldloca"); - //var typedLocalPtr = LLVM.BuildPointerCast(_builder, localPtr, GetLLVMTypeForTypeDesc(_locals[index].Type.MakePointerType()), "ldloca"); - - _stack.Push(new ExpressionEntry(StackValueKind.ByRef, "ldloca", localPtr, _locals[index].Type.MakePointerType())); + private void ImportAddressOfVar(int index, bool argument) + { + TypeDesc type; + LLVMValueRef typedLoadLocation = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out type); + _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldloca", typedLoadLocation, type.MakePointerType())); } private void ImportDup() @@ -640,8 +743,7 @@ namespace Internal.IL { StackEntry retVal = _stack.Pop(); LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_signature.ReturnType); - - ImportStoreHelper(retVal.LLVMValue, valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0); + ImportStoreHelper(retVal.ValueAsType(valueType, _builder), valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0); } LLVM.BuildRetVoid(_builder); @@ -650,7 +752,6 @@ namespace Internal.IL private void ImportCall(ILOpcode opcode, int token) { MethodDesc callee = (MethodDesc)_methodIL.GetObject(token); - if (callee.IsIntrinsic) { if (ImportIntrinsicCall(callee)) @@ -665,8 +766,29 @@ namespace Internal.IL return; } + if (opcode == ILOpcode.newobj) + { + if (callee.OwningType.IsString) + { + // String constructors actually look like regular method calls + IMethodNode node = _compilation.NodeFactory.StringAllocator(callee); + _dependencies.Add(node); + callee = node.Method; + opcode = ILOpcode.call; + } + else + { + StackEntry newObjResult = AllocateObject(callee.OwningType); + //one for the real result and one to be consumed by ctor + if (callee.Signature.Length > _stack.Length) //System.Reflection.MemberFilter.ctor + throw new InvalidProgramException(); + _stack.InsertAt(newObjResult, _stack.Top - callee.Signature.Length); + _stack.InsertAt(newObjResult, _stack.Top - callee.Signature.Length); + } + } + // we don't really have virtual call support, but we'll treat it as direct for now - if (opcode != ILOpcode.call && opcode != ILOpcode.callvirt) + if (opcode != ILOpcode.call && opcode != ILOpcode.callvirt && opcode != ILOpcode.newobj) { throw new NotImplementedException(); } @@ -678,6 +800,50 @@ namespace Internal.IL HandleCall(callee); } + private ExpressionEntry AllocateObject(TypeDesc type) + { + MetadataType metadataType = (MetadataType)type; + int objectSize = metadataType.InstanceByteCount.AsInt; + if (metadataType.IsValueType) + { + objectSize += type.Context.Target.PointerSize; + } + + LLVMValueRef allocatedMemory = LLVM.BuildMalloc(_builder, LLVM.ArrayType(LLVM.Int8Type(), (uint)objectSize), "newobj"); + LLVMValueRef castMemory = LLVM.BuildPointerCast(_builder, allocatedMemory, LLVM.PointerType(LLVM.Int8Type(), 0), "castnewobj"); + ImportCallMemset(castMemory, 0, objectSize); + LLVMValueRef eeTypePointer = GetEETypeForTypeDesc(type); + LLVMValueRef objectHeaderPtr = LLVM.BuildPointerCast(_builder, allocatedMemory, LLVM.PointerType(LLVM.TypeOf(eeTypePointer), 0), "objectHeaderPtr"); + LLVM.BuildStore(_builder, eeTypePointer, objectHeaderPtr); + return new ExpressionEntry(StackValueKind.ObjRef, "newobj", castMemory, type); + } + + private static LLVMValueRef BuildConstInt1(int number) + { + Debug.Assert(number == 0 || number == 1, "Non-boolean int1"); + return LLVM.ConstInt(LLVM.Int1Type(), (ulong)number, LLVMMisc.False); + } + + private static LLVMValueRef BuildConstInt8(byte number) + { + return LLVM.ConstInt(LLVM.Int8Type(), number, LLVMMisc.False); + } + + private static LLVMValueRef BuildConstInt32(int number) + { + return LLVM.ConstInt(LLVM.Int32Type(), (ulong)number, LLVMMisc.False); + } + + private LLVMValueRef GetEETypeForTypeDesc(TypeDesc target) + { + ISymbolNode node = _compilation.NodeFactory.ConstructedTypeSymbol(target); + LLVMValueRef eeTypePointer = LoadAddressOfSymbolNode(node); + _dependencies.Add(node); + var eeTypePtrType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr"); + var ptrPtrType = LLVM.PointerType(GetLLVMTypeForTypeDesc(eeTypePtrType), 0); + return LLVM.BuildPointerCast(_builder, eeTypePointer, ptrPtrType, "castEETypePtr"); + } + /// <summary> /// Implements intrinsic methods instread of calling them /// </summary> @@ -735,16 +901,16 @@ namespace Internal.IL } // The last argument is the top of the stack. We need to reverse them and store starting at the first argument - LLVMValueRef[] argumentValues = new LLVMValueRef[callee.Signature.Length + instanceAdjustment]; + StackEntry[] argumentValues = new StackEntry[callee.Signature.Length + instanceAdjustment]; for(int i = 0; i < argumentValues.Length; i++) { - argumentValues[argumentValues.Length - i - 1] = _stack.Pop().LLVMValue; + argumentValues[argumentValues.Length - i - 1] = _stack.Pop(); } for (int index = 0; index < argumentValues.Length; index++) { - LLVMValueRef toStore = argumentValues[index]; + StackEntry toStore = argumentValues[index]; TypeDesc argType; if (index == 0 && !callee.Signature.IsStatic) @@ -758,7 +924,7 @@ namespace Internal.IL LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(argType); - ImportStoreHelper(toStore, valueType, castShadowStack, argOffset); + ImportStoreHelper(toStore.ValueAsType(valueType, _builder), valueType, castShadowStack, argOffset); argOffset += (uint)argType.GetElementSize().AsInt; } @@ -772,8 +938,7 @@ namespace Internal.IL { LLVMTypeRef returnLLVMType = GetLLVMTypeForTypeDesc(callee.Signature.ReturnType); LLVMValueRef returnLLVMPointer = LLVM.BuildPointerCast(_builder, returnAddress, LLVM.PointerType(returnLLVMType, 0), "castreturnpointer"); - LLVMValueRef loadResult = LLVM.BuildLoad(_builder, returnLLVMPointer, String.Empty); - PushExpression(GetStackValueKind(callee.Signature.ReturnType), String.Empty, loadResult, callee.Signature.ReturnType); + PushLoadExpression(GetStackValueKind(callee.Signature.ReturnType), String.Empty, returnLLVMPointer, callee.Signature.ReturnType); } } @@ -786,6 +951,11 @@ namespace Internal.IL { LLVMValueRef nativeFunc = LLVM.GetNamedFunction(Module, method.Name); + //emscripten dies if this is output because its expected to have i32, i32, i64. But the runtime has defined it as i8*, i8*, i64 + if (method.Name == "memmove") + throw new NotImplementedException(); + + // Create an import if we haven't already if (nativeFunc.Pointer == IntPtr.Zero) { @@ -806,24 +976,17 @@ namespace Internal.IL LLVMValueRef[] arguments = new LLVMValueRef[method.Signature.Length]; for(int i = 0; i < arguments.Length; i++) { - LLVMValueRef argValue = _stack.Pop().LLVMValue; - // Arguments are reversed on the stack // Coerce pointers to the native type TypeDesc signatureType = method.Signature[arguments.Length - i - 1]; - LLVMValueRef typedValue = argValue; - if (signatureType.IsPointer) - { - LLVMTypeRef signatureLlvmType = GetLLVMTypeForTypeDesc(signatureType); - typedValue = LLVM.BuildPointerCast(_builder, argValue, signatureLlvmType, "castarg"); - } - arguments[arguments.Length - i - 1] = typedValue; + arguments[arguments.Length - i - 1] = _stack.Pop().ValueAsType(GetLLVMTypeForTypeDesc(signatureType), _builder); } - var returnValue = LLVM.BuildCall(_builder, nativeFunc, arguments, "call"); + //dont name the return value if the function returns void, its invalid + var returnValue = LLVM.BuildCall(_builder, nativeFunc, arguments, !method.Signature.ReturnType.IsVoid ? "call" : string.Empty); if(!method.Signature.ReturnType.IsVoid) - PushExpression(GetStackValueKind(method.Signature.ReturnType), String.Empty, returnValue, method.Signature.ReturnType); + PushExpression(GetStackValueKind(method.Signature.ReturnType), "retval", returnValue, method.Signature.ReturnType); } private void ImportCalli(int token) @@ -862,6 +1025,10 @@ namespace Internal.IL { if (opcode == ILOpcode.br) { + ImportFallthrough(target); + //TODO: why does this illegal branch happen in System.Reflection.MemberFilter.ctor + if (target.StartOffset == 0) + throw new InvalidProgramException(); LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(target)); } else @@ -871,11 +1038,10 @@ namespace Internal.IL if (opcode == ILOpcode.brfalse || opcode == ILOpcode.brtrue) { var op = _stack.Pop(); - LLVMValueRef value = op.LLVMValue; - if (LLVM.GetTypeKind(LLVM.TypeOf(value)) == LLVMTypeKind.LLVMPointerTypeKind) - { - value = LLVM.BuildPtrToInt(_builder, value, LLVM.Int32Type(), String.Empty); - } + LLVMValueRef value = op.ValueAsInt32(_builder, false); + + if (LLVM.TypeOf(value).TypeKind != LLVMTypeKind.LLVMIntegerTypeKind) + throw new InvalidProgramException("branch on non integer"); if (opcode == ILOpcode.brfalse) { @@ -903,21 +1069,8 @@ namespace Internal.IL kind = op2.Kind; } - LLVMValueRef left = op1.LLVMValue; - LLVMValueRef right = op2.LLVMValue; - - if (kind == StackValueKind.NativeInt || kind == StackValueKind.ObjRef || kind == StackValueKind.ByRef) - { - if (LLVM.GetTypeKind(LLVM.TypeOf(left)) == LLVMTypeKind.LLVMPointerTypeKind) - { - left = LLVM.BuildPtrToInt(_builder, left, LLVM.Int32Type(), "lptrasint"); - } - if (LLVM.GetTypeKind(LLVM.TypeOf(right)) == LLVMTypeKind.LLVMPointerTypeKind) - { - right = LLVM.BuildPtrToInt(_builder, right, LLVM.Int32Type(), "rptrasint"); - } - } - + LLVMValueRef left = op1.ValueForStackKind(kind, _builder, false); + LLVMValueRef right = op2.ValueForStackKind(kind, _builder, false); switch (opcode) { @@ -959,19 +1112,17 @@ namespace Internal.IL if (target.StartOffset == 0) throw new NotImplementedException("cant branch to entry basic block"); - LLVM.BuildCondBr(_builder, condition, GetLLVMBasicBlockForBlock(target), GetLLVMBasicBlockForBlock(fallthrough)); - + ImportFallthrough(target); ImportFallthrough(fallthrough); + LLVM.BuildCondBr(_builder, condition, GetLLVMBasicBlockForBlock(target), GetLLVMBasicBlockForBlock(fallthrough)); } - - ImportFallthrough(target); } private void ImportSwitchJump(int jmpBase, int[] jmpDelta, BasicBlock fallthrough) { var operand = _stack.Pop(); - var @switch = LLVM.BuildSwitch(_builder, operand.LLVMValue, GetLLVMBasicBlockForBlock(fallthrough), (uint)jmpDelta.Length); + var @switch = LLVM.BuildSwitch(_builder, operand.ValueAsInt32(_builder, false), GetLLVMBasicBlockForBlock(fallthrough), (uint)jmpDelta.Length); for (var i = 0; i < jmpDelta.Length; i++) { var target = _basicBlocks[_currentOffset + jmpDelta[i]]; @@ -989,22 +1140,13 @@ namespace Internal.IL private void ImportLoadIndirect(TypeDesc type) { - StackEntry pointer = _stack.Pop(); - LLVMTypeRef loadType = GetLLVMTypeForTypeDesc(type); - LLVMTypeRef pointerType = LLVM.PointerType(loadType, 0); - - LLVMValueRef typedPointer; - if (LLVM.GetTypeKind(LLVM.TypeOf(pointer.LLVMValue)) != LLVMTypeKind.LLVMPointerTypeKind) - { - typedPointer = LLVM.BuildIntToPtr(_builder, pointer.LLVMValue, pointerType, "ldindintptrcast"); - } - else - { - typedPointer = LLVM.BuildPointerCast(_builder, pointer.LLVMValue, pointerType, "ldindptrcast"); - } - - LLVMValueRef load = LLVM.BuildLoad(_builder, typedPointer, "ldind"); - PushExpression(GetStackValueKind(type), "ldlind", load, type); + var pointer = _stack.Pop(); + Debug.Assert(pointer is ExpressionEntry || pointer is ConstantEntry); + var expressionPointer = pointer as ExpressionEntry; + TypeDesc pointerElementType = pointer.Type.GetParameterType(); + LLVMValueRef rawValue = expressionPointer?.RawLLVMValue ?? LLVM.ConstNull(GetLLVMTypeForTypeDesc(pointerElementType)); + _stack.Push(new LoadExpressionEntry(type != null ? GetStackValueKind(type) : StackValueKind.ByRef, "ldind", + rawValue, pointer.Type.GetParameterType())); } private void ImportStoreIndirect(int token) @@ -1016,29 +1158,18 @@ namespace Internal.IL { StackEntry value = _stack.Pop(); StackEntry destinationPointer = _stack.Pop(); - LLVMTypeRef requestedPointerType = LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0); - LLVMValueRef typedValue = value.LLVMValue; - LLVMValueRef typedPointer = destinationPointer.LLVMValue; + LLVMValueRef typedValue; + LLVMValueRef typedPointer; - if (LLVM.GetTypeKind(LLVM.TypeOf(destinationPointer.LLVMValue)) != LLVMTypeKind.LLVMPointerTypeKind) + if (type != null) { - typedPointer = LLVM.BuildIntToPtr(_builder, destinationPointer.LLVMValue, requestedPointerType, "stindintptrcast"); + typedValue = value.ValueAsType(type, _builder); + typedPointer = destinationPointer.ValueAsType(type.MakePointerType(), _builder); } else { - typedPointer = LLVM.BuildPointerCast(_builder, destinationPointer.LLVMValue, requestedPointerType, "stindptrcast"); - } - - if (value.Type != type) - { - if (LLVM.GetTypeKind(GetLLVMTypeForTypeDesc(value.Type)) != LLVMTypeKind.LLVMPointerTypeKind) - { - typedValue = LLVM.BuildIntCast(_builder, typedValue, GetLLVMTypeForTypeDesc(type), "stindvalcast"); - } - else - { - typedValue = LLVM.BuildPointerCast(_builder, typedValue, GetLLVMTypeForTypeDesc(type), "stindvalptrcast"); - } + typedPointer = destinationPointer.ValueAsType(LLVM.PointerType(LLVM.Int32Type(), 0), _builder); + typedValue = value.ValueAsInt32(_builder, false); } LLVM.BuildStore(_builder, typedValue, typedPointer); @@ -1065,106 +1196,140 @@ namespace Internal.IL } // The one exception from the above rule - if ((kind == StackValueKind.ByRef) && - (opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un)) + if (kind == StackValueKind.ByRef) { kind = StackValueKind.NativeInt; - type = null; + type = type.MakePointerType(); } LLVMValueRef result; - LLVMValueRef left = op1.LLVMValue; - LLVMValueRef right = op2.LLVMValue; - - if (kind == StackValueKind.NativeInt || kind == StackValueKind.ObjRef || kind == StackValueKind.ByRef) + LLVMValueRef left = op1.ValueForStackKind(kind, _builder, false); + LLVMValueRef right = op2.ValueForStackKind(kind, _builder, false); + if (kind == StackValueKind.Float) { - if (LLVM.GetTypeKind(LLVM.TypeOf(left)) == LLVMTypeKind.LLVMPointerTypeKind) + switch (opcode) { - left = LLVM.BuildPtrToInt(_builder, left, LLVM.Int32Type(), "lptrasint"); + case ILOpcode.add: + result = LLVM.BuildFAdd(_builder, left, right, "fadd"); + break; + case ILOpcode.sub: + result = LLVM.BuildFSub(_builder, left, right, "fsub"); + break; + case ILOpcode.mul: + result = LLVM.BuildFMul(_builder, left, right, "fmul"); + break; + case ILOpcode.div: + result = LLVM.BuildFDiv(_builder, left, right, "fdiv"); + break; + case ILOpcode.rem: + result = LLVM.BuildFRem(_builder, left, right, "frem"); + break; + + // TODO: Overflow checks + case ILOpcode.add_ovf: + case ILOpcode.add_ovf_un: + result = LLVM.BuildFAdd(_builder, left, right, "fadd"); + break; + case ILOpcode.sub_ovf: + case ILOpcode.sub_ovf_un: + result = LLVM.BuildFSub(_builder, left, right, "fsub"); + break; + case ILOpcode.mul_ovf: + case ILOpcode.mul_ovf_un: + result = LLVM.BuildFMul(_builder, left, right, "fmul"); + break; + + default: + throw new InvalidOperationException(); // Should be unreachable } - if (LLVM.GetTypeKind(LLVM.TypeOf(right)) == LLVMTypeKind.LLVMPointerTypeKind) + } + else + { + switch (opcode) { - right = LLVM.BuildPtrToInt(_builder, right, LLVM.Int32Type(), "rptrasint"); + case ILOpcode.add: + result = LLVM.BuildAdd(_builder, left, right, "add"); + break; + case ILOpcode.sub: + result = LLVM.BuildSub(_builder, left, right, "sub"); + break; + case ILOpcode.mul: + result = LLVM.BuildMul(_builder, left, right, "mul"); + break; + case ILOpcode.div: + result = LLVM.BuildSDiv(_builder, left, right, "sdiv"); + break; + case ILOpcode.div_un: + result = LLVM.BuildUDiv(_builder, left, right, "udiv"); + break; + case ILOpcode.rem: + result = LLVM.BuildSRem(_builder, left, right, "srem"); + break; + case ILOpcode.rem_un: + result = LLVM.BuildURem(_builder, left, right, "urem"); + break; + case ILOpcode.and: + result = LLVM.BuildAnd(_builder, left, right, "and"); + break; + case ILOpcode.or: + result = LLVM.BuildOr(_builder, left, right, "or"); + break; + case ILOpcode.xor: + result = LLVM.BuildXor(_builder, left, right, "xor"); + break; + + // TODO: Overflow checks + case ILOpcode.add_ovf: + case ILOpcode.add_ovf_un: + result = LLVM.BuildAdd(_builder, left, right, "add"); + break; + case ILOpcode.sub_ovf: + case ILOpcode.sub_ovf_un: + result = LLVM.BuildSub(_builder, left, right, "sub"); + break; + case ILOpcode.mul_ovf: + case ILOpcode.mul_ovf_un: + result = LLVM.BuildMul(_builder, left, right, "mul"); + break; + + default: + throw new InvalidOperationException(); // Should be unreachable } } - switch (opcode) - { - case ILOpcode.add: - result = LLVM.BuildAdd(_builder, left, right, "add"); - break; - case ILOpcode.sub: - result = LLVM.BuildSub(_builder, left, right, "sub"); - break; - case ILOpcode.mul: - result = LLVM.BuildMul(_builder, left, right, "mul"); - break; - case ILOpcode.div: - result = LLVM.BuildSDiv(_builder, left, right, "sdiv"); - break; - case ILOpcode.div_un: - result = LLVM.BuildUDiv(_builder, left, right, "udiv"); - break; - case ILOpcode.rem: - result = LLVM.BuildSRem(_builder, left, right, "srem"); - break; - case ILOpcode.rem_un: - result = LLVM.BuildURem(_builder, left, right, "urem"); - break; - case ILOpcode.and: - result = LLVM.BuildAnd(_builder, left, right, "and"); - break; - case ILOpcode.or: - result = LLVM.BuildOr(_builder, left, right, "or"); - break; - case ILOpcode.xor: - result = LLVM.BuildXor(_builder, left, right, "xor"); - break; - // TODO: Overflow checks - case ILOpcode.add_ovf: - case ILOpcode.add_ovf_un: - result = LLVM.BuildAdd(_builder, left, right, "add"); - break; - case ILOpcode.sub_ovf: - case ILOpcode.sub_ovf_un: - result = LLVM.BuildSub(_builder, left, right, "sub"); - break; - case ILOpcode.mul_ovf: - case ILOpcode.mul_ovf_un: - result = LLVM.BuildMul(_builder, left, right, "mul"); - break; - - default: - throw new InvalidOperationException(); // Should be unreachable + if (kind == StackValueKind.NativeInt || kind == StackValueKind.ByRef || kind == StackValueKind.ObjRef) + { + //we need to put the type back if we changed it because it started out a pointer + result = CastToTypeDesc(result, type); } - - PushExpression(kind, "", result, type); + PushExpression(kind, "binop", result, type); } private void ImportShiftOperation(ILOpcode opcode) { LLVMValueRef result; - StackEntry numBitsToShift = _stack.Pop(); StackEntry valueToShift = _stack.Pop(); + LLVMValueRef valueToShiftValue = valueToShift.ValueForStackKind(valueToShift.Kind, _builder, false); + switch (opcode) { case ILOpcode.shl: - result = LLVM.BuildShl(_builder, valueToShift.LLVMValue, numBitsToShift.LLVMValue, "shl"); + result = LLVM.BuildShl(_builder, valueToShiftValue, numBitsToShift.ValueAsInt32(_builder, false), "shl"); break; case ILOpcode.shr: - result = LLVM.BuildAShr(_builder, valueToShift.LLVMValue, numBitsToShift.LLVMValue, "shr"); + result = LLVM.BuildAShr(_builder, valueToShiftValue, numBitsToShift.ValueAsInt32(_builder, false), "shr"); break; case ILOpcode.shr_un: - result = LLVM.BuildLShr(_builder, valueToShift.LLVMValue, numBitsToShift.LLVMValue, "shr"); + result = LLVM.BuildLShr(_builder, valueToShiftValue, numBitsToShift.ValueAsInt32(_builder, false), "shr"); break; default: throw new InvalidOperationException(); // Should be unreachable } - PushExpression(valueToShift.Kind, "", result, valueToShift.Type); + PushExpression(valueToShift.Kind, "shiftop", result, valueToShift.Type); } private void ImportCompareOperation(ILOpcode opcode) @@ -1185,34 +1350,8 @@ namespace Internal.IL } LLVMValueRef result; - //TODO: deal with sign extension here instead of just casting - var typeSaneOp1 = op1.LLVMValue; - var typeSaneOp2 = op2.LLVMValue; - if (op1.Type != op2.Type || op1.Type == null) - { - if (op1.Type != null && op2.Type != null) - { - if (op1.Type.IsPrimitive && op2.Type.IsPrimitive) - { - if (op1.Type.GetElementSize().AsInt > op2.Type.GetElementSize().AsInt) - typeSaneOp2 = CastIfNecessary(op2.LLVMValue, GetLLVMTypeForTypeDesc(op1.Type)); - else - typeSaneOp1 = CastIfNecessary(op1.LLVMValue, GetLLVMTypeForTypeDesc(op2.Type)); - } - else - { - typeSaneOp2 = CastIfNecessary(op2.LLVMValue, GetLLVMTypeForTypeDesc(op1.Type)); - } - } - else if (op1.Type == null && op1.Kind == StackValueKind.ObjRef) - { - typeSaneOp1 = CastIfNecessary(op1.LLVMValue, LLVM.TypeOf(typeSaneOp2)); - } - else if (op2.Type == null && op2.Kind == StackValueKind.ObjRef) - { - typeSaneOp2 = CastIfNecessary(op2.LLVMValue, LLVM.TypeOf(typeSaneOp1)); - } - } + LLVMValueRef typeSaneOp1 = op1.ValueForStackKind(kind, _builder, true); + LLVMValueRef typeSaneOp2 = op2.ValueForStackKind(kind, _builder, true); switch (opcode) { @@ -1235,23 +1374,30 @@ namespace Internal.IL throw new NotSupportedException(); // unreachable } - PushExpression(kind, "", result, GetWellKnownType(WellKnownType.SByte)); + PushExpression(StackValueKind.Int32, "cmpop", result, GetWellKnownType(WellKnownType.SByte)); } private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned) { StackEntry value = _stack.Pop(); - StackEntry convertedValue = value.Duplicate(); + LLVMValueRef convertedValue; //conv.u for a pointer should change to a int8* - if(wellKnownType == WellKnownType.UIntPtr) + if (wellKnownType == WellKnownType.UIntPtr) { if (value.Kind == StackValueKind.Int32) { - convertedValue.LLVMValue = LLVM.BuildIntToPtr(_builder, value.LLVMValue, LLVM.PointerType(LLVM.Int8Type(), 0), "conv.u"); + convertedValue = LLVM.BuildIntToPtr(_builder, value.ValueAsInt32(_builder, false), LLVM.PointerType(LLVM.Int8Type(), 0), "conv.u"); + } + else + { + convertedValue = value.ValueAsType(GetWellKnownType(wellKnownType), _builder); } } - - _stack.Push(convertedValue); + else + { + convertedValue = value.ValueAsType(GetWellKnownType(wellKnownType), _builder); + } + PushExpression(value.Kind, "conv", convertedValue, value.Type); } private void ImportUnaryOperation(ILOpcode opCode) @@ -1264,21 +1410,21 @@ namespace Internal.IL case ILOpcode.neg: if (argument.Kind == StackValueKind.Float) { - result = LLVM.BuildFNeg(_builder, argument.LLVMValue, "neg"); + result = LLVM.BuildFNeg(_builder, argument.ValueForStackKind(argument.Kind, _builder, false), "neg"); } else { - result = LLVM.BuildNeg(_builder, argument.LLVMValue, "neg"); + result = LLVM.BuildNeg(_builder, argument.ValueForStackKind(argument.Kind, _builder, true), "neg"); } break; case ILOpcode.not: - result = LLVM.BuildNot(_builder, argument.LLVMValue, "not"); + result = LLVM.BuildNot(_builder, argument.ValueForStackKind(argument.Kind, _builder, true), "not"); break; default: throw new NotSupportedException(); // unreachable } - PushExpression(argument.Kind, "", result, argument.Type); + PushExpression(argument.Kind, "unaryop", result, argument.Type); } private void ImportCpOpj(int token) @@ -1287,6 +1433,37 @@ namespace Internal.IL private void ImportUnbox(int token, ILOpcode opCode) { + TypeDesc type = ResolveTypeToken(token); + if (type.IsNullable) + throw new NotImplementedException(); + + if (opCode == ILOpcode.unbox) + { + var unboxResult = _stack.Pop().ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder); + LLVMValueRef unboxData = LLVM.BuildGEP(_builder, unboxResult, new LLVMValueRef[] { BuildConstInt32(type.Context.Target.PointerSize) }, "unboxData"); + //push the pointer to the data, but it shouldnt be implicitly dereferenced + PushExpression(GetStackValueKind(type), "unboxed", unboxData, type); + } + else //unbox_any + { + Debug.Assert(opCode == ILOpcode.unbox_any); + + //TODO: when the runtime is ready switch this to calling the real RhUnboxAny + //LLVMValueRef eeType = GetEETypeForTypeDesc(type); + //var eeTypeDesc = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr"); + //LLVMValueRef untypedObjectValue = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(type), "objptr"); + //PushExpression(StackValueKind.ByRef, "objPtr", untypedObjectValue, type.MakePointerType()); + //PushExpression(StackValueKind.ByRef, "eeType", eeType, eeTypeDesc); + //CallRuntimeExport(_compilation.TypeSystemContext, "RhUnboxAny"); + //PushLoadExpression(GetStackValueKind(type), "unboxed", untypedObjectValue, type); + //this can be removed once we can call RhUnboxAny + if (!type.IsValueType) + throw new NotImplementedException(); + + var unboxResult = _stack.Pop().ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder); + LLVMValueRef unboxData = LLVM.BuildGEP(_builder, unboxResult, new LLVMValueRef[] { BuildConstInt32(type.Context.Target.PointerSize) }, "unboxData"); + PushLoadExpression(GetStackValueKind(type), "unboxed", unboxData, type); + } } private void ImportRefAnyVal(int token) @@ -1310,21 +1487,16 @@ namespace Internal.IL if (ldtokenValue is TypeDesc) { ldtokenKind = WellKnownType.RuntimeTypeHandle; - //AddTypeReference((TypeDesc)ldtokenValue, false); - - // todo: this doesn't work because we don't have the eetypeptr pushed. How do we get the eetypeptr? + PushExpression(StackValueKind.ByRef, "ldtoken", GetEETypeForTypeDesc(ldtokenValue as TypeDesc), _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr")); MethodDesc helper = _compilation.TypeSystemContext.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeTypeHandle"); - //AddMethodReference(helper); + AddMethodReference(helper); HandleCall(helper); name = ldtokenValue.ToString(); - - //value = new LdTokenEntry<TypeDesc>(StackValueKind.ValueType, name, (TypeDesc)ldtokenValue, GetWellKnownType(ldtokenKind)); } else if (ldtokenValue is FieldDesc) { ldtokenKind = WellKnownType.RuntimeFieldHandle; - // todo: this is probably the wrong llvm value for the field - value = new LdTokenEntry<FieldDesc>(StackValueKind.ValueType, null, (FieldDesc)ldtokenValue, LLVM.ConstInt(LLVM.Int32Type(), (uint)token, LLVMMisc.False), GetWellKnownType(ldtokenKind)); + value = new LdTokenEntry<FieldDesc>(StackValueKind.ValueType, null, (FieldDesc)ldtokenValue, GetWellKnownType(ldtokenKind)); _stack.Push(value); } else if (ldtokenValue is MethodDesc) @@ -1404,21 +1576,35 @@ namespace Internal.IL private LLVMValueRef GetInstanceFieldAddress(StackEntry objectEntry, FieldDesc field) { var objectType = objectEntry.Type ?? field.OwningType; - LLVMValueRef typedObjectValue; + LLVMValueRef untypedObjectValue; + LLVMTypeRef llvmObjectType = GetLLVMTypeForTypeDesc(objectType); if (objectType.IsValueType && !objectType.IsPointer && objectEntry.Kind != StackValueKind.NativeInt && objectEntry.Kind != StackValueKind.ByRef) { - typedObjectValue = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(objectType), "objptr"); - LLVM.BuildStore(_builder, objectEntry.LLVMValue, typedObjectValue); + if (objectEntry is LoadExpressionEntry) + { + untypedObjectValue = CastToRawPointer(((LoadExpressionEntry)objectEntry).RawLLVMValue); + } + else + { + untypedObjectValue = LLVM.BuildAlloca(_builder, llvmObjectType, "objptr"); + LLVM.BuildStore(_builder, objectEntry.ValueAsType(llvmObjectType, _builder), untypedObjectValue); + untypedObjectValue = LLVM.BuildPointerCast(_builder, untypedObjectValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), "objptrcast"); + } + } + else + { + untypedObjectValue = objectEntry.ValueAsType(LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), _builder); + } + if (field.Offset.AsInt == 0) + { + return untypedObjectValue; } else { - typedObjectValue = objectEntry.LLVMValue; + var loadLocation = LLVM.BuildGEP(_builder, untypedObjectValue, + new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)field.Offset.AsInt, LLVMMisc.False) }, String.Empty); + return loadLocation; } - - var untypedObjectPointer = CastIfNecessary(typedObjectValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0)); - var loadLocation = LLVM.BuildGEP(_builder, untypedObjectPointer, - new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)field.Offset.AsInt, LLVMMisc.False) }, String.Empty); - return LLVM.BuildPointerCast(_builder, loadLocation, LLVM.PointerType(GetLLVMTypeForTypeDesc(field.FieldType), 0), "fieldaddresscast"); } private LLVMValueRef GetFieldAddress(FieldDesc field, bool isStatic) @@ -1429,8 +1615,7 @@ namespace Internal.IL if (!isStatic) _stack.Pop(); - LLVMValueRef untypedFieldAddress = WebAssemblyObjectWriter.EmitGlobal(Module, field, _compilation.NameMangler); - return LLVM.BuildPointerCast(_builder, untypedFieldAddress, LLVM.PointerType(GetLLVMTypeForTypeDesc(field.FieldType), 0), "tempfieldaddresscast"); + return WebAssemblyObjectWriter.EmitGlobal(Module, field, _compilation.NameMangler); } else { @@ -1442,26 +1627,22 @@ namespace Internal.IL { FieldDesc field = (FieldDesc)_methodIL.GetObject(token); LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic); - LLVMValueRef loadValue = LLVM.BuildLoad(_builder, fieldAddress, "ldfld_" + field.Name); - PushExpression(GetStackValueKind(field.FieldType), "ldfld", loadValue, field.FieldType); + PushLoadExpression(GetStackValueKind(field.FieldType), "ldfld_" + field.Name, fieldAddress, field.FieldType); } private void ImportAddressOfField(int token, bool isStatic) { FieldDesc field = (FieldDesc)_methodIL.GetObject(token); LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic); - PushExpression(StackValueKind.ByRef, "ldflda", fieldAddress, field.FieldType.MakePointerType()); + _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldflda", fieldAddress, field.FieldType.MakePointerType())); } private void ImportStoreField(int token, bool isStatic) { FieldDesc field = (FieldDesc)_methodIL.GetObject(token); StackEntry valueEntry = _stack.Pop(); - LLVMValueRef value = valueEntry.LLVMValue; - - value = CastIfNecessary(value, GetLLVMTypeForTypeDesc(field.FieldType)); LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic); - LLVM.BuildStore(_builder, value, fieldAddress); + CastingStore(fieldAddress, valueEntry, field.FieldType); } // Loads symbol address. Address is represented as a i32* @@ -1485,10 +1666,36 @@ namespace Internal.IL private void ImportInitObj(int token) { + TypeDesc type = ResolveTypeToken(token); + var valueEntry = _stack.Pop(); + var llvmType = GetLLVMTypeForTypeDesc(type); + if (llvmType.TypeKind == LLVMTypeKind.LLVMArrayTypeKind) + ImportCallMemset(valueEntry.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), 0, type.GetElementSize().AsInt); + else if (llvmType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind) + LLVM.BuildStore(_builder, LLVM.ConstInt(llvmType, 0, LLVMMisc.False), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder)); + else if (llvmType.TypeKind == LLVMTypeKind.LLVMPointerTypeKind) + LLVM.BuildStore(_builder, LLVM.ConstNull(llvmType), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder)); + else if (llvmType.TypeKind == LLVMTypeKind.LLVMFloatTypeKind) + LLVM.BuildStore(_builder, LLVM.ConstReal(llvmType, 0.0), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder)); + else + throw new NotImplementedException(); } private void ImportBox(int token) { + TypeDesc type = ResolveTypeToken(token); + if (type.IsValueType) + { + if (type.IsNullable) + throw new NotImplementedException(); + + var value = _stack.Pop(); + ExpressionEntry boxTarget = AllocateObject(type); + LLVMValueRef boxData = LLVM.BuildGEP(_builder, boxTarget.RawLLVMValue, new LLVMValueRef[] { BuildConstInt32(type.Context.Target.PointerSize) }, "boxData"); + LLVMValueRef typedBoxData = LLVM.BuildPointerCast(_builder, boxData, LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0), "typedBoxData"); + LLVM.BuildStore(_builder, value.ValueAsType(type, _builder), typedBoxData); + _stack.Push(boxTarget); + } } private void ImportLeave(BasicBlock target) @@ -1573,38 +1780,55 @@ namespace Internal.IL if (_stack.Length > 0) { entryStack = new EvaluationStack<StackEntry>(_stack.Length); - -#pragma warning disable 162 // Due to not implement3ed exception incrementer in for needs pragma warning disable for (int i = 0; i < _stack.Length; i++) { - // todo: do we need anything special for spilled stacks like cpp codegen does? - entryStack.Push(_stack[i]); - //entryStack.Push(NewSpillSlot(_stack[i])); + entryStack.Push(NewSpillSlot(_stack[i])); } -#pragma warning restore 162 } next.EntryStack = entryStack; } if (entryStack != null) { - // todo: do we have to do anything here? -#pragma warning disable 162// Due to not implement3ed exception incrementer in for needs pragma warning disable for (int i = 0; i < entryStack.Length; i++) { - /*AppendLine(); - Append(entryStack[i]); - Append(" = "); - Append(_stack[i]); - AppendSemicolon();*/ + var currentEntry = _stack[i]; + var entry = entryStack[i] as SpilledExpressionEntry; + if (entry == null) + throw new InvalidProgramException(); + + if (currentEntry is SpilledExpressionEntry) + continue; //this is already a sharable value + + StoreTemp(entry.LocalIndex, currentEntry.ValueAsType(entry.Type, _builder)); } -#pragma warning restore 162 } MarkBasicBlock(next); } + private void CallRuntimeExport(TypeSystemContext context, string methodName) + { + MetadataType helperType = context.SystemModule.GetKnownType("System.Runtime", "RuntimeExports"); + MethodDesc helperMethod = helperType.GetKnownMethod(methodName, null); + HandleCall(helperMethod); + } + + private StackEntry NewSpillSlot(StackEntry entry) + { + if (entry is SpilledExpressionEntry) + return entry; + else + { + var entryType = entry.Type ?? GetWellKnownType(WellKnownType.Object); //type is required here, currently the only time entry.Type is null is if someone has pushed a null literal + var entryIndex = _spilledExpressions.Count; + var newEntry = new SpilledExpressionEntry(entry.Kind, entry is ExpressionEntry ? ((ExpressionEntry)entry).Name : "spilled" + entryIndex, entryType, entryIndex, this); + _spilledExpressions.Add(newEntry); + return newEntry; + } + } + private TypeDesc ResolveTypeToken(int token) { return (TypeDesc)_methodIL.GetObject(token); diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs index 8a814508e..3a5f48117 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs @@ -101,7 +101,6 @@ namespace Internal.IL static LLVMValueRef TrapFunction = default(LLVMValueRef); static LLVMValueRef DoNothingFunction = default(LLVMValueRef); - private static IEnumerable<string> GetParameterNamesForMethod(MethodDesc method) { // TODO: The uses of this method need revision. The right way to get to this info is from diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs index 335157917..140e2b1bc 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs @@ -188,6 +188,17 @@ namespace ILCompiler.DependencyAnalysis //throw new NotImplementedException(); // This function isn't complete } + public static LLVMValueRef GetConstZeroArray(int length) + { + var int8Type = LLVM.Int8Type(); + var result = new LLVMValueRef[length]; + for (int i = 0; i < length; i++) + { + result[i] = LLVM.ConstInt(int8Type, 0, LLVMMisc.False); + } + return LLVM.ConstArray(int8Type, result); + } + public static LLVMValueRef EmitGlobal(LLVMModuleRef module, FieldDesc field, NameMangler nameMangler) { if (field.IsThreadStatic) @@ -203,7 +214,7 @@ namespace ILCompiler.DependencyAnalysis var valueType = LLVM.ArrayType(LLVM.Int8Type(), (uint)field.FieldType.GetElementSize().AsInt); var llvmValue = LLVM.AddGlobal(module, valueType, nameMangler.GetMangledFieldName(field).ToString()); LLVM.SetLinkage(llvmValue, LLVMLinkage.LLVMInternalLinkage); - LLVM.SetInitializer(llvmValue, LLVM.ConstPointerNull(valueType)); + LLVM.SetInitializer(llvmValue, GetConstZeroArray(field.FieldType.GetElementSize().AsInt)); s_staticFieldMapping.Add(field, llvmValue); return llvmValue; } @@ -262,7 +273,7 @@ namespace ILCompiler.DependencyAnalysis { LLVMValueRef valRef = IsFunction ? LLVM.GetNamedFunction(module, SymbolName) : LLVM.GetNamedGlobal(module, SymbolName); - if (Offset != 0) + if (Offset != 0 && valRef.Pointer != IntPtr.Zero) { var pointerType = LLVM.PointerType(LLVM.Int8Type(), 0); var bitCast = LLVM.ConstBitCast(valRef, pointerType); @@ -313,8 +324,16 @@ namespace ILCompiler.DependencyAnalysis if (ObjectSymbolRefs.TryGetValue(curOffset, out symbolRef)) { LLVMValueRef pointedAtValue = symbolRef.ToLLVMValueRef(module); - var ptrValue = LLVM.ConstBitCast(pointedAtValue, intPtrType); - entries.Add(ptrValue); + //TODO: why did this come back null + if (pointedAtValue.Pointer != IntPtr.Zero) + { + var ptrValue = LLVM.ConstBitCast(pointedAtValue, intPtrType); + entries.Add(ptrValue); + } + else + { + entries.Add(LLVM.ConstPointerNull(intPtrType)); + } } else { @@ -358,7 +377,6 @@ namespace ILCompiler.DependencyAnalysis _dataToFill.Add(new ObjectNodeDataEmission(arrayglobal, _currentObjectData.ToArray(), _currentObjectSymbolRefs)); - foreach (var symbolIdInfo in _symbolDefs) { EmitSymbolDef(arrayglobal, symbolIdInfo.Key, symbolIdInfo.Value); diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs index 039969de2..978e29f8e 100644 --- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs +++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs @@ -32,8 +32,8 @@ namespace ILCompiler.DependencyAnalysis protected override IMethodNode CreateUnboxingStubNode(MethodDesc method) { - // TODO: this is wrong: this returns an assembly stub node - return new UnboxingStubNode(method, Target); + // TODO: this is wrong: this returns an unstubbed node + return new WebAssemblyMethodCodeNode(method); } protected override ISymbolNode CreateReadyToRunHelperNode(ReadyToRunHelperKey helperCall) diff --git a/src/ILCompiler/ILCompiler.sln b/src/ILCompiler/ILCompiler.sln index 8008033a8..c210088aa 100644 --- a/src/ILCompiler/ILCompiler.sln +++ b/src/ILCompiler/ILCompiler.sln @@ -28,6 +28,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.WebAssembly", ". EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "desktop", "desktop\desktop.csproj", "{CE9781B1-0028-4039-A48C-8193F0D28467}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Build.Tasks", "..\ILCompiler.Build.Tasks\src\ILCompiler.Build.Tasks.csproj", "{44DE7F7B-AD73-40EA-87CC-554F2F57C38A}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\System.Private.CoreLib\shared\System.Private.CoreLib.Shared.projitems*{be95c560-b508-4588-8907-f9fc5bc1a0cf}*SharedItemsImports = 4 @@ -253,6 +255,26 @@ Global {CE9781B1-0028-4039-A48C-8193F0D28467}.Release|x64.Build.0 = Release|x64 {CE9781B1-0028-4039-A48C-8193F0D28467}.Release|x86.ActiveCfg = Release|Any CPU {CE9781B1-0028-4039-A48C-8193F0D28467}.Release|x86.Build.0 = Release|Any CPU + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|arm.ActiveCfg = Debug|arm + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|arm.Build.0 = Debug|arm + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|arm64.ActiveCfg = Debug|arm64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|arm64.Build.0 = Debug|arm64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|x64.ActiveCfg = Debug|x64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|x64.Build.0 = Debug|x64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|x86.ActiveCfg = Debug|x86 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Debug|x86.Build.0 = Debug|x86 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|Any CPU.Build.0 = Release|Any CPU + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|arm.ActiveCfg = Release|arm + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|arm.Build.0 = Release|arm + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|arm64.ActiveCfg = Release|arm64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|arm64.Build.0 = Release|arm64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|x64.ActiveCfg = Release|x64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|x64.Build.0 = Release|x64 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|x86.ActiveCfg = Release|x86 + {44DE7F7B-AD73-40EA-87CC-554F2F57C38A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ILVerify/src/AccessVerificationHelpers.cs b/src/ILVerify/src/AccessVerificationHelpers.cs index 37064f850..9274cad54 100644 --- a/src/ILVerify/src/AccessVerificationHelpers.cs +++ b/src/ILVerify/src/AccessVerificationHelpers.cs @@ -262,7 +262,7 @@ namespace ILVerify foreach (var attribute in assembly.GetDecodedCustomAttributes("System.Runtime.CompilerServices", "InternalsVisibleToAttribute")) { - var friendValues = ((string)attribute.FixedArguments[0].Value).Split(", "); + var friendValues = ((string)attribute.FixedArguments[0].Value).Split(new string[] { ", " }, StringSplitOptions.None); if (friendValues.Length >= 1 && friendValues.Length <= 2) { if (friendValues[0] != friendName.Name) diff --git a/src/ILVerify/src/ILVerify.csproj b/src/ILVerify/src/ILVerify.csproj index 73c0208a6..d07d962fa 100644 --- a/src/ILVerify/src/ILVerify.csproj +++ b/src/ILVerify/src/ILVerify.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFramework>netcoreapp2.0</TargetFramework> + <TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks> <CLSCompliant>false</CLSCompliant> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <EnableDefaultCompileItems>false</EnableDefaultCompileItems> @@ -294,7 +294,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="System.IO.MemoryMappedFiles" Version="4.0.0" /> + <PackageReference Include="System.IO.MemoryMappedFiles" Version="4.3.0" /> <PackageReference Include="System.Reflection.Metadata" Version="1.4.1" /> <PackageReference Include="System.CommandLine" Version="0.1.0-e160909-1" /> </ItemGroup> diff --git a/src/Native/Bootstrap/main.cpp b/src/Native/Bootstrap/main.cpp index bbeff8c9c..e3c1a2fc9 100644 --- a/src/Native/Bootstrap/main.cpp +++ b/src/Native/Bootstrap/main.cpp @@ -85,11 +85,12 @@ static char& __unbox_z = __stop___unbox; #endif // !CPPCODEGEN +// Do not warn that extern C methods throw exceptions. This is temporary +// as long as we have unimplemented/throwing APIs in this file. +#pragma warning(disable:4297) #ifdef CPPCODEGEN -#pragma warning(disable:4297) - extern "C" Object * RhNewObject(MethodTable * pMT); extern "C" Object * RhNewArray(MethodTable * pMT, int32_t elements); extern "C" void * RhTypeCast_IsInstanceOf(void * pObject, MethodTable * pMT); @@ -238,15 +239,18 @@ extern "C" void RhpUniversalTransition_DebugStepTailCall() { throw "RhpUniversalTransition_DebugStepTailCall"; } -extern "C" void CCWAddRef() -{ - throw "CCWAddRef"; -} void* RtRHeaderWrapper(); #endif // CPPCODEGEN +// This works around System.Private.Interop's references to Interop.Native. +// This won't be needed once we stop dragging in S.P.Interop for basic p/invoke support. +extern "C" void CCWAddRef() +{ + throw "CCWAddRef"; +} + extern "C" void __fail_fast() { // TODO: FailFast diff --git a/src/Native/CMakeLists.txt b/src/Native/CMakeLists.txt index 5aeb930a5..e77b1b6f4 100644 --- a/src/Native/CMakeLists.txt +++ b/src/Native/CMakeLists.txt @@ -224,6 +224,7 @@ if(WIN32) add_compile_options($<$<CONFIG:Debug>:-DDEBUG>) add_compile_options($<$<CONFIG:Debug>:/MTd>) add_compile_options($<$<CONFIG:Release>:/MT>) + add_compile_options(/source-charset:utf-8) # Force MSVC to compile source as UTF-8. add_compile_options(/Zi) # enable debugging information set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG") diff --git a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec new file mode 100644 index 000000000..f3421bb32 --- /dev/null +++ b/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<package > + <metadata> + <id>Microsoft.DotNet.ObjectWriter</id> + <version>1.0.19-prerelease-00001</version> + <title>Microsoft .NET Object File Generator</title> + <authors>Microsoft</authors> + <owners>Microsoft</owners> + <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> + <projectUrl>https://github.com/dotnet/corert</projectUrl> + <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> + <requireLicenseAcceptance>true</requireLicenseAcceptance> + <description>Provides object writer to the managed to native code-generator.</description> + <releaseNotes>Initial release</releaseNotes> + <copyright>Copyright © Microsoft Corporation</copyright> + </metadata> + <files> + <file src="runtime.json" /> + </files> +</package> diff --git a/src/Native/ObjWriter/.nuget/runtime.json b/src/Native/ObjWriter/.nuget/runtime.json new file mode 100644 index 000000000..c9c5b8e6b --- /dev/null +++ b/src/Native/ObjWriter/.nuget/runtime.json @@ -0,0 +1,19 @@ +{ + "runtimes": { + "win7-x64": { + "Microsoft.DotNet.ObjectWriter": { + "toolchain.win7-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001" + } + }, + "ubuntu.14.04-x64": { + "Microsoft.DotNet.ObjectWriter": { + "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001" + } + }, + "osx.10.10-x64": { + "Microsoft.DotNet.ObjectWriter": { + "toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001" + } + } + } +} diff --git a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec new file mode 100644 index 000000000..7a571beaf --- /dev/null +++ b/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<package > + <metadata> + <id>toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter</id> + <version>1.0.19-prerelease-00001</version> + <title>Microsoft .NET Object File Generator</title> + <authors>Microsoft</authors> + <owners>Microsoft</owners> + <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> + <projectUrl>https://github.com/dotnet/corert</projectUrl> + <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> + <requireLicenseAcceptance>true</requireLicenseAcceptance> + <description>Provides object writer to the managed to native code-generator.</description> + <releaseNotes>Initial release</releaseNotes> + <copyright>Copyright © Microsoft Corporation</copyright> + </metadata> + <files> + <file src="../libobjwriter.dylib" target="runtimes/osx.10.10-x64/native/libobjwriter.dylib" /> + </files> +</package> diff --git a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec new file mode 100644 index 000000000..fd9c514c6 --- /dev/null +++ b/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<package > + <metadata> + <id>toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter</id> + <version>1.0.19-prerelease-00001</version> + <title>Microsoft .NET Object File Generator</title> + <authors>Microsoft</authors> + <owners>Microsoft</owners> + <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> + <projectUrl>https://github.com/dotnet/corert</projectUrl> + <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> + <requireLicenseAcceptance>true</requireLicenseAcceptance> + <description>Provides object writer to the managed to native code-generator.</description> + <releaseNotes>Initial release</releaseNotes> + <copyright>Copyright © Microsoft Corporation</copyright> + </metadata> + <files> + <file src="../libobjwriter.so" target="runtimes/ubuntu.14.04-x64/native/libobjwriter.so" /> + </files> +</package> diff --git a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec new file mode 100644 index 000000000..a54cdc230 --- /dev/null +++ b/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<package > + <metadata> + <id>toolchain.win7-x64.Microsoft.DotNet.ObjectWriter</id> + <version>1.0.19-prerelease-00001</version> + <title>Microsoft .NET Object File Generator</title> + <authors>Microsoft</authors> + <owners>Microsoft</owners> + <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> + <projectUrl>https://github.com/dotnet/corert</projectUrl> + <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> + <requireLicenseAcceptance>true</requireLicenseAcceptance> + <description>Provides object writer to the managed to native code-generator.</description> + <releaseNotes>Initial release</releaseNotes> + <copyright>Copyright © Microsoft Corporation</copyright> + </metadata> + <files> + <file src="..\objwriter.dll" target="runtimes\win7-x64\native\objwriter.dll" /> + </files> +</package> diff --git a/src/Native/ObjWriter/CMakeLists.txt b/src/Native/ObjWriter/CMakeLists.txt new file mode 100644 index 000000000..ead1db75b --- /dev/null +++ b/src/Native/ObjWriter/CMakeLists.txt @@ -0,0 +1,41 @@ +project(objwriter) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti") +include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(.) +add_definitions(${LLVM_DEFINITIONS}) + +if (WIN32) + # Create .def file containing a list of exports preceeded by + # 'EXPORTS'. The file "objwriter.exports" already contains the list, so we + # massage it into the correct format here to create "objwriter.exports.def". + set(OBJWRITER_EXPORTS_DEF ${CMAKE_CURRENT_BINARY_DIR}/objwriter.exports.def) + set(OBJWRITER_EXPORTS_DEF_TEMP ${OBJWRITER_EXPORTS_DEF}.txt) + file(READ "objwriter.exports" exports_list) + file(WRITE ${OBJWRITER_EXPORTS_DEF_TEMP} "LIBRARY OBJWRITER\n") + file(APPEND ${OBJWRITER_EXPORTS_DEF_TEMP} "EXPORTS\n") + file(APPEND ${OBJWRITER_EXPORTS_DEF_TEMP} ${exports_list}) + # Copy the file only if it has changed. + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${OBJWRITER_EXPORTS_DEF_TEMP} ${OBJWRITER_EXPORTS_DEF}) +endif() + +# Now build our tools +add_library(objwriter + SHARED + objwriter.cpp + typeBuilder.cpp + objwriter.h # Visual Studio generator doesn't include necessary header files into the project automatically + typeBuilder.h + ${OBJWRITER_EXPORTS_DEF} +) + +# Find the libraries that correspond to the LLVM components +# that we wish to use +llvm_map_components_to_libnames(llvm_libs + ${LLVM_TARGETS_TO_BUILD} +) + +# Link against LLVM libraries +target_link_libraries(objwriter +${llvm_libs}) diff --git a/src/Native/ObjWriter/cfi.h b/src/Native/ObjWriter/cfi.h new file mode 100644 index 000000000..fc359acd3 --- /dev/null +++ b/src/Native/ObjWriter/cfi.h @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Keep in sync with https://github.com/dotnet/coreclr/blob/master/src/inc/cfi.h +// + +#ifndef CFI_H_ +#define CFI_H_ + +#define DWARF_REG_ILLEGAL -1 +enum CFI_OPCODE +{ + CFI_ADJUST_CFA_OFFSET, // Offset is adjusted relative to the current one. + CFI_DEF_CFA_REGISTER, // New register is used to compute CFA + CFI_REL_OFFSET // Register is saved at offset from the current CFA +}; + +struct CFI_CODE +{ + unsigned char CodeOffset;// Offset from the start of code the frame covers. + unsigned char CfiOpCode; + short DwarfReg; // Dwarf register number. 0~32 for x64. + int Offset; + CFI_CODE(unsigned char codeOffset, unsigned char cfiOpcode, + short dwarfReg, int offset) + : CodeOffset(codeOffset) + , CfiOpCode(cfiOpcode) + , DwarfReg(dwarfReg) + , Offset(offset) + {} +}; +typedef CFI_CODE* PCFI_CODE; + +#endif // CFI_H + diff --git a/src/Native/ObjWriter/cordebuginfo.h b/src/Native/ObjWriter/cordebuginfo.h new file mode 100644 index 000000000..1ed430a11 --- /dev/null +++ b/src/Native/ObjWriter/cordebuginfo.h @@ -0,0 +1,327 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Keep in sync with https://github.com/dotnet/coreclr/blob/master/src/inc/cordebuginfo.h +// + +/**********************************************************************************/ +// DebugInfo types shared by JIT-EE interface and EE-Debugger interface + +class ICorDebugInfo +{ +public: + /*----------------------------- Boundary-info ---------------------------*/ + + enum MappingTypes + { + NO_MAPPING = -1, + PROLOG = -2, + EPILOG = -3, + MAX_MAPPING_VALUE = -3 // Sentinal value. This should be set to the largest magnitude value in the enum + // so that the compression routines know the enum's range. + }; + + enum BoundaryTypes + { + NO_BOUNDARIES = 0x00, // No implicit boundaries + STACK_EMPTY_BOUNDARIES = 0x01, // Boundary whenever the IL evaluation stack is empty + NOP_BOUNDARIES = 0x02, // Before every CEE_NOP instruction + CALL_SITE_BOUNDARIES = 0x04, // Before every CEE_CALL, CEE_CALLVIRT, etc instruction + + // Set of boundaries that debugger should always reasonably ask the JIT for. + DEFAULT_BOUNDARIES = STACK_EMPTY_BOUNDARIES | NOP_BOUNDARIES | CALL_SITE_BOUNDARIES + }; + + // Note that SourceTypes can be OR'd together - it's possible that + // a sequence point will also be a stack_empty point, and/or a call site. + // The debugger will check to see if a boundary offset's source field & + // SEQUENCE_POINT is true to determine if the boundary is a sequence point. + + enum SourceTypes + { + SOURCE_TYPE_INVALID = 0x00, // To indicate that nothing else applies + SEQUENCE_POINT = 0x01, // The debugger asked for it. + STACK_EMPTY = 0x02, // The stack is empty here + CALL_SITE = 0x04, // This is a call site. + NATIVE_END_OFFSET_UNKNOWN = 0x08, // Indicates a epilog endpoint + CALL_INSTRUCTION = 0x10 // The actual instruction of a call. + + }; + + struct OffsetMapping + { + DWORD nativeOffset; + DWORD ilOffset; + SourceTypes source; // The debugger needs this so that + // we don't put Edit and Continue breakpoints where + // the stack isn't empty. We can put regular breakpoints + // there, though, so we need a way to discriminate + // between offsets. + }; + + /*------------------------------ Var-info -------------------------------*/ + + // Note: The debugger needs to target register numbers on platforms other than which the debugger itself + // is running. To this end it maintains its own values for REGNUM_SP and REGNUM_AMBIENT_SP across multiple + // platforms. So any change here that may effect these values should be reflected in the definitions + // contained in debug/inc/DbgIPCEvents.h. + enum RegNum + { +#ifdef _TARGET_X86_ + REGNUM_EAX, + REGNUM_ECX, + REGNUM_EDX, + REGNUM_EBX, + REGNUM_ESP, + REGNUM_EBP, + REGNUM_ESI, + REGNUM_EDI, +#elif _TARGET_ARM_ + REGNUM_R0, + REGNUM_R1, + REGNUM_R2, + REGNUM_R3, + REGNUM_R4, + REGNUM_R5, + REGNUM_R6, + REGNUM_R7, + REGNUM_R8, + REGNUM_R9, + REGNUM_R10, + REGNUM_R11, + REGNUM_R12, + REGNUM_SP, + REGNUM_LR, + REGNUM_PC, +#elif _TARGET_ARM64_ + REGNUM_X0, + REGNUM_X1, + REGNUM_X2, + REGNUM_X3, + REGNUM_X4, + REGNUM_X5, + REGNUM_X6, + REGNUM_X7, + REGNUM_X8, + REGNUM_X9, + REGNUM_X10, + REGNUM_X11, + REGNUM_X12, + REGNUM_X13, + REGNUM_X14, + REGNUM_X15, + REGNUM_X16, + REGNUM_X17, + REGNUM_X18, + REGNUM_X19, + REGNUM_X20, + REGNUM_X21, + REGNUM_X22, + REGNUM_X23, + REGNUM_X24, + REGNUM_X25, + REGNUM_X26, + REGNUM_X27, + REGNUM_X28, + REGNUM_FP, + REGNUM_LR, + REGNUM_SP, + REGNUM_PC, +#elif _TARGET_AMD64_ + REGNUM_RAX, + REGNUM_RCX, + REGNUM_RDX, + REGNUM_RBX, + REGNUM_RSP, + REGNUM_RBP, + REGNUM_RSI, + REGNUM_RDI, + REGNUM_R8, + REGNUM_R9, + REGNUM_R10, + REGNUM_R11, + REGNUM_R12, + REGNUM_R13, + REGNUM_R14, + REGNUM_R15, +#else + PORTABILITY_WARNING("Register numbers not defined on this platform") +#endif + REGNUM_COUNT, + REGNUM_AMBIENT_SP, // ambient SP support. Ambient SP is the original SP in the non-BP based frame. + // Ambient SP should not change even if there are push/pop operations in the method. + +#ifdef _TARGET_X86_ + REGNUM_FP = REGNUM_EBP, + REGNUM_SP = REGNUM_ESP, +#elif _TARGET_AMD64_ + REGNUM_SP = REGNUM_RSP, +#elif _TARGET_ARM_ +#ifdef REDHAWK + REGNUM_FP = REGNUM_R7, +#else + REGNUM_FP = REGNUM_R11, +#endif //REDHAWK +#elif _TARGET_ARM64_ + //Nothing to do here. FP is already alloted. +#else + // RegNum values should be properly defined for this platform + REGNUM_FP = 0, + REGNUM_SP = 1, +#endif + + }; + + // VarLoc describes the location of a native variable. Note that currently, VLT_REG_BYREF and VLT_STK_BYREF + // are only used for value types on X64. + + enum VarLocType + { + VLT_REG, // variable is in a register + VLT_REG_BYREF, // address of the variable is in a register + VLT_REG_FP, // variable is in an fp register + VLT_STK, // variable is on the stack (memory addressed relative to the frame-pointer) + VLT_STK_BYREF, // address of the variable is on the stack (memory addressed relative to the frame-pointer) + VLT_REG_REG, // variable lives in two registers + VLT_REG_STK, // variable lives partly in a register and partly on the stack + VLT_STK_REG, // reverse of VLT_REG_STK + VLT_STK2, // variable lives in two slots on the stack + VLT_FPSTK, // variable lives on the floating-point stack + VLT_FIXED_VA, // variable is a fixed argument in a varargs function (relative to VARARGS_HANDLE) + + VLT_COUNT, + VLT_INVALID, + }; + + struct VarLoc + { + VarLocType vlType; + + union + { + // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc) + // eg. EAX + // VLT_REG_BYREF -- the specified register contains the address of the variable + // eg. [EAX] + + struct + { + RegNum vlrReg; + } vlReg; + + // VLT_STK -- Any 32 bit value which is on the stack + // eg. [ESP+0x20], or [EBP-0x28] + // VLT_STK_BYREF -- the specified stack location contains the address of the variable + // eg. mov EAX, [ESP+0x20]; [EAX] + + struct + { + RegNum vlsBaseReg; + signed vlsOffset; + } vlStk; + + // VLT_REG_REG -- TYP_LONG with both DWords enregistred + // eg. RBM_EAXEDX + + struct + { + RegNum vlrrReg1; + RegNum vlrrReg2; + } vlRegReg; + + // VLT_REG_STK -- Partly enregistered TYP_LONG + // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] } + + struct + { + RegNum vlrsReg; + struct + { + RegNum vlrssBaseReg; + signed vlrssOffset; + } vlrsStk; + } vlRegStk; + + // VLT_STK_REG -- Partly enregistered TYP_LONG + // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX } + + struct + { + struct + { + RegNum vlsrsBaseReg; + signed vlsrsOffset; + } vlsrStk; + RegNum vlsrReg; + } vlStkReg; + + // VLT_STK2 -- Any 64 bit value which is on the stack, + // in 2 successsive DWords. + // eg 2 DWords at [ESP+0x10] + + struct + { + RegNum vls2BaseReg; + signed vls2Offset; + } vlStk2; + + // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack) + // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk") + + struct + { + unsigned vlfReg; + } vlFPstk; + + // VLT_FIXED_VA -- fixed argument of a varargs function. + // The argument location depends on the size of the variable + // arguments (...). Inspecting the VARARGS_HANDLE indicates the + // location of the first arg. This argument can then be accessed + // relative to the position of the first arg + + struct + { + unsigned vlfvOffset; + } vlFixedVarArg; + + // VLT_MEMORY + + struct + { + void *rpValue; // pointer to the in-process + // location of the value. + } vlMemory; + }; + }; + + // This is used to report implicit/hidden arguments + + enum + { + VARARGS_HND_ILNUM = -1, // Value for the CORINFO_VARARGS_HANDLE varNumber + RETBUF_ILNUM = -2, // Pointer to the return-buffer + TYPECTXT_ILNUM = -3, // ParamTypeArg for CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG + + UNKNOWN_ILNUM = -4, // Unknown variable + + MAX_ILNUM = -4 // Sentinal value. This should be set to the largest magnitude value in th enum + // so that the compression routines know the enum's range. + }; + + struct ILVarInfo + { + DWORD startOffset; + DWORD endOffset; + DWORD varNumber; + }; + + struct NativeVarInfo + { + DWORD startOffset; + DWORD endOffset; + DWORD varNumber; + VarLoc loc; + }; +}; diff --git a/src/Native/ObjWriter/cvconst.h b/src/Native/ObjWriter/cvconst.h new file mode 100644 index 000000000..5c4f2569e --- /dev/null +++ b/src/Native/ObjWriter/cvconst.h @@ -0,0 +1,3716 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +// cvconst.h - codeview constant definitions +//----------------------------------------------------------------- +// +// Copyright Microsoft Corporation. All Rights Reserved. +// +//--------------------------------------------------------------- +#ifndef _CVCONST_H_ +#define _CVCONST_H_ + +// Enumeration for function call type + +typedef enum CV_call_e { + CV_CALL_NEAR_C = 0x00, // near right to left push, caller pops stack + CV_CALL_FAR_C = 0x01, // far right to left push, caller pops stack + CV_CALL_NEAR_PASCAL = 0x02, // near left to right push, callee pops stack + CV_CALL_FAR_PASCAL = 0x03, // far left to right push, callee pops stack + CV_CALL_NEAR_FAST = + 0x04, // near left to right push with regs, callee pops stack + CV_CALL_FAR_FAST = + 0x05, // far left to right push with regs, callee pops stack + CV_CALL_SKIPPED = 0x06, // skipped (unused) call index + CV_CALL_NEAR_STD = 0x07, // near standard call + CV_CALL_FAR_STD = 0x08, // far standard call + CV_CALL_NEAR_SYS = 0x09, // near sys call + CV_CALL_FAR_SYS = 0x0a, // far sys call + CV_CALL_THISCALL = 0x0b, // this call (this passed in register) + CV_CALL_MIPSCALL = 0x0c, // Mips call + CV_CALL_GENERIC = 0x0d, // Generic call sequence + CV_CALL_ALPHACALL = 0x0e, // Alpha call + CV_CALL_PPCCALL = 0x0f, // PPC call + CV_CALL_SHCALL = 0x10, // Hitachi SuperH call + CV_CALL_ARMCALL = 0x11, // ARM call + CV_CALL_AM33CALL = 0x12, // AM33 call + CV_CALL_TRICALL = 0x13, // TriCore Call + CV_CALL_SH5CALL = 0x14, // Hitachi SuperH-5 call + CV_CALL_M32RCALL = 0x15, // M32R Call + CV_CALL_CLRCALL = 0x16, // clr call + CV_CALL_INLINE = + 0x17, // Marker for routines always inlined and thus lacking a convention + CV_CALL_NEAR_VECTOR = + 0x18, // near left to right push with regs, callee pops stack + CV_CALL_RESERVED = 0x19 // first unused call enumeration + + // Do NOT add any more machine specific conventions. This is to be used for + // calling conventions in the source only (e.g. __cdecl, __stdcall). +} CV_call_e; + +// Values for the access protection of class attributes + +typedef enum CV_access_e { + CV_private = 1, + CV_protected = 2, + CV_public = 3 +} CV_access_e; + +typedef enum THUNK_ORDINAL { + THUNK_ORDINAL_NOTYPE, // standard thunk + THUNK_ORDINAL_ADJUSTOR, // "this" adjustor thunk + THUNK_ORDINAL_VCALL, // virtual call thunk + THUNK_ORDINAL_PCODE, // pcode thunk + THUNK_ORDINAL_LOAD, // thunk which loads the address to jump to + // via unknown means... + + // trampoline thunk ordinals - only for use in Trampoline thunk symbols + THUNK_ORDINAL_TRAMP_INCREMENTAL, + THUNK_ORDINAL_TRAMP_BRANCHISLAND, + +} THUNK_ORDINAL; + +enum CV_SourceChksum_t { + CHKSUM_TYPE_NONE = 0, // indicates no checksum is available + CHKSUM_TYPE_MD5, + CHKSUM_TYPE_SHA1, + CHKSUM_TYPE_SHA_256, +}; + +// +// DIA enums +// + +enum SymTagEnum { + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagCallSite, + SymTagInlineSite, + SymTagBaseInterface, + SymTagVectorType, + SymTagMatrixType, + SymTagHLSLType, + SymTagCaller, + SymTagCallee, + SymTagExport, + SymTagHeapAllocationSite, + SymTagCoffGroup, + SymTagMax +}; + +enum LocationType { + LocIsNull, + LocIsStatic, + LocIsTLS, + LocIsRegRel, + LocIsThisRel, + LocIsEnregistered, + LocIsBitField, + LocIsSlot, + LocIsIlRel, + LocInMetaData, + LocIsConstant, + LocTypeMax +}; + +enum DataKind { + DataIsUnknown, + DataIsLocal, + DataIsStaticLocal, + DataIsParam, + DataIsObjectPtr, + DataIsFileStatic, + DataIsGlobal, + DataIsMember, + DataIsStaticMember, + DataIsConstant +}; + +enum UdtKind { UdtStruct, UdtClass, UdtUnion, UdtInterface }; + +enum BasicType { + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31, + btChar16 = 32, // char16_t + btChar32 = 33, // char32_t +}; + +// enumeration for type modifier values + +typedef enum CV_modifier_e { + // 0x0000 - 0x01ff - Reserved. + + CV_MOD_INVALID = 0x0000, + + // Standard modifiers. + + CV_MOD_CONST = 0x0001, + CV_MOD_VOLATILE = 0x0002, + CV_MOD_UNALIGNED = 0x0003, + + // 0x0200 - 0x03ff - HLSL modifiers. + + CV_MOD_HLSL_UNIFORM = 0x0200, + CV_MOD_HLSL_LINE = 0x0201, + CV_MOD_HLSL_TRIANGLE = 0x0202, + CV_MOD_HLSL_LINEADJ = 0x0203, + CV_MOD_HLSL_TRIANGLEADJ = 0x0204, + CV_MOD_HLSL_LINEAR = 0x0205, + CV_MOD_HLSL_CENTROID = 0x0206, + CV_MOD_HLSL_CONSTINTERP = 0x0207, + CV_MOD_HLSL_NOPERSPECTIVE = 0x0208, + CV_MOD_HLSL_SAMPLE = 0x0209, + CV_MOD_HLSL_CENTER = 0x020a, + CV_MOD_HLSL_SNORM = 0x020b, + CV_MOD_HLSL_UNORM = 0x020c, + CV_MOD_HLSL_PRECISE = 0x020d, + CV_MOD_HLSL_UAV_GLOBALLY_COHERENT = 0x020e, + + // 0x0400 - 0xffff - Unused. + +} CV_modifier_e; + +// built-in type kinds + +typedef enum CV_builtin_e { + + // 0x0000 - 0x01ff - Reserved. + CV_BI_INVALID = 0x0000, + + // 0x0200 - 0x03ff - HLSL types. + + CV_BI_HLSL_INTERFACE_POINTER = 0x0200, + CV_BI_HLSL_TEXTURE1D = 0x0201, + CV_BI_HLSL_TEXTURE1D_ARRAY = 0x0202, + CV_BI_HLSL_TEXTURE2D = 0x0203, + CV_BI_HLSL_TEXTURE2D_ARRAY = 0x0204, + CV_BI_HLSL_TEXTURE3D = 0x0205, + CV_BI_HLSL_TEXTURECUBE = 0x0206, + CV_BI_HLSL_TEXTURECUBE_ARRAY = 0x0207, + CV_BI_HLSL_TEXTURE2DMS = 0x0208, + CV_BI_HLSL_TEXTURE2DMS_ARRAY = 0x0209, + CV_BI_HLSL_SAMPLER = 0x020a, + CV_BI_HLSL_SAMPLERCOMPARISON = 0x020b, + CV_BI_HLSL_BUFFER = 0x020c, + CV_BI_HLSL_POINTSTREAM = 0x020d, + CV_BI_HLSL_LINESTREAM = 0x020e, + CV_BI_HLSL_TRIANGLESTREAM = 0x020f, + CV_BI_HLSL_INPUTPATCH = 0x0210, + CV_BI_HLSL_OUTPUTPATCH = 0x0211, + CV_BI_HLSL_RWTEXTURE1D = 0x0212, + CV_BI_HLSL_RWTEXTURE1D_ARRAY = 0x0213, + CV_BI_HLSL_RWTEXTURE2D = 0x0214, + CV_BI_HLSL_RWTEXTURE2D_ARRAY = 0x0215, + CV_BI_HLSL_RWTEXTURE3D = 0x0216, + CV_BI_HLSL_RWBUFFER = 0x0217, + CV_BI_HLSL_BYTEADDRESS_BUFFER = 0x0218, + CV_BI_HLSL_RWBYTEADDRESS_BUFFER = 0x0219, + CV_BI_HLSL_STRUCTURED_BUFFER = 0x021a, + CV_BI_HLSL_RWSTRUCTURED_BUFFER = 0x021b, + CV_BI_HLSL_APPEND_STRUCTURED_BUFFER = 0x021c, + CV_BI_HLSL_CONSUME_STRUCTURED_BUFFER = 0x021d, + CV_BI_HLSL_MIN8FLOAT = 0x021e, + CV_BI_HLSL_MIN10FLOAT = 0x021f, + CV_BI_HLSL_MIN16FLOAT = 0x0220, + CV_BI_HLSL_MIN12INT = 0x0221, + CV_BI_HLSL_MIN16INT = 0x0222, + CV_BI_HLSL_MIN16UINT = 0x0223, + + // 0x0400 - 0xffff - Unused. + +} CV_builtin_e; + +// enum describing the compile flag source language + +typedef enum CV_CFL_LANG { + CV_CFL_C = 0x00, + CV_CFL_CXX = 0x01, + CV_CFL_FORTRAN = 0x02, + CV_CFL_MASM = 0x03, + CV_CFL_PASCAL = 0x04, + CV_CFL_BASIC = 0x05, + CV_CFL_COBOL = 0x06, + CV_CFL_LINK = 0x07, + CV_CFL_CVTRES = 0x08, + CV_CFL_CVTPGD = 0x09, + CV_CFL_CSHARP = 0x0A, // C# + CV_CFL_VB = 0x0B, // Visual Basic + CV_CFL_ILASM = 0x0C, // IL (as in CLR) ASM + CV_CFL_JAVA = 0x0D, + CV_CFL_JSCRIPT = 0x0E, + CV_CFL_MSIL = 0x0F, // Unknown MSIL (LTCG of .NETMODULE) + CV_CFL_HLSL = 0x10, // High Level Shader Language +} CV_CFL_LANG; + +// enum describing target processor + +typedef enum CV_CPU_TYPE_e { + CV_CFL_8080 = 0x00, + CV_CFL_8086 = 0x01, + CV_CFL_80286 = 0x02, + CV_CFL_80386 = 0x03, + CV_CFL_80486 = 0x04, + CV_CFL_PENTIUM = 0x05, + CV_CFL_PENTIUMII = 0x06, + CV_CFL_PENTIUMPRO = CV_CFL_PENTIUMII, + CV_CFL_PENTIUMIII = 0x07, + CV_CFL_MIPS = 0x10, + CV_CFL_MIPSR4000 = CV_CFL_MIPS, // don't break current code + CV_CFL_MIPS16 = 0x11, + CV_CFL_MIPS32 = 0x12, + CV_CFL_MIPS64 = 0x13, + CV_CFL_MIPSI = 0x14, + CV_CFL_MIPSII = 0x15, + CV_CFL_MIPSIII = 0x16, + CV_CFL_MIPSIV = 0x17, + CV_CFL_MIPSV = 0x18, + CV_CFL_M68000 = 0x20, + CV_CFL_M68010 = 0x21, + CV_CFL_M68020 = 0x22, + CV_CFL_M68030 = 0x23, + CV_CFL_M68040 = 0x24, + CV_CFL_ALPHA = 0x30, + CV_CFL_ALPHA_21064 = 0x30, + CV_CFL_ALPHA_21164 = 0x31, + CV_CFL_ALPHA_21164A = 0x32, + CV_CFL_ALPHA_21264 = 0x33, + CV_CFL_ALPHA_21364 = 0x34, + CV_CFL_PPC601 = 0x40, + CV_CFL_PPC603 = 0x41, + CV_CFL_PPC604 = 0x42, + CV_CFL_PPC620 = 0x43, + CV_CFL_PPCFP = 0x44, + CV_CFL_PPCBE = 0x45, + CV_CFL_SH3 = 0x50, + CV_CFL_SH3E = 0x51, + CV_CFL_SH3DSP = 0x52, + CV_CFL_SH4 = 0x53, + CV_CFL_SHMEDIA = 0x54, + CV_CFL_ARM3 = 0x60, + CV_CFL_ARM4 = 0x61, + CV_CFL_ARM4T = 0x62, + CV_CFL_ARM5 = 0x63, + CV_CFL_ARM5T = 0x64, + CV_CFL_ARM6 = 0x65, + CV_CFL_ARM_XMAC = 0x66, + CV_CFL_ARM_WMMX = 0x67, + CV_CFL_ARM7 = 0x68, + CV_CFL_OMNI = 0x70, + CV_CFL_IA64 = 0x80, + CV_CFL_IA64_1 = 0x80, + CV_CFL_IA64_2 = 0x81, + CV_CFL_CEE = 0x90, + CV_CFL_AM33 = 0xA0, + CV_CFL_M32R = 0xB0, + CV_CFL_TRICORE = 0xC0, + CV_CFL_X64 = 0xD0, + CV_CFL_AMD64 = CV_CFL_X64, + CV_CFL_EBC = 0xE0, + CV_CFL_THUMB = 0xF0, + CV_CFL_ARMNT = 0xF4, + CV_CFL_ARM64 = 0xF6, + CV_CFL_D3D11_SHADER = 0x100, +} CV_CPU_TYPE_e; + +typedef enum CV_HREG_e { + // Register subset shared by all processor types, + // must not overlap with any of the ranges below, hence the high values + + CV_ALLREG_ERR = 30000, + CV_ALLREG_TEB = 30001, + CV_ALLREG_TIMER = 30002, + CV_ALLREG_EFAD1 = 30003, + CV_ALLREG_EFAD2 = 30004, + CV_ALLREG_EFAD3 = 30005, + CV_ALLREG_VFRAME = 30006, + CV_ALLREG_HANDLE = 30007, + CV_ALLREG_PARAMS = 30008, + CV_ALLREG_LOCALS = 30009, + CV_ALLREG_TID = 30010, + CV_ALLREG_ENV = 30011, + CV_ALLREG_CMDLN = 30012, + + // Register set for the Intel 80x86 and ix86 processor series + // (plus PCODE registers) + + CV_REG_NONE = 0, + CV_REG_AL = 1, + CV_REG_CL = 2, + CV_REG_DL = 3, + CV_REG_BL = 4, + CV_REG_AH = 5, + CV_REG_CH = 6, + CV_REG_DH = 7, + CV_REG_BH = 8, + CV_REG_AX = 9, + CV_REG_CX = 10, + CV_REG_DX = 11, + CV_REG_BX = 12, + CV_REG_SP = 13, + CV_REG_BP = 14, + CV_REG_SI = 15, + CV_REG_DI = 16, + CV_REG_EAX = 17, + CV_REG_ECX = 18, + CV_REG_EDX = 19, + CV_REG_EBX = 20, + CV_REG_ESP = 21, + CV_REG_EBP = 22, + CV_REG_ESI = 23, + CV_REG_EDI = 24, + CV_REG_ES = 25, + CV_REG_CS = 26, + CV_REG_SS = 27, + CV_REG_DS = 28, + CV_REG_FS = 29, + CV_REG_GS = 30, + CV_REG_IP = 31, + CV_REG_FLAGS = 32, + CV_REG_EIP = 33, + CV_REG_EFLAGS = 34, + CV_REG_TEMP = 40, // PCODE Temp + CV_REG_TEMPH = 41, // PCODE TempH + CV_REG_QUOTE = 42, // PCODE Quote + CV_REG_PCDR3 = 43, // PCODE reserved + CV_REG_PCDR4 = 44, // PCODE reserved + CV_REG_PCDR5 = 45, // PCODE reserved + CV_REG_PCDR6 = 46, // PCODE reserved + CV_REG_PCDR7 = 47, // PCODE reserved + CV_REG_CR0 = 80, // CR0 -- control registers + CV_REG_CR1 = 81, + CV_REG_CR2 = 82, + CV_REG_CR3 = 83, + CV_REG_CR4 = 84, // Pentium + CV_REG_DR0 = 90, // Debug register + CV_REG_DR1 = 91, + CV_REG_DR2 = 92, + CV_REG_DR3 = 93, + CV_REG_DR4 = 94, + CV_REG_DR5 = 95, + CV_REG_DR6 = 96, + CV_REG_DR7 = 97, + CV_REG_GDTR = 110, + CV_REG_GDTL = 111, + CV_REG_IDTR = 112, + CV_REG_IDTL = 113, + CV_REG_LDTR = 114, + CV_REG_TR = 115, + + CV_REG_PSEUDO1 = 116, + CV_REG_PSEUDO2 = 117, + CV_REG_PSEUDO3 = 118, + CV_REG_PSEUDO4 = 119, + CV_REG_PSEUDO5 = 120, + CV_REG_PSEUDO6 = 121, + CV_REG_PSEUDO7 = 122, + CV_REG_PSEUDO8 = 123, + CV_REG_PSEUDO9 = 124, + + CV_REG_ST0 = 128, + CV_REG_ST1 = 129, + CV_REG_ST2 = 130, + CV_REG_ST3 = 131, + CV_REG_ST4 = 132, + CV_REG_ST5 = 133, + CV_REG_ST6 = 134, + CV_REG_ST7 = 135, + CV_REG_CTRL = 136, + CV_REG_STAT = 137, + CV_REG_TAG = 138, + CV_REG_FPIP = 139, + CV_REG_FPCS = 140, + CV_REG_FPDO = 141, + CV_REG_FPDS = 142, + CV_REG_ISEM = 143, + CV_REG_FPEIP = 144, + CV_REG_FPEDO = 145, + + CV_REG_MM0 = 146, + CV_REG_MM1 = 147, + CV_REG_MM2 = 148, + CV_REG_MM3 = 149, + CV_REG_MM4 = 150, + CV_REG_MM5 = 151, + CV_REG_MM6 = 152, + CV_REG_MM7 = 153, + + CV_REG_XMM0 = 154, // KATMAI registers + CV_REG_XMM1 = 155, + CV_REG_XMM2 = 156, + CV_REG_XMM3 = 157, + CV_REG_XMM4 = 158, + CV_REG_XMM5 = 159, + CV_REG_XMM6 = 160, + CV_REG_XMM7 = 161, + + CV_REG_XMM00 = 162, // KATMAI sub-registers + CV_REG_XMM01 = 163, + CV_REG_XMM02 = 164, + CV_REG_XMM03 = 165, + CV_REG_XMM10 = 166, + CV_REG_XMM11 = 167, + CV_REG_XMM12 = 168, + CV_REG_XMM13 = 169, + CV_REG_XMM20 = 170, + CV_REG_XMM21 = 171, + CV_REG_XMM22 = 172, + CV_REG_XMM23 = 173, + CV_REG_XMM30 = 174, + CV_REG_XMM31 = 175, + CV_REG_XMM32 = 176, + CV_REG_XMM33 = 177, + CV_REG_XMM40 = 178, + CV_REG_XMM41 = 179, + CV_REG_XMM42 = 180, + CV_REG_XMM43 = 181, + CV_REG_XMM50 = 182, + CV_REG_XMM51 = 183, + CV_REG_XMM52 = 184, + CV_REG_XMM53 = 185, + CV_REG_XMM60 = 186, + CV_REG_XMM61 = 187, + CV_REG_XMM62 = 188, + CV_REG_XMM63 = 189, + CV_REG_XMM70 = 190, + CV_REG_XMM71 = 191, + CV_REG_XMM72 = 192, + CV_REG_XMM73 = 193, + + CV_REG_XMM0L = 194, + CV_REG_XMM1L = 195, + CV_REG_XMM2L = 196, + CV_REG_XMM3L = 197, + CV_REG_XMM4L = 198, + CV_REG_XMM5L = 199, + CV_REG_XMM6L = 200, + CV_REG_XMM7L = 201, + + CV_REG_XMM0H = 202, + CV_REG_XMM1H = 203, + CV_REG_XMM2H = 204, + CV_REG_XMM3H = 205, + CV_REG_XMM4H = 206, + CV_REG_XMM5H = 207, + CV_REG_XMM6H = 208, + CV_REG_XMM7H = 209, + + CV_REG_MXCSR = 211, // XMM status register + + CV_REG_EDXEAX = 212, // EDX:EAX pair + + CV_REG_EMM0L = 220, // XMM sub-registers (WNI integer) + CV_REG_EMM1L = 221, + CV_REG_EMM2L = 222, + CV_REG_EMM3L = 223, + CV_REG_EMM4L = 224, + CV_REG_EMM5L = 225, + CV_REG_EMM6L = 226, + CV_REG_EMM7L = 227, + + CV_REG_EMM0H = 228, + CV_REG_EMM1H = 229, + CV_REG_EMM2H = 230, + CV_REG_EMM3H = 231, + CV_REG_EMM4H = 232, + CV_REG_EMM5H = 233, + CV_REG_EMM6H = 234, + CV_REG_EMM7H = 235, + + // do not change the order of these regs, first one must be even too + CV_REG_MM00 = 236, + CV_REG_MM01 = 237, + CV_REG_MM10 = 238, + CV_REG_MM11 = 239, + CV_REG_MM20 = 240, + CV_REG_MM21 = 241, + CV_REG_MM30 = 242, + CV_REG_MM31 = 243, + CV_REG_MM40 = 244, + CV_REG_MM41 = 245, + CV_REG_MM50 = 246, + CV_REG_MM51 = 247, + CV_REG_MM60 = 248, + CV_REG_MM61 = 249, + CV_REG_MM70 = 250, + CV_REG_MM71 = 251, + + CV_REG_YMM0 = 252, // AVX registers + CV_REG_YMM1 = 253, + CV_REG_YMM2 = 254, + CV_REG_YMM3 = 255, + CV_REG_YMM4 = 256, + CV_REG_YMM5 = 257, + CV_REG_YMM6 = 258, + CV_REG_YMM7 = 259, + + CV_REG_YMM0H = 260, + CV_REG_YMM1H = 261, + CV_REG_YMM2H = 262, + CV_REG_YMM3H = 263, + CV_REG_YMM4H = 264, + CV_REG_YMM5H = 265, + CV_REG_YMM6H = 266, + CV_REG_YMM7H = 267, + + CV_REG_YMM0I0 = 268, // AVX integer registers + CV_REG_YMM0I1 = 269, + CV_REG_YMM0I2 = 270, + CV_REG_YMM0I3 = 271, + CV_REG_YMM1I0 = 272, + CV_REG_YMM1I1 = 273, + CV_REG_YMM1I2 = 274, + CV_REG_YMM1I3 = 275, + CV_REG_YMM2I0 = 276, + CV_REG_YMM2I1 = 277, + CV_REG_YMM2I2 = 278, + CV_REG_YMM2I3 = 279, + CV_REG_YMM3I0 = 280, + CV_REG_YMM3I1 = 281, + CV_REG_YMM3I2 = 282, + CV_REG_YMM3I3 = 283, + CV_REG_YMM4I0 = 284, + CV_REG_YMM4I1 = 285, + CV_REG_YMM4I2 = 286, + CV_REG_YMM4I3 = 287, + CV_REG_YMM5I0 = 288, + CV_REG_YMM5I1 = 289, + CV_REG_YMM5I2 = 290, + CV_REG_YMM5I3 = 291, + CV_REG_YMM6I0 = 292, + CV_REG_YMM6I1 = 293, + CV_REG_YMM6I2 = 294, + CV_REG_YMM6I3 = 295, + CV_REG_YMM7I0 = 296, + CV_REG_YMM7I1 = 297, + CV_REG_YMM7I2 = 298, + CV_REG_YMM7I3 = 299, + + CV_REG_YMM0F0 = 300, // AVX floating-point single precise registers + CV_REG_YMM0F1 = 301, + CV_REG_YMM0F2 = 302, + CV_REG_YMM0F3 = 303, + CV_REG_YMM0F4 = 304, + CV_REG_YMM0F5 = 305, + CV_REG_YMM0F6 = 306, + CV_REG_YMM0F7 = 307, + CV_REG_YMM1F0 = 308, + CV_REG_YMM1F1 = 309, + CV_REG_YMM1F2 = 310, + CV_REG_YMM1F3 = 311, + CV_REG_YMM1F4 = 312, + CV_REG_YMM1F5 = 313, + CV_REG_YMM1F6 = 314, + CV_REG_YMM1F7 = 315, + CV_REG_YMM2F0 = 316, + CV_REG_YMM2F1 = 317, + CV_REG_YMM2F2 = 318, + CV_REG_YMM2F3 = 319, + CV_REG_YMM2F4 = 320, + CV_REG_YMM2F5 = 321, + CV_REG_YMM2F6 = 322, + CV_REG_YMM2F7 = 323, + CV_REG_YMM3F0 = 324, + CV_REG_YMM3F1 = 325, + CV_REG_YMM3F2 = 326, + CV_REG_YMM3F3 = 327, + CV_REG_YMM3F4 = 328, + CV_REG_YMM3F5 = 329, + CV_REG_YMM3F6 = 330, + CV_REG_YMM3F7 = 331, + CV_REG_YMM4F0 = 332, + CV_REG_YMM4F1 = 333, + CV_REG_YMM4F2 = 334, + CV_REG_YMM4F3 = 335, + CV_REG_YMM4F4 = 336, + CV_REG_YMM4F5 = 337, + CV_REG_YMM4F6 = 338, + CV_REG_YMM4F7 = 339, + CV_REG_YMM5F0 = 340, + CV_REG_YMM5F1 = 341, + CV_REG_YMM5F2 = 342, + CV_REG_YMM5F3 = 343, + CV_REG_YMM5F4 = 344, + CV_REG_YMM5F5 = 345, + CV_REG_YMM5F6 = 346, + CV_REG_YMM5F7 = 347, + CV_REG_YMM6F0 = 348, + CV_REG_YMM6F1 = 349, + CV_REG_YMM6F2 = 350, + CV_REG_YMM6F3 = 351, + CV_REG_YMM6F4 = 352, + CV_REG_YMM6F5 = 353, + CV_REG_YMM6F6 = 354, + CV_REG_YMM6F7 = 355, + CV_REG_YMM7F0 = 356, + CV_REG_YMM7F1 = 357, + CV_REG_YMM7F2 = 358, + CV_REG_YMM7F3 = 359, + CV_REG_YMM7F4 = 360, + CV_REG_YMM7F5 = 361, + CV_REG_YMM7F6 = 362, + CV_REG_YMM7F7 = 363, + + CV_REG_YMM0D0 = 364, // AVX floating-point double precise registers + CV_REG_YMM0D1 = 365, + CV_REG_YMM0D2 = 366, + CV_REG_YMM0D3 = 367, + CV_REG_YMM1D0 = 368, + CV_REG_YMM1D1 = 369, + CV_REG_YMM1D2 = 370, + CV_REG_YMM1D3 = 371, + CV_REG_YMM2D0 = 372, + CV_REG_YMM2D1 = 373, + CV_REG_YMM2D2 = 374, + CV_REG_YMM2D3 = 375, + CV_REG_YMM3D0 = 376, + CV_REG_YMM3D1 = 377, + CV_REG_YMM3D2 = 378, + CV_REG_YMM3D3 = 379, + CV_REG_YMM4D0 = 380, + CV_REG_YMM4D1 = 381, + CV_REG_YMM4D2 = 382, + CV_REG_YMM4D3 = 383, + CV_REG_YMM5D0 = 384, + CV_REG_YMM5D1 = 385, + CV_REG_YMM5D2 = 386, + CV_REG_YMM5D3 = 387, + CV_REG_YMM6D0 = 388, + CV_REG_YMM6D1 = 389, + CV_REG_YMM6D2 = 390, + CV_REG_YMM6D3 = 391, + CV_REG_YMM7D0 = 392, + CV_REG_YMM7D1 = 393, + CV_REG_YMM7D2 = 394, + CV_REG_YMM7D3 = 395, + + CV_REG_BND0 = 396, + CV_REG_BND1 = 397, + CV_REG_BND2 = 398, + CV_REG_BND3 = 399, + + // registers for the 68K processors + + CV_R68_D0 = 0, + CV_R68_D1 = 1, + CV_R68_D2 = 2, + CV_R68_D3 = 3, + CV_R68_D4 = 4, + CV_R68_D5 = 5, + CV_R68_D6 = 6, + CV_R68_D7 = 7, + CV_R68_A0 = 8, + CV_R68_A1 = 9, + CV_R68_A2 = 10, + CV_R68_A3 = 11, + CV_R68_A4 = 12, + CV_R68_A5 = 13, + CV_R68_A6 = 14, + CV_R68_A7 = 15, + CV_R68_CCR = 16, + CV_R68_SR = 17, + CV_R68_USP = 18, + CV_R68_MSP = 19, + CV_R68_SFC = 20, + CV_R68_DFC = 21, + CV_R68_CACR = 22, + CV_R68_VBR = 23, + CV_R68_CAAR = 24, + CV_R68_ISP = 25, + CV_R68_PC = 26, + // reserved 27 + CV_R68_FPCR = 28, + CV_R68_FPSR = 29, + CV_R68_FPIAR = 30, + // reserved 31 + CV_R68_FP0 = 32, + CV_R68_FP1 = 33, + CV_R68_FP2 = 34, + CV_R68_FP3 = 35, + CV_R68_FP4 = 36, + CV_R68_FP5 = 37, + CV_R68_FP6 = 38, + CV_R68_FP7 = 39, + // reserved 40 + CV_R68_MMUSR030 = 41, + CV_R68_MMUSR = 42, + CV_R68_URP = 43, + CV_R68_DTT0 = 44, + CV_R68_DTT1 = 45, + CV_R68_ITT0 = 46, + CV_R68_ITT1 = 47, + // reserved 50 + CV_R68_PSR = 51, + CV_R68_PCSR = 52, + CV_R68_VAL = 53, + CV_R68_CRP = 54, + CV_R68_SRP = 55, + CV_R68_DRP = 56, + CV_R68_TC = 57, + CV_R68_AC = 58, + CV_R68_SCC = 59, + CV_R68_CAL = 60, + CV_R68_TT0 = 61, + CV_R68_TT1 = 62, + // reserved 63 + CV_R68_BAD0 = 64, + CV_R68_BAD1 = 65, + CV_R68_BAD2 = 66, + CV_R68_BAD3 = 67, + CV_R68_BAD4 = 68, + CV_R68_BAD5 = 69, + CV_R68_BAD6 = 70, + CV_R68_BAD7 = 71, + CV_R68_BAC0 = 72, + CV_R68_BAC1 = 73, + CV_R68_BAC2 = 74, + CV_R68_BAC3 = 75, + CV_R68_BAC4 = 76, + CV_R68_BAC5 = 77, + CV_R68_BAC6 = 78, + CV_R68_BAC7 = 79, + + // Register set for the MIPS 4000 + + CV_M4_NOREG = CV_REG_NONE, + + CV_M4_IntZERO = 10, /* CPU REGISTER */ + CV_M4_IntAT = 11, + CV_M4_IntV0 = 12, + CV_M4_IntV1 = 13, + CV_M4_IntA0 = 14, + CV_M4_IntA1 = 15, + CV_M4_IntA2 = 16, + CV_M4_IntA3 = 17, + CV_M4_IntT0 = 18, + CV_M4_IntT1 = 19, + CV_M4_IntT2 = 20, + CV_M4_IntT3 = 21, + CV_M4_IntT4 = 22, + CV_M4_IntT5 = 23, + CV_M4_IntT6 = 24, + CV_M4_IntT7 = 25, + CV_M4_IntS0 = 26, + CV_M4_IntS1 = 27, + CV_M4_IntS2 = 28, + CV_M4_IntS3 = 29, + CV_M4_IntS4 = 30, + CV_M4_IntS5 = 31, + CV_M4_IntS6 = 32, + CV_M4_IntS7 = 33, + CV_M4_IntT8 = 34, + CV_M4_IntT9 = 35, + CV_M4_IntKT0 = 36, + CV_M4_IntKT1 = 37, + CV_M4_IntGP = 38, + CV_M4_IntSP = 39, + CV_M4_IntS8 = 40, + CV_M4_IntRA = 41, + CV_M4_IntLO = 42, + CV_M4_IntHI = 43, + + CV_M4_Fir = 50, + CV_M4_Psr = 51, + + CV_M4_FltF0 = 60, /* Floating point registers */ + CV_M4_FltF1 = 61, + CV_M4_FltF2 = 62, + CV_M4_FltF3 = 63, + CV_M4_FltF4 = 64, + CV_M4_FltF5 = 65, + CV_M4_FltF6 = 66, + CV_M4_FltF7 = 67, + CV_M4_FltF8 = 68, + CV_M4_FltF9 = 69, + CV_M4_FltF10 = 70, + CV_M4_FltF11 = 71, + CV_M4_FltF12 = 72, + CV_M4_FltF13 = 73, + CV_M4_FltF14 = 74, + CV_M4_FltF15 = 75, + CV_M4_FltF16 = 76, + CV_M4_FltF17 = 77, + CV_M4_FltF18 = 78, + CV_M4_FltF19 = 79, + CV_M4_FltF20 = 80, + CV_M4_FltF21 = 81, + CV_M4_FltF22 = 82, + CV_M4_FltF23 = 83, + CV_M4_FltF24 = 84, + CV_M4_FltF25 = 85, + CV_M4_FltF26 = 86, + CV_M4_FltF27 = 87, + CV_M4_FltF28 = 88, + CV_M4_FltF29 = 89, + CV_M4_FltF30 = 90, + CV_M4_FltF31 = 91, + CV_M4_FltFsr = 92, + + // Register set for the ALPHA AXP + + CV_ALPHA_NOREG = CV_REG_NONE, + + CV_ALPHA_FltF0 = 10, // Floating point registers + CV_ALPHA_FltF1 = 11, + CV_ALPHA_FltF2 = 12, + CV_ALPHA_FltF3 = 13, + CV_ALPHA_FltF4 = 14, + CV_ALPHA_FltF5 = 15, + CV_ALPHA_FltF6 = 16, + CV_ALPHA_FltF7 = 17, + CV_ALPHA_FltF8 = 18, + CV_ALPHA_FltF9 = 19, + CV_ALPHA_FltF10 = 20, + CV_ALPHA_FltF11 = 21, + CV_ALPHA_FltF12 = 22, + CV_ALPHA_FltF13 = 23, + CV_ALPHA_FltF14 = 24, + CV_ALPHA_FltF15 = 25, + CV_ALPHA_FltF16 = 26, + CV_ALPHA_FltF17 = 27, + CV_ALPHA_FltF18 = 28, + CV_ALPHA_FltF19 = 29, + CV_ALPHA_FltF20 = 30, + CV_ALPHA_FltF21 = 31, + CV_ALPHA_FltF22 = 32, + CV_ALPHA_FltF23 = 33, + CV_ALPHA_FltF24 = 34, + CV_ALPHA_FltF25 = 35, + CV_ALPHA_FltF26 = 36, + CV_ALPHA_FltF27 = 37, + CV_ALPHA_FltF28 = 38, + CV_ALPHA_FltF29 = 39, + CV_ALPHA_FltF30 = 40, + CV_ALPHA_FltF31 = 41, + + CV_ALPHA_IntV0 = 42, // Integer registers + CV_ALPHA_IntT0 = 43, + CV_ALPHA_IntT1 = 44, + CV_ALPHA_IntT2 = 45, + CV_ALPHA_IntT3 = 46, + CV_ALPHA_IntT4 = 47, + CV_ALPHA_IntT5 = 48, + CV_ALPHA_IntT6 = 49, + CV_ALPHA_IntT7 = 50, + CV_ALPHA_IntS0 = 51, + CV_ALPHA_IntS1 = 52, + CV_ALPHA_IntS2 = 53, + CV_ALPHA_IntS3 = 54, + CV_ALPHA_IntS4 = 55, + CV_ALPHA_IntS5 = 56, + CV_ALPHA_IntFP = 57, + CV_ALPHA_IntA0 = 58, + CV_ALPHA_IntA1 = 59, + CV_ALPHA_IntA2 = 60, + CV_ALPHA_IntA3 = 61, + CV_ALPHA_IntA4 = 62, + CV_ALPHA_IntA5 = 63, + CV_ALPHA_IntT8 = 64, + CV_ALPHA_IntT9 = 65, + CV_ALPHA_IntT10 = 66, + CV_ALPHA_IntT11 = 67, + CV_ALPHA_IntRA = 68, + CV_ALPHA_IntT12 = 69, + CV_ALPHA_IntAT = 70, + CV_ALPHA_IntGP = 71, + CV_ALPHA_IntSP = 72, + CV_ALPHA_IntZERO = 73, + + CV_ALPHA_Fpcr = 74, // Control registers + CV_ALPHA_Fir = 75, + CV_ALPHA_Psr = 76, + CV_ALPHA_FltFsr = 77, + CV_ALPHA_SoftFpcr = 78, + + // Register Set for Motorola/IBM PowerPC + + /* + ** PowerPC General Registers ( User Level ) + */ + CV_PPC_GPR0 = 1, + CV_PPC_GPR1 = 2, + CV_PPC_GPR2 = 3, + CV_PPC_GPR3 = 4, + CV_PPC_GPR4 = 5, + CV_PPC_GPR5 = 6, + CV_PPC_GPR6 = 7, + CV_PPC_GPR7 = 8, + CV_PPC_GPR8 = 9, + CV_PPC_GPR9 = 10, + CV_PPC_GPR10 = 11, + CV_PPC_GPR11 = 12, + CV_PPC_GPR12 = 13, + CV_PPC_GPR13 = 14, + CV_PPC_GPR14 = 15, + CV_PPC_GPR15 = 16, + CV_PPC_GPR16 = 17, + CV_PPC_GPR17 = 18, + CV_PPC_GPR18 = 19, + CV_PPC_GPR19 = 20, + CV_PPC_GPR20 = 21, + CV_PPC_GPR21 = 22, + CV_PPC_GPR22 = 23, + CV_PPC_GPR23 = 24, + CV_PPC_GPR24 = 25, + CV_PPC_GPR25 = 26, + CV_PPC_GPR26 = 27, + CV_PPC_GPR27 = 28, + CV_PPC_GPR28 = 29, + CV_PPC_GPR29 = 30, + CV_PPC_GPR30 = 31, + CV_PPC_GPR31 = 32, + + /* + ** PowerPC Condition Register ( User Level ) + */ + CV_PPC_CR = 33, + CV_PPC_CR0 = 34, + CV_PPC_CR1 = 35, + CV_PPC_CR2 = 36, + CV_PPC_CR3 = 37, + CV_PPC_CR4 = 38, + CV_PPC_CR5 = 39, + CV_PPC_CR6 = 40, + CV_PPC_CR7 = 41, + + /* + ** PowerPC Floating Point Registers ( User Level ) + */ + CV_PPC_FPR0 = 42, + CV_PPC_FPR1 = 43, + CV_PPC_FPR2 = 44, + CV_PPC_FPR3 = 45, + CV_PPC_FPR4 = 46, + CV_PPC_FPR5 = 47, + CV_PPC_FPR6 = 48, + CV_PPC_FPR7 = 49, + CV_PPC_FPR8 = 50, + CV_PPC_FPR9 = 51, + CV_PPC_FPR10 = 52, + CV_PPC_FPR11 = 53, + CV_PPC_FPR12 = 54, + CV_PPC_FPR13 = 55, + CV_PPC_FPR14 = 56, + CV_PPC_FPR15 = 57, + CV_PPC_FPR16 = 58, + CV_PPC_FPR17 = 59, + CV_PPC_FPR18 = 60, + CV_PPC_FPR19 = 61, + CV_PPC_FPR20 = 62, + CV_PPC_FPR21 = 63, + CV_PPC_FPR22 = 64, + CV_PPC_FPR23 = 65, + CV_PPC_FPR24 = 66, + CV_PPC_FPR25 = 67, + CV_PPC_FPR26 = 68, + CV_PPC_FPR27 = 69, + CV_PPC_FPR28 = 70, + CV_PPC_FPR29 = 71, + CV_PPC_FPR30 = 72, + CV_PPC_FPR31 = 73, + + /* + ** PowerPC Floating Point Status and Control Register ( User Level ) + */ + CV_PPC_FPSCR = 74, + + /* + ** PowerPC Machine State Register ( Supervisor Level ) + */ + CV_PPC_MSR = 75, + + /* + ** PowerPC Segment Registers ( Supervisor Level ) + */ + CV_PPC_SR0 = 76, + CV_PPC_SR1 = 77, + CV_PPC_SR2 = 78, + CV_PPC_SR3 = 79, + CV_PPC_SR4 = 80, + CV_PPC_SR5 = 81, + CV_PPC_SR6 = 82, + CV_PPC_SR7 = 83, + CV_PPC_SR8 = 84, + CV_PPC_SR9 = 85, + CV_PPC_SR10 = 86, + CV_PPC_SR11 = 87, + CV_PPC_SR12 = 88, + CV_PPC_SR13 = 89, + CV_PPC_SR14 = 90, + CV_PPC_SR15 = 91, + + /* + ** For all of the special purpose registers add 100 to the SPR# that the + ** Motorola/IBM documentation gives with the exception of any imaginary + ** registers. + */ + + /* + ** PowerPC Special Purpose Registers ( User Level ) + */ + CV_PPC_PC = 99, // PC (imaginary register) + + CV_PPC_MQ = 100, // MPC601 + CV_PPC_XER = 101, + CV_PPC_RTCU = 104, // MPC601 + CV_PPC_RTCL = 105, // MPC601 + CV_PPC_LR = 108, + CV_PPC_CTR = 109, + + CV_PPC_COMPARE = 110, // part of XER (internal to the debugger only) + CV_PPC_COUNT = 111, // part of XER (internal to the debugger only) + + /* + ** PowerPC Special Purpose Registers ( Supervisor Level ) + */ + CV_PPC_DSISR = 118, + CV_PPC_DAR = 119, + CV_PPC_DEC = 122, + CV_PPC_SDR1 = 125, + CV_PPC_SRR0 = 126, + CV_PPC_SRR1 = 127, + CV_PPC_SPRG0 = 372, + CV_PPC_SPRG1 = 373, + CV_PPC_SPRG2 = 374, + CV_PPC_SPRG3 = 375, + CV_PPC_ASR = 280, // 64-bit implementations only + CV_PPC_EAR = 382, + CV_PPC_PVR = 287, + CV_PPC_BAT0U = 628, + CV_PPC_BAT0L = 629, + CV_PPC_BAT1U = 630, + CV_PPC_BAT1L = 631, + CV_PPC_BAT2U = 632, + CV_PPC_BAT2L = 633, + CV_PPC_BAT3U = 634, + CV_PPC_BAT3L = 635, + CV_PPC_DBAT0U = 636, + CV_PPC_DBAT0L = 637, + CV_PPC_DBAT1U = 638, + CV_PPC_DBAT1L = 639, + CV_PPC_DBAT2U = 640, + CV_PPC_DBAT2L = 641, + CV_PPC_DBAT3U = 642, + CV_PPC_DBAT3L = 643, + + /* + ** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor + *Level ) + */ + + /* + ** Doesn't appear that IBM/Motorola has finished defining these. + */ + + CV_PPC_PMR0 = 1044, // MPC620, + CV_PPC_PMR1 = 1045, // MPC620, + CV_PPC_PMR2 = 1046, // MPC620, + CV_PPC_PMR3 = 1047, // MPC620, + CV_PPC_PMR4 = 1048, // MPC620, + CV_PPC_PMR5 = 1049, // MPC620, + CV_PPC_PMR6 = 1050, // MPC620, + CV_PPC_PMR7 = 1051, // MPC620, + CV_PPC_PMR8 = 1052, // MPC620, + CV_PPC_PMR9 = 1053, // MPC620, + CV_PPC_PMR10 = 1054, // MPC620, + CV_PPC_PMR11 = 1055, // MPC620, + CV_PPC_PMR12 = 1056, // MPC620, + CV_PPC_PMR13 = 1057, // MPC620, + CV_PPC_PMR14 = 1058, // MPC620, + CV_PPC_PMR15 = 1059, // MPC620, + + CV_PPC_DMISS = 1076, // MPC603 + CV_PPC_DCMP = 1077, // MPC603 + CV_PPC_HASH1 = 1078, // MPC603 + CV_PPC_HASH2 = 1079, // MPC603 + CV_PPC_IMISS = 1080, // MPC603 + CV_PPC_ICMP = 1081, // MPC603 + CV_PPC_RPA = 1082, // MPC603 + + CV_PPC_HID0 = 1108, // MPC601, MPC603, MPC620 + CV_PPC_HID1 = 1109, // MPC601 + CV_PPC_HID2 = 1110, // MPC601, MPC603, MPC620 ( IABR ) + CV_PPC_HID3 = 1111, // Not Defined + CV_PPC_HID4 = 1112, // Not Defined + CV_PPC_HID5 = 1113, // MPC601, MPC604, MPC620 ( DABR ) + CV_PPC_HID6 = 1114, // Not Defined + CV_PPC_HID7 = 1115, // Not Defined + CV_PPC_HID8 = 1116, // MPC620 ( BUSCSR ) + CV_PPC_HID9 = 1117, // MPC620 ( L2CSR ) + CV_PPC_HID10 = 1118, // Not Defined + CV_PPC_HID11 = 1119, // Not Defined + CV_PPC_HID12 = 1120, // Not Defined + CV_PPC_HID13 = 1121, // MPC604 ( HCR ) + CV_PPC_HID14 = 1122, // Not Defined + CV_PPC_HID15 = 1123, // MPC601, MPC604, MPC620 ( PIR ) + + // + // JAVA VM registers + // + + CV_JAVA_PC = 1, + + // + // Register set for the Hitachi SH3 + // + + CV_SH3_NOREG = CV_REG_NONE, + + CV_SH3_IntR0 = 10, // CPU REGISTER + CV_SH3_IntR1 = 11, + CV_SH3_IntR2 = 12, + CV_SH3_IntR3 = 13, + CV_SH3_IntR4 = 14, + CV_SH3_IntR5 = 15, + CV_SH3_IntR6 = 16, + CV_SH3_IntR7 = 17, + CV_SH3_IntR8 = 18, + CV_SH3_IntR9 = 19, + CV_SH3_IntR10 = 20, + CV_SH3_IntR11 = 21, + CV_SH3_IntR12 = 22, + CV_SH3_IntR13 = 23, + CV_SH3_IntFp = 24, + CV_SH3_IntSp = 25, + CV_SH3_Gbr = 38, + CV_SH3_Pr = 39, + CV_SH3_Mach = 40, + CV_SH3_Macl = 41, + + CV_SH3_Pc = 50, + CV_SH3_Sr = 51, + + CV_SH3_BarA = 60, + CV_SH3_BasrA = 61, + CV_SH3_BamrA = 62, + CV_SH3_BbrA = 63, + CV_SH3_BarB = 64, + CV_SH3_BasrB = 65, + CV_SH3_BamrB = 66, + CV_SH3_BbrB = 67, + CV_SH3_BdrB = 68, + CV_SH3_BdmrB = 69, + CV_SH3_Brcr = 70, + + // + // Additional registers for Hitachi SH processors + // + + CV_SH_Fpscr = 75, // floating point status/control register + CV_SH_Fpul = 76, // floating point communication register + + CV_SH_FpR0 = 80, // Floating point registers + CV_SH_FpR1 = 81, + CV_SH_FpR2 = 82, + CV_SH_FpR3 = 83, + CV_SH_FpR4 = 84, + CV_SH_FpR5 = 85, + CV_SH_FpR6 = 86, + CV_SH_FpR7 = 87, + CV_SH_FpR8 = 88, + CV_SH_FpR9 = 89, + CV_SH_FpR10 = 90, + CV_SH_FpR11 = 91, + CV_SH_FpR12 = 92, + CV_SH_FpR13 = 93, + CV_SH_FpR14 = 94, + CV_SH_FpR15 = 95, + + CV_SH_XFpR0 = 96, + CV_SH_XFpR1 = 97, + CV_SH_XFpR2 = 98, + CV_SH_XFpR3 = 99, + CV_SH_XFpR4 = 100, + CV_SH_XFpR5 = 101, + CV_SH_XFpR6 = 102, + CV_SH_XFpR7 = 103, + CV_SH_XFpR8 = 104, + CV_SH_XFpR9 = 105, + CV_SH_XFpR10 = 106, + CV_SH_XFpR11 = 107, + CV_SH_XFpR12 = 108, + CV_SH_XFpR13 = 109, + CV_SH_XFpR14 = 110, + CV_SH_XFpR15 = 111, + + // + // Register set for the ARM processor. + // + + CV_ARM_NOREG = CV_REG_NONE, + + CV_ARM_R0 = 10, + CV_ARM_R1 = 11, + CV_ARM_R2 = 12, + CV_ARM_R3 = 13, + CV_ARM_R4 = 14, + CV_ARM_R5 = 15, + CV_ARM_R6 = 16, + CV_ARM_R7 = 17, + CV_ARM_R8 = 18, + CV_ARM_R9 = 19, + CV_ARM_R10 = 20, + CV_ARM_R11 = 21, // Frame pointer, if allocated + CV_ARM_R12 = 22, + CV_ARM_SP = 23, // Stack pointer + CV_ARM_LR = 24, // Link Register + CV_ARM_PC = 25, // Program counter + CV_ARM_CPSR = 26, // Current program status register + + CV_ARM_ACC0 = 27, // DSP co-processor 0 40 bit accumulator + + // + // Registers for ARM VFP10 support + // + + CV_ARM_FPSCR = 40, + CV_ARM_FPEXC = 41, + + CV_ARM_FS0 = 50, + CV_ARM_FS1 = 51, + CV_ARM_FS2 = 52, + CV_ARM_FS3 = 53, + CV_ARM_FS4 = 54, + CV_ARM_FS5 = 55, + CV_ARM_FS6 = 56, + CV_ARM_FS7 = 57, + CV_ARM_FS8 = 58, + CV_ARM_FS9 = 59, + CV_ARM_FS10 = 60, + CV_ARM_FS11 = 61, + CV_ARM_FS12 = 62, + CV_ARM_FS13 = 63, + CV_ARM_FS14 = 64, + CV_ARM_FS15 = 65, + CV_ARM_FS16 = 66, + CV_ARM_FS17 = 67, + CV_ARM_FS18 = 68, + CV_ARM_FS19 = 69, + CV_ARM_FS20 = 70, + CV_ARM_FS21 = 71, + CV_ARM_FS22 = 72, + CV_ARM_FS23 = 73, + CV_ARM_FS24 = 74, + CV_ARM_FS25 = 75, + CV_ARM_FS26 = 76, + CV_ARM_FS27 = 77, + CV_ARM_FS28 = 78, + CV_ARM_FS29 = 79, + CV_ARM_FS30 = 80, + CV_ARM_FS31 = 81, + + // + // ARM VFP Floating Point Extra control registers + // + + CV_ARM_FPEXTRA0 = 90, + CV_ARM_FPEXTRA1 = 91, + CV_ARM_FPEXTRA2 = 92, + CV_ARM_FPEXTRA3 = 93, + CV_ARM_FPEXTRA4 = 94, + CV_ARM_FPEXTRA5 = 95, + CV_ARM_FPEXTRA6 = 96, + CV_ARM_FPEXTRA7 = 97, + + // XSCALE Concan co-processor registers + CV_ARM_WR0 = 128, + CV_ARM_WR1 = 129, + CV_ARM_WR2 = 130, + CV_ARM_WR3 = 131, + CV_ARM_WR4 = 132, + CV_ARM_WR5 = 133, + CV_ARM_WR6 = 134, + CV_ARM_WR7 = 135, + CV_ARM_WR8 = 136, + CV_ARM_WR9 = 137, + CV_ARM_WR10 = 138, + CV_ARM_WR11 = 139, + CV_ARM_WR12 = 140, + CV_ARM_WR13 = 141, + CV_ARM_WR14 = 142, + CV_ARM_WR15 = 143, + + // XSCALE Concan co-processor control registers + CV_ARM_WCID = 144, + CV_ARM_WCON = 145, + CV_ARM_WCSSF = 146, + CV_ARM_WCASF = 147, + CV_ARM_WC4 = 148, + CV_ARM_WC5 = 149, + CV_ARM_WC6 = 150, + CV_ARM_WC7 = 151, + CV_ARM_WCGR0 = 152, + CV_ARM_WCGR1 = 153, + CV_ARM_WCGR2 = 154, + CV_ARM_WCGR3 = 155, + CV_ARM_WC12 = 156, + CV_ARM_WC13 = 157, + CV_ARM_WC14 = 158, + CV_ARM_WC15 = 159, + + // + // ARM VFPv3/Neon extended floating Point + // + + CV_ARM_FS32 = 200, + CV_ARM_FS33 = 201, + CV_ARM_FS34 = 202, + CV_ARM_FS35 = 203, + CV_ARM_FS36 = 204, + CV_ARM_FS37 = 205, + CV_ARM_FS38 = 206, + CV_ARM_FS39 = 207, + CV_ARM_FS40 = 208, + CV_ARM_FS41 = 209, + CV_ARM_FS42 = 210, + CV_ARM_FS43 = 211, + CV_ARM_FS44 = 212, + CV_ARM_FS45 = 213, + CV_ARM_FS46 = 214, + CV_ARM_FS47 = 215, + CV_ARM_FS48 = 216, + CV_ARM_FS49 = 217, + CV_ARM_FS50 = 218, + CV_ARM_FS51 = 219, + CV_ARM_FS52 = 220, + CV_ARM_FS53 = 221, + CV_ARM_FS54 = 222, + CV_ARM_FS55 = 223, + CV_ARM_FS56 = 224, + CV_ARM_FS57 = 225, + CV_ARM_FS58 = 226, + CV_ARM_FS59 = 227, + CV_ARM_FS60 = 228, + CV_ARM_FS61 = 229, + CV_ARM_FS62 = 230, + CV_ARM_FS63 = 231, + + // ARM double-precision floating point + + CV_ARM_ND0 = 300, + CV_ARM_ND1 = 301, + CV_ARM_ND2 = 302, + CV_ARM_ND3 = 303, + CV_ARM_ND4 = 304, + CV_ARM_ND5 = 305, + CV_ARM_ND6 = 306, + CV_ARM_ND7 = 307, + CV_ARM_ND8 = 308, + CV_ARM_ND9 = 309, + CV_ARM_ND10 = 310, + CV_ARM_ND11 = 311, + CV_ARM_ND12 = 312, + CV_ARM_ND13 = 313, + CV_ARM_ND14 = 314, + CV_ARM_ND15 = 315, + CV_ARM_ND16 = 316, + CV_ARM_ND17 = 317, + CV_ARM_ND18 = 318, + CV_ARM_ND19 = 319, + CV_ARM_ND20 = 320, + CV_ARM_ND21 = 321, + CV_ARM_ND22 = 322, + CV_ARM_ND23 = 323, + CV_ARM_ND24 = 324, + CV_ARM_ND25 = 325, + CV_ARM_ND26 = 326, + CV_ARM_ND27 = 327, + CV_ARM_ND28 = 328, + CV_ARM_ND29 = 329, + CV_ARM_ND30 = 330, + CV_ARM_ND31 = 331, + + // ARM extended precision floating point + + CV_ARM_NQ0 = 400, + CV_ARM_NQ1 = 401, + CV_ARM_NQ2 = 402, + CV_ARM_NQ3 = 403, + CV_ARM_NQ4 = 404, + CV_ARM_NQ5 = 405, + CV_ARM_NQ6 = 406, + CV_ARM_NQ7 = 407, + CV_ARM_NQ8 = 408, + CV_ARM_NQ9 = 409, + CV_ARM_NQ10 = 410, + CV_ARM_NQ11 = 411, + CV_ARM_NQ12 = 412, + CV_ARM_NQ13 = 413, + CV_ARM_NQ14 = 414, + CV_ARM_NQ15 = 415, + + // + // Register set for ARM64 + // + + CV_ARM64_NOREG = CV_REG_NONE, + + // General purpose 32-bit integer registers + + CV_ARM64_W0 = 10, + CV_ARM64_W1 = 11, + CV_ARM64_W2 = 12, + CV_ARM64_W3 = 13, + CV_ARM64_W4 = 14, + CV_ARM64_W5 = 15, + CV_ARM64_W6 = 16, + CV_ARM64_W7 = 17, + CV_ARM64_W8 = 18, + CV_ARM64_W9 = 19, + CV_ARM64_W10 = 20, + CV_ARM64_W11 = 21, + CV_ARM64_W12 = 22, + CV_ARM64_W13 = 23, + CV_ARM64_W14 = 24, + CV_ARM64_W15 = 25, + CV_ARM64_W16 = 26, + CV_ARM64_W17 = 27, + CV_ARM64_W18 = 28, + CV_ARM64_W19 = 29, + CV_ARM64_W20 = 30, + CV_ARM64_W21 = 31, + CV_ARM64_W22 = 32, + CV_ARM64_W23 = 33, + CV_ARM64_W24 = 34, + CV_ARM64_W25 = 35, + CV_ARM64_W26 = 36, + CV_ARM64_W27 = 37, + CV_ARM64_W28 = 38, + CV_ARM64_W29 = 39, + CV_ARM64_W30 = 40, + CV_ARM64_WZR = 41, + + // General purpose 64-bit integer registers + + CV_ARM64_X0 = 50, + CV_ARM64_X1 = 51, + CV_ARM64_X2 = 52, + CV_ARM64_X3 = 53, + CV_ARM64_X4 = 54, + CV_ARM64_X5 = 55, + CV_ARM64_X6 = 56, + CV_ARM64_X7 = 57, + CV_ARM64_X8 = 58, + CV_ARM64_X9 = 59, + CV_ARM64_X10 = 60, + CV_ARM64_X11 = 61, + CV_ARM64_X12 = 62, + CV_ARM64_X13 = 63, + CV_ARM64_X14 = 64, + CV_ARM64_X15 = 65, + CV_ARM64_IP0 = 66, + CV_ARM64_IP1 = 67, + CV_ARM64_X18 = 68, + CV_ARM64_X19 = 69, + CV_ARM64_X20 = 70, + CV_ARM64_X21 = 71, + CV_ARM64_X22 = 72, + CV_ARM64_X23 = 73, + CV_ARM64_X24 = 74, + CV_ARM64_X25 = 75, + CV_ARM64_X26 = 76, + CV_ARM64_X27 = 77, + CV_ARM64_X28 = 78, + CV_ARM64_FP = 79, + CV_ARM64_LR = 80, + CV_ARM64_SP = 81, + CV_ARM64_ZR = 82, + + // statue register + + CV_ARM64_NZCV = 90, + + // 32-bit floating point registers + + CV_ARM64_S0 = 100, + CV_ARM64_S1 = 101, + CV_ARM64_S2 = 102, + CV_ARM64_S3 = 103, + CV_ARM64_S4 = 104, + CV_ARM64_S5 = 105, + CV_ARM64_S6 = 106, + CV_ARM64_S7 = 107, + CV_ARM64_S8 = 108, + CV_ARM64_S9 = 109, + CV_ARM64_S10 = 110, + CV_ARM64_S11 = 111, + CV_ARM64_S12 = 112, + CV_ARM64_S13 = 113, + CV_ARM64_S14 = 114, + CV_ARM64_S15 = 115, + CV_ARM64_S16 = 116, + CV_ARM64_S17 = 117, + CV_ARM64_S18 = 118, + CV_ARM64_S19 = 119, + CV_ARM64_S20 = 120, + CV_ARM64_S21 = 121, + CV_ARM64_S22 = 122, + CV_ARM64_S23 = 123, + CV_ARM64_S24 = 124, + CV_ARM64_S25 = 125, + CV_ARM64_S26 = 126, + CV_ARM64_S27 = 127, + CV_ARM64_S28 = 128, + CV_ARM64_S29 = 129, + CV_ARM64_S30 = 130, + CV_ARM64_S31 = 131, + + // 64-bit floating point registers + + CV_ARM64_D0 = 140, + CV_ARM64_D1 = 141, + CV_ARM64_D2 = 142, + CV_ARM64_D3 = 143, + CV_ARM64_D4 = 144, + CV_ARM64_D5 = 145, + CV_ARM64_D6 = 146, + CV_ARM64_D7 = 147, + CV_ARM64_D8 = 148, + CV_ARM64_D9 = 149, + CV_ARM64_D10 = 150, + CV_ARM64_D11 = 151, + CV_ARM64_D12 = 152, + CV_ARM64_D13 = 153, + CV_ARM64_D14 = 154, + CV_ARM64_D15 = 155, + CV_ARM64_D16 = 156, + CV_ARM64_D17 = 157, + CV_ARM64_D18 = 158, + CV_ARM64_D19 = 159, + CV_ARM64_D20 = 160, + CV_ARM64_D21 = 161, + CV_ARM64_D22 = 162, + CV_ARM64_D23 = 163, + CV_ARM64_D24 = 164, + CV_ARM64_D25 = 165, + CV_ARM64_D26 = 166, + CV_ARM64_D27 = 167, + CV_ARM64_D28 = 168, + CV_ARM64_D29 = 169, + CV_ARM64_D30 = 170, + CV_ARM64_D31 = 171, + + // 128-bit SIMD registers + + CV_ARM64_Q0 = 180, + CV_ARM64_Q1 = 181, + CV_ARM64_Q2 = 182, + CV_ARM64_Q3 = 183, + CV_ARM64_Q4 = 184, + CV_ARM64_Q5 = 185, + CV_ARM64_Q6 = 186, + CV_ARM64_Q7 = 187, + CV_ARM64_Q8 = 188, + CV_ARM64_Q9 = 189, + CV_ARM64_Q10 = 190, + CV_ARM64_Q11 = 191, + CV_ARM64_Q12 = 192, + CV_ARM64_Q13 = 193, + CV_ARM64_Q14 = 194, + CV_ARM64_Q15 = 195, + CV_ARM64_Q16 = 196, + CV_ARM64_Q17 = 197, + CV_ARM64_Q18 = 198, + CV_ARM64_Q19 = 199, + CV_ARM64_Q20 = 200, + CV_ARM64_Q21 = 201, + CV_ARM64_Q22 = 202, + CV_ARM64_Q23 = 203, + CV_ARM64_Q24 = 204, + CV_ARM64_Q25 = 205, + CV_ARM64_Q26 = 206, + CV_ARM64_Q27 = 207, + CV_ARM64_Q28 = 208, + CV_ARM64_Q29 = 209, + CV_ARM64_Q30 = 210, + CV_ARM64_Q31 = 211, + + // Floating point status register + + CV_ARM64_FPSR = 220, + + // + // Register set for Intel IA64 + // + + CV_IA64_NOREG = CV_REG_NONE, + + // Branch Registers + + CV_IA64_Br0 = 512, + CV_IA64_Br1 = 513, + CV_IA64_Br2 = 514, + CV_IA64_Br3 = 515, + CV_IA64_Br4 = 516, + CV_IA64_Br5 = 517, + CV_IA64_Br6 = 518, + CV_IA64_Br7 = 519, + + // Predicate Registers + + CV_IA64_P0 = 704, + CV_IA64_P1 = 705, + CV_IA64_P2 = 706, + CV_IA64_P3 = 707, + CV_IA64_P4 = 708, + CV_IA64_P5 = 709, + CV_IA64_P6 = 710, + CV_IA64_P7 = 711, + CV_IA64_P8 = 712, + CV_IA64_P9 = 713, + CV_IA64_P10 = 714, + CV_IA64_P11 = 715, + CV_IA64_P12 = 716, + CV_IA64_P13 = 717, + CV_IA64_P14 = 718, + CV_IA64_P15 = 719, + CV_IA64_P16 = 720, + CV_IA64_P17 = 721, + CV_IA64_P18 = 722, + CV_IA64_P19 = 723, + CV_IA64_P20 = 724, + CV_IA64_P21 = 725, + CV_IA64_P22 = 726, + CV_IA64_P23 = 727, + CV_IA64_P24 = 728, + CV_IA64_P25 = 729, + CV_IA64_P26 = 730, + CV_IA64_P27 = 731, + CV_IA64_P28 = 732, + CV_IA64_P29 = 733, + CV_IA64_P30 = 734, + CV_IA64_P31 = 735, + CV_IA64_P32 = 736, + CV_IA64_P33 = 737, + CV_IA64_P34 = 738, + CV_IA64_P35 = 739, + CV_IA64_P36 = 740, + CV_IA64_P37 = 741, + CV_IA64_P38 = 742, + CV_IA64_P39 = 743, + CV_IA64_P40 = 744, + CV_IA64_P41 = 745, + CV_IA64_P42 = 746, + CV_IA64_P43 = 747, + CV_IA64_P44 = 748, + CV_IA64_P45 = 749, + CV_IA64_P46 = 750, + CV_IA64_P47 = 751, + CV_IA64_P48 = 752, + CV_IA64_P49 = 753, + CV_IA64_P50 = 754, + CV_IA64_P51 = 755, + CV_IA64_P52 = 756, + CV_IA64_P53 = 757, + CV_IA64_P54 = 758, + CV_IA64_P55 = 759, + CV_IA64_P56 = 760, + CV_IA64_P57 = 761, + CV_IA64_P58 = 762, + CV_IA64_P59 = 763, + CV_IA64_P60 = 764, + CV_IA64_P61 = 765, + CV_IA64_P62 = 766, + CV_IA64_P63 = 767, + + CV_IA64_Preds = 768, + + // Banked General Registers + + CV_IA64_IntH0 = 832, + CV_IA64_IntH1 = 833, + CV_IA64_IntH2 = 834, + CV_IA64_IntH3 = 835, + CV_IA64_IntH4 = 836, + CV_IA64_IntH5 = 837, + CV_IA64_IntH6 = 838, + CV_IA64_IntH7 = 839, + CV_IA64_IntH8 = 840, + CV_IA64_IntH9 = 841, + CV_IA64_IntH10 = 842, + CV_IA64_IntH11 = 843, + CV_IA64_IntH12 = 844, + CV_IA64_IntH13 = 845, + CV_IA64_IntH14 = 846, + CV_IA64_IntH15 = 847, + + // Special Registers + + CV_IA64_Ip = 1016, + CV_IA64_Umask = 1017, + CV_IA64_Cfm = 1018, + CV_IA64_Psr = 1019, + + // Banked General Registers + + CV_IA64_Nats = 1020, + CV_IA64_Nats2 = 1021, + CV_IA64_Nats3 = 1022, + + // General-Purpose Registers + + // Integer registers + CV_IA64_IntR0 = 1024, + CV_IA64_IntR1 = 1025, + CV_IA64_IntR2 = 1026, + CV_IA64_IntR3 = 1027, + CV_IA64_IntR4 = 1028, + CV_IA64_IntR5 = 1029, + CV_IA64_IntR6 = 1030, + CV_IA64_IntR7 = 1031, + CV_IA64_IntR8 = 1032, + CV_IA64_IntR9 = 1033, + CV_IA64_IntR10 = 1034, + CV_IA64_IntR11 = 1035, + CV_IA64_IntR12 = 1036, + CV_IA64_IntR13 = 1037, + CV_IA64_IntR14 = 1038, + CV_IA64_IntR15 = 1039, + CV_IA64_IntR16 = 1040, + CV_IA64_IntR17 = 1041, + CV_IA64_IntR18 = 1042, + CV_IA64_IntR19 = 1043, + CV_IA64_IntR20 = 1044, + CV_IA64_IntR21 = 1045, + CV_IA64_IntR22 = 1046, + CV_IA64_IntR23 = 1047, + CV_IA64_IntR24 = 1048, + CV_IA64_IntR25 = 1049, + CV_IA64_IntR26 = 1050, + CV_IA64_IntR27 = 1051, + CV_IA64_IntR28 = 1052, + CV_IA64_IntR29 = 1053, + CV_IA64_IntR30 = 1054, + CV_IA64_IntR31 = 1055, + + // Register Stack + CV_IA64_IntR32 = 1056, + CV_IA64_IntR33 = 1057, + CV_IA64_IntR34 = 1058, + CV_IA64_IntR35 = 1059, + CV_IA64_IntR36 = 1060, + CV_IA64_IntR37 = 1061, + CV_IA64_IntR38 = 1062, + CV_IA64_IntR39 = 1063, + CV_IA64_IntR40 = 1064, + CV_IA64_IntR41 = 1065, + CV_IA64_IntR42 = 1066, + CV_IA64_IntR43 = 1067, + CV_IA64_IntR44 = 1068, + CV_IA64_IntR45 = 1069, + CV_IA64_IntR46 = 1070, + CV_IA64_IntR47 = 1071, + CV_IA64_IntR48 = 1072, + CV_IA64_IntR49 = 1073, + CV_IA64_IntR50 = 1074, + CV_IA64_IntR51 = 1075, + CV_IA64_IntR52 = 1076, + CV_IA64_IntR53 = 1077, + CV_IA64_IntR54 = 1078, + CV_IA64_IntR55 = 1079, + CV_IA64_IntR56 = 1080, + CV_IA64_IntR57 = 1081, + CV_IA64_IntR58 = 1082, + CV_IA64_IntR59 = 1083, + CV_IA64_IntR60 = 1084, + CV_IA64_IntR61 = 1085, + CV_IA64_IntR62 = 1086, + CV_IA64_IntR63 = 1087, + CV_IA64_IntR64 = 1088, + CV_IA64_IntR65 = 1089, + CV_IA64_IntR66 = 1090, + CV_IA64_IntR67 = 1091, + CV_IA64_IntR68 = 1092, + CV_IA64_IntR69 = 1093, + CV_IA64_IntR70 = 1094, + CV_IA64_IntR71 = 1095, + CV_IA64_IntR72 = 1096, + CV_IA64_IntR73 = 1097, + CV_IA64_IntR74 = 1098, + CV_IA64_IntR75 = 1099, + CV_IA64_IntR76 = 1100, + CV_IA64_IntR77 = 1101, + CV_IA64_IntR78 = 1102, + CV_IA64_IntR79 = 1103, + CV_IA64_IntR80 = 1104, + CV_IA64_IntR81 = 1105, + CV_IA64_IntR82 = 1106, + CV_IA64_IntR83 = 1107, + CV_IA64_IntR84 = 1108, + CV_IA64_IntR85 = 1109, + CV_IA64_IntR86 = 1110, + CV_IA64_IntR87 = 1111, + CV_IA64_IntR88 = 1112, + CV_IA64_IntR89 = 1113, + CV_IA64_IntR90 = 1114, + CV_IA64_IntR91 = 1115, + CV_IA64_IntR92 = 1116, + CV_IA64_IntR93 = 1117, + CV_IA64_IntR94 = 1118, + CV_IA64_IntR95 = 1119, + CV_IA64_IntR96 = 1120, + CV_IA64_IntR97 = 1121, + CV_IA64_IntR98 = 1122, + CV_IA64_IntR99 = 1123, + CV_IA64_IntR100 = 1124, + CV_IA64_IntR101 = 1125, + CV_IA64_IntR102 = 1126, + CV_IA64_IntR103 = 1127, + CV_IA64_IntR104 = 1128, + CV_IA64_IntR105 = 1129, + CV_IA64_IntR106 = 1130, + CV_IA64_IntR107 = 1131, + CV_IA64_IntR108 = 1132, + CV_IA64_IntR109 = 1133, + CV_IA64_IntR110 = 1134, + CV_IA64_IntR111 = 1135, + CV_IA64_IntR112 = 1136, + CV_IA64_IntR113 = 1137, + CV_IA64_IntR114 = 1138, + CV_IA64_IntR115 = 1139, + CV_IA64_IntR116 = 1140, + CV_IA64_IntR117 = 1141, + CV_IA64_IntR118 = 1142, + CV_IA64_IntR119 = 1143, + CV_IA64_IntR120 = 1144, + CV_IA64_IntR121 = 1145, + CV_IA64_IntR122 = 1146, + CV_IA64_IntR123 = 1147, + CV_IA64_IntR124 = 1148, + CV_IA64_IntR125 = 1149, + CV_IA64_IntR126 = 1150, + CV_IA64_IntR127 = 1151, + + // Floating-Point Registers + + // Low Floating Point Registers + CV_IA64_FltF0 = 2048, + CV_IA64_FltF1 = 2049, + CV_IA64_FltF2 = 2050, + CV_IA64_FltF3 = 2051, + CV_IA64_FltF4 = 2052, + CV_IA64_FltF5 = 2053, + CV_IA64_FltF6 = 2054, + CV_IA64_FltF7 = 2055, + CV_IA64_FltF8 = 2056, + CV_IA64_FltF9 = 2057, + CV_IA64_FltF10 = 2058, + CV_IA64_FltF11 = 2059, + CV_IA64_FltF12 = 2060, + CV_IA64_FltF13 = 2061, + CV_IA64_FltF14 = 2062, + CV_IA64_FltF15 = 2063, + CV_IA64_FltF16 = 2064, + CV_IA64_FltF17 = 2065, + CV_IA64_FltF18 = 2066, + CV_IA64_FltF19 = 2067, + CV_IA64_FltF20 = 2068, + CV_IA64_FltF21 = 2069, + CV_IA64_FltF22 = 2070, + CV_IA64_FltF23 = 2071, + CV_IA64_FltF24 = 2072, + CV_IA64_FltF25 = 2073, + CV_IA64_FltF26 = 2074, + CV_IA64_FltF27 = 2075, + CV_IA64_FltF28 = 2076, + CV_IA64_FltF29 = 2077, + CV_IA64_FltF30 = 2078, + CV_IA64_FltF31 = 2079, + + // High Floating Point Registers + CV_IA64_FltF32 = 2080, + CV_IA64_FltF33 = 2081, + CV_IA64_FltF34 = 2082, + CV_IA64_FltF35 = 2083, + CV_IA64_FltF36 = 2084, + CV_IA64_FltF37 = 2085, + CV_IA64_FltF38 = 2086, + CV_IA64_FltF39 = 2087, + CV_IA64_FltF40 = 2088, + CV_IA64_FltF41 = 2089, + CV_IA64_FltF42 = 2090, + CV_IA64_FltF43 = 2091, + CV_IA64_FltF44 = 2092, + CV_IA64_FltF45 = 2093, + CV_IA64_FltF46 = 2094, + CV_IA64_FltF47 = 2095, + CV_IA64_FltF48 = 2096, + CV_IA64_FltF49 = 2097, + CV_IA64_FltF50 = 2098, + CV_IA64_FltF51 = 2099, + CV_IA64_FltF52 = 2100, + CV_IA64_FltF53 = 2101, + CV_IA64_FltF54 = 2102, + CV_IA64_FltF55 = 2103, + CV_IA64_FltF56 = 2104, + CV_IA64_FltF57 = 2105, + CV_IA64_FltF58 = 2106, + CV_IA64_FltF59 = 2107, + CV_IA64_FltF60 = 2108, + CV_IA64_FltF61 = 2109, + CV_IA64_FltF62 = 2110, + CV_IA64_FltF63 = 2111, + CV_IA64_FltF64 = 2112, + CV_IA64_FltF65 = 2113, + CV_IA64_FltF66 = 2114, + CV_IA64_FltF67 = 2115, + CV_IA64_FltF68 = 2116, + CV_IA64_FltF69 = 2117, + CV_IA64_FltF70 = 2118, + CV_IA64_FltF71 = 2119, + CV_IA64_FltF72 = 2120, + CV_IA64_FltF73 = 2121, + CV_IA64_FltF74 = 2122, + CV_IA64_FltF75 = 2123, + CV_IA64_FltF76 = 2124, + CV_IA64_FltF77 = 2125, + CV_IA64_FltF78 = 2126, + CV_IA64_FltF79 = 2127, + CV_IA64_FltF80 = 2128, + CV_IA64_FltF81 = 2129, + CV_IA64_FltF82 = 2130, + CV_IA64_FltF83 = 2131, + CV_IA64_FltF84 = 2132, + CV_IA64_FltF85 = 2133, + CV_IA64_FltF86 = 2134, + CV_IA64_FltF87 = 2135, + CV_IA64_FltF88 = 2136, + CV_IA64_FltF89 = 2137, + CV_IA64_FltF90 = 2138, + CV_IA64_FltF91 = 2139, + CV_IA64_FltF92 = 2140, + CV_IA64_FltF93 = 2141, + CV_IA64_FltF94 = 2142, + CV_IA64_FltF95 = 2143, + CV_IA64_FltF96 = 2144, + CV_IA64_FltF97 = 2145, + CV_IA64_FltF98 = 2146, + CV_IA64_FltF99 = 2147, + CV_IA64_FltF100 = 2148, + CV_IA64_FltF101 = 2149, + CV_IA64_FltF102 = 2150, + CV_IA64_FltF103 = 2151, + CV_IA64_FltF104 = 2152, + CV_IA64_FltF105 = 2153, + CV_IA64_FltF106 = 2154, + CV_IA64_FltF107 = 2155, + CV_IA64_FltF108 = 2156, + CV_IA64_FltF109 = 2157, + CV_IA64_FltF110 = 2158, + CV_IA64_FltF111 = 2159, + CV_IA64_FltF112 = 2160, + CV_IA64_FltF113 = 2161, + CV_IA64_FltF114 = 2162, + CV_IA64_FltF115 = 2163, + CV_IA64_FltF116 = 2164, + CV_IA64_FltF117 = 2165, + CV_IA64_FltF118 = 2166, + CV_IA64_FltF119 = 2167, + CV_IA64_FltF120 = 2168, + CV_IA64_FltF121 = 2169, + CV_IA64_FltF122 = 2170, + CV_IA64_FltF123 = 2171, + CV_IA64_FltF124 = 2172, + CV_IA64_FltF125 = 2173, + CV_IA64_FltF126 = 2174, + CV_IA64_FltF127 = 2175, + + // Application Registers + + CV_IA64_ApKR0 = 3072, + CV_IA64_ApKR1 = 3073, + CV_IA64_ApKR2 = 3074, + CV_IA64_ApKR3 = 3075, + CV_IA64_ApKR4 = 3076, + CV_IA64_ApKR5 = 3077, + CV_IA64_ApKR6 = 3078, + CV_IA64_ApKR7 = 3079, + CV_IA64_AR8 = 3080, + CV_IA64_AR9 = 3081, + CV_IA64_AR10 = 3082, + CV_IA64_AR11 = 3083, + CV_IA64_AR12 = 3084, + CV_IA64_AR13 = 3085, + CV_IA64_AR14 = 3086, + CV_IA64_AR15 = 3087, + CV_IA64_RsRSC = 3088, + CV_IA64_RsBSP = 3089, + CV_IA64_RsBSPSTORE = 3090, + CV_IA64_RsRNAT = 3091, + CV_IA64_AR20 = 3092, + CV_IA64_StFCR = 3093, + CV_IA64_AR22 = 3094, + CV_IA64_AR23 = 3095, + CV_IA64_EFLAG = 3096, + CV_IA64_CSD = 3097, + CV_IA64_SSD = 3098, + CV_IA64_CFLG = 3099, + CV_IA64_StFSR = 3100, + CV_IA64_StFIR = 3101, + CV_IA64_StFDR = 3102, + CV_IA64_AR31 = 3103, + CV_IA64_ApCCV = 3104, + CV_IA64_AR33 = 3105, + CV_IA64_AR34 = 3106, + CV_IA64_AR35 = 3107, + CV_IA64_ApUNAT = 3108, + CV_IA64_AR37 = 3109, + CV_IA64_AR38 = 3110, + CV_IA64_AR39 = 3111, + CV_IA64_StFPSR = 3112, + CV_IA64_AR41 = 3113, + CV_IA64_AR42 = 3114, + CV_IA64_AR43 = 3115, + CV_IA64_ApITC = 3116, + CV_IA64_AR45 = 3117, + CV_IA64_AR46 = 3118, + CV_IA64_AR47 = 3119, + CV_IA64_AR48 = 3120, + CV_IA64_AR49 = 3121, + CV_IA64_AR50 = 3122, + CV_IA64_AR51 = 3123, + CV_IA64_AR52 = 3124, + CV_IA64_AR53 = 3125, + CV_IA64_AR54 = 3126, + CV_IA64_AR55 = 3127, + CV_IA64_AR56 = 3128, + CV_IA64_AR57 = 3129, + CV_IA64_AR58 = 3130, + CV_IA64_AR59 = 3131, + CV_IA64_AR60 = 3132, + CV_IA64_AR61 = 3133, + CV_IA64_AR62 = 3134, + CV_IA64_AR63 = 3135, + CV_IA64_RsPFS = 3136, + CV_IA64_ApLC = 3137, + CV_IA64_ApEC = 3138, + CV_IA64_AR67 = 3139, + CV_IA64_AR68 = 3140, + CV_IA64_AR69 = 3141, + CV_IA64_AR70 = 3142, + CV_IA64_AR71 = 3143, + CV_IA64_AR72 = 3144, + CV_IA64_AR73 = 3145, + CV_IA64_AR74 = 3146, + CV_IA64_AR75 = 3147, + CV_IA64_AR76 = 3148, + CV_IA64_AR77 = 3149, + CV_IA64_AR78 = 3150, + CV_IA64_AR79 = 3151, + CV_IA64_AR80 = 3152, + CV_IA64_AR81 = 3153, + CV_IA64_AR82 = 3154, + CV_IA64_AR83 = 3155, + CV_IA64_AR84 = 3156, + CV_IA64_AR85 = 3157, + CV_IA64_AR86 = 3158, + CV_IA64_AR87 = 3159, + CV_IA64_AR88 = 3160, + CV_IA64_AR89 = 3161, + CV_IA64_AR90 = 3162, + CV_IA64_AR91 = 3163, + CV_IA64_AR92 = 3164, + CV_IA64_AR93 = 3165, + CV_IA64_AR94 = 3166, + CV_IA64_AR95 = 3167, + CV_IA64_AR96 = 3168, + CV_IA64_AR97 = 3169, + CV_IA64_AR98 = 3170, + CV_IA64_AR99 = 3171, + CV_IA64_AR100 = 3172, + CV_IA64_AR101 = 3173, + CV_IA64_AR102 = 3174, + CV_IA64_AR103 = 3175, + CV_IA64_AR104 = 3176, + CV_IA64_AR105 = 3177, + CV_IA64_AR106 = 3178, + CV_IA64_AR107 = 3179, + CV_IA64_AR108 = 3180, + CV_IA64_AR109 = 3181, + CV_IA64_AR110 = 3182, + CV_IA64_AR111 = 3183, + CV_IA64_AR112 = 3184, + CV_IA64_AR113 = 3185, + CV_IA64_AR114 = 3186, + CV_IA64_AR115 = 3187, + CV_IA64_AR116 = 3188, + CV_IA64_AR117 = 3189, + CV_IA64_AR118 = 3190, + CV_IA64_AR119 = 3191, + CV_IA64_AR120 = 3192, + CV_IA64_AR121 = 3193, + CV_IA64_AR122 = 3194, + CV_IA64_AR123 = 3195, + CV_IA64_AR124 = 3196, + CV_IA64_AR125 = 3197, + CV_IA64_AR126 = 3198, + CV_IA64_AR127 = 3199, + + // CPUID Registers + + CV_IA64_CPUID0 = 3328, + CV_IA64_CPUID1 = 3329, + CV_IA64_CPUID2 = 3330, + CV_IA64_CPUID3 = 3331, + CV_IA64_CPUID4 = 3332, + + // Control Registers + + CV_IA64_ApDCR = 4096, + CV_IA64_ApITM = 4097, + CV_IA64_ApIVA = 4098, + CV_IA64_CR3 = 4099, + CV_IA64_CR4 = 4100, + CV_IA64_CR5 = 4101, + CV_IA64_CR6 = 4102, + CV_IA64_CR7 = 4103, + CV_IA64_ApPTA = 4104, + CV_IA64_ApGPTA = 4105, + CV_IA64_CR10 = 4106, + CV_IA64_CR11 = 4107, + CV_IA64_CR12 = 4108, + CV_IA64_CR13 = 4109, + CV_IA64_CR14 = 4110, + CV_IA64_CR15 = 4111, + CV_IA64_StIPSR = 4112, + CV_IA64_StISR = 4113, + CV_IA64_CR18 = 4114, + CV_IA64_StIIP = 4115, + CV_IA64_StIFA = 4116, + CV_IA64_StITIR = 4117, + CV_IA64_StIIPA = 4118, + CV_IA64_StIFS = 4119, + CV_IA64_StIIM = 4120, + CV_IA64_StIHA = 4121, + CV_IA64_CR26 = 4122, + CV_IA64_CR27 = 4123, + CV_IA64_CR28 = 4124, + CV_IA64_CR29 = 4125, + CV_IA64_CR30 = 4126, + CV_IA64_CR31 = 4127, + CV_IA64_CR32 = 4128, + CV_IA64_CR33 = 4129, + CV_IA64_CR34 = 4130, + CV_IA64_CR35 = 4131, + CV_IA64_CR36 = 4132, + CV_IA64_CR37 = 4133, + CV_IA64_CR38 = 4134, + CV_IA64_CR39 = 4135, + CV_IA64_CR40 = 4136, + CV_IA64_CR41 = 4137, + CV_IA64_CR42 = 4138, + CV_IA64_CR43 = 4139, + CV_IA64_CR44 = 4140, + CV_IA64_CR45 = 4141, + CV_IA64_CR46 = 4142, + CV_IA64_CR47 = 4143, + CV_IA64_CR48 = 4144, + CV_IA64_CR49 = 4145, + CV_IA64_CR50 = 4146, + CV_IA64_CR51 = 4147, + CV_IA64_CR52 = 4148, + CV_IA64_CR53 = 4149, + CV_IA64_CR54 = 4150, + CV_IA64_CR55 = 4151, + CV_IA64_CR56 = 4152, + CV_IA64_CR57 = 4153, + CV_IA64_CR58 = 4154, + CV_IA64_CR59 = 4155, + CV_IA64_CR60 = 4156, + CV_IA64_CR61 = 4157, + CV_IA64_CR62 = 4158, + CV_IA64_CR63 = 4159, + CV_IA64_SaLID = 4160, + CV_IA64_SaIVR = 4161, + CV_IA64_SaTPR = 4162, + CV_IA64_SaEOI = 4163, + CV_IA64_SaIRR0 = 4164, + CV_IA64_SaIRR1 = 4165, + CV_IA64_SaIRR2 = 4166, + CV_IA64_SaIRR3 = 4167, + CV_IA64_SaITV = 4168, + CV_IA64_SaPMV = 4169, + CV_IA64_SaCMCV = 4170, + CV_IA64_CR75 = 4171, + CV_IA64_CR76 = 4172, + CV_IA64_CR77 = 4173, + CV_IA64_CR78 = 4174, + CV_IA64_CR79 = 4175, + CV_IA64_SaLRR0 = 4176, + CV_IA64_SaLRR1 = 4177, + CV_IA64_CR82 = 4178, + CV_IA64_CR83 = 4179, + CV_IA64_CR84 = 4180, + CV_IA64_CR85 = 4181, + CV_IA64_CR86 = 4182, + CV_IA64_CR87 = 4183, + CV_IA64_CR88 = 4184, + CV_IA64_CR89 = 4185, + CV_IA64_CR90 = 4186, + CV_IA64_CR91 = 4187, + CV_IA64_CR92 = 4188, + CV_IA64_CR93 = 4189, + CV_IA64_CR94 = 4190, + CV_IA64_CR95 = 4191, + CV_IA64_CR96 = 4192, + CV_IA64_CR97 = 4193, + CV_IA64_CR98 = 4194, + CV_IA64_CR99 = 4195, + CV_IA64_CR100 = 4196, + CV_IA64_CR101 = 4197, + CV_IA64_CR102 = 4198, + CV_IA64_CR103 = 4199, + CV_IA64_CR104 = 4200, + CV_IA64_CR105 = 4201, + CV_IA64_CR106 = 4202, + CV_IA64_CR107 = 4203, + CV_IA64_CR108 = 4204, + CV_IA64_CR109 = 4205, + CV_IA64_CR110 = 4206, + CV_IA64_CR111 = 4207, + CV_IA64_CR112 = 4208, + CV_IA64_CR113 = 4209, + CV_IA64_CR114 = 4210, + CV_IA64_CR115 = 4211, + CV_IA64_CR116 = 4212, + CV_IA64_CR117 = 4213, + CV_IA64_CR118 = 4214, + CV_IA64_CR119 = 4215, + CV_IA64_CR120 = 4216, + CV_IA64_CR121 = 4217, + CV_IA64_CR122 = 4218, + CV_IA64_CR123 = 4219, + CV_IA64_CR124 = 4220, + CV_IA64_CR125 = 4221, + CV_IA64_CR126 = 4222, + CV_IA64_CR127 = 4223, + + // Protection Key Registers + + CV_IA64_Pkr0 = 5120, + CV_IA64_Pkr1 = 5121, + CV_IA64_Pkr2 = 5122, + CV_IA64_Pkr3 = 5123, + CV_IA64_Pkr4 = 5124, + CV_IA64_Pkr5 = 5125, + CV_IA64_Pkr6 = 5126, + CV_IA64_Pkr7 = 5127, + CV_IA64_Pkr8 = 5128, + CV_IA64_Pkr9 = 5129, + CV_IA64_Pkr10 = 5130, + CV_IA64_Pkr11 = 5131, + CV_IA64_Pkr12 = 5132, + CV_IA64_Pkr13 = 5133, + CV_IA64_Pkr14 = 5134, + CV_IA64_Pkr15 = 5135, + + // Region Registers + + CV_IA64_Rr0 = 6144, + CV_IA64_Rr1 = 6145, + CV_IA64_Rr2 = 6146, + CV_IA64_Rr3 = 6147, + CV_IA64_Rr4 = 6148, + CV_IA64_Rr5 = 6149, + CV_IA64_Rr6 = 6150, + CV_IA64_Rr7 = 6151, + + // Performance Monitor Data Registers + + CV_IA64_PFD0 = 7168, + CV_IA64_PFD1 = 7169, + CV_IA64_PFD2 = 7170, + CV_IA64_PFD3 = 7171, + CV_IA64_PFD4 = 7172, + CV_IA64_PFD5 = 7173, + CV_IA64_PFD6 = 7174, + CV_IA64_PFD7 = 7175, + CV_IA64_PFD8 = 7176, + CV_IA64_PFD9 = 7177, + CV_IA64_PFD10 = 7178, + CV_IA64_PFD11 = 7179, + CV_IA64_PFD12 = 7180, + CV_IA64_PFD13 = 7181, + CV_IA64_PFD14 = 7182, + CV_IA64_PFD15 = 7183, + CV_IA64_PFD16 = 7184, + CV_IA64_PFD17 = 7185, + + // Performance Monitor Config Registers + + CV_IA64_PFC0 = 7424, + CV_IA64_PFC1 = 7425, + CV_IA64_PFC2 = 7426, + CV_IA64_PFC3 = 7427, + CV_IA64_PFC4 = 7428, + CV_IA64_PFC5 = 7429, + CV_IA64_PFC6 = 7430, + CV_IA64_PFC7 = 7431, + CV_IA64_PFC8 = 7432, + CV_IA64_PFC9 = 7433, + CV_IA64_PFC10 = 7434, + CV_IA64_PFC11 = 7435, + CV_IA64_PFC12 = 7436, + CV_IA64_PFC13 = 7437, + CV_IA64_PFC14 = 7438, + CV_IA64_PFC15 = 7439, + + // Instruction Translation Registers + + CV_IA64_TrI0 = 8192, + CV_IA64_TrI1 = 8193, + CV_IA64_TrI2 = 8194, + CV_IA64_TrI3 = 8195, + CV_IA64_TrI4 = 8196, + CV_IA64_TrI5 = 8197, + CV_IA64_TrI6 = 8198, + CV_IA64_TrI7 = 8199, + + // Data Translation Registers + + CV_IA64_TrD0 = 8320, + CV_IA64_TrD1 = 8321, + CV_IA64_TrD2 = 8322, + CV_IA64_TrD3 = 8323, + CV_IA64_TrD4 = 8324, + CV_IA64_TrD5 = 8325, + CV_IA64_TrD6 = 8326, + CV_IA64_TrD7 = 8327, + + // Instruction Breakpoint Registers + + CV_IA64_DbI0 = 8448, + CV_IA64_DbI1 = 8449, + CV_IA64_DbI2 = 8450, + CV_IA64_DbI3 = 8451, + CV_IA64_DbI4 = 8452, + CV_IA64_DbI5 = 8453, + CV_IA64_DbI6 = 8454, + CV_IA64_DbI7 = 8455, + + // Data Breakpoint Registers + + CV_IA64_DbD0 = 8576, + CV_IA64_DbD1 = 8577, + CV_IA64_DbD2 = 8578, + CV_IA64_DbD3 = 8579, + CV_IA64_DbD4 = 8580, + CV_IA64_DbD5 = 8581, + CV_IA64_DbD6 = 8582, + CV_IA64_DbD7 = 8583, + + // + // Register set for the TriCore processor. + // + + CV_TRI_NOREG = CV_REG_NONE, + + // General Purpose Data Registers + + CV_TRI_D0 = 10, + CV_TRI_D1 = 11, + CV_TRI_D2 = 12, + CV_TRI_D3 = 13, + CV_TRI_D4 = 14, + CV_TRI_D5 = 15, + CV_TRI_D6 = 16, + CV_TRI_D7 = 17, + CV_TRI_D8 = 18, + CV_TRI_D9 = 19, + CV_TRI_D10 = 20, + CV_TRI_D11 = 21, + CV_TRI_D12 = 22, + CV_TRI_D13 = 23, + CV_TRI_D14 = 24, + CV_TRI_D15 = 25, + + // General Purpose Address Registers + + CV_TRI_A0 = 26, + CV_TRI_A1 = 27, + CV_TRI_A2 = 28, + CV_TRI_A3 = 29, + CV_TRI_A4 = 30, + CV_TRI_A5 = 31, + CV_TRI_A6 = 32, + CV_TRI_A7 = 33, + CV_TRI_A8 = 34, + CV_TRI_A9 = 35, + CV_TRI_A10 = 36, + CV_TRI_A11 = 37, + CV_TRI_A12 = 38, + CV_TRI_A13 = 39, + CV_TRI_A14 = 40, + CV_TRI_A15 = 41, + + // Extended (64-bit) data registers + + CV_TRI_E0 = 42, + CV_TRI_E2 = 43, + CV_TRI_E4 = 44, + CV_TRI_E6 = 45, + CV_TRI_E8 = 46, + CV_TRI_E10 = 47, + CV_TRI_E12 = 48, + CV_TRI_E14 = 49, + + // Extended (64-bit) address registers + + CV_TRI_EA0 = 50, + CV_TRI_EA2 = 51, + CV_TRI_EA4 = 52, + CV_TRI_EA6 = 53, + CV_TRI_EA8 = 54, + CV_TRI_EA10 = 55, + CV_TRI_EA12 = 56, + CV_TRI_EA14 = 57, + + CV_TRI_PSW = 58, + CV_TRI_PCXI = 59, + CV_TRI_PC = 60, + CV_TRI_FCX = 61, + CV_TRI_LCX = 62, + CV_TRI_ISP = 63, + CV_TRI_ICR = 64, + CV_TRI_BIV = 65, + CV_TRI_BTV = 66, + CV_TRI_SYSCON = 67, + CV_TRI_DPRx_0 = 68, + CV_TRI_DPRx_1 = 69, + CV_TRI_DPRx_2 = 70, + CV_TRI_DPRx_3 = 71, + CV_TRI_CPRx_0 = 68, + CV_TRI_CPRx_1 = 69, + CV_TRI_CPRx_2 = 70, + CV_TRI_CPRx_3 = 71, + CV_TRI_DPMx_0 = 68, + CV_TRI_DPMx_1 = 69, + CV_TRI_DPMx_2 = 70, + CV_TRI_DPMx_3 = 71, + CV_TRI_CPMx_0 = 68, + CV_TRI_CPMx_1 = 69, + CV_TRI_CPMx_2 = 70, + CV_TRI_CPMx_3 = 71, + CV_TRI_DBGSSR = 72, + CV_TRI_EXEVT = 73, + CV_TRI_SWEVT = 74, + CV_TRI_CREVT = 75, + CV_TRI_TRnEVT = 76, + CV_TRI_MMUCON = 77, + CV_TRI_ASI = 78, + CV_TRI_TVA = 79, + CV_TRI_TPA = 80, + CV_TRI_TPX = 81, + CV_TRI_TFA = 82, + + // + // Register set for the AM33 and related processors. + // + + CV_AM33_NOREG = CV_REG_NONE, + + // "Extended" (general purpose integer) registers + CV_AM33_E0 = 10, + CV_AM33_E1 = 11, + CV_AM33_E2 = 12, + CV_AM33_E3 = 13, + CV_AM33_E4 = 14, + CV_AM33_E5 = 15, + CV_AM33_E6 = 16, + CV_AM33_E7 = 17, + + // Address registers + CV_AM33_A0 = 20, + CV_AM33_A1 = 21, + CV_AM33_A2 = 22, + CV_AM33_A3 = 23, + + // Integer data registers + CV_AM33_D0 = 30, + CV_AM33_D1 = 31, + CV_AM33_D2 = 32, + CV_AM33_D3 = 33, + + // (Single-precision) floating-point registers + CV_AM33_FS0 = 40, + CV_AM33_FS1 = 41, + CV_AM33_FS2 = 42, + CV_AM33_FS3 = 43, + CV_AM33_FS4 = 44, + CV_AM33_FS5 = 45, + CV_AM33_FS6 = 46, + CV_AM33_FS7 = 47, + CV_AM33_FS8 = 48, + CV_AM33_FS9 = 49, + CV_AM33_FS10 = 50, + CV_AM33_FS11 = 51, + CV_AM33_FS12 = 52, + CV_AM33_FS13 = 53, + CV_AM33_FS14 = 54, + CV_AM33_FS15 = 55, + CV_AM33_FS16 = 56, + CV_AM33_FS17 = 57, + CV_AM33_FS18 = 58, + CV_AM33_FS19 = 59, + CV_AM33_FS20 = 60, + CV_AM33_FS21 = 61, + CV_AM33_FS22 = 62, + CV_AM33_FS23 = 63, + CV_AM33_FS24 = 64, + CV_AM33_FS25 = 65, + CV_AM33_FS26 = 66, + CV_AM33_FS27 = 67, + CV_AM33_FS28 = 68, + CV_AM33_FS29 = 69, + CV_AM33_FS30 = 70, + CV_AM33_FS31 = 71, + + // Special purpose registers + + // Stack pointer + CV_AM33_SP = 80, + + // Program counter + CV_AM33_PC = 81, + + // Multiply-divide/accumulate registers + CV_AM33_MDR = 82, + CV_AM33_MDRQ = 83, + CV_AM33_MCRH = 84, + CV_AM33_MCRL = 85, + CV_AM33_MCVF = 86, + + // CPU status words + CV_AM33_EPSW = 87, + CV_AM33_FPCR = 88, + + // Loop buffer registers + CV_AM33_LIR = 89, + CV_AM33_LAR = 90, + + // + // Register set for the Mitsubishi M32R + // + + CV_M32R_NOREG = CV_REG_NONE, + + CV_M32R_R0 = 10, + CV_M32R_R1 = 11, + CV_M32R_R2 = 12, + CV_M32R_R3 = 13, + CV_M32R_R4 = 14, + CV_M32R_R5 = 15, + CV_M32R_R6 = 16, + CV_M32R_R7 = 17, + CV_M32R_R8 = 18, + CV_M32R_R9 = 19, + CV_M32R_R10 = 20, + CV_M32R_R11 = 21, + CV_M32R_R12 = 22, // Gloabal Pointer, if used + CV_M32R_R13 = 23, // Frame Pointer, if allocated + CV_M32R_R14 = 24, // Link Register + CV_M32R_R15 = 25, // Stack Pointer + CV_M32R_PSW = 26, // Preocessor Status Register + CV_M32R_CBR = 27, // Condition Bit Register + CV_M32R_SPI = 28, // Interrupt Stack Pointer + CV_M32R_SPU = 29, // User Stack Pointer + CV_M32R_SPO = 30, // OS Stack Pointer + CV_M32R_BPC = 31, // Backup Program Counter + CV_M32R_ACHI = 32, // Accumulator High + CV_M32R_ACLO = 33, // Accumulator Low + CV_M32R_PC = 34, // Program Counter + + // + // Register set for the SuperH SHMedia processor including compact + // mode + // + + // Integer - 64 bit general registers + CV_SHMEDIA_NOREG = CV_REG_NONE, + CV_SHMEDIA_R0 = 10, + CV_SHMEDIA_R1 = 11, + CV_SHMEDIA_R2 = 12, + CV_SHMEDIA_R3 = 13, + CV_SHMEDIA_R4 = 14, + CV_SHMEDIA_R5 = 15, + CV_SHMEDIA_R6 = 16, + CV_SHMEDIA_R7 = 17, + CV_SHMEDIA_R8 = 18, + CV_SHMEDIA_R9 = 19, + CV_SHMEDIA_R10 = 20, + CV_SHMEDIA_R11 = 21, + CV_SHMEDIA_R12 = 22, + CV_SHMEDIA_R13 = 23, + CV_SHMEDIA_R14 = 24, + CV_SHMEDIA_R15 = 25, + CV_SHMEDIA_R16 = 26, + CV_SHMEDIA_R17 = 27, + CV_SHMEDIA_R18 = 28, + CV_SHMEDIA_R19 = 29, + CV_SHMEDIA_R20 = 30, + CV_SHMEDIA_R21 = 31, + CV_SHMEDIA_R22 = 32, + CV_SHMEDIA_R23 = 33, + CV_SHMEDIA_R24 = 34, + CV_SHMEDIA_R25 = 35, + CV_SHMEDIA_R26 = 36, + CV_SHMEDIA_R27 = 37, + CV_SHMEDIA_R28 = 38, + CV_SHMEDIA_R29 = 39, + CV_SHMEDIA_R30 = 40, + CV_SHMEDIA_R31 = 41, + CV_SHMEDIA_R32 = 42, + CV_SHMEDIA_R33 = 43, + CV_SHMEDIA_R34 = 44, + CV_SHMEDIA_R35 = 45, + CV_SHMEDIA_R36 = 46, + CV_SHMEDIA_R37 = 47, + CV_SHMEDIA_R38 = 48, + CV_SHMEDIA_R39 = 49, + CV_SHMEDIA_R40 = 50, + CV_SHMEDIA_R41 = 51, + CV_SHMEDIA_R42 = 52, + CV_SHMEDIA_R43 = 53, + CV_SHMEDIA_R44 = 54, + CV_SHMEDIA_R45 = 55, + CV_SHMEDIA_R46 = 56, + CV_SHMEDIA_R47 = 57, + CV_SHMEDIA_R48 = 58, + CV_SHMEDIA_R49 = 59, + CV_SHMEDIA_R50 = 60, + CV_SHMEDIA_R51 = 61, + CV_SHMEDIA_R52 = 62, + CV_SHMEDIA_R53 = 63, + CV_SHMEDIA_R54 = 64, + CV_SHMEDIA_R55 = 65, + CV_SHMEDIA_R56 = 66, + CV_SHMEDIA_R57 = 67, + CV_SHMEDIA_R58 = 68, + CV_SHMEDIA_R59 = 69, + CV_SHMEDIA_R60 = 70, + CV_SHMEDIA_R61 = 71, + CV_SHMEDIA_R62 = 72, + CV_SHMEDIA_R63 = 73, + + // Target Registers - 32 bit + CV_SHMEDIA_TR0 = 74, + CV_SHMEDIA_TR1 = 75, + CV_SHMEDIA_TR2 = 76, + CV_SHMEDIA_TR3 = 77, + CV_SHMEDIA_TR4 = 78, + CV_SHMEDIA_TR5 = 79, + CV_SHMEDIA_TR6 = 80, + CV_SHMEDIA_TR7 = 81, + CV_SHMEDIA_TR8 = 82, // future-proof + CV_SHMEDIA_TR9 = 83, // future-proof + CV_SHMEDIA_TR10 = 84, // future-proof + CV_SHMEDIA_TR11 = 85, // future-proof + CV_SHMEDIA_TR12 = 86, // future-proof + CV_SHMEDIA_TR13 = 87, // future-proof + CV_SHMEDIA_TR14 = 88, // future-proof + CV_SHMEDIA_TR15 = 89, // future-proof + + // Single - 32 bit fp registers + CV_SHMEDIA_FR0 = 128, + CV_SHMEDIA_FR1 = 129, + CV_SHMEDIA_FR2 = 130, + CV_SHMEDIA_FR3 = 131, + CV_SHMEDIA_FR4 = 132, + CV_SHMEDIA_FR5 = 133, + CV_SHMEDIA_FR6 = 134, + CV_SHMEDIA_FR7 = 135, + CV_SHMEDIA_FR8 = 136, + CV_SHMEDIA_FR9 = 137, + CV_SHMEDIA_FR10 = 138, + CV_SHMEDIA_FR11 = 139, + CV_SHMEDIA_FR12 = 140, + CV_SHMEDIA_FR13 = 141, + CV_SHMEDIA_FR14 = 142, + CV_SHMEDIA_FR15 = 143, + CV_SHMEDIA_FR16 = 144, + CV_SHMEDIA_FR17 = 145, + CV_SHMEDIA_FR18 = 146, + CV_SHMEDIA_FR19 = 147, + CV_SHMEDIA_FR20 = 148, + CV_SHMEDIA_FR21 = 149, + CV_SHMEDIA_FR22 = 150, + CV_SHMEDIA_FR23 = 151, + CV_SHMEDIA_FR24 = 152, + CV_SHMEDIA_FR25 = 153, + CV_SHMEDIA_FR26 = 154, + CV_SHMEDIA_FR27 = 155, + CV_SHMEDIA_FR28 = 156, + CV_SHMEDIA_FR29 = 157, + CV_SHMEDIA_FR30 = 158, + CV_SHMEDIA_FR31 = 159, + CV_SHMEDIA_FR32 = 160, + CV_SHMEDIA_FR33 = 161, + CV_SHMEDIA_FR34 = 162, + CV_SHMEDIA_FR35 = 163, + CV_SHMEDIA_FR36 = 164, + CV_SHMEDIA_FR37 = 165, + CV_SHMEDIA_FR38 = 166, + CV_SHMEDIA_FR39 = 167, + CV_SHMEDIA_FR40 = 168, + CV_SHMEDIA_FR41 = 169, + CV_SHMEDIA_FR42 = 170, + CV_SHMEDIA_FR43 = 171, + CV_SHMEDIA_FR44 = 172, + CV_SHMEDIA_FR45 = 173, + CV_SHMEDIA_FR46 = 174, + CV_SHMEDIA_FR47 = 175, + CV_SHMEDIA_FR48 = 176, + CV_SHMEDIA_FR49 = 177, + CV_SHMEDIA_FR50 = 178, + CV_SHMEDIA_FR51 = 179, + CV_SHMEDIA_FR52 = 180, + CV_SHMEDIA_FR53 = 181, + CV_SHMEDIA_FR54 = 182, + CV_SHMEDIA_FR55 = 183, + CV_SHMEDIA_FR56 = 184, + CV_SHMEDIA_FR57 = 185, + CV_SHMEDIA_FR58 = 186, + CV_SHMEDIA_FR59 = 187, + CV_SHMEDIA_FR60 = 188, + CV_SHMEDIA_FR61 = 189, + CV_SHMEDIA_FR62 = 190, + CV_SHMEDIA_FR63 = 191, + + // Double - 64 bit synonyms for 32bit fp register pairs + // subtract 128 to find first base single register + CV_SHMEDIA_DR0 = 256, + CV_SHMEDIA_DR2 = 258, + CV_SHMEDIA_DR4 = 260, + CV_SHMEDIA_DR6 = 262, + CV_SHMEDIA_DR8 = 264, + CV_SHMEDIA_DR10 = 266, + CV_SHMEDIA_DR12 = 268, + CV_SHMEDIA_DR14 = 270, + CV_SHMEDIA_DR16 = 272, + CV_SHMEDIA_DR18 = 274, + CV_SHMEDIA_DR20 = 276, + CV_SHMEDIA_DR22 = 278, + CV_SHMEDIA_DR24 = 280, + CV_SHMEDIA_DR26 = 282, + CV_SHMEDIA_DR28 = 284, + CV_SHMEDIA_DR30 = 286, + CV_SHMEDIA_DR32 = 288, + CV_SHMEDIA_DR34 = 290, + CV_SHMEDIA_DR36 = 292, + CV_SHMEDIA_DR38 = 294, + CV_SHMEDIA_DR40 = 296, + CV_SHMEDIA_DR42 = 298, + CV_SHMEDIA_DR44 = 300, + CV_SHMEDIA_DR46 = 302, + CV_SHMEDIA_DR48 = 304, + CV_SHMEDIA_DR50 = 306, + CV_SHMEDIA_DR52 = 308, + CV_SHMEDIA_DR54 = 310, + CV_SHMEDIA_DR56 = 312, + CV_SHMEDIA_DR58 = 314, + CV_SHMEDIA_DR60 = 316, + CV_SHMEDIA_DR62 = 318, + + // Vector - 128 bit synonyms for 32bit fp register quads + // subtract 384 to find first base single register + CV_SHMEDIA_FV0 = 512, + CV_SHMEDIA_FV4 = 516, + CV_SHMEDIA_FV8 = 520, + CV_SHMEDIA_FV12 = 524, + CV_SHMEDIA_FV16 = 528, + CV_SHMEDIA_FV20 = 532, + CV_SHMEDIA_FV24 = 536, + CV_SHMEDIA_FV28 = 540, + CV_SHMEDIA_FV32 = 544, + CV_SHMEDIA_FV36 = 548, + CV_SHMEDIA_FV40 = 552, + CV_SHMEDIA_FV44 = 556, + CV_SHMEDIA_FV48 = 560, + CV_SHMEDIA_FV52 = 564, + CV_SHMEDIA_FV56 = 568, + CV_SHMEDIA_FV60 = 572, + + // Matrix - 512 bit synonyms for 16 adjacent 32bit fp registers + // subtract 896 to find first base single register + CV_SHMEDIA_MTRX0 = 1024, + CV_SHMEDIA_MTRX16 = 1040, + CV_SHMEDIA_MTRX32 = 1056, + CV_SHMEDIA_MTRX48 = 1072, + + // Control - Implementation defined 64bit control registers + CV_SHMEDIA_CR0 = 2000, + CV_SHMEDIA_CR1 = 2001, + CV_SHMEDIA_CR2 = 2002, + CV_SHMEDIA_CR3 = 2003, + CV_SHMEDIA_CR4 = 2004, + CV_SHMEDIA_CR5 = 2005, + CV_SHMEDIA_CR6 = 2006, + CV_SHMEDIA_CR7 = 2007, + CV_SHMEDIA_CR8 = 2008, + CV_SHMEDIA_CR9 = 2009, + CV_SHMEDIA_CR10 = 2010, + CV_SHMEDIA_CR11 = 2011, + CV_SHMEDIA_CR12 = 2012, + CV_SHMEDIA_CR13 = 2013, + CV_SHMEDIA_CR14 = 2014, + CV_SHMEDIA_CR15 = 2015, + CV_SHMEDIA_CR16 = 2016, + CV_SHMEDIA_CR17 = 2017, + CV_SHMEDIA_CR18 = 2018, + CV_SHMEDIA_CR19 = 2019, + CV_SHMEDIA_CR20 = 2020, + CV_SHMEDIA_CR21 = 2021, + CV_SHMEDIA_CR22 = 2022, + CV_SHMEDIA_CR23 = 2023, + CV_SHMEDIA_CR24 = 2024, + CV_SHMEDIA_CR25 = 2025, + CV_SHMEDIA_CR26 = 2026, + CV_SHMEDIA_CR27 = 2027, + CV_SHMEDIA_CR28 = 2028, + CV_SHMEDIA_CR29 = 2029, + CV_SHMEDIA_CR30 = 2030, + CV_SHMEDIA_CR31 = 2031, + CV_SHMEDIA_CR32 = 2032, + CV_SHMEDIA_CR33 = 2033, + CV_SHMEDIA_CR34 = 2034, + CV_SHMEDIA_CR35 = 2035, + CV_SHMEDIA_CR36 = 2036, + CV_SHMEDIA_CR37 = 2037, + CV_SHMEDIA_CR38 = 2038, + CV_SHMEDIA_CR39 = 2039, + CV_SHMEDIA_CR40 = 2040, + CV_SHMEDIA_CR41 = 2041, + CV_SHMEDIA_CR42 = 2042, + CV_SHMEDIA_CR43 = 2043, + CV_SHMEDIA_CR44 = 2044, + CV_SHMEDIA_CR45 = 2045, + CV_SHMEDIA_CR46 = 2046, + CV_SHMEDIA_CR47 = 2047, + CV_SHMEDIA_CR48 = 2048, + CV_SHMEDIA_CR49 = 2049, + CV_SHMEDIA_CR50 = 2050, + CV_SHMEDIA_CR51 = 2051, + CV_SHMEDIA_CR52 = 2052, + CV_SHMEDIA_CR53 = 2053, + CV_SHMEDIA_CR54 = 2054, + CV_SHMEDIA_CR55 = 2055, + CV_SHMEDIA_CR56 = 2056, + CV_SHMEDIA_CR57 = 2057, + CV_SHMEDIA_CR58 = 2058, + CV_SHMEDIA_CR59 = 2059, + CV_SHMEDIA_CR60 = 2060, + CV_SHMEDIA_CR61 = 2061, + CV_SHMEDIA_CR62 = 2062, + CV_SHMEDIA_CR63 = 2063, + + CV_SHMEDIA_FPSCR = 2064, + + // Compact mode synonyms + CV_SHMEDIA_GBR = CV_SHMEDIA_R16, + CV_SHMEDIA_MACL = 90, // synonym for lower 32bits of media R17 + CV_SHMEDIA_MACH = 91, // synonym for upper 32bits of media R17 + CV_SHMEDIA_PR = CV_SHMEDIA_R18, + CV_SHMEDIA_T = 92, // synonym for lowest bit of media R19 + CV_SHMEDIA_FPUL = CV_SHMEDIA_FR32, + CV_SHMEDIA_PC = 93, + CV_SHMEDIA_SR = CV_SHMEDIA_CR0, + + // + // AMD64 registers + // + + CV_AMD64_AL = 1, + CV_AMD64_CL = 2, + CV_AMD64_DL = 3, + CV_AMD64_BL = 4, + CV_AMD64_AH = 5, + CV_AMD64_CH = 6, + CV_AMD64_DH = 7, + CV_AMD64_BH = 8, + CV_AMD64_AX = 9, + CV_AMD64_CX = 10, + CV_AMD64_DX = 11, + CV_AMD64_BX = 12, + CV_AMD64_SP = 13, + CV_AMD64_BP = 14, + CV_AMD64_SI = 15, + CV_AMD64_DI = 16, + CV_AMD64_EAX = 17, + CV_AMD64_ECX = 18, + CV_AMD64_EDX = 19, + CV_AMD64_EBX = 20, + CV_AMD64_ESP = 21, + CV_AMD64_EBP = 22, + CV_AMD64_ESI = 23, + CV_AMD64_EDI = 24, + CV_AMD64_ES = 25, + CV_AMD64_CS = 26, + CV_AMD64_SS = 27, + CV_AMD64_DS = 28, + CV_AMD64_FS = 29, + CV_AMD64_GS = 30, + CV_AMD64_FLAGS = 32, + CV_AMD64_RIP = 33, + CV_AMD64_EFLAGS = 34, + + // Control registers + CV_AMD64_CR0 = 80, + CV_AMD64_CR1 = 81, + CV_AMD64_CR2 = 82, + CV_AMD64_CR3 = 83, + CV_AMD64_CR4 = 84, + CV_AMD64_CR8 = 88, + + // Debug registers + CV_AMD64_DR0 = 90, + CV_AMD64_DR1 = 91, + CV_AMD64_DR2 = 92, + CV_AMD64_DR3 = 93, + CV_AMD64_DR4 = 94, + CV_AMD64_DR5 = 95, + CV_AMD64_DR6 = 96, + CV_AMD64_DR7 = 97, + CV_AMD64_DR8 = 98, + CV_AMD64_DR9 = 99, + CV_AMD64_DR10 = 100, + CV_AMD64_DR11 = 101, + CV_AMD64_DR12 = 102, + CV_AMD64_DR13 = 103, + CV_AMD64_DR14 = 104, + CV_AMD64_DR15 = 105, + + CV_AMD64_GDTR = 110, + CV_AMD64_GDTL = 111, + CV_AMD64_IDTR = 112, + CV_AMD64_IDTL = 113, + CV_AMD64_LDTR = 114, + CV_AMD64_TR = 115, + + CV_AMD64_ST0 = 128, + CV_AMD64_ST1 = 129, + CV_AMD64_ST2 = 130, + CV_AMD64_ST3 = 131, + CV_AMD64_ST4 = 132, + CV_AMD64_ST5 = 133, + CV_AMD64_ST6 = 134, + CV_AMD64_ST7 = 135, + CV_AMD64_CTRL = 136, + CV_AMD64_STAT = 137, + CV_AMD64_TAG = 138, + CV_AMD64_FPIP = 139, + CV_AMD64_FPCS = 140, + CV_AMD64_FPDO = 141, + CV_AMD64_FPDS = 142, + CV_AMD64_ISEM = 143, + CV_AMD64_FPEIP = 144, + CV_AMD64_FPEDO = 145, + + CV_AMD64_MM0 = 146, + CV_AMD64_MM1 = 147, + CV_AMD64_MM2 = 148, + CV_AMD64_MM3 = 149, + CV_AMD64_MM4 = 150, + CV_AMD64_MM5 = 151, + CV_AMD64_MM6 = 152, + CV_AMD64_MM7 = 153, + + CV_AMD64_XMM0 = 154, // KATMAI registers + CV_AMD64_XMM1 = 155, + CV_AMD64_XMM2 = 156, + CV_AMD64_XMM3 = 157, + CV_AMD64_XMM4 = 158, + CV_AMD64_XMM5 = 159, + CV_AMD64_XMM6 = 160, + CV_AMD64_XMM7 = 161, + + CV_AMD64_XMM0_0 = 162, // KATMAI sub-registers + CV_AMD64_XMM0_1 = 163, + CV_AMD64_XMM0_2 = 164, + CV_AMD64_XMM0_3 = 165, + CV_AMD64_XMM1_0 = 166, + CV_AMD64_XMM1_1 = 167, + CV_AMD64_XMM1_2 = 168, + CV_AMD64_XMM1_3 = 169, + CV_AMD64_XMM2_0 = 170, + CV_AMD64_XMM2_1 = 171, + CV_AMD64_XMM2_2 = 172, + CV_AMD64_XMM2_3 = 173, + CV_AMD64_XMM3_0 = 174, + CV_AMD64_XMM3_1 = 175, + CV_AMD64_XMM3_2 = 176, + CV_AMD64_XMM3_3 = 177, + CV_AMD64_XMM4_0 = 178, + CV_AMD64_XMM4_1 = 179, + CV_AMD64_XMM4_2 = 180, + CV_AMD64_XMM4_3 = 181, + CV_AMD64_XMM5_0 = 182, + CV_AMD64_XMM5_1 = 183, + CV_AMD64_XMM5_2 = 184, + CV_AMD64_XMM5_3 = 185, + CV_AMD64_XMM6_0 = 186, + CV_AMD64_XMM6_1 = 187, + CV_AMD64_XMM6_2 = 188, + CV_AMD64_XMM6_3 = 189, + CV_AMD64_XMM7_0 = 190, + CV_AMD64_XMM7_1 = 191, + CV_AMD64_XMM7_2 = 192, + CV_AMD64_XMM7_3 = 193, + + CV_AMD64_XMM0L = 194, + CV_AMD64_XMM1L = 195, + CV_AMD64_XMM2L = 196, + CV_AMD64_XMM3L = 197, + CV_AMD64_XMM4L = 198, + CV_AMD64_XMM5L = 199, + CV_AMD64_XMM6L = 200, + CV_AMD64_XMM7L = 201, + + CV_AMD64_XMM0H = 202, + CV_AMD64_XMM1H = 203, + CV_AMD64_XMM2H = 204, + CV_AMD64_XMM3H = 205, + CV_AMD64_XMM4H = 206, + CV_AMD64_XMM5H = 207, + CV_AMD64_XMM6H = 208, + CV_AMD64_XMM7H = 209, + + CV_AMD64_MXCSR = 211, // XMM status register + + CV_AMD64_EMM0L = 220, // XMM sub-registers (WNI integer) + CV_AMD64_EMM1L = 221, + CV_AMD64_EMM2L = 222, + CV_AMD64_EMM3L = 223, + CV_AMD64_EMM4L = 224, + CV_AMD64_EMM5L = 225, + CV_AMD64_EMM6L = 226, + CV_AMD64_EMM7L = 227, + + CV_AMD64_EMM0H = 228, + CV_AMD64_EMM1H = 229, + CV_AMD64_EMM2H = 230, + CV_AMD64_EMM3H = 231, + CV_AMD64_EMM4H = 232, + CV_AMD64_EMM5H = 233, + CV_AMD64_EMM6H = 234, + CV_AMD64_EMM7H = 235, + + // do not change the order of these regs, first one must be even too + CV_AMD64_MM00 = 236, + CV_AMD64_MM01 = 237, + CV_AMD64_MM10 = 238, + CV_AMD64_MM11 = 239, + CV_AMD64_MM20 = 240, + CV_AMD64_MM21 = 241, + CV_AMD64_MM30 = 242, + CV_AMD64_MM31 = 243, + CV_AMD64_MM40 = 244, + CV_AMD64_MM41 = 245, + CV_AMD64_MM50 = 246, + CV_AMD64_MM51 = 247, + CV_AMD64_MM60 = 248, + CV_AMD64_MM61 = 249, + CV_AMD64_MM70 = 250, + CV_AMD64_MM71 = 251, + + // Extended KATMAI registers + CV_AMD64_XMM8 = 252, // KATMAI registers + CV_AMD64_XMM9 = 253, + CV_AMD64_XMM10 = 254, + CV_AMD64_XMM11 = 255, + CV_AMD64_XMM12 = 256, + CV_AMD64_XMM13 = 257, + CV_AMD64_XMM14 = 258, + CV_AMD64_XMM15 = 259, + + CV_AMD64_XMM8_0 = 260, // KATMAI sub-registers + CV_AMD64_XMM8_1 = 261, + CV_AMD64_XMM8_2 = 262, + CV_AMD64_XMM8_3 = 263, + CV_AMD64_XMM9_0 = 264, + CV_AMD64_XMM9_1 = 265, + CV_AMD64_XMM9_2 = 266, + CV_AMD64_XMM9_3 = 267, + CV_AMD64_XMM10_0 = 268, + CV_AMD64_XMM10_1 = 269, + CV_AMD64_XMM10_2 = 270, + CV_AMD64_XMM10_3 = 271, + CV_AMD64_XMM11_0 = 272, + CV_AMD64_XMM11_1 = 273, + CV_AMD64_XMM11_2 = 274, + CV_AMD64_XMM11_3 = 275, + CV_AMD64_XMM12_0 = 276, + CV_AMD64_XMM12_1 = 277, + CV_AMD64_XMM12_2 = 278, + CV_AMD64_XMM12_3 = 279, + CV_AMD64_XMM13_0 = 280, + CV_AMD64_XMM13_1 = 281, + CV_AMD64_XMM13_2 = 282, + CV_AMD64_XMM13_3 = 283, + CV_AMD64_XMM14_0 = 284, + CV_AMD64_XMM14_1 = 285, + CV_AMD64_XMM14_2 = 286, + CV_AMD64_XMM14_3 = 287, + CV_AMD64_XMM15_0 = 288, + CV_AMD64_XMM15_1 = 289, + CV_AMD64_XMM15_2 = 290, + CV_AMD64_XMM15_3 = 291, + + CV_AMD64_XMM8L = 292, + CV_AMD64_XMM9L = 293, + CV_AMD64_XMM10L = 294, + CV_AMD64_XMM11L = 295, + CV_AMD64_XMM12L = 296, + CV_AMD64_XMM13L = 297, + CV_AMD64_XMM14L = 298, + CV_AMD64_XMM15L = 299, + + CV_AMD64_XMM8H = 300, + CV_AMD64_XMM9H = 301, + CV_AMD64_XMM10H = 302, + CV_AMD64_XMM11H = 303, + CV_AMD64_XMM12H = 304, + CV_AMD64_XMM13H = 305, + CV_AMD64_XMM14H = 306, + CV_AMD64_XMM15H = 307, + + CV_AMD64_EMM8L = 308, // XMM sub-registers (WNI integer) + CV_AMD64_EMM9L = 309, + CV_AMD64_EMM10L = 310, + CV_AMD64_EMM11L = 311, + CV_AMD64_EMM12L = 312, + CV_AMD64_EMM13L = 313, + CV_AMD64_EMM14L = 314, + CV_AMD64_EMM15L = 315, + + CV_AMD64_EMM8H = 316, + CV_AMD64_EMM9H = 317, + CV_AMD64_EMM10H = 318, + CV_AMD64_EMM11H = 319, + CV_AMD64_EMM12H = 320, + CV_AMD64_EMM13H = 321, + CV_AMD64_EMM14H = 322, + CV_AMD64_EMM15H = 323, + + // Low byte forms of some standard registers + CV_AMD64_SIL = 324, + CV_AMD64_DIL = 325, + CV_AMD64_BPL = 326, + CV_AMD64_SPL = 327, + + // 64-bit regular registers + CV_AMD64_RAX = 328, + CV_AMD64_RBX = 329, + CV_AMD64_RCX = 330, + CV_AMD64_RDX = 331, + CV_AMD64_RSI = 332, + CV_AMD64_RDI = 333, + CV_AMD64_RBP = 334, + CV_AMD64_RSP = 335, + + // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D) + CV_AMD64_R8 = 336, + CV_AMD64_R9 = 337, + CV_AMD64_R10 = 338, + CV_AMD64_R11 = 339, + CV_AMD64_R12 = 340, + CV_AMD64_R13 = 341, + CV_AMD64_R14 = 342, + CV_AMD64_R15 = 343, + + CV_AMD64_R8B = 344, + CV_AMD64_R9B = 345, + CV_AMD64_R10B = 346, + CV_AMD64_R11B = 347, + CV_AMD64_R12B = 348, + CV_AMD64_R13B = 349, + CV_AMD64_R14B = 350, + CV_AMD64_R15B = 351, + + CV_AMD64_R8W = 352, + CV_AMD64_R9W = 353, + CV_AMD64_R10W = 354, + CV_AMD64_R11W = 355, + CV_AMD64_R12W = 356, + CV_AMD64_R13W = 357, + CV_AMD64_R14W = 358, + CV_AMD64_R15W = 359, + + CV_AMD64_R8D = 360, + CV_AMD64_R9D = 361, + CV_AMD64_R10D = 362, + CV_AMD64_R11D = 363, + CV_AMD64_R12D = 364, + CV_AMD64_R13D = 365, + CV_AMD64_R14D = 366, + CV_AMD64_R15D = 367, + + // AVX registers 256 bits + CV_AMD64_YMM0 = 368, + CV_AMD64_YMM1 = 369, + CV_AMD64_YMM2 = 370, + CV_AMD64_YMM3 = 371, + CV_AMD64_YMM4 = 372, + CV_AMD64_YMM5 = 373, + CV_AMD64_YMM6 = 374, + CV_AMD64_YMM7 = 375, + CV_AMD64_YMM8 = 376, + CV_AMD64_YMM9 = 377, + CV_AMD64_YMM10 = 378, + CV_AMD64_YMM11 = 379, + CV_AMD64_YMM12 = 380, + CV_AMD64_YMM13 = 381, + CV_AMD64_YMM14 = 382, + CV_AMD64_YMM15 = 383, + + // AVX registers upper 128 bits + CV_AMD64_YMM0H = 384, + CV_AMD64_YMM1H = 385, + CV_AMD64_YMM2H = 386, + CV_AMD64_YMM3H = 387, + CV_AMD64_YMM4H = 388, + CV_AMD64_YMM5H = 389, + CV_AMD64_YMM6H = 390, + CV_AMD64_YMM7H = 391, + CV_AMD64_YMM8H = 392, + CV_AMD64_YMM9H = 393, + CV_AMD64_YMM10H = 394, + CV_AMD64_YMM11H = 395, + CV_AMD64_YMM12H = 396, + CV_AMD64_YMM13H = 397, + CV_AMD64_YMM14H = 398, + CV_AMD64_YMM15H = 399, + + // Lower/upper 8 bytes of XMM registers. Unlike CV_AMD64_XMM<regnum><H/L>, + // these + // values reprsesent the bit patterns of the registers as 64-bit integers, not + // the representation of these registers as a double. + CV_AMD64_XMM0IL = 400, + CV_AMD64_XMM1IL = 401, + CV_AMD64_XMM2IL = 402, + CV_AMD64_XMM3IL = 403, + CV_AMD64_XMM4IL = 404, + CV_AMD64_XMM5IL = 405, + CV_AMD64_XMM6IL = 406, + CV_AMD64_XMM7IL = 407, + CV_AMD64_XMM8IL = 408, + CV_AMD64_XMM9IL = 409, + CV_AMD64_XMM10IL = 410, + CV_AMD64_XMM11IL = 411, + CV_AMD64_XMM12IL = 412, + CV_AMD64_XMM13IL = 413, + CV_AMD64_XMM14IL = 414, + CV_AMD64_XMM15IL = 415, + + CV_AMD64_XMM0IH = 416, + CV_AMD64_XMM1IH = 417, + CV_AMD64_XMM2IH = 418, + CV_AMD64_XMM3IH = 419, + CV_AMD64_XMM4IH = 420, + CV_AMD64_XMM5IH = 421, + CV_AMD64_XMM6IH = 422, + CV_AMD64_XMM7IH = 423, + CV_AMD64_XMM8IH = 424, + CV_AMD64_XMM9IH = 425, + CV_AMD64_XMM10IH = 426, + CV_AMD64_XMM11IH = 427, + CV_AMD64_XMM12IH = 428, + CV_AMD64_XMM13IH = 429, + CV_AMD64_XMM14IH = 430, + CV_AMD64_XMM15IH = 431, + + CV_AMD64_YMM0I0 = 432, // AVX integer registers + CV_AMD64_YMM0I1 = 433, + CV_AMD64_YMM0I2 = 434, + CV_AMD64_YMM0I3 = 435, + CV_AMD64_YMM1I0 = 436, + CV_AMD64_YMM1I1 = 437, + CV_AMD64_YMM1I2 = 438, + CV_AMD64_YMM1I3 = 439, + CV_AMD64_YMM2I0 = 440, + CV_AMD64_YMM2I1 = 441, + CV_AMD64_YMM2I2 = 442, + CV_AMD64_YMM2I3 = 443, + CV_AMD64_YMM3I0 = 444, + CV_AMD64_YMM3I1 = 445, + CV_AMD64_YMM3I2 = 446, + CV_AMD64_YMM3I3 = 447, + CV_AMD64_YMM4I0 = 448, + CV_AMD64_YMM4I1 = 449, + CV_AMD64_YMM4I2 = 450, + CV_AMD64_YMM4I3 = 451, + CV_AMD64_YMM5I0 = 452, + CV_AMD64_YMM5I1 = 453, + CV_AMD64_YMM5I2 = 454, + CV_AMD64_YMM5I3 = 455, + CV_AMD64_YMM6I0 = 456, + CV_AMD64_YMM6I1 = 457, + CV_AMD64_YMM6I2 = 458, + CV_AMD64_YMM6I3 = 459, + CV_AMD64_YMM7I0 = 460, + CV_AMD64_YMM7I1 = 461, + CV_AMD64_YMM7I2 = 462, + CV_AMD64_YMM7I3 = 463, + CV_AMD64_YMM8I0 = 464, + CV_AMD64_YMM8I1 = 465, + CV_AMD64_YMM8I2 = 466, + CV_AMD64_YMM8I3 = 467, + CV_AMD64_YMM9I0 = 468, + CV_AMD64_YMM9I1 = 469, + CV_AMD64_YMM9I2 = 470, + CV_AMD64_YMM9I3 = 471, + CV_AMD64_YMM10I0 = 472, + CV_AMD64_YMM10I1 = 473, + CV_AMD64_YMM10I2 = 474, + CV_AMD64_YMM10I3 = 475, + CV_AMD64_YMM11I0 = 476, + CV_AMD64_YMM11I1 = 477, + CV_AMD64_YMM11I2 = 478, + CV_AMD64_YMM11I3 = 479, + CV_AMD64_YMM12I0 = 480, + CV_AMD64_YMM12I1 = 481, + CV_AMD64_YMM12I2 = 482, + CV_AMD64_YMM12I3 = 483, + CV_AMD64_YMM13I0 = 484, + CV_AMD64_YMM13I1 = 485, + CV_AMD64_YMM13I2 = 486, + CV_AMD64_YMM13I3 = 487, + CV_AMD64_YMM14I0 = 488, + CV_AMD64_YMM14I1 = 489, + CV_AMD64_YMM14I2 = 490, + CV_AMD64_YMM14I3 = 491, + CV_AMD64_YMM15I0 = 492, + CV_AMD64_YMM15I1 = 493, + CV_AMD64_YMM15I2 = 494, + CV_AMD64_YMM15I3 = 495, + + CV_AMD64_YMM0F0 = 496, // AVX floating-point single precise registers + CV_AMD64_YMM0F1 = 497, + CV_AMD64_YMM0F2 = 498, + CV_AMD64_YMM0F3 = 499, + CV_AMD64_YMM0F4 = 500, + CV_AMD64_YMM0F5 = 501, + CV_AMD64_YMM0F6 = 502, + CV_AMD64_YMM0F7 = 503, + CV_AMD64_YMM1F0 = 504, + CV_AMD64_YMM1F1 = 505, + CV_AMD64_YMM1F2 = 506, + CV_AMD64_YMM1F3 = 507, + CV_AMD64_YMM1F4 = 508, + CV_AMD64_YMM1F5 = 509, + CV_AMD64_YMM1F6 = 510, + CV_AMD64_YMM1F7 = 511, + CV_AMD64_YMM2F0 = 512, + CV_AMD64_YMM2F1 = 513, + CV_AMD64_YMM2F2 = 514, + CV_AMD64_YMM2F3 = 515, + CV_AMD64_YMM2F4 = 516, + CV_AMD64_YMM2F5 = 517, + CV_AMD64_YMM2F6 = 518, + CV_AMD64_YMM2F7 = 519, + CV_AMD64_YMM3F0 = 520, + CV_AMD64_YMM3F1 = 521, + CV_AMD64_YMM3F2 = 522, + CV_AMD64_YMM3F3 = 523, + CV_AMD64_YMM3F4 = 524, + CV_AMD64_YMM3F5 = 525, + CV_AMD64_YMM3F6 = 526, + CV_AMD64_YMM3F7 = 527, + CV_AMD64_YMM4F0 = 528, + CV_AMD64_YMM4F1 = 529, + CV_AMD64_YMM4F2 = 530, + CV_AMD64_YMM4F3 = 531, + CV_AMD64_YMM4F4 = 532, + CV_AMD64_YMM4F5 = 533, + CV_AMD64_YMM4F6 = 534, + CV_AMD64_YMM4F7 = 535, + CV_AMD64_YMM5F0 = 536, + CV_AMD64_YMM5F1 = 537, + CV_AMD64_YMM5F2 = 538, + CV_AMD64_YMM5F3 = 539, + CV_AMD64_YMM5F4 = 540, + CV_AMD64_YMM5F5 = 541, + CV_AMD64_YMM5F6 = 542, + CV_AMD64_YMM5F7 = 543, + CV_AMD64_YMM6F0 = 544, + CV_AMD64_YMM6F1 = 545, + CV_AMD64_YMM6F2 = 546, + CV_AMD64_YMM6F3 = 547, + CV_AMD64_YMM6F4 = 548, + CV_AMD64_YMM6F5 = 549, + CV_AMD64_YMM6F6 = 550, + CV_AMD64_YMM6F7 = 551, + CV_AMD64_YMM7F0 = 552, + CV_AMD64_YMM7F1 = 553, + CV_AMD64_YMM7F2 = 554, + CV_AMD64_YMM7F3 = 555, + CV_AMD64_YMM7F4 = 556, + CV_AMD64_YMM7F5 = 557, + CV_AMD64_YMM7F6 = 558, + CV_AMD64_YMM7F7 = 559, + CV_AMD64_YMM8F0 = 560, + CV_AMD64_YMM8F1 = 561, + CV_AMD64_YMM8F2 = 562, + CV_AMD64_YMM8F3 = 563, + CV_AMD64_YMM8F4 = 564, + CV_AMD64_YMM8F5 = 565, + CV_AMD64_YMM8F6 = 566, + CV_AMD64_YMM8F7 = 567, + CV_AMD64_YMM9F0 = 568, + CV_AMD64_YMM9F1 = 569, + CV_AMD64_YMM9F2 = 570, + CV_AMD64_YMM9F3 = 571, + CV_AMD64_YMM9F4 = 572, + CV_AMD64_YMM9F5 = 573, + CV_AMD64_YMM9F6 = 574, + CV_AMD64_YMM9F7 = 575, + CV_AMD64_YMM10F0 = 576, + CV_AMD64_YMM10F1 = 577, + CV_AMD64_YMM10F2 = 578, + CV_AMD64_YMM10F3 = 579, + CV_AMD64_YMM10F4 = 580, + CV_AMD64_YMM10F5 = 581, + CV_AMD64_YMM10F6 = 582, + CV_AMD64_YMM10F7 = 583, + CV_AMD64_YMM11F0 = 584, + CV_AMD64_YMM11F1 = 585, + CV_AMD64_YMM11F2 = 586, + CV_AMD64_YMM11F3 = 587, + CV_AMD64_YMM11F4 = 588, + CV_AMD64_YMM11F5 = 589, + CV_AMD64_YMM11F6 = 590, + CV_AMD64_YMM11F7 = 591, + CV_AMD64_YMM12F0 = 592, + CV_AMD64_YMM12F1 = 593, + CV_AMD64_YMM12F2 = 594, + CV_AMD64_YMM12F3 = 595, + CV_AMD64_YMM12F4 = 596, + CV_AMD64_YMM12F5 = 597, + CV_AMD64_YMM12F6 = 598, + CV_AMD64_YMM12F7 = 599, + CV_AMD64_YMM13F0 = 600, + CV_AMD64_YMM13F1 = 601, + CV_AMD64_YMM13F2 = 602, + CV_AMD64_YMM13F3 = 603, + CV_AMD64_YMM13F4 = 604, + CV_AMD64_YMM13F5 = 605, + CV_AMD64_YMM13F6 = 606, + CV_AMD64_YMM13F7 = 607, + CV_AMD64_YMM14F0 = 608, + CV_AMD64_YMM14F1 = 609, + CV_AMD64_YMM14F2 = 610, + CV_AMD64_YMM14F3 = 611, + CV_AMD64_YMM14F4 = 612, + CV_AMD64_YMM14F5 = 613, + CV_AMD64_YMM14F6 = 614, + CV_AMD64_YMM14F7 = 615, + CV_AMD64_YMM15F0 = 616, + CV_AMD64_YMM15F1 = 617, + CV_AMD64_YMM15F2 = 618, + CV_AMD64_YMM15F3 = 619, + CV_AMD64_YMM15F4 = 620, + CV_AMD64_YMM15F5 = 621, + CV_AMD64_YMM15F6 = 622, + CV_AMD64_YMM15F7 = 623, + + CV_AMD64_YMM0D0 = 624, // AVX floating-point double precise registers + CV_AMD64_YMM0D1 = 625, + CV_AMD64_YMM0D2 = 626, + CV_AMD64_YMM0D3 = 627, + CV_AMD64_YMM1D0 = 628, + CV_AMD64_YMM1D1 = 629, + CV_AMD64_YMM1D2 = 630, + CV_AMD64_YMM1D3 = 631, + CV_AMD64_YMM2D0 = 632, + CV_AMD64_YMM2D1 = 633, + CV_AMD64_YMM2D2 = 634, + CV_AMD64_YMM2D3 = 635, + CV_AMD64_YMM3D0 = 636, + CV_AMD64_YMM3D1 = 637, + CV_AMD64_YMM3D2 = 638, + CV_AMD64_YMM3D3 = 639, + CV_AMD64_YMM4D0 = 640, + CV_AMD64_YMM4D1 = 641, + CV_AMD64_YMM4D2 = 642, + CV_AMD64_YMM4D3 = 643, + CV_AMD64_YMM5D0 = 644, + CV_AMD64_YMM5D1 = 645, + CV_AMD64_YMM5D2 = 646, + CV_AMD64_YMM5D3 = 647, + CV_AMD64_YMM6D0 = 648, + CV_AMD64_YMM6D1 = 649, + CV_AMD64_YMM6D2 = 650, + CV_AMD64_YMM6D3 = 651, + CV_AMD64_YMM7D0 = 652, + CV_AMD64_YMM7D1 = 653, + CV_AMD64_YMM7D2 = 654, + CV_AMD64_YMM7D3 = 655, + CV_AMD64_YMM8D0 = 656, + CV_AMD64_YMM8D1 = 657, + CV_AMD64_YMM8D2 = 658, + CV_AMD64_YMM8D3 = 659, + CV_AMD64_YMM9D0 = 660, + CV_AMD64_YMM9D1 = 661, + CV_AMD64_YMM9D2 = 662, + CV_AMD64_YMM9D3 = 663, + CV_AMD64_YMM10D0 = 664, + CV_AMD64_YMM10D1 = 665, + CV_AMD64_YMM10D2 = 666, + CV_AMD64_YMM10D3 = 667, + CV_AMD64_YMM11D0 = 668, + CV_AMD64_YMM11D1 = 669, + CV_AMD64_YMM11D2 = 670, + CV_AMD64_YMM11D3 = 671, + CV_AMD64_YMM12D0 = 672, + CV_AMD64_YMM12D1 = 673, + CV_AMD64_YMM12D2 = 674, + CV_AMD64_YMM12D3 = 675, + CV_AMD64_YMM13D0 = 676, + CV_AMD64_YMM13D1 = 677, + CV_AMD64_YMM13D2 = 678, + CV_AMD64_YMM13D3 = 679, + CV_AMD64_YMM14D0 = 680, + CV_AMD64_YMM14D1 = 681, + CV_AMD64_YMM14D2 = 682, + CV_AMD64_YMM14D3 = 683, + CV_AMD64_YMM15D0 = 684, + CV_AMD64_YMM15D1 = 685, + CV_AMD64_YMM15D2 = 686, + CV_AMD64_YMM15D3 = 687 + + // Note: Next set of platform registers need to go into a new enum... + // this one is above 44K now. + +} CV_HREG_e; + +typedef enum CV_HLSLREG_e { + CV_HLSLREG_TEMP = 0, + CV_HLSLREG_INPUT = 1, + CV_HLSLREG_OUTPUT = 2, + CV_HLSLREG_INDEXABLE_TEMP = 3, + CV_HLSLREG_IMMEDIATE32 = 4, + CV_HLSLREG_IMMEDIATE64 = 5, + CV_HLSLREG_SAMPLER = 6, + CV_HLSLREG_RESOURCE = 7, + CV_HLSLREG_CONSTANT_BUFFER = 8, + CV_HLSLREG_IMMEDIATE_CONSTANT_BUFFER = 9, + CV_HLSLREG_LABEL = 10, + CV_HLSLREG_INPUT_PRIMITIVEID = 11, + CV_HLSLREG_OUTPUT_DEPTH = 12, + CV_HLSLREG_NULL = 13, + CV_HLSLREG_RASTERIZER = 14, + CV_HLSLREG_OUTPUT_COVERAGE_MASK = 15, + CV_HLSLREG_STREAM = 16, + CV_HLSLREG_FUNCTION_BODY = 17, + CV_HLSLREG_FUNCTION_TABLE = 18, + CV_HLSLREG_INTERFACE = 19, + CV_HLSLREG_FUNCTION_INPUT = 20, + CV_HLSLREG_FUNCTION_OUTPUT = 21, + CV_HLSLREG_OUTPUT_CONTROL_POINT_ID = 22, + CV_HLSLREG_INPUT_FORK_INSTANCE_ID = 23, + CV_HLSLREG_INPUT_JOIN_INSTANCE_ID = 24, + CV_HLSLREG_INPUT_CONTROL_POINT = 25, + CV_HLSLREG_OUTPUT_CONTROL_POINT = 26, + CV_HLSLREG_INPUT_PATCH_CONSTANT = 27, + CV_HLSLREG_INPUT_DOMAIN_POINT = 28, + CV_HLSLREG_THIS_POINTER = 29, + CV_HLSLREG_UNORDERED_ACCESS_VIEW = 30, + CV_HLSLREG_THREAD_GROUP_SHARED_MEMORY = 31, + CV_HLSLREG_INPUT_THREAD_ID = 32, + CV_HLSLREG_INPUT_THREAD_GROUP_ID = 33, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP = 34, + CV_HLSLREG_INPUT_COVERAGE_MASK = 35, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, + CV_HLSLREG_INPUT_GS_INSTANCE_ID = 37, + CV_HLSLREG_OUTPUT_DEPTH_GREATER_EQUAL = 38, + CV_HLSLREG_OUTPUT_DEPTH_LESS_EQUAL = 39, + CV_HLSLREG_CYCLE_COUNTER = 40, +} CV_HLSLREG_e; + +enum StackFrameTypeEnum { + FrameTypeFPO, // Frame pointer omitted, FPO info available + FrameTypeTrap, // Kernel Trap frame + FrameTypeTSS, // Kernel Trap frame + FrameTypeStandard, // Standard EBP stackframe + FrameTypeFrameData, // Frame pointer omitted, FrameData info available + + FrameTypeUnknown = -1, // Frame which does not have any debug info +}; + +enum MemoryTypeEnum { + MemTypeCode, // Read only code memory + MemTypeData, // Read only data/stack memory + MemTypeStack, // Read only stack memory + MemTypeCodeOnHeap, // Read only memory for code generated on heap by runtime + + MemTypeAny = -1, +}; + +typedef enum CV_HLSLMemorySpace_e { + // HLSL specific memory spaces + + CV_HLSL_MEMSPACE_DATA = 0x00, + CV_HLSL_MEMSPACE_SAMPLER = 0x01, + CV_HLSL_MEMSPACE_RESOURCE = 0x02, + CV_HLSL_MEMSPACE_RWRESOURCE = 0x03, + + CV_HLSL_MEMSPACE_MAX = 0x0F, +} CV_HLSLMemorySpace_e; + +#endif diff --git a/src/Native/ObjWriter/jitDebugInfo.h b/src/Native/ObjWriter/jitDebugInfo.h new file mode 100644 index 000000000..103dff8ad --- /dev/null +++ b/src/Native/ObjWriter/jitDebugInfo.h @@ -0,0 +1,43 @@ +#ifndef JIT_DEBUG_INFO_H +#define JIT_DEBUG_INFO_H + +typedef unsigned int DWORD; +#define _TARGET_AMD64_ 1 + +#include "cordebuginfo.h" +#include "cvconst.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" + +struct DebugLocInfo { + int NativeOffset; + int FileId; + int LineNumber; + int ColNumber; +}; + +struct DebugVarInfo { + std::string Name; + int TypeIndex; + bool IsParam; + std::vector<ICorDebugInfo::NativeVarInfo> Ranges; + + DebugVarInfo() {} + DebugVarInfo(char *ArgName, int ArgTypeIndex, bool ArgIsParam) + : Name(ArgName), TypeIndex(ArgTypeIndex), IsParam(ArgIsParam) {} +}; + +typedef unsigned short CVRegMapping; + +#define CVREGDAT(p2, cv) cv + +const CVRegMapping cvRegMapAmd64[] = { + CVREGDAT(REGNUM_RAX, CV_AMD64_RAX), CVREGDAT(REGNUM_RCX, CV_AMD64_RCX), + CVREGDAT(REGNUM_RDX, CV_AMD64_RDX), CVREGDAT(REGNUM_RBX, CV_AMD64_RBX), + CVREGDAT(REGNUM_RSP, CV_AMD64_RSP), CVREGDAT(REGNUM_RBP, CV_AMD64_RBP), + CVREGDAT(REGNUM_RSI, CV_AMD64_RSI), CVREGDAT(REGNUM_RDI, CV_AMD64_RDI), + CVREGDAT(REGNUM_R8, CV_AMD64_R8), CVREGDAT(REGNUM_R9, CV_AMD64_R9), + CVREGDAT(REGNUM_R10, CV_AMD64_R10), CVREGDAT(REGNUM_R11, CV_AMD64_R11), + CVREGDAT(REGNUM_R12, CV_AMD64_R12), CVREGDAT(REGNUM_R13, CV_AMD64_R13), + CVREGDAT(REGNUM_R14, CV_AMD64_R14), CVREGDAT(REGNUM_R15, CV_AMD64_R15)}; + +#endif // JIT_DEBUG_INFO_H diff --git a/src/Native/ObjWriter/llvm.patch b/src/Native/ObjWriter/llvm.patch new file mode 100644 index 000000000..2dde952d5 --- /dev/null +++ b/src/Native/ObjWriter/llvm.patch @@ -0,0 +1,123 @@ +diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h +index 7c1189e46ab..d1d77c97311 100644 +--- a/include/llvm/MC/MCObjectStreamer.h ++++ b/include/llvm/MC/MCObjectStreamer.h +@@ -101,6 +101,11 @@ public: + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + bool = false) override; + ++ /// \brief EmitValueImpl with additional param, that allows to emit PCRelative ++ /// MCFixup. ++ void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc, ++ bool isPCRelative); ++ + /// \brief Emit an instruction to a special fragment, because this instruction + /// can change its size during relaxation. + virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &); +diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp +index 174397e2739..ef7161fb56c 100644 +--- a/lib/MC/MCObjectStreamer.cpp ++++ b/lib/MC/MCObjectStreamer.cpp +@@ -122,7 +122,7 @@ void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) { + } + + void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, +- SMLoc Loc) { ++ SMLoc Loc, bool isPCRelative) { + MCStreamer::EmitValueImpl(Value, Size, Loc); + MCDataFragment *DF = getOrCreateDataFragment(); + flushPendingLabels(DF, DF->getContents().size()); +@@ -143,10 +143,16 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + } + DF->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, +- MCFixup::getKindForSize(Size, false), Loc)); ++ MCFixup::getKindForSize(Size, isPCRelative), Loc)); + DF->getContents().resize(DF->getContents().size() + Size, 0); + } + ++ ++void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, ++ SMLoc Loc) { ++ EmitValueImpl(Value, Size, Loc, false); ++} ++ + void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { + // We need to create a local symbol to avoid relocations. + Frame.Begin = getContext().createTempSymbol(); +diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +index a77df7a2598..e1aa7526f9b 100644 +--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp ++++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +@@ -48,6 +48,14 @@ public: + }; + } // end anonymous namespace + ++Optional<MCFixupKind> ARMAsmBackend::getFixupKind(StringRef Name) const { ++ return StringSwitch<Optional<MCFixupKind>>(Name) ++ .Case("R_ARM_THM_MOVW_ABS_NC", (MCFixupKind)ARM::fixup_t2_movw_lo16) ++ .Case("R_ARM_THM_MOVT_ABS", (MCFixupKind)ARM::fixup_t2_movt_hi16) ++ .Case("R_ARM_THM_JUMP24", (MCFixupKind)ARM::fixup_arm_thumb_blx) ++ .Default(MCAsmBackend::getFixupKind(Name)); ++} ++ + const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = { + // This table *must* be in the order that the fixup_* kinds are defined in +@@ -386,6 +394,8 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, + case FK_Data_2: + case FK_Data_4: + return Value; ++ case FK_PCRel_4: ++ return Value; + case FK_SecRel_2: + return Value; + case FK_SecRel_4: +@@ -825,6 +835,9 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { + case ARM::fixup_t2_so_imm: + return 4; + ++ case FK_PCRel_4: ++ return 4; ++ + case FK_SecRel_2: + return 2; + case FK_SecRel_4: +diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +index 02374966daf..01676a01683 100644 +--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h ++++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +@@ -36,6 +36,7 @@ public: + + bool hasNOP() const { return STI->getFeatureBits()[ARM::HasV6T2Ops]; } + ++ Optional<MCFixupKind> getFixupKind(StringRef Name) const override; + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, +diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +index 59f31be69d5..9b95598f99f 100644 +--- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp ++++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +@@ -103,6 +103,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, + break; + } + break; ++ case FK_PCRel_4: ++ Type = ELF::R_ARM_REL32; ++ break; + case ARM::fixup_arm_blx: + case ARM::fixup_arm_uncondbl: + switch (Modifier) { +diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt +index b654b8c5cb8..58d25159af8 100644 +--- a/tools/CMakeLists.txt ++++ b/tools/CMakeLists.txt +@@ -46,6 +46,7 @@ add_llvm_external_project(clang) + add_llvm_external_project(llgo) + add_llvm_external_project(lld) + add_llvm_external_project(lldb) ++add_llvm_external_project(ObjWriter) + + # Automatically add remaining sub-directories containing a 'CMakeLists.txt' + # file as external projects. diff --git a/src/Native/ObjWriter/objwriter.cpp b/src/Native/ObjWriter/objwriter.cpp new file mode 100644 index 000000000..5f22998a2 --- /dev/null +++ b/src/Native/ObjWriter/objwriter.cpp @@ -0,0 +1,806 @@ +//===---- objwriter.cpp --------------------------------*- C++ -*-===// +// +// object writer +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Implementation of object writer API for JIT/AOT +/// +//===----------------------------------------------------------------------===// + +#include "objwriter.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetOptionsCommandFlags.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compression.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Win64EH.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; +using namespace llvm::codeview; + +bool error(const Twine &Error) { + errs() << Twine("error: ") + Error + "\n"; + return false; +} + +void ObjectWriter::InitTripleName() { + TripleName = sys::getDefaultTargetTriple(); +} + +Triple ObjectWriter::GetTriple() { + Triple TheTriple(TripleName); + + if (TheTriple.getOS() == Triple::OSType::Darwin) { + TheTriple = Triple( + TheTriple.getArchName(), TheTriple.getVendorName(), "darwin", + TheTriple + .getEnvironmentName()); // it is workaround for llvm bug + // https://bugs.llvm.org//show_bug.cgi?id=24927. + } + return TheTriple; +} + +bool ObjectWriter::Init(llvm::StringRef ObjectFilePath) { + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + + TargetMOptions = InitMCTargetOptionsFromFlags(); + + InitTripleName(); + Triple TheTriple = GetTriple(); + + // Get the target specific parser. + std::string TargetError; + const Target *TheTarget = + TargetRegistry::lookupTarget(TripleName, TargetError); + if (!TheTarget) { + return error("Unable to create target for " + ObjectFilePath + ": " + + TargetError); + } + + std::error_code EC; + OS.reset(new raw_fd_ostream(ObjectFilePath, EC, sys::fs::F_None)); + if (EC) + return error("Unable to create file for " + ObjectFilePath + ": " + + EC.message()); + + RegisterInfo.reset(TheTarget->createMCRegInfo(TripleName)); + if (!RegisterInfo) + return error("Unable to create target register info!"); + + AsmInfo.reset(TheTarget->createMCAsmInfo(*RegisterInfo, TripleName)); + if (!AsmInfo) + return error("Unable to create target asm info!"); + + ObjFileInfo.reset(new MCObjectFileInfo); + OutContext.reset( + new MCContext(AsmInfo.get(), RegisterInfo.get(), ObjFileInfo.get())); + ObjFileInfo->InitMCObjectFileInfo(TheTriple, false, CodeModel::Default, + *OutContext); + + InstrInfo.reset(TheTarget->createMCInstrInfo()); + if (!InstrInfo) + return error("no instr info info for target " + TripleName); + + std::string FeaturesStr; + std::string MCPU; + SubtargetInfo.reset( + TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); + if (!SubtargetInfo) + return error("no subtarget info for target " + TripleName); + + CodeEmitter = + TheTarget->createMCCodeEmitter(*InstrInfo, *RegisterInfo, *OutContext); + if (!CodeEmitter) + return error("no code emitter for target " + TripleName); + + AsmBackend = TheTarget->createMCAsmBackend(*RegisterInfo, TripleName, MCPU, + TargetMOptions); + if (!AsmBackend) + return error("no asm backend for target " + TripleName); + + Streamer = (MCObjectStreamer *)TheTarget->createMCObjectStreamer( + TheTriple, *OutContext, *AsmBackend, *OS, CodeEmitter, *SubtargetInfo, + RelaxAll, + /*IncrementalLinkerCompatible*/ true, + /*DWARFMustBeAtTheEnd*/ false); + if (!Streamer) + return error("no object streamer for target " + TripleName); + Assembler = &Streamer->getAssembler(); + + TMachine.reset(TheTarget->createTargetMachine(TripleName, MCPU, FeaturesStr, + TargetOptions(), None)); + if (!TMachine) + return error("no target machine for target " + TripleName); + + AssemblerPrinter.reset(TheTarget->createAsmPrinter( + *TMachine, std::unique_ptr<MCStreamer>(Streamer))); + if (!AssemblerPrinter) + return error("no asm printer for target " + TripleName); + + FrameOpened = false; + FuncId = 1; + + SetCodeSectionAttribute("text", CustomSectionAttributes_Executable, nullptr); + + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { + TypeBuilder.SetStreamer(Streamer); + unsigned TargetPointerSize = AssemblerPrinter->getPointerSize(); + TypeBuilder.SetTargetPointerSize(TargetPointerSize); + } + + return true; +} + +void ObjectWriter::Finish() { Streamer->Finish(); } + +void ObjectWriter::SwitchSection(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName) { + MCSection *Section = GetSection(SectionName, attributes, ComdatName); + Streamer->SwitchSection(Section); + if (Sections.count(Section) == 0) { + Sections.insert(Section); + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsMachO) { + assert(!Section->getBeginSymbol()); + // Output a DWARF linker-local symbol. + // This symbol is used as a base for other symbols in a section. + MCSymbol *SectionStartSym = OutContext->createTempSymbol(); + Streamer->EmitLabel(SectionStartSym); + Section->setBeginSymbol(SectionStartSym); + } + } +} + +MCSection *ObjectWriter::GetSection(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName) { + MCSection *Section = nullptr; + + if (strcmp(SectionName, "text") == 0) { + Section = ObjFileInfo->getTextSection(); + } else if (strcmp(SectionName, "data") == 0) { + Section = ObjFileInfo->getDataSection(); + } else if (strcmp(SectionName, "rdata") == 0) { + Section = ObjFileInfo->getReadOnlySection(); + } else if (strcmp(SectionName, "xdata") == 0) { + Section = ObjFileInfo->getXDataSection(); + } else { + Section = GetSpecificSection(SectionName, attributes, ComdatName); + } + assert(Section); + return Section; +} + +MCSection *ObjectWriter::GetSpecificSection(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName) { + Triple TheTriple(TripleName); + MCSection *Section = nullptr; + SectionKind Kind = (attributes & CustomSectionAttributes_Executable) + ? SectionKind::getText() + : (attributes & CustomSectionAttributes_Writeable) + ? SectionKind::getData() + : SectionKind::getReadOnly(); + switch (TheTriple.getObjectFormat()) { + case Triple::MachO: { + unsigned typeAndAttributes = 0; + if (attributes & CustomSectionAttributes_MachO_Init_Func_Pointers) { + typeAndAttributes |= MachO::SectionType::S_MOD_INIT_FUNC_POINTERS; + } + Section = OutContext->getMachOSection( + (attributes & CustomSectionAttributes_Executable) ? "__TEXT" : "__DATA", + SectionName, typeAndAttributes, Kind); + break; + } + case Triple::COFF: { + unsigned Characteristics = COFF::IMAGE_SCN_MEM_READ; + + if (attributes & CustomSectionAttributes_Executable) { + Characteristics |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; + } else if (attributes & CustomSectionAttributes_Writeable) { + Characteristics |= + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_WRITE; + } else { + Characteristics |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; + } + + if (ComdatName != nullptr) { + Section = OutContext->getCOFFSection( + SectionName, Characteristics | COFF::IMAGE_SCN_LNK_COMDAT, Kind, + ComdatName, COFF::COMDATType::IMAGE_COMDAT_SELECT_ANY); + } else { + Section = OutContext->getCOFFSection(SectionName, Characteristics, Kind); + } + break; + } + case Triple::ELF: { + unsigned Flags = ELF::SHF_ALLOC; + if (ComdatName != nullptr) { + MCSymbolELF *GroupSym = + cast<MCSymbolELF>(OutContext->getOrCreateSymbol(ComdatName)); + OutContext->createELFGroupSection(GroupSym); + Flags |= ELF::SHF_GROUP; + } + if (attributes & CustomSectionAttributes_Executable) { + Flags |= ELF::SHF_EXECINSTR; + } else if (attributes & CustomSectionAttributes_Writeable) { + Flags |= ELF::SHF_WRITE; + } + Section = + OutContext->getELFSection(SectionName, ELF::SHT_PROGBITS, Flags, 0, + ComdatName != nullptr ? ComdatName : ""); + break; + } + default: + error("Unknown output format for target " + TripleName); + break; + } + return Section; +} + +void ObjectWriter::SetCodeSectionAttribute(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName) { + MCSection *Section = GetSection(SectionName, attributes, ComdatName); + + assert(!Section->hasInstructions()); + Section->setHasInstructions(true); + if (ObjFileInfo->getObjectFileType() != ObjFileInfo->IsCOFF) { + OutContext->addGenDwarfSection(Section); + } +} + +void ObjectWriter::EmitAlignment(int ByteAlignment) { + Streamer->EmitValueToAlignment(ByteAlignment, 0x90 /* Nop */); +} + +void ObjectWriter::EmitBlob(int BlobSize, const char *Blob) { + Streamer->EmitBytes(StringRef(Blob, BlobSize)); +} + +void ObjectWriter::EmitIntValue(uint64_t Value, unsigned Size) { + Streamer->EmitIntValue(Value, Size); +} + +void ObjectWriter::EmitSymbolDef(const char *SymbolName) { + MCSymbol *Sym = OutContext->getOrCreateSymbol(Twine(SymbolName)); + Streamer->EmitSymbolAttribute(Sym, MCSA_Global); + Streamer->EmitLabel(Sym); +} + +const MCSymbolRefExpr * +ObjectWriter::GetSymbolRefExpr(const char *SymbolName, + MCSymbolRefExpr::VariantKind Kind) { + // Create symbol reference + MCSymbol *T = OutContext->getOrCreateSymbol(SymbolName); + Assembler->registerSymbol(*T); + return MCSymbolRefExpr::create(T, Kind, *OutContext); +} + +int ObjectWriter::EmitSymbolRef(const char *SymbolName, + RelocType RelocationType, int Delta) { + bool IsPCRelative = false; + int Size = 0; + MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; + + // Convert RelocationType to MCSymbolRefExpr + switch (RelocationType) { + case RelocType::IMAGE_REL_BASED_ABSOLUTE: + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF); + Kind = MCSymbolRefExpr::VK_COFF_IMGREL32; + Size = 4; + break; + case RelocType::IMAGE_REL_BASED_HIGHLOW: + Size = 4; + break; + case RelocType::IMAGE_REL_BASED_DIR64: + Size = 8; + break; + case RelocType::IMAGE_REL_BASED_REL32: + Size = 4; + IsPCRelative = true; + break; + default: + assert(false && "NYI RelocationType!"); + } + + const MCExpr *TargetExpr = GetSymbolRefExpr(SymbolName, Kind); + + if (IsPCRelative) { + // If the fixup is pc-relative, we need to bias the value to be relative to + // the start of the field, not the end of the field + TargetExpr = MCBinaryExpr::createSub( + TargetExpr, MCConstantExpr::create(Size, *OutContext), *OutContext); + } + + if (Delta != 0) { + TargetExpr = MCBinaryExpr::createAdd( + TargetExpr, MCConstantExpr::create(Delta, *OutContext), *OutContext); + } + Streamer->EmitValueImpl(TargetExpr, Size, SMLoc(), IsPCRelative); + return Size; +} + +void ObjectWriter::EmitWinFrameInfo(const char *FunctionName, int StartOffset, + int EndOffset, const char *BlobSymbolName) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF); + + // .pdata emission + MCSection *Section = ObjFileInfo->getPDataSection(); + + // If the function was emitted to a Comdat section, create an associative + // section to place the frame info in. This is due to the Windows linker + // requirement that a function and its unwind info come from the same + // object file. + MCSymbol *Fn = OutContext->getOrCreateSymbol(Twine(FunctionName)); + const MCSectionCOFF *FunctionSection = cast<MCSectionCOFF>(&Fn->getSection()); + if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { + Section = OutContext->getAssociativeCOFFSection( + cast<MCSectionCOFF>(Section), FunctionSection->getCOMDATSymbol()); + } + + Streamer->SwitchSection(Section); + Streamer->EmitValueToAlignment(4); + + const MCExpr *BaseRefRel = + GetSymbolRefExpr(FunctionName, MCSymbolRefExpr::VK_COFF_IMGREL32); + + // start Offset + const MCExpr *StartOfs = MCConstantExpr::create(StartOffset, *OutContext); + Streamer->EmitValue( + MCBinaryExpr::createAdd(BaseRefRel, StartOfs, *OutContext), 4); + + // end Offset + const MCExpr *EndOfs = MCConstantExpr::create(EndOffset, *OutContext); + Streamer->EmitValue(MCBinaryExpr::createAdd(BaseRefRel, EndOfs, *OutContext), + 4); + + // frame symbol reference + Streamer->EmitValue( + GetSymbolRefExpr(BlobSymbolName, MCSymbolRefExpr::VK_COFF_IMGREL32), 4); +} + +void ObjectWriter::EmitCFIStart(int Offset) { + assert(!FrameOpened && "frame should be closed before CFIStart"); + Streamer->EmitCFIStartProc(false); + FrameOpened = true; +} + +void ObjectWriter::EmitCFIEnd(int Offset) { + assert(FrameOpened && "frame should be opened before CFIEnd"); + Streamer->EmitCFIEndProc(); + FrameOpened = false; +} + +void ObjectWriter::EmitCFILsda(const char *LsdaBlobSymbolName) { + assert(FrameOpened && "frame should be opened before CFILsda"); + + // Create symbol reference + MCSymbol *T = OutContext->getOrCreateSymbol(LsdaBlobSymbolName); + Assembler->registerSymbol(*T); + Streamer->EmitCFILsda(T, llvm::dwarf::Constants::DW_EH_PE_pcrel | + llvm::dwarf::Constants::DW_EH_PE_sdata4); +} + +void ObjectWriter::EmitCFICode(int Offset, const char *Blob) { + assert(FrameOpened && "frame should be opened before CFICode"); + + const CFI_CODE *CfiCode = (const CFI_CODE *)Blob; + switch (CfiCode->CfiOpCode) { + case CFI_ADJUST_CFA_OFFSET: + assert(CfiCode->DwarfReg == DWARF_REG_ILLEGAL && + "Unexpected Register Value for OpAdjustCfaOffset"); + Streamer->EmitCFIAdjustCfaOffset(CfiCode->Offset); + break; + case CFI_REL_OFFSET: + Streamer->EmitCFIRelOffset(CfiCode->DwarfReg, CfiCode->Offset); + break; + case CFI_DEF_CFA_REGISTER: + assert(CfiCode->Offset == 0 && + "Unexpected Offset Value for OpDefCfaRegister"); + Streamer->EmitCFIDefCfaRegister(CfiCode->DwarfReg); + break; + default: + assert(false && "Unrecognized CFI"); + break; + } +} + +void ObjectWriter::EmitLabelDiff(const MCSymbol *From, const MCSymbol *To, + unsigned int Size) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *FromRef = MCSymbolRefExpr::create(From, Variant, *OutContext), + *ToRef = MCSymbolRefExpr::create(To, Variant, *OutContext); + const MCExpr *AddrDelta = + MCBinaryExpr::create(MCBinaryExpr::Sub, ToRef, FromRef, *OutContext); + Streamer->EmitValue(AddrDelta, Size); +} + +void ObjectWriter::EmitSymRecord(int Size, SymbolRecordKind SymbolKind) { + RecordPrefix Rec; + Rec.RecordLen = ulittle16_t(Size + sizeof(ulittle16_t)); + Rec.RecordKind = ulittle16_t((uint16_t)SymbolKind); + Streamer->EmitBytes(StringRef((char *)&Rec, sizeof(Rec))); +} + +void ObjectWriter::EmitCOFFSecRel32Value(MCExpr const *Value) { + MCDataFragment *DF = Streamer->getOrCreateDataFragment(); + MCFixup Fixup = MCFixup::create(DF->getContents().size(), Value, FK_SecRel_4); + DF->getFixups().push_back(Fixup); + DF->getContents().resize(DF->getContents().size() + 4, 0); +} + +void ObjectWriter::EmitVarDefRange(const MCSymbol *Fn, + const LocalVariableAddrRange &Range) { + const MCSymbolRefExpr *BaseSym = MCSymbolRefExpr::create(Fn, *OutContext); + const MCExpr *Offset = MCConstantExpr::create(Range.OffsetStart, *OutContext); + const MCExpr *Expr = MCBinaryExpr::createAdd(BaseSym, Offset, *OutContext); + EmitCOFFSecRel32Value(Expr); + Streamer->EmitCOFFSectionIndex(Fn); + Streamer->EmitIntValue(Range.Range, 2); +} + +void ObjectWriter::EmitCVDebugVarInfo(const MCSymbol *Fn, + const DebugVarInfo LocInfos[], + int NumVarInfos) { + for (int I = 0; I < NumVarInfos; I++) { + // Emit an S_LOCAL record + DebugVarInfo Var = LocInfos[I]; + TypeIndex Type = TypeIndex(Var.TypeIndex); + LocalSymFlags Flags = LocalSymFlags::None; + unsigned SizeofSym = sizeof(Type) + sizeof(Flags); + unsigned NameLength = Var.Name.length() + 1; + EmitSymRecord(SizeofSym + NameLength, SymbolRecordKind::LocalSym); + if (Var.IsParam) { + Flags |= LocalSymFlags::IsParameter; + } + Streamer->EmitBytes(StringRef((char *)&Type, sizeof(Type))); + Streamer->EmitIntValue(static_cast<uint16_t>(Flags), sizeof(Flags)); + Streamer->EmitBytes(StringRef(Var.Name.c_str(), NameLength)); + + for (const auto &Range : Var.Ranges) { + // Emit a range record + switch (Range.loc.vlType) { + case ICorDebugInfo::VLT_REG: + case ICorDebugInfo::VLT_REG_FP: { + + // Currently only support integer registers. + // TODO: support xmm registers + if (Range.loc.vlReg.vlrReg >= + sizeof(cvRegMapAmd64) / sizeof(cvRegMapAmd64[0])) { + break; + } + SymbolRecordKind SymbolKind = SymbolRecordKind::DefRangeRegisterSym; + unsigned SizeofDefRangeRegisterSym = sizeof(DefRangeRegisterSym::Hdr) + + sizeof(DefRangeRegisterSym::Range); + EmitSymRecord(SizeofDefRangeRegisterSym, SymbolKind); + + DefRangeRegisterSym DefRangeRegisterSymbol(SymbolKind); + DefRangeRegisterSymbol.Range.OffsetStart = Range.startOffset; + DefRangeRegisterSymbol.Range.Range = + Range.endOffset - Range.startOffset; + DefRangeRegisterSymbol.Range.ISectStart = 0; + DefRangeRegisterSymbol.Hdr.Register = + cvRegMapAmd64[Range.loc.vlReg.vlrReg]; + unsigned Length = sizeof(DefRangeRegisterSymbol.Hdr); + Streamer->EmitBytes( + StringRef((char *)&DefRangeRegisterSymbol.Hdr, Length)); + EmitVarDefRange(Fn, DefRangeRegisterSymbol.Range); + break; + } + + case ICorDebugInfo::VLT_STK: { + + // TODO: support REGNUM_AMBIENT_SP + if (Range.loc.vlStk.vlsBaseReg >= + sizeof(cvRegMapAmd64) / sizeof(cvRegMapAmd64[0])) { + break; + } + + assert(Range.loc.vlStk.vlsBaseReg < + sizeof(cvRegMapAmd64) / sizeof(cvRegMapAmd64[0]) && + "Register number should be in the range of [REGNUM_RAX, " + "REGNUM_R15]."); + + SymbolRecordKind SymbolKind = SymbolRecordKind::DefRangeRegisterRelSym; + unsigned SizeofDefRangeRegisterRelSym = + sizeof(DefRangeRegisterRelSym::Hdr) + + sizeof(DefRangeRegisterRelSym::Range); + EmitSymRecord(SizeofDefRangeRegisterRelSym, SymbolKind); + + DefRangeRegisterRelSym DefRangeRegisterRelSymbol(SymbolKind); + DefRangeRegisterRelSymbol.Range.OffsetStart = Range.startOffset; + DefRangeRegisterRelSymbol.Range.Range = + Range.endOffset - Range.startOffset; + DefRangeRegisterRelSymbol.Range.ISectStart = 0; + DefRangeRegisterRelSymbol.Hdr.Register = + cvRegMapAmd64[Range.loc.vlStk.vlsBaseReg]; + DefRangeRegisterRelSymbol.Hdr.BasePointerOffset = + Range.loc.vlStk.vlsOffset; + + unsigned Length = sizeof(DefRangeRegisterRelSymbol.Hdr); + Streamer->EmitBytes( + StringRef((char *)&DefRangeRegisterRelSymbol.Hdr, Length)); + EmitVarDefRange(Fn, DefRangeRegisterRelSymbol.Range); + break; + } + + case ICorDebugInfo::VLT_REG_BYREF: + case ICorDebugInfo::VLT_STK_BYREF: + case ICorDebugInfo::VLT_REG_REG: + case ICorDebugInfo::VLT_REG_STK: + case ICorDebugInfo::VLT_STK_REG: + case ICorDebugInfo::VLT_STK2: + case ICorDebugInfo::VLT_FPSTK: + case ICorDebugInfo::VLT_FIXED_VA: + // TODO: for optimized debugging + break; + + default: + assert(false && "Unknown varloc type!"); + break; + } + } + } +} + +void ObjectWriter::EmitCVDebugFunctionInfo(const char *FunctionName, + int FunctionSize) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF); + + // Mark the end of function. + MCSymbol *FnEnd = OutContext->createTempSymbol(); + Streamer->EmitLabel(FnEnd); + + MCSection *Section = ObjFileInfo->getCOFFDebugSymbolsSection(); + Streamer->SwitchSection(Section); + // Emit debug section magic before the first entry. + if (FuncId == 1) { + Streamer->EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4); + } + MCSymbol *Fn = OutContext->getOrCreateSymbol(Twine(FunctionName)); + + // Emit a symbol subsection, required by VS2012+ to find function boundaries. + MCSymbol *SymbolsBegin = OutContext->createTempSymbol(), + *SymbolsEnd = OutContext->createTempSymbol(); + Streamer->EmitIntValue(unsigned(DebugSubsectionKind::Symbols), 4); + EmitLabelDiff(SymbolsBegin, SymbolsEnd); + Streamer->EmitLabel(SymbolsBegin); + { + ProcSym ProcSymbol(SymbolRecordKind::GlobalProcIdSym); + ProcSymbol.CodeSize = FunctionSize; + ProcSymbol.DbgEnd = FunctionSize; + + unsigned FunctionNameLength = strlen(FunctionName) + 1; + unsigned HeaderSize = + sizeof(ProcSymbol.Parent) + sizeof(ProcSymbol.End) + + sizeof(ProcSymbol.Next) + sizeof(ProcSymbol.CodeSize) + + sizeof(ProcSymbol.DbgStart) + sizeof(ProcSymbol.DbgEnd) + + sizeof(ProcSymbol.FunctionType); + unsigned SymbolSize = HeaderSize + 4 + 2 + 1 + FunctionNameLength; + EmitSymRecord(SymbolSize, SymbolRecordKind::GlobalProcIdSym); + + Streamer->EmitBytes(StringRef((char *)&ProcSymbol.Parent, HeaderSize)); + // Emit relocation + Streamer->EmitCOFFSecRel32(Fn, 0); + Streamer->EmitCOFFSectionIndex(Fn); + + // Emit flags + Streamer->EmitIntValue(0, 1); + + // Emit the function display name as a null-terminated string. + + Streamer->EmitBytes(StringRef(FunctionName, FunctionNameLength)); + + // Emit local var info + int NumVarInfos = DebugVarInfos.size(); + if (NumVarInfos > 0) { + EmitCVDebugVarInfo(Fn, &DebugVarInfos[0], NumVarInfos); + DebugVarInfos.clear(); + } + + // We're done with this function. + EmitSymRecord(0, SymbolRecordKind::ProcEnd); + } + + Streamer->EmitLabel(SymbolsEnd); + + // Every subsection must be aligned to a 4-byte boundary. + Streamer->EmitValueToAlignment(4); + + // We have an assembler directive that takes care of the whole line table. + // We also increase function id for the next function. + Streamer->EmitCVLinetableDirective(FuncId++, Fn, FnEnd); +} + +void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) { + assert(FileId > 0 && "FileId should be greater than 0."); + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { + Streamer->EmitCVFileDirective(FileId, FileName); + } else { + Streamer->EmitDwarfFileDirective(FileId, "", FileName); + } +} + +void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName, + int FunctionSize) { + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { + Streamer->EmitCVFuncIdDirective(FuncId); + EmitCVDebugFunctionInfo(FunctionName, FunctionSize); + } else { + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) { + MCSymbol *Sym = OutContext->getOrCreateSymbol(Twine(FunctionName)); + Streamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); + Streamer->emitELFSize(Sym, + MCConstantExpr::create(FunctionSize, *OutContext)); + } + // TODO: Should test it for Macho. + } +} + +void ObjectWriter::EmitDebugVar(char *Name, int TypeIndex, bool IsParm, + int RangeCount, + const ICorDebugInfo::NativeVarInfo *Ranges) { + assert(RangeCount != 0); + DebugVarInfo NewVar(Name, TypeIndex, IsParm); + + for (int I = 0; I < RangeCount; I++) { + assert(Ranges[0].varNumber == Ranges[I].varNumber); + NewVar.Ranges.push_back(Ranges[I]); + } + + DebugVarInfos.push_back(NewVar); +} + +void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber, + int ColNumber) { + assert(FileId > 0 && "FileId should be greater than 0."); + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { + Streamer->EmitCVFuncIdDirective(FuncId); + Streamer->EmitCVLocDirective(FuncId, FileId, LineNumber, ColNumber, false, + true, "", SMLoc()); + } else { + Streamer->EmitDwarfLocDirective(FileId, LineNumber, ColNumber, 1, 0, 0, ""); + } +} + +void ObjectWriter::EmitCVUserDefinedTypesSymbols() { + const auto &UDTs = TypeBuilder.GetUDTs(); + if (UDTs.empty()) { + return; + } + MCSection *Section = ObjFileInfo->getCOFFDebugSymbolsSection(); + Streamer->SwitchSection(Section); + + MCSymbol *SymbolsBegin = OutContext->createTempSymbol(), + *SymbolsEnd = OutContext->createTempSymbol(); + Streamer->EmitIntValue(unsigned(DebugSubsectionKind::Symbols), 4); + EmitLabelDiff(SymbolsBegin, SymbolsEnd); + Streamer->EmitLabel(SymbolsBegin); + + for (const std::pair<std::string, codeview::TypeIndex> &UDT : UDTs) { + unsigned NameLength = UDT.first.length() + 1; + unsigned RecordLength = 2 + 4 + NameLength; + Streamer->EmitIntValue(RecordLength, 2); + Streamer->EmitIntValue(unsigned(SymbolKind::S_UDT), 2); + Streamer->EmitIntValue(UDT.second.getIndex(), 4); + Streamer->EmitBytes(StringRef(UDT.first.c_str(), NameLength)); + } + Streamer->EmitLabel(SymbolsEnd); + Streamer->EmitValueToAlignment(4); +} + +void ObjectWriter::EmitDebugModuleInfo() { + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { + TypeBuilder.EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection()); + EmitCVUserDefinedTypesSymbols(); + } + + // Ensure ending all sections. + for (auto Section : Sections) { + Streamer->endSection(Section); + } + + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { + MCSection *Section = ObjFileInfo->getCOFFDebugSymbolsSection(); + Streamer->SwitchSection(Section); + Streamer->EmitCVFileChecksumsDirective(); + Streamer->EmitCVStringTableDirective(); + } else { + OutContext->setGenDwarfForAssembly(true); + } +} + +unsigned +ObjectWriter::GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetEnumTypeIndex(TypeDescriptor, TypeRecords); +} + +unsigned +ObjectWriter::GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetClassTypeIndex(ClassDescriptor); +} + +unsigned ObjectWriter::GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetCompleteClassTypeIndex( + ClassDescriptor, ClassFieldsDescriptor, FieldsDescriptors); +} + +unsigned +ObjectWriter::GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor); +} + +unsigned +ObjectWriter::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetPointerTypeIndex(PointerDescriptor); +} + +unsigned +ObjectWriter::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes); +} + +unsigned +ObjectWriter::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) { + assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && + "only COFF is supported now"); + return TypeBuilder.GetMemberFunctionId(MemberIdDescriptor); +} + diff --git a/src/Native/ObjWriter/objwriter.exports b/src/Native/ObjWriter/objwriter.exports new file mode 100644 index 000000000..c42c465df --- /dev/null +++ b/src/Native/ObjWriter/objwriter.exports @@ -0,0 +1,26 @@ +InitObjWriter +FinishObjWriter +SwitchSection +SetCodeSectionAttribute +EmitAlignment +EmitBlob +EmitIntValue +EmitSymbolDef +EmitSymbolRef +EmitWinFrameInfo +EmitCFIStart +EmitCFIEnd +EmitCFICode +EmitCFILsda +EmitDebugFileInfo +EmitDebugLoc +EmitDebugFunctionInfo +EmitDebugModuleInfo +EmitDebugVar +GetEnumTypeIndex +GetClassTypeIndex +GetCompleteClassTypeIndex +GetArrayTypeIndex +GetPointerTypeIndex +GetMemberFunctionTypeIndex +GetMemberFunctionIdTypeIndex
\ No newline at end of file diff --git a/src/Native/ObjWriter/objwriter.h b/src/Native/ObjWriter/objwriter.h new file mode 100644 index 000000000..bf9757b37 --- /dev/null +++ b/src/Native/ObjWriter/objwriter.h @@ -0,0 +1,312 @@ +//===---- objwriter.h --------------------------------*- C++ -*-===// +// +// object writer +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" + +#include "cfi.h" +#include "jitDebugInfo.h" +#include <string> +#include <set> +#include "typeBuilder.h" + +using namespace llvm; +using namespace llvm::codeview; + +enum CustomSectionAttributes : int32_t { + CustomSectionAttributes_ReadOnly = 0x0000, + CustomSectionAttributes_Writeable = 0x0001, + CustomSectionAttributes_Executable = 0x0002, + CustomSectionAttributes_MachO_Init_Func_Pointers = 0x0100, +}; + +enum class RelocType { + IMAGE_REL_BASED_ABSOLUTE = 0x00, + IMAGE_REL_BASED_HIGHLOW = 0x03, + IMAGE_REL_BASED_DIR64 = 0x0A, + IMAGE_REL_BASED_REL32 = 0x10, +}; + +class ObjectWriter { +public: + bool Init(StringRef FunctionName); + void Finish(); + + void SwitchSection(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName); + void SetCodeSectionAttribute(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName); + + void EmitAlignment(int ByteAlignment); + void EmitBlob(int BlobSize, const char *Blob); + void EmitIntValue(uint64_t Value, unsigned Size); + void EmitSymbolDef(const char *SymbolName); + void EmitWinFrameInfo(const char *FunctionName, int StartOffset, + int EndOffset, const char *BlobSymbolName); + int EmitSymbolRef(const char *SymbolName, RelocType RelocType, int Delta); + + void EmitDebugFileInfo(int FileId, const char *FileName); + void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize); + void EmitDebugVar(char *Name, int TypeIndex, bool IsParm, int RangeCount, + const ICorDebugInfo::NativeVarInfo *Ranges); + void EmitDebugLoc(int NativeOffset, int FileId, int LineNumber, + int ColNumber); + void EmitDebugModuleInfo(); + + void EmitCFIStart(int Offset); + void EmitCFIEnd(int Offset); + void EmitCFILsda(const char *LsdaBlobSymbolName); + void EmitCFICode(int Offset, const char *Blob); + + unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords); + unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor); + unsigned GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors); + + unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor); + + unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor); + + unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes); + + unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor); + +private: + void EmitLabelDiff(const MCSymbol *From, const MCSymbol *To, + unsigned int Size = 4); + void EmitSymRecord(int Size, SymbolRecordKind SymbolKind); + void EmitCOFFSecRel32Value(MCExpr const *Value); + + void EmitVarDefRange(const MCSymbol *Fn, const LocalVariableAddrRange &Range); + void EmitCVDebugVarInfo(const MCSymbol *Fn, const DebugVarInfo LocInfos[], + int NumVarInfos); + void EmitCVDebugFunctionInfo(const char *FunctionName, int FunctionSize); + + const MCSymbolRefExpr *GetSymbolRefExpr( + const char *SymbolName, + MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None); + + MCSection *GetSection(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName); + + MCSection *GetSpecificSection(const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName); + + void EmitCVUserDefinedTypesSymbols(); + + void InitTripleName(); + Triple GetTriple(); + +private: + std::unique_ptr<MCRegisterInfo> RegisterInfo; + std::unique_ptr<MCAsmInfo> AsmInfo; + std::unique_ptr<MCObjectFileInfo> ObjFileInfo; + std::unique_ptr<MCContext> OutContext; + MCAsmBackend *AsmBackend; // Owned by MCStreamer + std::unique_ptr<MCInstrInfo> InstrInfo; + std::unique_ptr<MCSubtargetInfo> SubtargetInfo; + MCCodeEmitter *CodeEmitter; // Owned by MCStreamer + std::unique_ptr<TargetMachine> TMachine; + std::unique_ptr<AsmPrinter> AssemblerPrinter; + MCAssembler *Assembler; // Owned by MCStreamer + + std::unique_ptr<raw_fd_ostream> OS; + MCTargetOptions TargetMOptions; + bool FrameOpened; + std::vector<DebugVarInfo> DebugVarInfos; + + std::set<MCSection *> Sections; + int FuncId; + + UserDefinedTypesBuilder TypeBuilder; + + std::string TripleName; + + MCObjectStreamer *Streamer; // Owned by AsmPrinter +}; + +// When object writer is created/initialized successfully, it is returned. +// Or null object is returned. Client should check this. +extern "C" ObjectWriter *InitObjWriter(const char *ObjectFilePath) { + ObjectWriter *OW = new ObjectWriter(); + if (OW->Init(ObjectFilePath)) { + return OW; + } + delete OW; + return nullptr; +} + +extern "C" void FinishObjWriter(ObjectWriter *OW) { + assert(OW && "ObjWriter is null"); + OW->Finish(); + delete OW; +} + +extern "C" void SwitchSection(ObjectWriter *OW, const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName) { + assert(OW && "ObjWriter is null"); + OW->SwitchSection(SectionName, attributes, ComdatName); +} + +extern "C" void SetCodeSectionAttribute(ObjectWriter *OW, + const char *SectionName, + CustomSectionAttributes attributes, + const char *ComdatName) { + assert(OW && "ObjWriter is null"); + OW->SetCodeSectionAttribute(SectionName, attributes, ComdatName); +} + +extern "C" void EmitAlignment(ObjectWriter *OW, int ByteAlignment) { + assert(OW && "ObjWriter is null"); + OW->EmitAlignment(ByteAlignment); +} + +extern "C" void EmitBlob(ObjectWriter *OW, int BlobSize, const char *Blob) { + assert(OW && "ObjWriter null"); + OW->EmitBlob(BlobSize, Blob); +} + +extern "C" void EmitIntValue(ObjectWriter *OW, uint64_t Value, unsigned Size) { + assert(OW && "ObjWriter is null"); + OW->EmitIntValue(Value, Size); +} + +extern "C" void EmitSymbolDef(ObjectWriter *OW, const char *SymbolName) { + assert(OW && "ObjWriter is null"); + OW->EmitSymbolDef(SymbolName); +} + +extern "C" int EmitSymbolRef(ObjectWriter *OW, const char *SymbolName, + RelocType RelocType, int Delta) { + assert(OW && "ObjWriter is null"); + return OW->EmitSymbolRef(SymbolName, RelocType, Delta); +} + +extern "C" void EmitWinFrameInfo(ObjectWriter *OW, const char *FunctionName, + int StartOffset, int EndOffset, + const char *BlobSymbolName) { + assert(OW && "ObjWriter is null"); + OW->EmitWinFrameInfo(FunctionName, StartOffset, EndOffset, BlobSymbolName); +} + +extern "C" void EmitCFIStart(ObjectWriter *OW, int Offset) { + assert(OW && "ObjWriter is null"); + OW->EmitCFIStart(Offset); +} + +extern "C" void EmitCFIEnd(ObjectWriter *OW, int Offset) { + assert(OW && "ObjWriter is null"); + OW->EmitCFIEnd(Offset); +} + +extern "C" void EmitCFILsda(ObjectWriter *OW, const char *LsdaBlobSymbolName) { + assert(OW && "ObjWriter is null"); + OW->EmitCFILsda(LsdaBlobSymbolName); +} + +extern "C" void EmitCFICode(ObjectWriter *OW, int Offset, const char *Blob) { + assert(OW && "ObjWriter is null"); + OW->EmitCFICode(Offset, Blob); +} + +extern "C" void EmitDebugFileInfo(ObjectWriter *OW, int FileId, + const char *FileName) { + assert(OW && "ObjWriter is null"); + OW->EmitDebugFileInfo(FileId, FileName); +} + +extern "C" void EmitDebugFunctionInfo(ObjectWriter *OW, + const char *FunctionName, + int FunctionSize) { + assert(OW && "ObjWriter is null"); + OW->EmitDebugFunctionInfo(FunctionName, FunctionSize); +} + +extern "C" void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex, + bool IsParam, int RangeCount, + ICorDebugInfo::NativeVarInfo *Ranges) { + assert(OW && "ObjWriter is null"); + OW->EmitDebugVar(Name, TypeIndex, IsParam, RangeCount, Ranges); +} + +extern "C" void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId, + int LineNumber, int ColNumber) { + assert(OW && "ObjWriter is null"); + OW->EmitDebugLoc(NativeOffset, FileId, LineNumber, ColNumber); +} + +// This should be invoked at the end of module emission to finalize +// debug module info. +extern "C" void EmitDebugModuleInfo(ObjectWriter *OW) { + assert(OW && "ObjWriter is null"); + OW->EmitDebugModuleInfo(); +} + +extern "C" unsigned GetEnumTypeIndex(ObjectWriter *OW, + EnumTypeDescriptor TypeDescriptor, + EnumRecordTypeDescriptor *TypeRecords) { + assert(OW && "ObjWriter is null"); + return OW->GetEnumTypeIndex(TypeDescriptor, TypeRecords); +} + +extern "C" unsigned GetClassTypeIndex(ObjectWriter *OW, + ClassTypeDescriptor ClassDescriptor) { + assert(OW && "ObjWriter is null"); + return OW->GetClassTypeIndex(ClassDescriptor); +} + +extern "C" unsigned +GetCompleteClassTypeIndex(ObjectWriter *OW, ClassTypeDescriptor ClassDescriptor, + ClassFieldsTypeDescriptior ClassFieldsDescriptor, + DataFieldDescriptor *FieldsDescriptors) { + assert(OW && "ObjWriter is null"); + return OW->GetCompleteClassTypeIndex(ClassDescriptor, ClassFieldsDescriptor, + FieldsDescriptors); +} + +extern "C" unsigned GetArrayTypeIndex(ObjectWriter *OW, + ClassTypeDescriptor ClassDescriptor, + ArrayTypeDescriptor ArrayDescriptor) { + assert(OW && "ObjWriter is null"); + return OW->GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor); +} + +extern "C" unsigned GetPointerTypeIndex(ObjectWriter *OW, + PointerTypeDescriptor PointerDescriptor) { + assert(OW && "ObjWriter is null"); + return OW->GetPointerTypeIndex(PointerDescriptor); +} + +extern "C" unsigned GetMemberFunctionTypeIndex(ObjectWriter *OW, + MemberFunctionTypeDescriptor MemberDescriptor, + uint32_t *ArgumentTypes) { + assert(OW && "ObjWriter is null"); + return OW->GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes); +} + +extern "C" unsigned GetMemberFunctionIdTypeIndex(ObjectWriter *OW, + MemberFunctionIdTypeDescriptor MemberIdDescriptor) { + assert(OW && "ObjWriter is null"); + return OW->GetMemberFunctionId(MemberIdDescriptor); +} diff --git a/src/Native/ObjWriter/typeBuilder.cpp b/src/Native/ObjWriter/typeBuilder.cpp new file mode 100644 index 000000000..2b6edacc5 --- /dev/null +++ b/src/Native/ObjWriter/typeBuilder.cpp @@ -0,0 +1,321 @@ +//===---- typeBuilder.cpp --------------------------------*- C++ -*-===// +// +// type builder implementation using codeview::TypeTableBuilder +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. +// +//===----------------------------------------------------------------------===// + +#include "typeBuilder.h" +#include "llvm/BinaryFormat/COFF.h" +#include <sstream> +#include <vector> + +UserDefinedTypesBuilder::UserDefinedTypesBuilder() + : Allocator(), TypeTable(Allocator), Streamer(nullptr), + TargetPointerSize(0) +{ + VFTableShapeRecord vfTableShape(TypeRecordKind::VFTableShape); + ClassVTableTypeIndex = TypeTable.writeKnownType(vfTableShape); +} + +void UserDefinedTypesBuilder::SetStreamer(MCObjectStreamer *Streamer) { + assert(this->Streamer == nullptr); + assert(Streamer != nullptr); + this->Streamer = Streamer; +} + +void UserDefinedTypesBuilder::SetTargetPointerSize(unsigned TargetPointerSize) { + assert(this->TargetPointerSize == 0); + assert(TargetPointerSize != 0); + this->TargetPointerSize = TargetPointerSize; +} + +void UserDefinedTypesBuilder::EmitCodeViewMagicVersion() { + Streamer->EmitValueToAlignment(4); + Streamer->AddComment("Debug section magic"); + Streamer->EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4); +} + +ClassOptions UserDefinedTypesBuilder::GetCommonClassOptions() { + return ClassOptions(); +} + +void UserDefinedTypesBuilder::EmitTypeInformation( + MCSection *COFFDebugTypesSection) { + + if (TypeTable.empty()) + return; + + Streamer->SwitchSection(COFFDebugTypesSection); + EmitCodeViewMagicVersion(); + + TypeTable.ForEachRecord([&](TypeIndex FieldTypeIndex, + ArrayRef<uint8_t> Record) { + StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size()); + Streamer->EmitBinaryData(S); + }); +} + +unsigned UserDefinedTypesBuilder::GetEnumFieldListType( + uint64 Count, const EnumRecordTypeDescriptor *TypeRecords) { + FieldListRecordBuilder FLRB(TypeTable); + FLRB.begin(); +#ifndef NDEBUG + uint64 MaxInt = (unsigned int)-1; + assert(Count <= MaxInt && "There are too many fields inside enum"); +#endif + for (int i = 0; i < (int)Count; ++i) { + EnumRecordTypeDescriptor record = TypeRecords[i]; + EnumeratorRecord ER(MemberAccess::Public, APSInt::getUnsigned(record.Value), + record.Name); + FLRB.writeMemberType(ER); + } + TypeIndex Type = FLRB.end(true); + return Type.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetEnumTypeIndex( + const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) { + + ClassOptions CO = GetCommonClassOptions(); + unsigned FieldListIndex = + GetEnumFieldListType(TypeDescriptor.ElementCount, TypeRecords); + TypeIndex FieldListIndexType = TypeIndex(FieldListIndex); + TypeIndex ElementTypeIndex = TypeIndex(TypeDescriptor.ElementType); + + EnumRecord EnumRecord(TypeDescriptor.ElementCount, CO, FieldListIndexType, + TypeDescriptor.Name, StringRef(), + ElementTypeIndex); + + TypeIndex Type = TypeTable.writeKnownType(EnumRecord); + UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type)); + return Type.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor) { + TypeRecordKind Kind = + ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class; + ClassOptions CO = ClassOptions::ForwardReference | GetCommonClassOptions(); + + TypeIndex FieldListIndex = TypeIndex(); + uint16_t memberCount = 0; + + if (!ClassDescriptor.IsStruct) { + FieldListRecordBuilder FLBR(TypeTable); + FLBR.begin(); + memberCount++; + AddClassVTShape(FLBR); + FieldListIndex = FLBR.end(true); + } + + ClassRecord CR(Kind, memberCount, CO, FieldListIndex, TypeIndex(), TypeIndex(), 0, + ClassDescriptor.Name, StringRef()); + TypeIndex FwdDeclTI = TypeTable.writeKnownType(CR); + return FwdDeclTI.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors) { + + FieldListRecordBuilder FLBR(TypeTable); + FLBR.begin(); + + uint16_t memberCount = 0; + if (!ClassDescriptor.IsStruct) { + memberCount++; + AddClassVTShape(FLBR); + } + + if (ClassDescriptor.BaseClassId != 0) { + memberCount++; + AddBaseClass(FLBR, ClassDescriptor.BaseClassId); + } + + for (int i = 0; i < ClassFieldsDescriptor.FieldsCount; ++i) { + DataFieldDescriptor desc = FieldsDescriptors[i]; + MemberAccess Access = MemberAccess::Public; + TypeIndex MemberBaseType(desc.FieldTypeIndex); + if (desc.Offset == 0xFFFFFFFF) + { + StaticDataMemberRecord SDMR(Access, MemberBaseType, desc.Name); + FLBR.writeMemberType(SDMR); + } + else + { + int MemberOffsetInBytes = desc.Offset; + DataMemberRecord DMR(Access, MemberBaseType, MemberOffsetInBytes, + desc.Name); + FLBR.writeMemberType(DMR); + } + memberCount++; + } + TypeIndex FieldListIndex = FLBR.end(true); + TypeRecordKind Kind = + ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class; + ClassOptions CO = GetCommonClassOptions(); + ClassRecord CR(Kind, memberCount, CO, FieldListIndex, + TypeIndex(), TypeIndex(), ClassFieldsDescriptor.Size, + ClassDescriptor.Name, StringRef()); + TypeIndex ClassIndex = TypeTable.writeKnownType(CR); + + UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex)); + + return ClassIndex.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetArrayTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor) { + FieldListRecordBuilder FLBR(TypeTable); + FLBR.begin(); + + unsigned Offset = 0; + unsigned FieldsCount = 0; + + assert(ClassDescriptor.BaseClassId != 0); + + AddClassVTShape(FLBR); + FieldsCount++; + AddBaseClass(FLBR, ClassDescriptor.BaseClassId); + FieldsCount++; + Offset += TargetPointerSize; + + MemberAccess Access = MemberAccess::Public; + TypeIndex IndexType = TypeIndex(SimpleTypeKind::Int32); + DataMemberRecord CountDMR(Access, IndexType, Offset, "count"); + FLBR.writeMemberType(CountDMR); + FieldsCount++; + Offset += TargetPointerSize; + + if (ArrayDescriptor.IsMultiDimensional == 1) { + for (unsigned i = 0; i < ArrayDescriptor.Rank; ++i) { + DataMemberRecord LengthDMR(Access, TypeIndex(SimpleTypeKind::Int32), + Offset, ArrayDimentions.GetLengthName(i)); + FLBR.writeMemberType(LengthDMR); + FieldsCount++; + Offset += 4; + } + + for (unsigned i = 0; i < ArrayDescriptor.Rank; ++i) { + DataMemberRecord BoundsDMR(Access, TypeIndex(SimpleTypeKind::Int32), + Offset, ArrayDimentions.GetBoundsName(i)); + FLBR.writeMemberType(BoundsDMR); + FieldsCount++; + Offset += 4; + } + } + + TypeIndex ElementTypeIndex = TypeIndex(ArrayDescriptor.ElementType); + ArrayRecord AR(ElementTypeIndex, IndexType, ArrayDescriptor.Size, ""); + TypeIndex ArrayIndex = TypeTable.writeKnownType(AR); + DataMemberRecord ArrayDMR(Access, ArrayIndex, Offset, "values"); + FLBR.writeMemberType(ArrayDMR); + FieldsCount++; + + TypeIndex FieldListIndex = FLBR.end(true); + + assert(ClassDescriptor.IsStruct == false); + TypeRecordKind Kind = TypeRecordKind::Class; + ClassOptions CO = GetCommonClassOptions(); + ClassRecord CR(Kind, FieldsCount, CO, FieldListIndex, TypeIndex(), + TypeIndex(), ArrayDescriptor.Size, ClassDescriptor.Name, + StringRef()); + TypeIndex ClassIndex = TypeTable.writeKnownType(CR); + + UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex)); + + return ClassIndex.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) +{ + uint32_t elementType = PointerDescriptor.ElementType; + PointerKind pointerKind = PointerDescriptor.Is64Bit ? PointerKind::Near64 : PointerKind::Near32; + PointerMode pointerMode = PointerDescriptor.IsReference ? PointerMode::LValueReference : PointerMode::Pointer; + PointerOptions pointerOptions = PointerDescriptor.IsConst ? PointerOptions::Const : PointerOptions::None; + + PointerRecord PointerToClass(TypeIndex(elementType), pointerKind, pointerMode, pointerOptions, 0); + TypeIndex PointerIndex = TypeTable.writeKnownType(PointerToClass); + return PointerIndex.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes) +{ + std::vector<TypeIndex> argumentTypes; + argumentTypes.reserve(MemberDescriptor.NumberOfArguments); + for (uint16_t iArgument = 0; iArgument < MemberDescriptor.NumberOfArguments; iArgument++) + { + argumentTypes.emplace_back(ArgumentTypes[iArgument]); + } + + ArgListRecord ArgList(TypeRecordKind::ArgList, argumentTypes); + TypeIndex ArgumentList = TypeTable.writeKnownType(ArgList); + + MemberFunctionRecord MemberFunction(TypeIndex(MemberDescriptor.ReturnType), + TypeIndex(MemberDescriptor.ContainingClass), + TypeIndex(MemberDescriptor.TypeIndexOfThisPointer), + CallingConvention(MemberDescriptor.CallingConvention), + FunctionOptions::None, MemberDescriptor.NumberOfArguments, + ArgumentList, + MemberDescriptor.ThisAdjust); + + TypeIndex MemberFunctionIndex = TypeTable.writeKnownType(MemberFunction); + return MemberFunctionIndex.getIndex(); +} + +unsigned UserDefinedTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) +{ + MemberFuncIdRecord MemberFuncId(TypeIndex(MemberIdDescriptor.MemberFunction), TypeIndex(MemberIdDescriptor.ParentClass), MemberIdDescriptor.Name); + TypeIndex MemberFuncIdIndex = TypeTable.writeKnownType(MemberFuncId); + return MemberFuncIdIndex.getIndex(); +} + +void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR, + unsigned BaseClassId) { + MemberAttributes def; + TypeIndex BaseTypeIndex(BaseClassId); + BaseClassRecord BCR(def, BaseTypeIndex, 0); + FLBR.writeMemberType(BCR); +} + +void UserDefinedTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) { + VFPtrRecord VfPtr(ClassVTableTypeIndex); + FLBR.writeMemberType(VfPtr); +} + +const char *ArrayDimensionsDescriptor::GetLengthName(unsigned index) { + if (Lengths.size() <= index) { + Resize(index + 1); + } + return Lengths[index].c_str(); +} + +const char *ArrayDimensionsDescriptor::GetBoundsName(unsigned index) { + if (Bounds.size() <= index) { + Resize(index); + } + return Bounds[index].c_str(); +} + +void ArrayDimensionsDescriptor::Resize(unsigned NewSize) { + unsigned OldSize = Lengths.size(); + assert(OldSize == Bounds.size()); + Lengths.resize(NewSize); + Bounds.resize(NewSize); + for (unsigned i = OldSize; i < NewSize; ++i) { + std::stringstream ss; + ss << "length" << i; + ss >> Lengths[i]; + ss.clear(); + ss << "bounds" << i; + ss >> Bounds[i]; + } +} diff --git a/src/Native/ObjWriter/typeBuilder.h b/src/Native/ObjWriter/typeBuilder.h new file mode 100644 index 000000000..a5037b769 --- /dev/null +++ b/src/Native/ObjWriter/typeBuilder.h @@ -0,0 +1,145 @@ +//===---- typeBuilder.h --------------------------------*- C++ -*-===// +// +// type builder is used to convert .Net types into CodeView descriptors. +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/MC/MCObjectStreamer.h" + +#include <string> +#include <vector> + +using namespace llvm; +using namespace llvm::codeview; + +typedef unsigned long long uint64; + +#pragma pack(push, 8) + +extern "C" struct EnumRecordTypeDescriptor { + uint64 Value; + char *Name; +}; + +extern "C" struct EnumTypeDescriptor { + uint32_t ElementType; + uint64 ElementCount; + char *Name; +}; + +extern "C" struct ClassTypeDescriptor { + int32_t IsStruct; + char *Name; + uint32_t BaseClassId; +}; + +extern "C" struct DataFieldDescriptor { + uint32_t FieldTypeIndex; + uint64 Offset; + char *Name; +}; + +extern "C" struct ClassFieldsTypeDescriptior { + uint64 Size; + int32_t FieldsCount; +}; + +extern "C" struct ArrayTypeDescriptor { + uint32_t Rank; + uint32_t ElementType; + uint32_t Size; + int32_t IsMultiDimensional; +}; + +extern "C" struct PointerTypeDescriptor { + uint32_t ElementType; + int32_t IsReference; + int32_t IsConst; + int32_t Is64Bit; +}; + +extern "C" struct MemberFunctionTypeDescriptor { + uint32_t ReturnType; + uint32_t ContainingClass; + uint32_t TypeIndexOfThisPointer; + int32_t ThisAdjust; + uint32_t CallingConvention; + uint16_t NumberOfArguments; +}; + +extern "C" struct MemberFunctionIdTypeDescriptor { + uint32_t MemberFunction; + uint32_t ParentClass; + char *Name; +}; + +class ArrayDimensionsDescriptor { +public: + const char *GetLengthName(unsigned index); + const char *GetBoundsName(unsigned index); + +private: + void Resize(unsigned NewSize); + + std::vector<std::string> Lengths; + std::vector<std::string> Bounds; +}; + +#pragma pack(pop) +class UserDefinedTypesBuilder { +public: + UserDefinedTypesBuilder(); + void SetStreamer(MCObjectStreamer *Streamer); + void SetTargetPointerSize(unsigned TargetPointerSize); + void EmitTypeInformation(MCSection *COFFDebugTypesSection); + + unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords); + unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor); + unsigned GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors); + + unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor); + + unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor); + + unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes); + + unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor); + + const std::vector<std::pair<std::string, codeview::TypeIndex>> &GetUDTs() { + return UserDefinedTypes; + } + +private: + void EmitCodeViewMagicVersion(); + ClassOptions GetCommonClassOptions(); + + unsigned GetEnumFieldListType(uint64 Count, + const EnumRecordTypeDescriptor *TypeRecords); + + void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId); + void AddClassVTShape(FieldListRecordBuilder &FLBR); + + BumpPtrAllocator Allocator; + TypeTableBuilder TypeTable; + + MCObjectStreamer *Streamer; + unsigned TargetPointerSize; + + ArrayDimensionsDescriptor ArrayDimentions; + TypeIndex ClassVTableTypeIndex; + + std::vector<std::pair<std::string, codeview::TypeIndex>> UserDefinedTypes; +}; diff --git a/src/Native/Runtime/unix/UnixContext.cpp b/src/Native/Runtime/unix/UnixContext.cpp index 3be92658f..0fdbc23ca 100644 --- a/src/Native/Runtime/unix/UnixContext.cpp +++ b/src/Native/Runtime/unix/UnixContext.cpp @@ -197,45 +197,11 @@ #endif // __APPLE__ -// Update unw_context_t from REGDISPLAY -static void RegDisplayToUnwindContext(REGDISPLAY* regDisplay, unw_context_t *unwContext) -{ -#if defined(_ARM_) - // Assuming that unw_set_reg() on cursor will point the cursor to the - // supposed stack frame is dangerous for libunwind-arm in Linux. - // It is because libunwind's unw_cursor_t has other data structure - // initialized by unw_init_local(), which are not updated by - // unw_set_reg(). - -#define ASSIGN_REG(regIndex, regName) \ - unwContext->data[regIndex] = (regDisplay->regName); - -#define ASSIGN_REG_PTR(regIndex, regName) \ - if (regDisplay->p##regName != NULL) \ - unwContext->data[regIndex] = *(regDisplay->p##regName); - - ASSIGN_REG_PTR(4, R4); - ASSIGN_REG_PTR(5, R5); - ASSIGN_REG_PTR(6, R6); - ASSIGN_REG_PTR(7, R7); - ASSIGN_REG_PTR(8, R8); - ASSIGN_REG_PTR(9, R9); - ASSIGN_REG_PTR(10, R10); - ASSIGN_REG_PTR(11, R11); - ASSIGN_REG(13, SP); - ASSIGN_REG_PTR(14, LR); - ASSIGN_REG(15, IP); - -#undef ASSIGN_REG -#undef ASSIGN_REG_PTR - -#endif // _ARM_ -} - -// Update unw_cursor_t from REGDISPLAY +// Update unw_cursor_t from REGDISPLAY. +// NOTE: We don't set the IP here since the current use cases for this function +// don't require it. static void RegDisplayToUnwindCursor(REGDISPLAY* regDisplay, unw_cursor_t *cursor) { -#if defined(_AMD64_) #define ASSIGN_REG(regName1, regName2) \ unw_set_reg(cursor, regName1, regDisplay->regName2); @@ -243,7 +209,7 @@ static void RegDisplayToUnwindCursor(REGDISPLAY* regDisplay, unw_cursor_t *curso if (regDisplay->p##regName2 != NULL) \ unw_set_reg(cursor, regName1, *(regDisplay->p##regName2)); - ASSIGN_REG(UNW_REG_IP, IP) +#if defined(_AMD64_) ASSIGN_REG(UNW_REG_SP, SP) ASSIGN_REG_PTR(UNW_X86_64_RBP, Rbp) ASSIGN_REG_PTR(UNW_X86_64_RBX, Rbx) @@ -251,10 +217,61 @@ static void RegDisplayToUnwindCursor(REGDISPLAY* regDisplay, unw_cursor_t *curso ASSIGN_REG_PTR(UNW_X86_64_R13, R13) ASSIGN_REG_PTR(UNW_X86_64_R14, R14) ASSIGN_REG_PTR(UNW_X86_64_R15, R15) +#elif _ARM_ + ASSIGN_REG(UNW_ARM_SP, SP) + ASSIGN_REG_PTR(UNW_ARM_R4, R4) + ASSIGN_REG_PTR(UNW_ARM_R5, R5) + ASSIGN_REG_PTR(UNW_ARM_R6, R6) + ASSIGN_REG_PTR(UNW_ARM_R7, R7) + ASSIGN_REG_PTR(UNW_ARM_R8, R8) + ASSIGN_REG_PTR(UNW_ARM_R9, R9) + ASSIGN_REG_PTR(UNW_ARM_R10, R10) + ASSIGN_REG_PTR(UNW_ARM_R11, R11) + ASSIGN_REG_PTR(UNW_ARM_R14, LR) +#endif #undef ASSIGN_REG #undef ASSIGN_REG_PTR -#endif // _AMD64_ +} + +// Returns the unw_proc_info_t for a given IP. +bool GetUnwindProcInfo(PCODE ip, unw_proc_info_t *procInfo) +{ + int st; + + unw_context_t unwContext; + unw_cursor_t cursor; + + st = unw_getcontext(&unwContext); + if (st < 0) + { + return false; + } + +#ifdef _AMD64_ + // We manually index into the unw_context_t's internals for now because there's + // no better way to modify it. This will go away in the future when we locate the + // LSDA and other information without initializing an unwind cursor. + unwContext.data[16] = ip; +#elif _ARM_ + ((uint32_t*)(unwContext.data))[15] = ip; +#else + #error "GetUnwindProcInfo is not supported on this arch yet." +#endif + + st = unw_init_local(&cursor, &unwContext); + if (st < 0) + { + return false; + } + + st = unw_get_proc_info(&cursor, procInfo); + if (st < 0) + { + return false; + } + + return true; } // Initialize unw_cursor_t and unw_context_t from REGDISPLAY @@ -268,7 +285,18 @@ bool InitializeUnwindContextAndCursor(REGDISPLAY* regDisplay, unw_cursor_t* curs return false; } - RegDisplayToUnwindContext(regDisplay, unwContext); + // Set the IP here instead of after unwinder initialization. unw_init_local + // will do some initialization of internal structures based on the IP value. + // We manually index into the unw_context_t's internals for now because there's + // no better way to modify it. This whole function will go away in the future + // when we are able to read unwind info without initializing an unwind cursor. +#ifdef _AMD64_ + unwContext->data[16] = regDisplay->IP; +#elif _ARM_ + ((uint32_t*)(unwContext->data))[15] = regDisplay->IP; +#else + #error "InitializeUnwindContextAndCursor is not supported on this arch yet." +#endif st = unw_init_local(cursor, unwContext); if (st < 0) @@ -276,7 +304,7 @@ bool InitializeUnwindContextAndCursor(REGDISPLAY* regDisplay, unw_cursor_t* curs return false; } - // Set the unwind context to the specified windows context + // Set the unwind context to the specified Windows context. RegDisplayToUnwindCursor(regDisplay, cursor); return true; @@ -516,21 +544,9 @@ uint64_t GetPC(void* context) // Find LSDA and start address for a function at address controlPC bool FindProcInfo(UIntNative controlPC, UIntNative* startAddress, UIntNative* lsda) { - unw_context_t unwContext; - unw_cursor_t cursor; - REGDISPLAY regDisplay; - memset(®Display, 0, sizeof(REGDISPLAY)); - - regDisplay.SetIP((PCODE)controlPC); - - if (!InitializeUnwindContextAndCursor(®Display, &cursor, &unwContext)) - { - return false; - } - unw_proc_info_t procInfo; - int st = unw_get_proc_info(&cursor, &procInfo); - if (st < 0) + + if (!GetUnwindProcInfo((PCODE)controlPC, &procInfo)) { return false; } diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems index 90a656f52..5b7629f24 100644 --- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems +++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems @@ -53,6 +53,7 @@ <Compile Include="$(MSBuildThisFileDirectory)System\CharEnumerator.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\CLSCompliantAttribute.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\DictionaryEntry.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\Dictionary.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\ICollection.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\ICollectionDebugView.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\IComparer.cs" /> @@ -67,7 +68,9 @@ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\IReadOnlyList.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\KeyNotFoundException.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\KeyValuePair.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\NonRandomizedStringEqualityComparer.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\List.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)System\Collections\HashHelpers.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\ICollection.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\IComparer.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Collections\IDictionary.cs" /> diff --git a/src/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs index bf5e4df08..5b576973a 100644 --- a/src/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs @@ -1,8 +1,7 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Internal.Runtime.CompilerServices; using System; using System.Collections; using System.Diagnostics; @@ -50,7 +49,6 @@ namespace System.Collections.Generic private Entry[] entries; private int count; private int version; - private int freeList; private int freeCount; private IEqualityComparer<TKey> comparer; @@ -60,7 +58,7 @@ namespace System.Collections.Generic // constants for serialization private const string VersionName = "Version"; // Do not rename (binary serialization) - private const string HashSizeName = "HashSize"; // Do not rename (binary serialization). Must save buckets.Length + private const string HashSizeName = "HashSize"; // Do not rename (binary serialization). Must save buckets.Length private const string KeyValuePairsName = "KeyValuePairs"; // Do not rename (binary serialization) private const string ComparerName = "Comparer"; // Do not rename (binary serialization) @@ -72,7 +70,7 @@ namespace System.Collections.Generic public Dictionary(int capacity, IEqualityComparer<TKey> comparer) { - if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), capacity, SR.ArgumentOutOfRange_NeedNonNegNum); + if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); if (capacity > 0) Initialize(capacity); this.comparer = comparer ?? EqualityComparer<TKey>.Default; @@ -89,7 +87,7 @@ namespace System.Collections.Generic { if (dictionary == null) { - throw new ArgumentNullException(nameof(dictionary)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); } // It is likely that the passed-in dictionary is Dictionary<TKey,TValue>. When this is the case, @@ -124,7 +122,7 @@ namespace System.Collections.Generic { if (collection == null) { - throw new ArgumentNullException(nameof(collection)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); } foreach (KeyValuePair<TKey, TValue> pair in collection) @@ -138,7 +136,7 @@ namespace System.Collections.Generic // We can't do anything with the keys and values until the entire graph has been deserialized // and we have a resonable estimate that GetHashCode is not going to fail. For the time being, // we'll just cache this. The graph is not valid until OnDeserialization has been called. - DictionaryHashHelpers.SerializationInfoTable.Add(this, info); + HashHelpers.SerializationInfoTable.Add(this, info); } public IEqualityComparer<TKey> Comparer @@ -214,7 +212,8 @@ namespace System.Collections.Generic { int i = FindEntry(key); if (i >= 0) return entries[i].value; - throw new KeyNotFoundException(); + ThrowHelper.ThrowKeyNotFoundException(); + return default(TValue); } set { @@ -297,17 +296,17 @@ namespace System.Collections.Generic { if (array == null) { - throw new ArgumentNullException(nameof(array)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (index < 0 || index > array.Length) { - throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { - throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } int count = this.count; @@ -335,7 +334,7 @@ namespace System.Collections.Generic { if (info == null) { - throw new ArgumentNullException(nameof(info)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info); } info.AddValue(VersionName, version); @@ -354,7 +353,7 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if (buckets != null) @@ -381,7 +380,7 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if (buckets == null) Initialize(0); @@ -402,7 +401,7 @@ namespace System.Collections.Generic if (behavior == InsertionBehavior.ThrowOnExisting) { - throw new ArgumentException(SR.Format(SR.Argument_AddingDuplicate, key)); + ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key); } return false; @@ -411,7 +410,6 @@ namespace System.Collections.Generic } int index; - if (freeCount > 0) { index = freeList; @@ -436,6 +434,9 @@ namespace System.Collections.Generic buckets[targetBucket] = index; version++; + // If we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing + // i.e. EqualityComparer<string>.Default. + if (collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) { comparer = (IEqualityComparer<TKey>)EqualityComparer<string>.Default; @@ -448,7 +449,8 @@ namespace System.Collections.Generic public virtual void OnDeserialization(object sender) { SerializationInfo siInfo; - DictionaryHashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo); + HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo); + if (siInfo == null) { // We can return immediately if this function is called twice. @@ -467,19 +469,19 @@ namespace System.Collections.Generic entries = new Entry[hashsize]; freeList = -1; - KeyValuePair<TKey, TValue>[] array = - (KeyValuePair<TKey, TValue>[])siInfo.GetValue(KeyValuePairsName, typeof(KeyValuePair<TKey, TValue>[])); + KeyValuePair<TKey, TValue>[] array = (KeyValuePair<TKey, TValue>[]) + siInfo.GetValue(KeyValuePairsName, typeof(KeyValuePair<TKey, TValue>[])); if (array == null) { - throw new SerializationException(SR.Serialization_MissingKeys); + ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingKeys); } for (int i = 0; i < array.Length; i++) { if (array[i].Key == null) { - throw new SerializationException(SR.Serialization_NullKey); + ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_NullKey); } Add(array[i].Key, array[i].Value); } @@ -490,7 +492,7 @@ namespace System.Collections.Generic } version = realVersion; - DictionaryHashHelpers.SerializationInfoTable.Remove(this); + HashHelpers.SerializationInfoTable.Remove(this); } private void Resize() @@ -503,7 +505,6 @@ namespace System.Collections.Generic Debug.Assert(newSize >= entries.Length); int[] newBuckets = new int[newSize]; for (int i = 0; i < newBuckets.Length; i++) newBuckets[i] = -1; - Entry[] newEntries = new Entry[newSize]; Array.Copy(entries, 0, newEntries, 0, count); @@ -539,7 +540,7 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if (buckets != null) @@ -547,27 +548,40 @@ namespace System.Collections.Generic int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; int bucket = hashCode % buckets.Length; int last = -1; - for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next) + int i = buckets[bucket]; + while (i >= 0) { - if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) + ref Entry entry = ref entries[i]; + + if (entry.hashCode == hashCode && comparer.Equals(entry.key, key)) { if (last < 0) { - buckets[bucket] = entries[i].next; + buckets[bucket] = entry.next; } else { - entries[last].next = entries[i].next; + entries[last].next = entry.next; + } + entry.hashCode = -1; + entry.next = freeList; + + if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>()) + { + entry.key = default(TKey); + } + if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>()) + { + entry.value = default(TValue); } - entries[i].hashCode = -1; - entries[i].next = freeList; - entries[i].key = default(TKey); - entries[i].value = default(TValue); freeList = i; freeCount++; version++; return true; } + + last = i; + i = entry.next; } } return false; @@ -580,7 +594,7 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if (buckets != null) @@ -588,30 +602,43 @@ namespace System.Collections.Generic int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; int bucket = hashCode % buckets.Length; int last = -1; - for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next) + int i = buckets[bucket]; + while (i >= 0) { - if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) + ref Entry entry = ref entries[i]; + + if (entry.hashCode == hashCode && comparer.Equals(entry.key, key)) { if (last < 0) { - buckets[bucket] = entries[i].next; + buckets[bucket] = entry.next; } else { - entries[last].next = entries[i].next; + entries[last].next = entry.next; } - value = entries[i].value; + value = entry.value; - entries[i].hashCode = -1; - entries[i].next = freeList; - entries[i].key = default(TKey); - entries[i].value = default(TValue); + entry.hashCode = -1; + entry.next = freeList; + + if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>()) + { + entry.key = default(TKey); + } + if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>()) + { + entry.value = default(TValue); + } freeList = i; freeCount++; version++; return true; } + + last = i; + i = entry.next; } } value = default(TValue); @@ -646,27 +673,27 @@ namespace System.Collections.Generic { if (array == null) { - throw new ArgumentNullException(nameof(array)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (array.Rank != 1) { - throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array)); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); } if (array.GetLowerBound(0) != 0) { - throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array)); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); } if (index < 0 || index > array.Length) { - throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { - throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[]; @@ -678,7 +705,6 @@ namespace System.Collections.Generic { DictionaryEntry[] dictEntryArray = array as DictionaryEntry[]; Entry[] entries = this.entries; - for (int i = 0; i < count; i++) { if (entries[i].hashCode >= 0) @@ -692,7 +718,7 @@ namespace System.Collections.Generic object[] objects = array as object[]; if (objects == null) { - throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } try @@ -709,7 +735,7 @@ namespace System.Collections.Generic } catch (ArrayTypeMismatchException) { - throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -730,7 +756,7 @@ namespace System.Collections.Generic { if (_syncRoot == null) { - System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null); + System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null); } return _syncRoot; } @@ -774,10 +800,9 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - if (value == null && !(default(TValue) == null)) - throw new ArgumentNullException(nameof(value)); + ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value); try { @@ -788,12 +813,12 @@ namespace System.Collections.Generic } catch (InvalidCastException) { - throw new ArgumentException(SR.Format(SR.Arg_WrongType, value, typeof(TValue)), nameof(value)); + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue)); } } catch (InvalidCastException) { - throw new ArgumentException(SR.Format(SR.Arg_WrongType, key, typeof(TKey)), nameof(key)); + ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey)); } } } @@ -802,7 +827,7 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } return (key is TKey); } @@ -811,11 +836,9 @@ namespace System.Collections.Generic { if (key == null) { - throw new ArgumentNullException(nameof(key)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - - if (value == null && !(default(TValue) == null)) - throw new ArgumentNullException(nameof(value)); + ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value); try { @@ -827,12 +850,12 @@ namespace System.Collections.Generic } catch (InvalidCastException) { - throw new ArgumentException(SR.Format(SR.Arg_WrongType, value, typeof(TValue)), nameof(value)); + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue)); } } catch (InvalidCastException) { - throw new ArgumentException(SR.Format(SR.Arg_WrongType, key, typeof(TKey)), nameof(key)); + ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey)); } } @@ -884,20 +907,20 @@ namespace System.Collections.Generic { if (version != dictionary.version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue while ((uint)index < (uint)dictionary.count) { - if (dictionary.entries[index].hashCode >= 0) + ref Entry entry = ref dictionary.entries[index++]; + + if (entry.hashCode >= 0) { - current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value); - index++; + current = new KeyValuePair<TKey, TValue>(entry.key, entry.value); return true; } - index++; } index = dictionary.count + 1; @@ -920,7 +943,7 @@ namespace System.Collections.Generic { if (index == 0 || (index == dictionary.count + 1)) { - throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } if (getEnumeratorRetType == DictEntry) @@ -938,7 +961,7 @@ namespace System.Collections.Generic { if (version != dictionary.version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; @@ -951,7 +974,7 @@ namespace System.Collections.Generic { if (index == 0 || (index == dictionary.count + 1)) { - throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return new DictionaryEntry(current.Key, current.Value); @@ -964,7 +987,7 @@ namespace System.Collections.Generic { if (index == 0 || (index == dictionary.count + 1)) { - throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return current.Key; @@ -977,7 +1000,7 @@ namespace System.Collections.Generic { if (index == 0 || (index == dictionary.count + 1)) { - throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return current.Value; @@ -995,7 +1018,7 @@ namespace System.Collections.Generic { if (dictionary == null) { - throw new ArgumentNullException(nameof(dictionary)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); } this.dictionary = dictionary; } @@ -1009,22 +1032,21 @@ namespace System.Collections.Generic { if (array == null) { - throw new ArgumentNullException(nameof(array)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (index < 0 || index > array.Length) { - throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) { - throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } int count = dictionary.count; Entry[] entries = dictionary.entries; - for (int i = 0; i < count; i++) { if (entries[i].hashCode >= 0) array[index++] = entries[i].key; @@ -1043,12 +1065,12 @@ namespace System.Collections.Generic void ICollection<TKey>.Add(TKey item) { - throw new NotSupportedException(SR.NotSupported_KeyCollectionSet); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); } void ICollection<TKey>.Clear() { - throw new NotSupportedException(SR.NotSupported_KeyCollectionSet); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); } bool ICollection<TKey>.Contains(TKey item) @@ -1058,7 +1080,8 @@ namespace System.Collections.Generic bool ICollection<TKey>.Remove(TKey item) { - throw new NotSupportedException(SR.NotSupported_KeyCollectionSet); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet); + return false; } IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator() @@ -1075,27 +1098,27 @@ namespace System.Collections.Generic { if (array == null) { - throw new ArgumentNullException(nameof(array)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (array.Rank != 1) { - throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array)); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); } if (array.GetLowerBound(0) != 0) { - throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array)); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); } if (index < 0 || index > array.Length) { - throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) { - throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } TKey[] keys = array as TKey[]; @@ -1108,12 +1131,11 @@ namespace System.Collections.Generic object[] objects = array as object[]; if (objects == null) { - throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = dictionary.count; Entry[] entries = dictionary.entries; - try { for (int i = 0; i < count; i++) @@ -1123,7 +1145,7 @@ namespace System.Collections.Generic } catch (ArrayTypeMismatchException) { - throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -1161,18 +1183,18 @@ namespace System.Collections.Generic { if (version != dictionary.version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } while ((uint)index < (uint)dictionary.count) { - if (dictionary.entries[index].hashCode >= 0) + ref Entry entry = ref dictionary.entries[index++]; + + if (entry.hashCode >= 0) { - currentKey = dictionary.entries[index].key; - index++; + currentKey = entry.key; return true; } - index++; } index = dictionary.count + 1; @@ -1194,7 +1216,7 @@ namespace System.Collections.Generic { if (index == 0 || (index == dictionary.count + 1)) { - throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return currentKey; @@ -1205,7 +1227,7 @@ namespace System.Collections.Generic { if (version != dictionary.version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; @@ -1224,7 +1246,7 @@ namespace System.Collections.Generic { if (dictionary == null) { - throw new ArgumentNullException(nameof(dictionary)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); } this.dictionary = dictionary; } @@ -1238,22 +1260,21 @@ namespace System.Collections.Generic { if (array == null) { - throw new ArgumentNullException(nameof(array)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (index < 0 || index > array.Length) { - throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) { - throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } int count = dictionary.count; Entry[] entries = dictionary.entries; - for (int i = 0; i < count; i++) { if (entries[i].hashCode >= 0) array[index++] = entries[i].value; @@ -1272,17 +1293,18 @@ namespace System.Collections.Generic void ICollection<TValue>.Add(TValue item) { - throw new NotSupportedException(SR.NotSupported_ValueCollectionSet); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); } bool ICollection<TValue>.Remove(TValue item) { - throw new NotSupportedException(SR.NotSupported_ValueCollectionSet); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); + return false; } void ICollection<TValue>.Clear() { - throw new NotSupportedException(SR.NotSupported_ValueCollectionSet); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet); } bool ICollection<TValue>.Contains(TValue item) @@ -1304,26 +1326,26 @@ namespace System.Collections.Generic { if (array == null) { - throw new ArgumentNullException(nameof(array)); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (array.Rank != 1) { - throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array)); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); } if (array.GetLowerBound(0) != 0) { - throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array)); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); } if (index < 0 || index > array.Length) { - throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) - throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); TValue[] values = array as TValue[]; if (values != null) @@ -1335,12 +1357,11 @@ namespace System.Collections.Generic object[] objects = array as object[]; if (objects == null) { - throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = dictionary.count; Entry[] entries = dictionary.entries; - try { for (int i = 0; i < count; i++) @@ -1350,7 +1371,7 @@ namespace System.Collections.Generic } catch (ArrayTypeMismatchException) { - throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array)); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -1388,18 +1409,18 @@ namespace System.Collections.Generic { if (version != dictionary.version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } while ((uint)index < (uint)dictionary.count) { - if (dictionary.entries[index].hashCode >= 0) + ref Entry entry = ref dictionary.entries[index++]; + + if (entry.hashCode >= 0) { - currentValue = dictionary.entries[index].value; - index++; + currentValue = entry.value; return true; } - index++; } index = dictionary.count + 1; currentValue = default(TValue); @@ -1420,7 +1441,7 @@ namespace System.Collections.Generic { if (index == 0 || (index == dictionary.count + 1)) { - throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return currentValue; @@ -1431,7 +1452,7 @@ namespace System.Collections.Generic { if (version != dictionary.version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; currentValue = default(TValue); @@ -1439,9 +1460,4 @@ namespace System.Collections.Generic } } } - - internal class DictionaryHashHelpers - { - internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable { get; } = new ConditionalWeakTable<object, SerializationInfo>(); - } } diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs new file mode 100644 index 000000000..ef44fefc8 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.Serialization; + +namespace System.Collections.Generic +{ + // NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary<string,...> + // We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which + // keeps the performance not affected till we hit collision threshold and then we switch to the comparer which is using + // randomized string hashing. + [Serializable] // Required for compatibility with .NET Core 2.0 as we exposed the NonRandomizedStringEqualityComparer inside the serialization blob +#if CORECLR + internal +#else + public +#endif + sealed class NonRandomizedStringEqualityComparer : EqualityComparer<string>, ISerializable + { + internal static new IEqualityComparer<string> Default { get; } = new NonRandomizedStringEqualityComparer(); + + private NonRandomizedStringEqualityComparer() { } + + // This is used by the serialization engine. + private NonRandomizedStringEqualityComparer(SerializationInfo information, StreamingContext context) { } + + public sealed override bool Equals(string x, string y) => string.Equals(x, y); + + public sealed override int GetHashCode(string obj) => obj?.GetLegacyNonRandomizedHashCode() ?? 0; + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + // We are doing this to stay compatible with .NET Framework. + info.SetType(typeof(GenericEqualityComparer<string>)); + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs new file mode 100644 index 000000000..49cff85b5 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Threading; + +namespace System.Collections +{ + internal static class HashHelpers + { + public const int HashCollisionThreshold = 100; + + public const int HashPrime = 101; + + // Table of prime numbers to use as hash table sizes. + // A typical resize algorithm would pick the smallest prime number in this array + // that is larger than twice the previous capacity. + // Suppose our Hashtable currently has capacity x and enough elements are added + // such that a resize needs to occur. Resizing first computes 2x then finds the + // first prime in the table greater than 2x, i.e. if primes are ordered + // p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n. + // Doubling is important for preserving the asymptotic complexity of the + // hashtable operations such as add. Having a prime guarantees that double + // hashing does not lead to infinite loops. IE, your hash function will be + // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime. + public static readonly int[] primes = { + 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, + 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, + 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, + 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, + 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369}; + + public static bool IsPrime(int candidate) + { + if ((candidate & 1) != 0) + { + int limit = (int)Math.Sqrt(candidate); + for (int divisor = 3; divisor <= limit; divisor += 2) + { + if ((candidate % divisor) == 0) + return false; + } + return true; + } + return (candidate == 2); + } + + public static int GetPrime(int min) + { + if (min < 0) + throw new ArgumentException(SR.Arg_HTCapacityOverflow); + + for (int i = 0; i < primes.Length; i++) + { + int prime = primes[i]; + if (prime >= min) return prime; + } + + //outside of our predefined table. + //compute the hard way. + for (int i = (min | 1); i < Int32.MaxValue; i += 2) + { + if (IsPrime(i) && ((i - 1) % HashPrime != 0)) + return i; + } + return min; + } + + // Returns size of hashtable to grow to. + public static int ExpandPrime(int oldSize) + { + int newSize = 2 * oldSize; + + // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize) + { + Debug.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength"); + return MaxPrimeArrayLength; + } + + return GetPrime(newSize); + } + + + // This is the maximum prime smaller than Array.MaxArrayLength + public const int MaxPrimeArrayLength = 0x7FEFFFFD; + + + // Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo + // object until OnDeserialization is called. + private static ConditionalWeakTable<object, SerializationInfo> s_serializationInfoTable; + + internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable + { + get + { + if (s_serializationInfoTable == null) + Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null); + + return s_serializationInfoTable; + } + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs index 071911813..fa3e7c06c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs @@ -35,7 +35,7 @@ namespace System.Runtime.CompilerServices /// <summary>Provides an awaiter for a <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary> [StructLayout(LayoutKind.Auto)] - public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion + public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, IConfiguredValueTaskAwaiter { /// <summary>The value being awaited.</summary> private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies @@ -71,6 +71,18 @@ namespace System.Runtime.CompilerServices /// <summary>Gets the task underlying <see cref="_value"/>.</summary> internal Task<TResult> AsTask() => _value.AsTask(); + + /// <summary>Gets the task underlying the incomplete <see cref="_value"/>.</summary> + /// <remarks>This method is used when awaiting and IsCompleted returned false; thus we expect the value task to be wrapping a non-null task.</remarks> + (Task, bool) IConfiguredValueTaskAwaiter.GetTask() => (_value.AsTaskExpectNonNull(), _continueOnCapturedContext); } } + + /// <summary> + /// Internal interface used to enable extract the Task from arbitrary configured ValueTask awaiters. + /// </summary> + internal interface IConfiguredValueTaskAwaiter + { + (Task task, bool continueOnCapturedContext) GetTask(); + } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs index 203039a4a..0b0ed8595 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace System.Runtime.CompilerServices { /// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary> - public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion + public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion, IValueTaskAwaiter { /// <summary>The value being awaited.</summary> private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies @@ -38,5 +38,17 @@ namespace System.Runtime.CompilerServices /// <summary>Gets the task underlying <see cref="_value"/>.</summary> internal Task<TResult> AsTask() => _value.AsTask(); + + /// <summary>Gets the task underlying the incomplete <see cref="_value"/>.</summary> + /// <remarks>This method is used when awaiting and IsCompleted returned false; thus we expect the value task to be wrapping a non-null task.</remarks> + Task IValueTaskAwaiter.GetTask() => _value.AsTaskExpectNonNull(); + } + + /// <summary> + /// Internal interface used to enable extract the Task from arbitrary ValueTask awaiters. + /// </summary>> + internal interface IValueTaskAwaiter + { + Task GetTask(); } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs index 384e4a8ab..4ccf0f8a4 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs @@ -116,6 +116,15 @@ namespace System.Threading.Tasks // and the hash code we generate in GetHashCode. _task ?? AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result); + internal Task<TResult> AsTaskExpectNonNull() => + // Return the task if we were constructed from one, otherwise manufacture one. + // Unlike AsTask(), this method is called only when we expect _task to be non-null, + // and thus we don't want GetTaskForResult inlined. + _task ?? GetTaskForResultNoInlining(); + + [MethodImpl(MethodImplOptions.NoInlining)] + private Task<TResult> GetTaskForResultNoInlining() => AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result); + /// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a completed operation.</summary> public bool IsCompleted => _task == null || _task.IsCompleted; diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 941ff5475..3c4f91f71 100644 --- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -195,8 +195,6 @@ <Compile Include="System\Collections\Generic\CompatibilityEqualityComparers.cs" /> <Compile Include="System\Collections\Generic\EqualityComparer.cs" /> <Compile Include="System\Collections\Generic\EqualOnlyComparer.cs" /> - <Compile Include="System\Collections\Generic\Dictionary.cs" /> - <Compile Include="System\Collections\Generic\NonRandomizedStringEqualityComparer.cs" /> <Compile Include="System\Collections\LowLevelComparer.cs" /> <Compile Include="System\CurrentSystemTimeZone.Cache.cs" /> <Compile Include="System\Decimal.DecCalc.cs" /> @@ -709,9 +707,6 @@ <Compile Include="..\..\Common\src\System\Collections\Generic\LowLevelDictionary.cs"> <Link>System\Collections\Generic\LowLevelDictionary.cs</Link> </Compile> - <Compile Include="..\..\Common\src\System\Collections\HashHelpers.cs"> - <Link>System\Collections\HashHelpers.cs</Link> - </Compile> <Compile Include="..\..\Common\src\System\Collections\Concurrent\ConcurrentUnifier.cs"> <Link>System\Collections\Concurrent\ConcurrentUnifier.cs</Link> </Compile> diff --git a/src/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs b/src/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs deleted file mode 100644 index a1f3e38bd..000000000 --- a/src/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Collections.Generic -{ - // NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary<string,...> - // As the randomized string hashing is now turned on with no opt-out, we need to keep the performance not affected - // as much as possible in the main stream scenarios like Dictionary<string,> - // We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which - // keep the performance not affected till we hit collision threshold and then we switch to the comparer which is using - // randomized string hashing. - [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public sealed class NonRandomizedStringEqualityComparer : EqualityComparer<string> - { - private static volatile IEqualityComparer<string> s_nonRandomizedComparer; - - internal static new IEqualityComparer<string> Default => s_nonRandomizedComparer ?? (s_nonRandomizedComparer = new NonRandomizedStringEqualityComparer()); - - public sealed override bool Equals(string x, string y) => string.Equals(x, y); - - public sealed override int GetHashCode(string obj) - { - if (obj == null) - return 0; - return obj.GetLegacyNonRandomizedHashCode(); - } - } -} diff --git a/src/System.Private.CoreLib/src/System/Decimal.cs b/src/System.Private.CoreLib/src/System/Decimal.cs index 9ee8069f3..ad5709161 100644 --- a/src/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/System.Private.CoreLib/src/System/Decimal.cs @@ -556,6 +556,11 @@ namespace System return Number.TryParseDecimal(s.AsReadOnlySpan(), NumberStyles.Number, null, out result); } + public static bool TryParse(ReadOnlySpan<char> s, out decimal result) + { + return Number.TryParseDecimal(s, NumberStyles.Number, null, out result); + } + public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Decimal result) { ValidateParseStyleFloatingPoint(style); @@ -567,7 +572,7 @@ namespace System return Number.TryParseDecimal(s.AsReadOnlySpan(), style, provider, out result); } - public static Boolean TryParse(ReadOnlySpan<char> s, out Decimal result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null) + public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider, out decimal result) { ValidateParseStyleFloatingPoint(style); return Number.TryParseDecimal(s, style, provider, out result); diff --git a/src/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/System.Private.CoreLib/src/System/ThrowHelper.cs index 4ca4103dc..01a31fae6 100644 --- a/src/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -35,8 +35,10 @@ // multiple times for different instantiation. // +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.Serialization; namespace System { @@ -102,6 +104,38 @@ namespace System ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } + private static ArgumentException GetWrongKeyTypeArgumentException(object key, Type targetType) + { + return new ArgumentException(SR.Format(SR.Arg_WrongType, key, targetType), nameof(key)); + } + internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) + { + throw GetWrongKeyTypeArgumentException(key, targetType); + } + + private static ArgumentException GetWrongValueTypeArgumentException(object value, Type targetType) + { + return new ArgumentException(SR.Format(SR.Arg_WrongType, value, targetType), nameof(value)); + } + internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) + { + throw GetWrongValueTypeArgumentException(value, targetType); + } + + private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object key) + { + return new ArgumentException(SR.Format(SR.Argument_AddingDuplicate, key)); + } + internal static void ThrowAddingDuplicateWithKeyArgumentException(object key) + { + throw GetAddingDuplicateWithKeyArgumentException(key); + } + + internal static void ThrowKeyNotFoundException() + { + throw new KeyNotFoundException(); + } + internal static void ThrowArgumentException(ExceptionResource resource) { throw new ArgumentException(GetResourceString(resource)); @@ -121,15 +155,6 @@ namespace System throw new ArgumentException(GetResourceString(ExceptionResource.Argument_InvalidArrayType)); } - private static ArgumentException GetWrongValueTypeArgumentException(object value, Type targetType) - { - return new ArgumentException(SR.Format(SR.Arg_WrongType, value, targetType), nameof(value)); - } - internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) - { - throw GetWrongValueTypeArgumentException(value, targetType); - } - internal static void ThrowArgumentNullException(ExceptionArgument argument) { throw new ArgumentNullException(GetArgumentName(argument)); @@ -155,6 +180,10 @@ namespace System throw new InvalidOperationException(GetResourceString(ExceptionResource.InvalidOperation_EnumOpCantHappen)); } + internal static void ThrowSerializationException(ExceptionResource resource) + { + throw new SerializationException(GetResourceString(resource)); + } internal static void ThrowNotSupportedException(ExceptionResource resource) { @@ -176,14 +205,20 @@ namespace System { switch (argument) { + case ExceptionArgument.obj: + return "obj"; + case ExceptionArgument.dictionary: + return "dictionary"; case ExceptionArgument.array: return "array"; + case ExceptionArgument.info: + return "info"; + case ExceptionArgument.key: + return "key"; case ExceptionArgument.text: return "text"; case ExceptionArgument.values: return "values"; - case ExceptionArgument.obj: - return "obj"; case ExceptionArgument.value: return "value"; case ExceptionArgument.startIndex: @@ -218,6 +253,8 @@ namespace System return "comparison"; case ExceptionArgument.pointer: return "pointer"; + case ExceptionArgument.start: + return "start"; default: Debug.Assert(false, "The enum value is not defined, please check the ExceptionArgument Enum."); @@ -261,6 +298,14 @@ namespace System return SR.InvalidOperation_EnumFailedVersion; case ExceptionResource.InvalidOperation_EnumOpCantHappen: return SR.InvalidOperation_EnumOpCantHappen; + case ExceptionResource.Serialization_MissingKeys: + return SR.Serialization_MissingKeys; + case ExceptionResource.Serialization_NullKey: + return SR.Serialization_NullKey; + case ExceptionResource.NotSupported_KeyCollectionSet: + return SR.NotSupported_KeyCollectionSet; + case ExceptionResource.NotSupported_ValueCollectionSet: + return SR.NotSupported_ValueCollectionSet; default: Debug.Assert(false, "The enum value is not defined, please check the ExceptionResource Enum."); @@ -274,10 +319,13 @@ namespace System // internal enum ExceptionArgument { + obj, + dictionary, array, + info, + key, text, values, - obj, value, startIndex, task, @@ -295,6 +343,7 @@ namespace System action, comparison, pointer, + start } // @@ -318,5 +367,9 @@ namespace System ArgumentOutOfRange_BiggerThanCollection, InvalidOperation_EnumFailedVersion, InvalidOperation_EnumOpCantHappen, + Serialization_MissingKeys, + Serialization_NullKey, + NotSupported_KeyCollectionSet, + NotSupported_ValueCollectionSet, } } diff --git a/src/System.Private.Interop/src/Interop/Interop.WinRT.Basic.cs b/src/System.Private.Interop/src/Interop/Interop.WinRT.Basic.cs index b265e8c16..8989c2f72 100644 --- a/src/System.Private.Interop/src/Interop/Interop.WinRT.Basic.cs +++ b/src/System.Private.Interop/src/Interop/Interop.WinRT.Basic.cs @@ -67,6 +67,7 @@ namespace System.Runtime.InteropServices public static partial class ExternalInterop { +#if ENABLE_MIN_WINRT [DllImport(Libraries.CORE_WINRT)] [McgGeneratedNativeCallCodeAttribute] [MethodImplAttribute(MethodImplOptions.NoInlining)] @@ -80,6 +81,7 @@ namespace System.Runtime.InteropServices uint length, HSTRING_HEADER* phstringHeader, void* hstring); +#endif [DllImport(Libraries.CORE_COM)] [McgGeneratedNativeCallCodeAttribute] @@ -157,6 +159,7 @@ namespace System.Runtime.InteropServices } } +#if ENABLE_MIN_WINRT internal static unsafe void RoGetActivationFactory(string className, ref Guid iid, out IntPtr ppv) { fixed (char* unsafe_className = className) @@ -186,6 +189,7 @@ namespace System.Runtime.InteropServices } } } +#endif public static unsafe int CoGetContextToken(out IntPtr ppToken) { diff --git a/src/System.Private.Interop/src/System.Private.Interop.csproj b/src/System.Private.Interop/src/System.Private.Interop.csproj index 34b57e303..a16d0f8ec 100644 --- a/src/System.Private.Interop/src/System.Private.Interop.csproj +++ b/src/System.Private.Interop/src/System.Private.Interop.csproj @@ -189,11 +189,11 @@ <Compile Include="Windows\Foundation\Size.cs" /> <Compile Include="Windows\Foundation\TokenizerHelper.cs" /> <Compile Include="Windows\Foundation\IReference.cs" /> + <Compile Include="Interop\Interop.WinRT.cs" /> </ItemGroup> <ItemGroup Condition="'$(TargetsWindows)' == 'true'"> <Compile Include="Interop\Interop.Sync.Windows.cs" /> - <Compile Include="Interop\Interop.WinRT.cs" /> <Compile Include="Interop\Interop.WinRT.Basic.cs" /> <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.MemAllocFree.cs"> diff --git a/tests/src/Simple/HelloWasm/Program.cs b/tests/src/Simple/HelloWasm/Program.cs index 453a8555e..6d4a5a6e7 100644 --- a/tests/src/Simple/HelloWasm/Program.cs +++ b/tests/src/Simple/HelloWasm/Program.cs @@ -11,10 +11,12 @@ internal static class Program private static unsafe void Main(string[] args) { Add(1, 2); - + var tempObj = new TestClass(1337); int tempInt = 0; (*(&tempInt)) = 9; + tempObj.TestMethod("Hello"); + if(tempInt == 9) { PrintLine("Hello from C#!"); @@ -22,6 +24,8 @@ internal static class Program TwoByteStr str = new TwoByteStr() { first = 1, second = 2 }; TwoByteStr str2 = new TwoByteStr() { first = 3, second = 4 }; + *(&str) = str2; + str2 = *(&str); if (str2.second == 4) { @@ -34,6 +38,12 @@ internal static class Program PrintLine("static int field test: Ok."); } + var boxedInt = (object)tempInt; + if(((int)boxedInt) == 9) + { + PrintLine("box test: Ok."); + } + var not = Not(0xFFFFFFFF) == 0x00000000; if (not) { @@ -57,6 +67,7 @@ internal static class Program { PrintLine("shiftRight test: Ok."); } + var unsignedShift = UnsignedShift(0xFFFFFFFFu, 4) == 0x0FFFFFFFu; if (unsignedShift) { @@ -159,3 +170,21 @@ public struct TwoByteStr public byte second; } +public class TestClass +{ + public string TestString {get; set;} + + public TestClass(int number) + { + if(number != 1337) + throw new Exception(); + } + + public void TestMethod(string str) + { + TestString = str; + if(TestString != str) + throw new Exception(); + } +} + |