This commit is contained in:
dotnet-bot 2015-02-12 14:54:02 -08:00 коммит произвёл Michelle McDaniel
Коммит 63dbfe850d
62 изменённых файлов: 34559 добавлений и 0 удалений

63
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

159
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,159 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac desktop service store files
.DS_Store
/src/3fjtrdxe.dt5
/src/j1xrvkr3.mrf
TAGS

367
CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,367 @@
# If we are not building as a part of LLVM, build MSILCJit as an
# standalone project, using LLVM as an external library:
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
project(MSILCJit)
cmake_minimum_required(VERSION 2.8)
set(MSILCJIT_PATH_TO_LLVM_SOURCE "" CACHE PATH
"Path to LLVM source code. Not necessary if using an installed LLVM.")
set(MSILCJIT_PATH_TO_LLVM_BUILD "" CACHE PATH
"Path to the directory where LLVM was built or installed.")
if( MSILCJIT_PATH_TO_LLVM_SOURCE )
if( NOT EXISTS "${MSILCJIT_PATH_TO_LLVM_SOURCE}/cmake/config-ix.cmake" )
message(FATAL_ERROR "Please set MSILCJIT_PATH_TO_LLVM_SOURCE to the root directory of LLVM source code.")
else()
get_filename_component(LLVM_MAIN_SRC_DIR ${MSILCJIT_PATH_TO_LLVM_SOURCE}
ABSOLUTE)
list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
endif()
endif()
if (EXISTS "${MSILCJIT_PATH_TO_LLVM_BUILD}/bin/llvm-config${CMAKE_EXECUTABLE_SUFFIX}")
set (PATH_TO_LLVM_CONFIG "${MSILCJIT_PATH_TO_LLVM_BUILD}/bin/llvm-config${CMAKE_EXECUTABLE_SUFFIX}")
elseif (EXISTS "${MSILCJIT_PATH_TO_LLVM_BUILD}/bin/Debug/llvm-config${CMAKE_EXECUTABLE_SUFFIX}")
# Looking for bin/Debug/llvm-config seems suboptimal. How can we get
# around this?
set (PATH_TO_LLVM_CONFIG "${MSILCJIT_PATH_TO_LLVM_BUILD}/bin/Debug/llvm-config${CMAKE_EXECUTABLE_SUFFIX}")
else()
message(FATAL_ERROR "Please set MSILCJIT_PATH_TO_LLVM_BUILD to a directory containing a LLVM build.")
endif()
list(APPEND CMAKE_MODULE_PATH "${MSILCJIT_PATH_TO_LLVM_BUILD}/share/llvm/cmake")
get_filename_component(PATH_TO_LLVM_BUILD ${MSILCJIT_PATH_TO_LLVM_BUILD}
ABSOLUTE)
option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF)
include(AddLLVM)
include(TableGen)
include("${MSILCJIT_PATH_TO_LLVM_BUILD}/share/llvm/cmake/LLVMConfig.cmake")
include(HandleLLVMOptions)
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
set(LLVM_MAIN_INCLUDE_DIR "${LLVM_MAIN_SRC_DIR}/include")
set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories("${PATH_TO_LLVM_BUILD}/include" "${LLVM_MAIN_INCLUDE_DIR}")
link_directories("${PATH_TO_LLVM_BUILD}/lib")
exec_program("${PATH_TO_LLVM_CONFIG} --bindir" OUTPUT_VARIABLE LLVM_BINARY_DIR)
set(LLVM_TABLEGEN_EXE "${LLVM_BINARY_DIR}/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}")
# Define the default arguments to use with 'lit', and an option for the user
# to override.
set(LIT_ARGS_DEFAULT "-sv")
if (MSVC OR XCODE)
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( MSILCJIT_BUILT_STANDALONE 1 )
find_package(LibXml2)
if (LIBXML2_FOUND)
set(MSILCJIT_HAVE_LIBXML 1)
endif ()
endif()
set(MSILCJIT_RESOURCE_DIR "" CACHE STRING
"Relative directory from the MSILCJit binary to its resource files.")
set(C_INCLUDE_DIRS "" CACHE STRING
"Colon separated list of directories MSILCJit will search for headers.")
set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." )
set(DEFAULT_SYSROOT "" CACHE PATH
"Default <path> to all compiler invocations for --sysroot=<path>." )
set(MSILCJIT_VENDOR "" CACHE STRING
"Vendor-specific text for showing with version information.")
if( MSILCJIT_VENDOR )
add_definitions( -DMSILCJIT_VENDOR="${MSILCJIT_VENDOR} " )
endif()
set(MSILCJIT_REPOSITORY_STRING "" CACHE STRING
"Vendor-specific text for showing the repository the source is taken from.")
if(MSILCJIT_REPOSITORY_STRING)
add_definitions(-DMSILCJIT_REPOSITORY_STRING="${MSILCJIT_REPOSITORY_STRING}")
endif()
set(MSILCJIT_VENDOR_UTI "org.llvm.msilcjit" CACHE STRING
"Vendor-specific uti.")
set(MSILCJIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(MSILCJIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
"the makefiles distributed with LLVM. Please create a directory and run cmake "
"from there, passing the path to this source directory as the last argument. "
"This process created the file `CMakeCache.txt' and the directory "
"`CMakeFiles'. Please delete them.")
endif()
if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
file(GLOB_RECURSE
tablegenned_files_on_include_dir
"${MSILCJIT_SOURCE_DIR}/include/*.inc")
if( tablegenned_files_on_include_dir )
message(FATAL_ERROR "Apparently there is a previous in-source build, "
"probably as the result of running `configure' and `make' on "
"${MSILCJIT_SOURCE_DIR}. This may cause problems. The suspicious files are:\n"
"${tablegenned_files_on_include_dir}\nPlease clean the source directory.")
endif()
endif()
# Compute the MSILCJit version from the LLVM version.
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" MSILCJIT_VERSION
${PACKAGE_VERSION})
message(STATUS "MSILCJit version: ${MSILCJIT_VERSION}")
string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" MSILCJIT_VERSION_MAJOR
${MSILCJIT_VERSION})
string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" MSILCJIT_VERSION_MINOR
${MSILCJIT_VERSION})
if (${MSILCJIT_VERSION} MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+")
set(MSILCJIT_HAS_VERSION_PATCHLEVEL 1)
string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" MSILCJIT_VERSION_PATCHLEVEL
${MSILCJIT_VERSION})
else()
set(MSILCJIT_HAS_VERSION_PATCHLEVEL 0)
endif()
if (DEBUG)
add_definitions( -DDEBUG -D_DEBUG )
endif()
# Add appropriate flags for GCC
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -fno-rtti")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
endif ()
# Enable -pedantic for MSILCJit even if it's not enabled for LLVM.
if (NOT LLVM_ENABLE_PEDANTIC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wno-long-long")
endif ()
check_cxx_compiler_flag("-Werror -Wnested-anon-types" CXX_SUPPORTS_NO_NESTED_ANON_TYPES_FLAG)
if( CXX_SUPPORTS_NO_NESTED_ANON_TYPES_FLAG )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nested-anon-types" )
endif()
endif ()
if (APPLE)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-flat_namespace -Wl,-undefined -Wl,suppress")
endif ()
include(LLVMParseArguments)
function(msilcjit_tablegen)
# Syntax:
# msilcjit-tablegen output-file [tablegen-arg ...] SOURCE source-file
# [[TARGET cmake-target-name] [DEPENDS extra-dependency ...]]
#
# Generates a custom command for invoking tblgen as
#
# tblgen source-file -o=output-file tablegen-arg ...
#
# and, if cmake-target-name is provided, creates a custom target for
# executing the custom command depending on output-file. It is
# possible to list more files to depend after DEPENDS.
parse_arguments( CTG "SOURCE;TARGET;DEPENDS" "" ${ARGN} )
if( NOT CTG_SOURCE )
message(FATAL_ERROR "SOURCE source-file required by msilcjit_tablegen")
endif()
set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} )
tablegen( MSILCJit ${CTG_DEFAULT_ARGS} )
list( GET CTG_DEFAULT_ARGS 0 output_file )
if( CTG_TARGET )
add_custom_target( ${CTG_TARGET} DEPENDS ${output_file} ${CTG_DEPENDS} )
set_target_properties( ${CTG_TARGET} PROPERTIES FOLDER "MSILCJit tablegenning")
endif()
endfunction(msilcjit_tablegen)
# FIXME: Generalize and move to llvm.
function(add_msilcjit_symbol_exports target_name export_file)
# Makefile.rules contains special cases for different platforms.
# We restrict ourselves to Darwin for the time being.
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_custom_command(OUTPUT symbol.exports
COMMAND sed -e "s/^/_/" < ${export_file} > symbol.exports
DEPENDS ${export_file}
VERBATIM
COMMENT "Creating export file for ${target_name}")
add_custom_target(${target_name}_exports DEPENDS symbol.exports)
set_property(DIRECTORY APPEND
PROPERTY ADDITIONAL_MAKE_CLEAN_FILES symbol.exports)
get_property(srcs TARGET ${target_name} PROPERTY SOURCES)
foreach(src ${srcs})
get_filename_component(extension ${src} EXT)
if(extension STREQUAL ".cpp")
set(first_source_file ${src})
break()
endif()
endforeach()
# Force re-linking when the exports file changes. Actually, it
# forces recompilation of the source file. The LINK_DEPENDS target
# property only works for makefile-based generators.
set_property(SOURCE ${first_source_file} APPEND PROPERTY
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/symbol.exports)
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-exported_symbols_list,${CMAKE_CURRENT_BINARY_DIR}/symbol.exports")
add_dependencies(${target_name} ${target_name}_exports)
endif()
endfunction(add_msilcjit_symbol_exports)
macro(add_msilcjit_library name)
llvm_process_sources(srcs ${ARGN})
if(MSVC_IDE OR XCODE)
# Add public headers
file(RELATIVE_PATH lib_path
${MSILCJIT_SOURCE_DIR}/lib/
${CMAKE_CURRENT_SOURCE_DIR}
)
if(NOT lib_path MATCHES "^[.][.]")
file( GLOB_RECURSE headers
${MSILCJIT_SOURCE_DIR}/include/${lib_path}/*.h
${MSILCJIT_SOURCE_DIR}/include/${lib_path}/*.def
)
set_source_files_properties(${headers} PROPERTIES HEADER_FILE_ONLY ON)
file( GLOB_RECURSE tds
${MSILCJIT_SOURCE_DIR}/include/${lib_path}/*.td
)
source_group("TableGen descriptions" FILES ${tds})
set_source_files_properties(${tds}} PROPERTIES HEADER_FILE_ONLY ON)
set(srcs ${srcs} ${headers} ${tds})
endif()
endif(MSVC_IDE OR XCODE)
if (MODULE)
set(libkind MODULE)
elseif (SHARED_LIBRARY)
set(libkind SHARED)
else()
set(libkind)
endif()
add_library( ${name} ${libkind} ${srcs} )
if( LLVM_COMMON_DEPENDS )
add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
endif( LLVM_COMMON_DEPENDS )
llvm_config( ${name} ${LLVM_LINK_COMPONENTS} )
target_link_libraries( ${name} ${LLVM_COMMON_LIBS} )
if (SHARED_LIBRARY AND EXPORTED_SYMBOL_FILE)
add_msilcjit_symbol_exports( ${name} ${EXPORTED_SYMBOL_FILE} )
endif()
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libmsilcjit")
install(TARGETS ${name}
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
RUNTIME DESTINATION bin)
endif()
set_target_properties(${name} PROPERTIES FOLDER "MSILCJit libraries")
endmacro(add_msilcjit_library)
macro(add_msilcjit_executable name)
add_llvm_executable( ${name} ${ARGN} )
set_target_properties(${name} PROPERTIES FOLDER "msilcjit executables")
endmacro(add_msilcjit_executable)
include_directories(BEFORE
${CMAKE_CURRENT_BINARY_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/include
)
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
install(DIRECTORY include/
DESTINATION include
FILES_MATCHING
PATTERN "*.def"
PATTERN "*.h"
PATTERN "config.h" EXCLUDE
PATTERN ".svn" EXCLUDE
)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/
DESTINATION include
FILES_MATCHING
PATTERN "CMakeFiles" EXCLUDE
PATTERN "*.inc"
)
endif()
add_definitions( -D_GNU_SOURCE )
add_definitions( -DFEATURE_CORECLR )
if (UNIX)
add_definitions( -DPLATFORM_UNIX )
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/Pal/Rt)
else()
add_definitions( -DWIN32_LEAN_AND_MEAN )
add_definitions( -DNOMINMAX )
endif()
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
add_definitions( -DBIT64 )
add_definitions( -D_WIN64 )
endif()
# MSILCJit version information
set(MSILCJIT_EXECUTABLE_VERSION
"${MSILCJIT_VERSION_MAJOR}.${MSILCJIT_VERSION_MINOR}" CACHE STRING
"Version number that will be placed into the msilcjit executable, in the form XX.YY")
set(LIBMSILCJIT_LIBRARY_VERSION
"${MSILCJIT_VERSION_MAJOR}.${MSILCJIT_VERSION_MINOR}" CACHE STRING
"Version number that will be placed into the libmsilcjit library , in the form XX.YY")
mark_as_advanced(MSILCJIT_EXECUTABLE_VERSION LIBMSILCJIT_LIBRARY_VERSION)
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(tools)
option(MSILCJIT_INCLUDE_TESTS
"Generate build targets for the MSILCJit unit tests."
${LLVM_INCLUDE_TESTS})
if( MSILCJIT_INCLUDE_TESTS )
add_subdirectory(test)
endif()
# Workaround for MSVS10 to avoid the Dialog Hell
# FIXME: This could be removed with future version of CMake.
if( MSILCJIT_BUILT_STANDALONE AND MSVC_VERSION EQUAL 1600 )
set(MSILCJIT_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/msilcjit.sln")
if( EXISTS "${MSILCJIT_SLN_FILENAME}" )
file(APPEND "${MSILCJIT_SLN_FILENAME}" "\n# This should be regenerated!\n")
endif()
endif()
set(BUG_REPORT_URL "http://llvm.org/bugs/FixME:::" CACHE STRING // Lub FixMe:
"Default URL where bug reports are to be submitted.")
set(MSILCJIT_ORDER_FILE "" CACHE FILEPATH
"Order file to use when compiling MSILCJit in order to improve startup time.")

21
LICENSE.TXT Normal file
Просмотреть файл

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.

28
README.md Normal file
Просмотреть файл

@ -0,0 +1,28 @@
# MSILC Developers Guide
## Introduction
MSILC is the Microsoft code name for cross-platform .NET tools.
It currently includes an LLVM-based Jit.
## MSILC Coding Guidelines
### Use of LLVM I/O APIs
Rather than using the printf family of output functions the MSILC team
uses the LLVML I/O APIs. This is a simplified form of C++ output.
- The base type is raw_ostream.
- Derived classes are:
- raw_fd_ostream, for output to a file descriptor. Two of these are
made and accessed as follows:
- outs() is connected to stdout
- errs() is connected to stderr.
- dbgs() is a debug stream that is connected to stderr but which
may optionally have circular buffering but by default it is
an unbuffered connection to errs().
- raw_string_ostream connects to a std::string given in its
- constructor. Any output to that stream is appended to the
end of the string.
- As with C++ the "<<" operator has overloads for outputting all the
common data types.
- In addition the form "<< format(formatstring, args)" may be
used to get the usual printf-stype formatting to a stream.

5
include/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,5 @@
add_subdirectory(clr)
add_subdirectory(Driver)
add_subdirectory(Jit)
add_subdirectory(Pal)
add_subdirectory(Reader)

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,96 @@
//===--------------- include/Jit/EEMemoryManager.h --------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Declaration of the memory manager interface to the EE.
//
//===----------------------------------------------------------------------===//
#ifndef EE_MEMORYMANAGER_H
#define EE_MEMORYMANAGER_H
#include "llvm/ExecutionEngine/RuntimeDyld.h"
class MSILCJitContext;
namespace llvm {
// Override MemoryManager to implement interface to EE allocator.
// It is through the EE allocated memory that we will return the encoded
// method for execution.
class EEMemoryManager : public RTDyldMemoryManager {
public:
EEMemoryManager(MSILCJitContext *C)
: Context(C), HotCodeBlock(nullptr), ColdCodeBlock(nullptr),
ReadOnlyDataBlock(nullptr) {}
~EEMemoryManager() override;
/// \brief Allocates a memory block of (at least) the given size suitable
/// for executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is
/// zero a default alignment of 16 will be used.
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override;
/// \brief Allocates a memory block of (at least) the given size suitable
/// for executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is
/// zero a default alignment of 16 will be used.
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override;
/// \brief Update section-specific memory permissions and other attributes.
///
/// This method is called when object loading is complete and section page
/// permissions can be applied. It is up to the memory manager
/// implementation to decide whether or not to act on this method.
/// The memory manager will typically allocate all sections as read-write
/// and then apply specific permissions when this method is called. Code
/// sections cannot be executed until this function has been called.
/// In addition, any cache coherency operations needed to reliably use the
/// memory are also performed.
///
/// \returns true if an error occurred, false otherwise.
bool finalizeMemory(std::string *ErrMsg = nullptr) override;
/// Inform the memory manager about the total amount of memory required to
/// allocate all sections to be loaded:
/// \p CodeSize - the total size of all code sections
/// \p DataSizeRO - the total size of all read-only data sections
/// \p DataSizeRW - the total size of all read-write data sections
///
/// Note that by default the callback is disabled. To enable it
/// redefine the method needsToReserveAllocationSpace to return true.
void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
uintptr_t DataSizeRW) override;
/// Overriding to return true to enable the reserveAllocationSpace callback.
bool needsToReserveAllocationSpace() override { return true; }
/// \brief Callback to handle processing unwind data.
///
/// This is currently invoked once per .xdata section.
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
private:
MSILCJitContext *Context;
uint8_t *HotCodeBlock;
uint8_t *ColdCodeBlock;
uint8_t *ReadOnlyDataBlock;
uint8_t *ReadOnlyDataUnallocated;
};
} // namespace llvm
#endif // EEMEMORYMANAGER_H

120
include/Jit/MSILCJit.h Normal file
Просмотреть файл

@ -0,0 +1,120 @@
//===----------------- include/Jit/MSILCJit.h -------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declaration of the main Jit data structures.
///
//===----------------------------------------------------------------------===//
#ifndef MSILC_JIT_H
#define MSILC_JIT_H
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/ThreadLocal.h"
struct MSILCJitPerThreadState;
/// \brief This struct holds per-jit request state.
///
/// A Jit context object is allocated (on the stack) each
/// time compileMethod is invoked. Note that the Jit
/// can be re-entered on this thread if while in the middle
/// of jitting a method, other methods must be run.
class MSILCJitContext {
public:
MSILCJitContext(MSILCJitPerThreadState *State);
~MSILCJitContext();
llvm::Module *getModuleForMethod(CORINFO_METHOD_INFO *MethodInfo);
void outputDebugMethodName();
inline BYTE getILByte() { return *((BYTE *&)ILCursor)++; }
inline DWORD getILDword() { return *((UNALIGNED DWORD *&)ILCursor)++; }
public:
BYTE *ILCursor;
ICorJitInfo *JitInfo;
CORINFO_METHOD_INFO *MethodInfo;
UINT Flags;
llvm::Module *CurrentModule;
std::string MethodName;
llvm::ExecutionEngine *EE;
bool HasLoadedBitCode;
MSILCJitContext *Next;
MSILCJitPerThreadState *State;
CORINFO_EE_INFO EEInfo;
llvm::LLVMContext *LLVMContext;
// Allocated memory sizes for method being processed.
// This is encoded byte size for the complied method
// and associated data.
ULONG HotCodeSize = 0;
ULONG ColdCodeSize = 0;
ULONG ReadOnlyDataSize = 0;
};
/// \brief This struct holds per-thread Jit state.
///
/// The Jit may be invoked concurrently on more than
/// one thread. To avoid synchronization overhead
/// it maintains per-thread state, mainly to map from
/// EE artifacts to LLVM data structures.
///
/// The per thread state also provides access to the
/// current Jit context in case it's needed.
struct MSILCJitPerThreadState {
public:
MSILCJitPerThreadState()
: LLVMContext(), ClassTypeMap(), ArrayTypeMap(), FieldIndexMap(),
JitContext(NULL) {}
llvm::LLVMContext LLVMContext;
MSILCJitContext *JitContext;
std::map<CORINFO_CLASS_HANDLE, llvm::Type *> ClassTypeMap;
std::map<std::tuple<CorInfoType, CORINFO_CLASS_HANDLE, unsigned int>,
llvm::Type *> ArrayTypeMap;
std::map<CORINFO_FIELD_HANDLE, unsigned int> FieldIndexMap;
};
/// \brief The Jit interface to the EE.
///
/// This class implements the Jit interface to the EE.
class MSILCJit : public ICorJitCompiler {
public:
MSILCJit();
CorJitResult __stdcall compileMethod(ICorJitInfo *JitInfo,
CORINFO_METHOD_INFO *MethodInfo,
UINT Flags, BYTE **NativeEntry,
ULONG *NativeSizeOfCode) override;
void clearCache() override;
BOOL isCacheCleanupRequired() override;
void getVersionIdentifier(GUID *VersionIdentifier) override;
static MSILCJitContext *getMSILCJitContext() {
return TheJit->State.get()->JitContext;
}
static void __cdecl fatal(int Errnum, ...);
static void signalHandler(void *Cookie);
private:
bool readMethod(MSILCJitContext *JitContext);
bool outputGCInfo(MSILCJitContext *JitContext);
public:
static MSILCJit *TheJit;
private:
llvm::sys::ThreadLocal<MSILCJitPerThreadState> State;
};
#endif // MSILC_JIT_H

34
include/Jit/global.h Normal file
Просмотреть файл

@ -0,0 +1,34 @@
//===--------------- include/Jit/global.h -----------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Host and target defines.
//
//===----------------------------------------------------------------------===//
#ifndef JIT_GLOBAL_H
#define JIT_GLOBAL_H
#if defined(_M_IX86) || defined(__i386__)
#define _TARGET_X86_ 1
#define _HOST_X86_ 1
#elif defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__)
#define _TARGET_X64_ 1
#define _TARGET_AMD64_ 1
#define _HOST_X64_ 1
#define _HOST_AMD64_ 1
#elif defined(_M_ARM) || defined(__arm__)
#define _TARGET_ARM_ 1
#define _HOST_ARM_ 1
#elif defined(_M_ARM64) || defined(__aarch64__)
#define _TARGET_ARM64_ 1
#define _HOST_ARM64_ 1
#endif
#endif // JIT_GLOBAL_H

31
include/Jit/jitpch.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
//===--------------- include/Jit/jitpch.h -----------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Jit precompiled header
//
//===----------------------------------------------------------------------===//
#ifndef JIT_PCH_H
#define JIT_PCH_H
#include "global.h"
#include "MSILCPal.h"
#if defined(_MSC_VER)
#include <windows.h>
#else
#include <cstddef>
#include <cstdarg>
#include "ntimage.h"
#endif
#include "corjit.h"
#endif // JIT_PCH_H

Просмотреть файл

@ -0,0 +1 @@
add_subdirectory(Rt)

971
include/Pal/MSILCPal.h Normal file
Просмотреть файл

@ -0,0 +1,971 @@
//===--- include/Pal/MSILCPal.h ---------------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Minimal PAL for non-Windows platforms.
//
//===----------------------------------------------------------------------===//
#ifndef MSILC_PAL
#define MSILC_PAL
// We still need the PAL EH macros on Windows, so define them here.
#if defined(_MSC_VER)
#include "staticcontract.h"
// Note: PAL_SEH_RESTORE_GUARD_PAGE is only ever defined in clrex.h, so we only restore guard pages automatically
// when these macros are used from within the VM.
#define PAL_SEH_RESTORE_GUARD_PAGE
#define PAL_TRY_NAKED \
{ \
bool __exHandled; __exHandled = false; \
DWORD __exCode; __exCode = 0; \
SCAN_EHMARKER(); \
__try \
{ \
SCAN_EHMARKER_TRY();
#define PAL_EXCEPT_NAKED(Disposition) \
} \
__except(__exCode = GetExceptionCode(), Disposition) \
{ \
__exHandled = true; \
SCAN_EHMARKER_CATCH(); \
PAL_SEH_RESTORE_GUARD_PAGE
#define PAL_EXCEPT_FILTER_NAKED(pfnFilter, param) \
} \
__except(__exCode = GetExceptionCode(), \
pfnFilter(GetExceptionInformation(), param)) \
{ \
__exHandled = true; \
SCAN_EHMARKER_CATCH(); \
PAL_SEH_RESTORE_GUARD_PAGE
#define PAL_FINALLY_NAKED \
} \
__finally \
{ \
#define PAL_ENDTRY_NAKED \
} \
PAL_ENDTRY_NAKED_DBG \
} \
#if defined(_DEBUG) && !defined(DACCESS_COMPILE)
//
// In debug mode, compile the try body as a method of a local class.
// This way, the compiler will check that the body is not directly
// accessing any local variables and arguments.
//
#define PAL_TRY(__ParamType, __paramDef, __paramRef) \
{ \
__ParamType __param = __paramRef; \
__ParamType __paramToPassToFilter = __paramRef; \
class __Body \
{ \
public: \
static void Run(__ParamType __paramDef) \
{ \
PAL_TRY_HANDLER_DBG_BEGIN
// PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by
// JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods
// as on PAL.
#define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) \
{ \
struct __HandlerData { \
__ParamType __param; \
COMPILER_INSTANCE *__ciPtr; \
}; \
__HandlerData handlerData; \
handlerData.__param = __paramRef; \
handlerData.__ciPtr = ciPtr; \
__HandlerData* __param = &handlerData; \
__ParamType __paramToPassToFilter = __paramRef; \
class __Body \
{ \
public: \
static void Run(__HandlerData* __pHandlerData) \
{ \
PAL_TRY_HANDLER_DBG_BEGIN \
COMPILER_INSTANCE *ciPtr = __pHandlerData->__ciPtr; \
__ParamType __paramDef = __pHandlerData->__param;
#define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \
{ \
__ParamType __param = __paramRef; \
__ParamType __paramToPassToFilter = __paramRef; \
class __Body \
{ \
public: \
static void Run(__ParamType __paramDef) \
{ \
PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason)
#define PAL_EXCEPT(Disposition) \
PAL_TRY_HANDLER_DBG_END \
} \
}; \
PAL_TRY_NAKED \
__Body::Run(__param); \
PAL_EXCEPT_NAKED(Disposition)
#define PAL_EXCEPT_FILTER(pfnFilter) \
PAL_TRY_HANDLER_DBG_END \
} \
}; \
PAL_TRY_NAKED \
__Body::Run(__param); \
PAL_EXCEPT_FILTER_NAKED(pfnFilter, __paramToPassToFilter)
#define PAL_FINALLY \
PAL_TRY_HANDLER_DBG_END \
} \
}; \
PAL_TRY_NAKED \
__Body::Run(__param); \
PAL_FINALLY_NAKED
#define PAL_ENDTRY \
PAL_ENDTRY_NAKED \
}
#else // _DEBUG
#define PAL_TRY(__ParamType, __paramDef, __paramRef) \
{ \
__ParamType __param = __paramRef; \
__ParamType __paramDef = __param; \
PAL_TRY_NAKED \
PAL_TRY_HANDLER_DBG_BEGIN
// PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by
// JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods
// as on PAL.
#define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) PAL_TRY(__ParamType, __paramDef, __paramRef)
#define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \
{ \
__ParamType __param = __paramRef; \
__ParamType __paramDef; __paramDef = __param; \
PAL_TRY_NAKED \
PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason)
#define PAL_EXCEPT(Disposition) \
PAL_TRY_HANDLER_DBG_END \
PAL_EXCEPT_NAKED(Disposition)
#define PAL_EXCEPT_FILTER(pfnFilter) \
PAL_TRY_HANDLER_DBG_END \
PAL_EXCEPT_FILTER_NAKED(pfnFilter, __param)
#define PAL_FINALLY \
PAL_TRY_HANDLER_DBG_END \
PAL_FINALLY_NAKED
#define PAL_ENDTRY \
PAL_ENDTRY_NAKED \
}
#endif // _DEBUG
#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(CROSS_COMPILE) && !defined(_TARGET_ARM_) // @ARMTODO: no contracts for speed
#define PAL_TRY_HANDLER_DBG_BEGIN \
BOOL ___oldOkayToThrowValue = FALSE; \
SO_INFRASTRUCTURE_CODE(BOOL ___oldSOTolerantState = FALSE;) \
ClrDebugState *___pState = ::GetClrDebugState(); \
__try \
{ \
___oldOkayToThrowValue = ___pState->IsOkToThrow(); \
SO_INFRASTRUCTURE_CODE(___oldSOTolerantState = ___pState->IsSOTolerant();) \
___pState->SetOkToThrow(); \
PAL_ENTER_THROWS_REGION;
// Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach.
#define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \
BOOL ___oldOkayToThrowValue = FALSE; \
SO_INFRASTRUCTURE_CODE(BOOL ___oldSOTolerantState = FALSE;) \
ClrDebugState *___pState = NULL; \
if (_reason != DLL_PROCESS_ATTACH) \
___pState = CheckClrDebugState(); \
__try \
{ \
if (___pState) \
{ \
___oldOkayToThrowValue = ___pState->IsOkToThrow(); \
SO_INFRASTRUCTURE_CODE(___oldSOTolerantState = ___pState->IsSOTolerant();) \
___pState->SetOkToThrow(); \
} \
if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \
{ \
___pState = NULL; \
} \
PAL_ENTER_THROWS_REGION;
#define PAL_TRY_HANDLER_DBG_END \
PAL_LEAVE_THROWS_REGION \
} \
__finally \
{ \
if (___pState != NULL) \
{ \
_ASSERTE(___pState == CheckClrDebugState()); \
___pState->SetOkToThrow( ___oldOkayToThrowValue ); \
SO_INFRASTRUCTURE_CODE(___pState->SetSOTolerance( ___oldSOTolerantState );) \
} \
}
#define PAL_ENDTRY_NAKED_DBG \
if (__exHandled) \
{ \
RESTORE_SO_TOLERANCE_STATE; \
} \
#else
#define PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN;
#define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN;
#define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END;
#define PAL_ENDTRY_NAKED_DBG
#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD)
#else // defined(_MSC_VER)
// SAL
#define _In_
#define _Out_opt_
#define _Out_writes_to_opt_(size,count)
#define __out_ecount(count)
#define __inout_ecount(count)
#define __deref_inout_ecount(count)
#ifdef __cplusplus
extern "C" {
#endif
// Linkage
#if defined(__cplusplus)
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif // __cplusplus
#if defined(__llvm__)
#define DECLSPEC_ALIGN(x) __declspec(align(x))
#else
#define DECLSPEC_ALIGN(x)
#endif
#define _ASSERTE assert
#define __assume(x) (void)0
#define UNALIGNED
#define PALIMPORT EXTERN_C
#define PALAPI __stdcall
#define _cdecl __cdecl
#define STDMETHODCALLTYPE __stdcall
#define STDAPICALLTYPE __stdcall
#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
#define PURE = 0
#if defined(__GNUC__)
#define DECLSPEC_NOVTABLE
#define DECLSPEC_IMPORT
#define DECLSPEC_SELECTANY __attribute__((weak))
#define SELECTANY extern __attribute__((weak))
#else
#define DECLSPEC_NOVTABLE
#define DECLSPEC_IMPORT
#define DECLSPEC_SELECTANY
#define SELECTANY
#endif
#if defined(__cplusplus)
}
#endif
#define _alloca alloca
// A bunch of source files (e.g. most of the ndp tree) include pal.h
// but are written to be LLP64, not LP64. (LP64 => long = 64 bits
// LLP64 => longs = 32 bits, long long = 64 bits)
//
// To handle this difference, we #define long to be int (and thus 32 bits) when
// compiling those files. (See the bottom of this file or search for
// #define long to see where we do this.)
//
// But this fix is more complicated than it seems, because we also use the
// preprocessor to #define __int64 to long for LP64 architectures (__int64
// isn't a builtin in gcc). We don't want __int64 to be an int (by cascading
// macro rules). So we play this little trick below where we add
// __cppmungestrip before "long", which is what we're really #defining __int64
// to. The preprocessor sees __cppmungestriplong as something different than
// long, so it doesn't replace it with int. The during the cppmunge phase, we
// remove the __cppmungestrip part, leaving long for the compiler to see.
//
// Note that we can't just use a typedef to define __int64 as long before
// #defining long because typedefed types can't be signedness-agnostic (i.e.
// they must be either signed or unsigned) and we want to be able to use
// __int64 as though it were intrinsic
#if defined(BIT64)
#define __int64 long
#else // _WIN64
#define __int64 long long
#endif // _WIN64
#define __int32 int
#define __int16 short int
#define __int8 char // assumes char is signed
typedef void VOID, *PVOID, *LPVOID, *LPCVOID;
#if !defined(PLATFORM_UNIX)
typedef long LONG
typedef unsigned long ULONG;
typedef unsigned long DWORD
#else
typedef int LONG; // NOTE: diff from windows.h, for LP64 compat
typedef unsigned int ULONG; // NOTE: diff from windows.h, for LP64 compat
typedef unsigned int DWORD; // NOTE: diff from windows.h, for LP64 compat
#endif
#if defined (PLATFORM_UNIX)
#if defined(__cplusplus)
typedef char16_t WCHAR;
#else
typedef unsigned short WCHAR;
#endif
#endif
typedef int BOOL;
typedef unsigned char BYTE, *PBYTE;
typedef char CHAR, *LPCSTR;
typedef unsigned char UCHAR;
typedef unsigned short WORD;
typedef short SHORT;
typedef unsigned short USHORT;
typedef WCHAR *LPWSTR, *LPCWSTR;
typedef int INT;
typedef unsigned int UINT;
typedef float FLOAT;
typedef double DOUBLE;
typedef BYTE BOOLEAN;
typedef signed __int32 INT32;
typedef unsigned __int32 UINT32;
typedef unsigned __int32 ULONG32;
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;
typedef unsigned __int64 ULONG64;
typedef ULONGLONG DWORD64, *PDWORD64;
#define _W64
#if _WIN64
typedef unsigned __int64 UINT_PTR;
typedef unsigned __int64 ULONG_PTR;
#else
typedef _W64 unsigned __int32 UINT_PTR;
typedef _W64 unsigned __int32 ULONG_PTR;
#endif
typedef ULONG_PTR SIZE_T;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
// Handles
typedef VOID *HANDLE;
typedef HANDLE HINSTANCE;
// HRESULTs
typedef LONG HRESULT;
// diff from Win32
#define MAKE_HRESULT(sev,fac,code) \
((HRESULT) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((ULONG)(code))) )
#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
#define S_OK _HRESULT_TYPEDEF_(0x00000000L)
#define FACILITY_NULL 0
#define NO_ERROR 0L
#define SEVERITY_ERROR 1
#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
#define FAILED(Status) ((HRESULT)(Status)<0)
// EH
#define EXCEPTION_NONCONTINUABLE 0x1
#define EXCEPTION_UNWINDING 0x2
#define EXCEPTION_MAXIMUM_PARAMETERS 15
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PVOID ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS, *LPEXCEPTION_POINTERS;
#define EXCEPTION_CONTINUE_SEARCH 0
#define EXCEPTION_EXECUTE_HANDLER 1
#define EXCEPTION_CONTINUE_EXECUTION -1
#define GetExceptionCode (DWORD)__exception_code
#define GetExceptionInformation (PEXCEPTION_POINTERS)__exception_info
#define METHOD_CANNOT_BE_FOLDED_DEBUG
#define ANNOTATION_TRY_BEGIN { }
#define ANNOTATION_TRY_END { }
#define ANNOTATION_FN_THROWS { }
#define ANNOTATION_FN_GC_NOTRIGGER { }
#define ANNOTATION_FN_SO_TOLERANT { }
#define STATIC_CONTRACT_THROWS ANNOTATION_FN_THROWS
#define STATIC_CONTRACT_GC_NOTRIGGER ANNOTATION_FN_GC_NOTRIGGER
#define STATIC_CONTRACT_SO_TOLERANT ANNOTATION_FN_SO_TOLERANT
namespace StaticContract
{
struct ScanThrowMarkerStandard
{
__declspec(noinline) ScanThrowMarkerStandard()
{
METHOD_CANNOT_BE_FOLDED_DEBUG;
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_NOTRIGGER;
STATIC_CONTRACT_SO_TOLERANT;
}
};
struct ScanThrowMarkerTerminal
{
__declspec(noinline) ScanThrowMarkerTerminal()
{
METHOD_CANNOT_BE_FOLDED_DEBUG;
}
};
struct ScanThrowMarkerIgnore
{
__declspec(noinline) ScanThrowMarkerIgnore()
{
METHOD_CANNOT_BE_FOLDED_DEBUG;
}
};
}
typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker;
// This is used to annotate code as throwing a terminal exception, and should
// be used immediately before the throw so that infer that it can be inferred
// that the block in which this annotation appears throws unconditionally.
#define SCAN_THROW_MARKER do { ScanThrowMarker __throw_marker; } while (0)
#define SCAN_EHMARKER()
#define SCAN_EHMARKER_TRY()
#define SCAN_EHMARKER_END_TRY()
#define SCAN_EHMARKER_CATCH()
#define SCAN_EHMARKER_END_CATCH()
#if defined(__cplusplus)
extern "C"
{
#endif // __cplusplus
//
// Exception Handling ABI Level I: Base ABI
//
typedef enum
{
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8,
} _Unwind_Reason_Code;
typedef enum
{
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
} _Unwind_Action;
#define _UA_PHASE_MASK (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)
struct _Unwind_Context;
void *_Unwind_GetIP(struct _Unwind_Context *context);
void _Unwind_SetIP(struct _Unwind_Context *context, void *new_value);
void *_Unwind_GetCFA(struct _Unwind_Context *context);
void *_Unwind_GetGR(struct _Unwind_Context *context, int index);
void _Unwind_SetGR(struct _Unwind_Context *context, int index, void *new_value);
struct _Unwind_Exception;
typedef void (*_Unwind_Exception_Cleanup_Fn)(
_Unwind_Reason_Code urc,
struct _Unwind_Exception *exception_object);
struct _Unwind_Exception
{
ULONG64 exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
UINT_PTR private_1;
UINT_PTR private_2;
} __attribute__((aligned));
void _Unwind_DeleteException(struct _Unwind_Exception *exception_object);
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *context, void *pvParam);
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn pfnTrace, void *pvParam);
_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exception_object);
__attribute__((noreturn)) void _Unwind_Resume(struct _Unwind_Exception *exception_object);
//
// Exception Handling ABI Level II: C++ ABI
//
void *__cxa_begin_catch(void *exceptionObject);
void __cxa_end_catch();
#if defined(__cplusplus)
};
#endif // __cplusplus
typedef LONG EXCEPTION_DISPOSITION;
enum {
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind,
};
// A pretend exception code that we use to stand for external exceptions,
// such as a C++ exception leaking across a P/Invoke boundary into
// COMPlusFrameHandler.
#define EXCEPTION_FOREIGN 0xe0455874 // 0xe0000000 | 'EXT'
// Test whether the argument exceptionObject is an SEH exception. If it is,
// return the associated exception pointers. If it is not, return NULL.
typedef void (*PFN_PAL_BODY)(void *pvParam);
typedef struct _PAL_DISPATCHER_CONTEXT {
_Unwind_Action actions;
struct _Unwind_Exception *exception_object;
struct _Unwind_Context *context;
} PAL_DISPATCHER_CONTEXT;
typedef EXCEPTION_DISPOSITION (*PFN_PAL_EXCEPTION_FILTER)(
EXCEPTION_POINTERS *ExceptionPointers,
PAL_DISPATCHER_CONTEXT *DispatcherContext,
void *pvParam);
PALIMPORT
PALAPI
struct _Unwind_Exception *PAL_TryExcept(
PFN_PAL_BODY pfnBody,
PFN_PAL_EXCEPTION_FILTER pfnFilter,
void *pvParam,
BOOL *pfExecuteHandler);
PALIMPORT
VOID
PALAPI
RaiseException(
DWORD dwExceptionCode,
DWORD dwExceptionFlags,
DWORD nNumberOfArguments,
const ULONG_PTR *lpArguments);
//
// Possible results from PAL_TryExcept:
//
// returned exception pfExecuteHandler means
// ------------------ ---------------- ----------------------------------------
// NULL any No exception escaped from the try block.
// non-NULL FALSE An exception escaped from the try block,
// but the filter did not want to handle it.
// non-NULL TRUE An exception escaped from the try block,
// and the filter wanted to handle it.
//
#define DEBUG_OK_TO_RETURN_BEGIN(arg)
#define DEBUG_OK_TO_RETURN_END(arg)
#define PAL_DUMMY_CALL
#if defined(__cplusplus)
class PAL_CatchHolder
{
public:
PAL_CatchHolder(_Unwind_Exception *exceptionObject)
{
__cxa_begin_catch(exceptionObject);
}
~PAL_CatchHolder()
{
__cxa_end_catch();
}
};
class PAL_ExceptionHolder
{
private:
_Unwind_Exception *m_exceptionObject;
public:
PAL_ExceptionHolder(_Unwind_Exception *exceptionObject)
{
m_exceptionObject = exceptionObject;
}
~PAL_ExceptionHolder()
{
if (m_exceptionObject)
{
_Unwind_DeleteException(m_exceptionObject);
}
}
void SuppressRelease()
{
m_exceptionObject = 0;
}
};
class PAL_NoHolder
{
public:
void SuppressRelease() {}
};
#endif // __cplusplus
#define PAL_TRY(__ParamType, __paramDef, __paramRef) \
{ \
struct __HandlerData \
{ \
__ParamType __param; \
EXCEPTION_DISPOSITION __handlerDisposition; \
__HandlerData(__ParamType param) : __param(param) {} \
}; \
__HandlerData __handlerData(__paramRef); \
class __Body \
{ \
public: \
static void Run(void *__pvHandlerData) \
{ \
__ParamType __paramDef = ((__HandlerData *)__pvHandlerData)->__param; \
PAL_DUMMY_CALL;
// On Windows 32bit, we dont invoke filters on the second pass.
// To ensure the same happens on the Mac, we check if we are
// in the first phase or not. If we are, we invoke the
// filter and save the disposition in a local static.
//
// However, if we are not in the first phase but in the second,
// and thus unwinding, then we return the disposition saved
// from the first pass back (similar to how CRT
// does it on x86).
#define PAL_EXCEPT(dispositionExpression) \
} \
static EXCEPTION_DISPOSITION Handler( \
EXCEPTION_POINTERS *ExceptionPointers, \
PAL_DISPATCHER_CONTEXT *DispatcherContext, \
void *pvHandlerData) \
{ \
DEBUG_OK_TO_RETURN_BEGIN(PAL_EXCEPT) \
__HandlerData *pHandlerData = (__HandlerData *)pvHandlerData; \
void *pvParam = NULL; \
pvParam = pHandlerData->__param; \
if (!(ExceptionPointers->ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)) \
pHandlerData->__handlerDisposition = (EXCEPTION_DISPOSITION) (dispositionExpression); \
return pHandlerData->__handlerDisposition; \
DEBUG_OK_TO_RETURN_END(PAL_EXCEPT) \
} \
}; \
BOOL __fExecuteHandler; \
_Unwind_Exception *__exception = \
PAL_TryExcept(__Body::Run, __Body::Handler, &__handlerData, &__fExecuteHandler); \
PAL_NoHolder __exceptionHolder; \
if (__exception && __fExecuteHandler) \
{ \
PAL_CatchHolder __catchHolder(__exception); \
__exception = NULL;
#define PAL_EXCEPT_FILTER(filter) PAL_EXCEPT(filter(ExceptionPointers, pvParam))
// Executes the handler if the specified exception code matches
// the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH.
#define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) \
PAL_EXCEPT(((ExceptionPointers->ExceptionRecord->ExceptionCode == dwExceptionCode)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH))
#define PAL_FINALLY \
} \
static EXCEPTION_DISPOSITION Filter( \
EXCEPTION_POINTERS *ExceptionPointers, \
PAL_DISPATCHER_CONTEXT *DispatcherContext, \
void *pvHandlerData) \
{ \
DEBUG_OK_TO_RETURN_BEGIN(PAL_FINALLY) \
return EXCEPTION_CONTINUE_SEARCH; \
DEBUG_OK_TO_RETURN_END(PAL_FINALLY) \
} \
}; \
BOOL __fExecuteHandler; \
_Unwind_Exception *__exception = \
PAL_TryExcept(__Body::Run, __Body::Filter, &__handlerData, &__fExecuteHandler); \
PAL_ExceptionHolder __exceptionHolder(__exception); \
{
#define PAL_ENDTRY \
} \
if (__exception) \
{ \
__exceptionHolder.SuppressRelease(); \
_Unwind_Resume(__exception); \
} \
}
// COM
typedef struct _GUID {
ULONG Data1; // NOTE: diff from Win32, for LP64
USHORT Data2;
USHORT Data3;
UCHAR Data4[ 8 ];
} GUID;
#if defined(__cplusplus)
#define REFGUID const GUID &
#else
#define REFGUID const GUID *
#endif
typedef GUID IID;
#if defined(__cplusplus)
#define REFIID const IID &
#else
#define REFIID const IID *
#endif
typedef GUID CLSID;
#if defined(__cplusplus)
#define REFCLSID const CLSID &
#else
#define REFCLSID const CLSID *
#endif
#define DECLSPEC_UUID(x) __declspec(uuid(x))
#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) __declspec(novtable)
#define EXTERN_GUID(itf,l1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) \
EXTERN_C const IID DECLSPEC_SELECTANY itf = {l1,s1,s2,{c1,c2,c3,c4,c5,c6,c7,c8}}
#define interface struct
#define DECLARE_INTERFACE(iface) interface DECLSPEC_NOVTABLE iface
#define DECLARE_INTERFACE_(iface, baseiface) interface DECLSPEC_NOVTABLE iface : public baseiface
typedef interface IUnknown IUnknown;
typedef /* [unique] */ IUnknown *LPUNKNOWN;
// 00000000-0000-0000-C000-000000000046
EXTERN_C const IID IID_IUnknown;
MIDL_INTERFACE("00000000-0000-0000-C000-000000000046")
IUnknown
{
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
};
interface IStream;
interface IRecordInfo;
interface ITypeInfo;
typedef SHORT VARIANT_BOOL;
typedef LONG SCODE;
typedef union tagCY {
struct {
#if BIGENDIAN
LONG Hi;
ULONG Lo;
#else
ULONG Lo;
LONG Hi;
#endif
} u;
LONGLONG int64;
} CY;
typedef WCHAR *BSTR;
typedef double DATE;
typedef struct tagDEC {
// Decimal.cs treats the first two shorts as one long
// And they seriable the data so we need to little endian
// seriliazation
// The wReserved overlaps with Variant's vt member
#if BIGENDIAN
union {
struct {
BYTE sign;
BYTE scale;
} u;
USHORT signscale;
} u;
USHORT wReserved;
#else
USHORT wReserved;
union {
struct {
BYTE scale;
BYTE sign;
} u;
USHORT signscale;
} u;
#endif
ULONG Hi32;
union {
struct {
ULONG Lo32;
ULONG Mid32;
} v;
ULONGLONG Lo64;
} v;
} DECIMAL;
typedef unsigned short VARTYPE;
typedef struct tagVARIANT VARIANT;
struct tagVARIANT
{
union
{
struct
{
#if BIGENDIAN
// We need to make sure vt overlaps with DECIMAL's wReserved.
// See the DECIMAL type for details.
WORD wReserved1;
VARTYPE vt;
#else
VARTYPE vt;
WORD wReserved1;
#endif
WORD wReserved2;
WORD wReserved3;
union
{
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
interface IUnknown *punkVal;
BYTE *pbVal;
SHORT *piVal;
LONG *plVal;
LONGLONG *pllVal;
FLOAT *pfltVal;
DOUBLE *pdblVal;
VARIANT_BOOL *pboolVal;
SCODE *pscode;
CY *pcyVal;
DATE *pdate;
BSTR *pbstrVal;
interface IUnknown **ppunkVal;
VARIANT *pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
ULONGLONG ullVal;
INT intVal;
UINT uintVal;
DECIMAL *pdecVal;
CHAR *pcVal;
USHORT *puiVal;
ULONG *pulVal;
ULONGLONG *pullVal;
INT *pintVal;
UINT *puintVal;
struct __tagBRECORD
{
PVOID pvRecord;
interface IRecordInfo *pRecInfo;
} brecVal;
} n3;
} n2;
DECIMAL decVal;
} n1;
};
#endif // _MSC_VER
#endif // MSILC_PAL

Просмотреть файл

14
include/Pal/Rt/ole2.h Normal file
Просмотреть файл

@ -0,0 +1,14 @@
//===--- include/Pal/Rt/ole2.h ----------------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Dummy ole2.h for non-Windows platforms.
//
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -0,0 +1,13 @@
//===--- include/Pal/Rt/specstrings.h ---------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Dummy specstrings.h for non-Windows platforms.
//
//===----------------------------------------------------------------------===//

13
include/Pal/Rt/windef.h Normal file
Просмотреть файл

@ -0,0 +1,13 @@
//===--- include/Pal/Rt/windef.h ------------------------- ------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Dummy windef.h for non-Windows platforms.
//
//===----------------------------------------------------------------------===//

13
include/Pal/Rt/winerror.h Normal file
Просмотреть файл

@ -0,0 +1,13 @@
//===--- include/Pal/Rt/winerror.h ------------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Dummy winerror.h for non-Windows platforms.
//
//===----------------------------------------------------------------------===//

Просмотреть файл

57
include/Reader/gverify.h Normal file
Просмотреть файл

@ -0,0 +1,57 @@
//===------------------- include/Reader/gverify.h ---------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Declares data structures useful for MSIL bytecode verification.
//
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_GVERIFY_H
#define MSIL_READER_GVERIFY_H
#include "vtypeinfo.h"
class FlowGraphNode;
// global verification structures
typedef struct {
FlowGraphNode *Block;
int TosIndex;
int SsaIndex;
} TOSTemp;
struct TagGlobalVerifyData;
typedef struct TagGlobalVerifyData GlobalVerifyData;
enum InitState {
ThisUnreached = -1,
ThisUnInit = 0,
ThisInited = 1,
ThisInconsistent = 2,
ThisEHReached = 3
};
struct TagGlobalVerifyData {
int MinStack;
int MaxStack;
int NetStack;
int TOSTempsCount;
TOSTemp *TOSTemps;
int SsaBase;
int StkDepth;
VerType *TiStack;
bool IsOnWorklist, BlockIsBad;
GlobalVerifyData *WorklistPrev, *WorklistNext;
FlowGraphNode *Block;
InitState ThisInitialized;
bool ContainsCtorCall;
};
#endif // MSIL_READER_GVERIFY_H

40
include/Reader/imeta.def Normal file
Просмотреть файл

@ -0,0 +1,40 @@
//===------------------- include/Reader/imeta.def ----------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares constants useful for imeta.h interface
///
//===----------------------------------------------------------------------===//
#define mdtJitHelper 0x73000000
#define mdtInterfaceOffset 0x74000000
#define mdtCodeOffset 0x75000000
#define mdtSyncHandle 0x76000000
#define mdtVarArgsHandle 0x77000000
#define mdtPInvokeCalliHandle 0x78000000
#define mdtIBCProfHandle 0x79000000
// When returning a struct with gc through a hidden param, we
// call the ASSIGN_STRUCT helper and we need a dummy token to pass
// around with the class handle we got from the method sig.
#define mdtMBReturnHandle 0x7A000000
#define mdtGSCookie 0x7B000000
#define mdtJMCHandle 0x7C000000
#define mdtCaptureThreadGlobal 0x7D000000
#define mdtModuleID 0x7E000000
// For instantiation parameters where we have a handle, but no token
#define mdtMethodHandle 0x7F000000
#define mdtClassHandle 0x80000000
#define mdtVarArgsSigHandle 0x81000000
#define mdtVarArgsMDHandle 0x82000000
#define mdtVarArgsMSHandle 0x83000000

21
include/Reader/imeta.h Normal file
Просмотреть файл

@ -0,0 +1,21 @@
//===------------------- include/Reader/imeta.h -----------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares extra information not provided by the jit interface.
///
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_IMETA_H
#define MSIL_READER_IMETA_H
#include "imeta.def"
#endif // MSIL_READER_IMETA_H

135
include/Reader/jit64.h Normal file
Просмотреть файл

@ -0,0 +1,135 @@
//===------------------- include/Reader/jit64.h -----------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Declarations and defines for things that are common to various
// users of the reader framweork.
//
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_JIT64_H
#define MSIL_READER_JIT64_H
// ---------------------- HRESULT value definitions -----------------
//
// HRESULT definitions
//
//
// Values are 32 bit values layed out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//
//
// Internal JIT exceptions.
#define FACILITY_JIT64 0x64 // This is a made up facility code
// Some fatal error occurred
#define JIT64_FATAL_ERROR CORJIT_INTERNALERROR
// An out of memory error occurred in the JIT64
#define JIT64_NOMEM_ERROR CORJIT_OUTOFMEM
#define JIT64_FATALEXCEPTION_CODE (0xE0000000 | FACILITY_JIT64 << 16 | 1)
#define JIT64_READEREXCEPTION_CODE (0xE0000000 | FACILITY_JIT64 << 16 | 2)
//===========================================================================
// Function: jitFilter
//
// Filter to detect/handle internal JIT exceptions.
// Returns EXCEPTION_EXECUTE_HANDLER for JIT64 exceptions,
// and EXCEPTION_CONTINUE_SEARCH for all others.
//
#ifdef __cplusplus
extern "C"
#endif
int
jitFilter(PEXCEPTION_POINTERS ExceptionPointersPtr, LPVOID Param);
extern void _cdecl fatal(int Errnum, ...);
// Global environment config variables (set by GetConfigString).
// These are defined/set in jit.cpp.
#ifdef __cplusplus
extern "C" {
#endif
extern UINT EnvConfigCseOn;
#ifndef NDEBUG
extern UINT EnvConfigCseBinarySearch;
extern UINT EnvConfigCseMax;
extern UINT EnvConfigCopyPropMax;
extern UINT EnvConfigDeadCodeMax;
extern UINT EnvConfigCseStats;
#endif // !NDEBUG
#if !defined(CC_PEVERIFY)
extern UINT EnvConfigTailCallOpt;
#if !defined(NODEBUG)
extern UINT EnvConfigDebugVerify;
extern UINT EnvConfigTailCallMax;
#endif // !NODEBUG
#endif // !CC_PEVERIFY
extern UINT EnvConfigPInvokeInline;
extern UINT EnvConfigPInvokeCalliOpt;
extern UINT EnvConfigNewGCCalc;
extern UINT EnvConfigTurnOffDebugInfo;
extern WCHAR *EnvConfigJitName;
extern BOOL HaveEnvConfigCseOn;
extern BOOL HaveEnvConfigCseStats;
#ifndef NDEBUG
extern BOOL HaveEnvConfigCseBinarySearch;
extern BOOL HaveEnvConfigCseMax;
extern BOOL HaveEnvConfigCopyPropMax;
extern BOOL HaveEnvConfigDeadCodeMax;
#endif // !NDEBUG
#if !defined(CC_PEVERIFY)
extern BOOL HaveEnvConfigTailCallOpt;
#if !defined(NODEBUG)
extern BOOL HaveEnvConfigDebugVerify;
extern BOOL HaveEnvConfigTailCallMax;
#endif // !NODEBUG
#endif // !CC_PEVERIFY
extern BOOL HaveEnvConfigPInvokeInline;
extern BOOL HaveEnvConfigPInvokeCalliOpt;
extern BOOL HaveEnvConfigNewGCCalc;
extern BOOL HaveEnvConfigTurnOffDebugInfo;
extern BOOL HaveEnvConfigJitName;
} // extern "C"
struct JITFilterParams {
CorJitResult *ErrorCode;
};
struct JITFilterCommonParams {
EXCEPTION_POINTERS ExceptionPointers;
};
#endif // MSIL_READER_JIT64_H

204
include/Reader/newvstate.h Normal file
Просмотреть файл

@ -0,0 +1,204 @@
//===------------------- include/Reader/newvstate.h -------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Data structures for holding verification state.
//
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_NEW_VSTATE_H
#define MSIL_READER_NEW_VSTATE_H
#include "vtypeinfo.h"
#include "corerror.h"
#include "gverify.h"
class LocalDescr {
public:
CorInfoType Type;
CORINFO_CLASS_HANDLE Class;
};
class VerificationState {
public:
bool BlockIsBad;
bool *ArgsInitialized;
// This field caches the token of the delegate method
// in a potential delegate creation sequence.
mdToken DelegateMethodRef;
UINT ConstrainedPrefix : 1;
UINT ReadonlyPrefix : 1;
UINT TailPrefix : 1;
UINT VolatilePrefix : 1;
UINT UnalignedPrefix : 1;
UINT TailInBlock : 1;
// say we initialize the 'this' pointer in a try.
// Real successors of the block can assume 'this' is inited.
// nominal successors cannot. However if we know 'this' was inited in
UINT ThisInitializedThisBlock : 1;
UINT StrongThisInitialized : 1;
UINT ContainsCtorCall : 1; // block is in a ctor and calls a parent or same
// class ctor
const BYTE *DelegateCreateStart;
InitState ThisInitialized; // 'this' has been initialized on some paths
private:
VerType *Vstack;
unsigned Vsp;
unsigned MaxStack;
VerificationState() {}
public:
ReaderBase *Base;
inline void setStack(VerType *StackMem);
inline void init(unsigned MaxStackSize, unsigned NumLocals, bool InitLocals,
InitState InitState);
inline void print();
inline void push(VerType Typ);
inline VerType pop();
inline VerType impStackTop(unsigned N = 0);
// pop an objref which might be an uninitialized 'this' ptr
// See Partion 3 1.8.1.4
// No operations can be performed on an uninitialized 'this'
// except for storing into and loading from the object's fields.
inline VerType popPossiblyUninit();
inline unsigned stackLevel() { return Vsp; }
bool isThisPublishable() {
if (ThisInitialized == ThisInited || ThisInitialized == ThisEHReached)
return true;
else
return false;
}
bool isThisInitialized() { return (ThisInitialized == ThisInited); }
void setThisInitialized() {
// if its EHREACHED keep that
if (ThisInitialized != ThisEHReached)
ThisInitialized = ThisInited;
}
};
void VerificationState::setStack(VerType *StackMem) { Vstack = StackMem; }
void VerificationState::init(unsigned MaxStackSize, unsigned NumLocals,
bool InitLocals, InitState InitState) {
Vsp = 0;
MaxStack = MaxStackSize;
DelegateMethodRef = mdTokenNil;
BlockIsBad = false;
ConstrainedPrefix = false;
ReadonlyPrefix = false;
TailPrefix = false;
VolatilePrefix = false;
UnalignedPrefix = false;
TailInBlock = false;
DelegateCreateStart = NULL;
ThisInitializedThisBlock = false;
ThisInitialized = InitState;
StrongThisInitialized = false;
for (unsigned I = 0; I < NumLocals; I++) {
ArgsInitialized[I] = InitLocals;
}
}
VerType VerificationState::pop() {
VerType Ret = popPossiblyUninit();
Base->verifyAndReportFound((!Ret.isObjRef()) ||
(!Ret.isUninitialisedObjRef()),
Ret, MVER_E_STACK_UNINIT);
return Ret;
}
// See Partion 3 1.8.1.4
// No operations can be performed on an uninitialized 'this'
// except for storing into and loading from the object's fields.
VerType VerificationState::popPossiblyUninit() {
Base->gverifyOrReturn(Vsp > 0, MVER_E_STACK_UNDERFLOW);
Vsp--;
VerType Result = Vstack[Vsp];
// blank out the thing we just popped
#ifndef NDEBUG
memset(Vstack + Vsp, 0xcd, sizeof(VerType));
#endif
return Result;
}
void VerificationState::push(VerType Typ) {
Base->gverifyOrReturn(Vsp < MaxStack, MVER_E_STACK_OVERFLOW);
Vstack[Vsp] = Typ;
Vsp++;
}
VerType VerificationState::impStackTop(unsigned N) {
Base->gverifyOrReturn(Vsp > N, MVER_E_STACK_UNDERFLOW);
return Vstack[Vsp - N - 1];
}
// =========================================================================
// ================ Exceptions
// =========================================================================
class CallAuthorizationException : public ReaderException {};
class VerificationException : public ReaderException {
public:
DWORD DwFlags; // VER_ERR_XXX
union {
ReaderBaseNS::OPCODE Opcode;
unsigned long Padding1; // to match with idl generated struct size
};
union {
DWORD DwOffset; // #of bytes from start of method
long Offset; // for backward compat with Metadata validator
};
union {
mdToken Token; // for backward compat with metadata validator
BYTE CallConv;
CorElementType Elem;
DWORD StackSlot; // positon in the Stack
unsigned long Padding2; // to match with idl generated struct size
};
union {
DWORD Exception1; // Exception Record #
DWORD VarNumber; // Variable #
DWORD ArgNumber; // Argument #
DWORD Operand; // Operand for the opcode
};
union {
DWORD Exception2; // Exception Record #
};
};
#endif // MSIL_READER_NEW_VSTATE_H

163
include/Reader/ophelper.def Normal file
Просмотреть файл

@ -0,0 +1,163 @@
//===------------------- include/Reader/ophelper.h --------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Include file to make cleaner use of the opcode.def file to create mappings
// for info on MSIL ops.
//
// To use this header:
// #define OPDEF_HELPER
//
//===----------------------------------------------------------------------===//
#ifndef OPDEF_HELPER
#error "Must specify OPDEF_HELPER"
#endif
#define OPDEF_OPCODENAME 123001
#define OPDEF_OPERANDSIZE 123002
#define OPDEF_PUSHCOUNT 123003
#define OPDEF_POPCOUNT 123004
#define OPDEF_ISBRACH 123005
#if OPDEF_HELPER == OPDEF_OPCODENAME
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) s,
#include "opcode.def"
#undef OPDEF
#elif OPDEF_HELPER == OPDEF_OPERANDSIZE
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) args,
#define InlineNone 0
#define ShortInlineVar 1
#define ShortInlineI 1
#define InlineI 4
#define InlineI8 8
#define ShortInlineR 4
#define InlineR 8
#define InlineMethod 4
#define InlineSig 4
#define ShortInlineBrTarget 1
#define InlineBrTarget 4
#define InlineSwitch (BYTE)-1
#define InlineType 4
#define InlineString 4
#define InlineField 4
#define InlineTok 4
#define InlineVar 2
#include "opcode.def"
#undef OPDEF
#undef InlineNone
#undef ShortInlineVar
#undef ShortInlineI
#undef InlineI
#undef InlineI8
#undef ShortInlineR
#undef InlineR
#undef InlineMethod
#undef InlineSig
#undef ShortInlineBrTarget
#undef InlineBrTarget
#undef InlineSwitch
#undef InlineType
#undef InlineString
#undef InlineField
#undef InlineTok
#undef InlineVar
#elif OPDEF_HELPER == OPDEF_PUSHCOUNT
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) push,
#define Push0 0
#define Push1 1
#define VarPush -1
#define PushI 1
#define PushI4 1
#define PushI8 1
#define PushR4 1
#define PushR8 1
#define PushRef 1
#include "opcode.def"
#undef OPDEF
#undef Push0
#undef Push1
#undef VarPush
#undef PushI
#undef PushI4
#undef PushI8
#undef PushR4
#undef PushR8
#undef PushRef
#elif OPDEF_HELPER == OPDEF_POPCOUNT
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) pop,
#define Pop0 0
#define Pop1 1
#define VarPop -1
#define PopI 1
#define PopI4 1
#define PopI8 1
#define PopR4 1
#define PopR8 1
#define PopRef 1
#include "opcode.def"
#undef OPDEF
#undef Pop0
#undef Pop1
#undef VarPop
#undef PopI
#undef PopI4
#undef PopI8
#undef PopR4
#undef PopR8
#undef PopRef
#elif OPDEF_HELPER == OPDEF_ISBRANCH
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) ctrl,
#define NEXT 0
#define BREAK 0
#define CALL 0
#if defined(_MSC_VER)
#pragma push_macro("RETURN")
#endif // _MSC_VER
#if defined(RETURN)
#undef RETURN
#endif
#define RETURN 0
#define BRANCH 0
#define COND_BRANCH 1
#define THROW 0
#define META 0
#include "opcode.def"
#undef OPDEF
#undef NEXT
#undef BREAK
#undef CALL
#undef RETURN
#if defined(_MSC_VER)
#pragma pop_macro("RETURN")
#else
#undef RETURN
#endif // defined(_MSC_VER)
#undef BRANCH
#undef COND_BRANCH
#undef THROW
#undef META
#else
#error "Unrecognized OPDEF_HELPER"
#endif
#undef OPDEF_OPCODENAME
#undef OPDEF_OPERANDSIZE
#undef OPDEF_PUSHCOUNT
#undef OPDEF_POPCOUNT

2104
include/Reader/reader.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

550
include/Reader/readerenum.h Normal file
Просмотреть файл

@ -0,0 +1,550 @@
//===------------------- include/Reader/readerenum.h ------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Enumerations that are useful in translating from MSIL bytecode to some
// other representation.
//
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_ENUM_H
#define MSIL_READER_ENUM_H
namespace ReaderBaseNS {
// Opcode Enumerations for communicating opcode between
// reader and genir. Do not change the order of these
// enumerations as client may use these as indices into
// private arrays.
#include "openum.h"
enum UnaryOpcode {
Neg = 0,
Not,
LastUnaryOpcode
};
enum BinaryOpcode {
Add = 0,
AddOvf,
AddOvfUn,
And,
Div,
DivUn,
Mul,
MulOvf,
MulOvfUn,
Or,
Rem,
RemUn,
Sub,
SubOvf,
SubOvfUn,
Xor,
LastBinaryOpcode
};
enum BoolBranchOpcode {
BrFalse = 0,
BrFalseS,
BrTrue,
BrTrueS,
LastBoolBranchOpcode
};
enum CallOpcode {
Jmp = 0,
Call,
CallVirt,
Calli,
Tail,
NewObj, // Call code is used to process NewObj...
LastCallOpcode
};
enum CmpOpcode {
Ceq = 0,
Cgt,
CgtUn,
Clt,
CltUn,
LastCmpOpcode
};
enum CondBranchOpcode {
Beq = 0,
BeqS,
Bge,
BgeS,
BgeUn,
BgeUnS,
Bgt,
BgtS,
BgtUn,
BgtUnS,
Ble,
BleS,
BleUn,
BleUnS,
Blt,
BltS,
BltUn,
BltUnS,
BneUn,
BneUnS,
LastCondBranchOpcode
};
enum ConvOpcode {
ConvI1 = 0,
ConvI2,
ConvI4,
ConvI8,
ConvR4,
ConvR8,
ConvU1,
ConvU2,
ConvU4,
ConvU8,
ConvI,
ConvU,
ConvOvfI1,
ConvOvfI2,
ConvOvfI4,
ConvOnvI8,
ConvOvfU1,
ConvOvfU2,
ConvOvfU4,
ConvOvfU8,
ConvOvfI,
ConvOvfU,
ConvOvfI1Un,
ConvOvfI2Un,
ConvOvfI4Un,
ConvOvfI8Un,
ConvOvfU1Un,
ConvOvfU2Un,
ConvOvfU4Un,
ConvOvfU8Un,
ConvOvfIUn,
ConvOvfUUn,
ConvRUn,
LastConvOpcode
};
enum ExceptOpcode {
EndFilter,
Throw,
LastExceptOpcode
};
enum LdElemOpcode {
LdelemI1 = 0,
LdelemU1,
LdelemI2,
LdelemU2,
LdelemI4,
LdelemU4,
LdelemI8,
LdelemI,
LdelemR4,
LdelemR8,
LdelemRef,
Ldelem, // (M2 Generics)
LastLdelemOpcode
};
enum LdIndirOpcode {
LdindI1 = 0,
LdindU1,
LdindI2,
LdindU2,
LdindI4,
LdindU4,
LdindI8,
LdindI,
LdindR4,
LdindR8,
LdindRef,
LastLdindOpcode
};
enum StElemOpcode {
StelemI = 0,
StelemI1,
StelemI2,
StelemI4,
StelemI8,
StelemR4,
StelemR8,
StelemRef,
Stelem,
LastStelemOpcode
};
enum ShiftOpcode {
Shl = 0,
Shr,
ShrUn,
LastShiftOpcode
};
enum StIndirOpcode {
StindI1 = 0,
StindI2,
StindI4,
StindI8,
StindI,
StindR4,
StindR8,
StindRef,
LastStindOpcode
};
// Taken from rgn.h, eventually needs to go into its own file.
typedef enum {
RGN_Unknown = 0,
RGN_None,
RGN_Root,
RGN_Try,
RGN_Except, // C++ except (SEH)
RGN_Fault,
RGN_Finally,
RGN_Filter,
RGN_Dtor,
RGN_Catch, // C++ catch
RGN_MExcept, // managed (CLR) except
RGN_MCatch, // managed (CLR) catch
// New region types used in common reader
RGN_ClauseNone,
RGN_ClauseFilter,
RGN_ClauseFinally,
RGN_ClauseError,
RGN_ClauseFault,
} RegionKind;
// Taken from rgn.h, eventually needs to go into its own file.
typedef enum {
TRY_None = 0,
TRY_Fin,
TRY_Fault, // try/fault
TRY_MCatch, // the try has only catch handlers
TRY_MCatchXcpt, // the try has both catch and except handlers
TRY_MXcpt, // the try has only except handlers
// for native compiler code, not used in current jit64
TRY_Xcpt, // native SEH except
TRY_CCatch // native C++ catch
} TryKind;
};
// Used to map read opcodes to function-specific opcode enumerations.
// Uses the same ordering as openum.h.
SELECTANY const char
OpcodeRemap[ReaderBaseNS::CEE_MACRO_END - ReaderBaseNS::CEE_NOP] = {
-1, // CEE_NOP,
-1, // CEE_BREAK,
0, // CEE_LDARG_0,
1, // CEE_LDARG_1,
2, // CEE_LDARG_2,
3, // CEE_LDARG_3,
0, // CEE_LDLOC_0,
1, // CEE_LDLOC_1,
2, // CEE_LDLOC_2,
3, // CEE_LDLOC_3,
0, // CEE_STLOC_0,
1, // CEE_STLOC_1,
2, // CEE_STLOC_2,
3, // CEE_STLOC_3,
-1, // CEE_LDARG_S,
-1, // CEE_LDARGA_S,
-1, // CEE_STARG_S,
-1, // CEE_LDLOC_S,
-1, // CEE_LDLOCA_S,
-1, // CEE_STLOC_S,
-1, // CEE_LDNULL,
-1, // CEE_LDC_I4_M1,
0, // CEE_LDC_I4_0,
1, // CEE_LDC_I4_1,
2, // CEE_LDC_I4_2,
3, // CEE_LDC_I4_3,
4, // CEE_LDC_I4_4,
5, // CEE_LDC_I4_5,
6, // CEE_LDC_I4_6,
7, // CEE_LDC_I4_7,
8, // CEE_LDC_I4_8,
-1, // CEE_LDC_I4_S,
-1, // CEE_LDC_I4,
-1, // CEE_LDC_I8,
-1, // CEE_LDC_R4,
-1, // CEE_LDC_R8,
-1, // CEE_UNUSED49,
-1, // CEE_DUP,
-1, // CEE_POP,
ReaderBaseNS::Jmp, // CEE_JMP,
ReaderBaseNS::Call, // CEE_CALL,
ReaderBaseNS::Calli, // CEE_CALLI,
-1, // CEE_RET,
-1, // CEE_BR_S,
ReaderBaseNS::BrFalseS, // CEE_BRFALSE_S,
ReaderBaseNS::BrTrueS, // CEE_BRTRUE_S,
ReaderBaseNS::BeqS, ReaderBaseNS::BgeS, ReaderBaseNS::BgtS,
ReaderBaseNS::BleS, ReaderBaseNS::BltS, ReaderBaseNS::BneUnS,
ReaderBaseNS::BgeUnS, ReaderBaseNS::BgtUnS, ReaderBaseNS::BleUnS,
ReaderBaseNS::BltUnS,
-1, // CEE_BR,
ReaderBaseNS::BrFalse, // CEE_BRFALSE,
ReaderBaseNS::BrTrue, // CEE_BRTRUE,
ReaderBaseNS::Beq, ReaderBaseNS::Bge, ReaderBaseNS::Bgt,
ReaderBaseNS::Ble, ReaderBaseNS::Blt, ReaderBaseNS::BneUn,
ReaderBaseNS::BgeUn, ReaderBaseNS::BgtUn, ReaderBaseNS::BleUn,
ReaderBaseNS::BltUn,
-1, // CEE_SWITCH,
ReaderBaseNS::LdindI1, // CEE_LDIND_I1,
ReaderBaseNS::LdindU1, // CEE_LDIND_U1,
ReaderBaseNS::LdindI2, // CEE_LDIND_I2,
ReaderBaseNS::LdindU2, // CEE_LDIND_U2,
ReaderBaseNS::LdindI4, // CEE_LDIND_I4,
ReaderBaseNS::LdindU4, // CEE_LDIND_U4,
ReaderBaseNS::LdindI8, // CEE_LDIND_I8,
ReaderBaseNS::LdindI, // CEE_LDIND_I,
ReaderBaseNS::LdindR4, // CEE_LDIND_R4,
ReaderBaseNS::LdindR8, // CEE_LDIND_R8,
ReaderBaseNS::LdindRef, // CEE_LDIND_REF,
ReaderBaseNS::StindRef, // CEE_STIND_REF,
ReaderBaseNS::StindI1, // CEE_STIND_I1,
ReaderBaseNS::StindI2, // CEE_STIND_I2,
ReaderBaseNS::StindI4, // CEE_STIND_I4,
ReaderBaseNS::StindI8, // CEE_STIND_I8,
ReaderBaseNS::StindR4, // CEE_STIND_R4,
ReaderBaseNS::StindR8, // CEE_STIND_R8,
ReaderBaseNS::Add, // CEE_ADD,
ReaderBaseNS::Sub, // CEE_SUB,
ReaderBaseNS::Mul, // CEE_MUL,
ReaderBaseNS::Div, // CEE_DIV,
ReaderBaseNS::DivUn, // CEE_DIV_UN,
ReaderBaseNS::Rem, // CEE_REM,
ReaderBaseNS::RemUn, // CEE_REM_UN,
ReaderBaseNS::And, // CEE_AND,
ReaderBaseNS::Or, // CEE_OR,
ReaderBaseNS::Xor, // CEE_XOR,
ReaderBaseNS::Shl, // CEE_SHL,
ReaderBaseNS::Shr, // CEE_SHR,
ReaderBaseNS::ShrUn, // CEE_SHR_UN,
ReaderBaseNS::Neg, // CEE_NEG,
ReaderBaseNS::Not, // CEE_NOT,
ReaderBaseNS::ConvI1, // CEE_CONV_I1,
ReaderBaseNS::ConvI2, // CEE_CONV_I2,
ReaderBaseNS::ConvI4, // CEE_CONV_I4,
ReaderBaseNS::ConvI8, // CEE_CONV_I8,
ReaderBaseNS::ConvR4, // CEE_CONV_R4,
ReaderBaseNS::ConvR8, // CEE_CONV_R8,
ReaderBaseNS::ConvU4, // CEE_CONV_U4,
ReaderBaseNS::ConvU8, // CEE_CONV_U8,
ReaderBaseNS::CallVirt, // CEE_CALLVIRT,
-1, // CEE_CPOBJ,
-1, // CEE_LDOBJ,
-1, // CEE_LDSTR,
ReaderBaseNS::NewObj, // CEE_NEWOBJ,
-1, // CEE_CASTCLASS,
-1, // CEE_ISINST,
ReaderBaseNS::ConvRUn, // CEE_CONV_R_UN,
-1, // CEE_UNUSED58,
-1, // CEE_UNUSED1,
-1, // CEE_UNBOX,
ReaderBaseNS::Throw, // CEE_THROW,
-1, // CEE_LDFLD,
-1, // CEE_LDFLDA,
-1, // CEE_STFLD,
-1, // CEE_LDSFLD,
-1, // CEE_LDSFLDA,
-1, // CEE_STSFLD,
-1, // CEE_STOBJ,
ReaderBaseNS::ConvOvfI1Un, // CEE_CONV_OVF_I1_UN,
ReaderBaseNS::ConvOvfI2Un, // CEE_CONV_OVF_I2_UN,
ReaderBaseNS::ConvOvfI4Un, // CEE_CONV_OVF_I4_UN,
ReaderBaseNS::ConvOvfI8Un, // CEE_CONV_OVF_I8_UN,
ReaderBaseNS::ConvOvfU1Un, // CEE_CONV_OVF_U1_UN,
ReaderBaseNS::ConvOvfU2Un, // CEE_CONV_OVF_U2_UN,
ReaderBaseNS::ConvOvfU4Un, // CEE_CONV_OVF_U4_UN,
ReaderBaseNS::ConvOvfU8Un, // CEE_CONV_OVF_U8_UN,
ReaderBaseNS::ConvOvfIUn, // CEE_CONV_OVF_I_UN,
ReaderBaseNS::ConvOvfUUn, // CEE_CONV_OVF_U_UN,
-1, // CEE_BOX,
-1, // CEE_NEWARR,
-1, // CEE_LDLEN,
-1, // CEE_LDELEMA,
ReaderBaseNS::LdelemI1, // CEE_LDELEM_I1,
ReaderBaseNS::LdelemU1, // CEE_LDELEM_U1,
ReaderBaseNS::LdelemI2, // CEE_LDELEM_I2,
ReaderBaseNS::LdelemU2, // CEE_LDELEM_U2,
ReaderBaseNS::LdelemI4, // CEE_LDELEM_I4,
ReaderBaseNS::LdelemU4, // CEE_LDELEM_U4,
ReaderBaseNS::LdelemI8, // CEE_LDELEM_I8,
ReaderBaseNS::LdelemI, // CEE_LDELEM_I,
ReaderBaseNS::LdelemR4, // CEE_LDELEM_R4,
ReaderBaseNS::LdelemR8, // CEE_LDELEM_R8,
ReaderBaseNS::LdelemRef, // CEE_LDELEM_REF,
ReaderBaseNS::StelemI, // CEE_STELEM_I,
ReaderBaseNS::StelemI1, // CEE_STELEM_I1,
ReaderBaseNS::StelemI2, // CEE_STELEM_I2,
ReaderBaseNS::StelemI4, // CEE_STELEM_I4,
ReaderBaseNS::StelemI8, // CEE_STELEM_I8,
ReaderBaseNS::StelemR4, // CEE_STELEM_R4,
ReaderBaseNS::StelemR8, // CEE_STELEM_R8,
ReaderBaseNS::StelemRef, // CEE_STELEM_REF,
ReaderBaseNS::Ldelem, // CEE_LDELEM (M2 Generics),
ReaderBaseNS::Stelem, // CEE_STELEM (M2 Generics),
-1, // UNBOX_ANY (M2 Generics),
-1, // CEE_UNUSED5
-1, // CEE_UNUSED6
-1, // CEE_UNUSED7
-1, // CEE_UNUSED8
-1, // CEE_UNUSED9
-1, // CEE_UNUSED10
-1, // CEE_UNUSED11
-1, // CEE_UNUSED12
-1, // CEE_UNUSED13
-1, // CEE_UNUSED14
-1, // CEE_UNUSED15
-1, // CEE_UNUSED16
-1, // CEE_UNUSED17
ReaderBaseNS::ConvOvfI1, // CEE_CONV_OVF_I1,
ReaderBaseNS::ConvOvfU1, // CEE_CONV_OVF_U1,
ReaderBaseNS::ConvOvfI2, // CEE_CONV_OVF_I2,
ReaderBaseNS::ConvOvfU2, // CEE_CONV_OVF_U2,
ReaderBaseNS::ConvOvfI4, // CEE_CONV_OVF_I4,
ReaderBaseNS::ConvOvfU4, // CEE_CONV_OVF_U4,
ReaderBaseNS::ConvOnvI8, // CEE_CONV_OVF_I8,
ReaderBaseNS::ConvOvfU8, // CEE_CONV_OVF_U8,
-1, // CEE_UNUSED50,
-1, // CEE_UNUSED18,
-1, // CEE_UNUSED19,
-1, // CEE_UNUSED20,
-1, // CEE_UNUSED21,
-1, // CEE_UNUSED22,
-1, // CEE_UNUSED23,
-1, // CEE_REFANYVAL,
-1, // CEE_CKFINITE,
-1, // CEE_UNUSED24,
-1, // CEE_UNUSED25,
-1, // CEE_MKREFANY,
-1, // CEE_UNUSED59,
-1, // CEE_UNUSED60,
-1, // CEE_UNUSED61,
-1, // CEE_UNUSED62,
-1, // CEE_UNUSED63,
-1, // CEE_UNUSED64,
-1, // CEE_UNUSED65,
-1, // CEE_UNUSED66,
-1, // CEE_UNUSED67,
-1, // CEE_LDTOKEN,
ReaderBaseNS::ConvU2, // CEE_CONV_U2,
ReaderBaseNS::ConvU1, // CEE_CONV_U1,
ReaderBaseNS::ConvI, // CEE_CONV_I,
ReaderBaseNS::ConvOvfI, // CEE_CONV_OVF_I,
ReaderBaseNS::ConvOvfU, // CEE_CONV_OVF_U,
ReaderBaseNS::AddOvf, // CEE_ADD_OVF,
ReaderBaseNS::AddOvfUn, // CEE_ADD_OVF_UN,
ReaderBaseNS::MulOvf, // CEE_MUL_OVF,
ReaderBaseNS::MulOvfUn, // CEE_MUL_OVF_UN,
ReaderBaseNS::SubOvf, // CEE_SUB_OVF,
ReaderBaseNS::SubOvfUn, // CEE_SUB_OVF_UN,
-1, // CEE_ENDFINALLY,
-1, // CEE_LEAVE,
-1, // CEE_LEAVE_S,
ReaderBaseNS::StindI, // CEE_STIND_I,
ReaderBaseNS::ConvU, // CEE_CONV_U,
-1, // CEE_UNUSED26,
-1, // CEE_UNUSED27,
-1, // CEE_UNUSED28,
-1, // CEE_UNUSED29,
-1, // CEE_UNUSED30,
-1, // CEE_UNUSED31,
-1, // CEE_UNUSED32,
-1, // CEE_UNUSED33,
-1, // CEE_UNUSED34,
-1, // CEE_UNUSED35,
-1, // CEE_UNUSED36,
-1, // CEE_UNUSED37,
-1, // CEE_UNUSED38,
-1, // CEE_UNUSED39,
-1, // CEE_UNUSED40,
-1, // CEE_UNUSED41,
-1, // CEE_UNUSED42,
-1, // CEE_UNUSED43,
-1, // CEE_UNUSED44,
-1, // CEE_UNUSED45,
-1, // CEE_UNUSED46,
-1, // CEE_UNUSED47,
-1, // CEE_UNUSED48,
-1, // CEE_PREFIX7,
-1, // CEE_PREFIX6,
-1, // CEE_PREFIX5,
-1, // CEE_PREFIX4,
-1, // CEE_PREFIX3,
-1, // CEE_PREFIX2,
-1, // CEE_PREFIX1,
-1, // CEE_PREFIXREF,
-1, // CEE_ARGLIST,
ReaderBaseNS::Ceq, // CEE_CEQ,
ReaderBaseNS::Cgt, // CEE_CGT,
ReaderBaseNS::CgtUn, // CEE_CGT_UN,
ReaderBaseNS::Clt, // CEE_CLT,
ReaderBaseNS::CltUn, // CEE_CLT_UN,
-1, // CEE_LDFTN,
-1, // CEE_LDVIRTFTN,
-1, // CEE_UNUSED56,
-1, // CEE_LDARG,
-1, // CEE_LDARGA,
-1, // CEE_STARG,
-1, // CEE_LDLOC,
-1, // CEE_LDLOCA,
-1, // CEE_STLOC,
-1, // CEE_LOCALLOC,
-1, // CEE_UNUSED57,
ReaderBaseNS::EndFilter, // CEE_ENDFILTER,
-1, // CEE_UNALIGNED,
-1, // CEE_VOLATILE,
-1, // CEE_TAILCALL,
-1, // CEE_INITOBJ,
-1, // CEE_CONSTRAINED,
-1, // CEE_CPBLK,
-1, // CEE_INITBLK,
-1, // CEE_UNUSED69,
-1, // CEE_RETHROW,
-1, // CEE_UNUSED51,
-1, // CEE_SIZEOF,
-1, // CEE_REFANYTYPE,
-1, // CEE_READONLY,
-1, // CEE_UNUSED53,
-1, // CEE_UNUSED54,
-1, // CEE_UNUSED55,
-1, // CEE_UNUSED70,
-1, // CEE_ILLEGAL,
};
#endif // MSIL_READER_ENUM_H

883
include/Reader/readerir.h Normal file
Просмотреть файл

@ -0,0 +1,883 @@
//===------------------- include/Reader/readerir.h --------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Declares the GenIR class, which overrides ReaderBase to generate LLVM IR
// from MSIL bytecode.
//
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_IR_H
#define MSIL_READER_IR_H
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/CFG.h"
#include "reader.h"
#include "MSILCJit.h"
class FlowGraphNode : public llvm::BasicBlock {};
struct FlowGraphNodeInfo {
public:
unsigned int StartMSILOffset;
unsigned int EndMSILOffset;
bool IsVisited;
ReaderStack *ReaderStack;
};
class IRNode : public llvm::Value {};
class FlowGraphEdgeList {
public:
FlowGraphEdgeList(){};
virtual void moveNext() = 0;
virtual FlowGraphNode *getSink() = 0;
virtual FlowGraphNode *getSource() = 0;
};
class FlowGraphPredecessorEdgeList : public FlowGraphEdgeList {
public:
FlowGraphPredecessorEdgeList(FlowGraphNode *Fg)
: FlowGraphEdgeList(), PredIterator(Fg), PredIteratorEnd(Fg, true) {}
void moveNext() override { PredIterator++; }
FlowGraphNode *getSink() override {
return (FlowGraphNode *)PredIterator.getUse().get();
}
FlowGraphNode *getSource() override {
return (PredIterator == PredIteratorEnd) ? NULL
: (FlowGraphNode *)*PredIterator;
}
private:
llvm::pred_iterator PredIterator;
llvm::pred_iterator PredIteratorEnd;
};
class FlowGraphSuccessorEdgeList : public FlowGraphEdgeList {
public:
FlowGraphSuccessorEdgeList(FlowGraphNode *Fg)
: FlowGraphEdgeList(), SuccIterator(Fg->getTerminator()),
SuccIteratorEnd(Fg->getTerminator(), true) {}
void moveNext() override { SuccIterator++; }
FlowGraphNode *getSink() override {
return (SuccIterator == SuccIteratorEnd) ? NULL
: (FlowGraphNode *)*SuccIterator;
}
FlowGraphNode *getSource() override {
return (FlowGraphNode *)SuccIterator.getSource();
}
private:
llvm::succ_iterator SuccIterator;
llvm::succ_iterator SuccIteratorEnd;
};
class GenStack : public ReaderStack {
public:
GenStack();
GenStack(int MaxStack, ReaderBase *Reader);
IRNode *pop(void) override;
void push(IRNode *NewVal, IRNode **NewIR) override;
void clearStack(void) override;
bool empty(void) override;
void assertEmpty(void) override;
int depth() override;
// For iteration
IRNode *getIterator(ReaderStackIterator **) override;
IRNode *iteratorGetNext(ReaderStackIterator **) override;
void iteratorReplace(ReaderStackIterator **, IRNode *) override;
IRNode *getReverseIterator(ReaderStackIterator **) override;
IRNode *getReverseIteratorFromDepth(ReaderStackIterator **,
int Depth) override;
IRNode *reverseIteratorGetNext(ReaderStackIterator **) override;
#if !defined(NODEBUG)
void print() override;
#endif
ReaderStack *copy() override;
private:
int Max;
int Top;
IRNode **Stack;
ReaderBase *Reader;
};
class GenIR : public ReaderBase {
public:
GenIR(MSILCJitContext *JitContext,
std::map<CORINFO_CLASS_HANDLE, llvm::Type *> *ClassTypeMap,
std::map<std::tuple<CorInfoType, CORINFO_CLASS_HANDLE, unsigned int>,
llvm::Type *> *ArrayTypeMap,
std::map<CORINFO_FIELD_HANDLE, unsigned int> *FieldIndexMap)
: ReaderBase(JitContext->JitInfo, JitContext->MethodInfo,
JitContext->Flags) {
this->JitContext = JitContext;
this->ClassTypeMap = ClassTypeMap;
this->ArrayTypeMap = ArrayTypeMap;
this->FieldIndexMap = FieldIndexMap;
}
static bool isValidStackType(IRNode *Node);
// ////////////////////////////////////////////////////////////////////
// IL generation methods supplied by the clients
//
// All pure virtual routines must be implemented by the client, non-pure
// virtual routines have a default implementation in the reader, but can
// be overloaded if necessary.
// /////////////////////////////////////////////////////////////////////
// MSIL Routines - client defined routines that are invoked by the reader.
// One will be called for each msil opcode.
unsigned int getPointerByteSize() override {
return TargetPointerSizeInBits / 8;
}
void opcodeDebugPrint(BYTE *Buf, unsigned StartOffset,
unsigned EndOffset) override {
return;
};
// Used for testing, client can force verification.
bool verForceVerification(void) override { return false; };
bool abs(IRNode *Arg1, IRNode **RetVal, IRNode **NewIR) override {
throw NotYetImplementedException("abs");
};
IRNode *argList(IRNode **NewIR) override {
throw NotYetImplementedException("argList");
};
IRNode *instParam(IRNode **NewIR) override {
throw NotYetImplementedException("instParam");
};
IRNode *secretParam(IRNode **NewIR) override {
throw NotYetImplementedException("secretParam");
};
IRNode *thisObj(IRNode **NewIR) override {
throw NotYetImplementedException("thisObj");
};
void boolBranch(ReaderBaseNS::BoolBranchOpcode Opcode, IRNode *Arg1,
IRNode **NewIR) override;
IRNode *binaryOp(ReaderBaseNS::BinaryOpcode Opcode, IRNode *Arg1,
IRNode *Arg2, IRNode **NewIR) override;
void branch(IRNode **NewIR) override;
IRNode *call(ReaderBaseNS::CallOpcode Opcode, mdToken Token,
mdToken ConstraintTypeRef, mdToken LoadFtnToken,
bool HasReadOnlyPrefix, bool HasTailCallPrefix,
bool IsUnmarkedTailCall, unsigned int CurrOffset,
bool *RecursiveTailCall, IRNode **NewIR) override;
IRNode *castOp(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *ObjRefNode,
IRNode **NewIR, CorInfoHelpFunc HelperId) override;
IRNode *ckFinite(IRNode *Arg1, IRNode **NewIR) override {
throw NotYetImplementedException("ckFinite");
};
IRNode *cmp(ReaderBaseNS::CmpOpcode Opode, IRNode *Arg1, IRNode *Arg2,
IRNode **NewIR) override;
void condBranch(ReaderBaseNS::CondBranchOpcode Opcode, IRNode *Arg1,
IRNode *Arg2, IRNode **NewIR) override;
IRNode *conv(ReaderBaseNS::ConvOpcode Opcode, IRNode *Arg1,
IRNode **NewIR) override;
void dup(IRNode *Opr, IRNode **Result1, IRNode **Result2,
IRNode **NewIR) override;
void endFilter(IRNode *Arg1, IRNode **NewIR) override {
throw NotYetImplementedException("endFilter");
};
FlowGraphNode *fgNodeGetNext(FlowGraphNode *FgNode) override;
unsigned int fgNodeGetStartMSILOffset(FlowGraphNode *Fg) override;
void fgNodeSetStartMSILOffset(FlowGraphNode *Fg,
unsigned int Offset) override;
unsigned int fgNodeGetEndMSILOffset(FlowGraphNode *Fg) override;
void fgNodeSetEndMSILOffset(FlowGraphNode *FgNode,
unsigned int Offset) override;
bool fgNodeIsVisited(FlowGraphNode *FgNode) override;
void fgNodeSetVisited(FlowGraphNode *FgNode, bool Visited) override;
void fgNodeSetOperandStack(FlowGraphNode *Fg, ReaderStack *Stack) override;
ReaderStack *fgNodeGetOperandStack(FlowGraphNode *Fg) override;
IRNode *getStaticFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken,
IRNode **NewIR) override;
void jmp(ReaderBaseNS::CallOpcode Opcode, mdToken Token, bool HasThis,
bool HasVarArg, IRNode **NewIR) override {
throw NotYetImplementedException("jmp");
};
void leave(unsigned int TargetOffset, bool IsNonLocal,
bool EndsWithNonLocalGoto, IRNode **NewIR) override;
IRNode *loadArg(unsigned int ArgOrdinal, bool IsJmp, IRNode **NewIR) override;
IRNode *loadLocal(unsigned int ArgOrdinal, IRNode **NewIR) override;
IRNode *loadArgAddress(unsigned int ArgOrdinal, IRNode **NewIR) override;
IRNode *loadLocalAddress(unsigned int LocOrdinal, IRNode **NewIR) override;
IRNode *loadConstantI4(int Constant, IRNode **NewIR) override;
IRNode *loadConstantI8(__int64 Constant, IRNode **NewIR) override;
IRNode *loadConstantI(size_t Constant, IRNode **NewIR) override;
IRNode *loadConstantR4(float Value, IRNode **NewIR) override;
IRNode *loadConstantR8(double Value, IRNode **NewIR) override;
IRNode *loadElem(ReaderBaseNS::LdElemOpcode Opcode,
CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
IRNode *Arg2, IRNode **NewIR) override {
throw NotYetImplementedException("loadElem");
};
IRNode *loadElemA(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
IRNode *Arg2, bool IsReadOnly, IRNode **NewIR) override {
throw NotYetImplementedException("loadElemA");
};
IRNode *loadField(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
ReaderAlignType Alignment, bool IsVolatile,
IRNode **NewIR) override;
IRNode *loadFuncptr(CORINFO_RESOLVED_TOKEN *ResolvedToken,
CORINFO_CALL_INFO *CallInfo, IRNode **NewIR) override {
throw NotYetImplementedException("loadFuncptr");
};
IRNode *loadNull(IRNode **NewIR) override;
IRNode *localAlloc(IRNode *Arg, bool ZeroInit, IRNode **NewIR) override {
throw NotYetImplementedException("localAlloc");
};
IRNode *loadFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Obj,
IRNode **NewIR) override;
IRNode *loadLen(IRNode *Arg1, IRNode **NewIR) override;
bool arrayAddress(CORINFO_SIG_INFO *Sig, IRNode **RetVal,
IRNode **NewIR) override {
throw NotYetImplementedException("arrayAddress");
};
IRNode *loadStringLen(IRNode *Arg1, IRNode **NewIR) override;
IRNode *getTypeFromHandle(IRNode *Arg1, IRNode **NewIR) override {
throw NotYetImplementedException("getTypeFromHandle");
};
IRNode *getValueFromRuntimeHandle(IRNode *Arg1, IRNode **NewIR) override {
throw NotYetImplementedException("getValueFromRuntimeHandle");
};
IRNode *arrayGetDimLength(IRNode *Arg1, IRNode *Arg2,
CORINFO_CALL_INFO *CallInfo,
IRNode **NewIR) override {
throw NotYetImplementedException("arrayGetDimLength");
};
IRNode *loadAndBox(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Addr,
ReaderAlignType AlignmentPrefix, IRNode **NewIR) override {
throw NotYetImplementedException("loadAndBox");
};
IRNode *convertHandle(IRNode *GetTokenNumericNode, CorInfoHelpFunc HelperID,
CORINFO_CLASS_HANDLE ClassHandle,
IRNode **NewIR) override {
throw NotYetImplementedException("convertHandle");
};
void convertTypeHandleLookupHelperToIntrinsic(bool CanCompareToGetType,
IRNode *IR) override {
throw NotYetImplementedException(
"convertTypeHandleLookupHelperToIntrinsic");
};
IRNode *loadStaticField(CORINFO_RESOLVED_TOKEN *FieldToken, bool IsVolatile,
IRNode **NewIR) override;
IRNode *stringLiteral(mdToken Token, void *StringHandle, InfoAccessType Iat,
IRNode **NewIR);
IRNode *loadStr(mdToken Token, IRNode **NewIR) override;
IRNode *loadVirtFunc(IRNode *Arg1, CORINFO_RESOLVED_TOKEN *ResolvedToken,
CORINFO_CALL_INFO *CallInfo, IRNode **NewIR) override {
throw NotYetImplementedException("loadVirtFunc");
};
IRNode *loadPrimitiveType(IRNode *Addr, CorInfoType CorInfoType,
ReaderAlignType Alignment, bool IsVolatile,
bool IsInterfConst, IRNode **NewIR) override;
IRNode *loadNonPrimitiveObj(IRNode *Addr, CORINFO_CLASS_HANDLE ClassHandle,
ReaderAlignType Alignment, bool IsVolatile,
IRNode **NewIR) override {
throw NotYetImplementedException("loadNonPrimitiveObj");
};
IRNode *makeRefAny(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Object,
IRNode **NewIR) override {
throw NotYetImplementedException("makeRefAny");
};
IRNode *newArr(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
IRNode **NewIR) override;
IRNode *newObj(mdToken Token, mdToken LoadFtnToken, unsigned int CurrOffset,
IRNode **NewIR) override;
void pop(IRNode *Opr, IRNode **NewIR) override;
IRNode *refAnyType(IRNode *Arg1, IRNode **NewIR) override {
throw NotYetImplementedException("refAnyType");
};
void rethrow(IRNode **NewIR) override {
throw NotYetImplementedException("rethrow");
};
void returnOpcode(IRNode *Opr, bool SynchronousMethod,
IRNode **NewIR) override;
IRNode *shift(ReaderBaseNS::ShiftOpcode Opcode, IRNode *ShiftAmount,
IRNode *ShiftOperand, IRNode **NewIR) override;
IRNode *sizeofOpcode(CORINFO_RESOLVED_TOKEN *ResolvedToken,
IRNode **NewIR) override;
void storeArg(unsigned int ArgOrdinal, IRNode *Arg1,
ReaderAlignType Alignment, bool IsVolatile,
IRNode **NewIR) override;
void storeElem(ReaderBaseNS::StElemOpcode Opcode,
CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
IRNode *Arg2, IRNode *Arg3, IRNode **NewIR) override {
throw NotYetImplementedException("storeElem");
};
void storeField(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
IRNode *Arg2, ReaderAlignType Alignment, bool IsVolatile,
IRNode **NewIR) override;
void storePrimitiveType(IRNode *Value, IRNode *Addr, CorInfoType CorInfoType,
ReaderAlignType Alignment, bool IsVolatile,
IRNode **NewIR) override {
throw NotYetImplementedException("storePrimitiveType");
};
void storeLocal(unsigned int LocOrdinal, IRNode *Arg1,
ReaderAlignType Alignment, bool IsVolatile,
IRNode **NewIR) override;
void storeStaticField(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1,
bool IsVolatile, IRNode **NewIR) override {
throw NotYetImplementedException("storeStaticField");
};
IRNode *stringGetChar(IRNode *Arg1, IRNode *Arg2, IRNode **NewIR) override;
bool sqrt(IRNode *Arg1, IRNode **RetVal, IRNode **NewIR) override {
throw NotYetImplementedException("sqrt");
};
// The callTarget node is only required on IA64.
bool interlockedIntrinsicBinOp(IRNode *Arg1, IRNode *Arg2, IRNode **RetVal,
CorInfoIntrinsics IntrinsicID,
IRNode **NewIR) override {
throw NotYetImplementedException("interlockedIntrinsicBinOp");
};
bool interlockedCmpXchg(IRNode *Arg1, IRNode *Arg2, IRNode *Arg3,
IRNode **RetVal, CorInfoIntrinsics IntrinsicID,
IRNode **NewIR) override {
throw NotYetImplementedException("interlockedCmpXchg");
};
bool memoryBarrier(IRNode **NewIR) override {
throw NotYetImplementedException("memoryBarrier");
};
void switchOpcode(IRNode *Opr, IRNode **NewIR) override {
throw NotYetImplementedException("switchOpcode");
};
void throwOpcode(IRNode *Arg1, IRNode **NewIR) override;
IRNode *unaryOp(ReaderBaseNS::UnaryOpcode Opcode, IRNode *Arg1,
IRNode **NewIR) override;
IRNode *unbox(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg2,
IRNode **NewIR, bool AndLoad, ReaderAlignType Alignment,
bool IsVolatile) override {
throw NotYetImplementedException("unbox");
};
void nop(IRNode **NewIR) override;
void insertIBCAnnotations() override;
IRNode *insertIBCAnnotation(FlowGraphNode *Node, unsigned int Count,
unsigned int Offset) override {
throw NotYetImplementedException("insertIBCAnnotation");
};
//
// REQUIRED Client Helper Routines.
//
// Base calls to alert client it needs a security check
void methodNeedsSecurityCheck() override {
throw NotYetImplementedException("methodNeedsSecurityCheck");
};
// Base calls to alert client it needs keep generics context alive
void
methodNeedsToKeepAliveGenericsContext(bool KeepGenericsCtxtAlive) override;
// Called to instantiate an empty reader stack.
ReaderStack *createStack(int MaxStack, ReaderBase *Reader) override;
// Called when reader begins processing method.
void readerPrePass(BYTE *Buf, unsigned int NumBytes) override;
// Called between building the flow graph and inserting the IR
void readerMiddlePass(void) override;
// Called when reader has finished processing method.
void readerPostPass(bool IsImportOnly) override;
// Called at the start of block processing
void beginFlowGraphNode(FlowGraphNode *Fg, unsigned int CurrOffset,
bool IsVerifyOnly) override;
// Called at the end of block processing.
void endFlowGraphNode(FlowGraphNode *Fg, unsigned int CurrOffset,
IRNode **NewIR) override;
// Used to maintain operand stack.
void maintainOperandStack(IRNode **Opr1, IRNode **Opr2,
IRNode **NewIR) override;
void assignToSuccessorStackNode(FlowGraphNode *, IRNode *Dst, IRNode *Src,
IRNode **NewIR,
bool *IsMultiByteAssign) override {
throw NotYetImplementedException("assignToSuccessorStackNode");
};
// ReaderStackNode* CopyStackList(ReaderStackNode* stack) =
// 0;
bool typesCompatible(IRNode *Src1, IRNode *Src2) override {
throw NotYetImplementedException("typesCompatible");
};
void removeStackInterference(IRNode **NewIR) override;
void removeStackInterferenceForLocalStore(unsigned int Opcode,
unsigned int Ordinal,
IRNode **NewIR) override;
// Remove all IRNodes from block (for verification error processing.)
void clearCurrentBlock(IRNode **NewIR) override {
throw NotYetImplementedException("clearCurrentBlock");
};
// Notify client of alignment problem
void verifyStaticAlignment(void *Pointer, CorInfoType CorType,
unsigned MinClassAlign) override;
// Allocate temporary (Reader lifetime) memory
void *getTempMemory(unsigned Bytes) override;
// Allocate procedure-lifetime memory
void *getProcMemory(unsigned Bytes) override;
EHRegion *rgnAllocateRegion() override;
EHRegionList *rgnAllocateRegionList() override;
//
// REQUIRED Flow and Region Graph Manipulation Routines
//
FlowGraphNode *fgPrePhase(FlowGraphNode *Fg) override;
void fgPostPhase(void) override;
FlowGraphNode *fgGetHeadBlock(void) override;
FlowGraphNode *fgGetTailBlock(void) override;
unsigned fgGetBlockCount(void) override;
FlowGraphNode *fgNodeGetIDom(FlowGraphNode *Fg) override {
throw NotYetImplementedException("fgNodeGetIDom");
};
IRNode *fgNodeFindStartLabel(FlowGraphNode *Block) override;
BranchList *fgGetLabelBranchList(IRNode *LabelNode) override {
throw NotYetImplementedException("fgGetLabelBranchList");
};
void insertHandlerAnnotation(EHRegion *HandlerRegion) override {
throw NotYetImplementedException("insertHandlerAnnotation");
};
void insertRegionAnnotation(IRNode *RegionStartNode,
IRNode *RegionEndNode) override {
throw NotYetImplementedException("insertRegionAnnotation");
};
void fgAddLabelToBranchList(IRNode *LabelNode, IRNode *BranchNode) override;
void fgAddArc(IRNode *BranchNode, FlowGraphNode *Source,
FlowGraphNode *Sink) override {
throw NotYetImplementedException("fgAddArc");
};
bool fgBlockHasFallThrough(FlowGraphNode *Block) override;
bool fgBlockIsRegionEnd(FlowGraphNode *Block) override {
throw NotYetImplementedException("fgBlockIsRegionEnd");
};
void fgDeleteBlock(FlowGraphNode *Block) override;
void fgDeleteEdge(FlowGraphEdgeList *Arc) override {
throw NotYetImplementedException("fgDeleteEdge");
};
void fgDeleteNodesFromBlock(FlowGraphNode *Block) override;
bool commonTailCallChecks(CORINFO_METHOD_HANDLE DeclaredMethod,
CORINFO_METHOD_HANDLE ExactMethod,
bool IsUnmarkedTailCall, bool SuppressMsgs);
// Returns true iff client considers the JMP recursive and wants a
// loop back-edge rather than a forward edge to the exit label.
bool fgOptRecurse(mdToken Token) override;
// Returns true iff client considers the CALL/JMP recursive and wants a
// loop back-edge rather than a forward edge to the exit label.
bool fgOptRecurse(ReaderCallTargetData *Data) override;
// Returns true if node (the start of a new eh Region) cannot be the start of
// a block.
bool fgEHRegionStartRequiresBlockSplit(IRNode *Node) override {
throw NotYetImplementedException("fgEHRegionStartRequiresBlockSplit");
};
bool fgIsExceptRegionStartNode(IRNode *Node) override {
throw NotYetImplementedException("fgIsExceptRegionStartNode");
};
FlowGraphNode *fgSplitBlock(FlowGraphNode *Block, IRNode *Node) override;
void fgSetBlockToRegion(FlowGraphNode *Block, EHRegion *Region,
unsigned int LastOffset) override {
throw NotYetImplementedException("fgSetBlockToRegion");
};
IRNode *fgMakeBranch(IRNode *LabelNode, IRNode *InsertNode,
unsigned int CurrentOffset, bool IsConditional,
bool IsNominal) override;
IRNode *fgMakeEndFinally(IRNode *InsertNode, unsigned int CurrentOffset,
bool IsLexicalEnd) override;
// turns an unconditional branch to the entry label into a fall-through
// or a branch to the exit label, depending on whether it was a recursive
// jmp or tail.call.
void fgRevertRecursiveBranch(IRNode *BranchNode) override {
throw NotYetImplementedException("fgRevertRecursiveBranch");
};
IRNode *fgMakeSwitch(IRNode *DefaultLabel, IRNode *Insert) override {
throw NotYetImplementedException("fgMakeSwitch");
};
IRNode *fgMakeThrow(IRNode *Insert) override;
IRNode *fgMakeRethrow(IRNode *Insert) override {
throw NotYetImplementedException("fgMakeRethrow");
};
IRNode *fgAddCaseToCaseList(IRNode *SwitchNode, IRNode *LabelNode,
unsigned Element) override {
throw NotYetImplementedException("fgAddCaseToCaseList");
};
void insertEHAnnotationNode(IRNode *InsertionPointNode,
IRNode *InsertNode) override {
throw NotYetImplementedException("insertEHAnnotationNode");
};
FlowGraphNode *makeFlowGraphNode(unsigned int TargetOffset,
EHRegion *Region) override;
void markAsEHLabel(IRNode *LabelNode) override {
throw NotYetImplementedException("markAsEHLabel");
};
IRNode *makeTryEndNode(void) override {
throw NotYetImplementedException("makeTryEndNode");
};
IRNode *makeRegionStartNode(ReaderBaseNS::RegionKind RegionType) override {
throw NotYetImplementedException("makeRegionStartNode");
};
IRNode *makeRegionEndNode(ReaderBaseNS::RegionKind RegionType) override {
throw NotYetImplementedException("makeRegionEndNode");
};
// Allow client to override reader's decision to optimize castclass/isinst
bool disableCastClassOptimization();
// Hook to permit client to record call information returns true if the call
// is a recursive tail
// call and thus should be turned into a loop
bool fgCall(ReaderBaseNS::OPCODE Opcode, mdToken Token,
mdToken ConstraintToken, unsigned MsilOffset, IRNode *Block,
bool CanInline, bool IsTailCall, bool IsUnmarkedTailCall,
bool IsReadOnly) override;
// Hook to permit client to record when calls feed branches
void fgCmp(ReaderBaseNS::OPCODE) override {
throw NotYetImplementedException("fgCmp");
};
// Replace all uses of oldNode in the IR with newNode and delete oldNode.
void replaceFlowGraphNodeUses(FlowGraphNode *OldNode,
FlowGraphNode *NewNode) override;
IRNode *findBlockSplitPointAfterNode(IRNode *Node) override;
IRNode *exitLabel(void) override {
throw NotYetImplementedException("exitLabel");
};
IRNode *entryLabel(void) override {
throw NotYetImplementedException("entryLabel");
};
// Function is passed a try region, and is expected to return the first label
// or instruction
// after the region.
IRNode *findTryRegionEndOfClauses(EHRegion *TryRegion) override {
throw NotYetImplementedException("findTryRegionEndOfClauses");
};
bool isCall(IRNode **NewIR) override {
throw NotYetImplementedException("isCall");
};
bool isRegionStartBlock(FlowGraphNode *Fg) override {
throw NotYetImplementedException("isRegionStartBlock");
};
bool isRegionEndBlock(FlowGraphNode *Fg) override {
throw NotYetImplementedException("isRegionEndBlock");
};
// Create a symbol node that will be used to represent the stack-incoming
// exception object
// upon entry to funclets.
IRNode *makeExceptionObject(IRNode **NewIR) override {
throw NotYetImplementedException("makeExceptionObject");
};
// //////////////////////////////////////////////////////////////////////////
// Client Supplied Helper Routines, required by VOS support
// //////////////////////////////////////////////////////////////////////////
// Asks GenIR to make operand value accessible by address, and return a node
// that references the incoming operand by address.
IRNode *addressOfLeaf(IRNode *Leaf, IRNode **NewIR) override;
IRNode *addressOfValue(IRNode *Leaf, IRNode **NewIR) override;
// Helper callback used by rdrCall to emit call code.
IRNode *genCall(ReaderCallTargetData *CallTargetInfo, CallArgTriple *ArgArray,
unsigned int NumArgs, IRNode **CallNode,
IRNode **NewIR) override;
bool canMakeDirectCall(ReaderCallTargetData *CallTargetData) override;
// Generate call to helper
IRNode *callHelper(CorInfoHelpFunc HelperID, IRNode *Dst, IRNode **NewIR,
IRNode *Arg1 = NULL, IRNode *Arg2 = NULL,
IRNode *Arg3 = NULL, IRNode *Arg4 = NULL,
ReaderAlignType Alignment = Reader_AlignUnknown,
bool IsVolatile = false, bool NoCtor = false,
bool CanMoveUp = false) override;
// Generate special generics helper that might need to insert flow
IRNode *callRuntimeHandleHelper(CorInfoHelpFunc Helper, IRNode *Arg1,
IRNode *Arg2, IRNode *NullCheckArg,
IRNode **NewIR) override {
throw NotYetImplementedException("callRuntimeHandleHelper");
};
IRNode *convertToHelperArgumentType(IRNode *Opr, unsigned int DestinationSize,
IRNode **NewIR) override {
throw NotYetImplementedException("convertToHelperArgumentType");
};
IRNode *genNullCheck(IRNode *Node, IRNode **NewIR) override {
throw NotYetImplementedException("genNullCheck");
};
void
createSym(int Num, bool IsAuto, CorInfoType CorType,
CORINFO_CLASS_HANDLE Class, bool IsPinned,
ReaderSpecialSymbolType SymType = Reader_NotSpecialSymbol) override;
IRNode *derefAddress(IRNode *Address, bool DstIsGCPtr, bool IsConst,
IRNode **NewIR) override {
throw NotYetImplementedException("derefAddress");
};
IRNode *conditionalDerefAddress(IRNode *Address, IRNode **NewIR) override {
throw NotYetImplementedException("conditionalDerefAddress");
};
IRNode *getHelperCallAddress(CorInfoHelpFunc HelperId,
IRNode **NewIR) override;
IRNode *handleToIRNode(mdToken Token, void *EmbedHandle, void *RealHandle,
bool IsIndirect, bool IsReadOnly, bool IsRelocatable,
bool IsCallTarget, IRNode **NewIR,
bool IsFrozenObject = false) override;
// Create an operand that will be used to hold a pointer.
IRNode *makePtrDstGCOperand(bool IsInteriorGC) override {
throw NotYetImplementedException("makePtrDstGCOperand");
};
IRNode *makePtrNode(ReaderPtrType PtrType = Reader_PtrNotGc) override {
throw NotYetImplementedException("makePtrNode");
};
IRNode *makeStackTypeNode(IRNode *Node) override {
throw NotYetImplementedException("makeStackTypeNode");
};
IRNode *makeCallReturnNode(CORINFO_SIG_INFO *Sig, unsigned *HiddenMBParamSize,
GCLayoutStruct **GcLayout) override;
IRNode *makeDirectCallTargetNode(CORINFO_METHOD_HANDLE Method,
void *CodeAddr) override;
// Called once region tree has been built.
void setEHInfo(EHRegion *EhRegionTree, EHRegionList *EhRegionList) override;
void setSequencePoint(unsigned int, ICorDebugInfo::SourceTypes,
IRNode **NewIR) override {
throw NotYetImplementedException("setSequencePoint");
};
bool needSequencePoints() override;
#if !defined(CC_PEVERIFY)
//
// Helper functions for calls
//
// vararg
bool callIsCorVarArgs(IRNode *CallNode);
void canonVarargsCall(IRNode *CallNode, ReaderCallTargetData *CallTargetInfo,
IRNode **NewIR) {
throw NotYetImplementedException("canonVarargsCall");
};
// newobj
bool canonNewObjCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData,
IRNode **OutResult, IRNode **NewIR);
void canonNewArrayCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData,
IRNode **OutResult, IRNode **NewIR);
#endif
// Used to expand multidimensional array access intrinsics
bool arrayGet(CORINFO_SIG_INFO *Sig, IRNode **RetVal,
IRNode **NewIR) override {
throw NotYetImplementedException("arrayGet");
};
bool arraySet(CORINFO_SIG_INFO *Sig, IRNode **NewIR) override {
throw NotYetImplementedException("arraySet");
};
#if !defined(NDEBUG)
void dbDumpFunction(void) override {
throw NotYetImplementedException("dbDumpFunction");
};
void dbPrintIRNode(IRNode *NewIR) override { NewIR->dump(); };
void dbPrintFGNode(FlowGraphNode *Fg) override {
throw NotYetImplementedException("dbPrintFGNode");
};
void dbPrintEHRegion(EHRegion *Eh) override {
throw NotYetImplementedException("dbPrintEHRegion");
};
DWORD dbGetFuncHash(void) override {
throw NotYetImplementedException("dbGetFuncHash");
};
#endif
private:
llvm::Type *getType(CorInfoType Type, CORINFO_CLASS_HANDLE ClassHandle,
bool GetRefClassFields = true);
llvm::Function *getFunction(CORINFO_METHOD_HANDLE Method);
llvm::FunctionType *getFunctionType(CORINFO_METHOD_HANDLE Method);
llvm::Type *getClassType(CORINFO_CLASS_HANDLE ClassHandle,
bool IsRefClass, bool GetRefClassFields);
/// Convert node to the desired type.
/// May reinterpret, truncate, or extend as needed.
/// \p Type - Desired type
/// \p Node - Value to be converted
/// \p IsSigned - Perform sign extension if necessary, otherwise
/// integral values are zero extended
IRNode *convert(llvm::Type *Type, llvm::Value *Node, bool IsSigned);
llvm::Type *binaryOpType(llvm::Type *Type1, llvm::Type *Type2);
IRNode *genPointerAdd(IRNode *Arg1, IRNode *Arg2);
IRNode *genPointerSub(IRNode *Arg1, IRNode *Arg2);
IRNode *getFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken,
CORINFO_FIELD_INFO *FieldInfo, IRNode *Obj,
bool MustNullCheck, IRNode **NewIR);
IRNode *simpleFieldAddress(IRNode *BaseAddress,
CORINFO_RESOLVED_TOKEN *ResolvedToken,
CORINFO_FIELD_INFO *FieldInfo,
IRNode **NewIR) override;
void classifyCmpType(llvm::Type *Ty, unsigned int &Size, bool &IsPointer,
bool &IsFloat);
unsigned int size(CorInfoType CorType);
unsigned int stackSize(CorInfoType CorType);
static bool isSigned(CorInfoType CorType);
llvm::Type *getStackType(CorInfoType CorType);
/// Convert a result to a valid stack type,
/// generally by either reinterpretation or extension.
/// \p Node - Value to be converted
/// \p CorType - additional information needed to determine if
/// Node's type is signed or unsigned
IRNode *convertToStackType(IRNode *Node, CorInfoType CorType);
/// Convert a result from a stack type to the desired type,
/// generally by either reinterpretation or truncation.
/// \p Node - Value to be converted
/// \p CorType - additional information needed to determine if
/// ResultTy is signed or unsigned
/// \p ResultTy - Desired type
IRNode *convertFromStackType(IRNode *Node, CorInfoType CorType,
llvm::Type *ResultTy);
bool objIsThis(IRNode *Obj);
/// Create a new temporary variable that can be
/// used anywhere within the method.
///
/// \p Ty - Type for the new variable.
/// \returns Instruction establishing the variable's location.
llvm::Instruction * createTemporary(llvm::Type * Ty);
IRNode *
loadManagedAddress(const std::vector<llvm::Value *> &UnmanagedAddresses,
unsigned int Index);
llvm::PointerType *getManagedPointerType(llvm::Type *ElementType);
llvm::PointerType *getUnmanagedPointerType(llvm::Type *ElementType);
bool isManagedPointerType(llvm::PointerType *PointerType);
unsigned int argOrdinalToArgIndex(unsigned int ArgOrdinal);
unsigned int argIndexToArgOrdinal(unsigned int ArgIndex);
void makeStore(llvm::Type *Ty, llvm::Value *Address,
llvm::Value *ValueToStore, bool IsVolatile, IRNode **NewIR);
private:
MSILCJitContext *JitContext;
llvm::Function *Function;
llvm::IRBuilder<> *LLVMBuilder;
std::map<CORINFO_CLASS_HANDLE, llvm::Type *> *ClassTypeMap;
std::map<std::tuple<CorInfoType, CORINFO_CLASS_HANDLE, unsigned int>,
llvm::Type *> *ArrayTypeMap;
std::map<CORINFO_FIELD_HANDLE, unsigned int> *FieldIndexMap;
std::map<llvm::BasicBlock *, FlowGraphNodeInfo> FlowGraphInfoMap;
std::vector<llvm::Value *> LocalVars;
std::vector<CorInfoType> LocalVarCorTypes;
std::vector<llvm::Value *> Arguments;
std::vector<CorInfoType> ArgumentCorTypes;
CorInfoType ReturnCorType;
bool HasThis;
bool HasTypeParameter;
bool HasVarargsToken;
llvm::BasicBlock *EntryBlock;
llvm::Instruction *TempInsertionPoint;
unsigned int TargetPointerSizeInBits;
const unsigned int UnmanagedAddressSpace = 0;
const unsigned int ManagedAddressSpace = 1;
};
#endif // MSIL_READER_IR_H

623
include/Reader/vtypeinfo.h Normal file
Просмотреть файл

@ -0,0 +1,623 @@
//===------------------- include/Reader/vtypeinfo.h -------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Type information for an MSIL verifier.
//
//===----------------------------------------------------------------------===//
#ifndef MSIL_READER_TYPEINFO_H
#define MSIL_READER_TYPEINFO_H
#include <string>
class TypeInfo;
typedef TypeInfo VerType;
typedef BYTE VarTypes;
void gVerifyOrReturn(int Cond, char *Message);
void gVerifyOrReturn(int Cond, HRESULT Message);
#define gVerify(cond, Message) gVerifyOrReturn(cond, Message)
enum TITypes {
TI_Error,
TI_Ref,
TI_Struct,
TI_Method,
TI_OnlyEnum = TI_Method, // Enum values above this are completely described by
// the enumeration
TI_Byte,
TI_Short,
TI_Int,
TI_Long,
TI_I,
TI_Float,
TI_Double,
TI_Null,
TI_Ptr,
TI_Count
};
enum VerErrTypeEnum {
LocalError = 1,
GlobalError = 2,
TokenValid = 4,
OffsetValid = 8
};
// going to OR these together
typedef UINT VerErrType;
// Convert the type returned from the VM to a TIType.
#define assertx(x)
#ifdef DEBUG
#define WHENDEBUG(x) x
#define PREFIX_ASSERT(x) assert(x)
#else
#define WHENDEBUG(x)
#define PREFIX_ASSERT(x)
#endif
SELECTANY const TITypes MapTIType[CORINFO_TYPE_COUNT] =
{ // see the definition of enum CorInfoType in file inc/corinfo.h
TI_Error, // CORINFO_TYPE_UNDEF
TI_Error, // CORINFO_TYPE_VOID
TI_Byte, // CORINFO_TYPE_BOOL
TI_Short, // CORINFO_TYPE_CHAR
TI_Byte, // CORINFO_TYPE_BYTE
TI_Byte, // CORINFO_TYPE_UBYTE
TI_Short, // CORINFO_TYPE_SHORT
TI_Short, // CORINFO_TYPE_USHORT
TI_Int, // CORINFO_TYPE_INT
TI_Int, // CORINFO_TYPE_UINT
TI_Long, // CORINFO_TYPE_LONG
TI_Long, // CORINFO_TYPE_ULONG
TI_I, // CORINFO_TYPE_NATIVEINT
TI_I, // CORINFO_TYPE_NATIVEUINT
TI_Float, // CORINFO_TYPE_FLOAT
TI_Double, // CORINFO_TYPE_DOUBLE
TI_Ref, // CORINFO_TYPE_STRING
TI_Ptr, // CORINFO_TYPE_PTR
TI_Error, // CORINFO_TYPE_BYREF
TI_Struct, // CORINFO_TYPE_VALUECLASS
TI_Ref, // CORINFO_TYPE_CLASS
TI_Struct, // CORINFO_TYPE_REFANY
TI_Ref, // CORINFO_TYPE_VAR
};
inline TITypes jitType2TIType(CorInfoType Type) {
// spot check to make certain enumerations have not changed
assertx(MapTIType[CORINFO_TYPE_CLASS] == TI_Ref);
assertx(MapTIType[CORINFO_TYPE_BYREF] == TI_Error);
assertx(MapTIType[CORINFO_TYPE_DOUBLE] == TI_Double);
assertx(MapTIType[CORINFO_TYPE_VALUECLASS] == TI_Struct);
assertx(MapTIType[CORINFO_TYPE_STRING] == TI_Ref);
Type = CorInfoType(Type & CORINFO_TYPE_MASK); // strip off modifiers
assertx(Type < CORINFO_TYPE_COUNT);
assertx(MapTIType[Type] != TI_Error || Type == CORINFO_TYPE_VOID);
return MapTIType[Type];
};
/*****************************************************************************
* Declares the TypeInfo class, which represents the type of an entity on the
* stack, in a local variable or an argument.
*
* Flags: LLLLLLLLLLLLLLLLffffffffffTTTTTT
*
* L = local var # or instance field #
* x = unused
* f = flags
* T = type
*
* The lower bits are used to store the type component, and may be one of:
*
* TI_* (primitive) - see tyelist.h for enumeration (BYTE, SHORT, INT..)
* TI_Ref - OBJREF / ARRAY use m_cls for the type
* (including arrays and null objref)
* TI_Struct - VALUE type, use m_cls for the actual type
*
* NOTE carefully that BYREF info is not stored here. You will never see a
* TI_BYREF in this component. For example, the type component
* of a "byref TI_Int" is TI_FLAG_BYREF | TI_Int.
*
* NOTE carefully that Generic Type Variable info is
* only stored here in part. Values of type "T" (e.g "!0" in ILASM syntax),
* i.e. some generic variable type, appear only when verifying generic
* code. They come in two flavours: unboxed and boxed. Unboxed
* is the norm, e.g. a local, field or argument of type T. Boxed
* values arise from an IL instruction such as "box !0".
* The EE provides type handles for each different type
* variable and the EE's "canCast" operation decides casting
* for boxed type variable. Thus:
*
* (TI_Ref, <type-variable-type-handle>) == boxed type variable
*
* (TI_Ref, <type-variable-type-handle>)
* + TI_FLAG_GENERIC_TYPE_VAR == unboxed type variable
*
* Using TI_Ref for these may seem odd but using TI_Struct means the
* code-generation parts of the importer get confused when they
* can't work out the size, GC-ness etc. of the "struct". So using TI_Ref
* just tricks these backend parts into generating pseudo-trees for
* the generic code we're verifying. These trees then get thrown away
* anyway as we do verification of genreic code in import-only mode.
*
*/
// TI_Count is less than or equal to TI_FLAG_DATA_MASK
#define TI_FLAG_DATA_BITS 6
#define TI_FLAG_DATA_MASK ((1 << TI_FLAG_DATA_BITS) - 1)
// Flag indicating this item is uninitialised
// Note that if UNINIT and BYREF are both set,
// it means byref (uninit x) - i.e. we are pointing to an uninit <something>
#define TI_FLAG_UNINIT_OBJREF 0x00000040
// Flag indicating this item is a byref <something>
#define TI_FLAG_BYREF 0x00000080
// This item is a byref generated using the readonly. prefix
// to a ldelema or Address function on an array type. The
// runtime type check is ignored in these cases, but the
// resulting byref can only be used in order to perform a
// constraint call.
#define TI_FLAG_BYREF_READONLY 0x00000100
// This item contains the 'this' pointer (used for tracking)
#define TI_FLAG_THIS_PTR 0x00001000
// This item is a byref to something which has a permanent home
// (e.g. a static field, or instance field of an object in GC heap, as
// opposed to the stack or a local variable). TI_FLAG_BYREF must also be
// set. This information is useful for tail calls and return byrefs.
//
// Instructions that generate a permanent home byref:
//
// ldelema
// ldflda of a ref object or another permanent home byref
// array element address Get() helper
// call or calli to a method that returns a byref and is verifiable or
// SkipVerify
// dup
// unbox
#define TI_FLAG_BYREF_PERMANENT_HOME 0x00002000
// This is for use when verifying generic code.
// This indicates that the type handle is really an unboxed
// generic type variable (e.g. the result of loading an argument
// of type T in a class List<T>). Without this flag
// the same type handle indicates a boxed generic value,
// e.g. the result of a "box T" instruction.
#define TI_FLAG_GENERIC_TYPE_VAR 0x00004000
// Number of bits local var # is shifted
#define TI_FLAG_LOCAL_VAR_SHIFT 16
#define TI_FLAG_LOCAL_VAR_MASK 0xFFFF0000
// Field info uses the same space as the local info
#define TI_FLAG_FIELD_SHIFT TI_FLAG_LOCAL_VAR_SHIFT
#define TI_FLAG_FIELD_MASK TI_FLAG_LOCAL_VAR_MASK
#define TI_ALL_BYREF_FLAGS \
(TI_FLAG_BYREF | TI_FLAG_BYREF_READONLY | TI_FLAG_BYREF_PERMANENT_HOME)
const CORINFO_CLASS_HANDLE BadClassHandle = (CORINFO_CLASS_HANDLE)-1;
/*****************************************************************************
* A TypeInfo can be one of several types:
* - A primitive type (I4,I8,R4,R8,I)
* - A type (ref, array, value type) (m_cls describes the type)
* - An array (m_cls describes the array type)
* - A byref (byref flag set, otherwise the same as the above),
* - A Function Pointer (m_method)
* - A byref local variable (byref and byref local flags set), can be
* uninitialised
*
* The reason that there can be 2 types of byrefs (general byrefs, and byref
* locals) is that byref locals initially point to uninitialised items.
* Therefore these byrefs must be tracked specialy.
*/
class TypeInfo {
friend class Compiler;
public:
// private:
union {
// Right now m_bits is for debugging,
struct {
TITypes Type : 6;
unsigned UninitObj : 1; // used
unsigned ByRef : 1; // used
unsigned ByRefReadOnly : 1;
unsigned : 3; // unused?
unsigned ThisPtr : 1; // used
unsigned : 1; // unused?
unsigned GenericTypeVar : 1; // used
} Bits;
DWORD Flags;
};
union {
// Valid only for TI_Struct or TI_Ref
CORINFO_CLASS_HANDLE Cls;
// Valid only for type TI_Method
CORINFO_METHOD_HANDLE Method;
};
public:
TypeInfo() : Flags(TI_Error) {
Bits.Type = TI_Error;
WHENDEBUG(Cls = BadClassHandle);
}
TypeInfo(TITypes TiType) {
assertx((TiType >= TI_Byte) && (TiType <= TI_Null));
assertx(TiType <= TI_FLAG_DATA_MASK);
Flags = (DWORD)TiType;
WHENDEBUG(Cls = BadClassHandle);
}
TypeInfo(CorInfoType VarType) {
Flags = (DWORD)jitType2TIType(VarType);
WHENDEBUG(Cls = BadClassHandle);
}
TypeInfo(TITypes TiType, CORINFO_CLASS_HANDLE Cls, bool TypeVar = false) {
assertx(TiType == TI_Struct || TiType == TI_Ref);
assertx(Cls != 0 && Cls != CORINFO_CLASS_HANDLE(0xcccccccc));
Flags = TiType;
if (TypeVar)
Flags |= TI_FLAG_GENERIC_TYPE_VAR;
Cls = Cls;
}
TypeInfo(CORINFO_METHOD_HANDLE Method) {
assertx(Method != 0 && Method != CORINFO_METHOD_HANDLE(0xcccccccc));
Flags = TI_Method;
Method = Method;
}
int operator==(const TypeInfo &Ti) const {
TITypes LType, RType;
LType = getRawType();
RType = Ti.getRawType();
// I interchanges with INT
// except when we are talking about addresses
if (LType != RType) {
if (!isByRef()) {
if (!((LType == TI_I && RType == TI_Int) ||
(LType == TI_Int && RType == TI_I)))
return false;
} else {
return false;
}
}
if (LType == TI_Ptr || RType == TI_Ptr)
return false;
if ((Flags & (TI_FLAG_BYREF | TI_FLAG_BYREF_READONLY |
TI_FLAG_GENERIC_TYPE_VAR | TI_FLAG_UNINIT_OBJREF)) !=
(Ti.Flags & (TI_FLAG_BYREF | TI_FLAG_BYREF_READONLY |
TI_FLAG_GENERIC_TYPE_VAR | TI_FLAG_UNINIT_OBJREF)))
return false;
assertx(TI_Error < TI_OnlyEnum); // TI_Error looks like it needs more than
// enum. This optimises the success case a
// bit
if (LType > TI_OnlyEnum)
return true;
if (LType == TI_Error)
return false; // TI_Error != TI_Error
assertx(Cls != BadClassHandle && Ti.Cls != BadClassHandle);
return Cls == Ti.Cls;
}
static BOOL tiMergeToCommonParent(ICorJitInfo *JitInfo, TypeInfo *PDest,
const TypeInfo *PSrc);
static BOOL tiCompatibleWith(ICorJitInfo *JitInfo, const TypeInfo &Child,
const TypeInfo &Parent);
static BOOL tiMergeCompatibleWith(ICorJitInfo *JitInfo, const TypeInfo &Child,
const TypeInfo &Parent);
/////////////////////////////////////////////////////////////////////////
// Operations
/////////////////////////////////////////////////////////////////////////
void setIsThisPtr() {
Flags |= TI_FLAG_THIS_PTR;
assertx(Bits.ThisPtr);
}
void clearThisPtr() { Flags &= ~(TI_FLAG_THIS_PTR); }
void setIsPermanentHomeByRef() {
assertx(isByRef());
Flags |= TI_FLAG_BYREF_PERMANENT_HOME;
}
void setIsReadonlyByRef() {
assertx(isByRef());
Flags |= TI_FLAG_BYREF_READONLY;
}
// Set that this item is uninitialised.
void setUninitialisedObjRef() {
assertx((isObjRef() && isThisPtr()));
// For now, this is used only to track uninit this ptrs in ctors
Flags |= TI_FLAG_UNINIT_OBJREF;
assertx(Bits.UninitObj);
}
// Set that this item is initialised.
void setInitialisedObjRef() {
assertx((isObjRef() && isThisPtr()));
// For now, this is used only to track uninit this ptrs in ctors
Flags &= ~TI_FLAG_UNINIT_OBJREF;
}
TypeInfo &dereferenceByRef() {
if (!isByRef()) {
Flags = TI_Error;
WHENDEBUG(Cls = BadClassHandle);
}
Flags &= ~(TI_FLAG_THIS_PTR | TI_ALL_BYREF_FLAGS);
return *this;
}
TypeInfo &makeByRef() {
assertx(!isByRef());
Flags &= ~(TI_FLAG_THIS_PTR);
Flags |= TI_FLAG_BYREF;
return *this;
}
// I1,I2 --> I4
// FLOAT --> DOUBLE
// objref, arrays, byrefs, value classes are unchanged
//
TypeInfo &normaliseForStack() {
switch (getType()) {
case TI_Byte:
case TI_Short:
Flags = TI_Int;
break;
case TI_Float:
Flags = TI_Double;
break;
default:
break;
}
return (*this);
}
/////////////////////////////////////////////////////////////////////////
// Getters
/////////////////////////////////////////////////////////////////////////
CORINFO_CLASS_HANDLE getClassHandle() const {
// crusso: not sure about this conditional
if (!isType(TI_Ref) && !isType(TI_Struct))
return 0;
return Cls;
}
CORINFO_CLASS_HANDLE getClassHandleForValueClass() const {
assertx(isType(TI_Struct));
assertx(Cls && Cls != BadClassHandle);
return Cls;
}
CORINFO_CLASS_HANDLE getClassHandleForObjRef() const {
assertx(isType(TI_Ref));
assertx(Cls && Cls != BadClassHandle);
return Cls;
}
CORINFO_METHOD_HANDLE getMethod() const {
assertx(getType() == TI_Method);
return Method;
}
// Get this item's type
// If primitive, returns the primitive type (TI_*)
// If not primitive, returns:
// - TI_Error if a byref anything
// - TI_Ref if a class or array or null or a generic type variable
// - TI_Struct if a value class
TITypes getType() const {
if (Flags & TI_FLAG_BYREF)
return TI_Error;
// objref/array/null (objref), value class, ptr, primitive
return getRawType();
}
TITypes getRawType() const { return (TITypes)(Flags & TI_FLAG_DATA_MASK); }
BOOL isType(TITypes Type) const {
assertx(Type != TI_Error);
return (Flags & (TI_FLAG_DATA_MASK | TI_ALL_BYREF_FLAGS |
TI_FLAG_GENERIC_TYPE_VAR)) == DWORD(Type);
}
// Returns whether this is an objref
BOOL isObjRef() const { return isType(TI_Ref) || isType(TI_Null); }
// Returns whether this is a by-ref
BOOL isByRef() const { return (Flags & TI_FLAG_BYREF); }
// Returns whether this is the this pointer
BOOL isThisPtr() const { return (Flags & TI_FLAG_THIS_PTR); }
BOOL isUnboxedGenericTypeVar() const {
return !isByRef() && (Flags & TI_FLAG_GENERIC_TYPE_VAR);
}
BOOL isReadonlyByRef() const {
return isByRef() && (Flags & TI_FLAG_BYREF_READONLY);
}
BOOL isPermanentHomeByRef() const {
return isByRef() && (Flags & TI_FLAG_BYREF_PERMANENT_HOME);
}
// Returns whether this is a method desc
BOOL isMethod() const { return (getType() == TI_Method); }
// A byref value class is NOT a value class
BOOL isValueClass() const {
// TODO: make a table lookup for efficiency
return (isType(TI_Struct) || isPrimitiveType());
}
// Does not return true for primitives. Will return true for value types that
// behave as primitives
BOOL isValueClassWithClsHnd() const {
if ((getType() == TI_Struct) ||
(Cls && getType() != TI_Ref && getType() != TI_Method &&
getType() != TI_Error)) // necessary because if byref bit is set, we
// return TI_Error)
{
return TRUE;
} else {
return FALSE;
}
}
// Returns whether this is an integer or real number
// NOTE: Use NormaliseToPrimitiveType() if you think you may have a
// System.Int32 etc., because those types are not considered number
// types by this function.
BOOL isNumberType() const {
TITypes Type = getType();
// I1, I2, Boolean, character etc. cannot exist nakedly -
// everything is at least an I4
return (Type == TI_Int || Type == TI_Long || Type == TI_I ||
Type == TI_Double);
}
// Returns whether this is an integer
// NOTE: Use NormaliseToPrimitiveType() if you think you may have a
// System.Int32 etc., because those types are not considered number
// types by this function.
BOOL isIntegerType() const {
TITypes Type = getType();
// I1, I2, Boolean, character etc. cannot exist nakedly -
// everything is at least an I4
return (Type == TI_Int || Type == TI_Long || Type == TI_I);
}
// Returns whether this is a primitive type (not a byref, objref,
// array, null, value class, invalid value)
// May Need to normalise first (m/r/I4 --> I4)
BOOL isPrimitiveType() const {
DWORD Type = getType();
// boolean, char, u1,u2 never appear on the operand stack
return (Type == TI_Byte || Type == TI_Short || Type == TI_Int ||
Type == TI_I || Type == TI_Long || Type == TI_Float ||
Type == TI_Double);
}
// Returns whether this is the null objref
BOOL isNullObjRef() const { return (isType(TI_Null)); }
// must be for a local which is an object type (i.e. has a slot >= 0)
// for primitive locals, use the liveness bitmap instead
// Note that this works if the error is 'Byref'
BOOL isDead() const {
return getRawType() == TI_Error || getRawType() == TI_Ptr;
}
BOOL isUninitialisedObjRef() const { return (Flags & TI_FLAG_UNINIT_OBJREF); }
// In the watch window of the debugger, type tiVarName.ToStaticString()
// to view a string representation of this instance.
void dump() const;
void toString(WCHAR *Buffer, int BufLen, ICorJitInfo *JitInfo,
CORINFO_METHOD_HANDLE Ctxt) const;
std::string toStaticString() const;
private:
// used to make functions that return typeinfo efficient.
TypeInfo(DWORD Flags, CORINFO_CLASS_HANDLE Cls) {
Cls = Cls;
Flags = Flags;
}
friend TypeInfo byRef(const TypeInfo &Ti);
friend TypeInfo dereferenceByRef(const TypeInfo &Ti);
friend TypeInfo normaliseForStack(const TypeInfo &Ti);
};
inline TypeInfo normaliseForStack(const TypeInfo &Ti) {
return TypeInfo(Ti).normaliseForStack();
}
// given ti make a byref to that type.
inline TypeInfo byRef(const TypeInfo &Ti) { return TypeInfo(Ti).makeByRef(); }
// given ti which is a byref, return the type it points at
inline TypeInfo dereferenceByRef(const TypeInfo &Ti) {
return TypeInfo(Ti).dereferenceByRef();
}
BOOL tiCompatibleWith(ICorJitInfo *JitInfo, const TypeInfo &Child,
const TypeInfo &Parent);
BOOL tiMergeToCommonParent(ICorJitInfo *JitInfo, TypeInfo *PDest,
const TypeInfo *PSrc);
BOOL tiEquivalent(ICorJitInfo *JitInfo, const VerType &ChildTarget,
const VerType &ParentTarget);
#ifndef CC_PEVERIFY // peverify OFF - just use the strings for debugging
// purposes
#include "vtypeinfodbg.def"
#else // CC_PEVERIFY on - use hresults and lookup
#include "vtypeinfores.def"
#endif
#endif // MSIL_READER_TYPEINFO_H

Просмотреть файл

@ -0,0 +1,328 @@
//===------------------- include/Reader/vtypeinfo.h -------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Result code literals for Verifier Type Interface
//
//===----------------------------------------------------------------------===//
#define MVER_E_HRESULT "[HRESULT 0x%08X]"
#define MVER_E_OFFSET "[offset 0x%08X]"
#define MVER_E_OPCODE "[opcode %s]"
#define MVER_E_OPERAND "[operand 0x%08X]"
#define MVER_E_TOKEN "[token 0x%08X]"
#define MVER_E_EXCEPT "[exception #0x%08X]"
#define MVER_E_STACK_SLOT "[stack slot 0x%08X]"
#define MVER_E_LOC "[local variable #0x%08X]"
#define MVER_E_LOC_BYNAME "[local variable '%s']"
#define MVER_E_ARG "[argument #0x%08x]"
#define MVER_E_FOUND "[found %s]"
#define MVER_E_EXPECTED "[expected %s]"
#define MVER_E_UNKNOWN_OPCODE "Unknown opcode [0x%08X]."
#define MVER_E_SIG_CALLCONV "Unknown calling convention [0x%08X]."
#define MVER_E_SIG_ELEMTYPE "Unknown ELEMENT_TYPE [0x%08x]."
#define MVER_E_RET_SIG "[return sig]"
#define MVER_E_FIELD_SIG "[field sig]"
#define MVER_E_INTERNAL "Internal error."
#define MVER_E_STACK_TOO_LARGE "Stack is too large."
#define MVER_E_ARRAY_NAME_LONG "Array name is too long."
#define MVER_E_FALLTHRU "fall through end of the method without " \
"returning"
#define MVER_E_TRY_GTEQ_END "try start >= try end"
#define MVER_E_TRYEND_GT_CS "try end > code size"
#define MVER_E_HND_GTEQ_END "handler >= handler end"
#define MVER_E_HNDEND_GT_CS "handler end > code size"
#define MVER_E_TRY_START "Try starts in the middle of an instruction."
#define MVER_E_HND_START "Handler starts in the middle of an " \
"instruction."
#define MVER_E_TRY_OVERLAP "Try block overlap with another block."
#define MVER_E_TRY_EQ_HND_FIL "Try and filter/handler blocks are " \
"equivalent."
#define MVER_E_TRY_SHARE_FIN_FAL "Try shared between finally and fault."
#define MVER_E_HND_OVERLAP "Handler block overlaps with another block."
#define MVER_E_HND_EQ "Handler block is the same as another block."
#define MVER_E_FIL_OVERLAP "Filter block overlaps with another block."
#define MVER_E_FIL_EQ "Filter block is the same as another block."
#define MVER_E_FIL_CONT_TRY "Filter contains try."
#define MVER_E_FIL_CONT_HND "Filter contains handler."
#define MVER_E_FIL_CONT_FIL "Nested filters."
#define MVER_E_FIL_GTEQ_CS "filter >= code size"
#define MVER_E_FIL_START "Filter starts in the middle of an " \
"instruction."
#define MVER_E_FALLTHRU_EXCEP "fallthru the end of an exception block"
#define MVER_E_FALLTHRU_INTO_HND "fallthru into an exception handler"
#define MVER_E_FALLTHRU_INTO_FIL "fallthru into an exception filter"
#define MVER_E_LEAVE "Leave from outside a try or catch block."
#define MVER_E_RETHROW "Rethrow from outside a catch handler."
#define MVER_E_ENDFINALLY "Endfinally from outside a finally handler"
#define MVER_E_ENDFILTER "Endfilter from outside an exception filter "\
"block"
#define MVER_E_ENDFILTER_MISSING "Missing Endfilter."
#define MVER_E_BR_INTO_TRY "Branch into try block."
#define MVER_E_BR_INTO_HND "Branch into exception handler block."
#define MVER_E_BR_INTO_FIL "Branch into exception filter block."
#define MVER_E_BR_OUTOF_TRY "Branch out of try block."
#define MVER_E_BR_OUTOF_HND "Branch out of exception handler block."
#define MVER_E_BR_OUTOF_FIL "Branch out of exception filter block."
#define MVER_E_BR_OUTOF_FIN "Branch out of finally block."
#define MVER_E_RET_FROM_TRY "Return out of try block."
#define MVER_E_RET_FROM_HND "Return out of exception handler block."
#define MVER_E_RET_FROM_FIL "Return out of exception filter block."
#define MVER_E_BAD_JMP_TARGET "jmp / exception into the middle of an " \
"instruction"
#define MVER_E_PATH_LOC "Non-compatible types depending on path."
#define MVER_E_PATH_THIS "Init state for this differs depending on " \
"path."
#define MVER_E_PATH_STACK "Non-compatible types on stack depending on "\
"path."
#define MVER_E_PATH_STACK_DEPTH "Stack depth differs depending on path."
#define MVER_E_THIS "Instance variable (this) missing."
#define MVER_E_THIS_UNINIT_EXCEP "Uninitialized this on entering a try block."
#define MVER_E_THIS_UNINIT_STORE "Store into this when it is uninitialized."
#define MVER_E_THIS_UNINIT_RET "Return from ctor when this is uninitialized."
#define MVER_E_THIS_UNINIT_V_RET "Return from ctor before all fields are " \
"initialized."
#define MVER_E_THIS_UNINIT_BR "Branch back when this is uninitialized."
#define MVER_E_LDFTN_CTOR "ldftn/ldvirtftn not allowed on ctor."
#define MVER_E_STACK_NOT_EQ "Non-compatible types on the stack."
#define MVER_E_STACK_UNEXPECTED "Unexpected type on the stack."
#define MVER_E_STACK_EXCEPTION "Missing stack slot for exception."
#define MVER_E_STACK_OVERFLOW "Stack overflow."
#define MVER_E_STACK_UNDERFLOW "Stack underflow."
#define MVER_E_STACK_EMPTY "Stack empty."
#define MVER_E_STACK_UNINIT "Uninitialized item on stack."
#define MVER_E_STACK_I_I4_I8 "Expected I, I4, or I8 on the stack."
#define MVER_E_STACK_I_I4 "Expected I, or I4 on the stack."
#define MVER_E_STACK_R_R4_R8 "Expected R, R4, or R8 on the stack."
#define MVER_E_STACK_NO_R_I8 "unexpected R, R4, R8, or I8 on the stack."
#define MVER_E_STACK_NUMERIC "Expected numeric type on the stack."
#define MVER_E_STACK_OBJREF "Expected an Objref on the stack."
#define MVER_E_STACK_P_OBJREF "Expected address of an Objref on the stack."
#define MVER_E_STACK_BYREF "Expected Byref on the stack."
#define MVER_E_STACK_METHOD "Expected pointer to function on the stack."
#define MVER_E_STACK_ARRAY_SD "Expected single dimension array on the " \
"stack."
#define MVER_E_STACK_VALCLASS "Expected value type instance on the stack."
#define MVER_E_STACK_P_VALCLASS "Expected address of value type on the stack."
#define MVER_E_STACK_NO_VALCLASS "Unexpected value type instance on the stack."
#define MVER_E_LOC_DEAD "Local variable is unusable at this point."
#define MVER_E_LOC_NUM "Unrecognized local variable number."
#define MVER_E_ARG_NUM "Unrecognized argument number."
#define MVER_E_TOKEN_RESOLVE "Unable to resolve token."
#define MVER_E_TOKEN_TYPE "Unable to resolve type of the token."
#define MVER_E_TOKEN_TYPE_MEMBER "Expected memberRef/memberDef/methodSpec " \
"token."
#define MVER_E_TOKEN_TYPE_FIELD "Expected memberRef/fieldDef token."
#define MVER_E_TOKEN_TYPE_SIG "Expected signature token."
#define MVER_E_UNVERIFIABLE "Instruction can not be verified."
#define MVER_E_LDSTR_OPERAND "Operand does not point to a valid " \
"string ref."
#define MVER_E_RET_PTR_TO_STACK "Return type is BYREF, TypedReference, " \
"ArgHandle, or ArgIterator."
#define MVER_E_RET_VOID "Stack must be empty on return from a " \
"void function."
#define MVER_E_RET_MISSING "Return value missing on the stack."
#define MVER_E_RET_EMPTY "Stack must contain only the return value."
#define MVER_E_RET_UNINIT "Return uninitialized data."
#define MVER_E_ARRAY_ACCESS "Illegal array access."
#define MVER_E_ARRAY_V_STORE "Store non Object type into Object array."
#define MVER_E_ARRAY_SD "Expected single dimension array."
#define MVER_E_ARRAY_SD_PTR "Expected single dimension array of " \
"pointer types."
#define MVER_E_ARRAY_FIELD "Array field access is denied."
#define MVER_E_ARGLIST "Allowed only in vararg methods."
#define MVER_E_VALCLASS "Value type expected."
#define MVER_E_OPEN_DLGT_PROT_ACC "Protected method access through an open " \
"instance delegate is not verifiable."
#define MVER_E_METHOD_ACCESS "Method is not visible."
#define MVER_E_FIELD_ACCESS "Field is not visible."
#define MVER_E_DEAD "Item is unusable at this point."
#define MVER_E_FIELD_STATIC "Expected static field."
#define MVER_E_FIELD_NO_STATIC "Expected non-static field."
#define MVER_E_ADDR "Address of not allowed for this item."
#define MVER_E_ADDR_BYREF "Address of not allowed for byref."
#define MVER_E_ADDR_LITERAL "Address of not allowed for literal field."
#define MVER_E_INITONLY "Can not change initonly field outside " \
"its ctor."
#define MVER_E_WRITE_RVA_STATIC "Can not modify an imaged based (RVA) static"
#define MVER_E_THROW "Can not throw this object."
#define MVER_E_CALLVIRT_VALCLASS "Callvirt on a value type method."
#define MVER_E_CALL_SIG "Call signature mismatch."
#define MVER_E_CALL_STATIC "Static function expected."
#define MVER_E_CTOR "Ctor expected."
#define MVER_E_CTOR_VIRT "Can not use callvirt on ctor."
#define MVER_E_CTOR_OR_SUPER "Only super::ctor or typeof(this)::ctor " \
"allowed here."
#define MVER_E_CTOR_MUL_INIT "Possible call to ctor more than once."
#define MVER_E_SIG "Unrecognized signature."
#define MVER_E_SIG_ARRAY "Can not resolve Array type."
#define MVER_E_SIG_ARRAY_PTR "Array of ELEMENT_TYPE_PTR."
#define MVER_E_SIG_ARRAY_BYREF "Array of ELEMENT_TYPE_BYREF or " \
"ELEMENT_TYPE_TYPEDBYREF."
#define MVER_E_SIG_ELEM_PTR "ELEMENT_TYPE_PTR can not be verified."
#define MVER_E_SIG_VARARG "Unexpected vararg."
#define MVER_E_SIG_VOID "Unexpected Void."
#define MVER_E_SIG_BYREF_BYREF "BYREF of BYREF"
#define MVER_E_CODE_SIZE_ZERO "Code size is zero."
#define MVER_E_BAD_VARARG "Unrecognized use of vararg."
#define MVER_E_TAIL_CALL "Missing call/callvirt/calli."
#define MVER_E_TAIL_BYREF "Can not pass byref to a tail call."
#define MVER_E_TAIL_RET "Missing ret."
#define MVER_E_TAIL_RET_VOID "Void ret type expected for tail call."
#define MVER_E_TAIL_RET_TYPE "Tail call return type not compatible."
#define MVER_E_TAIL_STACK_EMPTY "Stack not empty after tail call."
#define MVER_E_METHOD_END "Method ends in the middle of an instruction."
#define MVER_E_BAD_BRANCH "Branch out of the method."
#define MVER_E_FIN_OVERLAP "Finally handler blocks overlap."
#define MVER_E_LEXICAL_NESTING "Lexical nesting."
#define MVER_E_VOLATILE "Missing ldsfld/stsfld/ldind/stind/ldfld/" \
"stfld/ldobj/stobj/initblk/cpblk."
#define MVER_E_UNALIGNED "Missing ldind/stind/ldfld/stfld/ldobj/" \
"stobj/initblk/cpblk."
#define MVER_E_INNERMOST_FIRST "Innermost exception blocks should be " \
"declared first."
#define MVER_E_CALLI_VIRTUAL "Calli not allowed on virtual methods."
#define MVER_E_CALL_ABSTRACT "Call not allowed on abstract methods."
#define MVER_E_STACK_UNEXP_ARRAY "Unexpected array type on the stack."
#define MVER_E_NOT_IN_GC_HEAP "Value type with NotInGCHeap attribute " \
"being created on the GC heap."
#define MVER_E_TRY_N_EMPTY_STACK "Attempt to enter a try block with " \
"nonempty stack."
#define MVER_E_DLGT_CTOR "Unrecognized arguments for delegate ctor."
#define MVER_E_DLGT_BB "Delegate ctor not allowed at the start of " \
"a basic block when the function pointer " \
"argument is a virtual method."
#define MVER_E_DLGT_PATTERN "Dup, ldvirtftn, newobj delegate::.ctor() " \
"pattern expected (in the same basic block)."
#define MVER_E_DLGT_LDFTN "Ldftn/ldvirtftn instruction required " \
"before call to a delegate ctor."
#define MVER_E_FTN_ABSTRACT "Attempt to load address of an " \
"abstract method."
#define MVER_E_SIG_C_VC "ELEMENT_TYPE_CLASS ValueClass in signature."
#define MVER_E_SIG_VC_C "ELEMENT_TYPE_VALUETYPE non-ValueClass " \
"in signature."
#define MVER_E_BOX_PTR_TO_STACK "Box operation on TypedReference, " \
"ArgHandle, or ArgIterator."
#define MVER_E_SIG_BYREF_TB_AH "Byref of TypedReference, ArgHandle, " \
"or ArgIterator."
#define MVER_E_SIG_ARRAY_TB_AH "Array of TypedReference, ArgHandle, " \
"or ArgIterator."
#define MVER_E_ENDFILTER_STACK "Stack not empty when leaving an " \
"exception filter."
#define MVER_E_DLGT_SIG_I "Unrecognized delegate ctor signature; " \
"expected I."
#define MVER_E_DLGT_SIG_O "Unrecognized delegate ctor signature; " \
"expected Object."
#define MVER_E_RA_PTR_TO_STACK "Mkrefany on TypedReference, ArgHandle, " \
"or ArgIterator."
#define MVER_E_CATCH_VALUE_TYPE "Value type not allowed as catch type."
#define MVER_E_CATCH_BYREF "Byref not allowed as catch type."
#define MVER_E_FIL_PRECEED_HND "filter block should immediately precede " \
"handler block"
#define MVER_E_LDVIRTFTN_STATIC "ldvirtftn on static"
#define MVER_E_CALLVIRT_STATIC "callvirt on static"
#define MVER_E_INITLOCALS "initlocals must be set for verifiable " \
"methods with one or more local variables."
#define MVER_E_BR_TO_EXCEPTION "branch/leave to the beginning of a " \
"catch/filter handler"
#define MVER_E_CALL_CTOR "call to ctor only allowed to initialize " \
"this pointer from within a ctor. Try newobj."
//@GENERICSVER: new generics related error messages
#define MVER_E_VALCLASS_OBJREF_VAR "Value type, objref type or " \
"variable type expected."
#define MVER_E_STACK_P_VALCLASS_OBJREF_VAR "Expected address of value type, " \
"objref type or variable type " \
"on the stack."
#define MVER_E_SIG_VAR_PARAM "Unrecognized type parameter of " \
"enclosing class."
#define MVER_E_SIG_MVAR_PARAM "Unrecognized type parameter of " \
"enclosing method."
#define MVER_E_SIG_VAR_ARG "Unrecognized type argument of " \
"referenced class instantiation."
#define MVER_E_SIG_MVAR_ARG "Unrecognized type argument of " \
"referenced method instantiation."
#define MVER_E_SIG_GENERICINST "Can not resolve generic type."
#define MVER_E_SIG_METHOD_INST "Method instantiation contains non " \
"boxable type arguments."
#define MVER_E_SIG_METHOD_PARENT_INST "Method parent instantiation contains "\
"non boxable type arguments."
#define MVER_E_SIG_FIELD_PARENT_INST "Field parent instantiation contains " \
"non boxable type arguments."
#define MVER_E_CALLCONV_NOT_GENERICINST "Unrecognized calling convention for " \
"an instantiated generic method."
#define MVER_E_TOKEN_BAD_METHOD_SPEC "Unrecognized generic method in " \
"method instantiation."
#define MVER_E_BAD_READONLY_PREFIX "Missing ldelema/callvirt following " \
"readonly. prefix."
#define MVER_E_BAD_CONSTRAINED_PREFIX "Missing callvirt following " \
"constrained. prefix."
#define MVER_E_CIRCULAR_VAR_CONSTRAINTS "Method parent has circular class " \
"type parameter constraints."
#define MVER_E_CIRCULAR_MVAR_CONSTRAINTS "Method has circular method " \
"type parameter constraints."
#define MVER_E_UNSATISFIED_METHOD_INST "Method instantiation has " \
"unsatisfied method type " \
"parameter constraints."
#define MVER_E_UNSATISFIED_METHOD_PARENT_INST "Method parent instantiation " \
"has unsatisfied class type " \
"parameter constraints."
#define MVER_E_UNSATISFIED_FIELD_PARENT_INST "Field parent instantiation " \
"has unsatisfied class type " \
"parameter constraints."
#define MVER_E_UNSATISFIED_BOX_OPERAND "Type operand of box " \
"instruction has unsatisfied " \
"class type parameter " \
"constraints."
#define MVER_E_CONSTRAINED_CALL_WITH_NON_BYREF_THIS "The this argument to a " \
"constrained call must have " \
"byref type."
#define MVER_E_CONSTRAINED_OF_NON_VARIABLE_TYPE "The operand to a constrained "\
"prefix instruction must be a "\
"type parameter."
#define MVER_E_READONLY_UNEXPECTED_CALLEE "The readonly prefix may only "\
"be applied to calls to array "\
"methods returning byrefs."
#define MVER_E_READONLY_ILLEGAL_WRITE "Illegal write to " \
"readonly byref."
#define MVER_E_READONLY_IN_MKREFANY "A readonly byref cannot be " \
"used with mkrefany."
#define MVER_E_UNALIGNED_ALIGNMENT "Alignment specified for " \
"'unaligned' prefix must be " \
"1, 2, or 4"
#define MVER_E_TAILCALL_INSIDE_EH "The tail.call (or calli or " \
"callvirt) instruction cannot "\
"be used to transfer control " \
"out of a try, filter, catch, "\
"or finally block"
#define MVER_E_BACKWARD_BRANCH "Stack height at all points " \
"must be determinable in a " \
"single forward scan of IL"
#define MVER_E_CALL_TO_VTYPE_BASE "Call to base type of " \
"valuetype (which is never a " \
"valuetype)"
#define MVER_E_BAD_PE "Unverifiable PE Header/native stub."
#define MVER_E_BAD_MD "Unrecognized metadata, unable to verify IL."
#define MVER_E_BAD_APPDOMAIN "Unrecognized appdomain pointer."
#define MVER_E_TYPELOAD "Type load failed."
#define MVER_E_PE_LOAD "Module load failed."
#define MVER_E_NEWOBJ_OF_ABSTRACT_CLASS "Can not construct an instance of " \
"abstract class."
#define MVER_E_FIELD_OVERLAP "Accessing type with overlapping fields."
#define MVER_E_LDFTN_NON_FINAL_VIRTUAL "Cannot LDFTN a non-final " \
"virtual method."
#define MVER_E_UNMANAGED_POINTER "Unmanaged pointer is not a verifiable type."
#define MVER_E_THIS_MISMATCH "The 'this' parameter to the call must be " \
"the calling method's 'this' parameter."
#define MVER_E_INITIALIZE_ARRAY_MISSING_TOKEN "Ldtoken instruction required "\
"before call to System.Runtime.CompilerServices.InitializeArray."

Просмотреть файл

@ -0,0 +1,244 @@
//===------------------- include/Reader/vtypeinfo.h -------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Debugging String literal definitions for Verifier Type Interface
//
//===----------------------------------------------------------------------===//
#define MVER_E_HRESULT VER_E_HRESULT
#define MVER_E_OFFSET VER_E_OFFSET
#define MVER_E_OPCODE VER_E_OPCODE
#define MVER_E_OPERAND VER_E_OPERAND
#define MVER_E_TOKEN VER_E_TOKEN
#define MVER_E_EXCEPT VER_E_EXCEPT
#define MVER_E_STACK_SLOT VER_E_STACK_SLOT
#define MVER_E_LOC VER_E_LOC
#define MVER_E_LOC_BYNAME VER_E_LOC_BYNAME
#define MVER_E_ARG VER_E_ARG
#define MVER_E_FOUND VER_E_FOUND
#define MVER_E_EXPECTED VER_E_EXPECTED
#define MVER_E_UNKNOWN_OPCODE VER_E_UNKNOWN_OPCODE
#define MVER_E_SIG_CALLCONV VER_E_SIG_CALLCONV
#define MVER_E_SIG_ELEMTYPE VER_E_SIG_ELEMTYPE
#define MVER_E_RET_SIG VER_E_RET_SIG
#define MVER_E_FIELD_SIG VER_E_FIELD_SIG
#define MVER_E_INTERNAL VER_E_INTERNAL
#define MVER_E_STACK_TOO_LARGE VER_E_STACK_TOO_LARGE
#define MVER_E_ARRAY_NAME_LONG VER_E_ARRAY_NAME_LONG
#define MVER_E_FALLTHRU VER_E_FALLTHRU
#define MVER_E_TRY_GTEQ_END VER_E_TRY_GTEQ_END
#define MVER_E_TRYEND_GT_CS VER_E_TRYEND_GT_CS
#define MVER_E_HND_GTEQ_END VER_E_HND_GTEQ_END
#define MVER_E_HNDEND_GT_CS VER_E_HNDEND_GT_CS
#define MVER_E_TRY_START VER_E_TRY_START
#define MVER_E_HND_START VER_E_HND_START
#define MVER_E_TRY_OVERLAP VER_E_TRY_OVERLAP
#define MVER_E_TRY_EQ_HND_FIL VER_E_TRY_EQ_HND_FIL
#define MVER_E_TRY_SHARE_FIN_FAL VER_E_TRY_SHARE_FIN_FAL
#define MVER_E_HND_OVERLAP VER_E_HND_OVERLAP
#define MVER_E_HND_EQ VER_E_HND_EQ
#define MVER_E_FIL_OVERLAP VER_E_FIL_OVERLAP
#define MVER_E_FIL_EQ VER_E_FIL_EQ
#define MVER_E_FIL_CONT_TRY VER_E_FIL_CONT_TRY
#define MVER_E_FIL_CONT_HND VER_E_FIL_CONT_HND
#define MVER_E_FIL_CONT_FIL VER_E_FIL_CONT_FIL
#define MVER_E_FIL_GTEQ_CS VER_E_FIL_GTEQ_CS
#define MVER_E_FIL_START VER_E_FIL_START
#define MVER_E_FALLTHRU_EXCEP VER_E_FALLTHRU_EXCEP
#define MVER_E_FALLTHRU_INTO_HND VER_E_FALLTHRU_INTO_HND
#define MVER_E_FALLTHRU_INTO_FIL VER_E_FALLTHRU_INTO_FIL
#define MVER_E_LEAVE VER_E_LEAVE
#define MVER_E_RETHROW VER_E_RETHROW
#define MVER_E_ENDFINALLY VER_E_ENDFINALLY
#define MVER_E_ENDFILTER VER_E_ENDFILTER
#define MVER_E_ENDFILTER_MISSING VER_E_ENDFILTER_MISSING
#define MVER_E_BR_INTO_TRY VER_E_BR_INTO_TRY
#define MVER_E_BR_INTO_HND VER_E_BR_INTO_HND
#define MVER_E_BR_INTO_FIL VER_E_BR_INTO_FIL
#define MVER_E_BR_OUTOF_TRY VER_E_BR_OUTOF_TRY
#define MVER_E_BR_OUTOF_HND VER_E_BR_OUTOF_HND
#define MVER_E_BR_OUTOF_FIL VER_E_BR_OUTOF_FIL
#define MVER_E_BR_OUTOF_FIN VER_E_BR_OUTOF_FIN
#define MVER_E_RET_FROM_TRY VER_E_RET_FROM_TRY
#define MVER_E_RET_FROM_HND VER_E_RET_FROM_HND
#define MVER_E_RET_FROM_FIL VER_E_RET_FROM_FIL
#define MVER_E_BAD_JMP_TARGET VER_E_BAD_JMP_TARGET
#define MVER_E_PATH_LOC VER_E_PATH_LOC
#define MVER_E_PATH_THIS VER_E_PATH_THIS
#define MVER_E_PATH_STACK VER_E_PATH_STACK
#define MVER_E_PATH_STACK_DEPTH VER_E_PATH_STACK_DEPTH
#define MVER_E_THIS VER_E_THIS
#define MVER_E_THIS_UNINIT_EXCEP VER_E_THIS_UNINIT_EXCEP
#define MVER_E_THIS_UNINIT_STORE VER_E_THIS_UNINIT_STORE
#define MVER_E_THIS_UNINIT_RET VER_E_THIS_UNINIT_RET
#define MVER_E_THIS_UNINIT_V_RET VER_E_THIS_UNINIT_V_RET
#define MVER_E_THIS_UNINIT_BR VER_E_THIS_UNINIT_BR
#define MVER_E_LDFTN_CTOR VER_E_LDFTN_CTOR
#define MVER_E_STACK_NOT_EQ VER_E_STACK_NOT_EQ
#define MVER_E_STACK_UNEXPECTED VER_E_STACK_UNEXPECTED
#define MVER_E_STACK_EXCEPTION VER_E_STACK_EXCEPTION
#define MVER_E_STACK_OVERFLOW VER_E_STACK_OVERFLOW
#define MVER_E_STACK_UNDERFLOW VER_E_STACK_UNDERFLOW
#define MVER_E_STACK_EMPTY VER_E_STACK_EMPTY
#define MVER_E_STACK_UNINIT VER_E_STACK_UNINIT
#define MVER_E_STACK_I_I4_I8 VER_E_STACK_I_I4_I8
#define MVER_E_STACK_I_I4 VER_E_STACK_I_I4
#define MVER_E_STACK_R_R4_R8 VER_E_STACK_R_R4_R8
#define MVER_E_STACK_NO_R_I8 VER_E_STACK_NO_R_I8
#define MVER_E_STACK_NUMERIC VER_E_STACK_NUMERIC
#define MVER_E_STACK_OBJREF VER_E_STACK_OBJREF
#define MVER_E_STACK_P_OBJREF VER_E_STACK_P_OBJREF
#define MVER_E_STACK_BYREF VER_E_STACK_BYREF
#define MVER_E_STACK_METHOD VER_E_STACK_METHOD
#define MVER_E_STACK_ARRAY_SD VER_E_STACK_ARRAY_SD
#define MVER_E_STACK_VALCLASS VER_E_STACK_VALCLASS
#define MVER_E_STACK_P_VALCLASS VER_E_STACK_P_VALCLASS
#define MVER_E_STACK_NO_VALCLASS VER_E_STACK_NO_VALCLASS
#define MVER_E_LOC_DEAD VER_E_LOC_DEAD
#define MVER_E_LOC_NUM VER_E_LOC_NUM
#define MVER_E_ARG_NUM VER_E_ARG_NUM
#define MVER_E_TOKEN_RESOLVE VER_E_TOKEN_RESOLVE
#define MVER_E_TOKEN_TYPE VER_E_TOKEN_TYPE
#define MVER_E_TOKEN_TYPE_MEMBER VER_E_TOKEN_TYPE_MEMBER
#define MVER_E_TOKEN_TYPE_FIELD VER_E_TOKEN_TYPE_FIELD
#define MVER_E_TOKEN_TYPE_SIG VER_E_TOKEN_TYPE_SIG
#define MVER_E_UNVERIFIABLE VER_E_UNVERIFIABLE
#define MVER_E_LDSTR_OPERAND VER_E_LDSTR_OPERAND
#define MVER_E_RET_PTR_TO_STACK VER_E_RET_PTR_TO_STACK
#define MVER_E_RET_VOID VER_E_RET_VOID
#define MVER_E_RET_MISSING VER_E_RET_MISSING
#define MVER_E_RET_EMPTY VER_E_RET_EMPTY
#define MVER_E_RET_UNINIT VER_E_RET_UNINIT
#define MVER_E_ARRAY_ACCESS VER_E_ARRAY_ACCESS
#define MVER_E_ARRAY_V_STORE VER_E_ARRAY_V_STORE
#define MVER_E_ARRAY_SD VER_E_ARRAY_SD
#define MVER_E_ARRAY_SD_PTR VER_E_ARRAY_SD_PTR
#define MVER_E_ARRAY_FIELD VER_E_ARRAY_FIELD
#define MVER_E_ARGLIST VER_E_ARGLIST
#define MVER_E_VALCLASS VER_E_VALCLASS
#define MVER_E_OPEN_DLGT_PROT_ACC VER_E_OPEN_DLGT_PROT_ACC
#define MVER_E_METHOD_ACCESS VER_E_METHOD_ACCESS
#define MVER_E_FIELD_ACCESS VER_E_FIELD_ACCESS
#define MVER_E_DEAD VER_E_DEAD
#define MVER_E_FIELD_STATIC VER_E_FIELD_STATIC
#define MVER_E_FIELD_NO_STATIC VER_E_FIELD_NO_STATIC
#define MVER_E_ADDR VER_E_ADDR
#define MVER_E_ADDR_BYREF VER_E_ADDR_BYREF
#define MVER_E_ADDR_LITERAL VER_E_ADDR_LITERAL
#define MVER_E_INITONLY VER_E_INITONLY
#define MVER_E_WRITE_RVA_STATIC VER_E_WRITE_RVA_STATIC
#define MVER_E_THROW VER_E_THROW
#define MVER_E_CALLVIRT_VALCLASS VER_E_CALLVIRT_VALCLASS
#define MVER_E_CALL_SIG VER_E_CALL_SIG
#define MVER_E_CALL_STATIC VER_E_CALL_STATIC
#define MVER_E_CTOR VER_E_CTOR
#define MVER_E_CTOR_VIRT VER_E_CTOR_VIRT
#define MVER_E_CTOR_OR_SUPER VER_E_CTOR_OR_SUPER
#define MVER_E_CTOR_MUL_INIT VER_E_CTOR_MUL_INIT
#define MVER_E_SIG VER_E_SIG
#define MVER_E_SIG_ARRAY VER_E_SIG_ARRAY
#define MVER_E_SIG_ARRAY_PTR VER_E_SIG_ARRAY_PTR
#define MVER_E_SIG_ARRAY_BYREF VER_E_SIG_ARRAY_BYREF
#define MVER_E_SIG_ELEM_PTR VER_E_SIG_ELEM_PTR
#define MVER_E_SIG_VARARG VER_E_SIG_VARARG
#define MVER_E_SIG_VOID VER_E_SIG_VOID
#define MVER_E_SIG_BYREF_BYREF VER_E_SIG_BYREF_BYREF
#define MVER_E_CODE_SIZE_ZERO VER_E_CODE_SIZE_ZERO
#define MVER_E_BAD_VARARG VER_E_BAD_VARARG
#define MVER_E_TAIL_CALL VER_E_TAIL_CALL
#define MVER_E_TAIL_BYREF VER_E_TAIL_BYREF
#define MVER_E_TAIL_RET VER_E_TAIL_RET
#define MVER_E_TAIL_RET_VOID VER_E_TAIL_RET_VOID
#define MVER_E_TAIL_RET_TYPE VER_E_TAIL_RET_TYPE
#define MVER_E_TAIL_STACK_EMPTY VER_E_TAIL_STACK_EMPTY
#define MVER_E_METHOD_END VER_E_METHOD_END
#define MVER_E_BAD_BRANCH VER_E_BAD_BRANCH
#define MVER_E_FIN_OVERLAP VER_E_FIN_OVERLAP
#define MVER_E_LEXICAL_NESTING VER_E_LEXICAL_NESTING
#define MVER_E_VOLATILE VER_E_VOLATILE
#define MVER_E_UNALIGNED VER_E_UNALIGNED
#define MVER_E_INNERMOST_FIRST VER_E_INNERMOST_FIRST
#define MVER_E_CALLI_VIRTUAL VER_E_CALLI_VIRTUAL
#define MVER_E_CALL_ABSTRACT VER_E_CALL_ABSTRACT
#define MVER_E_STACK_UNEXP_ARRAY VER_E_STACK_UNEXP_ARRAY
#define MVER_E_NOT_IN_GC_HEAP VER_E_NOT_IN_GC_HEAP
#define MVER_E_TRY_N_EMPTY_STACK VER_E_TRY_N_EMPTY_STACK
#define MVER_E_DLGT_CTOR VER_E_DLGT_CTOR
#define MVER_E_DLGT_BB VER_E_DLGT_BB
#define MVER_E_DLGT_PATTERN VER_E_DLGT_PATTERN
#define MVER_E_DLGT_LDFTN VER_E_DLGT_LDFTN
#define MVER_E_FTN_ABSTRACT VER_E_FTN_ABSTRACT
#define MVER_E_SIG_C_VC VER_E_SIG_C_VC
#define MVER_E_SIG_VC_C VER_E_SIG_VC_C
#define MVER_E_BOX_PTR_TO_STACK VER_E_BOX_PTR_TO_STACK
#define MVER_E_SIG_BYREF_TB_AH VER_E_SIG_BYREF_TB_AH
#define MVER_E_SIG_ARRAY_TB_AH VER_E_SIG_ARRAY_TB_AH
#define MVER_E_ENDFILTER_STACK VER_E_ENDFILTER_STACK
#define MVER_E_DLGT_SIG_I VER_E_DLGT_SIG_I
#define MVER_E_DLGT_SIG_O VER_E_DLGT_SIG_O
#define MVER_E_RA_PTR_TO_STACK VER_E_RA_PTR_TO_STACK
#define MVER_E_CATCH_VALUE_TYPE VER_E_CATCH_VALUE_TYPE
#define MVER_E_CATCH_BYREF VER_E_CATCH_BYREF
#define MVER_E_FIL_PRECEED_HND VER_E_FIL_PRECEED_HND
#define MVER_E_LDVIRTFTN_STATIC VER_E_LDVIRTFTN_STATIC
#define MVER_E_CALLVIRT_STATIC VER_E_CALLVIRT_STATIC
#define MVER_E_INITLOCALS VER_E_INITLOCALS
#define MVER_E_BR_TO_EXCEPTION VER_E_BR_TO_EXCEPTION
#define MVER_E_CALL_CTOR VER_E_CALL_CTOR
#define MVER_E_VALCLASS_OBJREF_VAR VER_E_VALCLASS_OBJREF_VAR
#define MVER_E_STACK_P_VALCLASS_OBJREF_VAR VER_E_STACK_P_VALCLASS_OBJREF_VAR
#define MVER_E_SIG_VAR_PARAM VER_E_SIG_VAR_PARAM
#define MVER_E_SIG_MVAR_PARAM VER_E_SIG_MVAR_PARAM
#define MVER_E_SIG_VAR_ARG VER_E_SIG_VAR_ARG
#define MVER_E_SIG_MVAR_ARG VER_E_SIG_MVAR_ARG
#define MVER_E_SIG_GENERICINST VER_E_SIG_GENERICINST
#define MVER_E_SIG_METHOD_INST VER_E_SIG_METHOD_INST
#define MVER_E_SIG_METHOD_PARENT_INST VER_E_SIG_METHOD_PARENT_INST
#define MVER_E_SIG_FIELD_PARENT_INST VER_E_SIG_FIELD_PARENT_INST
#define MVER_E_CALLCONV_NOT_GENERICINST VER_E_CALLCONV_NOT_GENERICINST
#define MVER_E_TOKEN_BAD_METHOD_SPEC VER_E_TOKEN_BAD_METHOD_SPEC
#define MVER_E_BAD_READONLY_PREFIX VER_E_BAD_READONLY_PREFIX
#define MVER_E_BAD_CONSTRAINED_PREFIX VER_E_BAD_CONSTRAINED_PREFIX
#define MVER_E_CIRCULAR_VAR_CONSTRAINTS VER_E_CIRCULAR_VAR_CONSTRAINTS
#define MVER_E_CIRCULAR_MVAR_CONSTRAINTS VER_E_CIRCULAR_MVAR_CONSTRAINTS
#define MVER_E_UNSATISFIED_METHOD_INST VER_E_UNSATISFIED_METHOD_INST
#define MVER_E_UNSATISFIED_METHOD_PARENT_INST \
VER_E_UNSATISFIED_METHOD_PARENT_INST
#define MVER_E_UNSATISFIED_FIELD_PARENT_INST \
VER_E_UNSATISFIED_FIELD_PARENT_INST
#define MVER_E_UNSATISFIED_BOX_OPERAND VER_E_UNSATISFIED_BOX_OPERAND
#define MVER_E_CONSTRAINED_CALL_WITH_NON_BYREF_THIS \
VER_E_CONSTRAINED_CALL_WITH_NON_BYREF_THIS
#define MVER_E_CONSTRAINED_OF_NON_VARIABLE_TYPE \
VER_E_CONSTRAINED_OF_NON_VARIABLE_TYPE
#define MVER_E_READONLY_UNEXPECTED_CALLEE VER_E_READONLY_UNEXPECTED_CALLEE
#define MVER_E_READONLY_ILLEGAL_WRITE VER_E_READONLY_ILLEGAL_WRITE
#define MVER_E_READONLY_IN_MKREFANY VER_E_READONLY_IN_MKREFANY
#define MVER_E_UNALIGNED_ALIGNMENT VER_E_UNALIGNED_ALIGNMENT
#define MVER_E_TAILCALL_INSIDE_EH VER_E_TAILCALL_INSIDE_EH
#define MVER_E_BACKWARD_BRANCH VER_E_BACKWARD_BRANCH
#define MVER_E_CALL_TO_VTYPE_BASE VER_E_CALL_TO_VTYPE_BASE
#define MVER_E_BAD_PE VER_E_BAD_PE
#define MVER_E_BAD_MD VER_E_BAD_MD
#define MVER_E_BAD_APPDOMAIN VER_E_BAD_APPDOMAIN
#define MVER_E_TYPELOAD VER_E_TYPELOAD
#define MVER_E_PE_LOAD VER_E_PE_LOAD
#define MVER_E_NEWOBJ_OF_ABSTRACT_CLASS VER_E_NEWOBJ_OF_ABSTRACT_CLASS
#define MVER_E_FIELD_OVERLAP VER_E_FIELD_OVERLAP
#define MVER_E_LDFTN_NON_FINAL_VIRTUAL VER_E_LDFTN_NON_FINAL_VIRTUAL
#define MVER_E_UNMANAGED_POINTER VER_E_UNMANAGED_POINTER
#define MVER_E_THIS_MISMATCH VER_E_THIS_MISMATCH
#define MVER_E_INITIALIZE_ARRAY_MISSING_TOKEN \
VER_E_INITIALIZE_ARRAY_MISSING_TOKEN

Просмотреть файл

Просмотреть файл

@ -0,0 +1,395 @@
//===-- StaticContract.h - Static contract annotations --*- C++ -*-===//
//
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// See code:EEStartup#TableOfContents for EE overview
#ifndef MSIL_READER_STATIC_CONTRACT_H
#define MSIL_READER_STATIC_CONTRACT_H
#define SCAN_WIDEN2(x) L ## x
#define SCAN_WIDEN(x) SCAN_WIDEN2(x)
//
// PDB annotations for the static contract analysis tool. These are seperated
// from Contract.h to allow their inclusion in any part of the system.
//
#if defined(_DEBUG) && defined(_TARGET_X86_)
#define METHOD_CANNOT_BE_FOLDED_DEBUG \
static int _noFold = 0; \
_noFold++;
#else
#define METHOD_CANNOT_BE_FOLDED_DEBUG
#endif
#ifdef _TARGET_X86_
//
// currently, only x86 has a static contract analysis tool, so let's not
// bloat the PDBs of all the other architectures too..
//
#define ANNOTATION_TRY_BEGIN __annotation(L"TRY_BEGIN")
#define ANNOTATION_TRY_END __annotation(L"TRY_END")
#define ANNOTATION_HANDLER_BEGIN __annotation(L"HANDLER_BEGIN")
#define ANNOTATION_HANDLER_END __annotation(L"HANDLER_END")
#define ANNOTATION_NOTHROW __annotation(L"NOTHROW")
#define ANNOTATION_CANNOT_TAKE_LOCK __annotation(L"CANNOT_TAKE_LOCK")
#define ANNOTATION_WRAPPER __annotation(L"WRAPPER")
#define ANNOTATION_FAULT __annotation(L"FAULT")
#define ANNOTATION_FORBID_FAULT __annotation(L"FORBID_FAULT")
#define ANNOTATION_COOPERATIVE __annotation(L"MODE_COOPERATIVE")
#define ANNOTATION_MODE_COOPERATIVE __annotation(L"MODE_PREEMPTIVE")
#define ANNOTATION_MODE_ANY __annotation(L"MODE_ANY")
#define ANNOTATION_GC_TRIGGERS __annotation(L"GC_TRIGGERS")
#define ANNOTATION_IGNORE_THROW __annotation(L"THROWS", L"NOTHROW", L"CONDITIONAL_EXEMPT")
#define ANNOTATION_IGNORE_LOCK __annotation(L"CAN_TAKE_LOCK", L"CANNOT_TAKE_LOCK", L"CONDITIONAL_EXEMPT")
#define ANNOTATION_IGNORE_FAULT __annotation(L"FAULT", L"FORBID_FAULT", L"CONDITIONAL_EXEMPT")
#define ANNOTATION_IGNORE_TRIGGER __annotation(L"GC_TRIGGERS", L"GC_NOTRIGGER", L"CONDITIONAL_EXEMPT")
#define ANNOTATION_IGNORE_SO __annotation(L"SO_TOLERANT", L"SO_INTOLERANT", L"CONDITIONAL_EXEMPT")
#define ANNOTATION_VIOLATION(violationmask) __annotation(L"VIOLATION(" L#violationmask L")")
#define ANNOTATION_UNCHECKED(thecheck) __annotation(L"UNCHECKED(" L#thecheck L")")
#define ANNOTATION_MARK_BLOCK_ANNOTATION __annotation(L"MARK")
#define ANNOTATION_USE_BLOCK_ANNOTATION __annotation(L"USE")
#define ANNOTATION_END_USE_BLOCK_ANNOTATION __annotation(L"END_USE")
// here is the plan:
//
// a special holder which implements a violation
//
#define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN __annotation(L"SPECIAL_HOLDER_BEGIN " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_SPECIAL_HOLDER_END __annotation(L"SPECIAL_HOLDER_END")
#define ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT __annotation(L"SPECIAL_HOLDER_DYNAMIC")
#define ANNOTATION_SO_PROBE_BEGIN(probeAmount) __annotation(L"SO_PROBE_BEGIN(" L#probeAmount L")")
#define ANNOTATION_SO_PROBE_END __annotation(L"SO_PROBE_END")
//
// these annotations are all function-name qualified
//
#define ANNOTATION_FN_LEAF __annotation(L"LEAF " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_WRAPPER __annotation(L"WRAPPER " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_THROWS __annotation(L"THROWS " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_NOTHROW __annotation(L"NOTHROW " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_CAN_TAKE_LOCK __annotation(L"CAN_TAKE_LOCK " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_CANNOT_TAKE_LOCK __annotation(L"CANNOT_TAKE_LOCK " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_FAULT __annotation(L"FAULT " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_FORBID_FAULT __annotation(L"FORBID_FAULT " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_GC_TRIGGERS __annotation(L"GC_TRIGGERS " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_GC_NOTRIGGER __annotation(L"GC_NOTRIGGER " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_SO_TOLERANT __annotation(L"SO_TOLERANT " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_SO_INTOLERANT __annotation(L"SO_INTOLERANT " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_SO_NOT_MAINLINE __annotation(L"SO_NOT_MAINLINE " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_MODE_COOPERATIVE __annotation(L"MODE_COOPERATIVE " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_MODE_PREEMPTIVE __annotation(L"MODE_PREEMPTIVE " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_MODE_ANY __annotation(L"MODE_ANY " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_HOST_NOCALLS __annotation(L"HOST_NOCALLS " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_FN_HOST_CALLS __annotation(L"HOST_CALLS " SCAN_WIDEN(__FUNCTION__))
#define ANNOTATION_ENTRY_POINT __annotation(L"SO_EP " SCAN_WIDEN(__FUNCTION__))
// for DacCop
#define ANNOTATION_SUPPORTS_DAC __annotation(L"SUPPORTS_DAC")
#define ANNOTATION_SUPPORTS_DAC_HOST_ONLY __annotation(L"SUPPORTS_DAC_HOST_ONLY")
#ifdef _DEBUG
// @todo jenh: put correct annotation in and fixup the static analysis tool
// This is used to flag debug-only functions that we want to ignore in our static analysis
#define ANNOTATION_DEBUG_ONLY __annotation(L"DBG_ONLY")
#endif
#else // _TARGET_X86_
#define ANNOTATION_TRY_BEGIN { }
#define ANNOTATION_TRY_END { }
#define ANNOTATION_HANDLER_BEGIN { }
#define ANNOTATION_HANDLER_END { }
#define ANNOTATION_NOTHROW { }
#define ANNOTATION_CANNOT_TAKE_LOCK { }
#define ANNOTATION_WRAPPER { }
#define ANNOTATION_FAULT { }
#define ANNOTATION_FORBID_FAULT { }
#define ANNOTATION_COOPERATIVE { }
#define ANNOTATION_MODE_COOPERATIVE { }
#define ANNOTATION_MODE_ANY { }
#define ANNOTATION_GC_TRIGGERS { }
#define ANNOTATION_IGNORE_THROW { }
#define ANNOTATION_IGNORE_LOCK { }
#define ANNOTATION_IGNORE_FAULT { }
#define ANNOTATION_IGNORE_TRIGGER { }
#define ANNOTATION_IGNORE_SO { }
#define ANNOTATION_VIOLATION(violationmask) { }
#define ANNOTATION_UNCHECKED(thecheck) { }
#define ANNOTATION_TRY_MARKER { }
#define ANNOTATION_CATCH_MARKER { }
#define ANNOTATION_FN_HOST_NOCALLS { }
#define ANNOTATION_FN_HOST_CALLS { }
#define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN { }
#define ANNOTATION_SPECIAL_HOLDER_END { }
#define ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT { }
#define ANNOTATION_FN_LEAF { }
#define ANNOTATION_FN_WRAPPER { }
#define ANNOTATION_FN_THROWS { }
#define ANNOTATION_FN_NOTHROW { }
#define ANNOTATION_FN_CAN_TAKE_LOCK { }
#define ANNOTATION_FN_CANNOT_TAKE_LOCK { }
#define ANNOTATION_FN_FAULT { }
#define ANNOTATION_FN_FORBID_FAULT { }
#define ANNOTATION_FN_GC_TRIGGERS { }
#define ANNOTATION_FN_GC_NOTRIGGER { }
#define ANNOTATION_FN_SO_TOLERANT { }
#define ANNOTATION_FN_SO_INTOLERANT { }
#define ANNOTATION_FN_SO_NOT_MAINLINE { }
#define ANNOTATION_FN_MODE_COOPERATIVE { }
#define ANNOTATION_FN_MODE_PREEMPTIVE { }
#define ANNOTATION_FN_MODE_ANY { }
#define ANNOTATION_FN_HOST_NOCALLS { }
#define ANNOTATION_FN_HOST_CALLS { }
#define ANNOTATION_SUPPORTS_DAC { }
#define ANNOTATION_SUPPORTS_DAC_HOST_ONLY { }
#define ANNOTATION_SO_PROBE_BEGIN(probeAmount) { }
#define ANNOTATION_SO_PROBE_END { }
#define ANNOTATION_SO_TOLERANT { }
#define ANNOTATION_SO_INTOLERANT { }
#define ANNOTATION_SO_NOT_MAINLINE { }
#define ANNOTATION_SO_NOT_MAINLINE_BEGIN { }
#define ANNOTATION_SO_NOT_MAINLINE_END { }
#define ANNOTATION_ENTRY_POINT { }
#ifdef _DEBUG
#define ANNOTATION_DEBUG_ONLY { }
#endif
#endif // _TARGET_X86_
#define STATIC_CONTRACT_THROWS ANNOTATION_FN_THROWS
#define STATIC_CONTRACT_NOTHROW ANNOTATION_FN_NOTHROW
#define STATIC_CONTRACT_CAN_TAKE_LOCK ANNOTATION_FN_CAN_TAKE_LOCK
#define STATIC_CONTRACT_CANNOT_TAKE_LOCK ANNOTATION_FN_CANNOT_TAKE_LOCK
#define STATIC_CONTRACT_FAULT ANNOTATION_FN_FAULT
#define STATIC_CONTRACT_FORBID_FAULT ANNOTATION_FN_FORBID_FAULT
#define STATIC_CONTRACT_GC_TRIGGERS ANNOTATION_FN_GC_TRIGGERS
#define STATIC_CONTRACT_GC_NOTRIGGER ANNOTATION_FN_GC_NOTRIGGER
#define STATIC_CONTRACT_HOST_NOCALLS ANNOTATION_FN_HOST_NOCALLS
#define STATIC_CONTRACT_HOST_CALLS ANNOTATION_FN_HOST_CALLS
#define STATIC_CONTRACT_SUPPORTS_DAC ANNOTATION_SUPPORTS_DAC
#define STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY ANNOTATION_SUPPORTS_DAC_HOST_ONLY
#define STATIC_CONTRACT_MODE_COOPERATIVE ANNOTATION_FN_MODE_COOPERATIVE
#define STATIC_CONTRACT_MODE_PREEMPTIVE ANNOTATION_FN_MODE_PREEMPTIVE
#define STATIC_CONTRACT_MODE_ANY ANNOTATION_FN_MODE_ANY
#define STATIC_CONTRACT_LEAF ANNOTATION_FN_LEAF
#define STATIC_CONTRACT_LIMITED_METHOD ANNOTATION_FN_LEAF
#define STATIC_CONTRACT_WRAPPER ANNOTATION_FN_WRAPPER
#ifdef FEATURE_STACK_PROBE // Static SO contracts only required when SO Infrastructure code is present
#define STATIC_CONTRACT_SO_INTOLERANT ANNOTATION_FN_SO_INTOLERANT
#define STATIC_CONTRACT_SO_TOLERANT ANNOTATION_FN_SO_TOLERANT
#define STATIC_CONTRACT_SO_NOT_MAINLINE ANNOTATION_FN_SO_NOT_MAINLINE
#define STATIC_CONTRACT_ENTRY_POINT ANNOTATION_ENTRY_POINT; ANNOTATION_FN_SO_TOLERANT
#else // FEATURE_STACK_PROBE
#define STATIC_CONTRACT_SO_INTOLERANT
#define STATIC_CONTRACT_SO_TOLERANT
#define STATIC_CONTRACT_SO_NOT_MAINLINE
#define STATIC_CONTRACT_ENTRY_POINT
#endif // FEATURE_STACK_PROBE
#ifdef _DEBUG
#define STATIC_CONTRACT_DEBUG_ONLY \
ANNOTATION_DEBUG_ONLY; \
STATIC_CONTRACT_CANNOT_TAKE_LOCK; \
ANNOTATION_VIOLATION(TakesLockViolation); \
ANNOTATION_FN_SO_NOT_MAINLINE;
#else
#define STATIC_CONTRACT_DEBUG_ONLY
#endif
#define STATIC_CONTRACT_VIOLATION(mask) \
ANNOTATION_VIOLATION(mask)
#define SCAN_SCOPE_BEGIN \
METHOD_CANNOT_BE_FOLDED_DEBUG; \
ANNOTATION_FN_SPECIAL_HOLDER_BEGIN;
#define SCAN_SCOPE_END \
METHOD_CANNOT_BE_FOLDED_DEBUG; \
ANNOTATION_SPECIAL_HOLDER_END;
namespace StaticContract
{
struct ScanThrowMarkerStandard
{
__declspec(noinline) ScanThrowMarkerStandard()
{
METHOD_CANNOT_BE_FOLDED_DEBUG;
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_NOTRIGGER;
STATIC_CONTRACT_SO_TOLERANT;
}
};
struct ScanThrowMarkerTerminal
{
__declspec(noinline) ScanThrowMarkerTerminal()
{
METHOD_CANNOT_BE_FOLDED_DEBUG;
}
};
struct ScanThrowMarkerIgnore
{
__declspec(noinline) ScanThrowMarkerIgnore()
{
METHOD_CANNOT_BE_FOLDED_DEBUG;
}
};
}
typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker;
// This is used to annotate code as throwing a terminal exception, and should
// be used immediately before the throw so that infer that it can be inferred
// that the block in which this annotation appears throws unconditionally.
#define SCAN_THROW_MARKER do { ScanThrowMarker __throw_marker; } while (0)
#define SCAN_IGNORE_THROW_MARKER \
typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker
// Terminal exceptions are asynchronous and cannot be included in THROWS contract
// analysis. As such, this uses typedef to reassign the ScanThrowMarker to a
// non-annotating struct so that SCAN does not see the block as throwing.
#define STATIC_CONTRACT_THROWS_TERMINAL \
typedef StaticContract::ScanThrowMarkerTerminal ScanThrowMarker;
#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && defined(FEATURE_STACK_PROBE) && !defined(_TARGET_ARM_) // @ARMTODO
extern void ensureSOIntolerantOK(const char *szFunction, const char *szFile, int lineNum);
extern BOOL (*FpShouldValidateSOToleranceOnThisThread)();
// @todo jenh Is there any checks we can do here?
#define ENSURE_SHOULD_NOT_PROBE_FOR_SO
#define CHECK_IF_SO_INTOLERANT_OK \
ensureSOIntolerantOK(__FUNCTION__, __FILE__, __LINE__);
// Even if we can't have a full-blown contract, we can at least check
// if its ok to run an SO-Intolerant function.
#undef STATIC_CONTRACT_SO_INTOLERANT
#define STATIC_CONTRACT_SO_INTOLERANT \
ANNOTATION_FN_SO_INTOLERANT; \
CHECK_IF_SO_INTOLERANT_OK;
#undef STATIC_CONTRACT_SO_NOT_MAINLINE
#define STATIC_CONTRACT_SO_NOT_MAINLINE \
ENSURE_SHOULD_NOT_PROBE_FOR_SO \
ANNOTATION_FN_SO_NOT_MAINLINE
#else
#define ensureSOIntolerantOK(x,y,z)
#endif
#ifdef _MSC_VER
#define SCAN_IGNORE_THROW typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker; ANNOTATION_IGNORE_THROW
#define SCAN_IGNORE_LOCK ANNOTATION_IGNORE_LOCK
#define SCAN_IGNORE_FAULT ANNOTATION_IGNORE_FAULT
#define SCAN_IGNORE_TRIGGER ANNOTATION_IGNORE_TRIGGER
#define SCAN_IGNORE_SO ANNOTATION_IGNORE_SO
#else
#define SCAN_IGNORE_THROW
#define SCAN_IGNORE_LOCK
#define SCAN_IGNORE_FAULT
#define SCAN_IGNORE_TRIGGER
#define SCAN_IGNORE_SO
#endif
// we use BlockMarker's only for SCAN
#if defined(_DEBUG) && defined(_TARGET_X86_) && !defined(DACCESS_COMPILE)
template <UINT COUNT>
class BlockMarker
{
public:
__declspec(noinline) void markBlock()
{
ANNOTATION_MARK_BLOCK_ANNOTATION;
METHOD_CANNOT_BE_FOLDED_DEBUG;
return;
}
__declspec(noinline) void useMarkedBlockAnnotation()
{
ANNOTATION_USE_BLOCK_ANNOTATION;
METHOD_CANNOT_BE_FOLDED_DEBUG;
return;
}
__declspec(noinline) void endUseMarkedBlockAnnotation()
{
ANNOTATION_END_USE_BLOCK_ANNOTATION;
METHOD_CANNOT_BE_FOLDED_DEBUG;
return;
}
};
#define SCAN_BLOCKMARKER() BlockMarker<__COUNTER__> __blockMarker_onlyOneAllowedPerScope
#define SCAN_BLOCKMARKER_MARK() __blockMarker_onlyOneAllowedPerScope.markBlock()
#define SCAN_BLOCKMARKER_USE() __blockMarker_onlyOneAllowedPerScope.useMarkedBlockAnnotation()
#define SCAN_BLOCKMARKER_END_USE() __blockMarker_onlyOneAllowedPerScope.endUseMarkedBlockAnnotation()
#define SCAN_BLOCKMARKER_N(num) BlockMarker<__COUNTER__> __blockMarker_onlyOneAllowedPerScope##num
#define SCAN_BLOCKMARKER_MARK_N(num) __blockMarker_onlyOneAllowedPerScope##num.markBlock()
#define SCAN_BLOCKMARKER_USE_N(num) __blockMarker_onlyOneAllowedPerScope##num.useMarkedBlockAnnotation()
#define SCAN_BLOCKMARKER_END_USE_N(num) __blockMarker_onlyOneAllowedPerScope##num.endUseMarkedBlockAnnotation()
#define SCAN_EHMARKER() BlockMarker<__COUNTER__> __marker_onlyOneAllowedPerScope
#define SCAN_EHMARKER_TRY() __annotation(L"SCOPE(BLOCK);SCAN_TRY_BEGIN"); __marker_onlyOneAllowedPerScope.markBlock()
#define SCAN_EHMARKER_END_TRY() __annotation(L"SCOPE(BLOCK);SCAN_TRY_END")
#define SCAN_EHMARKER_CATCH() __marker_onlyOneAllowedPerScope.useMarkedBlockAnnotation()
#define SCAN_EHMARKER_END_CATCH() __marker_onlyOneAllowedPerScope.endUseMarkedBlockAnnotation()
#else
#define SCAN_BLOCKMARKER()
#define SCAN_BLOCKMARKER_MARK()
#define SCAN_BLOCKMARKER_USE()
#define SCAN_BLOCKMARKER_END_USE()
#define SCAN_BLOCKMARKER_N(num)
#define SCAN_BLOCKMARKER_MARK_N(num)
#define SCAN_BLOCKMARKER_USE_N(num)
#define SCAN_BLOCKMARKER_END_USE_N(num)
#define SCAN_EHMARKER()
#define SCAN_EHMARKER_TRY()
#define SCAN_EHMARKER_END_TRY()
#define SCAN_EHMARKER_CATCH()
#define SCAN_EHMARKER_END_CATCH()
#endif
//
// @todo remove this... if there really are cases where a function just shouldn't have a contract, then perhaps
// we can add a more descriptive name for it...
//
#define CANNOT_HAVE_CONTRACT __annotation(L"NO_CONTRACT")
#endif // MSIL_READER_STATIC_CONTRACT_H

2542
include/clr/cor.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1235
include/clr/corerror.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1925
include/clr/corhdr.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

3639
include/clr/corinfo.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

604
include/clr/corjit.h Normal file
Просмотреть файл

@ -0,0 +1,604 @@
//===---- CorJit.h - EE / JIT interface ----------*- C++ -*-===//
//
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// See code:EEStartup#TableOfContents for EE overview
/*******************************************************************************
* *
* <STRIP> *
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY *
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR *
* PURPOSE. *
* </STRIP> *
* *
\*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
//
// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the
// JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier
// must be updated. See code:JITEEVersionIdentifier for more information.
//
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _COR_JIT_H_
#define _COR_JIT_H_
#include <corinfo.h>
#define CORINFO_STACKPROBE_DEPTH 256*sizeof(UINT_PTR) // Guaranteed stack until an fcall/unmanaged
// code can set up a frame. Please make sure
// this is less than a page. This is due to
// 2 reasons:
//
// If we need to probe more than a page
// size, we need one instruction per page
// (7 bytes per instruction)
//
// The JIT wants some safe space so it doesn't
// have to put a probe on every call site. It achieves
// this by probing n bytes more than CORINFO_STACKPROBE_DEPTH
// If it hasn't used more than n for its own stuff, it
// can do a call without doing any other probe
//
// In any case, we do really expect this define to be
// small, as setting up a frame should be only pushing
// a couple of bytes on the stack
//
// There is a compile time assert
// in the x86 jit to protect you from this
//
/*****************************************************************************/
// These are error codes returned by CompileMethod
enum CorJitResult
{
// Note that I dont use FACILITY_NULL for the facility number,
// we may want to get a 'real' facility number
CORJIT_OK = NO_ERROR,
CORJIT_BADCODE = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 1),
CORJIT_OUTOFMEM = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 2),
CORJIT_INTERNALERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 3),
CORJIT_SKIPPED = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 4),
CORJIT_RECOVERABLEERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 5),
CORJIT_SKIPMDIL = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 6)
};
/* values for flags in compileMethod */
enum CorJitFlag
{
CORJIT_FLG_SPEED_OPT = 0x00000001,
CORJIT_FLG_SIZE_OPT = 0x00000002,
CORJIT_FLG_DEBUG_CODE = 0x00000004, // generate "debuggable" code (no code-mangling optimizations)
CORJIT_FLG_DEBUG_EnC = 0x00000008, // We are in Edit-n-Continue mode
CORJIT_FLG_DEBUG_INFO = 0x00000010, // generate line and local-var info
CORJIT_FLG_MIN_OPT = 0x00000020, // disable all jit optimizations (not necesarily debuggable code)
CORJIT_FLG_GCPOLL_CALLS = 0x00000040, // Emit calls to JIT_POLLGC for thread suspension.
CORJIT_FLG_MCJIT_BACKGROUND = 0x00000080, // Calling from multicore JIT background thread, do not call JitComplete
#ifdef FEATURE_LEGACYNETCF
CORJIT_FLG_NETCF_QUIRKS = 0x00000100, // Mimic .NetCF JIT's quirks for generated code (currently just inlining heuristics)
#else // FEATURE_LEGACYNETCF
CORJIT_FLG_UNUSED1 = 0x00000100,
#endif // FEATURE_LEGACYNETCF
#if defined(_TARGET_X86_)
CORJIT_FLG_PINVOKE_RESTORE_ESP = 0x00000200, // Restore ESP after returning from inlined PInvoke
CORJIT_FLG_TARGET_P4 = 0x00000400,
CORJIT_FLG_USE_FCOMI = 0x00000800, // Generated code may use fcomi(p) instruction
CORJIT_FLG_USE_CMOV = 0x00001000, // Generated code may use cmov instruction
CORJIT_FLG_USE_SSE2 = 0x00002000, // Generated code may use SSE-2 instructions
#elif defined(_TARGET_AMD64_)
CORJIT_FLG_USE_SSE3_4 = 0x00000200,
CORJIT_FLG_USE_AVX = 0x00000400,
CORJIT_FLG_USE_AVX2 = 0x00000800,
CORJIT_FLG_USE_AVX_512 = 0x00001000,
CORJIT_FLG_FEATURE_SIMD = 0x00002000,
#else // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_)
CORJIT_FLG_UNUSED2 = 0x00000200,
CORJIT_FLG_UNUSED3 = 0x00000400,
CORJIT_FLG_UNUSED4 = 0x00000800,
CORJIT_FLG_UNUSED5 = 0x00001000,
CORJIT_FLG_UNUSED6 = 0x00002000,
#endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_)
#ifdef MDIL
CORJIT_FLG_MDIL = 0x00004000, // Generate MDIL code instead of machine code
#else // MDIL
CORJIT_FLG_UNUSED7 = 0x00004000,
#endif // MDIL
#ifdef MDIL
// Safe to overlap with CORJIT_FLG_MAKEFINALCODE below. Not used by the JIT, used internally by NGen only.
CORJIT_FLG_MINIMAL_MDIL = 0x00008000, // Generate MDIL code suitable for use to bind other assemblies.
// Safe to overlap with CORJIT_FLG_READYTORUN below. Not used by the JIT, used internally by NGen only.
CORJIT_FLG_NO_MDIL = 0x00010000, // Generate an MDIL section but no code or CTL. Not used by the JIT, used internally by NGen only.
#endif // MDIL
#if defined(FEATURE_INTERPRETER)
CORJIT_FLG_MAKEFINALCODE = 0x00008000, // Use the final code generator, i.e., not the interpreter.
#endif // FEATURE_INTERPRETER
#ifdef FEATURE_READYTORUN_COMPILER
CORJIT_FLG_READYTORUN = 0x00010000, // Use version-resilient code generation
#endif
CORJIT_FLG_PROF_ENTERLEAVE = 0x00020000, // Instrument prologues/epilogues
CORJIT_FLG_PROF_REJIT_NOPS = 0x00040000, // Insert NOPs to ensure code is re-jitable
CORJIT_FLG_PROF_NO_PINVOKE_INLINE
= 0x00080000, // Disables PInvoke inlining
CORJIT_FLG_SKIP_VERIFICATION = 0x00100000, // (lazy) skip verification - determined without doing a full resolve. See comment below
CORJIT_FLG_PREJIT = 0x00200000, // jit or prejit is the execution engine.
CORJIT_FLG_RELOC = 0x00400000, // Generate relocatable code
CORJIT_FLG_IMPORT_ONLY = 0x00800000, // Only import the function
CORJIT_FLG_IL_STUB = 0x01000000, // method is an IL stub
CORJIT_FLG_PROCSPLIT = 0x02000000, // JIT should separate code into hot and cold sections
CORJIT_FLG_BBINSTR = 0x04000000, // Collect basic block profile information
CORJIT_FLG_BBOPT = 0x08000000, // Optimize method based on profile information
CORJIT_FLG_FRAMED = 0x10000000, // All methods have an EBP frame
CORJIT_FLG_ALIGN_LOOPS = 0x20000000, // add NOPs before loops to align them at 16 byte boundaries
CORJIT_FLG_PUBLISH_SECRET_PARAM= 0x40000000, // JIT must place stub secret param into local 0. (used by IL stubs)
CORJIT_FLG_GCPOLL_INLINE = 0x80000000, // JIT must inline calls to GCPoll when possible
};
/*****************************************************************************
Here is how CORJIT_FLG_SKIP_VERIFICATION should be interepreted.
Note that even if any method is inlined, it need not be verified.
if (CORJIT_FLG_SKIP_VERIFICATION is passed in to ICorJitCompiler::compileMethod())
{
No verification needs to be done.
Just compile the method, generating unverifiable code if necessary
}
else
{
switch(ICorMethodInfo::isInstantiationOfVerifiedGeneric())
{
case INSTVER_NOT_INSTANTIATION:
//
// Non-generic case, or open generic instantiation
//
switch(canSkipMethodVerification())
{
case CORINFO_VERIFICATION_CANNOT_SKIP:
{
ICorMethodInfo::initConstraintsForVerification(&circularConstraints)
if (circularConstraints)
{
Just emit code to call CORINFO_HELP_VERIFICATION
The IL will not be compiled
}
else
{
Verify the method.
if (unverifiable code is detected)
{
In place of branches with unverifiable code, emit code to call CORINFO_HELP_VERIFICATION
Mark the method (and any of its instantiations) as unverifiable
}
Compile the rest of the verifiable code
}
}
case CORINFO_VERIFICATION_CAN_SKIP:
{
No verification needs to be done.
Just compile the method, generating unverifiable code if necessary
}
case CORINFO_VERIFICATION_RUNTIME_CHECK:
{
ICorMethodInfo::initConstraintsForVerification(&circularConstraints)
if (circularConstraints)
{
Just emit code to call CORINFO_HELP_VERIFICATION
The IL will not be compiled
TODO: This could be changed to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK
}
else
{
Verify the method.
if (unverifiable code is detected)
{
In the prolog, emit code to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK
Mark the method (and any of its instantiations) as unverifiable
}
Compile the method, generating unverifiable code if necessary
}
}
case CORINFO_VERIFICATION_DONT_JIT:
{
ICorMethodInfo::initConstraintsForVerification(&circularConstraints)
if (circularConstraints)
{
Just emit code to call CORINFO_HELP_VERIFICATION
The IL will not be compiled
}
else
{
Verify the method.
if (unverifiable code is detected)
{
Fail the jit
}
}
}
}
case INSTVER_GENERIC_PASSED_VERIFICATION:
{
This cannot ever happen because the VM would pass in CORJIT_FLG_SKIP_VERIFICATION.
}
case INSTVER_GENERIC_FAILED_VERIFICATION:
switch(canSkipMethodVerification())
{
case CORINFO_VERIFICATION_CANNOT_SKIP:
{
This cannot be supported because the compiler does not know which branches should call CORINFO_HELP_VERIFICATION.
The CLR will throw a VerificationException instead of trying to compile this method
}
case CORINFO_VERIFICATION_CAN_SKIP:
{
This cannot ever happen because the CLR would pass in CORJIT_FLG_SKIP_VERIFICATION.
}
case CORINFO_VERIFICATION_RUNTIME_CHECK:
{
No verification needs to be done.
In the prolog, emit code to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK
Compile the method, generating unverifiable code if necessary
}
case CORINFO_VERIFICATION_DONT_JIT:
{
Fail the jit
}
}
}
}
*/
/*****************************************************************************/
// These are flags passed to ICorJitInfo::allocMem
// to guide the memory allocation for the code, readonly data, and read-write data
enum CorJitAllocMemFlag
{
CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will be use the normal alignment
CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned
};
enum CorJitFuncKind
{
CORJIT_FUNC_ROOT, // The main/root function (always id==0)
CORJIT_FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler)
CORJIT_FUNC_FILTER // a funclet associated with an EH filter
};
#if !defined(FEATURE_USE_ASM_GC_WRITE_BARRIERS) && defined(FEATURE_COUNT_GC_WRITE_BARRIERS)
// We have a performance-investigation mode (defined by the FEATURE settings above) in which the
// JIT adds an argument of this enumeration to checked write barrier calls, to classify them.
enum CheckedWriteBarrierKinds {
CWBKind_Unclassified, // Not one of the ones below.
CWBKind_RetBuf, // Store through a return buffer pointer argument.
CWBKind_ByRefArg, // Store through a by-ref argument (not an implicit return buffer).
CWBKind_OtherByRefLocal, // Store through a by-ref local variable.
CWBKind_AddrOfLocal, // Store through the address of a local (arguably a bug that this happens at all).
};
#endif
class ICorJitCompiler;
class ICorJitInfo;
struct IEEMemoryManager;
extern "C" ICorJitCompiler* __stdcall getJit();
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
//
// #JITEEVersionIdentifier
//
// This GUID represents the version of the JIT/EE interface. Any time the interface between the JIT and
// the EE changes (by adding or removing methods to any interface shared between them), this GUID should
// be changed. This is the identifier verified by ICorJitCompiler::getVersionIdentifier().
//
// You can use "uuidgen.exe -s" to generate this value.
//
// **** NOTE TO INTEGRATORS:
//
// If there is a merge conflict here, because the version changed in two different places, you must
// create a **NEW** GUID, not simply choose one or the other!
//
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(SELECTANY)
#define SELECTANY extern __declspec(selectany)
#endif
#if !defined(RYUJIT_CTPBUILD)
// Update this one
SELECTANY const GUID JITEEVersionIdentifier = { /* 9110edd8-8fc3-4e3d-8ac9-12555ff9be9c */
0x9110edd8,
0x8fc3,
0x4e3d,
{ 0x8a, 0xc9, 0x12, 0x55, 0x5f, 0xf9, 0xbe, 0x9c }
};
#else
// Leave this one alone
// We need it to build a .NET 4.5.1 compatible JIT for the RyuJIT CTP releases
SELECTANY const GUID JITEEVersionIdentifier = { /* 72d8f09d-1052-4466-94e9-d095b370bdae */
0x72d8f09d,
0x1052,
0x4466,
{0x94, 0xe9, 0xd0, 0x95, 0xb3, 0x70, 0xbd, 0xae}
};
#endif
// #EEToJitInterface
// ICorJitCompiler is the interface that the EE uses to get IL bytecode converted to native code. Note that
// to accomplish this the JIT has to call back to the EE to get symbolic information. The code:ICorJitInfo
// type passed as 'comp' to compileMethod is the mechanism to get this information. This is often the more
// interesting interface.
//
//
class ICorJitCompiler
{
public:
// compileMethod is the main routine to ask the JIT Compiler to create native code for a method. The
// method to be compiled is passed in the 'info' parameter, and the code:ICorJitInfo is used to allow the
// JIT to resolve tokens, and make any other callbacks needed to create the code. nativeEntry, and
// nativeSizeOfCode are just for convenience because the JIT asks the EE for the memory to emit code into
// (see code:ICorJitInfo.allocMem), so really the EE already knows where the method starts and how big
// it is (in fact, it could be in more than one chunk).
//
// * In the 32 bit jit this is implemented by code:CILJit.compileMethod
// * For the 64 bit jit this is implemented by code:PreJit.compileMethod
//
// Note: Obfuscators that are hacking the JIT depend on this method having __stdcall calling convention
virtual CorJitResult __stdcall compileMethod (
ICorJitInfo *comp, /* IN */
struct CORINFO_METHOD_INFO *info, /* IN */
unsigned /* code:CorJitFlag */ flags, /* IN */
BYTE **nativeEntry, /* OUT */
ULONG *nativeSizeOfCode /* OUT */
) = 0;
// Some JIT compilers (most notably Phoenix), cache information about EE structures from one invocation
// of the compiler to the next. This can be a problem when appdomains are unloaded, as some of this
// cached information becomes stale. The code:ICorJitCompiler.isCacheCleanupRequired is called by the EE
// early first to see if jit needs these notifications, and if so, the EE will call ClearCache is called
// whenever the compiler should abandon its cache (eg on appdomain unload)
virtual void clearCache() = 0;
virtual BOOL isCacheCleanupRequired() = 0;
// Do any appropriate work at process shutdown. Default impl is to do nothing.
virtual void ProcessShutdownWork(ICorStaticInfo* info) {};
// The EE asks the JIT for a "version identifier". This represents the version of the JIT/EE interface.
// If the JIT doesn't implement the same JIT/EE interface expected by the EE (because the JIT doesn't
// return the version identifier that the EE expects), then the EE fails to load the JIT.
//
virtual void getVersionIdentifier(
GUID* versionIdentifier /* OUT */
) = 0;
#ifndef RYUJIT_CTPBUILD
// When the EE loads the System.Numerics.Vectors assembly, it asks the JIT what length (in bytes) of
// SIMD vector it supports as an intrinsic type. Zero means that the JIT does not support SIMD
// intrinsics, so the EE should use the default size (i.e. the size of the IL implementation).
virtual unsigned getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) { return 0; }
#endif // RYUJIT_CTPBUILD
};
//------------------------------------------------------------------------------------------
// #JitToEEInterface
//
// ICorJitInfo is the main interface that the JIT uses to call back to the EE and get information. It is
// the companion to code:ICorJitCompiler#EEToJitInterface. The concrete implementation of this in the
// runtime is the code:CEEJitInfo type. There is also a version of this for the NGEN case.
//
// See code:ICorMethodInfo#EEJitContractDetails for subtle conventions used by this interface.
//
// There is more information on the JIT in the book of the runtime entry
// http://devdiv/sites/CLR/Product%20Documentation/2.0/BookOfTheRuntime/JIT/JIT%20Design.doc
//
class ICorJitInfo : public ICorDynamicInfo
{
public:
// return memory manager that the JIT can use to allocate a regular memory
virtual IEEMemoryManager* getMemoryManager() = 0;
// get a block of memory for the code, readonly data, and read-write data
virtual void allocMem (
ULONG hotCodeSize, /* IN */
ULONG coldCodeSize, /* IN */
ULONG roDataSize, /* IN */
ULONG xcptnsCount, /* IN */
CorJitAllocMemFlag flag, /* IN */
void ** hotCodeBlock, /* OUT */
void ** coldCodeBlock, /* OUT */
void ** roDataBlock /* OUT */
) = 0;
// Reserve memory for the method/funclet's unwind information.
// Note that this must be called before allocMem. It should be
// called once for the main method, once for every funclet, and
// once for every block of cold code for which allocUnwindInfo
// will be called.
//
// This is necessary because jitted code must allocate all the
// memory needed for the unwindInfo at the allocMem call.
// For prejitted code we split up the unwinding information into
// separate sections .rdata and .pdata.
//
virtual void reserveUnwindInfo (
BOOL isFunclet, /* IN */
BOOL isColdCode, /* IN */
ULONG unwindSize /* IN */
) = 0;
// Allocate and initialize the .rdata and .pdata for this method or
// funclet, and get the block of memory needed for the machine-specific
// unwind information (the info for crawling the stack frame).
// Note that allocMem must be called first.
//
// Parameters:
//
// pHotCode main method code buffer, always filled in
// pColdCode cold code buffer, only filled in if this is cold code,
// null otherwise
// startOffset start of code block, relative to appropriate code buffer
// (e.g. pColdCode if cold, pHotCode if hot).
// endOffset end of code block, relative to appropriate code buffer
// unwindSize size of unwind info pointed to by pUnwindBlock
// pUnwindBlock pointer to unwind info
// funcKind type of funclet (main method code, handler, filter)
//
virtual void allocUnwindInfo (
BYTE * pHotCode, /* IN */
BYTE * pColdCode, /* IN */
ULONG startOffset, /* IN */
ULONG endOffset, /* IN */
ULONG unwindSize, /* IN */
BYTE * pUnwindBlock, /* IN */
CorJitFuncKind funcKind /* IN */
) = 0;
// Get a block of memory needed for the code manager information,
// (the info for enumerating the GC pointers while crawling the
// stack frame).
// Note that allocMem must be called first
virtual void * allocGCInfo (
size_t size /* IN */
) = 0;
virtual void yieldExecution() = 0;
// Indicate how many exception handler blocks are to be returned.
// This is guaranteed to be called before any 'setEHinfo' call.
// Note that allocMem must be called before this method can be called.
virtual void setEHcount (
unsigned cEH /* IN */
) = 0;
// Set the values for one particular exception handler block.
//
// Handler regions should be lexically contiguous.
// This is because FinallyIsUnwinding() uses lexicality to
// determine if a "finally" clause is executing.
virtual void setEHinfo (
unsigned EHnumber, /* IN */
const CORINFO_EH_CLAUSE *clause /* IN */
) = 0;
// Level -> fatalError, Level 2 -> Error, Level 3 -> Warning
// Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ...
// returns non-zero if the logging succeeded
virtual BOOL logMsg(unsigned level, const char* fmt, va_list args) = 0;
// do an assert. will return true if the code should retry (DebugBreak)
// returns false, if the assert should be igored.
virtual int doAssert(const char* szFile, int iLine, const char* szExpr) = 0;
virtual void reportFatalError(CorJitResult result) = 0;
struct ProfileBuffer // Also defined here: code:CORBBTPROF_BLOCK_DATA
{
ULONG ILOffset;
ULONG ExecutionCount;
};
// allocate a basic block profile buffer where execution counts will be stored
// for jitted basic blocks.
virtual HRESULT allocBBProfileBuffer (
ULONG count, // The number of basic blocks that we have
ProfileBuffer ** profileBuffer
) = 0;
// get profile information to be used for optimizing the current method. The format
// of the buffer is the same as the format the JIT passes to allocBBProfileBuffer.
virtual HRESULT getBBProfileData(
CORINFO_METHOD_HANDLE ftnHnd,
ULONG * count, // The number of basic blocks that we have
ProfileBuffer ** profileBuffer,
ULONG * numRuns
) = 0;
#if !defined(RYUJIT_CTPBUILD)
// Associates a native call site, identified by its offset in the native code stream, with
// the signature information and method handle the JIT used to lay out the call site. If
// the call site has no signature information (e.g. a helper call) or has no method handle
// (e.g. a CALLI P/Invoke), then null should be passed instead.
virtual void recordCallSite(
ULONG instrOffset, /* IN */
CORINFO_SIG_INFO * callSig, /* IN */
CORINFO_METHOD_HANDLE methodHandle /* IN */
) = 0;
#endif // !defined(RYUJIT_CTPBUILD)
// A relocation is recorded if we are pre-jitting.
// A jump thunk may be inserted if we are jitting
virtual void recordRelocation(
void * location, /* IN */
void * target, /* IN */
WORD fRelocType, /* IN */
WORD slotNum = 0, /* IN */
INT32 addlDelta = 0 /* IN */
) = 0;
virtual WORD getRelocTypeHint(void * target) = 0;
// A callback to identify the range of address known to point to
// compiler-generated native entry points that call back into
// MSIL.
virtual void getModuleNativeEntryPointRange(
void ** pStart, /* OUT */
void ** pEnd /* OUT */
) = 0;
// For what machine does the VM expect the JIT to generate code? The VM
// returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM
// is cross-compiling (such as the case for crossgen), it will return a
// different value than if it was compiling for the host architecture.
//
virtual DWORD getExpectedTargetArchitecture() = 0;
};
/**********************************************************************************/
#endif // _COR_CORJIT_H_

1852
include/clr/ntimage.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

360
include/clr/opcode.def Normal file
Просмотреть файл

@ -0,0 +1,360 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*****************************************************************************
** **
** Opcode.def - COM+ Intrinsic Opcodes and Macros. **
** **
** This is the master table from which all opcode lists **
** are derived. New instructions must be added to this **
** table and generators run to produce the lookup tables **
** used by the interpreter loop. **
** **
** Stack Behaviour is describing the number of 4 byte **
** slots pushed and Poped. **
** **
*****************************************************************************/
#ifndef __OPCODE_DEF_
#define __OPCODE_DEF_
#define MOOT 0x00 // Marks unused second byte when encoding single
#define STP1 0xFE // Prefix code 1 for Standard Map
#define REFPRE 0xFF // Prefix for Reference Code Encoding
#define RESERVED_PREFIX_START 0xF7
#endif
// If the first byte of the standard encoding is 0xFF, then
// the second byte can be used as 1 byte encoding. Otherwise l b b
// the encoding is two bytes. e y y
// n t t
// g e e
// (unused) t
// Canonical Name String Name Stack Behaviour Operand Params Opcode Kind h 1 2 Control Flow
// -------------------------------------------------------------------------------------------------------------------------------------------------------
OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT)
OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK)
OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT)
OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT)
OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT)
OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT)
OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT)
OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT)
OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT)
OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT)
OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT)
OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT)
OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT)
OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT)
OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT)
OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT)
OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT)
OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT)
OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT)
OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT)
OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT)
OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT)
OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT)
OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT)
OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT)
OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT)
OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT)
OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT)
OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT)
OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT)
OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT)
OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT)
OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT)
OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT)
OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT)
OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT)
OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT)
OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT)
OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT)
OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL)
OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL)
OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL)
OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN)
OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH)
OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH)
OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH)
OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH)
OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH)
OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH)
OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH)
OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH)
OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH)
OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH)
OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH)
OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH)
OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH)
OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH)
OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH)
OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH)
OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH)
OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH)
OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH)
OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH)
OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH)
OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH)
OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH)
OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH)
OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH)
OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH)
OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH)
OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT)
OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT)
OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT)
OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT)
OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT)
OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT)
OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT)
OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT)
OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT)
OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT)
OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT)
OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT)
OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT)
OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT)
OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT)
OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT)
OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT)
OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT)
OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT)
OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT)
OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT)
OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT)
OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT)
OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT)
OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT)
OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT)
OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT)
OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT)
OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT)
OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT)
OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT)
OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT)
OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT)
OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT)
OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT)
OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT)
OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT)
OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT)
OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT)
OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT)
OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT)
OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL)
OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT)
OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT)
OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT)
OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL)
OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT)
OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT)
OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT)
OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT)
OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT)
OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT)
OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW)
OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT)
OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT)
OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT)
OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT)
OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT)
OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT)
OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT)
OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT)
OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT)
OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT)
OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT)
OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT)
OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT)
OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT)
OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT)
OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT)
OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT)
OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT)
OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT)
OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT)
OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT)
OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT)
OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT)
OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT)
OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT)
OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT)
OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT)
OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT)
OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT)
OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT)
OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT)
OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT)
OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT)
OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT)
OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT)
OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT)
OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT)
OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT)
OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT)
OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT)
OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT)
OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT)
OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT)
OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT)
OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT)
OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT)
OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT)
OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT)
OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT)
OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT)
OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT)
OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT)
OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT)
OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT)
OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT)
OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT)
OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT)
OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT)
OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT)
OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT)
OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT)
OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT)
OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT)
OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT)
OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT)
OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT)
OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT)
OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT)
OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT)
OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT)
OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT)
OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT)
OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT)
OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT)
OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT)
OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT)
OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT)
OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT)
OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT)
OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT)
OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT)
OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT)
OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT)
OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT)
OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT)
OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT)
OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT)
OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT)
OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT)
OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT)
OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT)
OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT)
OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT)
OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT)
OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT)
OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT)
OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT)
OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN)
OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH)
OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH)
OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT)
OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT)
OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT)
OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT)
OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT)
OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT)
OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT)
OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT)
OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT)
OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT)
OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT)
OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT)
OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT)
OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT)
OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT)
OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT)
OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT)
OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT)
OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT)
OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT)
OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT)
OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT)
OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT)
OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT)
OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT)
OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META)
OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META)
OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META)
OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META)
OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META)
OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META)
OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META)
OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META)
OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT)
OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT)
OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT)
OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT)
OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT)
OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT)
OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT)
OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT)
OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT)
OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT)
OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT)
OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT)
OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT)
OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT)
OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT)
OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT)
OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT)
OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN)
OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META)
OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META)
OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META)
OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT)
OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META)
OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT)
OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT)
OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT)
OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW)
OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT)
OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT)
OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT)
OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META)
OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT)
OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT)
OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT)
OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT)
// These are not real opcodes, but they are handy internally in the EE
OPDEF(CEE_ILLEGAL, "illegal", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META)
OPDEF(CEE_MACRO_END, "endmac", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META)
OPDEF(CEE_CODE_LABEL, "codelabel", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META)
#ifndef OPALIAS
#define _OPALIAS_DEFINED_
#define OPALIAS(canonicalName, stringName, realOpcode)
#endif
OPALIAS(CEE_BRNULL, "brnull", CEE_BRFALSE)
OPALIAS(CEE_BRNULL_S, "brnull.s", CEE_BRFALSE_S)
OPALIAS(CEE_BRZERO, "brzero", CEE_BRFALSE)
OPALIAS(CEE_BRZERO_S, "brzero.s", CEE_BRFALSE_S)
OPALIAS(CEE_BRINST, "brinst", CEE_BRTRUE)
OPALIAS(CEE_BRINST_S, "brinst.s", CEE_BRTRUE_S)
OPALIAS(CEE_LDIND_U8, "ldind.u8", CEE_LDIND_I8)
OPALIAS(CEE_LDELEM_U8, "ldelem.u8", CEE_LDELEM_I8)
OPALIAS(CEE_LDELEM_ANY, "ldelem.any", CEE_LDELEM)
OPALIAS(CEE_STELEM_ANY, "stelem.any", CEE_STELEM)
OPALIAS(CEE_LDC_I4_M1x, "ldc.i4.M1", CEE_LDC_I4_M1)
OPALIAS(CEE_ENDFAULT, "endfault", CEE_ENDFINALLY)
#ifdef _OPALIAS_DEFINED_
#undef OPALIAS
#undef _OPALIAS_DEFINED_
#endif

52
include/clr/openum.h Normal file
Просмотреть файл

@ -0,0 +1,52 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#ifndef __openum_h__
#define __openum_h__
typedef enum opcode_t
{
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) c,
#include "opcode.def"
#undef OPDEF
CEE_COUNT, /* number of instructions and macros pre-defined */
} OPCODE;
typedef enum opcode_format_t
{
InlineNone = 0, // no inline args
InlineVar = 1, // local variable (U2 (U1 if Short on))
InlineI = 2, // an signed integer (I4 (I1 if Short on))
InlineR = 3, // a real number (R8 (R4 if Short on))
InlineBrTarget = 4, // branch target (I4 (I1 if Short on))
InlineI8 = 5,
InlineMethod = 6, // method token (U4)
InlineField = 7, // field token (U4)
InlineType = 8, // type token (U4)
InlineString = 9, // string TOKEN (U4)
InlineSig = 10, // signature tok (U4)
InlineRVA = 11, // ldptr token (U4)
InlineTok = 12, // a meta-data token of unknown type (U4)
InlineSwitch = 13, // count (U4), pcrel1 (U4) .... pcrelN (U4)
InlinePhi = 14, // count (U1), var1 (U2) ... varN (U2)
// WATCH OUT we are close to the limit here, if you add
// more enumerations you need to change ShortIline definition below
// The extended enumeration also encodes the size in the IL stream
ShortInline = 16, // if this bit is set, the format is the 'short' format
PrimaryMask = (ShortInline-1), // mask these off to get primary enumeration above
ShortInlineVar = (ShortInline + InlineVar),
ShortInlineI = (ShortInline + InlineI),
ShortInlineR = (ShortInline + InlineR),
ShortInlineBrTarget = (ShortInline + InlineBrTarget),
InlineOpcode = (ShortInline + InlineNone), // This is only used internally. It means the 'opcode' is two byte instead of 1
} OPCODE_FORMAT;
#endif /* __openum_h__ */

40
include/clr/poppack.h Normal file
Просмотреть файл

@ -0,0 +1,40 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
//
// ===========================================================================
// File: poppack.h
//
// ===========================================================================
/*
Abstract:
This file turns packing of structures off. (That is, it enables
automatic alignment of structure fields.) An include file is needed
because various compilers do this in different ways.
poppack.h is the complement to pshpack?.h. An inclusion of poppack.h
MUST ALWAYS be preceded by an inclusion of one of pshpack?.h, in one-to-one
correspondence.
For Microsoft compatible compilers, this file uses the pop option
to the pack pragma so that it can restore the previous saved by the
pshpack?.h include file.
*/
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(pop)
#else
#pragma pack()
#endif
#else
#pragma pack()
#endif
#endif // ! (defined(lint) || defined(RC_INVOKED))

39
include/clr/pshpack1.h Normal file
Просмотреть файл

@ -0,0 +1,39 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
//
// ===========================================================================
// File: pshpack1.h
//
// ===========================================================================
/*++
Abstract:
This file turns 1 byte packing of structures on. (That is, it disables
automatic alignment of structure fields.) An include file is needed
because various compilers do this in different ways. For Microsoft
compatible compilers, this files uses the push option to the pack pragma
so that the poppack.h include file can restore the previous packing
reliably.
The file poppack.h is the complement to this file.
--*/
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push,1)
#else
#pragma pack(1)
#endif
#else
#pragma pack(1)
#endif
#endif // ! (defined(lint) || defined(RC_INVOKED))

38
include/clr/pshpack2.h Normal file
Просмотреть файл

@ -0,0 +1,38 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
//
// ===========================================================================
// File: pshpack2.h
//
// ===========================================================================
/*++
Abstract:
This file turns 2 byte packing of structures on. (That is, it disables
automatic alignment of structure fields.) An include file is needed
because various compilers do this in different ways. For Microsoft
compatible compilers, this files uses the push option to the pack pragma
so that the poppack.h include file can restore the previous packing
reliably.
The file poppack.h is the complement to this file.
--*/
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push,2)
#else
#pragma pack(2)
#endif
#else
#pragma pack(2)
#endif
#endif // ! (defined(lint) || defined(RC_INVOKED))

39
include/clr/pshpack4.h Normal file
Просмотреть файл

@ -0,0 +1,39 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
//
// ===========================================================================
// File: pshpack4.h
//
// ===========================================================================
/*++
Abstract:
This file turns 4 byte packing of structures on. (That is, it disables
automatic alignment of structure fields.) An include file is needed
because various compilers do this in different ways. For Microsoft
compatible compilers, this files uses the push option to the pack pragma
so that the poppack.h include file can restore the previous packing
reliably.
The file poppack.h is the complement to this file.
--*/
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push,4)
#else
#pragma pack(4)
#endif
#else
#pragma pack(4)
#endif
#endif // ! (defined(lint) || defined(RC_INVOKED))

39
include/clr/pshpack8.h Normal file
Просмотреть файл

@ -0,0 +1,39 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
//
// ===========================================================================
// File: pshpack8.h
//
// ===========================================================================
/*++
Abstract:
This file turns 8 byte packing of structures on. (That is, it disables
automatic alignment of structure fields.) An include file is needed
because various compilers do this in different ways. For Microsoft
compatible compilers, this files uses the push option to the pack pragma
so that the poppack.h include file can restore the previous packing
reliably.
The file poppack.h is the complement to this file.
--*/
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push,8)
#else
#pragma pack(8)
#endif
#else
#pragma pack(8)
#endif
#endif // ! (defined(lint) || defined(RC_INVOKED))

280
include/clr/switches.h Normal file
Просмотреть файл

@ -0,0 +1,280 @@
//===-- switches.h - common runtime configuration switches --*- C++ -*-===//
//
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// See code:EEStartup#TableOfContents for EE overview
#ifndef MSIL_READER_SWITCHES_H
#define MSIL_READER_SWITCHES_H
#ifndef CROSSGEN_COMPILE
#define STRESS_HEAP
#endif
#if !defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR)
#define STRESS_THREAD
#endif
// On CoreCLR, define VERIFY_HEAP only in debug builds
#if defined(_DEBUG) || !defined(FEATURE_CORECLR)
#define VERIFY_HEAP
#endif
// define this to test data safety for the DAC. See code:DataTest::TestDataSafety.
#define TEST_DATA_CONSISTENCY
#if !defined(STRESS_LOG) && !defined(FEATURE_UTILCODE_NO_DEPENDENCIES)
#define STRESS_LOG
#endif
#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
#define USE_CHECKED_OBJECTREFS
#endif
#define FAT_DISPATCH_TOKENS
#define FEATURE_SHARE_GENERIC_CODE
// #if defined(FEATURE_PREJIT)
// Support for string freezing. Disabled since it works for mscorlib.dll only.
// #define FEATURE_BASICFREEZE
// #endif
#if defined(_DEBUG) && !defined(DACCESS_COMPILE)
#define LOGGING
#endif
#if !defined(_TARGET_X86_)
#define WIN64EXCEPTIONS
#endif
#if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES)
// Failpoint support
#if defined(_DEBUG) && !defined(DACCESS_COMPILE)
#define FAILPOINTS_ENABLED
#endif
#endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES)
#if 0
#define APPDOMAIN_STATE
#define BREAK_ON_UNLOAD
#define AD_LOG_MEMORY
#define AD_NO_UNLOAD
#define AD_SNAPSHOT
#define BREAK_META_ACCESS
#define AD_BREAK_ON_CANNOT_UNLOAD
#define BREAK_ON_CLSLOAD
// Enable to track details of EESuspension
#define TIME_SUSPEND
#endif // 0
#ifndef DACCESS_COMPILE
// Enabled to track GC statistics
#define GC_STATS
#endif
#if !defined(FEATURE_CORECLR)
#define EMIT_FIXUPS
#endif
#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && (defined(_TARGET_X86_) || defined(_TARGET_AMD64_))
// On x86/x64 Windows debug builds, respect the COMPLUS_EnforceEEThreadNotRequiredContracts
// runtime switch. See code:InitThreadManager and code:GetThreadGenericFullCheck
#define ENABLE_GET_THREAD_GENERIC_FULL_CHECK
#endif
#if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
#define PAGE_SIZE 0x1000
#define USE_UPPER_ADDRESS 0
#elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
#define PAGE_SIZE 0x1000
#define USE_UPPER_ADDRESS 1
#define UPPER_ADDRESS_MAPPING_FACTOR 2
#define CLR_UPPER_ADDRESS_MIN 0x64400000000
#define CODEHEAP_START_ADDRESS 0x64480000000
#define CLR_UPPER_ADDRESS_MAX 0x644FC000000
#else
#error Please add a new #elif clause and define all portability macros for the new platform
#endif
#ifndef OS_PAGE_SIZE
#define OS_PAGE_SIZE PAGE_SIZE
#endif
#if defined(_WIN64)
#define JIT_IS_ALIGNED
#endif
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !! THE UNCONDITIONAL DEFINE OF ALLOW_SXS_JIT_NGEN SHOULD NOT BE INTEGRATED OUT OF
// !! THE CLR_JITBLUE BRANCH.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// AltJit is always allowed for JITting. Is is allowed in NGEN only for debug.
// Note that if ALLOW_SXS_JIT_NGEN is defined, then ALLOW_SXS_JIT must be defined.
#define ALLOW_SXS_JIT
#if defined(ALLOW_SXS_JIT)
#define ALLOW_SXS_JIT_NGEN
#endif // ALLOW_SXS_JIT
#if defined(FEATURE_CORECLR)
//master switch for gc suspension not based on hijacking
#define FEATURE_ENABLE_GCPOLL
#endif //FEATURE_CORECLR
#if defined(FEATURE_ENABLE_GCPOLL) && defined(_TARGET_X86_)
//this enables a fast version of the GC Poll helper instead of the default portable one.
#define ENABLE_FAST_GCPOLL_HELPER
#endif // defined(FEATURE_ENABLE_GCPOLL) && defined(_TARGET_X86_)
#if defined(_WIN32) || defined(_WIN64)
// PLATFORM_SUPPORTS_THREADSUSPEND is defined for platforms where it is safe to call
// SuspendThread. This API is dangerous on non-Windows platforms, as it can lead to
// deadlocks, due to low level OS resources that the PAL is not aware of, or due to
// the fact that PAL-unaware code in the process may hold onto some OS resources.
#define PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
#endif // defined(_WIN32) || defined(_WIN64)
#if !defined(PLATFORM_SUPPORTS_SAFE_THREADSUSPEND) && !defined(FEATURE_ENABLE_GCPOLL)
#error "Platform must support either safe thread suspension or GC polling"
#endif
// GCCoverage has a dependency on msvcdisXXX.dll, which is not available for CoreSystem. Hence, it is disabled for CoreSystem builds.
#if defined(STRESS_HEAP) && defined(_DEBUG) && defined(FEATURE_HIJACK) && !(defined(FEATURE_CORESYSTEM) && (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)))
#define HAVE_GCCOVER
#endif
#ifdef FEATURE_CORECLR
//Turns on a startup delay to allow simulation of slower and faster startup times.
#define ENABLE_STARTUP_DELAY
#endif
#ifndef ALLOW_LOCAL_WORKER
#define ALLOW_LOCAL_WORKER
#endif
#if defined(_DEBUG) && (defined(_TARGET_X86_) || defined(_WIN64) || defined(_TARGET_ARM_))
//hurray DAC makes everything more fun - you can't have defines that control whether
//or not data members are visible which differ between DAC and non-DAC builds.
//All of the _DATA defines match DAC and non-DAC, the other defines here are off in the DAC.
#if defined(PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED)
// See code:ProfControlBlock#TestOnlyELT.
#define PROF_TEST_ONLY_FORCE_ELT_DATA
// See code:ProfControlBlock#TestOnlyObjectAllocated.
#define PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED_DATA
#endif // PROFILING_SUPPORTED_DATA || PROFILING_SUPPORTED
#if defined(PROFILING_SUPPORTED)
// See code:ProfControlBlock#TestOnlyELT.
#define PROF_TEST_ONLY_FORCE_ELT
// See code:ProfControlBlock#TestOnlyObjectAllocated.
#define PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED
#endif // PROFILING_SUPPORTED
#endif // defined(_DEBUG) && (defined(_TARGET_X86_) || defined(_WIN64))
#if defined(PROFILING_SUPPORTED)
// On desktop CLR builds, the profiling API uses the event log for end-user-friendly
// diagnostic messages. CoreCLR on Windows ouputs debug strings for diagnostic messages.
// Rotor builds have no access to event log message resources, though, so they simply
// display popup dialogs for now.
#define FEATURE_PROFAPI_EVENT_LOGGING
#endif // defined(PROFILING_SUPPORTED)
// Windows desktop supports the profiling API attach / detach feature.
// This will eventually be supported on coreclr as well.
#if defined(PROFILING_SUPPORTED) && !defined(FEATURE_CORECLR)
#define FEATURE_PROFAPI_ATTACH_DETACH
#endif
// Windows desktop DAC builds need to see some of the data used in the profiling API
// attach / detach feature, particularly Thread::m_dwProfilerEvacuationCounter
#if defined(PROFILING_SUPPORTED_DATA) && !defined(FEATURE_CORECLR)
#define DATA_PROFAPI_ATTACH_DETACH
#endif
// MUST NEVER CHECK IN WITH THIS ENABLED.
// This is just for convenience in doing performance investigations in a checked-out enlistment.
// #define FEATURE_ENABLE_NO_RANGE_CHECKS
#ifndef FEATURE_CORECLR
// This controls whether a compilation-timing feature that relies on Windows APIs, if available, else direct
// hardware instructions (rdtsc), for accessing high-resolution hardware timers is enabled. This is disabled
// in Silverlight (just to avoid thinking about whether the extra code space is worthwhile).
#define FEATURE_JIT_TIMER
// This feature in JITBlue supersedes the FEATURE_JIT_TIMER. In addition to supporting the time log file, this
// feature also supports using COMPLUS_JitTimeLogCsv=a.csv, which will dump method-level and phase-level timing
// statistics. Also see comments on FEATURE_JIT_TIMER.
#define FEATURE_JIT_METHOD_PERF
#endif // FEATURE_CORECLR
#ifndef FEATURE_USE_ASM_GC_WRITE_BARRIERS
// If we're not using assembly write barriers, then this turns on a performance measurement
// mode that gathers and prints statistics about # of GC write barriers invokes.
// #define FEATURE_COUNT_GC_WRITE_BARRIERS
#endif
// Enables a mode in which GC is completely conservative in stacks and registers: all stack slots and registers
// are treated as potential pinned interior pointers. When enabled, the runtime flag COMPLUS_GCCONSERVATIVE
// determines dynamically whether GC is conservative. Note that appdomain unload, LCG and unloadable assemblies
// do not work reliably with conservative GC.
// #define FEATURE_CONSERVATIVE_GC
#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
#define FEATURE_HFA
#endif
// ARM requires that 64-bit primitive types are aligned at 64-bit boundaries for interlocked-like operations.
// Additionally the platform ABI requires these types and composite type containing them to be similarly
// aligned when passed as arguments.
#ifdef _TARGET_ARM_
#define FEATURE_64BIT_ALIGNMENT
#endif
// Prefer double alignment for structs and arrays with doubles. Put arrays of doubles more agressively
// into large object heap for performance because large object heap is 8 byte aligned
#if !defined(FEATURE_64BIT_ALIGNMENT) && !defined(_WIN64)
#define FEATURE_DOUBLE_ALIGNMENT_HINT
#endif
#if defined(FEATURE_CORESYSTEM)
#define FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
#endif // defined(FEATURE_CORESYSTEM)
#if defined(FEATURE_PREJIT) && defined(FEATURE_CORECLR) && defined(FEATURE_CORESYSTEM)
// Desktop CLR allows profilers and debuggers to opt out of loading NGENd images, and to
// JIT everything instead. "FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS" is roughly the
// equivalent for Apollo, where MSIL images may not be available at all.
// FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS allows profilers or debuggers to state
// they don't want to use pregenerated code, and to instead load the NGENd image but
// treat it as if it were MSIL by ignoring the prejitted code and prebaked structures,
// and instead to JIT and load types at run-time.
#define FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
#endif
// If defined, support interpretation.
#if !defined(CROSSGEN_COMPILE)
/* // Uncomment if building with the interpreter
#if defined(_TARGET_AMD64_)
#define FEATURE_INTERPRETER
#endif // defined(_TARGET_AMD64_)
*/
#if defined(_TARGET_ARM64_)
#define FEATURE_INTERPRETER
#endif // defined(_TARGET_ARM64_)
#endif // !defined(CROSSGEN_COMPILE)
#endif // MSIL_READER_SWITCHES_H

2
lib/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,2 @@
add_subdirectory(Reader)
add_subdirectory(Jit)

60
lib/Jit/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,60 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../include/clr
${CMAKE_CURRENT_SOURCE_DIR}/../../include/Pal
${CMAKE_CURRENT_SOURCE_DIR}/../../include/Jit
${CMAKE_CURRENT_SOURCE_DIR}/../../include/Reader)
set(LLVM_LINK_COMPONENTS
Analysis
CodeGen
Core
ExecutionEngine
IRReader
MCJIT
MC
Support
native
)
if ( WIN32 )
set(CMAKE_CXX_FLAGS "-EHsc")
# Create .def file containing a list of exports preceeded by
# 'EXPORTS'. The file "MSILCJit.exports" already contains the list, so we
# massage it into the correct format here to create "MSILCJit.exports.def".
set(MSILCJIT_EXPORTS_DEF ${CMAKE_CURRENT_BINARY_DIR}/MSILCJit.exports.def)
set(MSILCJIT_EXPORTS_DEF_TEMP ${MSILCJIT_EXPORTS_DEF}.txt)
file(READ "MSILCJit.exports" exports_list)
file(WRITE ${MSILCJIT_EXPORTS_DEF_TEMP} "LIBRARY MSILCJIT\n")
file(APPEND ${MSILCJIT_EXPORTS_DEF_TEMP} "EXPORTS\n")
file(APPEND ${MSILCJIT_EXPORTS_DEF_TEMP} ${exports_list})
# Copy the file only if it has changed.
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
${MSILCJIT_EXPORTS_DEF_TEMP} ${MSILCJIT_EXPORTS_DEF})
set(SHARED_LIB_SOURCES ${SOURCES} ${MSILCJIT_EXPORTS_DEF})
else()
set(SHARED_LIB_SOURCES ${SOURCES})
endif()
set(LLVM_EXPORTED_SYMBOL_FILE ${MSILCJIT_EXPORTS_DEF})
add_msilcjit_library(
msilcjit
SHARED
jitpch.cpp
MSILCJit.cpp
EEMemoryManager.cpp
${MSILCJIT_EXPORTS_DEF}
)
add_dependencies(
msilcjit
msilcReader
)
target_link_libraries(
msilcjit
${cmake_2_8_12_PRIVATE}
msilcReader
)

132
lib/Jit/EEMemoryManager.cpp Normal file
Просмотреть файл

@ -0,0 +1,132 @@
//===---- lib/Jit/EEMemoryManager.cpp ---------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// 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 the memory manager interface to the EE.
///
//===----------------------------------------------------------------------===//
#include "EEMemoryManager.h"
#include "jitpch.h"
#include "MSILCJit.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/PassManager.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/Debug.h"
#include <string>
namespace llvm {
uint8_t *EEMemoryManager::allocateCodeSection(uintptr_t Size,
unsigned int Alignment,
unsigned int SectionID,
StringRef SectionName) {
// ColdCodeBlock is not currently used.
return this->HotCodeBlock;
}
uint8_t *EEMemoryManager::allocateDataSection(uintptr_t Size,
unsigned int Alignment,
unsigned int SectionID,
StringRef SectionName,
bool IsReadOnly) {
// We don't expect to see RW data requests.
assert(IsReadOnly);
// There are multiple read-only sections, so we need to keep
// track of the current allocation point in the read-only memory region.
uint8_t *Result = ReadOnlyDataUnallocated;
ReadOnlyDataUnallocated += Size;
return Result;
}
bool EEMemoryManager::finalizeMemory(std::string *ErrMsg) {
// Do nothing
return true;
}
void EEMemoryManager::reserveAllocationSpace(uintptr_t CodeSize,
uintptr_t DataSizeRO,
uintptr_t DataSizeRW) {
// Assume for now all RO data is unwind related. We really only
// need to reserve space for .xdata here but without altering
// the pattern of callbacks we can't easily separate .xdata out from
// other read-only things like .rdata and .pdata.
this->Context->JitInfo->reserveUnwindInfo(FALSE, FALSE, DataSizeRO);
// Treat all code for now as "hot section"
ULONG HotCodeSize = CodeSize;
ULONG ColdCodeSize = 0;
// We still need to allocate space for the RO data here too, because
// LLVM's dynamic loader does not know where the EE's reservation was made.
// So this gives the dyamic loader room to copy the RO sections, and later
// the EE will copy from there to the place it really keeps unwind data.
ULONG ReadOnlyDataSize = DataSizeRO;
ULONG ExceptionCount = 0;
// Remap alignment to the EE notion of alignment
CorJitAllocMemFlag Flag =
CorJitAllocMemFlag::CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN;
assert(DataSizeRW == 0);
uint8_t *HotBlock = nullptr;
uint8_t *ColdBlock = nullptr;
uint8_t *RODataBlock = nullptr;
this->Context->JitInfo->allocMem(HotCodeSize, ColdCodeSize, ReadOnlyDataSize,
ExceptionCount, Flag, (void **)&HotBlock,
(void **)&ColdBlock, (void **)&RODataBlock);
assert(ColdBlock == nullptr);
this->HotCodeBlock = HotBlock;
this->ColdCodeBlock = ColdBlock;
this->ReadOnlyDataBlock = RODataBlock;
this->ReadOnlyDataUnallocated = RODataBlock;
this->Context->HotCodeSize = HotCodeSize;
this->Context->ColdCodeSize = ColdCodeSize;
this->Context->ReadOnlyDataSize = ReadOnlyDataSize;
}
// This is a callback from the dynamic loading code to actually
// register the .pdata with the runtime.
void EEMemoryManager::registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) {
// ColdCodeBlock, i.e. separated code is not supported.
assert(this->ColdCodeBlock == 0 && "ColdCodeBlock must be zero");
// Assume this unwind covers the entire method. Later when
// we have multiple unwind regions we'll need something more clever.
ULONG StartOffset = 0;
ULONG EndOffset = this->Context->HotCodeSize;
this->Context->JitInfo->allocUnwindInfo(
this->HotCodeBlock, nullptr, StartOffset, EndOffset, Size,
(BYTE *)LoadAddr, CorJitFuncKind::CORJIT_FUNC_ROOT);
}
EEMemoryManager::~EEMemoryManager() {
// nothing yet.
}
} // namespace llvm

339
lib/Jit/MSILCJit.cpp Normal file
Просмотреть файл

@ -0,0 +1,339 @@
//===---- lib/Jit/MSILCJit.cpp --------------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// 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 the main Jit entry points.
///
//===----------------------------------------------------------------------===//
#include "jitpch.h"
#include "MSILCJit.h"
#include "readerir.h"
#include "EEMemoryManager.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/PassManager.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/CommandLine.h"
#include <string>
using namespace llvm;
// The one and only Jit Object.
MSILCJit *MSILCJit::TheJit = NULL;
// This is guaranteed to be called by the EE
// in single-threaded mode.
ICorJitCompiler *__stdcall getJit() {
if (MSILCJit::TheJit == NULL) {
// These are one-time only operations.
// Create the singleton jit object.
MSILCJit::TheJit = new MSILCJit();
// Register a signal handler, mainly so that the critical
// section that is entered on windows when LLVM gets a fatal error
// is properly initialized.
sys::AddSignalHandler(&MSILCJit::signalHandler, MSILCJit::TheJit);
// Allow LLVM to pick up options via the environment
cl::ParseEnvironmentOptions("MSILCJit", "COMplus_altjitOptions");
}
return MSILCJit::TheJit;
}
// Construct the JIT instance
MSILCJit::MSILCJit() {
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
}
#ifdef LLVM_ON_WIN32
// Windows only
BOOL WINAPI DllMain(HANDLE Instance, DWORD Reason, LPVOID Reserved) {
if (Reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls((HINSTANCE)Instance);
} else if (Reason == DLL_PROCESS_DETACH) {
// TBD
}
return TRUE;
}
#endif // LLVM_ON_WIN32
extern "C"
void __stdcall sxsJitStartup(void *CcCallbacks) {
// nothing to do
}
void MSILCJitContext::outputDebugMethodName() {
const size_t SizeOfBuffer = 512;
char TempBuffer[SizeOfBuffer];
const char *DebugClassName = NULL;
const char *DebugMethodName = NULL;
DebugMethodName = JitInfo->getMethodName(MethodInfo->ftn, &DebugClassName);
dbgs() << format("INFO: jitting method %s::%s using MSILCJit\n",
DebugClassName, DebugMethodName);
}
MSILCJitContext::MSILCJitContext(MSILCJitPerThreadState *PerThreadState)
: State(PerThreadState), HasLoadedBitCode(false) {
this->Next = State->JitContext;
State->JitContext = this;
}
MSILCJitContext::~MSILCJitContext() {
MSILCJitContext *TopContext = State->JitContext;
assert(this == TopContext && "Unbalanced contexts!");
State->JitContext = TopContext->Next;
}
// This is the method invoked by the EE to Jit code.
CorJitResult MSILCJit::compileMethod(ICorJitInfo *JitInfo,
CORINFO_METHOD_INFO *MethodInfo,
UINT Flags, BYTE **NativeEntry,
ULONG *NativeSizeOfCode) {
// Bail if input is malformed
if (NULL == JitInfo || NULL == MethodInfo || NULL == NativeEntry ||
NULL == NativeSizeOfCode) {
return CORJIT_INTERNALERROR;
}
// Prep main outputs
*NativeEntry = NULL;
*NativeSizeOfCode = NULL;
// Set up state for this thread (if necessary)
MSILCJitPerThreadState *PerThreadState = State.get();
if (PerThreadState == NULL) {
PerThreadState = new MSILCJitPerThreadState();
State.set(PerThreadState);
}
// Set up context for this Jit request
MSILCJitContext Context = MSILCJitContext(PerThreadState);
// Fill in context information from the CLR
Context.JitInfo = JitInfo;
Context.MethodInfo = MethodInfo;
Context.ILCursor = MethodInfo->ILCode;
Context.Flags = Flags;
JitInfo->getEEInfo(&Context.EEInfo);
// Fill in context information from LLVM
Context.LLVMContext = &PerThreadState->LLVMContext;
Module *M = Context.getModuleForMethod(MethodInfo);
Context.CurrentModule = M;
EngineBuilder Builder(M);
std::string ErrStr;
Builder.setErrorStr(&ErrStr);
Builder.setUseMCJIT(true);
RTDyldMemoryManager *MM = new EEMemoryManager(&Context);
Builder.setMCJITMemoryManager(MM);
TargetOptions Options;
Options.EnableFastISel = true;
if ((Flags & CORJIT_FLG_DEBUG_CODE) == 0) {
Builder.setOptLevel(CodeGenOpt::Level::Default);
} else {
Builder.setOptLevel(CodeGenOpt::Level::None);
Options.NoFramePointerElim = 1;
}
Builder.setTargetOptions(Options);
ExecutionEngine *NewEngine = Builder.create();
if (!NewEngine) {
errs() << "Could not create ExecutionEngine: " << ErrStr << "\n";
return CORJIT_INTERNALERROR;
}
Context.EE = NewEngine;
// Now jit the method.
CorJitResult Result = CORJIT_INTERNALERROR;
Context.outputDebugMethodName();
bool HasMethod = this->readMethod(&Context);
if (HasMethod) {
Context.EE->generateCodeForModule(Context.CurrentModule);
// You need to pick up the COFFDyld changes from the MS branch of LLVM
// or this will fail with an "Incompatible object format!" error
// from LLVM's dynamic loader.
uint64_t FunctionAddress =
Context.EE->getFunctionAddress(Context.MethodName);
*NativeEntry = (BYTE *)FunctionAddress;
// TODO: ColdCodeSize, or separated code, is not enabled or included.
*NativeSizeOfCode = Context.HotCodeSize + Context.ReadOnlyDataSize;
// This is a stop-gap point to issue a default stub of GC info. This lets
// the CLR consume our methods cleanly. (and the ETW tracing still works)
// Down the road this will be superseded by a CLR specific
// GCMetadataPrinter instance or similar.
this->outputGCInfo(&Context);
// Dump out any enabled timing info.
TimerGroup::printAll(errs());
// Tell the CLR that we've successfully generated code for this method.
Result = CORJIT_OK;
}
return Result;
}
Module *MSILCJitContext::getModuleForMethod(CORINFO_METHOD_INFO *MethodInfo) {
// Grab name info from the EE.
const char *DebugClassName = NULL;
const char *DebugMethodName = NULL;
DebugMethodName = JitInfo->getMethodName(MethodInfo->ftn, &DebugClassName);
// Stop gap name. The full naming will likely require some more info.
std::string ModName(DebugClassName);
ModName.append(1, '.');
ModName.append(DebugMethodName);
Module *M = NULL;
char *BitcodePath = getenv("BITCODE_PATH");
if (BitcodePath != NULL) {
SMDiagnostic Err;
std::string Path = std::string(BitcodePath);
// If there is a bitcode path, use the debug module name to look for an .bc
// file. If one is found then load it directly.
Path.append("\\");
Path.append(ModName);
Path.append(".bc");
M = llvm::ParseIRFile(Path, Err, *this->LLVMContext);
if (!M) {
// Err.print("IR Parsing failed: ", errs());
this->HasLoadedBitCode = false;
} else {
std::string Message("Loaded bitcode from: ");
Message.append(Path);
dbgs() << Message;
this->HasLoadedBitCode = true;
}
}
if (!this->HasLoadedBitCode) {
M = new Module(ModName, *this->LLVMContext);
}
return M;
}
// Read method MSIL and construct LLVM bitcode
bool MSILCJit::readMethod(MSILCJitContext *JitContext) {
if (JitContext->HasLoadedBitCode) {
// This is a case where we side loaded a llvm bitcode module.
// The module is already complete so we avoid reading entirely.
return true;
}
MSILCJitPerThreadState *PerThreadState = State.get();
GenIR Reader(JitContext, &PerThreadState->ClassTypeMap,
&PerThreadState->ArrayTypeMap, &PerThreadState->FieldIndexMap);
std::string FuncName = JitContext->CurrentModule->getModuleIdentifier();
try {
Reader.msilToIR();
} catch (NotYetImplementedException &Nyi) {
errs() << "Failed to read " << FuncName << '[' << Nyi.reason() << "]\n";
return false;
}
Function *Func = JitContext->CurrentModule->getFunction(FuncName);
bool IsOk = !verifyFunction(*Func, &dbgs());
if (IsOk) {
errs() << "Successfully read " << FuncName << '\n';
} else {
errs() << "Read " << FuncName << " but failed verification\n";
}
Func->dump();
JitContext->MethodName = FuncName;
return IsOk;
}
// Stop gap function to allocate and emit stub GCInfo for the method.
// This avoids a crash in the EE.
// Assuming that this will be replaced by an override of the GCMetaData
// or similar writer in LLVM once we move to the safepoint design.
bool MSILCJit::outputGCInfo(MSILCJitContext *JitContext) {
size_t Size = 5;
void *GCInfoBuffer = JitContext->JitInfo->allocGCInfo(Size);
if (GCInfoBuffer == nullptr) {
return false;
}
// First word of the GCInfoBuffer should be the size of the method.
*(unsigned *)GCInfoBuffer = JitContext->HotCodeSize;
// 0x8 is the end sentinel of the buffer.
*(((char *)GCInfoBuffer) + 4) = 0x8;
return true;
}
// Notification from the runtime that any caches should be cleaned up.
void MSILCJit::clearCache() { return; }
// Notify runtime if we have something to clean up
BOOL MSILCJit::isCacheCleanupRequired() { return FALSE; }
// Verify the JIT/EE interface identifier.
void MSILCJit::getVersionIdentifier(GUID *VersionIdentifier) {
_ASSERTE(VersionIdentifier != nullptr);
memcpy(VersionIdentifier, &JITEEVersionIdentifier, sizeof(GUID));
}
// Raise a fatal error.
void __cdecl MSILCJit::fatal(int Errnum, ...) {
_ASSERTE(FAILED(Errnum));
ULONG_PTR ExceptArg = Errnum;
RaiseException(CORJIT_INTERNALERROR, EXCEPTION_NONCONTINUABLE, 1, &ExceptArg);
}
// Handle an abort signal from LLVM. We don't do anything, but registering
// this handler avoids a crash when LLVM goes down.
void MSILCJit::signalHandler(void *Cookie) {
// do nothing
}

2
lib/Jit/MSILCJit.exports Normal file
Просмотреть файл

@ -0,0 +1,2 @@
getJit
sxsJitStartup

16
lib/Jit/jitpch.cpp Normal file
Просмотреть файл

@ -0,0 +1,16 @@
//===---- lib/Jit/jitpch.cpp ------------------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Code portion of precompiled header support.
///
//===----------------------------------------------------------------------===//
#include "jitpch.h"

14
lib/Reader/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,14 @@
add_msilcjit_library(msilcReader
reader.cpp
readerir.cpp
GenIRStubs.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../include/clr
${CMAKE_CURRENT_SOURCE_DIR}/../../include/Pal
${CMAKE_CURRENT_SOURCE_DIR}/../../include/Reader
${CMAKE_CURRENT_SOURCE_DIR}/../../include/Jit)
if ( WIN32 )
set(CMAKE_CXX_FLAGS "-EHsc")
endif()

539
lib/Reader/GenIRStubs.cpp Normal file
Просмотреть файл

@ -0,0 +1,539 @@
//===---- lib/MSILReader/GenIRStubs.cpp -------------------------*- C++ -*-===//
//
// LLVM-MSILC
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
//
//===----------------------------------------------------------------------===//
//
// Common reader functionality that is either not yet implemented
// or stubbed out.
//
//===----------------------------------------------------------------------===//
#include "reader.h"
#include <cstdarg>
// Get the special block-start placekeeping node
IRNode *fgNodeGetStartIRNode(FlowGraphNode *FgNode) { return (IRNode *)FgNode; }
// Get the first non-placekeeping node in block
IRNode *fgNodeGetStartInsertIRNode(FlowGraphNode *FgNode) {
// Not using placekeepers yet
return fgNodeGetStartIRNode(FgNode);
}
// Get the special block-end placekeeping node
IRNode *fgNodeGetEndIRNode(FlowGraphNode *FgNode) {
throw NotYetImplementedException("fFgNodeGetEndIRNode");
}
IRNode *fgNodeGetEndIRInsertionPoint(FlowGraphNode *FgNode) { return NULL; }
void fgNodeSetIBCNotReal(FlowGraphNode *Fg) {
throw NotYetImplementedException("fgNodeSetIBCNotReal");
}
GlobalVerifyData *fgNodeGetGlobalVerifyData(FlowGraphNode *Fg) {
throw NotYetImplementedException("fgNodeGetGlobalVerifyData");
}
void fgNodeSetGlobalVerifyData(FlowGraphNode *Fg, GlobalVerifyData *GvData) {
throw NotYetImplementedException("fgNodeSetGlobalVerifyData");
}
unsigned int fgNodeGetBlockNum(FlowGraphNode *Fg) {
throw NotYetImplementedException("fgNodeGetBlockNum");
}
bool fgEdgeListIsHandler(FlowGraphEdgeList *FgEdge) {
throw NotYetImplementedException("fgEdgeListIsHandler");
}
bool fgEdgeListIsFake(FlowGraphEdgeList *FgEdge) {
throw NotYetImplementedException("fgEdgeListIsFake");
}
void fgEdgeListMakeFake(FlowGraphEdgeList *FgEdge) {
throw NotYetImplementedException("fgEdgeListMakeFake");
}
IRNode *irNodeGetNext(IRNode *Node) {
throw NotYetImplementedException("irNodeGetNext");
}
bool irNodeIsBranch(IRNode *Node) {
throw NotYetImplementedException("irNodeIsBranch");
}
IRNode *irNodeGetInsertPointAfterMSILOffset(IRNode *Node, unsigned int Offset) {
throw NotYetImplementedException("irNodeGetInsertPointAfterMSILOffset");
}
IRNode *irNodeGetInsertPointBeforeMSILOffset(IRNode *Node,
unsigned int Offset) {
throw NotYetImplementedException("irNodeGetInsertPointBeforeMSILOffset");
}
IRNode *
irNodeGetFirstLabelOrInstrNodeInEnclosingBlock(IRNode *HandlerStartNode) {
throw NotYetImplementedException(
"irNodeGetFirstLabelOrInstrNodeInEnclosingBlock");
}
unsigned int irNodeGetMSILOffset(IRNode *Node) {
throw NotYetImplementedException("irNodeGetMSILOffset");
}
void irNodeLabelSetMSILOffset(IRNode *Node, unsigned int LabelMSILOffset) {
throw NotYetImplementedException("irNodeLabelSetMSILOffset");
}
void irNodeBranchSetMSILOffset(IRNode *BranchNode, unsigned int Offset) {
throw NotYetImplementedException("irNodeBranchSetMSILOffset");
}
void irNodeExceptSetMSILOffset(IRNode *BranchNode, unsigned int Offset) {
throw NotYetImplementedException("irNodeExceptSetMSILOffset");
}
void irNodeInsertBefore(IRNode *InsertionPointTuple, IRNode *NewNode) {
throw NotYetImplementedException("irNodeInsertBefore");
}
void irNodeInsertAfter(IRNode *InsertionPointTuple, IRNode *NewNode) {
throw NotYetImplementedException("irNodeInsertAfter");
}
void irNodeSetRegion(IRNode *Node, EHRegion *Region) { return; }
EHRegion *irNodeGetRegion(IRNode *Node) {
throw NotYetImplementedException("irNodeGetRegion");
}
FlowGraphNode *irNodeGetEnclosingBlock(IRNode *Node) {
throw NotYetImplementedException("irNodeGetEnclosingBlock");
}
bool irNodeIsEHFlowAnnotation(IRNode *Node) {
throw NotYetImplementedException("irNodeIsEHFlowAnnotation");
}
bool irNodeIsHandlerFlowAnnotation(IRNode *Node) {
throw NotYetImplementedException("irNodeIsHandlerFlowAnnotation");
}
BranchList *branchListGetNext(BranchList *BranchList) {
throw NotYetImplementedException("branchListGetNext");
}
IRNode *branchListGetIRNode(BranchList *BranchList) {
throw NotYetImplementedException("branchListGetIRNode");
}
void ReaderBase::verifyNeedsVerification() { return; }
VerificationState *ReaderBase::verifyInitializeBlock(FlowGraphNode *,
unsigned int IlOffset) {
return NULL;
}
void ReaderBase::verPropEHInitFlow(FlowGraphNode *Block) { return; }
void ReaderBase::verPropHandlerInitFlow(FlowGraphNode *Block) { return; }
VerificationState *ReaderBase::verCreateNewVState(unsigned MaxStack,
unsigned NumLocals,
bool InitLocals,
InitState InitState) {
return NULL;
}
void ReaderBase::verifyFinishBlock(VerificationState *Vstate,
FlowGraphNode *Block) {
return;
}
void ReaderBase::verifyPropCtorInitToSucc(InitState CurrState,
FlowGraphNode *Succ, char *Reason) {
return;
}
void ReaderBase::verifyPropCtorInitThroughBadBlock(FlowGraphNode *Block) {
return;
}
FlowGraphNode *ReaderBase::verifyGetRegionBlock(EHRegion *Region) {
return NULL;
}
void ReaderBase::verifyEnqueueBlock(GlobalVerifyData *GvSucc) { return; }
FlowGraphNode *
ReaderBase::verifyFindFaultHandlerBlock(VerificationState *Vstate,
EHRegion *TryRegion) {
return NULL;
}
void ReaderBase::verifyRecordLocalType(int Num, CorInfoType Type,
CORINFO_CLASS_HANDLE ClassHandle) {
return;
}
void ReaderBase::verifyRecordParamType(int Num, CorInfoType Type,
CORINFO_CLASS_HANDLE ClassHandle,
bool MakeByRef, bool IsThis) {
return;
}
void ReaderBase::verifyRecordParamType(int Num, CORINFO_SIG_INFO *Sig,
CORINFO_ARG_LIST_HANDLE Args) {
return;
}
void ReaderBase::verifyRecordLocalType(int Num, CORINFO_SIG_INFO *Sig,
CORINFO_ARG_LIST_HANDLE Args) {
return;
}
void ReaderBase::verifyPushExceptionObject(VerificationState *Vstate,
mdToken Token) {
return;
}
void ReaderBase::verifyFieldAccess(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
BOOL verIsCallToInitThisPtr(CORINFO_CLASS_HANDLE Context,
CORINFO_CLASS_HANDLE Ttarget) {
return FALSE;
}
void ReaderBase::verifyLoadElemA(VerificationState *Vstate, bool ReadOnlyPrefix,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyLoadElem(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyLoadConstant(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode) {
return;
}
void ReaderBase::verifyStoreObj(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyLoadObj(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyStloc(VerificationState *Vstate, unsigned int Locnum) {
return;
}
void ReaderBase::verifyIsInst(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyCastClass(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyBox(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyLoadAddr(VerificationState *Vstate) { return; }
void ReaderBase::verifyLoadToken(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyUnbox(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyStoreElemRef(VerificationState *Vstate) { return; }
void ReaderBase::verifyLdarg(VerificationState *Vstate, unsigned int Locnum,
ReaderBaseNS::OPCODE Opcode) {
return;
}
void ReaderBase::verifyStarg(VerificationState *Vstate, unsigned int Locnum) {
return;
}
void ReaderBase::verifyLdloc(VerificationState *Vstate, unsigned int Locnum,
ReaderBaseNS::OPCODE Opcode) {
return;
}
void ReaderBase::verifyStoreElem(VerificationState *Vstate,
ReaderBaseNS::StElemOpcode Opcode,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyLoadLen(VerificationState *Vstate) { return; }
void ReaderBase::verifyDup(VerificationState *Vstate, const BYTE *CodeAddr) {
return;
}
void ReaderBase::verifyEndFilter(VerificationState *Vstate, DWORD MsilOffset) {
return;
}
void ReaderBase::verifyInitObj(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyCall(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode, bool TailCall,
bool ReadOnlyCall, bool ConstraintCall,
bool ThisPossiblyModified,
mdToken ConstraintTypeRef, mdToken Token) {
return;
}
void ReaderBase::verifyCpObj(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyNewObj(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode, bool IsTail,
CORINFO_RESOLVED_TOKEN *ResolvedToken,
const BYTE *CodeAddr) {
return;
}
void ReaderBase::verifyBoolBranch(VerificationState *Vstate,
unsigned int NextOffset,
unsigned int TargetOffset) {
return;
}
void ReaderBase::verifyLoadNull(VerificationState *Vstate) { return; }
void ReaderBase::verifyLoadStr(VerificationState *Vstate, mdToken Token) {
return;
}
void ReaderBase::verifyIntegerBinary(VerificationState *Vstate) { return; }
void ReaderBase::verifyBinary(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode) {
return;
}
void ReaderBase::verifyShift(VerificationState *Vstate) { return; }
void ReaderBase::verifyReturn(VerificationState *Vstate, EHRegion *Region) {
return;
}
void ReaderBase::verifyEndFinally(VerificationState *Vstate) { return; }
void ReaderBase::verifyThrow(VerificationState *Vstate) { return; }
void ReaderBase::verifyLoadFtn(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode,
CORINFO_RESOLVED_TOKEN *ResolvedToken,
const BYTE *CodeAddr,
CORINFO_CALL_INFO *CallInfo) {
return;
}
void ReaderBase::verifyNewArr(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyLoadIndirect(VerificationState *Vstate,
ReaderBaseNS::LdIndirOpcode Opcode) {
return;
}
void ReaderBase::verifyStoreIndir(VerificationState *Vstate,
ReaderBaseNS::StIndirOpcode Opcode) {
return;
}
void ReaderBase::verifyConvert(VerificationState *Vstate,
ReaderBaseNS::ConvOpcode Opcode) {
return;
}
void ReaderBase::verifyCompare(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode) {
return;
}
void ReaderBase::verifyUnary(VerificationState *Vstate,
ReaderBaseNS::UnaryOpcode Opcode) {
return;
}
void ReaderBase::verifyPop(VerificationState *Vstate) { return; }
void ReaderBase::verifyArgList(VerificationState *Vstate) { return; }
void ReaderBase::verifyCkFinite(VerificationState *Vstate) { return; }
void ReaderBase::verifyFailure(VerificationState *Vstate) { return; }
void ReaderBase::verifyToken(mdToken Token) { return; }
void ReaderBase::verifyRefAnyVal(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyRefAnyType(VerificationState *Vstate) { return; }
void ReaderBase::verifyUnboxAny(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifySwitch(VerificationState *Vstate) { return; }
void ReaderBase::verifyMkRefAny(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifySizeOf(VerificationState *Vstate,
CORINFO_RESOLVED_TOKEN *ResolvedToken) {
return;
}
void ReaderBase::verifyRethrow(VerificationState *Vstate, EHRegion *Region) {
return;
}
void ReaderBase::verifyTail(VerificationState *Vstate, EHRegion *Region) {
return;
}
void ReaderBase::verifyConstrained(VerificationState *Vstate,
mdToken TypeDefOrRefOrSpec) {
return;
}
void ReaderBase::verifyReadOnly(VerificationState *Vstate) { return; }
void ReaderBase::verifyVolatile(VerificationState *Vstate) { return; }
void ReaderBase::verifyUnaligned(VerificationState *Vstate,
ReaderAlignType Alignment) {
return;
}
void ReaderBase::verifyPrefixConsumed(VerificationState *Vstate,
ReaderBaseNS::OPCODE Opcode) {
return;
}
void ReaderBase::verifyLeave(VerificationState *Vstate) { return; }
void ReaderBase::verifyBranchTarget(VerificationState *Vstate,
FlowGraphNode *CurrentFGNode,
EHRegion *SrcRegion,
unsigned int TargetOffset, bool IsLeave) {
return;
}
void ReaderBase::verifyReturnFlow(unsigned int SrcOffset) { return; }
void ReaderBase::verifyFallThrough(VerificationState *Vstate,
FlowGraphNode *Fg) {
return;
}
bool verCheckDelegateCreation(ReaderBaseNS::OPCODE Opcode,
VerificationState *Vstate, const BYTE *CodeAddr,
mdMemberRef &TargetMemberRef, VerType FtnType,
VerType ObjType) {
return false;
}
void ReaderBase::verVerifyCall(ReaderBaseNS::OPCODE Opcode,
const CORINFO_RESOLVED_TOKEN *ResolvedToken,
const CORINFO_CALL_INFO *CallInfo, bool TailCall,
const BYTE *CodeAddr,
VerificationState *Vstate) {
return;
}
void ReaderBase::verifyIsMethodToken(mdToken Token) { return; }
void ReaderBase::verifyIsCallToken(mdToken Token) { return; }
void ReaderBase::verVerifyField(CORINFO_RESOLVED_TOKEN *ResolvedToken,
const CORINFO_FIELD_INFO &FieldInfo,
const VerType *TiThis, BOOL Mutator) {
return;
}
bool ReaderBase::verIsValueClass(CORINFO_CLASS_HANDLE ClassHandle) {
return false;
}
bool ReaderBase::verIsBoxedValueType(const VerType &Ti) { return false; }
bool ReaderBase::verIsCallToken(mdToken Token) { return false; }
bool ReaderBase::verIsValClassWithStackPtr(CORINFO_CLASS_HANDLE ClassHandle) {
return false;
}
bool ReaderBase::verIsGenericTypeVar(CORINFO_CLASS_HANDLE ClassHandle) {
return false;
}
void ReaderBase::verDumpType(const VerType &Ti) { return; }
bool ReaderBase::verNeedsCtorTrack() { return false; }
void ReaderBase::verifyIsClassToken(mdToken Token) { return; }
void ReaderBase::verifyIsFieldToken(mdToken Token) { return; }
void ReaderBase::verifyEIT() { return; }
void ReaderBase::verGlobalError(const char *Message) { return; }
int _cdecl dbPrint(const char *Format, ...) {
va_list Args;
va_start(Args, Format);
int NumChars = vfprintf(stderr, Format, Args);
va_end(Args);
return NumChars;
}
BOOL HaveEnvConfigTailCallOpt = FALSE;
UINT EnvConfigTailCallOpt = 0;
BOOL HaveEnvConfigTailCallMax = FALSE;
UINT EnvConfigTailCallMax = 0;

8873
lib/Reader/reader.cpp Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

4018
lib/Reader/readerir.cpp Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1
tools/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1 @@
add_subdirectory(Driver)

Просмотреть файл

1
tools/Driver/ReadMe.txt Normal file
Просмотреть файл

@ -0,0 +1 @@
This is a placeholder for an AOT copmpilation driver.

182
utils/ccformat.cmd Normal file
Просмотреть файл

@ -0,0 +1,182 @@
REM ***********************************************
REM Copyright (c) Microsoft. All rights reserved.
REM Licensed under the MIT license. See LICENSE file in the project root for full license information.
REM ***********************************************
@echo off
setlocal
REM ***********************************************
REM Setup
REM ***********************************************
if "%LLVMSOURCE%"=="" (
echo.No LLVMSOURCE
set RETURN=2
goto done
)
if "%LLVMBUILD%"=="" (
echo.No LLVMBUILD
set RETURN=2
goto done
)
if "%MSILCSOURCE%"=="" (
set MSILCSOURCE=%LLVMSOURCE%\Tools\MSILC
)
set MSILCLIB=%MSILCSOURCE%\lib
set MSILCINC=%MSILCSOURCE%\include
set CLRINC=%MSILCINC%\clr
set LLVMINC=%LLVMSOURCE%\include
SET RETURN=0
set FIX=
set FORMAT=Check
set TIDY=Yes
:parse
REM ***********************************************
REM Driver
REM ***********************************************
if "%1"=="" (
goto done_parsing
) else if /I .%1==./fix (
set FIX=-fix
) else if /I .%1==./untidy (
set TIDY=No
) else if /I .%1==./noformat (
set FORMAT=No
) else if /I .%1==./help (
goto help
) else if /I .%1==./? (
goto help
) else (
echo.Unknown option %1
set RETURN=3
goto done
)
shift /1
goto parse
:done_parsing
:tidy
REM ***********************************************
REM Run Clang Tidy
REM ***********************************************
if .%TIDY%==.No (
goto Format
)
set INC=-I%MSILCLIB%\Jit -I%MSILCLIB%\MSILReader -I%MSILCINC% -I%LLVMINC% -I%CLRINC% -I%MSILCINC%\Driver -I%MSILCINC%\Jit -I%MSILCINC%\Reader -I%LLVMBUILD%\tools\MSILC\lib\Reader -I%LLVMBUILD%\tools\MSILC\include -I%LLVMBUILD%\include
set DEF=-D_DEBUG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS-D__STDC_LIMIT_MACROS -D_GNU_SOURCE -DMSILCJit_EXPORTS -D_WINDLL -D_MBCS
pushd %MSILCSOURCE%
for /f %%f in ('dir /s /b *.c *.cpp') do (
clang-tidy %FIX% -checks=llvm*,misc*,microsoft* -header-filter="MSILC.*(Reader)|(Jit)" %%f -- %DEF% %INC%
if ERRORLEVEL 1 set RETURN=1
)
popd
:Format
REM ***********************************************
REM Run Clang Format
REM ***********************************************
if .%FORMAT%==.No (
goto done
)
if .%FIX%==.-fix (
goto FormatFix
)
:FormatCheck
REM Clang Format -- check only
REM Check if the formatted output from clang-format
REM is any different from the source code file
set TMP_DIR=%TMP%\ccformat
IF NOT EXIST %TMP_DIR% mkdir %TMP_DIR%
pushd %MSILCSOURCE%
for /f %%f in ('dir /s /b *.c *.cpp') do (
clang-format -style=LLVM %%f > %TMP_DIR%\%%~nxf
diff -u %%f %TMP_DIR%\%%~nxf
if ERRORLEVEL 1 set RETURN=1
)
popd
REM CLR headers are exempt from formatting checks
pushd %MSILCINC%
for /f %%d in ('dir /AD /b') do (
if /i not .%%d==.clr (
pushd %%d
for /f %%f in ('dir /s /b *.h *.inc 2^>nul') do (
clang-format -style=LLVM %%f > %TMP_DIR%\%%~nxf
diff -u %%f %TMP_DIR%\%%~nxf
if ERRORLEVEL 1 set RETURN=1
)
popd
)
)
popd
rmdir /q /s %TMP_DIR%
goto done
:FormatFix
REM Clang Format -- fix errors
pushd %MSILCSOURCE%
for /f %%f in ('dir /s /b *.c *.cpp') do (
clang-format.exe -style=LLVM -i %%f
)
popd
pushd %MSILCINC%
for /f %%d in ('dir /AD /b') do (
if /i not .%%d==.clr (
pushd %%d
for /f %%f in ('dir /s /b *.h *.inc 2^>nul') do (
clang-format.exe -style=LLVM -i %%f
)
popd
)
)
popd
goto done
:help
REM ***********************************************
REM Help Section
REM ***********************************************
echo.Usage: ccFormat [/Check] [/Fix] [/?]
echo. /fix Fix failures when possible
echo. /untidy Don't run clang-tidy
echo. /noformat Don't run clang-format
echo. /help Display this help message.
echo.
echo.Requirements:
echo. Environment variables: LLVMSOURCE, LLVMBUILD
echo. Tools (on path): clang-format.exe, clang-tidy.exe
echo.
:done
exit /b %RETURN%