├── test ├── CMakeLists.txt ├── LLILCTestEnv.cmd ├── const.py ├── llilc_roslyn_stage.cmd ├── llilc_hook.py ├── applyfilter.py └── llilc_run.py ├── include ├── Jit │ ├── CMakeLists.txt │ ├── jitpch.h │ ├── global.h │ ├── compiler.h │ ├── jitoptions.h │ ├── utility.h │ └── EEMemoryManager.h ├── clr │ ├── CMakeLists.txt │ ├── pshpack2.h │ ├── pshpack1.h │ ├── pshpack4.h │ ├── pshpack8.h │ ├── poppack.h │ └── misc.h ├── Driver │ └── CMakeLists.txt ├── GcInfo │ ├── CMakeLists.txt │ ├── eexcp.h │ └── Target.h ├── Pal │ ├── Rt │ │ ├── CMakeLists.txt │ │ ├── ole2.h │ │ ├── windef.h │ │ ├── winerror.h │ │ └── specstrings.h │ ├── CMakeLists.txt │ └── earlyincludes.h ├── Reader │ ├── CMakeLists.txt │ ├── imeta.h │ ├── gverify.h │ ├── imeta.def │ ├── options.h │ ├── ophelper.def │ ├── newvstate.h │ ├── abisignature.h │ └── abi.h └── CMakeLists.txt ├── tools ├── Driver │ ├── CMakeLists.txt │ └── ReadMe.txt └── CMakeLists.txt ├── .clang-format ├── lib ├── Jit │ ├── LLILCJit.exports │ ├── jitpch.cpp │ ├── CMakeLists.txt │ └── utility.cpp ├── CMakeLists.txt ├── CoreDisTools │ ├── coredistools.exports │ ├── .nuget │ │ ├── Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.win-x64.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.win-x86.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.centos.7.1-x64.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.centos.7.1-x86.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.osx.10.11-x64.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.osx.10.11-x86.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.ubuntu.14.04-x64.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.ubuntu.14.04-x86.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.ubuntu.16.04-x64.Microsoft.NETCore.CoreDisTools.nuspec │ │ ├── runtime.ubuntu.16.04-x86.Microsoft.NETCore.CoreDisTools.nuspec │ │ └── runtime.json │ └── CMakeLists.txt ├── ObjWriter │ ├── objwriter.exports │ ├── .nuget │ │ ├── runtime.json │ │ ├── Microsoft.DotNet.ObjectWriter.nuspec │ │ ├── toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec │ │ ├── toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec │ │ └── toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec │ ├── CMakeLists.txt │ └── jitDebugInfo.h ├── GcInfo │ ├── CMakeLists.txt │ └── GcInfoUtil.cpp └── Reader │ └── CMakeLists.txt ├── Documentation ├── Images │ ├── AOTArch.png │ └── JITArch.png ├── llilc-at-six-months.md ├── index.md ├── Background.md ├── Welcome.md ├── Contributing.md ├── Getting-Started-For-Linux-and-OS-X.md ├── llilc-milestones.md ├── Code-Formatting.md ├── llilc-faq.md ├── Long-Running-Branch-Workflow.md ├── llilc-Coding-Conventions-and-Commenting-Style.md ├── Developer-Workflow.md ├── Areas-To-Contribute.md ├── Getting-Started-For-Windows.md ├── Setup-With-LLILC-Out-Of-LLVM-Tree.md ├── Testing.md └── llilc-gc-transition.md ├── utils ├── packages.config ├── NuGet.config ├── make_package.py └── BuildPackages.ps1 ├── CODE-OF-CONDUCT.md ├── LICENSE.TXT ├── CODE_OWNERS.TXT ├── .gitattributes ├── .gitignore ├── README.md └── netci.groovy /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/Jit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/clr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/Driver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/Driver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/GcInfo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/Pal/Rt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/Reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/Pal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Rt) 2 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Driver) 2 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | SortIncludes: false 3 | -------------------------------------------------------------------------------- /lib/Jit/LLILCJit.exports: -------------------------------------------------------------------------------- 1 | getJit 2 | sxsJitStartup 3 | jitStartup 4 | -------------------------------------------------------------------------------- /tools/Driver/ReadMe.txt: -------------------------------------------------------------------------------- 1 | This is a placeholder for an AOT (Ahead Of Time) compilation driver. 2 | -------------------------------------------------------------------------------- /Documentation/Images/AOTArch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/llilc/HEAD/Documentation/Images/AOTArch.png -------------------------------------------------------------------------------- /Documentation/Images/JITArch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/llilc/HEAD/Documentation/Images/JITArch.png -------------------------------------------------------------------------------- /Documentation/llilc-at-six-months.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/llilc/HEAD/Documentation/llilc-at-six-months.md -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(clr) 2 | add_subdirectory(Driver) 3 | add_subdirectory(GcInfo) 4 | add_subdirectory(Jit) 5 | add_subdirectory(Pal) 6 | add_subdirectory(Reader) 7 | -------------------------------------------------------------------------------- /utils/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Enable ObjWriter/CoreDisTools only 2 | #add_subdirectory(Reader) 3 | #add_subdirectory(Jit) 4 | #add_subdirectory(GcInfo) 5 | add_subdirectory(ObjWriter) 6 | add_subdirectory(CoreDisTools) 7 | 8 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | 6 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 7 | -------------------------------------------------------------------------------- /lib/CoreDisTools/coredistools.exports: -------------------------------------------------------------------------------- 1 | InitDisasm 2 | InitBufferedDisasm 3 | NewDisasm 4 | FinishDisasm 5 | DisasmInstruction 6 | DumpInstruction 7 | InitBufferedDiffer 8 | NewDiffer 9 | FinishDiff 10 | NearDiffCodeBlocks 11 | DumpCodeBlock 12 | DumpDiffBlocks 13 | GetOutputBuffer 14 | ClearOutputBuffer 15 | -------------------------------------------------------------------------------- /lib/ObjWriter/objwriter.exports: -------------------------------------------------------------------------------- 1 | InitObjWriter 2 | FinishObjWriter 3 | SwitchSection 4 | EmitAlignment 5 | EmitBlob 6 | EmitIntValue 7 | EmitSymbolDef 8 | EmitSymbolRef 9 | EmitWinFrameInfo 10 | EmitCFIStart 11 | EmitCFIEnd 12 | EmitCFICode 13 | EmitCFILsda 14 | EmitDebugFileInfo 15 | EmitDebugLoc 16 | EmitDebugFunctionInfo 17 | EmitDebugModuleInfo 18 | EmitDebugVar 19 | CreateCustomSection 20 | -------------------------------------------------------------------------------- /test/LLILCTestEnv.cmd: -------------------------------------------------------------------------------- 1 | REM ------------------------------------------------------------------------- 2 | REM 3 | REM This script provides LLILC test environment settings 4 | REM 5 | REM ------------------------------------------------------------------------- 6 | 7 | set COMPLUS_AltJit=* 8 | set COMPLUS_AltJitNgen=* 9 | set COMPLUS_AltJitName=LLILCJit.dll 10 | set COMPLUS_GCCONSERVATIVE=1 11 | set COMPLUS_ZapDisable=1 12 | set COMPLUS_NoGuiOnAssert=1 13 | -------------------------------------------------------------------------------- /utils/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /include/Pal/Rt/ole2.h: -------------------------------------------------------------------------------- 1 | //===--- include/Pal/Rt/ole2.h ----------------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Dummy ole2.h for non-Windows platforms. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | -------------------------------------------------------------------------------- /include/Pal/Rt/windef.h: -------------------------------------------------------------------------------- 1 | //===--- include/Pal/Rt/windef.h ------------------------- ------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Dummy windef.h for non-Windows platforms. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | -------------------------------------------------------------------------------- /include/Pal/Rt/winerror.h: -------------------------------------------------------------------------------- 1 | //===--- include/Pal/Rt/winerror.h ------------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Dummy winerror.h for non-Windows platforms. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | -------------------------------------------------------------------------------- /include/Pal/Rt/specstrings.h: -------------------------------------------------------------------------------- 1 | //===--- include/Pal/Rt/specstrings.h ---------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Dummy specstrings.h for non-Windows platforms. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | -------------------------------------------------------------------------------- /lib/Jit/jitpch.cpp: -------------------------------------------------------------------------------- 1 | //===---- lib/Jit/jitpch.cpp ------------------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Code portion of precompiled header support. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #include "jitpch.h" -------------------------------------------------------------------------------- /test/const.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #title :const.py 4 | #description : 5 | # 6 | # const class does not allow rebinding value to name so that name is constant. 7 | # 8 | #========================================================================================== 9 | 10 | class _const: 11 | class ConstError(TypeError): pass 12 | def __setattr__(self,name,value): 13 | if name in self.__dict__: 14 | message = "Can't rebind const " + name 15 | raise self.ConstError(message) 16 | self.__dict__[name]=value 17 | import sys 18 | sys.modules[__name__]=_const() 19 | -------------------------------------------------------------------------------- /lib/ObjWriter/.nuget/runtime.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimes": { 3 | "win7-x64": { 4 | "Microsoft.DotNet.ObjectWriter": { 5 | "toolchain.win7-x64.Microsoft.DotNet.ObjectWriter": "1.0.13-prerelease-00001" 6 | } 7 | }, 8 | "ubuntu.14.04-x64": { 9 | "Microsoft.DotNet.ObjectWriter": { 10 | "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter": "1.0.13-prerelease-00001" 11 | } 12 | }, 13 | "osx.10.10-x64": { 14 | "Microsoft.DotNet.ObjectWriter": { 15 | "toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter": "1.0.13-prerelease-00001" 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Documentation/index.md: -------------------------------------------------------------------------------- 1 | # LLILC 2 | 3 | ## Introduction 4 | Welcome to LLILC. 5 | 6 | This documentation describes the **internals** of 7 | LLILC, not the **external** use of LLILC. There are no instructions 8 | here on how to use LLILC, only the APIs that make up the software. For usage 9 | instructions, please see the programmer's guide or reference manual. 10 | 11 | ## Caveat 12 | This documentation is generated directly from the source code with doxygen. 13 | Since LLILC is under active development, what you're about to 14 | read is likely out of date! However, it may still be useful since certain portions 15 | of LLILC are very stable. 16 | -------------------------------------------------------------------------------- /lib/GcInfo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | get_filename_component(LLILC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../../include ABSOLUTE) 2 | 3 | include_directories(${LLILC_INCLUDES}/clr 4 | ${LLILC_INCLUDES}/GcInfo 5 | ${LLILC_INCLUDES}/Jit 6 | ${LLILC_INCLUDES}/Pal) 7 | 8 | add_definitions(-DSTANDALONE_BUILD) 9 | 10 | if(CLR_CMAKE_PLATFORM_UNIX) 11 | add_compile_options(-fPIC) 12 | endif(CLR_CMAKE_PLATFORM_UNIX) 13 | 14 | add_llilcjit_library(GcInfo 15 | STATIC 16 | ${CORECLR_GCINFO}/gcinfoencoder.cpp 17 | GcInfoUtil.cpp 18 | GcInfo.cpp 19 | ) 20 | 21 | if( NOT LLILC_BUILT_STANDALONE ) 22 | add_dependencies(GcInfo intrinsics_gen) 23 | endif() 24 | -------------------------------------------------------------------------------- /include/Reader/imeta.h: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/imeta.h -----------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declares extra information not provided by the jit interface. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef MSIL_READER_IMETA_H 17 | #define MSIL_READER_IMETA_H 18 | 19 | #include "imeta.def" 20 | 21 | #endif // MSIL_READER_IMETA_H 22 | -------------------------------------------------------------------------------- /lib/Reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | get_filename_component(LLILC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../../include ABSOLUTE) 2 | 3 | include_directories(${LLILC_INCLUDES}/clr 4 | ${LLILC_INCLUDES}/Pal 5 | ${LLILC_INCLUDES}/GcInfo 6 | ${LLILC_INCLUDES}/Reader 7 | ${LLILC_INCLUDES}/Jit) 8 | 9 | set(LLILCJIT_LINK_LIBRARIES GcInfo) 10 | 11 | add_definitions(-DSTANDALONE_BUILD) 12 | 13 | add_llilcjit_library(LLILCReader 14 | abi.cpp 15 | abisignature.cpp 16 | reader.cpp 17 | readerir.cpp 18 | GenIRStubs.cpp 19 | ) 20 | 21 | if( NOT LLILC_BUILT_STANDALONE ) 22 | add_dependencies(LLILCReader intrinsics_gen) 23 | endif() 24 | -------------------------------------------------------------------------------- /include/Pal/earlyincludes.h: -------------------------------------------------------------------------------- 1 | //===--- include/Pal/earlyincludes.h ----------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | // 11 | // Include files that must be included early to avoid interference with 12 | // Windows #defines. 13 | // 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef EARLYINCLUDES_INC 17 | #define EARLYINCLUDES_INC 18 | 19 | #include "llvm/Object/RelocVisitor.h" 20 | 21 | #endif // EARLYINCLUDES_INC 22 | -------------------------------------------------------------------------------- /include/Jit/jitpch.h: -------------------------------------------------------------------------------- 1 | //===--------------- include/Jit/jitpch.h -----------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Jit precompiled header 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef JIT_PCH_H 17 | #define JIT_PCH_H 18 | 19 | #include "global.h" 20 | #include "LLILCPal.h" 21 | 22 | #if defined(_MSC_VER) 23 | #include 24 | #else 25 | #include 26 | #include 27 | #include "ntimage.h" 28 | #endif 29 | 30 | #include "corjit.h" 31 | 32 | #endif // JIT_PCH_H 33 | -------------------------------------------------------------------------------- /Documentation/Background.md: -------------------------------------------------------------------------------- 1 | # Background 2 | 3 | LLILC is an Open-Source project that Compiles msIL (.NET) code to native 4 | binary, using the LLVM compiler framework. We pronounce it "lilac". The 5 | project will provide both a JIT ("Just-In-Time") and an AOT ("Ahead-Of-Time") 6 | compiler targeting [CoreCLR](https://github.com/dotnet/coreclr). 7 | 8 | The LLILC LLVM based toolchain is a companion project to the CoreCLR RyuJIT 9 | providing the community with an accessible infrastructure for experimentation 10 | and porting to new targets. Our goal is to make it easy(-ier) to make new 11 | tools or take C# to new platforms. Our initial supported platform is Windows 12 | but we plan to extend support to Linux and Mac in the near term. 13 | 14 | For more background on the .NET Architecture, see its [ECMA Specification](http://www.ecma-international.org/publications/standards/Ecma-335.htm). 15 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00005 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.DotNet.ObjectWriter 5 | 1.0.13-prerelease-00001 6 | Microsoft .NET Object File Generator 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/corert 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Provides object writer to the managed to native code-generator. 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /include/GcInfo/eexcp.h: -------------------------------------------------------------------------------- 1 | //===----------------- include/clr/eexcp.h ----------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Definition of some Exception handling structure definitions 13 | /// used in partially interruptible GC scenarios. 14 | /// 15 | //===----------------------------------------------------------------------===// 16 | 17 | #ifndef __EEXCP_X__ 18 | #define __EEXCP_X__ 19 | 20 | struct EE_ILEXCEPTION_CLAUSE { 21 | CorExceptionFlag Flags; 22 | DWORD TryStartPC; 23 | DWORD TryEndPC; 24 | DWORD HandlerStartPC; 25 | DWORD HandlerEndPC; 26 | union { 27 | void *TypeHandle; 28 | mdToken ClassToken; 29 | DWORD FilterOffset; 30 | }; 31 | }; 32 | 33 | #endif // __EEXCP_X__ 34 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.win-x64.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.win-x64.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00005 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.win-x86.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.win-x86.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00005 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | toolchain.win7-x64.Microsoft.DotNet.ObjectWriter 5 | 1.0.13-prerelease-00001 6 | Microsoft .NET Object File Generator 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/corert 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Provides object writer to the managed to native code-generator. 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.centos.7.1-x64.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.centos.7.1-x64.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.centos.7.1-x86.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.centos.7.1-x86.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.osx.10.11-x64.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.osx.10.11-x64.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.osx.10.11-x86.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.osx.10.11-x86.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.ubuntu.14.04-x64.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.ubuntu.14.04-x64.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.ubuntu.14.04-x86.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.ubuntu.14.04-x86.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.ubuntu.16.04-x64.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.ubuntu.16.04-x64.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.ubuntu.16.04-x86.Microsoft.NETCore.CoreDisTools.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | runtime.ubuntu.16.04-x86.Microsoft.NETCore.CoreDisTools 5 | 1.0.1-prerelease-00002 6 | Microsoft.NETCore Instruction-wise Disassembler 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/coreclr 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Disassembly Tools for CoreCLR 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter 5 | 1.0.13-prerelease-00001 6 | Microsoft .NET Object File Generator 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/corert 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Provides object writer to the managed to native code-generator. 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter 5 | 1.0.13-prerelease-00001 6 | Microsoft .NET Object File Generator 7 | Microsoft 8 | Microsoft 9 | http://go.microsoft.com/fwlink/?LinkId=329770 10 | https://github.com/dotnet/corert 11 | http://go.microsoft.com/fwlink/?LinkID=288859 12 | true 13 | Provides object writer to the managed to native code-generator. 14 | Initial release 15 | Copyright © Microsoft Corporation 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /include/Jit/global.h: -------------------------------------------------------------------------------- 1 | //===--------------- include/Jit/global.h -----------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Host and target defines. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef JIT_GLOBAL_H 17 | #define JIT_GLOBAL_H 18 | 19 | #if defined(_M_IX86) || defined(__i386__) 20 | #define _TARGET_X86_ 1 21 | #define _HOST_X86_ 1 22 | #elif defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__) 23 | #define _TARGET_X64_ 1 24 | #define _TARGET_AMD64_ 1 25 | #define _HOST_X64_ 1 26 | #define _HOST_AMD64_ 1 27 | #elif defined(_M_ARM) || defined(__arm__) 28 | #define _TARGET_ARM_ 1 29 | #define _HOST_ARM_ 1 30 | #elif defined(_M_ARM64) || defined(__aarch64__) 31 | #define _TARGET_ARM64_ 1 32 | #define _HOST_ARM64_ 1 33 | #endif 34 | 35 | #endif // JIT_GLOBAL_H 36 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /CODE_OWNERS.TXT: -------------------------------------------------------------------------------- 1 | The following is a list of owners for different areas of the LLILC code. 2 | Each of the owners is responsible for ensuring that changes in their areas 3 | are reviewed, either by themselves or by someone they designate, in 4 | addition to being the final word for the architecture and content of an area. 5 | 6 | List sorted by last name and the fields are Name (N), GitHub user account (G), 7 | Description (D). 8 | 9 | Note: If you don't find the area in the below list, or you have a general 10 | question, send a message to Andy Ayers and Russell Hadley. They can ensure 11 | that the question gets forwarded to the right person or answer it themselves. 12 | 13 | N: Andy Ayers 14 | G: AndyAyersMS 15 | D: JIT context/multi-threading, MSIL types in bitcode, test harness, 16 | everything else. 17 | 18 | N: Pat Gavlin 19 | G: pgavlin 20 | D: CLR/Target ABI processing. 21 | 22 | N: Russell C Hadley 23 | G: Russell Hadley 24 | D: JIT infrastructure, everything else. 25 | 26 | N: Eugene Rozenfeld 27 | G: erozenfeld 28 | D: MSIL reader. 29 | 30 | N: Swaroop Sridhar 31 | G: swaroop-sridhar 32 | D: CLR GC support 33 | 34 | N: Joseph Tremoulet 35 | G: JosephTremoulet 36 | D: CLR EH support. 37 | -------------------------------------------------------------------------------- /Documentation/Welcome.md: -------------------------------------------------------------------------------- 1 | # Welcome to LLILC 2 | 3 | We pronounce it 'lilac'. LLILC is comprised of a JIT and AOT compiler for C#. 4 | They work with the dotnet [CoreCLR](https://github.com/dotnet/coreclr) and 5 | will complement the current CoreCLR JIT by providing an alternate code 6 | generator built on the LLVM infrastructure. 7 | 8 | ## Developer Guides 9 | 10 | * [Background](Background.md) 11 | * [FAQ](llilc-faq.md) 12 | * [Getting Started for Windows](Getting-Started-For-Windows.md) 13 | * [Getting Started For Linux and OS X](Getting-Started-For-Linux-and-OS-X.md) 14 | * [Testing](Testing.md) 15 | * [Debugging](Debugging.md) 16 | * [Contribution Guide](Contributing.md) 17 | * [Areas To Contribute](Areas-To-Contribute.md) 18 | * [LLILC Coding Conventions and Commenting Style](llilc-Coding-Conventions-and-Commenting-Style.md) 19 | 20 | ## Architecture 21 | 22 | * [LLILC Architecture Overview](llilc-arch.md) 23 | 24 | ### Supporting managed constructs in LLVM 25 | * [LLILC MSIL Reader](llilc-reader.md) 26 | * [GC Support in LLILC](llilc-gc.md) 27 | * [EH Support in LLILC](llilc-jit-eh.md) 28 | 29 | ## Other Resources 30 | * [dotnet/CoreCLR](https://github.com/dotnet/coreclr) 31 | * [dotnet/CoreFx](https://github.com/dotnet/corefx) 32 | -------------------------------------------------------------------------------- /include/clr/pshpack2.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | // 6 | 7 | // 8 | // =========================================================================== 9 | // File: pshpack2.h 10 | // 11 | // =========================================================================== 12 | /*++ 13 | 14 | Abstract: 15 | 16 | This file turns 2 byte packing of structures on. (That is, it disables 17 | automatic alignment of structure fields.) An include file is needed 18 | because various compilers do this in different ways. For Microsoft 19 | compatible compilers, this files uses the push option to the pack pragma 20 | so that the poppack.h include file can restore the previous packing 21 | reliably. 22 | 23 | The file poppack.h is the complement to this file. 24 | 25 | --*/ 26 | 27 | #if ! (defined(lint) || defined(RC_INVOKED)) 28 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 29 | #pragma warning(disable:4103) 30 | #if !(defined( MIDL_PASS )) || defined( __midl ) 31 | #pragma pack(push,2) 32 | #else 33 | #pragma pack(2) 34 | #endif 35 | #else 36 | #pragma pack(2) 37 | #endif 38 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 39 | -------------------------------------------------------------------------------- /include/clr/pshpack1.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | // 6 | 7 | // 8 | // =========================================================================== 9 | // File: pshpack1.h 10 | // 11 | // =========================================================================== 12 | 13 | /*++ 14 | 15 | Abstract: 16 | 17 | This file turns 1 byte packing of structures on. (That is, it disables 18 | automatic alignment of structure fields.) An include file is needed 19 | because various compilers do this in different ways. For Microsoft 20 | compatible compilers, this files uses the push option to the pack pragma 21 | so that the poppack.h include file can restore the previous packing 22 | reliably. 23 | 24 | The file poppack.h is the complement to this file. 25 | 26 | --*/ 27 | 28 | #if ! (defined(lint) || defined(RC_INVOKED)) 29 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 30 | #pragma warning(disable:4103) 31 | #if !(defined( MIDL_PASS )) || defined( __midl ) 32 | #pragma pack(push,1) 33 | #else 34 | #pragma pack(1) 35 | #endif 36 | #else 37 | #pragma pack(1) 38 | #endif 39 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 40 | -------------------------------------------------------------------------------- /include/clr/pshpack4.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | // 6 | 7 | // 8 | // =========================================================================== 9 | // File: pshpack4.h 10 | // 11 | // =========================================================================== 12 | 13 | /*++ 14 | 15 | Abstract: 16 | 17 | This file turns 4 byte packing of structures on. (That is, it disables 18 | automatic alignment of structure fields.) An include file is needed 19 | because various compilers do this in different ways. For Microsoft 20 | compatible compilers, this files uses the push option to the pack pragma 21 | so that the poppack.h include file can restore the previous packing 22 | reliably. 23 | 24 | The file poppack.h is the complement to this file. 25 | 26 | --*/ 27 | 28 | #if ! (defined(lint) || defined(RC_INVOKED)) 29 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 30 | #pragma warning(disable:4103) 31 | #if !(defined( MIDL_PASS )) || defined( __midl ) 32 | #pragma pack(push,4) 33 | #else 34 | #pragma pack(4) 35 | #endif 36 | #else 37 | #pragma pack(4) 38 | #endif 39 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 40 | -------------------------------------------------------------------------------- /include/clr/pshpack8.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | // 6 | 7 | // 8 | // =========================================================================== 9 | // File: pshpack8.h 10 | // 11 | // =========================================================================== 12 | 13 | /*++ 14 | 15 | Abstract: 16 | 17 | This file turns 8 byte packing of structures on. (That is, it disables 18 | automatic alignment of structure fields.) An include file is needed 19 | because various compilers do this in different ways. For Microsoft 20 | compatible compilers, this files uses the push option to the pack pragma 21 | so that the poppack.h include file can restore the previous packing 22 | reliably. 23 | 24 | The file poppack.h is the complement to this file. 25 | 26 | --*/ 27 | 28 | #if ! (defined(lint) || defined(RC_INVOKED)) 29 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 30 | #pragma warning(disable:4103) 31 | #if !(defined( MIDL_PASS )) || defined( __midl ) 32 | #pragma pack(push,8) 33 | #else 34 | #pragma pack(8) 35 | #endif 36 | #else 37 | #pragma pack(8) 38 | #endif 39 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 40 | -------------------------------------------------------------------------------- /test/llilc_roslyn_stage.cmd: -------------------------------------------------------------------------------- 1 | REM Usage: llilc_roslyn_stage.cmd workspace buildsubdir stagedir 2 | REM 3 | REM Will first delete (if present) and then create %workspace%/roslyn/%stagedir% 4 | REM directory and set it up as the directory 5 | REM from which Roslyn will run on CoreClr, with LLILC as JIT. 6 | REM buildsubdir is the subdirectory of the workspace where LLVM (and LLILC) were built. 7 | 8 | setlocal 9 | set WORKSPACE=%1 10 | set buildsubdir=%2 11 | set buildtype=%3 12 | set stagedir=%4 13 | cd %WORKSPACE% 14 | call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x86 15 | echo on 16 | cd roslyn 17 | if exist %stagedir%/ rd /s /q %stagedir% 18 | mkdir %stagedir% 19 | xcopy /y %buildsubdir%\bin\%buildtype%\llilcjit.dll %stagedir% 20 | xcopy /S /Q Binaries\Debug\core-clr\* %stagedir% 21 | xcopy /S /Q /Y %WORKSPACE%\coreclr\bin\Product\Windows_NT.x64.Debug\* %stagedir% 22 | set command=python %WORKSPACE%\llvm\tools\llilc\test\llilc_run.py -c %WORKSPACE%\roslyn\%stagedir% -r corerun.exe /v -a %WORKSPACE%\roslyn\%stagedir%\csc.exe -- %%* 23 | echo %command% > %stagedir%\runcsc.cmd 24 | echo exit /b %%ERRORLEVEL%% >> %stagedir%\runcsc.cmd 25 | 26 | rd /s /q Binaries 27 | msbuild /m /v:d /p:CSCTOOLPATH=%WORKSPACE%\roslyn\%stagedir% /p:CSCTOOLEXE=runcsc.cmd /p:UseRoslynAnalyzers=false src/Compilers/CSharp/CscCore/CscCore.csproj 28 | endlocal 29 | -------------------------------------------------------------------------------- /include/clr/poppack.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | // 6 | 7 | // 8 | // =========================================================================== 9 | // File: poppack.h 10 | // 11 | // =========================================================================== 12 | /* 13 | Abstract: 14 | 15 | This file turns packing of structures off. (That is, it enables 16 | automatic alignment of structure fields.) An include file is needed 17 | because various compilers do this in different ways. 18 | 19 | poppack.h is the complement to pshpack?.h. An inclusion of poppack.h 20 | MUST ALWAYS be preceded by an inclusion of one of pshpack?.h, in one-to-one 21 | correspondence. 22 | 23 | For Microsoft compatible compilers, this file uses the pop option 24 | to the pack pragma so that it can restore the previous saved by the 25 | pshpack?.h include file. 26 | 27 | */ 28 | 29 | #if ! (defined(lint) || defined(RC_INVOKED)) 30 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 31 | #pragma warning(disable:4103) 32 | #if !(defined( MIDL_PASS )) || defined( __midl ) 33 | #pragma pack(pop) 34 | #else 35 | #pragma pack() 36 | #endif 37 | #else 38 | #pragma pack() 39 | #endif 40 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 41 | -------------------------------------------------------------------------------- /lib/ObjWriter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(objwriter) 2 | 3 | include_directories(${LLVM_INCLUDE_DIRS}) 4 | include_directories(${CORECLR_INCLUDE}) 5 | add_definitions(${LLVM_DEFINITIONS}) 6 | 7 | if (WIN32) 8 | # Create .def file containing a list of exports preceeded by 9 | # 'EXPORTS'. The file "objwriter.exports" already contains the list, so we 10 | # massage it into the correct format here to create "objwriter.exports.def". 11 | set(OBJWRITER_EXPORTS_DEF ${CMAKE_CURRENT_BINARY_DIR}/objwriter.exports.def) 12 | set(OBJWRITER_EXPORTS_DEF_TEMP ${OBJWRITER_EXPORTS_DEF}.txt) 13 | file(READ "objwriter.exports" exports_list) 14 | file(WRITE ${OBJWRITER_EXPORTS_DEF_TEMP} "LIBRARY OBJWRITER\n") 15 | file(APPEND ${OBJWRITER_EXPORTS_DEF_TEMP} "EXPORTS\n") 16 | file(APPEND ${OBJWRITER_EXPORTS_DEF_TEMP} ${exports_list}) 17 | # Copy the file only if it has changed. 18 | execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different 19 | ${OBJWRITER_EXPORTS_DEF_TEMP} ${OBJWRITER_EXPORTS_DEF}) 20 | endif() 21 | 22 | # Now build our tools 23 | add_library(objwriter 24 | SHARED 25 | objwriter.cpp 26 | ${OBJWRITER_EXPORTS_DEF} 27 | ) 28 | 29 | # Find the libraries that correspond to the LLVM components 30 | # that we wish to use 31 | 32 | llvm_map_components_to_libnames(llvm_libs 33 | ${LLVM_TARGETS_TO_BUILD} 34 | ) 35 | 36 | # Link against LLVM libraries 37 | target_link_libraries(objwriter 38 | ${llvm_libs}) 39 | -------------------------------------------------------------------------------- /lib/ObjWriter/jitDebugInfo.h: -------------------------------------------------------------------------------- 1 | #ifndef JIT_DEBUG_INFO_H 2 | #define JIT_DEBUG_INFO_H 3 | 4 | typedef unsigned int DWORD; 5 | #define _TARGET_AMD64_ 1 6 | 7 | #include "cordebuginfo.h" 8 | #include "cvconst.h" 9 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 10 | 11 | struct DebugLocInfo { 12 | int NativeOffset; 13 | int FileId; 14 | int LineNumber; 15 | int ColNumber; 16 | }; 17 | 18 | struct DebugVarInfo { 19 | std::string Name; 20 | int TypeIndex; 21 | bool IsParam; 22 | std::vector Ranges; 23 | 24 | DebugVarInfo() {} 25 | DebugVarInfo(char *ArgName, int ArgTypeIndex, bool ArgIsParam) 26 | : Name(ArgName), TypeIndex(ArgTypeIndex), IsParam(ArgIsParam) {} 27 | }; 28 | 29 | typedef unsigned short CVRegMapping; 30 | 31 | #define CVREGDAT(p2, cv) cv 32 | 33 | const CVRegMapping cvRegMapAmd64[] = { 34 | CVREGDAT(REGNUM_RAX, CV_AMD64_RAX), CVREGDAT(REGNUM_RCX, CV_AMD64_RCX), 35 | CVREGDAT(REGNUM_RDX, CV_AMD64_RDX), CVREGDAT(REGNUM_RBX, CV_AMD64_RBX), 36 | CVREGDAT(REGNUM_RSP, CV_AMD64_RSP), CVREGDAT(REGNUM_RBP, CV_AMD64_RBP), 37 | CVREGDAT(REGNUM_RSI, CV_AMD64_RSI), CVREGDAT(REGNUM_RDI, CV_AMD64_RDI), 38 | CVREGDAT(REGNUM_R8, CV_AMD64_R8), CVREGDAT(REGNUM_R9, CV_AMD64_R9), 39 | CVREGDAT(REGNUM_R10, CV_AMD64_R10), CVREGDAT(REGNUM_R11, CV_AMD64_R11), 40 | CVREGDAT(REGNUM_R12, CV_AMD64_R12), CVREGDAT(REGNUM_R13, CV_AMD64_R13), 41 | CVREGDAT(REGNUM_R14, CV_AMD64_R14), CVREGDAT(REGNUM_R15, CV_AMD64_R15)}; 42 | 43 | #endif // JIT_DEBUG_INFO_H 44 | -------------------------------------------------------------------------------- /include/Reader/gverify.h: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/gverify.h ---------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declares data structures useful for MSIL bytecode verification. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef MSIL_READER_GVERIFY_H 17 | #define MSIL_READER_GVERIFY_H 18 | 19 | #include "vtypeinfo.h" 20 | 21 | class FlowGraphNode; 22 | 23 | // global verification structures 24 | typedef struct { 25 | FlowGraphNode *Block; 26 | int32_t TosIndex; 27 | int32_t SsaIndex; 28 | } TOSTemp; 29 | 30 | struct TagGlobalVerifyData; 31 | typedef struct TagGlobalVerifyData GlobalVerifyData; 32 | 33 | enum InitState { 34 | ThisUnreached = -1, 35 | ThisUnInit = 0, 36 | ThisInited = 1, 37 | ThisInconsistent = 2, 38 | ThisEHReached = 3 39 | }; 40 | 41 | struct TagGlobalVerifyData { 42 | int32_t MinStack; 43 | int32_t MaxStack; 44 | int32_t NetStack; 45 | int32_t TOSTempsCount; 46 | TOSTemp *TOSTemps; 47 | int32_t SsaBase; 48 | 49 | int32_t StkDepth; 50 | VerType *TiStack; 51 | bool IsOnWorklist, BlockIsBad; 52 | GlobalVerifyData *WorklistPrev, *WorklistNext; 53 | FlowGraphNode *Block; 54 | InitState ThisInitialized; 55 | bool ContainsCtorCall; 56 | }; 57 | 58 | #endif // MSIL_READER_GVERIFY_H 59 | -------------------------------------------------------------------------------- /include/Reader/imeta.def: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/imeta.def ----------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declares constants useful for imeta.h interface 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #define mdtJitHelper 0x73000000 17 | #define mdtInterfaceOffset 0x74000000 18 | #define mdtCodeOffset 0x75000000 19 | #define mdtSyncHandle 0x76000000 20 | #define mdtVarArgsHandle 0x77000000 21 | #define mdtPInvokeCalliHandle 0x78000000 22 | #define mdtIBCProfHandle 0x79000000 23 | 24 | // When returning a struct with gc through a hidden param, we 25 | // call the ASSIGN_STRUCT helper and we need a dummy token to pass 26 | // around with the class handle we got from the method sig. 27 | #define mdtMBReturnHandle 0x7A000000 28 | #define mdtGSCookie 0x7B000000 29 | 30 | #define mdtJMCHandle 0x7C000000 31 | #define mdtCaptureThreadGlobal 0x7D000000 32 | #define mdtModuleID 0x7E000000 33 | 34 | // For instantiation parameters where we have a handle, but no token 35 | #define mdtMethodHandle 0x7F000000 36 | #define mdtClassHandle 0x80000000 37 | 38 | #define mdtVarArgsSigHandle 0x81000000 39 | #define mdtVarArgsMDHandle 0x82000000 40 | #define mdtVarArgsMSHandle 0x83000000 41 | -------------------------------------------------------------------------------- /lib/CoreDisTools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(coredistools) 2 | 3 | get_filename_component(LLILC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../../include ABSOLUTE) 4 | 5 | include_directories(${LLVM_INCLUDE_DIRS} 6 | ${CORECLR_INCLUDE}) 7 | 8 | add_definitions(${LLVM_DEFINITIONS}) 9 | 10 | if (WIN32) 11 | # Create .def file containing a list of exports preceeded by 12 | # 'EXPORTS'. The file "coredistools.exports" already contains the list, 13 | # so we massage it into the correct format here to create 14 | # "coredistools.exports.def". 15 | set(COREDISTOOLS_EXPORTS_DEF ${CMAKE_CURRENT_BINARY_DIR}/coredistools.exports.def) 16 | set(COREDISTOOLS_EXPORTS_DEF_TEMP ${COREDISTOOLS_EXPORTS_DEF}.txt) 17 | file(READ "coredistools.exports" exports_list) 18 | file(WRITE ${COREDISTOOLS_EXPORTS_DEF_TEMP} "LIBRARY COREDISTOOLS\n") 19 | file(APPEND ${COREDISTOOLS_EXPORTS_DEF_TEMP} "EXPORTS\n") 20 | file(APPEND ${COREDISTOOLS_EXPORTS_DEF_TEMP} ${exports_list}) 21 | # Copy the file only if it has changed. 22 | execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different 23 | ${COREDISTOOLS_EXPORTS_DEF_TEMP} ${COREDISTOOLS_EXPORTS_DEF}) 24 | endif() 25 | 26 | # Now build our tools 27 | add_library(coredistools 28 | SHARED 29 | coredistools.cpp 30 | ${COREDISTOOLS_EXPORTS_DEF} 31 | ) 32 | 33 | # Find the libraries that correspond to the LLVM components 34 | # that we wish to use 35 | llvm_map_components_to_libnames(llvm_libs 36 | ${LLVM_TARGETS_TO_BUILD} 37 | ) 38 | 39 | # Link against LLVM libraries 40 | target_link_libraries(coredistools 41 | ${llvm_libs}) 42 | 43 | # Output the export header corresponding to the coredistools library 44 | add_custom_command(TARGET coredistools POST_BUILD 45 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 46 | ${CORECLR_INCLUDE}/coredistools.h 47 | $/include/coredistools.h) 48 | -------------------------------------------------------------------------------- /lib/CoreDisTools/.nuget/runtime.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimes": { 3 | "win-x64": { 4 | "Microsoft.NETCore.CoreDisTools": { 5 | "runtime.win-x64.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00005" 6 | } 7 | }, 8 | "ubuntu.14.04-x64": { 9 | "Microsoft.NETCore.CoreDisTools": { 10 | "runtime.ubuntu.14.04-x64.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 11 | } 12 | }, 13 | "ubuntu.16.04-x64": { 14 | "Microsoft.NETCore.CoreDisTools": { 15 | "runtime.ubuntu.16.04-x64.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 16 | } 17 | }, 18 | "centos.7.1-x64": { 19 | "Microsoft.NETCore.CoreDisTools": { 20 | "runtime.centos.7.1-x64.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 21 | } 22 | }, 23 | "osx.10.11-x64": { 24 | "Microsoft.NETCore.CoreDisTools": { 25 | "runtime.osx.10.11-x64.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 26 | } 27 | }, 28 | "win-x86": { 29 | "Microsoft.NETCore.CoreDisTools": { 30 | "runtime.win-x86.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00005" 31 | } 32 | }, 33 | "ubuntu.14.04-x86": { 34 | "Microsoft.NETCore.CoreDisTools": { 35 | "runtime.ubuntu.14.04-x86.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 36 | } 37 | }, 38 | "ubuntu.16.04-x86": { 39 | "Microsoft.NETCore.CoreDisTools": { 40 | "runtime.ubuntu.16.04-x86.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 41 | } 42 | }, 43 | "centos.7.1-x86": { 44 | "Microsoft.NETCore.CoreDisTools": { 45 | "runtime.centos.7.1-x86.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 46 | } 47 | }, 48 | "osx.10.11-x86": { 49 | "Microsoft.NETCore.CoreDisTools": { 50 | "runtime.osx.10.11-x86.Microsoft.NETCore.CoreDisTools": "1.0.1-prerelease-00002" 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /include/clr/misc.h: -------------------------------------------------------------------------------- 1 | //===----------------- include/clr/misc.h -----------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Miscellaneous helper functions defined in Windows CRT 13 | /// Explicitly defined here for use in other platforms. 14 | /// 15 | //===----------------------------------------------------------------------===// 16 | 17 | #ifndef _MISC_H_ 18 | #define _MISC_H_ 19 | 20 | #if !defined(_MSC_VER) 21 | 22 | //-- Bit Manipulation -- 23 | 24 | #ifndef _rotl 25 | inline unsigned int __cdecl _rotl(unsigned int value, int shift) 26 | { 27 | unsigned int retval = 0; 28 | 29 | shift &= 0x1f; 30 | retval = (value << shift) | (value >> (sizeof(int)* 8 - shift)); 31 | return retval; 32 | } 33 | #endif 34 | 35 | #ifndef _rotr 36 | inline unsigned int __cdecl _rotr(unsigned int value, int shift) 37 | { 38 | unsigned int retval; 39 | 40 | shift &= 0x1f; 41 | retval = (value >> shift) | (value << (sizeof(int)* 8 - shift)); 42 | return retval; 43 | } 44 | #endif 45 | 46 | //-- Memory move/copy/set/cmp operations 47 | 48 | #define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length))) 49 | #define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length)) 50 | #define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length)) 51 | #define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length)) 52 | #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) 53 | 54 | #define MoveMemory RtlMoveMemory 55 | #define CopyMemory RtlCopyMemory 56 | #define FillMemory RtlFillMemory 57 | #define ZeroMemory RtlZeroMemory 58 | 59 | 60 | #endif // defined(MSC_VER) 61 | #endif // _MISC_H_ 62 | -------------------------------------------------------------------------------- /include/GcInfo/Target.h: -------------------------------------------------------------------------------- 1 | //===---- include/gcinfo/target.h -------------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Target specific definitions for GCInfo generation 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef GCINFO_TARGET_H 17 | #define GCINFO_TARGET_H 18 | 19 | #include "global.h" 20 | #include "corinfo.h" 21 | 22 | #if (defined(_TARGET_X86_) || defined(_TARGET_X64_) || \ 23 | defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)) 24 | 25 | // Identify the frame-pointer register number 26 | 27 | #if defined(_TARGET_X86_) 28 | #define REGNUM_FPBASE ICorDebugInfo::RegNum::REGNUM_EBP 29 | #elif (defined(_TARGET_AMD64_) || defined(_TARGET_X64_)) 30 | #define REGNUM_FPBASE ICorDebugInfo::RegNum::REGNUM_RBP 31 | #elif defined(_TARGET_ARM64_) 32 | #define REGNUM_FPBASE ICorDebugInfo::RegNum::REGNUM_FP 33 | #endif 34 | 35 | #if (defined(_TARGET_X86_) || defined(_TARGET_X64_) || defined(_TARGET_AMD64_)) 36 | 37 | // Define encodings for DWARF registers 38 | // Size variants (ex: AL,AH,AX,EAX,RAX) all get the same Dwarf register number 39 | 40 | #define DW_RAX 0 41 | #define DW_RBX 3 42 | #define DW_RCX 2 43 | #define DW_RDX 1 44 | #define DW_RSI 4 45 | #define DW_RDI 5 46 | #define DW_RBP 6 47 | #define DW_RSP 7 48 | #define DW_RIP 16 49 | #define DW_R8 8 50 | #define DW_R9 9 51 | #define DW_R10 10 52 | #define DW_R11 11 53 | #define DW_R12 12 54 | #define DW_R13 13 55 | #define DW_R14 14 56 | #define DW_R15 15 57 | 58 | #define DW_STACK_POINTER DW_RSP 59 | 60 | #elif defined(_TARGET_ARM64_) 61 | 62 | #define DW_FRAME_POINTER 29 63 | #define DW_STACK_POINTER 31 64 | 65 | #endif 66 | 67 | #else 68 | #error GCTables not implemented for this target 69 | #endif // defined(_TARGET_X86_ || _TARGET_X64_ || _TARGET_AMD64_ || 70 | // _TARGET_ARM64_) 71 | 72 | #endif // GCINFO_TARGET_H 73 | -------------------------------------------------------------------------------- /test/llilc_hook.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Title :llilc_hook.py 4 | # Description : 5 | # 6 | # Hook is called from runjs which during its build step requires llilc specific 7 | # setup. Currently all that is required is just a simple copy of llilcjit.dll. 8 | # The script requires two arguments to function the path of llilcjit.dll and the 9 | # bin path to copy into. 10 | # 11 | # Usage: llilc_hook.py 12 | # 13 | ################################################################################ 14 | 15 | import os 16 | import shutil 17 | import sys 18 | 19 | ################################################################################ 20 | 21 | def copydll(llilc_dll, drop_path): 22 | print "Copying %s into %s." % (llilc_dll, drop_path) 23 | 24 | shutil.copy2(llilc_dll, drop_path) 25 | 26 | print "Copied successfully." 27 | 28 | def handle_args(args): 29 | if (len(args) < 2): 30 | print "Incorrect number of arguments." 31 | 32 | print_usage() 33 | 34 | return None, None 35 | 36 | if (os.path.isfile(args[1]) is not True): 37 | print "lliljit.dll must be a valid file." 38 | 39 | print_usage() 40 | 41 | return None, None 42 | 43 | if (os.path.isdir(args[2]) is not True): 44 | print "run.js bin must be a valid directory." 45 | 46 | print_usage() 47 | 48 | return None, None 49 | 50 | return args[1], args[2] 51 | 52 | def print_usage(): 53 | 54 | # User has run the script incorrectly 55 | 56 | print "Hook to copy llilcdll.jit during runjs run." 57 | print "" 58 | print "Usage: llilcHook.py " 59 | print "" 60 | 61 | if __name__ == "__main__": 62 | 63 | print "Starting LLILC Hook: Last Updated - 26-Jul-15" 64 | 65 | # Expect two arguments, the first is the path to 66 | # llilc and the other is the directory to copy into. 67 | 68 | llilc_path, drop_path = handle_args(sys.argv) 69 | 70 | if (llilc_path is None or drop_path is None): 71 | sys.exit(-1) 72 | 73 | # Copy the dll 74 | copydll(llilc_path, drop_path) 75 | -------------------------------------------------------------------------------- /include/Jit/compiler.h: -------------------------------------------------------------------------------- 1 | //===--------------- include/Jit/compiler.h ---------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declaration of the compiler functor used in the ORC infrastructure 13 | /// to compile a module. 14 | /// 15 | //===----------------------------------------------------------------------===// 16 | 17 | #ifndef COMPILER_H 18 | #define COMPILER_H 19 | 20 | #include "GcInfo.h" 21 | #include "LLILCJit.h" 22 | #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" 23 | #include "llvm/IR/LegacyPassManager.h" 24 | #include "llvm/MC/MCContext.h" 25 | #include "llvm/Object/ObjectFile.h" 26 | #include "llvm/Target/TargetMachine.h" 27 | 28 | namespace llvm { 29 | namespace orc { 30 | 31 | /// \brief Default compile functor: Takes a single IR module and returns an 32 | /// ObjectFile. 33 | class LLILCCompiler { 34 | public: 35 | /// \brief Construct a simple compile functor with the given target. 36 | LLILCCompiler(TargetMachine &TM) : TM(TM) {} 37 | 38 | /// \brief Compile a Module to an ObjectFile. 39 | object::OwningBinary operator()(Module &M) const { 40 | SmallVector ObjBufferSV; 41 | raw_svector_ostream ObjStream(ObjBufferSV); 42 | 43 | legacy::PassManager PM; 44 | MCContext *Ctx; 45 | if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) 46 | llvm_unreachable("Target does not support MC emission."); 47 | PM.add(new GcInfoRecorder()); 48 | PM.run(M); 49 | std::unique_ptr ObjBuffer( 50 | new ObjectMemoryBuffer(std::move(ObjBufferSV))); 51 | ErrorOr> Obj = 52 | object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); 53 | // TODO: Actually report errors helpfully. 54 | typedef object::OwningBinary OwningObj; 55 | if (Obj) 56 | return OwningObj(std::move(*Obj), std::move(ObjBuffer)); 57 | return OwningObj(nullptr, nullptr); 58 | } 59 | 60 | private: 61 | TargetMachine &TM; 62 | }; 63 | } // namespace orc 64 | } // namespace llvm 65 | #endif // COMPILER_H 66 | -------------------------------------------------------------------------------- /Documentation/Contributing.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | ## Workflow 4 | We follow the standard [GitHub workflow](https://guides.github.com/introduction/flow/). 5 | We like to track ongoing work using GitHub issues as described in the 6 | [developer workflow document](Developer-Workflow.md). 7 | - To submit changes, please create a personal fork of the LLILC repo, push 8 | your changes there, and issue a pull request to merge those changes into 9 | the master branch of the main repository. 10 | - Please be sure to perform the appropriate [formatting](#coding-conventions-and-formatting) 11 | and [testing](#testing) as described below before submitting your pull 12 | request. 13 | - Whenever possible, please divide any changes you want to make into a 14 | series of small, incremental changes that can be submitted and reviewed 15 | independently. Doing so will 16 | - Make the code easier to review (allowing for higher quality review 17 | feedback) 18 | - Keep your work aligned with LLILC's direction and architecture along 19 | the way (avoiding wasted time pursuing a direction that ultimately 20 | gets abandoned) 21 | - Spare you the pain of keeping large outstanding changes up-to-date 22 | with tip-of-tree 23 | - Occasionally we'll deviate from this model and use long-lived branches, 24 | which follow [another workflow](Long-Running-Branch-Workflow.md). 25 | 26 | ## Coding Conventions and Formatting 27 | Any code being submitted must be formatted per the instructions in the 28 | [code formatting document](Code-Formatting.md). We follow LLVM's coding 29 | conventions, as described in our [coding conventions document](llilc-Coding-Conventions-and-Commenting-Style.md). 30 | 31 | The clang-format and clang-tidy exes used in the lab are generated nightly 32 | and can be downloaded for local use: 33 | [here for clang-format](http://dotnet-ci.cloudapp.net/view/dotnet_llilc/job/dotnet_llilc_code_formatter_drop/lastSuccessfulBuild/Azure/processDownloadRequest/build/Release/bin/clang-format.exe) 34 | and [here for clang-tidy](http://dotnet-ci.cloudapp.net/view/dotnet_llilc/job/dotnet_llilc_code_formatter_drop/lastSuccessfulBuild/Azure/processDownloadRequest/build/Release/bin/clang-tidy.exe). 35 | 36 | ## Testing 37 | The [test harness document](Testing.md) describes the tests we expect to be 38 | run for each submission and how to run them. 39 | 40 | ## Open Areas 41 | Looking for an area to contribute to? See our [list of open areas](Areas-To-Contribute.md). 42 | -------------------------------------------------------------------------------- /lib/Jit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | get_filename_component(LLILC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../../include ABSOLUTE) 2 | 3 | include_directories(${LLILC_INCLUDES}/clr 4 | ${LLILC_INCLUDES}/Pal 5 | ${LLILC_INCLUDES}/GcInfo 6 | ${LLILC_INCLUDES}/Jit 7 | ${LLILC_INCLUDES}/Reader) 8 | 9 | set(LLVM_LINK_COMPONENTS 10 | Analysis 11 | CodeGen 12 | Core 13 | DebugInfoDWARF 14 | ExecutionEngine 15 | IPO 16 | IRReader 17 | OrcJIT 18 | MC 19 | Support 20 | native 21 | ) 22 | 23 | set(LLILCJIT_LINK_LIBRARIES LLILCReader GcInfo) 24 | 25 | if (WIN32) 26 | # Create .def file containing a list of exports preceeded by 27 | # 'EXPORTS'. The file "LLILCJit.exports" already contains the list, so we 28 | # massage it into the correct format here to create "LLILCJit.exports.def". 29 | set(LLILCJIT_EXPORTS_DEF ${CMAKE_CURRENT_BINARY_DIR}/LLILCJit.exports.def) 30 | set(LLILCJIT_EXPORTS_DEF_TEMP ${LLILCJIT_EXPORTS_DEF}.txt) 31 | file(READ "LLILCJit.exports" exports_list) 32 | file(WRITE ${LLILCJIT_EXPORTS_DEF_TEMP} "LIBRARY LLILCJIT\n") 33 | file(APPEND ${LLILCJIT_EXPORTS_DEF_TEMP} "EXPORTS\n") 34 | file(APPEND ${LLILCJIT_EXPORTS_DEF_TEMP} ${exports_list}) 35 | 36 | # Copy the file only if it has changed. 37 | execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different 38 | ${LLILCJIT_EXPORTS_DEF_TEMP} ${LLILCJIT_EXPORTS_DEF}) 39 | 40 | set(SHARED_LIB_SOURCES ${SOURCES} ${LLILCJIT_EXPORTS_DEF}) 41 | 42 | # For windows we need to specify the CoreCLR environment 43 | set(LLILC_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}-coreclr") 44 | else() 45 | if (UNIX) 46 | set(LLILCJIT_LINK_LIBRARIES ${LLILCJIT_LINK_LIBRARIES} coreclr) 47 | endif() 48 | 49 | set(SHARED_LIB_SOURCES ${SOURCES}) 50 | 51 | # For non-windows we can use the default triple for now 52 | set(LLILC_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}") 53 | endif() 54 | 55 | add_definitions(-DSTANDALONE_BUILD) 56 | 57 | message(STATUS "LLILC_TARGET_TRIPLE is ${LLILC_TARGET_TRIPLE}") 58 | add_definitions(-DLLILC_TARGET_TRIPLE="${LLILC_TARGET_TRIPLE}") 59 | 60 | set(LLVM_EXPORTED_SYMBOL_FILE ${LLILCJIT_EXPORTS_DEF}) 61 | 62 | add_llilcjit_library( 63 | llilcjit 64 | SHARED 65 | jitpch.cpp 66 | LLILCJit.cpp 67 | EEMemoryManager.cpp 68 | jitoptions.cpp 69 | utility.cpp 70 | ${LLILCJIT_EXPORTS_DEF} 71 | ) 72 | 73 | add_dependencies(llilcjit LLILCReader GcInfo) 74 | 75 | target_link_libraries( 76 | llilcjit 77 | PRIVATE 78 | ${LLILCJIT_LINK_LIBRARIES} 79 | ) 80 | -------------------------------------------------------------------------------- /Documentation/Getting-Started-For-Linux-and-OS-X.md: -------------------------------------------------------------------------------- 1 | # Getting Started for Linux and OS X 2 | 3 | ## Caveats 4 | 5 | Support for LLILC on Linux and OS X is still in its early stages. While the 6 | instructions below should get you up and running, the workflow is a bit rough 7 | around the edges and there are certainly holes with respect to what is 8 | supported. The most obvious missing piece is that without following the steps 9 | on the [CoreCLR wiki](https://github.com/dotnet/coreclr/wiki/Building-and-Running-CoreCLR-on-Linux) 10 | to obtain a version of mscorlib that is functional on these platforms, there 11 | is no way to run or test the output of the LLILC build. 12 | 13 | ## Prerequisites 14 | 15 | The prerequisites for building LLILC on Linux and OS X are the same as the 16 | [prerequisites for building LLVM](http://llvm.org/docs/GettingStarted.html#software) 17 | with CMake unioned with the prerequisites for building [CoreCLR](https://github.com/dotnet/coreclr). 18 | 19 | * [GCC](http://gcc.gnu.org) >= 4.7.0 20 | * [Clang](http://clang.llvm.org/) >= 3.5.0 21 | * [Python](http://python.org) >= 2.7 22 | * [CMake](http://cmake.org) >= 2.8.8 23 | * [libunwind](http://www.nongnu.org/libunwind/) >= 1.1 24 | 25 | In addition, LLILC requires very recent builds of the [Microsoft fork of LLVM](https://github.com/microsoft/llvm) 26 | and [CoreCLR](https://github.com/dotnet/coreclr). Instructions for fetching 27 | and building both can be found below. 28 | 29 | ## Getting and building the code 30 | 31 | 1. Clone and build CoreCLR: 32 | 33 | ``` 34 | $ git clone https://github.com/dotnet/coreclr 35 | $ cd coreclr 36 | $ ./build.sh 37 | $ cd .. 38 | ``` 39 | 40 | After it completes, the build will indicate where the CoreCLR binaries 41 | are available. Make a note of this location 42 | (typically binaries/Product/.x64.debug). 43 | 44 | 2. Clone the Microsoft fork of LLVM: 45 | 46 | ``` 47 | $ git clone -b MS https://github.com/microsoft/llvm 48 | ``` 49 | 50 | 3. Clone LLILC: 51 | 52 | ``` 53 | $ cd llvm/tools 54 | $ git clone https://github.com/dotnet/llilc 55 | $ cd .. 56 | ``` 57 | 58 | 4. Configure LLVM and LLILC: 59 | 60 | ``` 61 | $ mkdir build 62 | $ cd build 63 | $ cmake -DWITH_CORECLR=../../coreclr/path/to/CoreCLR/binaries -DLLVM_OPTIMIZED_TABLEGEN=ON .. 64 | ``` 65 | 66 | Ie, ../../coreclr/bin/Product/OSX.x64.Debug 67 | 68 | 5. Build LLVM and LLILC: 69 | 70 | ``` 71 | $ make 72 | ``` 73 | 74 | If all goes well, the build will complete without errors. 75 | -------------------------------------------------------------------------------- /Documentation/llilc-milestones.md: -------------------------------------------------------------------------------- 1 | # LLILC Bring-Up Milestones 2 | 3 | To meet the overarching goal of fully functional JIT and AOT code 4 | generators we've broken out some intermediate milestones that we 5 | think are good steps along the way. Each of these milestones represent 6 | a new level of functionality or robustness on the way to a production 7 | quality tool. 8 | 9 | ## Milestones 10 | 11 | * [X] **"Hello World"** - Using LLILC, JIT all the methods for runtime 12 | start-up and "Hello World" console app execution. This is the classic first 13 | app. Success is that the CLR comes up, and prints "Hello World" and 14 | exits cleanly. 15 | * [X] **Roslyn compiling "Hello World" on Windows** - Using LLILC, JIT 16 | all of Roslyn through a compile of "Hello World" then JIT and run 17 | "Hello World" on Windows. This is our first larger RWC test case. 18 | * [X] **Roslyn compiling "Hello World" on Linux** - Using LLILC, JIT all 19 | of Roslyn through a compile of "Hello World" then JIT and run on Linux. 20 | (Note: the run of Roslyn and everything else is on Linux) Porting this from 21 | Windows was a matter of a few commits. LLVM portability appears to be 22 | living up to its billing. 23 | * [ ] **Roslyn compiling Roslyn on Windows** - Full Roslyn compiling itself for 24 | CoreCLR on Windows with the JIT. 25 | * [ ] **Roslyn compiling Roslyn on Linux** - Full Roslyn compiling itself for 26 | CoreCLR on Linux with the JIT. 27 | * [ ] **NGen Roslyn on Windows/Linux** - Use crossgen to compile all of Roslyn at 28 | install time using LLILC. 29 | * [ ] **corefx tests on Windows** - Run corefx unit tests as an integration 30 | test. This tests a broad set of framework functionality. Success is a clean 31 | test run using run-test from the corefx repo. 32 | * [ ] **corefx tests on Linux** - Same as above just on Linux. 33 | * [ ] **JIT SelfHost on Linux** - Pass ~6k Jit SelfHost tests on Linux. 34 | These tests are currently being added to coreclr. Success will 35 | be running clean for the whole set. 36 | * [ ] **JIT SelfHost Stress on Linux** - Pass ~6k JIT SelfHost tests under 37 | GCStress. This will do basic validation of the GC implementation. 38 | * [ ] **AOT Roslyn on Linux** - Full Roslyn compiling itself as a command line 39 | AOT tool. 40 | 41 | We'll check these off as we get through them but we're evaluating open issues 42 | with respect to how fixing them will advance these goals. 43 | 44 | Note: To add a milestone to this list open an issue to start the discussion, 45 | then create a PR for a community review. 46 | -------------------------------------------------------------------------------- /include/Reader/options.h: -------------------------------------------------------------------------------- 1 | //===----------------- include/Jit/options.h -------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declaration of the Options class that encapsulates JIT options 13 | /// extracted from CoreCLR config values. 14 | /// 15 | //===----------------------------------------------------------------------===// 16 | 17 | #ifndef OPTIONS_H 18 | #define OPTIONS_H 19 | 20 | #include "utility.h" 21 | 22 | struct LLILCJitContext; 23 | 24 | /// \brief Enum for JIT optimization level. 25 | enum class OptLevel { 26 | INVALID, 27 | DEBUG_CODE, ///< No/Low optimization to preserve debug semantics. 28 | BLENDED_CODE, ///< Fast code that remains sensitive to code size. 29 | SMALL_CODE, ///< Optimized for small size. 30 | FAST_CODE ///< Optimized for speed. 31 | }; 32 | 33 | /// \brief Enum for LLVM IR Dump Level 34 | enum class DumpLevel { 35 | NODUMP, ///< Do not dump any LLVM IR or summary. 36 | SUMMARY, ///< Only dump one line summary per method. 37 | VERBOSE ///< Dump full LLVM IR and method summary. 38 | }; 39 | 40 | // Macro to determine the default behavior of automatically 41 | // detecting tail calls (without the "tail." opcode in MSIL). 42 | #define DEFAULT_TAIL_CALL_OPT 1 43 | 44 | /// \brief The JIT options provided via CoreCLR configurations. 45 | /// 46 | /// This class exposes the JIT options flags. This interface is passed 47 | /// around to Options consumers to give them access to the results of 48 | /// the ConfigValue queries but no query logic is exposed here. 49 | /// 50 | struct Options { 51 | ::DumpLevel DumpLevel; ///< Dump level for this JIT invocation. 52 | ::OptLevel OptLevel; ///< Optimization level for this JIT invocation. 53 | bool EnableOptimization; ///< True iff OptLevel is not debug 54 | bool UseConservativeGC; ///< True if the environment is set to use CGC. 55 | bool DoInsertStatepoints; ///< True if the environment calls for statepoints. 56 | bool DoTailCallOpt; ///< Tail call optimization. 57 | bool LogGcInfo; ///< Generate GCInfo Translation logs 58 | bool ExecuteHandlers; ///< Squelch handler suppression. 59 | bool DoSIMDIntrinsic; ///< True if SIMD intrinsic is on. 60 | unsigned PreferredIntrinsicSIMDVectorLength; ///< Prefer Intrinsic SIMD Vector 61 | /// Length in bytes. 62 | }; 63 | #endif // OPTIONS_H 64 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Documentation/Code-Formatting.md: -------------------------------------------------------------------------------- 1 | # Enforcing Coding Conventions 2 | 3 | The LLILC project is structured as a subproject of LLVM so we are using the 4 | same coding conventions as LLVM. See the [coding convention document](llilc-Coding-Conventions-and-Commenting-Style.md) 5 | for more details. To maintain these conventions, we require all contributors 6 | to run our code formatting script over their changes before submitting a pull 7 | request. The code formatting script is found at LLILC\utils\ccformat.py. 8 | 9 | ## Prerequisites 10 | 11 | * Binaries for clang-format and clang-tidy are required to run ccformat.py. 12 | * clang-format is available in the clang repository. It can either be downloaded 13 | from [LLVM](http://llvm.org/releases/download.html), or built from clang source tree. 14 | * clang-tidy is available in the clang-tools-extra repository. It should be built 15 | from the [MS branch](https://github.com/Microsoft/clang-tools-extra/tree/MS) 16 | of the clang-tools-extra repository. 17 | 18 | ## Setup 19 | 20 | * Set the INCLUDE=. On Windows, this can be done by executing 21 | > "%VS120COMNTOOLS%\\..\\..\VC\vcvarsall.bat" x64 22 | 23 | * Provide a full path to the following locations via the corresponding environment settings 24 | or command line arguments. 25 | 26 | Description | Environment Variable | Argument to ccFormat.py 27 | ------------|----------------------|----------------------------- 28 | LLVM source directory | LLVMSOURCE | --llvm-source \ 29 | LLVM build directory | LLVMBUILD | --llvm-build \ 30 | CoreClr build directory | CORECLRBUILD | --coreclr-build \ 31 | clang-format binary | /< on path/> | --clang-format \ 32 | clang-tidy binary | /< on path/> | --clang-tidy \ 33 | 34 | ## Running ccformat 35 | 36 | To check if a submission conforms to coding conventions, contributors 37 | should run from their main LLILC enlistment directory: 38 | 39 | > utils\ccformat.py 40 | 41 | ### Choosing Checks 42 | 43 | By default, ccFormat will run both clang-format and clang-tidy checks. 44 | To disable clang-format checks, run: 45 | > utils\ccformat.py --noformat 46 | 47 | To disable clang-tidy checks, run: 48 | > utils\ccformat.py --untidy 49 | 50 | ### Hiding Formatting Diffs 51 | 52 | If you do not want to see the diffs generated by clang-format 53 | (but only want to check if there are any formatting errors), run: 54 | > utils\ccformat.py --hide-diffs 55 | 56 | ### Fixing Formatting Errors 57 | 58 | If ccformat.py informs you that there are diffs between your code and the 59 | formatted version returned by clang-format, contributors need to run with 60 | --fix to automatically fix formatting errors: 61 | 62 | > utils\ccformat.py --fix 63 | 64 | ## Further Information 65 | 66 | For further information, please run: 67 | 68 | > utils\ccformat.py --help 69 | 70 | 71 | -------------------------------------------------------------------------------- /Documentation/llilc-faq.md: -------------------------------------------------------------------------------- 1 | # LLILC FAQ 2 | 3 | + Q: What is LLILC? 4 | A: LLILC is an MSIL code generator based on LLVM. Today LLILC can produce a JIT 5 | compiler that can be used with [CoreCLR](https://github.com/dotnet/coreclr), but our 6 | over-arching aim is to allow easier porting of managed languages to any platform 7 | while supporting a spectrum of compilation strategies. 8 | 9 | + Q: What targets will LLILC generate code for? 10 | A: Initially x64. In future: any target that LLVM supports is 11 | possible (x86, ARM-64, ...) 12 | 13 | + Q: What platforms will LLILC target? 14 | A: LLILC targets the same platforms as CoreCLR: Linux, MAC OS X and Windows 15 | 16 | + Q: How does the LLILC JIT compiler relate to the CoreCLR RyuJIT compiler? 17 | A: Their aims are different: RyuJIT is a high-performance, 18 | custom JIT, in that it implements its own optimizatons 19 | and codegen, specific to C#. It matches the high throughput required by 20 | the CoreCLR runtime. LLILC, by contrast, uses the LLVM framework, 21 | which provides industrial-strength optimizations, leveraged by 22 | the Clang C++ compiler. It thereby offers a familiar environment 23 | within which developers can implement low-level, ‘backend’ tools, 24 | such as code analyzers, obfuscators, verifiers, etc. 25 | 26 | + Q: How do I get started? 27 | A: See the [Welcome Document](Welcome.md) 28 | 29 | + Q: Are there any demos? 30 | A: Not as yet. We need to extend the JIT to handle more 31 | tests first. 32 | 33 | + Q: How does LLILC differ from Roslyn in the features it provides 34 | for building software tools? 35 | A: Roslyn provides *frontend* support, whilst LLILC 36 | (via LLVM) provides *backend* support: 37 | 38 | + Roslyn exposes the data structures of a *frontend* – so it’s ideal 39 | for building tools such as IDEs, with syntax coloring, warning 40 | squiggles, use/definition lookup, refactoring, etc; or 41 | translators that convert C# to some other language; or 42 | pretty-print formatters; or analyzers that check conformance 43 | with coding guidelines (think FxCop). 44 | 45 | + LLILC, via LLVM, exposes the data structures of a *backend* – so 46 | it’s ideal for building tools that inject extra code (eg: performance 47 | profiler, code tracer, debugger, parallelism analyzer, race 48 | detector); or super-optimizing code (eg: auto-vectorizer, auto-parallelizer); 49 | or test-case reduction. 50 | 51 | + Q: When will the LLILC AOT (Ahead-Of-Time) compiler be ready? 52 | A: At the moment, CoreCLR does not include an AOT. We envisage 53 | that the LLILC AOT will work in two kinds of environment – those 54 | that allow runtime codegen, and those where the entire code is converted to native binary. 55 | 56 | + Q: How does LLILC relate to the .NET Native work? 57 | A: .NET Native provides a broad tool-chain, targeting Windows. The LLILC AOT could 58 | be used as the compiler component of .NET Native to target other platforms. 59 | -------------------------------------------------------------------------------- /Documentation/Long-Running-Branch-Workflow.md: -------------------------------------------------------------------------------- 1 | # Long-Running Branches 2 | 3 | The first rule of long-running branches on the main LLILC repo is that they 4 | should be the exception, not the norm. Most changes should be pushed to a 5 | personal fork and a pull request issued to merge from the fork directly to 6 | the master branch of the main LLILC repo, per the [contribution guide](Contributing.md#workflow). 7 | 8 | Occasionally, however, we'll need to make changes that simultaneously 9 | - Involve a lot of code 10 | - Will take a long time to develop 11 | - Will begin with tentative/exploratory changes that are likely to be revised 12 | before the feature is complete 13 | - Are likely to destabilize the codebase until complete 14 | - Don't have a reasonably efficient incremental implementation path available 15 | 16 | For such changes, it makes sense to work in a long-lived branch, then 17 | retroactively parcel out the change into non-destabilizing pieces, as 18 | incremental as possible, for integration back into the master branch. When 19 | key features meet these criteria, we may create a long-lived branch on the 20 | main repo where the work will occur, to publicize it and facilitate 21 | collaboration/review in even the early tentative stages. For example, the 22 | initial bring-up of [exception handling support](https://github.com/dotnet/llilc/tree/EH) 23 | and [precise garbage collection support](https://github.com/dotnet/llilc/tree/GC) 24 | are both following this model. 25 | 26 | The expected workflow for long-lived branches in the main repo is: 27 | 1. The branch maintainer(s) will regularly push merges from master to the 28 | long-lived branch 29 | - Merging is preferred over rebasing to simplify collaboration 30 | - Pull requests are not expected for these merges (there's not really 31 | anything to review); the branch maintainer(s) will push them directly 32 | 2. All other changes in the branch should be made via pull requests from 33 | personal forks. These changes should be small and incremental, but may 34 | be destabilizing (when warranted to make forward progress). Getting 35 | code reviews along the way should help us end up with higher quality code 36 | and fewer late-stage surprises than delaying review until merging back to 37 | master would. 38 | 3. Any such branch may have its own policy for what level of testing is 39 | expected/required to maintain the quality bar as changes are made. 40 | Code style/formatting should be held to [the usual standards](Code-Formatting.md). 41 | 4. When the feature is stable/complete, the branch maintainer(s) should 42 | rebase/repackage the changes in a way that is logical to merge into master. 43 | - The individual changes to be merged must be stable, and should be as 44 | incremental as possible. 45 | - Pull requests should be opened to merge the changes into master. 46 | - Typically, each incremental change should have its own pull request. 47 | - A single pull request for a series of incremental changes is ok if 48 | they are a straightforward replay of already-reviewed commits from the 49 | branch. 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Python cache 50 | __pycache__ 51 | *.pyc 52 | 53 | # Visual C++ cache files 54 | ipch/ 55 | *.aps 56 | *.ncb 57 | *.opensdf 58 | *.sdf 59 | *.cachefile 60 | 61 | # Visual Studio profiler 62 | *.psess 63 | *.vsp 64 | *.vspx 65 | 66 | # Guidance Automation Toolkit 67 | *.gpState 68 | 69 | # ReSharper is a .NET coding add-in 70 | _ReSharper*/ 71 | *.[Rr]e[Ss]harper 72 | 73 | # TeamCity is a build add-in 74 | _TeamCity* 75 | 76 | # DotCover is a Code Coverage Tool 77 | *.dotCover 78 | 79 | # NCrunch 80 | *.ncrunch* 81 | .*crunch*.local.xml 82 | 83 | # Installshield output folder 84 | [Ee]xpress/ 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish/ 98 | 99 | # Publish Web Output 100 | *.Publish.xml 101 | 102 | # NuGet Packages Directory 103 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 104 | #packages/ 105 | 106 | # Windows Azure Build Output 107 | csx 108 | *.build.csdef 109 | 110 | # Windows Store app package directory 111 | AppPackages/ 112 | 113 | # Others 114 | sql/ 115 | *.Cache 116 | ClientBin/ 117 | [Ss]tyle[Cc]op.* 118 | ~$* 119 | *~ 120 | *.dbmdl 121 | *.[Pp]ublish.xml 122 | *.pfx 123 | *.publishsettings 124 | 125 | # RIA/Silverlight projects 126 | Generated_Code/ 127 | 128 | # Backup & report files from converting an old project file to a newer 129 | # Visual Studio version. Backup files are not needed, because we have git ;-) 130 | _UpgradeReport_Files/ 131 | Backup*/ 132 | UpgradeLog*.XML 133 | UpgradeLog*.htm 134 | 135 | # SQL Server files 136 | App_Data/*.mdf 137 | App_Data/*.ldf 138 | 139 | 140 | #LightSwitch generated files 141 | GeneratedArtifacts/ 142 | _Pvt_Extensions/ 143 | ModelManifest.xml 144 | 145 | # ========================= 146 | # Windows detritus 147 | # ========================= 148 | 149 | # Windows image file caches 150 | Thumbs.db 151 | ehthumbs.db 152 | 153 | # Folder config file 154 | Desktop.ini 155 | 156 | # Recycle Bin used on file shares 157 | $RECYCLE.BIN/ 158 | 159 | # Mac desktop service store files 160 | .DS_Store 161 | /src/3fjtrdxe.dt5 162 | /src/j1xrvkr3.mrf 163 | TAGS 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LLILC Is Now Archived 2 | 3 | LLILC was an experimental project to build a .NET compatible JIT from LLVM. It is no longer under active development. 4 | 5 | For questions or concerns please open an issue on https://github.com/dotnet/core. 6 | 7 | Welcome to LLILC 8 | ------------ 9 | 10 | [![Join the chat at https://gitter.im/dotnet/llilc](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dotnet/llilc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 11 | 12 | Build Status 13 | ------------ 14 | 15 | | | Windows | Linux | 16 | |-----------|---------------|-------------| 17 | | **Debug** |[![Build status](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/windows_nt_debug/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/windows_nt_debug/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/ubuntu_debug/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/ubuntu_debug/)| 18 | |**Release**|[![Build status](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/windows_nt_release/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/windows_nt_release/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/ubuntu_release/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_llilc/job/master/job/ubuntu_release/)| 19 | 20 | 21 | Introduction 22 | ------------- 23 | 24 | LLILC is an **LL**VM based MS**IL** **C**ompiler - we pronounce it 'lilac' - 25 | with a goal of producing a set of cross-platform .NET code generation tools. 26 | Today LLILC is being developed against [dotnet/CoreCLR](https://github.com/dotnet/coreclr) 27 | for use as a JIT, as well as an cross platform platform object emitter and disassembler 28 | that is used by CoreRT as well as other dotnet utilites. 29 | 30 | See the [documentation](Documentation/Welcome.md) for more information. 31 | It has a more complete discussion of our background and goals as well as 32 | "getting started" details and developer information. 33 | 34 | ObjectWriter for [CoreRT](https://github.com/dotnet/corert): 35 | CoreRT project uses ObjectWriter that lives in its own branch in this repo, 36 | if you want to build it then follow instructions from getting started, but use the following branches: 37 | 1. latest LLVM [version](https://github.com/llvm-mirror/llvm) and apply this [patch](https://reviews.llvm.org/D29483) or take the known working version from [Microsoft/llvm/CoreRT_ObjectWriter branch](https://github.com/dotnet/llilc/tree/ObjectWriter); 38 | 2. [llilc/ObjectWriter branch](https://github.com/dotnet/llilc/tree/ObjectWriter); 39 | 40 | libcoredistools: CoreCLR has a ongoing dependency on libcoredistools which is built out of this repo and placed into build/lib/libcoredistools.dylib|so|dll. To build coredistools follow the default workflow for building llilc/llvm on the master branch. 41 | 42 | 43 | Supported Platforms 44 | ------------------- 45 | 46 | Our initial supported platform is [Windows](Documentation/Getting-Started-For-Windows.md), 47 | but [Linux and Mac OS X](Documentation/Getting-Started-For-Linux-and-OS-X.md) 48 | support are under development. 49 | 50 | Contributions 51 | ------------- 52 | 53 | Please see our [issues](https://github.com/dotnet/llilc/issues) 54 | or the [contributing document](Documentation/Areas-To-Contribute.md) 55 | for how to pitch in. 56 | -------------------------------------------------------------------------------- /utils/make_package.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import argparse 5 | import os 6 | import subprocess 7 | import platform 8 | import io 9 | import string 10 | try: 11 | # For Python >= 3.0 12 | from urllib.request import urlopen 13 | except ImportError: 14 | # For Python < 3.0 15 | from urllib2 import urlopen 16 | import shutil 17 | import stat 18 | 19 | def run(args): 20 | nugetFolder = os.path.join(args.target, ".nuget") 21 | print("\nEnsuring folder: %s" % nugetFolder ) 22 | if not os.path.exists(nugetFolder): 23 | os.makedirs(nugetFolder) 24 | 25 | nugetExe = os.path.join(nugetFolder, "nuget.exe") 26 | if not os.path.exists(nugetExe): 27 | nugetOrg = "http://nuget.org/nuget.exe" 28 | print("Downloading... %s" % nugetOrg ) 29 | response = urlopen(nugetOrg) 30 | output = open(nugetExe,'wb') 31 | output.write(response.read()) 32 | output.close() 33 | # Ensure it's executable 34 | st = os.stat(nugetExe) 35 | os.chmod(nugetExe, st.st_mode | stat.S_IEXEC) 36 | 37 | if (sys.platform != "win32"): 38 | # shutil.which can be used for python 3.3 or later, instead. 39 | for mono in ["/usr/bin/mono", "/usr/local/bin/mono"]: 40 | if os.path.exists(mono): 41 | monopath = mono 42 | if not monopath: 43 | raise "mono is required to run nuget.exe" 44 | nugetExe = monopath + " " + nugetExe 45 | 46 | nugetSpec = os.path.join(nugetFolder, os.path.basename(args.nuspec)) 47 | if args.nuspec != nugetSpec: 48 | print("\nCopying " + args.nuspec + " to " + nugetSpec) 49 | shutil.copyfile(args.nuspec, nugetSpec) 50 | 51 | if args.json != None: 52 | nugetJson = os.path.join(nugetFolder, os.path.basename(args.json)) 53 | if args.json != nugetJson: 54 | print("\nCopying " + args.json + " to " + nugetJson) 55 | shutil.copyfile(args.json, nugetJson) 56 | 57 | nugetCommand = nugetExe + " pack " + nugetSpec \ 58 | + " -NoPackageAnalysis -NoDefaultExcludes" \ 59 | " -OutputDirectory %s" % nugetFolder 60 | 61 | ret = os.system(nugetCommand) 62 | return ret 63 | 64 | def main(argv): 65 | parser = argparse.ArgumentParser(description= 66 | "Download nuget and run it to create a package using the given nuspec. " \ 67 | "Example: make_package.py " \ 68 | "--target f:\llilc-rel\\bin\Release " \ 69 | "--nuspec f:\llilc\lib\ObjWriter\.nuget\Microsoft.Dotnet.ObjectWriter.nuspec", 70 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 71 | parser.add_argument("--target", metavar="PATH", 72 | default=None, 73 | help="path to a target directory that contains files that will " \ 74 | "packaged") 75 | parser.add_argument("--nuspec", metavar="PATH", 76 | default=None, 77 | help="path to a nuspec file. This file is assumed to be under " \ 78 | "a child directory (.nuget) of the target by convetion") 79 | parser.add_argument("--json", metavar="PATH", 80 | default=None, 81 | help="path to a json file. This file is used to create " \ 82 | "a redirection package") 83 | args,unknown = parser.parse_known_args(argv) 84 | 85 | if unknown: 86 | print("Unknown argument(s): ", ", ".join(unknown)) 87 | return -3 88 | 89 | returncode=0 90 | if args.target == None: 91 | print("--target is not specified.") 92 | return -3 93 | 94 | if args.nuspec == None: 95 | print("--nuspec is not specified") 96 | return -3 97 | 98 | returncode = run(args) 99 | 100 | return returncode 101 | 102 | 103 | if __name__ == "__main__": 104 | returncode = main(sys.argv[1:]) 105 | sys.exit(returncode) 106 | -------------------------------------------------------------------------------- /lib/GcInfo/GcInfoUtil.cpp: -------------------------------------------------------------------------------- 1 | //===---- include/gcinfo/gcinfoutil.cpp -------------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Implementation of utility classes used by GCInfoEncoder library 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #include 17 | #include "GcInfoUtil.h" 18 | 19 | //***************************************************************************** 20 | // GcInfoAllocator 21 | //***************************************************************************** 22 | 23 | int GcInfoAllocator::ZeroLengthAlloc = 0; 24 | 25 | //***************************************************************************** 26 | // Utility Functions 27 | //***************************************************************************** 28 | 29 | //------------------------------------------------------------------------ 30 | // BitPosition: Return the position of the single bit that is set in 'value'. 31 | // 32 | // Return Value: 33 | // The position (0 is LSB) of bit that is set in 'value' 34 | // 35 | // Notes: 36 | // 'value' must have exactly one bit set. 37 | // The algorithm is as follows: 38 | // - PRIME is a prime bigger than sizeof(unsigned int), which is not of the 39 | // form 2^n-1. 40 | // - Taking the modulo of 'value' with this will produce a unique hash for 41 | // all powers of 2 (which is what "value" is). 42 | // - Entries in hashTable[] which are -1 should never be used. There 43 | // should be PRIME-8*sizeof(value) entries which are -1 . 44 | //------------------------------------------------------------------------ 45 | 46 | unsigned BitPosition(unsigned value) { 47 | _ASSERTE((value != 0) && ((value & (value - 1)) == 0)); 48 | const unsigned PRIME = 37; 49 | 50 | static const int8_t hashTable[PRIME] = { 51 | -1, 0, 1, 26, 2, 23, 27, -1, 3, 16, 24, 30, 28, 11, -1, 13, 4, 7, 17, 52 | -1, 25, 22, 31, 15, 29, 10, 12, 6, -1, 21, 14, 9, 5, 20, 8, 19, 18}; 53 | 54 | _ASSERTE(PRIME >= 8 * sizeof(value)); 55 | _ASSERTE(sizeof(hashTable) == PRIME); 56 | 57 | unsigned hash = value % PRIME; 58 | int8_t index = hashTable[hash]; 59 | _ASSERTE(index != -1); 60 | 61 | return (unsigned)index; 62 | } 63 | 64 | //***************************************************************************** 65 | // ArrayList 66 | //***************************************************************************** 67 | 68 | void StructArrayListBase::CreateNewChunk(SIZE_T InitialChunkLength, 69 | SIZE_T ChunkLengthGrowthFactor, 70 | SIZE_T cbElement, AllocProc *pfnAlloc, 71 | SIZE_T alignment) { 72 | _ASSERTE(InitialChunkLength > 0); 73 | _ASSERTE(ChunkLengthGrowthFactor > 0); 74 | _ASSERTE(cbElement > 0); 75 | 76 | SIZE_T cbBaseSize = 77 | SIZE_T(roundUp(sizeof(StructArrayListEntryBase), alignment)); 78 | SIZE_T maxChunkCapacity = (MAXSIZE_T - cbBaseSize) / cbElement; 79 | 80 | _ASSERTE(maxChunkCapacity > 0); 81 | 82 | SIZE_T nChunkCapacity; 83 | if (!m_pChunkListHead) 84 | nChunkCapacity = InitialChunkLength; 85 | else 86 | nChunkCapacity = m_nLastChunkCapacity * ChunkLengthGrowthFactor; 87 | 88 | if (nChunkCapacity > maxChunkCapacity) { 89 | // Limit nChunkCapacity such that cbChunk computation does not overflow. 90 | nChunkCapacity = maxChunkCapacity; 91 | } 92 | 93 | SIZE_T cbChunk = cbBaseSize + SIZE_T(cbElement) * SIZE_T(nChunkCapacity); 94 | 95 | StructArrayListEntryBase *pNewChunk = 96 | (StructArrayListEntryBase *)pfnAlloc(this, cbChunk); 97 | 98 | if (m_pChunkListTail) { 99 | _ASSERTE(m_pChunkListHead); 100 | m_pChunkListTail->pNext = pNewChunk; 101 | } else { 102 | _ASSERTE(!m_pChunkListHead); 103 | m_pChunkListHead = pNewChunk; 104 | } 105 | 106 | pNewChunk->pNext = NULL; 107 | m_pChunkListTail = pNewChunk; 108 | 109 | m_nItemsInLastChunk = 0; 110 | m_nLastChunkCapacity = nChunkCapacity; 111 | } 112 | -------------------------------------------------------------------------------- /Documentation/llilc-Coding-Conventions-and-Commenting-Style.md: -------------------------------------------------------------------------------- 1 | # LLILC Coding Guidelines 2 | 3 | ## General Coding Guidelines 4 | 5 | The LLILC project is structured as a subproject of LLVM so we are using the 6 | same coding conventions as LLVM. The LLVM coding conventions are at 7 | . We use clang-format to 8 | check/enforce some formatting rules, as described on our 9 | [code formatting document](Code-Formatting.md). 10 | 11 | ## Commenting Guidelines 12 | 13 | In particular has 14 | guidelines for commenting code and using Doxygen markup. For a complete 15 | description of Doxygen markup see . 16 | 17 | We can summarize these as follows: 18 | 19 | * Use the "///" style of comment unless that file is written in C or may be 20 | included into a C file. 21 | 22 | * For Doyxygen markup, use the "\" form, e.g. \brief, rather than the "@" 23 | form, e.g. @brief. 24 | 25 | * Use the \file command to turn the standard file header into a file-level 26 | comment. 27 | 28 | * Include descriptive \brief paragraphs for all public interfaces (public 29 | classes, member and non-member functions). Explain API use and purpose in 30 | \brief paragraphs, don’t just restate the information that can be inferred 31 | from the API name. Put detailed discussion into separate paragraphs. 32 | 33 | * To refer to parameter names inside a paragraph, use the \p name command. 34 | Don’t use the \arg name command since it starts a new paragraph that 35 | contains documentation for the parameter. 36 | 37 | * Wrap non-inline code examples in \code ... \endcode. 38 | 39 | * To document a function parameter, start a new paragraph with the \param 40 | name command. If the parameter is used as an out or an in/out parameter, 41 | use the \param [out] name or \param [in,out] name command, respectively. 42 | 43 | * To describe function return value, start a new paragraph with the \returns 44 | command 45 | 46 | * For classes and class members that are declared in a header, put the Doxygen 47 | comments there. Otherwise put the comments in the implementation file. 48 | 49 | * For declaration of fields of a class, if the declaration is short 50 | use the "//<" form of document comments at the end of the line, 51 | if the comment will fit on not more than two lines. 52 | If the comment would be longer than two lines, put the documentation 53 | comment before the declaration. 54 | 55 | * When a documentation comment precedes a declaration, separate it from 56 | preceding declarations by a blank line. 57 | 58 | * For virtual methods, put the documentation on the method declaration in the 59 | base class that first introduced the method. Do not put documentation on 60 | the method overrides. In the Doxygen output the comments from the base 61 | class method will also be shown for the overriding methods. 62 | 63 | In addition to these recommendations from the LLVM coding standards I have 64 | the following recommendations: 65 | 66 | * Doxygen supports Markdown, so use it in your comments when it can do what 67 | you want. See 68 | 69 | * In order to provide greater logical clarity on the semantics of classes 70 | and methods I suggest using the Doxygen 71 | [\pre](http://www.stack.nl/~dimitri/doxygen/manual/commands.html#cmdpre), 72 | [\post](http://www.stack.nl/~dimitri/doxygen/manual/commands.html#cmdpost), 73 | and [\invariant](http://www.stack.nl/~dimitri/doxygen/manual/commands.html#cmdinvariant) 74 | [special commands](http://www.stack.nl/~dimitri/doxygen/manual/commands.html) 75 | to specify method preconditions and postconditions and class invariants. 76 | 77 | ## Use of LLVM I/O APIs 78 | 79 | Rather than using the printf family of output functions the LLILC team 80 | uses the LLVML I/O APIs. This is a simplified form of C++ output. 81 | 82 | - The base type is raw_ostream. 83 | - Derived classes are: 84 | - raw_fd_ostream, for output to a file descriptor. Two of these are 85 | made and accessed as follows: 86 | - outs() is connected to stdout 87 | - errs() is connected to stderr. 88 | - dbgs() is a debug stream that is connected to stderr but which 89 | may optionally have circular buffering but by default it is 90 | an unbuffered connection to errs(). 91 | - raw_string_ostream connects to a std::string given in its 92 | - constructor. Any output to that stream is appended to the 93 | end of the string. 94 | - As with C++ the "<<" operator has overloads for outputting all the 95 | common data types. 96 | - In addition the form "<< format(formatstring, args)" may be 97 | used to get the usual printf-stype formatting to a stream. 98 | -------------------------------------------------------------------------------- /lib/Jit/utility.cpp: -------------------------------------------------------------------------------- 1 | // Utility code 2 | 3 | #include 4 | 5 | #include "global.h" 6 | #include "jitpch.h" 7 | 8 | #include "cor.h" // CorSigUncompressData 9 | #include "utility.h" 10 | #include "llvm/Support/ConvertUTF.h" 11 | 12 | using std::string; 13 | using std::unique_ptr; 14 | 15 | int MethodID::parseArgs(const string &S, size_t &I) { 16 | size_t Start = ++I; // skip '(' 17 | 18 | I = S.find_first_of(")", I); 19 | if (I == string::npos) 20 | return MethodIDState::AnyArgs; 21 | 22 | string Num = string(S, Start, I - Start); 23 | int NArgs = atoi(Num.c_str()); 24 | ++I; // skip ) 25 | return NArgs; 26 | } 27 | 28 | unique_ptr MethodID::parse(const string &S, size_t &I) { 29 | MethodID MId; 30 | size_t SLen = S.length(); 31 | 32 | string Token = MId.scan(S, I); 33 | 34 | if (Token == "") // off the end of S 35 | return nullptr; 36 | 37 | if (Token == "*") { 38 | MId.ClassName = llvm::make_unique(Token); 39 | MId.MethodName = nullptr; 40 | if (I >= SLen || S[I] == ' ') { 41 | MId.NumArgs = MethodIDState::AnyArgs; 42 | } 43 | return llvm::make_unique(MId); 44 | return nullptr; 45 | } 46 | 47 | if (S[I] == ':') { // C:M | C:M(A) 48 | MId.ClassName = llvm::make_unique(Token); 49 | Token = MId.scan(S, ++I); // M | M(A) 50 | } 51 | 52 | MId.MethodName = llvm::make_unique(Token); 53 | 54 | if (I >= SLen || S[I] == ' ') { 55 | MId.NumArgs = MethodIDState::AnyArgs; 56 | return llvm::make_unique(MId); 57 | return nullptr; 58 | } 59 | 60 | if (S[I] != '(') // illegal 61 | return nullptr; 62 | 63 | MId.NumArgs = MId.parseArgs(S, I); 64 | return llvm::make_unique(MId); 65 | return nullptr; 66 | } 67 | 68 | string MethodID::scan(const string &S, size_t &I) { 69 | const size_t SLen = S.length(); 70 | 71 | if (I >= SLen) // already 'off the end' 72 | return string{""}; 73 | 74 | size_t Start = I = S.find_first_not_of(" \t", I); // skip whitespace 75 | 76 | I = S.find_first_of(" :()", I); 77 | 78 | if (I == string::npos) // eg: S = "*" 79 | I = SLen; 80 | 81 | return string(S, Start, I - Start); 82 | } 83 | 84 | void MethodSet::init(unique_ptr ConfigValue) { 85 | if (this->isInitialized()) { 86 | return; 87 | } 88 | insert(std::move(ConfigValue)); 89 | } 90 | 91 | void MethodSet::insert(unique_ptr Ups) { 92 | size_t I = 0; 93 | std::list *MIdList = new std::list(); 94 | string S = *Ups; 95 | 96 | auto MId = MethodID::parse(S, I); 97 | while (MId) { 98 | MIdList->push_back(*MId); 99 | MId = MethodID::parse(S, I); 100 | } 101 | 102 | // This write should be atomic, delete if we're not the first. 103 | llvm::sys::cas_flag F = llvm::sys::CompareAndSwap( 104 | (llvm::sys::cas_flag *)&(this->Initialized), 0x1, 0x0); 105 | if (F != 0x0) { 106 | delete MIdList; 107 | } else { 108 | this->MethodIDList = MIdList; 109 | } 110 | } 111 | 112 | bool MethodSet::contains(const char *MethodName, const char *ClassName, 113 | PCCOR_SIGNATURE PCSig) { 114 | 115 | assert(this->isInitialized()); 116 | 117 | int NumArgs = MethodIDState::AnyArgs; // assume no signature supplied 118 | 119 | if (PCSig) { 120 | PCSig++; // skip calling convention 121 | NumArgs = CorSigUncompressData(PCSig); 122 | } 123 | 124 | string StrClassName = ClassName ? ClassName : ""; 125 | string StrMethodName = MethodName ? MethodName : ""; 126 | 127 | auto Begin = this->MethodIDList->begin(); 128 | auto End = this->MethodIDList->end(); 129 | 130 | for (auto P = Begin; P != End; ++P) { // P => "pattern" 131 | 132 | // Check for "*", the common case, first 133 | if (P->ClassName && *P->ClassName == "*") 134 | return true; 135 | 136 | // Check for mis-match on NumArgs 137 | if (P->NumArgs != MethodIDState::AnyArgs && P->NumArgs != NumArgs) 138 | continue; 139 | 140 | // Check for mis-match on MethodName 141 | if (P->MethodName && (*P->MethodName != StrMethodName)) 142 | continue; 143 | 144 | // Check for match on ClassName (we already match NumArgs and MethodName) 145 | if (!P->ClassName) // no ClassName 146 | return true; 147 | 148 | if (*P->ClassName == StrClassName) 149 | return true; 150 | } 151 | 152 | return false; 153 | } 154 | 155 | unique_ptr Convert::utf16ToUtf8(const char16_t *WideStr) { 156 | // Get the length of the input 157 | size_t SrcLen = 0; 158 | for (; WideStr[SrcLen] != (char16_t)0; SrcLen++) 159 | ; 160 | 161 | llvm::ArrayRef SrcBytes((const char *)WideStr, 2 * SrcLen); 162 | unique_ptr OutString(new std::string); 163 | convertUTF16ToUTF8String(SrcBytes, *OutString); 164 | 165 | return OutString; 166 | } 167 | -------------------------------------------------------------------------------- /Documentation/Developer-Workflow.md: -------------------------------------------------------------------------------- 1 | # Developer Workflow 2 | 3 | ## Introduction 4 | 5 | This documents our typical workflow. At a high level this covers how we 6 | expect issues to work, what our development cadence is, and how we do design 7 | for larger features. And by we, we mean the whole community. These guidelines 8 | hopefully foster collaboration and high quality, useful software. 9 | (Some fun wouldn't hurt either.) 10 | 11 | ## Issues 12 | 13 | We use GitHub issues to track work, so if you're working on something, open 14 | an issue. It gives the community a place to have a conversation about the 15 | fix/feature that's being worked on. In addition it helps everybody keep 16 | track of who is working on what so that we can minimize duplication and 17 | redundant work. 18 | 19 | The typical issue flow is as follows: 20 | - Have a great idea, or find a bug, and open issue. 21 | - Issue is discussed on GitHub and a direction is established. 22 | - Somebody signs up to do the work and potentially a sprint milestone is 23 | assigned if the work directly effects a particular near term project 24 | [goal](https://github.com/dotnet/llilc/blob/master/Documentation/llilc-milestones.md). 25 | - Ongoing notes on the implementation are added to the issue as work progresses. 26 | - Work is completed, tested, PR'd, and merged in. 27 | - Issue is closed 28 | 29 | Note on 'assigning' issues: The only people that can be assigned to an issue 30 | in GitHub are people that are in one of the project groups (either *llilc* - 31 | read/write access, or *llilc-community* - read only access). We add people 32 | to the Community group after their first PR is accepted by the collaborators. 33 | This enables you to be added as the assignee for issues. So if this is your 34 | first issue, note your Github account name in the issue as the person 35 | working on it and others will understand that it's in flight. 36 | 37 | Note on read/write access: We'd like to develop a broad set of committers to 38 | the project from the community (we don't have any non-MS committers at this 39 | point) we think that this should happen after people build a track record in 40 | the llilc-community group. The expectation is that after few (3-5) non-trivial 41 | contributions a community member can request to be added to the project group 42 | and gain read/write access to the source. With this access also comes the 43 | expectation that the collaborator will help review others PR's, help maintain 44 | documentation, as well as generally facilitate the smooth running of the project. 45 | 46 | ## Workflow 47 | 48 | We use 3 week sprints in a agile(-ish) model. These sprints are added as 49 | Milestones in Github (not to be confused with the project [Milestones](llilc-milestones.md) 50 | which are larger granularity proof points of functionality.) Look at the 51 | [Github milestones page](https://github.com/dotnet/llilc/milestones) to see 52 | the individual sprints and their end dates. These sprints are used by core 53 | members of the team to managed work toward near term goals, but it is not 54 | necessary for community contributors to use these milestones. The only place 55 | where this could potentially cause some complication is if a particular 56 | feature/fix is needed for a near term goal. In this case we would have a 57 | conversation about assigning the issue to a milestone and potentially moving 58 | the work to a collaborator that can commit to a solution in the needed time 59 | frame. We're attempting to have a balance between an open and friendly 60 | environment to hack and the necessity to drive functionality (as well as 61 | meet product goals). 62 | 63 | A typical flow is as follows: 64 | - Day one of a sprint milestone work is self-assigned by developers based on 65 | a combination of priority and what the think that they can get done in a 3 66 | week period. 67 | - Through out the sprint notes are added to the issues assigned to the sprint 68 | outlining progress. 69 | - Issues are closed as they are merged back in and the CI system stays green. 70 | - On the first day of the next sprint, any items not completed are triaged 71 | and moved to the appropriate sprint. (Typically this is the next sprint) 72 | 73 | ## Design process 74 | 75 | As stated above, all features start as issues. If as part of the conversation 76 | about an issue, the community decides that a particular feature is large or 77 | complicated enough to warrant a separate write up a document will be created 78 | by interested parties describing the design and the staging of bring up. 79 | This document will be reviewed via PR and checked in as separate markdown in 80 | the project Documentation directory off the root. A good example of this is 81 | the [EH design document](llilc-jit-eh.md). As you can see today only larger, 82 | more complicated areas warrant this treatment. I want to highlight that 83 | typical work will be handled via issues, reserving this process for areas 84 | that require months of development to bring to fruition. 85 | -------------------------------------------------------------------------------- /netci.groovy: -------------------------------------------------------------------------------- 1 | import jobs.generation.Utilities; 2 | 3 | def project = GithubProject 4 | def branch = GithubBranchName 5 | 6 | static void addMultiScm(def myJob, boolean isPR) { 7 | if (isPR) { 8 | addPRTestMultiScm(myJob) 9 | } 10 | else { 11 | addMultiScm(myJob) 12 | } 13 | } 14 | 15 | static void addPRTestMultiScm(def job) { 16 | job.with { 17 | multiscm { 18 | git { 19 | remote { 20 | github('Microsoft/llvm') 21 | } 22 | branch('*/MS') 23 | wipeOutWorkspace(true) 24 | shallowClone(true) 25 | relativeTargetDir('llvm') 26 | } 27 | git { 28 | remote { 29 | github('dotnet/coreclr') 30 | } 31 | branch('*/master') 32 | relativeTargetDir('coreclr') 33 | } 34 | git { 35 | remote { 36 | github('dotnet/llilc') 37 | refspec('${GitRefSpec}') 38 | url('${GitRepoUrl}') 39 | } 40 | branch('${sha1}') 41 | relativeTargetDir('llvm\\tools\\llilc') 42 | } 43 | } 44 | } 45 | } 46 | 47 | static void addMultiScm(def myJob) { 48 | myJob.with { 49 | multiscm { 50 | git { 51 | remote { 52 | github('Microsoft/llvm') 53 | } 54 | branch('*/MS') 55 | wipeOutWorkspace(true) 56 | shallowClone(true) 57 | relativeTargetDir('llvm') 58 | } 59 | git { 60 | remote { 61 | github('dotnet/coreclr') 62 | } 63 | branch('*/master') 64 | relativeTargetDir('coreclr') 65 | } 66 | git { 67 | remote { 68 | github('dotnet/llilc') 69 | } 70 | branch('*/master') 71 | relativeTargetDir('llvm\\tools\\llilc') 72 | } 73 | } 74 | } 75 | } 76 | 77 | [true, false].each { isPR -> 78 | ['Debug', 'Release'].each { configuration -> 79 | lowerConfiguration = configuration.toLowerCase() 80 | def newJobName = Utilities.getFullJobName(project, "windows_nt_${lowerConfiguration}", isPR) 81 | 82 | def newJob = job (newJobName) { 83 | steps { 84 | batchFile("""cd llvm 85 | echo |set /p="LLVMCommit=" > %WORKSPACE%\\commits.txt 86 | git rev-parse "refs/remotes/origin/MS^{commit}" >> %WORKSPACE%\\commits.txt 87 | 88 | cd tools\\llilc 89 | echo |set /p="LLILCCommit=" >> %WORKSPACE%\\commits.txt 90 | git rev-parse "refs/remotes/origin/master^{commit}" >> %WORKSPACE%\\commits.txt 91 | 92 | cd %workspace%\\coreclr 93 | echo |set /p="CoreCLRCommit=" >> %WORKSPACE%\\commits.txt 94 | git rev-parse "refs/remotes/origin/master^{commit}" >> %WORKSPACE%\\commits.txt""") 95 | batchFile("""if exist build/ rd /s /q build 96 | mkdir build 97 | 98 | cd coreclr 99 | ./build.cmd ${lowerConfiguration} skiptests""") 100 | batchFile("""cd build 101 | cmake -G \"Visual Studio 14 2015 Win64\" -DWITH_CORECLR=%WORKSPACE%\\coreclr\\bin\\Product\\Windows_NT.x64.${configuration} -DLLVM_OPTIMIZED_TABLEGEN=ON ..\\llvm 102 | \"%VS140COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\" x86 && msbuild llvm.sln /p:Configuration=${configuration} /p:Platform=x64 /t:ALL_BUILD /m""") 103 | } 104 | } 105 | 106 | Utilities.setMachineAffinity(newJob, 'Windows_NT', 'latest-or-auto') 107 | Utilities.addStandardParameters(newJob, project, isPR, '*/master') 108 | addMultiScm(newJob, isPR) 109 | Utilities.addStandardOptions(newJob, isPR) 110 | if (isPR) { 111 | Utilities.addGithubPRTriggerForBranch(newJob, branch, "Windows ${lowerConfiguration}") 112 | } 113 | else { 114 | Utilities.addGithubPushTrigger(newJob) 115 | } 116 | } 117 | } 118 | 119 | [true, false].each { isPR -> 120 | ['Debug', 'Release'].each { configuration -> 121 | String lowerConfiguration = configuration.toLowerCase() 122 | def newJobName = Utilities.getFullJobName(project, "ubuntu_${lowerConfiguration}", isPR) 123 | 124 | def newJob = job (newJobName) { 125 | steps { 126 | shell("if which clang-3.5; then \n export CC=\$(which clang-3.5)\n export CXX=\$(which clang++-3.5)\nelif which clang; then\n export CC=\$(which clang)\n export CXX=\$(which clang++)\nelse\n echo Could not find clang or clang-3.5\n exit 1\nfi\n\n(cd coreclr && ./build.sh ${lowerConfiguration}) && (cd llvm && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=${configuration} -DWITH_CORECLR=../../coreclr/bin/Product/Linux.x64.${configuration} .. && make -j 5)") 127 | } 128 | } 129 | 130 | Utilities.setMachineAffinity(newJob, 'Ubuntu', 'latest-or-auto') 131 | Utilities.addStandardParameters(newJob, project, isPR, '*/master') 132 | addMultiScm(newJob, isPR) 133 | Utilities.addStandardOptions(newJob, isPR) 134 | if (isPR) { 135 | Utilities.addGithubPRTriggerForBranch(newJob, branch, "ubuntu ${lowerConfiguration}") 136 | } 137 | else { 138 | Utilities.addGithubPushTrigger(newJob) 139 | } 140 | } 141 | } 142 | 143 | -------------------------------------------------------------------------------- /Documentation/Areas-To-Contribute.md: -------------------------------------------------------------------------------- 1 | # Areas to Contribute 2 | 3 | Below is a list of areas where LLILC needs work. 4 | Their order follows the path to creating a functioning JIT, that can compile 5 | most C# programs; and doing so with contributions from the Community - so good 6 | documentation comes early. 7 | Each item is given a "star" rating: 1 star denotes easy; many stars denote challenging. 8 | 9 | We always keep a [list of open issues](https://github.com/dotnet/llilc/issues) 10 | in the repo, to track open work items. This is a good place to start. But 11 | beware that it changes day-by-day. So if you spot an item you'd like to work 12 | on, assign it to yourself, so everyone can see it's being worked on. 13 | 14 | As you work on an issue, it will likely spawn more work. So enter these as issues. 15 | 16 | ## Major Areas 17 | 18 | + (*) Areas where documentation needs improving. 19 | Eg: [#122](https://github.com/dotnet/llilc/issues/122), 20 | [#124](https://github.com/dotnet/llilc/issues/124), 21 | [#128](https://github.com/dotnet/llilc/issues/128), 22 | [#129](https://github.com/dotnet/llilc/issues/129), 23 | [#130](https://github.com/dotnet/llilc/issues/130), 24 | [#131](https://github.com/dotnet/llilc/issues/131), 25 | [#145](https://github.com/dotnet/llilc/issues/145), 26 | [#154](https://github.com/dotnet/llilc/issues/154), 27 | [#174](https://github.com/dotnet/llilc/issues/174), 28 | [#175](https://github.com/dotnet/llilc/issues/175), 29 | [#176](https://github.com/dotnet/llilc/issues/176) 30 | 31 | + (**) Extend the Reader 32 | Eg: [#281](https://github.com/dotnet/llilc/issues/281), 33 | [#283](https://github.com/dotnet/llilc/issues/283), 34 | [#284](https://github.com/dotnet/llilc/issues/284), 35 | [#286](https://github.com/dotnet/llilc/issues/286) 36 | 37 | + (**) Add support for more MSIL opcodes. 38 | Eg: [#191](https://github.com/dotnet/llilc/issues/191), 39 | [#192](https://github.com/dotnet/llilc/issues/192) 40 | 41 | + (**) Implement missing TODO features. Eg: 42 | + Synchronized methods [#271](https://github.com/dotnet/llilc/issues/271) 43 | + Just my code [#272](https://github.com/dotnet/llilc/issues/272) 44 | + Explicit class initialization [#274](https://github.com/dotnet/llilc/issues/274) 45 | + Union types [#275](https://github.com/dotnet/llilc/issues/275) 46 | + Virtual stub dispatch [#267](https://github.com/dotnet/llilc/issues/267) 47 | + Intrinsic calls 48 | 49 | + (***) Finish support for CoreCLR Generics. 50 | 51 | + (****) Exception Handling. 52 | Eg: [#66](https://github.com/dotnet/llilc/issues/66), 53 | [#67](https://github.com/dotnet/llilc/issues/67), 54 | [#68](https://github.com/dotnet/llilc/issues/68), 55 | [#69](https://github.com/dotnet/llilc/issues/69), 56 | [#70](https://github.com/dotnet/llilc/issues/70), 57 | [#71](https://github.com/dotnet/llilc/issues/71), 58 | [#73](https://github.com/dotnet/llilc/issues/73), 59 | [#74](https://github.com/dotnet/llilc/issues/74), 60 | [#75](https://github.com/dotnet/llilc/issues/75), 61 | [#76](https://github.com/dotnet/llilc/issues/76), 62 | [#77](https://github.com/dotnet/llilc/issues/77) 63 | 64 | + (**) Memory allocation [#233](https://github.com/dotnet/llilc/issues/233) 65 | 66 | + (***) Function inlining [#239](https://github.com/dotnet/llilc/issues/239) 67 | 68 | + (*) Enable vectorization (System.Numerics.Vector) 69 | 70 | + (**) Add aliasing information for loads that are known to be 71 | invariants (eg array length, vtables, etc). 72 | [#291](https://github.com/dotnet/llilc/issues/291) 73 | 74 | + (**) GC Lifetime Checker. 75 | [#34](https://github.com/dotnet/llilc/issues/34) 76 | 77 | + (***) Ports to other platforms. 78 | + Linux and MAC OSX are basically working, but need refining 79 | + Other platforms (eg: ARM-64) 80 | 81 | + (**) Enable deferred lowering of certain runtime 82 | constructs [#292](https://github.com/dotnet/llilc/issues/292) 83 | + Helper calls (eg: double->int conversions) 84 | + Write barriers 85 | + Struct copying 86 | 87 | 88 | + (***)Design & Architecture. 89 | Eg: [#22](https://github.com/dotnet/llilc/issues/22); Object-Model Operators; 90 | 91 | + (**) Optimizations specific to C#: 92 | + null check 93 | + bounds check 94 | + type check 95 | + overflow check 96 | + etc 97 | 98 | + (*) Add benchmarks for optimization 99 | 100 | + (\*\*) Add web-crawler to *harvest* MSIL tests and execute 101 | 102 | + (***) Generator for random (but legal) MSIL code [#503](https://github.com/dotnet/llilc/issues/503) 103 | 104 | + (**) Bugs 105 | + If you want to fix an existing bug, assign to yourself and go 106 | + If you find a new bug, please check it's not a 107 | duplicate, then enter as an issue, with as simple a repro as you can devise 108 | 109 | + (**) NGEN support [#287](https://github.com/dotnet/llilc/issues/287) 110 | -------------------------------------------------------------------------------- /test/applyfilter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #title :applyfilter.py 4 | #description : 5 | # This script performs normalization of verbose LLVM IR dump generated by LLILC JIT. 6 | # The module also provides support facilty for llilc_runtest and llilc_checkpass 7 | # such as ApplyAll etc. 8 | # 9 | # Normalized cases include: 10 | # 11 | # Suppress address difference from run to run 12 | # Assume the address is at least 10-digit number 13 | # Example 1: 14 | # 15 | # Normalize 16 | # %2 = call i64 inttoptr (i64 140704958972024 to i64 (i64)*)(i64 140704956891884) 17 | # to 18 | # %2 = call i64 inttoptr (i64 NORMALIZED_ADDRESS to i64 (i64)*)(i64 NORMALIZED_ADDRESS) 19 | # 20 | # Example 2: 21 | # 22 | # Normalize 23 | # %3 = icmp eq i64 140704956891886, %2 24 | # to 25 | # %3 = icmp eq i64 NORMALIZED_ADDRESS, %2 26 | # 27 | # Example 3: 28 | # 29 | # Normalize 30 | # %12 = phi i64 [ 709816494128, %3 ], [ 709816494128, %7 ] 31 | # to 32 | # %12 = phi i64 [ NORMALIZED_ADDRESS, %3 ], [ NORMALIZED_ADDRESS, %7 ] 33 | # 34 | # Suppress type id difference from run to run 35 | # 36 | # Example 1: 37 | # 38 | # Normalize 39 | # %3 = load %System.AppDomainSetup.239 addrspace(1)** %1 40 | # to 41 | # %3 = load %System.AppDomainSetup.NORMALIZED_TYPEID addrspace(1)** %1 42 | # 43 | # Example 2: 44 | # 45 | # Normalize 46 | # %0 = alloca %AppDomain.24 addrspace(1)* 47 | # to 48 | # %0 = alloca %AppDomain.NORMALIZED_TYPEID addrspace(1)* 49 | # 50 | # Suppress type id difference from run to run, string name with double quotes 51 | #========================================================================================== 52 | 53 | import os 54 | import sys 55 | import re 56 | import argparse 57 | 58 | # Apply filter on src and create a normalized file dest. 59 | # And extract out function summary if specified. 60 | def ApplyOne(src, dest, summary=None): 61 | re_addr = re.compile(r'i64 \d{10}\d*') 62 | re_type = re.compile(r'%("?)(.*?)\.\d+\1 addrspace') 63 | re_phi = re.compile(r'\[ \d{10}\d*, %') 64 | if summary is None: 65 | with open(src, 'r') as ins, open(dest, 'w') as outs: 66 | for line in ins: 67 | line = re_addr.sub(r'i64 NORMALIZED_ADDRESS', line) 68 | line = re_type.sub(r'%\1\2.NORMALIZED_TYPEID\1 addrspace', line) 69 | line = re_phi.sub(r'[ NORMALIZED_ADDRESS, %', line) 70 | outs.write(line) 71 | else: 72 | re_read_failure = re.compile(r'Failed to read ') 73 | re_read_success = re.compile(r'Successfully read ') 74 | with open(src, 'r') as ins, open(dest, 'w') as outs, open(summary, 'w') as sums: 75 | for line in ins: 76 | extract = re_read_failure.search(line) 77 | if extract is None: 78 | extract = re_read_success.search(line) 79 | if extract is not None: 80 | sums.write(line) 81 | else: 82 | line = re_addr.sub(r'i64 NORMALIZED_ADDRESS', line) 83 | line = re_type.sub(r'%\1\2.NORMALIZED_TYPEID\1 addrspace', line) 84 | line = re_phi.sub(r'[ NORMALIZED_ADDRESS, %', line) 85 | outs.write(line) 86 | 87 | # Apply filter recursively on directory walk_dir. 88 | # And extract out function summary. 89 | def ApplyAll(walk_dir): 90 | for root, sub_dirs, files in os.walk(walk_dir): 91 | for file_name in files: 92 | if file_name.endswith('error.txt'): 93 | sum_file_name = str(file_name).replace('error.txt', 'sum.txt') 94 | tmp_file_name = file_name + '.tmp' 95 | file_path = os.path.join(root, file_name) 96 | sum_file_path = os.path.join(root, sum_file_name) 97 | tmp_file_path = os.path.join(root, tmp_file_name) 98 | ApplyOne(file_path, tmp_file_path, sum_file_path) 99 | os.remove(file_path) 100 | os.rename(tmp_file_path, file_path) 101 | 102 | # Rename file name in summary result to match what ApplyAll may create 103 | # so that llilc_checkpass can perform checking. 104 | def SummaryRenameAll(walk_dir): 105 | for root, sub_dirs, files in os.walk(walk_dir): 106 | for file_name in files: 107 | if file_name.endswith('error.txt'): 108 | sum_file_name = str(file_name).replace('error.txt', 'sum.txt') 109 | file_path = os.path.join(root, file_name) 110 | sum_file_path = os.path.join(root, sum_file_name) 111 | os.rename(file_path, sum_file_path) 112 | 113 | # The script itself applies the filter on one file 114 | if __name__=='__main__': 115 | # Parse the command line 116 | parser = argparse.ArgumentParser() 117 | parser.add_argument('src', type=str, help='source result to apply filter on') 118 | parser.add_argument('dest', type=str, help='destination result after applying filter') 119 | args = parser.parse_args() 120 | 121 | # Apply the filter on one file 122 | ApplyOne(args.src, args.dest) -------------------------------------------------------------------------------- /include/Reader/ophelper.def: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/ophelper.h --------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Include file to make cleaner use of the opcode.def file to create mappings 13 | /// for info on MSIL ops. 14 | /// 15 | /// To use this header you must use 16 | /// 17 | /// ~~~ 18 | /// #define OPDEF_HELPER 19 | /// #include ophelper.def 20 | /// ~~~ 21 | /// 22 | /// This has the effect of extracting information from the opcode.def file. In particular 23 | /// a list of values is produced suitable for initializing a table. 24 | /// 25 | /// is one of these: 26 | /// - OPDEF_OPCODENAME: to get the opcode name 27 | /// - OPDEF_OPERANDSIZE: to get the operand size 28 | /// - OPDEF_PUSHCOUNT: to get the number of operands pushed 29 | /// - OPDEF_POPCOUNT: to get the number of operands popped 30 | /// - OPDEF_ISBRANCH: to tell if opcode is for a conditional branch. 31 | //===----------------------------------------------------------------------===// 32 | 33 | #ifndef OPDEF_HELPER 34 | #error "Must specify OPDEF_HELPER" 35 | #endif 36 | 37 | #define OPDEF_OPCODENAME 123001 38 | #define OPDEF_OPERANDSIZE 123002 39 | #define OPDEF_PUSHCOUNT 123003 40 | #define OPDEF_POPCOUNT 123004 41 | #define OPDEF_ISBRANCH 123005 42 | 43 | 44 | #if OPDEF_HELPER == OPDEF_OPCODENAME 45 | #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) s, 46 | #include "opcode.def" 47 | #undef OPDEF 48 | 49 | #elif OPDEF_HELPER == OPDEF_OPERANDSIZE 50 | #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) args, 51 | #define InlineNone 0 52 | #define ShortInlineVar 1 53 | #define ShortInlineI 1 54 | #define InlineI 4 55 | #define InlineI8 8 56 | #define ShortInlineR 4 57 | #define InlineR 8 58 | #define InlineMethod 4 59 | #define InlineSig 4 60 | #define ShortInlineBrTarget 1 61 | #define InlineBrTarget 4 62 | #define InlineSwitch -1 63 | #define InlineType 4 64 | #define InlineString 4 65 | #define InlineField 4 66 | #define InlineTok 4 67 | #define InlineVar 2 68 | #include "opcode.def" 69 | #undef OPDEF 70 | #undef InlineNone 71 | #undef ShortInlineVar 72 | #undef ShortInlineI 73 | #undef InlineI 74 | #undef InlineI8 75 | #undef ShortInlineR 76 | #undef InlineR 77 | #undef InlineMethod 78 | #undef InlineSig 79 | #undef ShortInlineBrTarget 80 | #undef InlineBrTarget 81 | #undef InlineSwitch 82 | #undef InlineType 83 | #undef InlineString 84 | #undef InlineField 85 | #undef InlineTok 86 | #undef InlineVar 87 | 88 | #elif OPDEF_HELPER == OPDEF_PUSHCOUNT 89 | #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) push, 90 | #define Push0 0 91 | #define Push1 1 92 | #define VarPush -1 93 | #define PushI 1 94 | #define PushI4 1 95 | #define PushI8 1 96 | #define PushR4 1 97 | #define PushR8 1 98 | #define PushRef 1 99 | #include "opcode.def" 100 | #undef OPDEF 101 | #undef Push0 102 | #undef Push1 103 | #undef VarPush 104 | #undef PushI 105 | #undef PushI4 106 | #undef PushI8 107 | #undef PushR4 108 | #undef PushR8 109 | #undef PushRef 110 | 111 | #elif OPDEF_HELPER == OPDEF_POPCOUNT 112 | #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) pop, 113 | #define Pop0 0 114 | #define Pop1 1 115 | #define VarPop -1 116 | #define PopI 1 117 | #define PopI4 1 118 | #define PopI8 1 119 | #define PopR4 1 120 | #define PopR8 1 121 | #define PopRef 1 122 | #include "opcode.def" 123 | #undef OPDEF 124 | #undef Pop0 125 | #undef Pop1 126 | #undef VarPop 127 | #undef PopI 128 | #undef PopI4 129 | #undef PopI8 130 | #undef PopR4 131 | #undef PopR8 132 | #undef PopRef 133 | 134 | #elif OPDEF_HELPER == OPDEF_ISBRANCH 135 | #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) ctrl, 136 | #define NEXT 0 137 | #define BREAK 0 138 | #define CALL 0 139 | 140 | #if defined(_MSC_VER) 141 | #pragma push_macro("RETURN") 142 | #endif // _MSC_VER 143 | 144 | #if defined(RETURN) 145 | #undef RETURN 146 | #endif 147 | #define RETURN 0 148 | #define BRANCH 0 149 | #define COND_BRANCH 1 150 | #define THROW 0 151 | #define META 0 152 | #include "opcode.def" 153 | #undef OPDEF 154 | #undef NEXT 155 | #undef BREAK 156 | #undef CALL 157 | #undef RETURN 158 | 159 | #if defined(_MSC_VER) 160 | #pragma pop_macro("RETURN") 161 | #else 162 | #undef RETURN 163 | #endif // defined(_MSC_VER) 164 | 165 | #undef BRANCH 166 | #undef COND_BRANCH 167 | #undef THROW 168 | #undef META 169 | 170 | #else 171 | #error "Unrecognized OPDEF_HELPER" 172 | #endif 173 | 174 | #undef OPDEF_OPCODENAME 175 | #undef OPDEF_OPERANDSIZE 176 | #undef OPDEF_PUSHCOUNT 177 | #undef OPDEF_POPCOUNT 178 | -------------------------------------------------------------------------------- /Documentation/Getting-Started-For-Windows.md: -------------------------------------------------------------------------------- 1 | # Getting Started for Windows 2 | 3 | Note: all commands are typed from a Windows Command Prompt, and `c:\dotnet` 4 | may be replaced in all commands below with the directory of your choice. 5 | 6 | * Install Git 7 | * Follow the instructions at [git-scm downloads](http://git-scm.com/downloads). 8 | All of the installer's defaults are acceptable. 9 | 10 | * Install CMake 11 | * Follow the instructions at [CMake Install](http://www.cmake.org/install/) 12 | * Make sure to select "Add CMake to the system PATH for all users" when 13 | running the installer (all other defaults are acceptable). 14 | 15 | * Clone and build CoreCLR: 16 | ``` 17 | $ git clone https://github.com/dotnet/coreclr 18 | $ cd coreclr 19 | $ .\build.cmd 20 | $ cd .. 21 | ``` 22 | After it completes, the build will indicate where the CoreCLR binaries 23 | are available. Make a note of this location 24 | (typically bin/Product/Windows_NT.x64.debug). 25 | 26 | * Clone the Microsoft fork of LLVM to your PC 27 | * Change directories to where you want to place your clone and run `git` 28 | to clone the Microsoft fork of LLVM: 29 | ``` 30 | > cd c:\dotnet 31 | > git clone -b MS https://github.com/microsoft/llvm 32 | ``` 33 | 34 | * This will create a directory tree under `llvm` that contains the cloned 35 | sources. 36 | 37 | * Clone LLILC to your PC 38 | * Because LLILC is structured as an LLVM tool, it is canonically cloned 39 | into the `tools` subdirectory of the LLVM tree created above: 40 | 41 | ``` 42 | > cd c:\dotnet\llvm\tools 43 | > git clone https://github.com/dotnet/llilc 44 | ``` 45 | 46 | * This will create a directory tree under `llilc` that contains the cloned 47 | sources. 48 | 49 | * Install Python 50 | * Follow the instructions at [Python Downloads](https://www.python.org/downloads/) 51 | * Choose Python 2.7.9 for Windows 52 | 53 | * Install Visual Studio 2013 54 | * Follow the instructions at [Visual Studio](http://www.visualstudio.com/en-us/products/visual-studio-community-vs) 55 | to install the free Community edition of Visual Studio 2013. 56 | * Update the product to [Visual Studio Update 4](http://www.microsoft.com/en-us/download/details.aspx?id=39305) 57 | 58 | * If you want to run [Doxygen](http://www.stack.nl/~dimitri/doxygen/) to 59 | produce documentation from your code comments, then in addition do the following: 60 | * Install [Doxygen](http://www.stack.nl/~dimitri/doxygen/) using the 61 | instructions on its web site. The LLVM web site is using Doxygen 1.7.6.1 62 | however the 1.8 series added support for Markdown formatting. We would like 63 | to use Markdown in our comments, so use the latest version of Doxygen. 64 | * Install [graphviz](http://graphviz.org/) using instructions on their 65 | site. The current version no longer modifies your path, so you should 66 | manually modify your path so that it includes "dot". 67 | * Create a Visual Studio Solution for LLVM + LLILC 68 | * Create a directory to hold the LLVM build output: 69 | 70 | ``` 71 | > cd c:\dotnet 72 | > mkdir llvm-build 73 | ``` 74 | 75 | * Run cmake from within the newly-created `llvm-build` directory with the 76 | Visual Studio backend to generate the LLVM solution: 77 | 78 | ``` 79 | > cd llvm-build 80 | > cmake -G "Visual Studio 12 2013 Win64" ..\llvm -DWITH_CORECLR=\bin\Product\$platform.$arch.$build> -DLLVM_OPTIMIZED_TABLEGEN=ON 81 | ``` 82 | note: for Windows $platform should resolve to 'Windows_NT' 83 | 84 | * However if you also want to run Doxygen, use the following instead: 85 | 86 | ``` 87 | > cd llvm-build 88 | > cmake -G "Visual Studio 12 2013 Win64" ..\llvm -DLLVM_ENABLE_DOXYGEN=ON -DWITH_CORECLR=\bin\Product\$platform.$arch.$build> -DLLVM_OPTIMIZED_TABLEGEN=ON 89 | ``` 90 | 91 | * This will generate `LLVM.sln` inside the `llvm-build` directory. 92 | 93 | * Build LLVM + LLILC from the command line 94 | * Change directories to the LLVM build directory and set up environment 95 | variables for the Visual Studio toolchain: 96 | 97 | ``` 98 | > cd c:\dotnet\llvm-build 99 | > "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x64 100 | ``` 101 | 102 | * Start the build. Note that If you have a multi-core machine, you may 103 | request a faster, parallel build by adding the `/m` flag to the command 104 | line, optionally specifying the degree of parallelism (e.g. `/m:4`). 105 | 106 | ``` 107 | > msbuild LLVM.sln /p:Configuration=Debug /p:Platform=x64 /t:ALL_BUILD 108 | ``` 109 | 110 | * To run doxygen over the LLILC sources use the following command line: 111 | 112 | ``` 113 | > msbuild LLVM.sln /p:Configuration=Debug /p:Platform=x64 /t:doxygen-llilc 114 | ``` 115 | 116 | The build steps above can also be done from Visual Studio by going to the 117 | solution explorer, right clicking the desired project (e.g. ALL_BUILD or 118 | doxygen-llilc) and selecting "build". 119 | -------------------------------------------------------------------------------- /utils/BuildPackages.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Builds and publishes the cross-platform and combined pacakges for RyuJit. Cross-platform binaries 4 | are sourced from Azure Blob Storage. 5 | #> 6 | 7 | [CmdletBinding()] 8 | Param( 9 | # The feed to publish to. 10 | [string]$feed, 11 | 12 | # The API key to use during publishing. 13 | [string]$apiKey, 14 | 15 | # The Azure account to use. 16 | [string]$storageAccount, 17 | 18 | # The Azure account key to use. 19 | [string]$storageKey, 20 | 21 | # The Azure container to use. 22 | [string]$storageContainer, 23 | 24 | # The path to NuGet. Defaults to "nuget.exe". 25 | [string]$nugetPath = "nuget.exe", 26 | 27 | # The output directory for the cross-platform binaries. 28 | [string]$binariesDir, 29 | 30 | # The package output directory. 31 | [string]$packageOutputDir, 32 | 33 | # The directory that contains the .nuspec files that will be used to create the 34 | # cross-platform and combined packages. 35 | [string]$nuspecDir 36 | ) 37 | 38 | function Get-Latest-Blob-Name 39 | { 40 | Param([array]$blobs, [string]$expectedSuffix) 41 | 42 | $chosenBlob = $null 43 | $chosenDate = $null 44 | foreach ($blob in $blobs) 45 | { 46 | if ($blob.name -notlike "*$expectedSuffix") 47 | { 48 | continue 49 | } 50 | 51 | $date = [datetime]($blob.properties."last-modified") 52 | if (!$chosenBlob -or ($chosenDate -and $date -ge $chosenDate)) 53 | { 54 | $chosenBlob = $blob.name 55 | $chosenDate = $date 56 | } 57 | } 58 | 59 | return $chosenBlob 60 | } 61 | 62 | # Get the list of blobs in storage 63 | $json = (azure storage blob list -a $storageAccount -k $storageKey $storageContainer --json) -join "" 64 | $blobs = ConvertFrom-Json $json 65 | 66 | # Find, fetch, and extract the latest Ubuntu and OSX blobs 67 | [System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null 68 | 69 | $ubuntuBlob = Get-Latest-Blob-Name $blobs "Ubuntu.14.04_LLILC_x64_Release_Enu.zip" 70 | $osxBlob = Get-Latest-Blob-Name $blobs "OSX_LLILC_x64_Release_Enu.zip" 71 | 72 | if (!$ubuntuBlob) 73 | { 74 | Write-Error "Could not locate an Ubuntu drop in Azure." 75 | exit 1 76 | } 77 | 78 | if (!$osxBlob) 79 | { 80 | Write-Error "Could not locate an OS X drop in Azure." 81 | exit 1 82 | } 83 | 84 | azure storage blob download -m -q -a $storageAccount -k $storageKey $storageContainer $ubuntuBlob 85 | if ($LastExitCode -ne 0) 86 | { 87 | Write-Error "Failed to fetch Ubuntu drop $ubuntuDrop from Azure." 88 | exit 1 89 | } 90 | 91 | azure storage blob download -m -q -a $storageAccount -k $storageKey $storageContainer $osxBlob 92 | if ($LastExitCode -ne 0) 93 | { 94 | Write-Error "Failed to fetch OS X drop $osxBlob from Azure." 95 | exit 1 96 | } 97 | 98 | $ubuntuDirectory = [System.IO.Path]::GetFileNameWithoutExtension($ubuntuBlob) 99 | try 100 | { 101 | [System.IO.Compression.ZipFile]::ExtractToDirectory($ubuntuBlob, $ubuntuDirectory) 102 | } 103 | catch 104 | { 105 | Write-Error "Failed to extract Ubuntu drop to $ubuntuDirectory`: $_.Exception.Message" 106 | exit 1 107 | } 108 | 109 | $osxDirectory = [System.IO.Path]::GetFileNameWithoutExtension($osxBlob) 110 | try 111 | { 112 | [System.IO.Compression.ZipFile]::ExtractToDirectory($osxBlob, $osxDirectory) 113 | } 114 | catch 115 | { 116 | Write-Error "Failed to extract OS X drop to $osxDirectory`: $_.Exception.Message" 117 | exit 1 118 | } 119 | 120 | # Gather the bits from the Ubuntu and OSX blobs into the bin directory 121 | $items = @( 122 | "$ubuntuDirectory\libobjwriter.so", 123 | "$osxDirectory\libobjwriter.dylib", 124 | ) 125 | 126 | Copy-Item -Path $items -Destination $binariesDir 127 | if ($LastExitCode -ne 0) 128 | { 129 | Write-Error "Failed to copy cross-platform bits to $binariesDir." 130 | exit 1 131 | } 132 | 133 | if (!(Test-Path $packageOutputDir)) 134 | { 135 | New-Item $packageOutputDir -Type Directory 136 | if ($LastExitCode -ne 0) 137 | { 138 | Write-Error "Failed to create $packageOutputDir" 139 | exit 1 140 | } 141 | } 142 | 143 | # Gather the .nuspecs and their dependencies into the package output directory 144 | $files = @( 145 | "$nuspecDir\Microsoft.DotNet.ObjectWriter.nuspec", 146 | "$nuspecDir\runtime.json", 147 | "$nuspecDir\toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec", 148 | "$nuspecDir\toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec", 149 | "$nuspecDir\toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec" 150 | ) 151 | Copy-Item -Path $files -Destination $packageOutputDir 152 | if ($LastExitCode -ne 0) 153 | { 154 | Write-Error "Failed to copy nuspecs to $packageOutputDir." 155 | exit 1 156 | } 157 | 158 | # Create the packages. 159 | $packages = @( 160 | "Microsoft.DotNet.ObjectWriter", 161 | "toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter", 162 | "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter", 163 | "toolchain.win7-x64.Microsoft.DotNet.ObjectWriter" 164 | ) 165 | 166 | # Note: nuget appears to exit with code 0 in every case, so there's no way to detect failure here 167 | # other than looking at the output. 168 | foreach ($package in $packages) { 169 | Invoke-Expression "$nugetPath pack $packageOutputDir\$package.nuspec -NoPackageAnalysis -NoDefaultExludes -OutputDirectory $packageOutputDir" 170 | Invoke-Expression "$nugetPath push -NonInteractive $packageOutputDir\$package.nupkg -s $feed $apiKey" 171 | } 172 | -------------------------------------------------------------------------------- /Documentation/Setup-With-LLILC-Out-Of-LLVM-Tree.md: -------------------------------------------------------------------------------- 1 | # Setup With LLILC Out-Of LLVM Tree 2 | 3 | The [Getting Started for Windows doc](Getting-Started-For-Windows.md) tells 4 | how to configure LLILC when the LLILC repository is placed in the LLVM/tools 5 | subdirectory. This page tells how to configure LLVM and LLILC when the LLILC 6 | workspace is separate from the LLVM workspace. This might be desirable, for 7 | example, if you want to have multiple LLILC workspaces (for working on 8 | multiple branches simultaneously) but want to share a single LLVM workspace 9 | and LLVM build. 10 | 11 | We document which steps are the same and which steps that are different 12 | from the [Getting Started for Windows document](Getting-Started-For-Windows.md). 13 | 14 | Steps that are the same are: 15 | 16 | * Install Git 17 | * Clone and build CoreCLR: 18 | * Clone the Microsoft fork of LLVM to your PC 19 | * Install Python 20 | * Install CMake 21 | * Install Visual Studio 2013 22 | * Install [Doxygen](http://www.stack.nl/~dimitri/doxygen/) 23 | * Install [graphviz](http://graphviz.org/) 24 | 25 | In what follows, let 26 | 27 | * $coreclr-repo-dir be the directory where the the coreclr was cloned. 28 | * $coreclr-build-dir be $coreclr-repo-dir\bin\Product\$platform.$arch.$build> directory. 29 | * $llvm-repo-dir be the directory where LLVM was cloned. 30 | * $llvm-build-dir be the directory where LLVM was built. 31 | * $llilc-repo-dir be the directory where LLILC was cloned 32 | * $llilc-build-dir be the directory where LLILC is built 33 | 34 | $coreclr-build-dir is fixed relative to $coreclr-repo-dir, but all of the others can be 35 | placed wherever you like. Below we use paths like $llilc-repo-dir/.. to denote the 36 | parent directory of $llilc-repo-dir. When we do a `cd` to a directory we assume you 37 | have previously created the directory. To simplify the description we also assume you 38 | will be enabling Doxygen. 39 | 40 | Steps that are different: 41 | 42 | * Clone LLILC to your PC 43 | * Unlike the [Getting Started for Windows](Getting-Started-For-Windows.md) 44 | directions, create a separate LLILC directory.: 45 | 46 | ``` 47 | > cd $llilc-repo-dir/.. 48 | > git clone https://github.com/dotnet/llilc 49 | ``` 50 | 51 | * This will create a directory tree under $llilc-repo-dir that contains 52 | the cloned sources. 53 | 54 | * Create a Visual Studio Solution for LLVM 55 | * Create a directory to hold the LLVM build output: 56 | 57 | ``` 58 | > mkdir $llvm-build-dir 59 | ``` 60 | 61 | * Run cmake from within the newly-created `llvm-build` directory with the 62 | Visual Studio backend to generate the LLVM solution: 63 | 64 | ``` 65 | > cd $llvm-build-dir 66 | > cmake -G "Visual Studio 12 2013 Win64" $llvm-repo-dir -DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_TARGETS_TO_BUILD:STRING=X86 -DLLVM_ENABLE_DOXYGEN=ON 67 | ``` 68 | 69 | * This will generate `LLVM.sln` inside the $llvm-build-dir directory. 70 | 71 | * Build LLVM from the command line 72 | * Change directories to the LLVM build directory and set up environment 73 | variables for the Visual Studio toolchain: 74 | 75 | ``` 76 | > cd $llvm-build-dir 77 | > "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x64 78 | ``` 79 | 80 | * Start the build. Note that If you have a multi-core machine, you may 81 | request a faster, parallel build by adding the `/m` flag to the command 82 | line, optionally specifying the degree of parallelism (e.g. `/m:4`). 83 | 84 | ``` 85 | > msbuild LLVM.sln /p:Configuration=Debug /p:Platform=x64 /t:ALL_BUILD 86 | ``` 87 | 88 | * Create a Visual Studio Solution for LLILC 89 | * Create a directory to hold the LLILC build output: 90 | 91 | ``` 92 | > mkdir $llilc-build-dir 93 | ``` 94 | 95 | * Run cmake from within the newly-created `llilc-build` directory with the 96 | Visual Studio backend to generate the LLVM solution: 97 | 98 | ``` 99 | > cd $llilc-build-dir 100 | > cmake -G "Visual Studio 12 2013 Win64" $llilc-repo-dir -DWITH_CORECLR=$coreclr-build-dir -DWITH_LLVM=$llvm-build-dir -DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_TARGETS_TO_BUILD:STRING=X86 -DLLVM_ENABLE_DOXYGEN=ON 101 | ``` 102 | 103 | * This will generate `LLILC.sln` inside the $llilc-build-dir directory. 104 | * Currently there is a bug in the LLVM configuration that leaves some file 105 | paths in Windows format with back slashes. If you get an error message 106 | when configuring, like 107 | ``` 108 | Syntax error in cmake code at 109 | 110 | share/llvm/cmake/LLVMExports.cmake:233 111 | 112 | when parsing string 113 | 114 | ...C:\Program Files (x86)\... 115 | 116 | Invalid escape sequence \P 117 | ``` 118 | you can work around it by editing the offending line by 119 | changing the back slashes to forward slashes. 120 | 121 | * Build LLILC from the command line 122 | * Change directories to the LLVM build directory and set up environment 123 | variables for the Visual Studio toolchain: 124 | 125 | ``` 126 | > cd $llilc-build-dir 127 | > "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x64 128 | ``` 129 | 130 | * Start the build. Note that If you have a multi-core machine, you may 131 | request a faster, parallel build by adding the `/m` flag to the command 132 | line, optionally specifying the degree of parallelism (e.g. `/m:4`). 133 | 134 | ``` 135 | > msbuild LLILC.sln /p:Configuration=Debug /p:Platform=x64 /t:ALL_BUILD 136 | ``` 137 | 138 | * To run doxgen over the LLILC sources use the following command line: 139 | 140 | ``` 141 | > msbuild LLVM.sln /p:Configuration=Debug /p:Platform=x64 /t:doxygen-llilc 142 | ``` 143 | -------------------------------------------------------------------------------- /Documentation/Testing.md: -------------------------------------------------------------------------------- 1 | # Testing LLILC 2 | 3 | ## Test Harness 4 | 5 | LLILC's test harness uses CoreCLR's test assets as underlying engine. It 6 | provides a LLILC-specific wrapper layer above it. The test harness is located 7 | at llilc\test. Please add this path to your PATH environment variable before 8 | using it. 9 | 10 | There are three steps in LLILC testing: building tests, running tests, and 11 | checking results. 12 | 13 | ## Building tests: 14 | 15 | Building tests is performed with CoreCLR script directly. A CoreCLR build 16 | automatically performs building tests. If it is done already, you can choose 17 | to skip this step. If you want to build test as a separate step, do the following: 18 | 19 | ``` 20 | cd C:\coreclr\tests 21 | buildtest.cmd clean 22 | ``` 23 | https://github.com/dotnet/coreclr/wiki/Test-instructions for more information. 24 | 25 | ## Running tests: 26 | 27 | Use llilc_runtest.py to run tests. With specified LLILC JIT and pre-built 28 | CoreCLR runtime, llilc_runtest runs CoreCLR testing. You can choose to create 29 | a running result if you want to. The result contains LLILC specific dumps: 30 | per function summary or detailed LLVM IR dumps. You need to run this script 31 | from coreclr\tests directory. 32 | ``` 33 | cd C:\coreclr\tests 34 | llilc_runtest -d verbose -j C:\llvm-build\bin\Debug\llilcjit.dll -c C:\coreclr\bin\Product\Windows_NT.x64.Debug -r C:\results\base 35 | ``` 36 | llilc_runtest --help for more information. 37 | 38 | **Note:** You may find that running tests with a pure DEBUG build of LLILC 39 | is very slow. To get a faster build that still has assertion checking, pass 40 | `-DCMAKE_BUILD_TYPE=RELWITHDEBINFO -DLLVM_ENABLE_ASSERTIONS=ON` to cmake and 41 | `/p:Configuration=RelWithDebInfo` to msbuild when you configure/build LLILC/LLVM. 42 | 43 | ## Checking results: 44 | 45 | Use llilc_checkpass to check the results. It takes two test results, using 46 | one as base result, one as diff result to perform the checking. This step is 47 | LLILC-specific. Because LLILC is still under early stage of development, we 48 | need to guarantee that any function that was successfully jitted by LLILC is 49 | not broken by new change. 50 | ``` 51 | llilc_checkpass -b C:\results\base -d C:\results\diff 52 | ``` 53 | llilc_checkpass --help for more information. 54 | 55 | It is required that developer has to guarantee all LLVM IR changes are benign. 56 | It can be achieved with any diff tool. 57 | 58 | ## Running individual tests: 59 | 60 | The process for running individual test cases on Windows in cmd is: 61 | * Copy the LLILCJit.dll in `llvm-build/bin/Debug` to the CoreCLR binary 62 | directory (`coreclr/bin/Product//`) 63 | * Run the `llilc/test/LLILCTestEnv.cmd` to set the needed env variables. If 64 | debug printing is desired, also run `set COMPlus_DumpLLVMIR=[summary, verbose]`. 65 | * Set the code page to 65001 (See #527 and #12). 66 | * Run the test binary via CoreRun.exe. 67 | 68 | ## Using llilc as an ngen jit: 69 | 70 | crossgen.exe is the tool used to generate ngen images for CoreCLR. The 71 | generated native image has .ni.exe or .ni.dll suffix. crossgen requires 72 | mscorlib.ni.dll to be available – you have to generate mscorlib.ni.dll first. 73 | The following environment variable needs to be set (in addition to running 74 | llilc/test/LLILCTestEnv.cmd): 75 | `set COMPlus_AltJitNgen=*`. 76 | 77 | ## Use Cases 78 | 79 | ### Developer Use Case 80 | Step 1: Update CoreCLR to latest, and build CoreCLR 81 | 82 | Step 2: Update LLILC master to latest, and build your baseline JIT 83 | 84 | Step 3: Create a verbose baseline result: 85 | 86 | ``` 87 | cd coreclr\tests 88 | llilc_runtest -j -c -d verbose -r 89 | ``` 90 | Step 4: Create your own branch 91 | 92 | Step 5: Do new development or fix issues on your branch, and build your new diff JIT 93 | 94 | Step 6: Check your change pass overall testing: 95 | 96 | ``` 97 | cd coreclr\tests 98 | llilc_runtest -j -c 99 | ``` 100 | If failed, back to step 5 for fixing. 101 | 102 | Step 7: Check you change does not cause new jitting failure: 103 | 104 | ``` 105 | cd coreclr\tests 106 | llilc_runtest -j -c -d summary -r 107 | llilc_checkpass -b -d 108 | ``` 109 | If failed, back to step 5 for fixing. 110 | 111 | Step 8: Check your change does not cause bad LLVM IR change. 112 | 113 | ``` 114 | llilc_runtest -j -c -d verbose -r 115 | ``` 116 | Use any diff tool to compare \ and \. 117 | If there is bad LLVM IR change, back to step 5 for fixing. 118 | 119 | Step 9: Now you are ready for a pull request. 120 | 121 | ### Lab CI Use Case 122 | Lab CI usage is the most simplified version. It only checks for overall 123 | pass/fail and does not keep any result. 124 | ``` 125 | cd coreclr\tests 126 | llilc_runtest -j -c 127 | ``` 128 | 129 | ### Lab Nightly Use Case 130 | Step 1. Create a summary result with last-known-good JIT as a baseline or use 131 | a previous last-known-good summary result as a baseline 132 | ``` 133 | cd coreclr\tests 134 | llilc_runtest -j -c -d summary -c 135 | ``` 136 | 137 | Step 2. Create a summary result with latest JIT as diff result 138 | ``` 139 | cd coreclr\tests 140 | llilc_runtest -j -c -d summary -r 141 | ``` 142 | 143 | Step 3. Check if there is any new jitting failure 144 | ``` 145 | cd coreclr\tests 146 | llilc_checkpass -b -d 147 | ``` 148 | 149 | Step 4. If llilc_checkpass result is negative, there is unexpected error. 150 | 151 | Step 5.If llilc_checkpass result is 0, mark latest JIT as last-known-good JIT. 152 | Result \ could be kept as last-known-good summary result. 153 | 154 | Step 6.If llilc_checkpass result is 1, send out failure notice to branch owner. 155 | Branch owner should analyze the case and bring relevant developer for fixing. 156 | -------------------------------------------------------------------------------- /include/Jit/jitoptions.h: -------------------------------------------------------------------------------- 1 | //===----------------- include/Jit/options.h -------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declaration of the Options class that encapsulates JIT options 13 | /// extracted from CoreCLR config values. 14 | /// 15 | //===----------------------------------------------------------------------===// 16 | 17 | #ifndef JITOPTIONS_H 18 | #define JITOPTIONS_H 19 | 20 | #include "options.h" 21 | 22 | /// \brief The JIT options implementation. 23 | /// 24 | /// This class queries the CoreCLR interface to compute the Options flags 25 | /// consumed by the JIT. The query logic here should only be usable from the 26 | /// base JIT at initialization time of the context. 27 | /// 28 | /// This derived class is responsible for filling out the base fields 29 | /// as well as it's own. The base Options class contains options used in 30 | /// all configurations but includes to query logic to fill them out as that 31 | /// will be client based (JIT or AOT) 32 | /// 33 | class JitOptions : public Options { 34 | public: 35 | /// Construct an JitOptions object based on the passed JitContext. 36 | JitOptions(LLILCJitContext &JitContext); 37 | 38 | /// Destruct Options object. 39 | ~JitOptions(); 40 | 41 | private: 42 | /// Set current JIT invocation as "AltJit". This sets up 43 | /// the JIT to filter based on the AltJit flag contents. 44 | /// \returns true if runing as the alternate JIT 45 | static bool queryIsAltJit(LLILCJitContext &JitContext); 46 | 47 | /// \brief Compute dump level for the JIT 48 | /// 49 | /// Dump level requested via CLR config for the JIT 50 | /// \returns Computed DumpLevel 51 | static ::DumpLevel queryDumpLevel(LLILCJitContext &JitContext); 52 | 53 | /// \brief Set optimization level for the JIT. 54 | /// 55 | /// Opt Level based on CLR provided flags and environment. 56 | /// \returns Computed OptLevel 57 | static ::OptLevel queryOptLevel(LLILCJitContext &JitContext); 58 | 59 | /// \brief Set UseConservativeGC based on environment variable. 60 | /// 61 | /// \returns true if COMPLUS_GCCONSERVATIVE is set in the environment. 62 | static bool queryUseConservativeGC(LLILCJitContext &JitContext); 63 | 64 | /// \brief Set DoInsertStatepoints 65 | /// 66 | /// \returns true if insert statepoints is indicated in the 67 | /// environment to model precise GC. (COMPLUS_INSERTSTATEPOINTS) 68 | static bool queryDoInsertStatepoints(LLILCJitContext &JitContext); 69 | 70 | /// \brief Set DoTailCallOpt based on environment variable. 71 | /// 72 | /// \returns true if COMPLUS_TAILCALLOPT is set in the environment. 73 | static bool queryDoTailCallOpt(LLILCJitContext &JitContext); 74 | 75 | /// \brief Set LogGcInfo based on environment variable. 76 | /// 77 | /// \returns true if COMPLUS_JitGCInfoLogging is set in the environment. 78 | static bool queryLogGcInfo(LLILCJitContext &JitContext); 79 | 80 | /// \brief Set ExecuteHandlers based on envirionment variable. 81 | /// 82 | /// \returns true if COMPlus_ExecuteHandlers is set in the environment. 83 | static bool queryExecuteHandlers(LLILCJitContext &JitContext); 84 | 85 | /// \brief Define set of methods to exclude from LLILC compilation 86 | /// 87 | /// \returns true if current method is in that set. 88 | static bool queryIsExcludeMethod(LLILCJitContext &JitContext); 89 | 90 | /// \brief Define set of methods on which to break. 91 | /// 92 | /// \returns true if current method is in that set. 93 | static bool queryIsBreakMethod(LLILCJitContext &JitContext); 94 | 95 | /// \brief Define set of methods for which to dump MSIL 96 | /// 97 | /// \returns true if current method is in that set. 98 | static bool queryIsMSILDumpMethod(LLILCJitContext &JitContext); 99 | 100 | /// \brief Define set of methods for which to dump LLVM IR. 101 | /// 102 | /// \returns true if current method is in that set. 103 | static bool queryIsLLVMDumpMethod(LLILCJitContext &JitContext); 104 | 105 | /// \brief Define set of methods for which to print code address range. 106 | /// 107 | /// \returns true if current method is in that set. 108 | static bool queryIsCodeRangeMethod(LLILCJitContext &JitContext); 109 | 110 | static bool queryMethodSet(LLILCJitContext &JitContext, MethodSet &TheSet, 111 | const char16_t *Name); 112 | 113 | /// \brief Check for non-null non-empty configuration variable. 114 | /// 115 | /// \param Name The name of the configuration variable 116 | /// \returns true if configuration variable is non-null and non-empty. 117 | static bool queryNonNullNonEmpty(LLILCJitContext &JitContext, 118 | const char16_t *Name); 119 | 120 | /// \brief Set SIMD intrinsics using. 121 | /// 122 | /// \returns true if SIMD_INTRINSIC is set in the environment set. 123 | static bool queryDoSIMDIntrinsic(LLILCJitContext &JitContext); 124 | 125 | public: 126 | bool IsAltJit; ///< True if running as the alternative JIT. 127 | bool IsExcludeMethod; ///< True if method is to be excluded. 128 | ///< Jit if IsAltJit && !IsExcludeMethod 129 | bool IsBreakMethod; ///< True if break requested when compiling this method. 130 | bool IsMSILDumpMethod; ///< True if dump of MSIL requested. 131 | bool IsLLVMDumpMethod; ///< True if dump of LLVM requested. 132 | bool IsCodeRangeMethod; ///< True if desired to dump entry address and size. 133 | 134 | private: 135 | static MethodSet AltJitMethodSet; ///< Singleton AltJit MethodSet. 136 | static MethodSet AltJitNgenMethodSet; ///< Singleton AltJitNgen MethodSet. 137 | static MethodSet ExcludeMethodSet; ///< Methods to exclude from jitting. 138 | static MethodSet BreakMethodSet; ///< Methods to break. 139 | static MethodSet MSILMethodSet; ///< Methods to dump MSIL. 140 | static MethodSet LLVMMethodSet; ///< Methods to dump LLVM IR. 141 | static MethodSet CodeRangeMethodSet; ///< Methods to dump code range 142 | }; 143 | 144 | #endif // JITOPTIONS_H 145 | -------------------------------------------------------------------------------- /include/Jit/utility.h: -------------------------------------------------------------------------------- 1 | //===----------------- include/Jit/utility.h -------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declarations of utility classes. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef UTILITY_H 17 | #define UTILITY_H 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "cor.h" 24 | #include "utility.h" 25 | 26 | #include "llvm/Support/Atomic.h" 27 | #include "llvm/ADT/STLExtras.h" 28 | #include "llvm/Config/llvm-config.h" 29 | 30 | // The MethodID.NumArgs field may hold either of 2 values: 31 | // Empty => the input string was all-blank, or empty. 32 | // AnyArgs => the pattern did not specify any constraint on the number of 33 | // arguments. Eg: "foo" as opposed to "foo()", "foo(3)", etc 34 | 35 | enum MethodIDState { Empty = -7, AnyArgs = -1 }; 36 | 37 | /// \brief MethodID struct represents a Method Signature. 38 | /// 39 | /// MethodIDs are held in a MethodSet and are used to decide which 40 | /// methods should be compiled when running as an "alt" JIT. 41 | 42 | class MethodID { 43 | public: 44 | /// Class name. 45 | std::unique_ptr ClassName; 46 | /// Method Name 47 | std::unique_ptr MethodName; 48 | /// Number of method arguments. MethodIDState::AnyArgs => not specified 49 | int NumArgs; 50 | 51 | /// Default constructor. 52 | MethodID() 53 | : ClassName(nullptr), MethodName(nullptr), 54 | NumArgs(MethodIDState::AnyArgs) {} 55 | 56 | /// Copy constructor. 57 | MethodID(const MethodID &Other) { 58 | if (Other.ClassName) { 59 | ClassName = llvm::make_unique(*Other.ClassName); 60 | } else { 61 | ClassName = nullptr; 62 | } 63 | if (Other.MethodName) { 64 | MethodName = llvm::make_unique(*Other.MethodName); 65 | } else { 66 | MethodName = nullptr; 67 | } 68 | this->NumArgs = Other.NumArgs; 69 | } 70 | 71 | /// Copy assignment operator. 72 | 73 | MethodID &operator=(const MethodID &Other) { 74 | if (this == &Other) 75 | return *this; 76 | if (Other.ClassName) { 77 | ClassName = llvm::make_unique(*Other.ClassName); 78 | } else { 79 | ClassName = nullptr; 80 | } 81 | if (Other.MethodName) { 82 | MethodName = llvm::make_unique(*Other.MethodName); 83 | } else { 84 | MethodName = nullptr; 85 | } 86 | NumArgs = Other.NumArgs; 87 | return *this; 88 | } 89 | 90 | /// Parse a string into a MethodID. 91 | /// Parse string S, starting at index I, into a MethodID. The string can be 92 | /// any of the following patterns: 93 | /// * => any method. 94 | /// M => method M, with any number of arguments. 95 | /// C:M => method M in class C. 96 | /// 97 | /// C can be a simple class name, or a namespace.classname. For example, 98 | /// "Sort" or "System.Array:Sort". (The dots in a namespace are ignored). 99 | /// 100 | /// M can be followed by the pattern (number) to specify its number of 101 | /// arguments. For example, .ctor(0) or Adjust(2) 102 | /// 103 | /// If the parse encounters an invalid pattern, we return nullptr. 104 | /// 105 | /// In actual use, S may consist of several such patterns, separated by one 106 | /// or more spaces. Therefore, leading spaces are skipped, but subsequent 107 | /// space is significant. 108 | /// 109 | // Eg: " foo Ns.MyClass:bar System.Array.Sort " holds 3 patterns. 110 | 111 | static std::unique_ptr parse(const std::string &S, size_t &I); 112 | 113 | // Scan the string S, starting at index I, for the next lexical token. 114 | // A token is terminated by any of {space, end-of-string, :, (, )}. 115 | // 116 | // Return the token, or empty string if none found. Update I to index 117 | // the character just past the end of the token. 118 | 119 | std::string scan(const std::string &S, size_t &I); 120 | 121 | // Parse string S, starting at index I, to determine how many arguments 122 | // the function specifies. On entry, S[I] holds the character '('. 123 | 124 | int parseArgs(const std::string &S, size_t &I); 125 | }; 126 | 127 | /// \brief MethodSet comprises a set of MethodID objects 128 | /// 129 | /// MethodSet specifies the methods to compile with the "alt" JIT. 130 | 131 | class MethodSet { 132 | public: 133 | /// Test if the MethodSet is empty. 134 | /// \returns true if MethodSet is empty. 135 | 136 | bool isEmpty() { 137 | assert(this->isInitialized()); 138 | return (this->MethodIDList->size() == 0); 139 | } 140 | 141 | /// Test whether specified method is matched in current MethodSet. 142 | /// \param MethodName Name of method 143 | /// \param ClassName Encapsulating namespace+class of the method. 144 | /// \param sig Pointer to method signature. 145 | /// \return true if Method is contained in Set. 146 | 147 | bool contains(const char *MethodName, const char *ClassName, 148 | PCCOR_SIGNATURE Sig); 149 | 150 | /// Initialize a new MethodSet - once only. 151 | void init(std::unique_ptr ConfigValue); 152 | 153 | /// Check whether current MethodSet has been initialized. 154 | bool isInitialized() { return MethodIDList != nullptr; } 155 | 156 | /// \brief Parse the string S into one or more MethodIDs, and insert 157 | /// them into current MethodSet. 158 | void insert(std::unique_ptr S); 159 | 160 | private: 161 | /// Internal initialized flag. This should only be accessed via interlocked 162 | /// exchange operations, since several methods may be JIT'ing concurrently. 163 | uint32_t Initialized = 0; 164 | 165 | /// MethodSigList implementing the set. 166 | std::list *MethodIDList = nullptr; 167 | }; 168 | 169 | /// \brief Class implementing miscellaneous conversion functions. 170 | class Convert { 171 | public: 172 | /// Convert a UTF-16 string to a UTF-8 string. 173 | static std::unique_ptr utf16ToUtf8(const char16_t *WideStr); 174 | }; 175 | 176 | #endif // UTILITY_H 177 | -------------------------------------------------------------------------------- /include/Reader/newvstate.h: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/newvstate.h -------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Data structures for holding verification state. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef MSIL_READER_NEW_VSTATE_H 17 | #define MSIL_READER_NEW_VSTATE_H 18 | 19 | #include "vtypeinfo.h" 20 | #include "corerror.h" 21 | #include "gverify.h" 22 | 23 | class LocalDescr { 24 | public: 25 | CorInfoType Type; 26 | CORINFO_CLASS_HANDLE Class; 27 | }; 28 | 29 | class VerificationState { 30 | public: 31 | bool BlockIsBad; 32 | bool *ArgsInitialized; 33 | 34 | // This field caches the token of the delegate method 35 | // in a potential delegate creation sequence. 36 | mdToken DelegateMethodRef; 37 | 38 | uint32_t ConstrainedPrefix : 1; 39 | uint32_t ReadonlyPrefix : 1; 40 | uint32_t TailPrefix : 1; 41 | uint32_t VolatilePrefix : 1; 42 | uint32_t UnalignedPrefix : 1; 43 | uint32_t TailInBlock : 1; 44 | // say we initialize the 'this' pointer in a try. 45 | // Real successors of the block can assume 'this' is inited. 46 | // nominal successors cannot. However if we know 'this' was inited in 47 | uint32_t ThisInitializedThisBlock : 1; 48 | uint32_t StrongThisInitialized : 1; 49 | uint32_t ContainsCtorCall : 1; // block is in a ctor and calls a parent or 50 | // same class ctor 51 | const uint8_t *DelegateCreateStart; 52 | 53 | InitState ThisInitialized; // 'this' has been initialized on some paths 54 | private: 55 | VerType *Vstack; 56 | uint32_t Vsp; 57 | uint32_t MaxStack; 58 | 59 | VerificationState() {} 60 | 61 | public: 62 | ReaderBase *Base; 63 | 64 | inline void setStack(VerType *StackMem); 65 | 66 | inline void init(uint32_t MaxStackSize, uint32_t NumLocals, bool InitLocals, 67 | InitState InitState); 68 | 69 | inline void print(); 70 | 71 | inline void push(VerType Typ); 72 | 73 | inline VerType pop(); 74 | 75 | inline VerType impStackTop(uint32_t N = 0); 76 | 77 | // pop an objref which might be an uninitialized 'this' ptr 78 | // See Partion 3 1.8.1.4 79 | // No operations can be performed on an uninitialized 'this' 80 | // except for storing into and loading from the object's fields. 81 | inline VerType popPossiblyUninit(); 82 | 83 | inline uint32_t stackLevel() { return Vsp; } 84 | 85 | bool isThisPublishable() { 86 | if (ThisInitialized == ThisInited || ThisInitialized == ThisEHReached) 87 | return true; 88 | else 89 | return false; 90 | } 91 | 92 | bool isThisInitialized() { return (ThisInitialized == ThisInited); } 93 | 94 | void setThisInitialized() { 95 | // if its EHREACHED keep that 96 | if (ThisInitialized != ThisEHReached) 97 | ThisInitialized = ThisInited; 98 | } 99 | }; 100 | 101 | void VerificationState::setStack(VerType *StackMem) { Vstack = StackMem; } 102 | 103 | void VerificationState::init(uint32_t MaxStackSize, uint32_t NumLocals, 104 | bool InitLocals, InitState InitState) { 105 | Vsp = 0; 106 | MaxStack = MaxStackSize; 107 | DelegateMethodRef = mdTokenNil; 108 | 109 | BlockIsBad = false; 110 | ConstrainedPrefix = false; 111 | ReadonlyPrefix = false; 112 | TailPrefix = false; 113 | VolatilePrefix = false; 114 | UnalignedPrefix = false; 115 | TailInBlock = false; 116 | DelegateCreateStart = nullptr; 117 | ThisInitializedThisBlock = false; 118 | 119 | ThisInitialized = InitState; 120 | StrongThisInitialized = false; 121 | 122 | for (uint32_t I = 0; I < NumLocals; I++) { 123 | ArgsInitialized[I] = InitLocals; 124 | } 125 | } 126 | 127 | VerType VerificationState::pop() { 128 | VerType Ret = popPossiblyUninit(); 129 | Base->verifyAndReportFound((!Ret.isObjRef()) || 130 | (!Ret.isUninitialisedObjRef()), 131 | Ret, MVER_E_STACK_UNINIT); 132 | return Ret; 133 | } 134 | 135 | // See Partion 3 1.8.1.4 136 | // No operations can be performed on an uninitialized 'this' 137 | // except for storing into and loading from the object's fields. 138 | VerType VerificationState::popPossiblyUninit() { 139 | Base->gverifyOrReturn(Vsp > 0, MVER_E_STACK_UNDERFLOW); 140 | 141 | Vsp--; 142 | VerType Result = Vstack[Vsp]; 143 | 144 | // blank out the thing we just popped 145 | #ifndef NDEBUG 146 | memset(Vstack + Vsp, 0xcd, sizeof(VerType)); 147 | #endif 148 | 149 | return Result; 150 | } 151 | 152 | void VerificationState::push(VerType Typ) { 153 | Base->gverifyOrReturn(Vsp < MaxStack, MVER_E_STACK_OVERFLOW); 154 | Vstack[Vsp] = Typ; 155 | Vsp++; 156 | } 157 | 158 | VerType VerificationState::impStackTop(uint32_t N) { 159 | Base->gverifyOrReturn(Vsp > N, MVER_E_STACK_UNDERFLOW); 160 | 161 | return Vstack[Vsp - N - 1]; 162 | } 163 | 164 | // ========================================================================= 165 | // ================ Exceptions 166 | // ========================================================================= 167 | 168 | class CallAuthorizationException : public ReaderException {}; 169 | 170 | class VerificationException : public ReaderException { 171 | public: 172 | uint32_t DwFlags; // VER_ERR_XXX 173 | 174 | union { 175 | ReaderBaseNS::OPCODE Opcode; 176 | uint32_t Padding1; // to match with idl generated struct size 177 | }; 178 | 179 | union { 180 | uint32_t DwOffset; // #of bytes from start of method 181 | long Offset; // for backward compat with Metadata validator 182 | }; 183 | 184 | union { 185 | mdToken Token; // for backward compat with metadata validator 186 | uint8_t CallConv; 187 | CorElementType Elem; 188 | uint32_t StackSlot; // positon in the Stack 189 | uint32_t Padding2; // to match with idl generated struct size 190 | }; 191 | 192 | union { 193 | uint32_t Exception1; // Exception Record # 194 | uint32_t VarNumber; // Variable # 195 | uint32_t ArgNumber; // Argument # 196 | uint32_t Operand; // Operand for the opcode 197 | }; 198 | 199 | union { 200 | uint32_t Exception2; // Exception Record # 201 | }; 202 | }; 203 | 204 | #endif // MSIL_READER_NEW_VSTATE_H 205 | -------------------------------------------------------------------------------- /Documentation/llilc-gc-transition.md: -------------------------------------------------------------------------------- 1 | # GC Transition Support in LLILC 2 | 3 | The CoreCLR runtime supports calls from managed (i.e. GC-aware) code to 4 | unmanaged (i.e. GC-unaware) code. In the runtime's parlance, such calls are 5 | termed "P/Invokes" (short for Platform Invoke); in LLILC/LLVM they are referred 6 | to as "unmanaged calls" or "GC transitions". Because the target of such a call 7 | is not aware of the CoreCLR GC, such calls require runtime-specific setup and 8 | teardown code. The nature of this transition code requires code in both LLILC 9 | and LLVM. A brief discussion of the specifics of GC transitions in CoreCLR and 10 | the support for these transitions in LLILC and LLVM follows. 11 | 12 | ## GC transitions in CoreCLR 13 | 14 | In order for the CoreCLR garbage collector to perform garbage collection it must 15 | be able to 16 | 1. logically pause all threads that are running managed code, and 17 | 2. scan each thread's stack for GC references. 18 | 19 | ### Thread suspension and GC modes 20 | 21 | To meet the first requirement above without physically suspending arbitrary 22 | threads (and thus aggravating the chance of deadlocks in the runtime), each 23 | thread that the runtime is tracking is assigned one of two modes: cooperative 24 | mode and preemptive mode. 25 | 26 | #### Cooperative mode 27 | 28 | Threads in cooperative mode are considered to be running managed code. These 29 | threads are therefore potentially modifying GC references, and must cooperate 30 | with the runtime in order to reach a GC safepoint before a collection may 31 | occur. All managed code (and almost all JIT compiled code) will run in 32 | cooperative mode. 33 | 34 | #### Preemptive mode 35 | 36 | Threads in preemptive mode are considered to be running unmanaged code. Such a 37 | thread obeys three invariants: 38 | 1. It must not currently be manipulating GC references, and all live GC 39 | references must be reachable from managed frames. 40 | 2. It must have registered the last managed frame on its stack with the runtime 41 | so that the GC may avoid scanning unmanaged frames. 42 | 3. It must not reenter managed code if a GC is in progress. 43 | 44 | Threads that are running in preemptive mode need not be driven to a GC safe 45 | point before a collection, as invariants (1) and (3) guarantee that the 46 | managed code on such threads is already logically paused. Invariants (1) and 47 | (2) serve to satisfy the requirement that the GC must be able to scan the 48 | thread's stack for GC references. 49 | 50 | ### Transitioning from managed and unmanaged code 51 | 52 | Transitioning from managed to unmanaged code boils down to switching the active 53 | thread from cooperative to preemptive mode while ensuring that the invariants 54 | associated with preemptive mode are obeyed. Abstractly, this looks something 55 | like the following, where `>> {Managed,Unmanaged} code` indicates the type of 56 | code currently running on the thread: 57 | 58 | ``` 59 | >> Managed code 60 | - Ensure all GC references in registers that might be updated by unmanaged code 61 | have been spilled to locations that will not be updated by unmanaged code. 62 | This satisfies the first preemptive mode invariant. 63 | - Register this frame as the last managed frame on this thread. This satisfies 64 | the second preemptive mode invariant. 65 | - Flip this thread's GC mode to preemptive mode. 66 | 67 | >> Unmanaged code 68 | - Run unmanaged code. Usually this is just a call to an unmanaged function. 69 | - Once the unmanaged code has run, flip this thread's GC mode to cooperative 70 | mode. 71 | 72 | >> Managed code 73 | - Check to see if a collection is in progress and if so, block this thread until 74 | it completes. This satisfies the third preemptive mode invariant. 75 | ``` 76 | 77 | ## Supporting GC transitions in LLILC and LLVM 78 | 79 | Ideally, LLILC would be able to emit all of the necessary transition code in 80 | LLVM IR. Unfortunately, it is not possible to do so while preserving the 81 | preemptive mode invariants: 82 | - The frame registration, mode transitions, and collection rendezvous must be 83 | positioned immediately before and after the unmanaged code. LLVM IR has no 84 | way of expressing this restriction. 85 | - Registering the managed frame requires knowing the address of the first 86 | managed instruction following the unmanaged code. Again, LLVM IR has no 87 | way of expressing this. 88 | 89 | As a result, the gc.statepoint intrinsic has been extended to support marking 90 | certain statepoints as transitions between code with differing GC models. 91 | These calls are then lowered differently by the backend, which is given an 92 | opportunity to lower the GC transition prologue and epilogue in a 93 | GC-model-specific fashion. In the case of CoreCLR, the backend is responsible 94 | for emitting the frame registration, mode transitions, and the collection 95 | rendezvous, while the frontend is responsible for allocating (and partially 96 | initializing) the frame registration data structure and marking calls to 97 | unamanged code as GC transitions. Example IR is given below. 98 | 99 | ``` 100 | !0 = !{!"rsp"} 101 | !1 = !{!"rbp"} 102 | 103 | void @DomainNeutralILStubClass.IL_STUB_PInvoke() gc "coreclr" { 104 | %InlinedCallFrame = alloca [64 x i8] ; Frame registration data structure for CoreCLR 105 | %ThreadPointer = alloca [0 x i8]* ; Pointer to current CoreCLR thread 106 | 107 | ; Get the current thread of execution 108 | %0 = getelementptr inbounds [64 x i8], [64 x i8]* %InlinedCallFrame, i32 0, i32 8 109 | %1 = call [0 x i8]* inttoptr (i64 140505971852800 to [0 x i8]* (i8*, i64)*)(i8* %0, i64 %param2) 110 | store [0 x i8]* %1, [0 x i8]** %ThreadPointer 111 | 112 | ; Record the stack pointer in the frame registration data 113 | %2 = getelementptr inbounds [64 x i8], [64 x i8]* %InlinedCallFrame, i32 0, i32 40 114 | %3 = bitcast i8* %2 to i64* 115 | %4 = call i64 @llvm.read_register.i64(metadata !0) 116 | store i64 %4, i64* %3 117 | 118 | ; Record the frame pointer in the frame registration data 119 | %5 = getelementptr inbounds [64 x i8], [64 x i8]* %InlinedCallFrame, i32 0, i32 56 120 | %6 = bitcast i8* %5 to i64* 121 | %7 = call i64 @llvm.read_register.i64(metadata !1) 122 | store i64 %7, i64* %6 123 | 124 | ; Push the current frame onto the frame registration stack 125 | %10 = getelementptr inbounds [64 x i8], [64 x i8]* %InlinedCallFrame, i32 0, i32 8 126 | %11 = load [0 x i8]*, [0 x i8]** %ThreadPointer 127 | %12 = getelementptr inbounds [0 x i8], [0 x i8]* %11, i32 0, i32 16 128 | %13 = bitcast i8* %12 to i8** 129 | store i8* %10, i8** %13 130 | 131 | ; Compute addresses for GC transition code 132 | %14 = getelementptr inbounds [64 x i8], [64 x i8]* %InlinedCallFrame, i32 0, i32 48 133 | %15 = bitcast i8* %14 to i8** 134 | %16 = getelementptr inbounds [0 x i8], [0 x i8]* %11, i32 0, i32 12 135 | %17 = load i64, i64* inttoptr (i64 140505987192288 to i64*) 136 | 137 | ; Perform the call. 138 | ; 139 | ; The fifth argument (i32 1) marks this statepoint as a GC transition. The 140 | ; backend will generate code to spill callee-saves, perform the GC mode 141 | ; switch, and check for a collection before reentering managed 142 | ; code. The four arguments immediately preceding the final argument provide 143 | ; data that is needed by the transition code. 144 | call void (i64, i32, void()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* null, i32 0, i32 1, i32 4, i8** %15, i8* %16, i32* inttoptr (i64 140505987311808 to i32*), i64 %17, i32 0) 145 | 146 | ; Pop the current frame from the registration stack 147 | store i8* null, i8** %15 148 | %18 = getelementptr inbounds [64 x i8], [64 x i8]* %InlinedCallFrame, i32 0, i32 16 149 | %19 = bitcast i8* %18 to i8** 150 | %20 = load i8*, i8** %19 151 | store i8* %20, i8** %13 152 | 153 | ret void 154 | } 155 | ``` 156 | -------------------------------------------------------------------------------- /include/Jit/EEMemoryManager.h: -------------------------------------------------------------------------------- 1 | //===--------------- include/Jit/EEMemoryManager.h --------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declaration of the memory manager interface to the EE. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef EE_MEMORYMANAGER_H 17 | #define EE_MEMORYMANAGER_H 18 | 19 | #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 20 | 21 | struct LLILCJitContext; 22 | 23 | namespace llvm { 24 | 25 | /// \brief Memory manager for LLILC 26 | /// 27 | /// This class extends \p RTDyldMemoryManager to obtain memory from the 28 | /// CoreCLR's EE for the persistent jit outputs (code, data, and unwind 29 | /// information). Each jit request instantiates its own memory manager. 30 | class EEMemoryManager : public RTDyldMemoryManager { 31 | 32 | public: 33 | /// Construct a new \p EEMemoryManager 34 | /// \param C Jit context for the method being jitted. 35 | EEMemoryManager(LLILCJitContext *C) 36 | : Context(C), HotCodeBlock(nullptr), ColdCodeBlock(nullptr), 37 | ReadOnlyDataBlock(nullptr), StackMapBlock(nullptr) {} 38 | 39 | /// Destroy an \p EEMemoryManager 40 | ~EEMemoryManager() override; 41 | 42 | /// \brief Allocates a memory block of (at least) the given size suitable 43 | /// for executable code. 44 | /// 45 | /// The value of \p Alignment must be a power of two. If \p Alignment is 46 | /// zero a default alignment of 16 will be used. 47 | /// 48 | /// \param Size Size of allocation request in bytes 49 | /// \param Alignment Alignment demand for the allocation 50 | /// \param SectionID SectionID for this particular section of code 51 | /// \param SectionName Name of the section 52 | /// \returns Pointer to the newly allocated memory region 53 | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 54 | unsigned SectionID, 55 | StringRef SectionName) override; 56 | 57 | // \brief Returns code section address. 58 | // \returns Code section address. 59 | uint8_t *getCodeSection(); 60 | 61 | /// \brief Allocates a memory block of (at least) the given size suitable 62 | /// for executable code. 63 | /// 64 | /// The value of \p Alignment must be a power of two. If \p Alignment is 65 | /// zero a default alignment of 16 will be used. 66 | /// 67 | /// \param Size Size of allocation request in bytes 68 | /// \param Alignment Alignment demand for the allocation 69 | /// \param SectionID SectionID for this particular section of code 70 | /// \param SectionName Name of the section 71 | /// \param IsReadOnly True if this is intended for read-only data 72 | /// \returns Pointer to the newly allocated memory region 73 | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 74 | unsigned SectionID, StringRef SectionName, 75 | bool IsReadOnly) override; 76 | 77 | /// \brief Update section-specific memory permissions and other attributes. 78 | /// 79 | /// This method is called when object loading is complete and section page 80 | /// permissions can be applied. It is up to the memory manager 81 | /// implementation to decide whether or not to act on this method. 82 | /// The memory manager will typically allocate all sections as read-write 83 | /// and then apply specific permissions when this method is called. Code 84 | /// sections cannot be executed until this function has been called. 85 | /// In addition, any cache coherency operations needed to reliably use the 86 | /// memory are also performed. 87 | /// 88 | /// \param ErrMsg [out] Additional information about finalization errors. 89 | /// \returns false if an error occurred, true otherwise. 90 | bool finalizeMemory(std::string *ErrMsg = nullptr) override; 91 | 92 | /// Inform the memory manager about the total amount of memory required to 93 | /// allocate all sections to be loaded. 94 | /// 95 | /// \param CodeSize - the total size of all code sections. 96 | /// \param CodeAlign - alignment required for the code sections. 97 | /// \param RODataSize - the total size of all read-only data sections. 98 | /// \param RODataAlign - alignment required for read-only data sections. 99 | /// \param RWDataSize - the total size of all read-write data sections. 100 | /// \param RWDataAlign - alignment required for read-write data sections. 101 | /// 102 | /// Note that by default the callback is disabled. To enable it 103 | /// redefine the method needsToReserveAllocationSpace to return true. 104 | void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, 105 | uintptr_t RODataSize, uint32_t RODataAlign, 106 | uintptr_t RWDataSize, 107 | uint32_t RWDataAlign) override; 108 | 109 | /// Inform the memory manager about the amount of memory required to hold 110 | /// unwind codes for the function and funclets being loaded. 111 | /// 112 | /// \param Obj - the Object being loaded 113 | void reserveUnwindSpace(const object::ObjectFile &Obj); 114 | 115 | /// \brief Override to enable the reserveAllocationSpace callback. 116 | /// 117 | /// The CoreCLR's EE requires an up-front resevation of the total allocation 118 | /// demands from the jit. This callback enables that to happen. 119 | /// \returns true to enable the callback. 120 | bool needsToReserveAllocationSpace() override { return true; } 121 | 122 | /// \brief Callback to handle processing unwind data. 123 | /// 124 | /// This is currently invoked once per .xdata section. The EE uses this info 125 | /// to build and register the appropriate .pdata with the OS. 126 | /// 127 | /// \param Addr The address of the data in the pre-loaded image. 128 | /// \param LoadAddr The address the data will have once loaded. 129 | /// \param Size Size of the unwind data in bytes. 130 | /// 131 | /// \note Because we're not relocating data during loading, \p Addr and 132 | /// \p LoadAddr are currently identical. 133 | void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; 134 | 135 | /// \brief Callback to handle unregistering unwind data. 136 | /// 137 | /// This is currently a no-op. 138 | /// 139 | /// \param Addr The address of the data in the image. 140 | /// \param LoadAddr The address the data has after loading. 141 | /// \param Size Size of the unwind data in bytes. 142 | void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, 143 | size_t Size) override; 144 | 145 | /// \brief Get the LLVM Stackmap section if allocated. 146 | /// 147 | /// Returns a pointer to the .llvm_stackmaps section 148 | /// if it is already loaded into memory. 149 | 150 | uint8_t *getStackMapSection() { return StackMapBlock; } 151 | 152 | /// \brief Get the HotCode section if allocated. 153 | /// 154 | /// Returns a pointer to the HotCode section 155 | /// if it is already loaded into memory. 156 | 157 | uint8_t *getHotCodeBlock() { return HotCodeBlock; } 158 | 159 | private: 160 | LLILCJitContext *Context; ///< LLVM context for types, etc. 161 | uint8_t *HotCodeBlock; ///< Memory to hold the hot method code. 162 | uint8_t *ColdCodeBlock; ///< Memory to hold the cold method code. 163 | uint8_t *ReadOnlyDataBlock; ///< Memory to hold the readonly data. 164 | uint8_t *StackMapBlock; ///< Memory to hold the readonly StackMap 165 | uint8_t *ReadOnlyDataUnallocated; ///< Address of unallocated part of RO data. 166 | }; 167 | } // namespace llvm 168 | 169 | #endif // EEMEMORYMANAGER_H 170 | -------------------------------------------------------------------------------- /include/Reader/abisignature.h: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/abisignature.h ----------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declares ABI signature abstractions used when lowering functions to 13 | /// LLVM IR. 14 | /// 15 | //===----------------------------------------------------------------------===// 16 | 17 | #ifndef _READER_ABISIGNATURE_H_ 18 | #define _READER_ABISIGNATURE_H_ 19 | 20 | /// \brief Encapsulates ABI-specific argument and result passing information for 21 | /// a particular function signature. 22 | class ABISignature { 23 | protected: 24 | llvm::Type *FuncResultType; ///< The return type of this function signature. 25 | ABIArgInfo Result; ///< Describes how the result of the function is passed. 26 | std::vector Args; ///< Describes how each argument to the function 27 | ///< is passed. 28 | 29 | ABISignature() {} 30 | 31 | /// \brief Fills in argument and result passing information for the given 32 | /// function signature. 33 | /// 34 | /// \param Signature The function signature. 35 | /// \param Reader The \p GenIR instance that will be used to emit IR. 36 | /// \param TheABIInfo The target \p ABIInfo. 37 | ABISignature(const ReaderCallSignature &Signature, GenIR &Reader, 38 | const ABIInfo &TheABIInfo); 39 | 40 | /// \brief Returns the number of arguments to the ABI signature. 41 | /// 42 | /// \returns The number of arguments to the ABI signature. 43 | uint32_t getNumABIArgs() const; 44 | 45 | public: 46 | /// \brief Expand a value according to a specific list of expansions. 47 | /// 48 | /// \param Reader The \p GenIR instance that will be used to emit IR. 49 | /// \param Expansions The list of expansions to be applied. 50 | /// \param Source The value to expand. 51 | /// \param Values [in] A slice that will hold the values that result from 52 | /// the expansion. 53 | /// \param Values [in] A slice that will hold the types of the values that 54 | /// result from the expansion. 55 | /// \param IsResult True if the value being expanded is the result value 56 | /// for a function. 57 | static void expand(GenIR &Reader, 58 | llvm::ArrayRef Expansions, 59 | llvm::Value *Source, 60 | llvm::MutableArrayRef Values, 61 | llvm::MutableArrayRef Types, bool IsResult); 62 | 63 | /// \brief Store a single value from an expanded argument into its 64 | /// destination. 65 | /// 66 | /// \param Reader The \p GenIR instance that will be used to emit IR. 67 | /// \param Exp The expansion information for the given value. 68 | /// \param Val The value to be collapsed. 69 | /// \param Base The base address of the target value as an i8*. 70 | static void collapse(GenIR &Reader, const ABIArgInfo::Expansion &Exp, 71 | llvm::Value *Val, llvm::Value *Base); 72 | 73 | /// \brief Coerces a value to a particular target type, casting or 74 | /// reinterpreting as necessary. 75 | /// 76 | /// \param Reader The \p GenIR instance that will be used to emit IR. 77 | /// \param TheType The target type of the coercion. 78 | /// \param TheValue The value to coerce. 79 | /// 80 | /// \returns A \p Value that represents the result of the coercion. 81 | static llvm::Value *coerce(GenIR &Reader, llvm::Type *TheType, 82 | llvm::Value *TheValue); 83 | }; 84 | 85 | /// \brief Encapsulates ABI-specific argument and result passing information for 86 | /// a particular call target signature and provides facilities to emit 87 | /// a call to a target with that signature. 88 | class ABICallSignature : public ABISignature { 89 | private: 90 | const ReaderCallSignature &Signature; ///< The target function signature. 91 | 92 | /// \brief Emits a call to an unmanaged function. 93 | /// 94 | /// This method is called by \p emitCall when emitting a call that targets an 95 | /// unmanaged function. It is responsible for emitting the IR required to 96 | /// perform any necessary bookkeeping for the GC as well as the call itself. 97 | /// The arguments must already have been arranged as per the calling 98 | /// convention and target ABI. 99 | /// 100 | /// \param Reader The \p GenIR instance that will be used to emit IR. 101 | /// \param Target The call target. 102 | /// \oaram MayThrow True iff the callee may raise an exception. 103 | /// \param Args The arguments to the call, arranged as per the 104 | /// calling convention and target ABI. 105 | /// 106 | /// \returns The call site corresponding to the unmanaged call. 107 | llvm::CallSite emitUnmanagedCall(GenIR &Reader, llvm::Value *Target, 108 | bool MayThrow, 109 | llvm::ArrayRef Args) const; 110 | 111 | public: 112 | ABICallSignature(const ReaderCallSignature &Signature, GenIR &Reader, 113 | const ABIInfo &TheABIInfo); 114 | 115 | /// \brief Emits a call to a function using the argument and result passing 116 | /// information for the signature provided when this value was created. 117 | /// 118 | /// \param Reader The \p GenIR instance that will be used to emit 119 | /// IR. 120 | /// \param Target The call target. 121 | /// \param MayThrow True iff the callee may raise an exception 122 | /// \param Args The arguments to the call. 123 | /// \param IndirectionCell The indirection cell argument for the call, if 124 | /// any. 125 | /// \param IsJmp True iff this is a call for a jmp instruction. 126 | /// \param CallNode [out] The call instruction. 127 | /// 128 | /// \returns The result of the call to the target. 129 | llvm::Value *emitCall(GenIR &Reader, llvm::Value *Target, bool MayThrow, 130 | llvm::ArrayRef Args, 131 | llvm::Value *IndirectionCell, bool IsJmp, 132 | llvm::Value **CallNode) const; 133 | 134 | /// \brief Check for an indirect result or indirect argument. 135 | /// 136 | /// Determines if expansion of this call might result in references to temps 137 | /// that live on the caller's stack. 138 | /// 139 | /// \returns True if there is an indirect result or indirect argument. 140 | bool hasIndirectResultOrArg() const; 141 | }; 142 | 143 | /// \brief Encapsulates ABI-specific argument and result passing information for 144 | /// a particular method signature and provides facilites to create an 145 | // appropriately-typed function symbol. 146 | class ABIMethodSignature : public ABISignature { 147 | private: 148 | const ReaderMethodSignature *Signature; ///< The target method signature. 149 | 150 | public: 151 | ABIMethodSignature() {} 152 | ABIMethodSignature(const ReaderMethodSignature &Signature, GenIR &Reader, 153 | const ABIInfo &TheABIInfo); 154 | 155 | /// \brief Creates a function symbol for the method signature provided when 156 | /// this vaule was created. 157 | /// 158 | /// \param Reader The \p GenIR instance that will be used to emit IR. 159 | /// \param M The module in which this function is to be created. 160 | /// 161 | /// \returns The newly-created function symbol. 162 | llvm::Function *createFunction(GenIR &Reader, llvm::Module &M); 163 | 164 | /// \brief Gets result passing information for this signature. 165 | /// 166 | /// \returns Result passing information for this signature. 167 | const ABIArgInfo &getResultInfo() const; 168 | 169 | /// \brief Gets argument passing information for the runtime argument at the 170 | /// given index into its parent \p ReaderMethodSignature. 171 | /// 172 | /// \param I The index of the runtime argument into its parent 173 | /// \p ReaderMethodSignature. 174 | /// 175 | /// \returns Argument passing information for the argument. 176 | const ABIArgInfo &getArgumentInfo(uint32_t I) const; 177 | }; 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /test/llilc_run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # title : llilcrun.py 4 | # description : Run a managed application using LLILC jit. 5 | # 6 | # This script has been tested running on both Python 2.7 and Python 3.4. 7 | # 8 | # usage: llilc_run.py [-h] [-d {summary,verbose}] [-x [EXTRA [EXTRA ...]]] [-n] 9 | # [-p] [-v] [-r [CORERUN_AND_ARGS [CORERUN_AND_ARGS ...]]] 10 | # [-j JIT_PATH] [-w [WINDBG_AND_ARGS [WINDBG_AND_ARGS ...]]] 11 | # -a APP_PATH -c CORECLR_RUNTIME_PATH 12 | # 13 | # Run a managed application with LLILC as the JIT. If the application has any 14 | # arguments, they must be appended to the end of the command line, preceded by 15 | # "--". 16 | # 17 | # optional arguments: 18 | # -h, --help show this help message and exit 19 | # -d {summary,verbose}, --dump-level {summary,verbose} 20 | # the dump level: summary, or verbose 21 | # -x [EXTRA [EXTRA ...]], --extra [EXTRA [EXTRA ...]] 22 | # list of extra COMPlus settings. Each item is 23 | # Name=Value, where Name does not have the 24 | # COMPlus_ prefix. 25 | # -n, --ngen use ngened mscorlib 26 | # -p, --precise-gc test with precise gc 27 | # -v, --verbose echo commands 28 | # -e, --eh enable exception handlers to run (as opposed to failfast) 29 | # -r [CORERUN_AND_ARGS [CORERUN_AND_ARGS ...]], --corerun-and-args [CORERUN_AND_ARGS [CORERUN_AND_ARGS ...]] 30 | # If explicit CoreRun is needed (app is not 31 | # CoreConsole), the CoreRun command and args to pass to 32 | # CoreRun, e.g. /v for verbose. 33 | # -j JIT_PATH, --jit-path JIT_PATH 34 | # full path to jit .dll. If given it is copied to 35 | # coreclr directory. If not given we check that it 36 | # exists in the coreclr directory. 37 | # -w [WINDBG_AND_ARGS [WINDBG_AND_ARGS ...]], --windbg-and-args [WINDBG_AND_ARGS [WINDBG_AND_ARGS ...]] 38 | # Full path to windbg executable followed by any 39 | # arguments you want to pass to windbg. 40 | # 41 | # required arguments: 42 | # -a APP_PATH, --app-path APP_PATH 43 | # full path to application to run with llilc. 44 | # -c CORECLR_RUNTIME_PATH, --coreclr-runtime-path CORECLR_RUNTIME_PATH 45 | # full path to CoreCLR run-time binary directory 46 | 47 | 48 | import argparse 49 | import os 50 | import shutil 51 | import subprocess 52 | import sys 53 | 54 | llilcverbose = False 55 | 56 | def QuoteArg(arg): 57 | '''Strip off any enclosing single quotes and enclose in double quotes''' 58 | arg = '"' + arg.strip("'").strip('"') + '"' 59 | return arg 60 | 61 | def UnquoteArg(arg): 62 | ''' Remove single and double quotes from front and back of arg''' 63 | return arg.strip("'").strip('"') 64 | 65 | def GetPrintString(*args): 66 | return ' '.join(map(str, args)) 67 | 68 | def Print(*args): 69 | print (GetPrintString(*args)) 70 | 71 | def PrintError(*args): 72 | ''' Mimic the python 3.x print statement (should the community ever go to 3.4, we would not need to change much.)''' 73 | sys.stderr.write(GetPrintString(*args) + '\n') 74 | 75 | def log(*objs): 76 | '''Print log message to both stdout and stderr''' 77 | Print("llilc_run\stdout: ", *objs) 78 | PrintError("llilc_run\stderr: ", *objs) 79 | 80 | def RunCommand(command): 81 | ''' Run a command and return its exit code, optionally echoing it.''' 82 | global llilcverbose 83 | if llilcverbose: 84 | log ('About to execute: ', command) 85 | error_level = subprocess.call(command, shell=True) 86 | return error_level 87 | 88 | def main(argv): 89 | ''' 90 | main method of script. arguments are script path and remaining arguments. 91 | ''' 92 | global llilcverbose 93 | parser = argparse.ArgumentParser(description='''Run a managed application with LLILC as the JIT. 94 | If the application has any arguments, they must be 95 | appended to the end of the command line, preceded by "--". 96 | ''' 97 | ) 98 | parser.add_argument('-d', '--dump-level', type=str, choices={'summary', 'verbose'}, 99 | help='the dump level: summary, or verbose') 100 | parser.add_argument('-x', '--extra', type=str, default=[], nargs='*', 101 | help='''list of extra COMPlus settings. Each item is Name=Value, where 102 | Name does not have the COMPlus_ prefix. 103 | ''') 104 | parser.add_argument('-n', '--ngen', help='use ngened mscorlib', default=False, action="store_true") 105 | parser.add_argument('-p', '--precise-gc', help='test with precise gc', default=False, action="store_true") 106 | parser.add_argument('-v', '--verbose', help='echo commands', default=False, action="store_true") 107 | parser.add_argument('-e', '--eh', help='enable exception handlers to run (as opposed to failfast)', default=False, action="store_true") 108 | parser.add_argument('-r', '--corerun-and-args', type=str, nargs='*', default=[], 109 | help='''If explicit CoreRun is needed (app is not CoreConsole), 110 | the CoreRun command and args to pass to CoreRun, e.g. /v for verbose. 111 | ''') 112 | parser.add_argument('-j', '--jit-path', type=str, 113 | help='''full path to jit .dll. If given it is copied to coreclr directory. 114 | If not given we check that it exists in the coreclr directory. 115 | ''') 116 | parser.add_argument('-w', '--windbg-and-args', type=str, nargs='*', default=[], 117 | help='''Full path to windbg executable followed by any arguments you 118 | want to pass to windbg. 119 | ''') 120 | required = parser.add_argument_group('required arguments') 121 | required.add_argument('-a', '--app-path', type=str, required=True, 122 | help='full path to application to run with llilc.') 123 | required.add_argument('-c', '--coreclr-runtime-path', required=True, 124 | help='full path to CoreCLR run-time binary directory') 125 | args, unknown = parser.parse_known_args(argv) 126 | llilcverbose = args.verbose 127 | if llilcverbose: 128 | log('Starting llilcrun.py') 129 | log(' argv=', argv) 130 | 131 | # Skip separating '--', if any. 132 | if unknown and (unknown[0] == '--'): 133 | unknown = unknown[1:] 134 | 135 | program_dir = os.path.dirname(args.app_path) 136 | jit_name = "llilcjit.dll" 137 | 138 | # jit_path is the path to where the jit would be in the CoreClr directory in order 139 | # to be used as the alternate jit. 140 | jit_path = os.path.join(args.coreclr_runtime_path, jit_name) 141 | 142 | if args.jit_path: 143 | # User specified a source path to the LLILC JIT. Copy it even if there 144 | # already is one, as it may be a revised version. 145 | shutil.copy2(args.jit_path, jit_path) 146 | elif not os.path.exists(jit_path): 147 | log("llilc jit not found at ", jit_path) 148 | return 1 149 | 150 | os.environ["COMPlus_AltJit"]="*" 151 | os.environ["COMPlus_AltJitNgen"]="*" 152 | os.environ["COMPlus_AltJitName"]=jit_name 153 | os.environ["COMPlus_NoGuiOnAssert"]="1" 154 | if (args.precise_gc): 155 | os.environ["COMPlus_InsertStatepoints"]="1" 156 | else: 157 | os.environ["COMPlus_GCConservative"]="1" 158 | if not args.ngen: 159 | os.environ["COMPlus_ZapDisable"]="1" 160 | if args.dump_level: 161 | os.environ["COMPlus_DumpLLVMIR"]=args.dump_level 162 | if args.eh: 163 | os.environ["COMPlus_ExecuteHandlers"]="1" 164 | for arg in args.extra: 165 | pair = UnquoteArg(arg).split('=', 1) 166 | name = 'COMPLUS_' + pair[0] 167 | value = pair[1] 168 | os.environ[name] = value 169 | os.environ["CORE_ROOT"]=args.coreclr_runtime_path 170 | os.environ["CORE_LIBRARIES"]=program_dir 171 | if llilcverbose: 172 | RunCommand('set complus_') 173 | RunCommand('set CORE_ROOT') 174 | RunCommand('set CORE_LIBRARIES') 175 | command = [] 176 | if args.windbg_and_args: 177 | for arg in args.windbg_and_args: 178 | command.append(arg) 179 | if args.corerun_and_args: 180 | first_corerun = True 181 | for arg in args.corerun_and_args: 182 | if first_corerun: 183 | # First of these will be the CoreRun.exe, so prefix with 184 | # the path. 185 | arg = os.path.join(args.coreclr_runtime_path, arg) 186 | first_corerun = False 187 | command.append(arg) 188 | 189 | command.append(args.app_path) 190 | for arg in unknown: 191 | command.append(arg) 192 | error_level = RunCommand(command) 193 | if llilcverbose: 194 | log ('Exiting llilc_run.py with exit code ', error_level) 195 | return error_level 196 | 197 | if __name__ == '__main__': 198 | return_code = main(sys.argv[1:]) 199 | sys.exit(return_code) 200 | -------------------------------------------------------------------------------- /include/Reader/abi.h: -------------------------------------------------------------------------------- 1 | //===------------------- include/Reader/abi.h -------------------*- C++ -*-===// 2 | // 3 | // LLILC 4 | // 5 | // Copyright (c) Microsoft. All rights reserved. 6 | // Licensed under the MIT license. 7 | // See LICENSE file in the project root for full license information. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | /// 11 | /// \file 12 | /// \brief Declares the ABI abstraction used when lowering functions to LLVM IR. 13 | /// 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef _READER_ABI_H_ 17 | #define _READER_ABI_H_ 18 | 19 | /// \brief Information about how a particular argument is passed to a function. 20 | /// 21 | /// This class encapsulates information such as whether a parameter is passed 22 | /// by value or by implicit reference, whether it must be coerced to a different 23 | /// type, etc. This information is used when generating call sequences or 24 | /// accessing method parameters/results. 25 | class ABIArgInfo { 26 | public: 27 | /// \brief Describes how a particular argument is passed to a function. 28 | enum Kind { 29 | Direct, ///< Pass the argument directly, optionally coercing it to a 30 | ///< different type. 31 | 32 | Expand, ///< Pass the argument directly after expanding its contents 33 | ///< according to the expansion records. 34 | 35 | ZeroExtend, ///< Pass the argument directly with zero-extension. 36 | 37 | SignExtend, ///< Pass the argument directly with sign-extension. 38 | 39 | Indirect, ///< Pass the argument indirectly via a hidden pointer 40 | }; 41 | 42 | /// \brief Describes how a subfield of a value is expanded into an argument. 43 | struct Expansion { 44 | llvm::Type *TheType; ///< The type of the expanded subfield. 45 | unsigned Offset; ///< The offset of the subfield in the value. 46 | }; 47 | 48 | private: 49 | Kind TheKind; ///< How this argument is to be passed 50 | union { 51 | llvm::Type *TheType; ///< The type this argument is to be passed as. 52 | ///< Especially relevant for Kind::Direct. 53 | 54 | llvm::SmallVector *Expansions; ///< The expansions used to 55 | ///< pass this arg. 56 | ///< Relevant only for 57 | ///< Kind::Expand. 58 | }; 59 | uint32_t Index; ///< Index of this argument in the argument list of 60 | ///< its containing \p Function. Currently only used by 61 | ///< \p ABIMethodSignature. 62 | 63 | ABIArgInfo(const ABIArgInfo &other) = delete; 64 | ABIArgInfo &operator=(const ABIArgInfo &other) = delete; 65 | 66 | ABIArgInfo(Kind TheKind, llvm::Type *TheType); 67 | ABIArgInfo(Kind TheKind, llvm::ArrayRef Expansions); 68 | 69 | public: 70 | ABIArgInfo(ABIArgInfo &&other); 71 | ~ABIArgInfo(); 72 | 73 | ABIArgInfo &operator=(ABIArgInfo &&other); 74 | 75 | /// \brief Create an \p ABIIArgInfo value for an argument that is to be 76 | /// passed by value with a particular type. 77 | /// 78 | /// \param TheType The type that this argument is passed as. 79 | /// 80 | /// \returns An \p ABIArgInfo value describing the argument. 81 | static ABIArgInfo getDirect(llvm::Type *TheType); 82 | 83 | /// \brief Create an \p ABIIArgInfo value for an argument that is to be 84 | /// passed by expansion. 85 | /// 86 | /// \param Expansions The expansion records for this argument. 87 | /// 88 | /// \returns An \p ABIArgInfo value describing the argument. 89 | static ABIArgInfo getExpand(llvm::ArrayRef Expansions); 90 | 91 | /// \brief Create an \p ABIIArgInfo value for an argument that is to be 92 | /// passed by value with zero extension. 93 | /// 94 | /// \param TheType The type that this argument is passed as. 95 | /// 96 | /// \returns An \p ABIArgInfo value describing the argument. 97 | static ABIArgInfo getZeroExtend(llvm::Type *TheType); 98 | 99 | /// \brief Create an \p ABIIArgInfo value for an argument that is to be 100 | /// passed by value with sign extension. 101 | /// 102 | /// \param TheType The type that this argument is passed as. 103 | /// 104 | /// \returns An \p ABIArgInfo value describing the argument. 105 | static ABIArgInfo getSignExtend(llvm::Type *TheType); 106 | 107 | /// \brief Create an \p ABIIArgInfo value for an argument that is to be 108 | /// passed by an implicit reference to a particular type. 109 | /// 110 | /// \param TheType The referent type for this argument. 111 | /// 112 | /// \returns An \p ABIArgInfo value describing the argument. 113 | static ABIArgInfo getIndirect(llvm::Type *TheType); 114 | 115 | /// \brief Empty constructor to allow vectors, data-dependent construction, 116 | /// etc. 117 | /// 118 | /// Actual values should be created using \p getDirect and \p getIndirect. 119 | ABIArgInfo() {} 120 | 121 | /// \brief Get the \p Kind that describes how this argument is passed. 122 | /// 123 | /// \returns The \p Kind that describes how this argument is passed. 124 | Kind getKind() const; 125 | 126 | /// \brief Get the type of this argument. 127 | /// 128 | /// \returns The type of the argument for direct args or the referent type 129 | /// of the argument for indirect args. 130 | llvm::Type *getType() const; 131 | 132 | /// \brief Get the expansions for this argument. 133 | /// 134 | /// \returns The expansion records for this argument. Only valid for expanded 135 | /// arguments. 136 | llvm::ArrayRef getExpansions() const; 137 | 138 | /// \brief Set the index of this argument in its containing argument list. 139 | /// 140 | /// \param Index The index of this argument in its containing agument list. 141 | void setIndex(uint32_t Index); 142 | 143 | /// \brief Get the index of this argument in its containing argument list. 144 | /// 145 | /// \returns The index of this argument in its containing argument list. 146 | uint32_t getIndex() const; 147 | }; 148 | 149 | /// \brief Encapsulates an \p llvm::Type* and its signedness. 150 | class ABIType { 151 | private: 152 | llvm::Type *TheType; ///< The type of this argument. 153 | CORINFO_CLASS_HANDLE Class; ///< The class handle for this argument. 154 | bool IsSigned; ///< True if the type is a signed integral type. 155 | 156 | public: 157 | /// \brief Creates an \p ABIType with the given type and signedness. 158 | /// 159 | /// \param TheType The \p llvm::Type* for this \p ABIType. 160 | /// \param Class The \p CORINFO_CLASS_HANDLE for this \p ABIType. 161 | /// \param IsSigned True if this \p ABIType is a signed integral type. 162 | ABIType(llvm::Type *TheType, CORINFO_CLASS_HANDLE Class, bool IsSigned); 163 | 164 | /// \brief Empty constructor to allow vectors, data-dependent construction, 165 | /// etc. 166 | ABIType() {} 167 | 168 | /// \brief Get the \p llvm::Type* for this \p ABIType. 169 | /// 170 | /// \returns The \p llvm::Type* for this \p ABIType. 171 | llvm::Type *getType() const; 172 | 173 | /// \brief Get the \p CORINFO_CLASS_HANDLE for this \p ABIType. 174 | /// 175 | /// \returns the \p CORINFO_CLASS_HANDLE for this \p ABIType. 176 | CORINFO_CLASS_HANDLE getClass() const; 177 | 178 | /// \brief Get the signedness of this \p ABIType. 179 | /// 180 | /// \returns True if this \p ABIType is a signed integral type. 181 | bool isSigned() const; 182 | }; 183 | 184 | /// \brief Encapsulautes ABI-specific functionality. 185 | /// 186 | /// The \p ABIInfo class provides ABI-specific services. Currently, this is 187 | /// limited to computing the details of how arguments are passed to functions 188 | /// for a given platform. 189 | class ABIInfo { 190 | public: 191 | /// \brief Gets an \p ABIInfo that corresponds to the target of the given 192 | /// \p Module. 193 | /// 194 | /// \returns An \p ABIInfo instance. This instance belongs to the caller and 195 | /// should be deleted when it is no longer needed. 196 | static ABIInfo *get(llvm::Module &M); 197 | 198 | /// \brief Computes argument passing information for the target ABI. 199 | /// 200 | /// This function is used to determine how the parameters to and result of a 201 | /// function are passed for the given calling convention and types for the 202 | /// target ABI. 203 | /// 204 | /// \param Context The \p LLILCJitContext instance that will be 205 | /// used to retrieve extended type information. 206 | /// \param CC The calling convention for the call target. 207 | /// \param IsManagedCallingConv True if the callling convention targets 208 | /// managed code. 209 | /// \param ResultType The type of the target's result. 210 | /// \param ArgTypes The types of the target's arguments. 211 | /// \param ResultInfo [out] Argument passing information for the target's 212 | /// result. 213 | /// \param ArgInfos [out] Argument passing information for the target's 214 | /// arguments. 215 | virtual void 216 | computeSignatureInfo(LLILCJitContext &Context, llvm::CallingConv::ID CC, 217 | bool IsManagedCallingConv, ABIType ResultType, 218 | llvm::ArrayRef ArgTypes, ABIArgInfo &ResultInfo, 219 | std::vector &ArgInfos) const = 0; 220 | 221 | /// \brief Virtual Destructor 222 | virtual ~ABIInfo() = default; 223 | }; 224 | 225 | #endif 226 | --------------------------------------------------------------------------------