зеркало из https://github.com/dotnet/llilc.git
Initial commit
This commit is contained in:
Коммит
63dbfe850d
|
@ -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
|
|
@ -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
|
|
@ -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.")
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
|
@ -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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
|
@ -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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
|
@ -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
|
|
@ -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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
||||
|
|
@ -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__ */
|
||||
|
||||
|
|
@ -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))
|
|
@ -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))
|
|
@ -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))
|
|
@ -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))
|
|
@ -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))
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
add_subdirectory(Reader)
|
||||
add_subdirectory(Jit)
|
|
@ -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
|
||||
)
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
getJit
|
||||
sxsJitStartup
|
|
@ -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"
|
|
@ -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()
|
|
@ -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;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1 @@
|
|||
add_subdirectory(Driver)
|
|
@ -0,0 +1 @@
|
|||
This is a placeholder for an AOT copmpilation driver.
|
|
@ -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%
|
Загрузка…
Ссылка в новой задаче