diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj
new file mode 100644
index 0000000000..74eb826efc
--- /dev/null
+++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj
@@ -0,0 +1,65 @@
+
+
+
+
+
+ net472
+ ILSpy.ReadyToRun.Plugin
+ 7.2
+
+ False
+
+ false
+
+ 6488064
+
+
+
+ full
+ true
+ True
+
+
+
+ pdbonly
+ true
+
+
+
+ ..\ILSpy\bin\$(Configuration)\
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+ ..\..\iced\Iced\bin\Debug\netstandard2.0\Iced.dll
+
+
+ ..\..\runtime\artifacts\bin\coreclr\Windows_NT.x64.Debug\ILCompiler.Reflection.ReadyToRun.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs b/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..85918694e1
--- /dev/null
+++ b/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+#region Using directives
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+#endregion
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ILSpy.ReadyToRun.Plugin")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ILSpy.ReadyToRun.Plugin")]
+[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+[assembly: InternalsVisibleTo("ILSpy.ReadyToRun.Tests")]
+
+// The assembly version has following format :
+//
+// Major.Minor.Build.Revision
+//
+// You can specify all the values or you can use the default the Revision and
+// Build Numbers by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs
new file mode 100644
index 0000000000..0d15383f1b
--- /dev/null
+++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs
@@ -0,0 +1,134 @@
+// Copyright (c) 2018 Siegfried Pammer
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.ComponentModel.Composition;
+using Iced.Intel;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Metadata;
+using ICSharpCode.Decompiler.Solution;
+using ICSharpCode.Decompiler.TypeSystem;
+using ILCompiler.Reflection.ReadyToRun;
+
+namespace ICSharpCode.ILSpy
+{
+ [Export(typeof(Language))]
+ class ReadyToRunLanguage : Language
+ {
+ public override string Name => "ReadyToRun";
+
+ public override string FileExtension {
+ get { return ".asm"; }
+ }
+
+ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
+ {
+ PEFile module = assembly.GetPEFileOrNull();
+ // TODO: avoid eager parsing
+ R2RReader reader = new R2RReader(new R2RAssemblyResolver(), module.Metadata, module.Reader, module.FileName);
+
+ output.WriteLine("// TODO - display ready to run information");
+ // TODO: display other header information
+ foreach (var method in reader.R2RMethods) {
+ output.WriteLine(method.SignatureString);
+ }
+
+ return base.DecompileAssembly(assembly, output, options);
+ }
+
+ public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
+ {
+ PEFile module = method.ParentModule.PEFile;
+ // TODO: avoid eager parsing in R2RReader
+ R2RReader reader = new R2RReader(new R2RAssemblyResolver(), module.Metadata, module.Reader, module.FileName);
+ foreach (var m in reader.R2RMethods) {
+ if (m.MethodHandle == method.MetadataToken) {
+ // TODO: Indexing
+ foreach (RuntimeFunction runtimeFunction in m.RuntimeFunctions) {
+ byte[] code = new byte[runtimeFunction.Size];
+ for (int i = 0; i < runtimeFunction.Size; i++) {
+ code[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
+ }
+ // TODO: Bitness
+ // TODO: RIP
+ DecoderFormatterExample(output, code, 64, 0);
+ }
+
+ }
+ }
+ }
+ private void DecoderFormatterExample(ITextOutput output, byte[] exampleCode, int exampleCodeBitness, ulong exampleCodeRIP)
+ {
+ // TODO: Decorate the disassembly with Unwind, GC and debug info
+ // You can also pass in a hex string, eg. "90 91 929394", or you can use your own CodeReader
+ // reading data from a file or memory etc
+ var codeBytes = exampleCode;
+ var codeReader = new ByteArrayCodeReader(codeBytes);
+ var decoder = Decoder.Create(exampleCodeBitness, codeReader);
+ decoder.IP = exampleCodeRIP;
+ ulong endRip = decoder.IP + (uint)codeBytes.Length;
+
+ // This list is faster than List since it uses refs to the Instructions
+ // instead of copying them (each Instruction is 32 bytes in size). It has a ref indexer,
+ // and a ref iterator. Add() uses 'in' (ref readonly).
+ var instructions = new InstructionList();
+ while (decoder.IP < endRip) {
+ // The method allocates an uninitialized element at the end of the list and
+ // returns a reference to it which is initialized by Decode().
+ decoder.Decode(out instructions.AllocUninitializedElement());
+ }
+
+ // Formatters: Masm*, Nasm*, Gas* (AT&T) and Intel* (XED)
+ // TODO: DecompilationOptions?
+ var formatter = new NasmFormatter();
+ formatter.Options.DigitSeparator = "`";
+ formatter.Options.FirstOperandCharIndex = 10;
+ var tempOutput = new StringBuilderFormatterOutput();
+ // Use InstructionList's ref iterator (C# 7.3) to prevent copying 32 bytes every iteration
+ foreach (var instr in instructions) {
+ // Don't use instr.ToString(), it allocates more, uses masm syntax and default options
+ formatter.Format(instr, tempOutput);
+ output.Write(instr.IP.ToString("X16"));
+ output.Write(" ");
+ int instrLen = instr.ByteLength;
+ int byteBaseIndex = (int)(instr.IP - exampleCodeRIP);
+ for (int i = 0; i < instrLen; i++)
+ output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
+ int missingBytes = 10 - instrLen;
+ for (int i = 0; i < missingBytes; i++)
+ output.Write(" ");
+ output.Write(" ");
+ output.WriteLine(tempOutput.ToStringAndReset());
+ }
+ }
+
+ private class R2RAssemblyResolver : ILCompiler.Reflection.ReadyToRun.IAssemblyResolver
+ {
+ public bool Naked => false;
+
+ public bool SignatureBinary => false;
+
+ public bool InlineSignatureBinary => false;
+
+ public string FindAssembly(string name, string filename)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ILSpy.sln b/ILSpy.sln
index 58bdc2b3e1..1445db3f9b 100644
--- a/ILSpy.sln
+++ b/ILSpy.sln
@@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.PdbP
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Tests", "ILSpy.Tests\ILSpy.Tests.csproj", "{B51C6636-B8D1-4200-9869-08F2689DE6C2}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.ReadyToRun", "ILSpy.ReadyToRun\ILSpy.ReadyToRun.csproj", "{0313F581-C63B-43BB-AA9B-07615DABD8A3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -79,6 +81,10 @@ Global
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE