Giter Club home page Giter Club logo

disasmo's Introduction

Disasmo

VS2022 Add-in. Click on any method or class to see JIT's codegen and more.

demo

Starting with .NET 7.0 RC1 this add-in no longer requires a local build of dotnet/runtime repo. However, it offers more features with a local one, to obtain a local one please follow these steps:

git clone git@github.com:dotnet/runtime.git
cd runtime
build.cmd Clr+Clr.Aot+Libs -c Release -rc Checked

# optional (for crossgen2 + arm64 for hw intrinsics):
build.cmd Clr.CoreLib -c Release -a arm64

See windows-requirements.md.

Release notes

See RELEASE_NOTES.md

Installation

Click on Extensions\Manage Extensions menu, select Online tab and type Disasmo in the "Search" text box. Once the add-in is installed you have to close all active instances of VS2022 to let the installer finish its job.

Features

  • Hot-key to quickly see codegen (Alt+Shift+D by default, can be changed in VS's settings)
  • Is able to show codegen for ARM64
  • Flowgraphs and JitDumps for JIT contributors
  • Diffs
  • "System.Runtime.Intrinsics quick search" tab
  • Inliner's decisions
  • 'Run' mode. Is useful for e.g. PGO inspection

Known Issues

  • Only .NET 6.0 and later projects are supported with custom runtime
  • .NET 7.0 RC1 (or newer) is needed for non-custom runtime mode
  • I only tested it for simple Console Apps, but it should work for libs as well
  • Generic methods are only supported in 'Run' mode
  • Resharper hides Roslyn actions by default (Uncheck "Do not show Visual Studio Light Bulb").
  • The lightbulb can be slow on first launch
  • When disassembling a method from a class, the associated C# Visual Studio project or one of its project files must the active/selected in the solution explorer, otherwise it will generate a blank disassembly window.
  • When disassembling a method that uses a code coming from a NuGet package, Disasmo will not be able to find the assembly. The workaround is to copy the assembly to the disasmo folder created in the output bin folder of the project.

3rd party dependencies

disasmo's People

Contributors

egorbo avatar en3tho avatar hopperpl avatar kant2002 avatar kindermannhubert avatar saucecontrol avatar singleaccretion avatar speshuric avatar tkp1n avatar xoofx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

disasmo's Issues

Feature Request: Add a define when compiling

I have a test app that runs DotNetBenchmark when building with Release, and some testing when ran in DEBUG.

I'd also really like Disasmo to run the debug case, but without actually compiling debug. I think this can be done by having Disamo adding a new define, so i can do:

#if DEBUG || DISASMO
//a
#else
//b
#endif

TypeLoadException

Visual Studio 2019 Preview 3.0
.NET Core 3.0 Console Application

Code to reproduce:

using System;
using System.Runtime.Intrinsics.X86;
namespace ConsoleApp1
{
	class Program
	{
		static unsafe void Main(string[] args)
		{
			Console.WriteLine("Hello World!");

			DoTest();

			Console.WriteLine($"Is sup: {Sse42.IsSupported}");
		}

		static unsafe void DoTest()
		{
			var srcBuf = stackalloc[] { (byte)0xF0, (byte)0xF0, (byte)0xF0, (byte)0xF0 };
			var dstBuf = stackalloc[] { (byte)0xF0, (byte)0xF0, (byte)0xF0, (byte)0xF0 };
			var cvrBuf = stackalloc[] { (byte)0xF0, (byte)0xF0, (byte)0xF0, (byte)0xF0 };
			var alphaBuf = stackalloc[] { (byte)0xF0, (byte)0xF0, (byte)0xF0, (byte)0xF0 };
			var csmBuf = stackalloc[]
			{
				(byte)0x00,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0x01,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0x02,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0x03,
				(byte)0xFF,
				(byte)0xFF,
				(byte)0xFF
			};
			var onesBuf = stackalloc[]
			{
				(byte)0x01,
				(byte)0x00,
				(byte)0x00,
				(byte)0x00,
				(byte)0x01,
				(byte)0x00,
				(byte)0x00,
				(byte)0x00,
				(byte)0x01,
				(byte)0x00,
				(byte)0x00,
				(byte)0x00,
				(byte)0x01,
				(byte)0x00,
				(byte)0x00,
				(byte)0x00,
			};

			var length = 4;

			var rCvr = Sse42.LoadVector128(cvrBuf);
			var rSrc = Sse42.LoadVector128(srcBuf);
			for (int i = 0; i < length; i++)
			{
				rCvr = Sse42.Shuffle(rCvr, Sse42.LoadVector128(csmBuf));
				rCvr = Sse42.Add(rCvr, Sse42.LoadVector128(onesBuf));
			}
		}
	}
}

"Disasm 'DoTest' method" fails with:

Unhandled Exception: System.TypeLoadException: Could not load type 'Internal.Runtime.Augments.EnvironmentAugments' from assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
   at System.Environment.get_CurrentManagedThreadId()
   at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate)
   at ConsoleApp1.Program.Main(String[] args)

net8.0 (preview 7) does not appear to be supported

@EgorBo trying to use Disasmo with .NET 8.0 preview 7 but this appears to not work.

Unhandled exception. System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
Could not load file or assembly 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

Project has

<TargetFrameworks>net7.0;net8.0</TargetFrameworks>

Publish Mode Doesn't work in AOT Enabled Project

Hello,

Thanks for this awesome extension, this is something I've wanted for a long time.

One issue I've encountered is the following:

  • I have some NuGet packages that my project uses, and when using the default "dotnet build" option, this fails to install them in the target directory, and I get this error:
Unhandled exception. System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
Could not load file or assembly 'Vortice.Win32, Version=1.9.14.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
Could not load file or assembly 'Vortice.Win32, Version=1.9.14.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.Assembly.GetTypes()
   at DisasmoLoader.PrecompileAllMethodsInType(String[] args)
   at DisasmoLoader.Main(String[] args)

Switching to "dotnet publish" mode, I now get this error:

C:\Program Files\dotnet\sdk\7.0.202\Sdks\Microsoft.DotNet.ILCompiler\build\Microsoft.NETCore.Native.Publish.targets(53,5):
error : PublishTrimmed is implied by native compilation and cannot be disabled. [pathtomy.csproj]

Disabling AOT by changing this option to false the ProperyGroup of my csproj:

<PublishAot>false</PublishAot>

Fixes the issue, and now Disasmo works in "dotnet publish" mode, however I then need to re-enable this option for other debugging and tests. Is there any way to get Disasmo working in an AOT project?

Thanks!

Visual Studio "Find" doesn't work

Repro:

  1. Disassemble a method
  2. Ctrl+F to try and find text in current document
  3. See that you cannot search the output window

There is an easy workaround of copying the text out to something like notepad++, but it would be nice for this to work with the built-in search functionality, particularly for JitDump

Switch to "dotnet build" leads to missing dependencies for libraries

I hit this when trying to disasm a method in a plain (only shared framework dependencies) net5.0 library. It was failing with could not load System.Runtime Version=5.0.0. After some investigation I determined that the cause of the error is the fact that Disasmo is now using dotnet build (presumably, for its higher performance) instead of dotnet publish to get the project's artifacts.

This does not work for libraries, as they, apparently, are built without the framework dependencies being copied to the output. Then CoreRun fails to find them and things do no work as expected.

The "easy" workaround would be to switch back to dotnet publish --self-contained true (note that plain publish does not work for libraries). I suspect, however, that the switch was deliberate and that would be a regression. Maybe CoreRun has some options for probing (I am not an expert in this area)?

Right now I am using a workaround of running a target that would publish my library to the Disasmo's folder after build. FWIW, it works, but it is not pretty.

Disasmo window shows build errors

I tried disasmo but I get following failure in the disasmo window. Any idea?

Microsoft (R) Build Engine version 16.9.0-preview-20611-06+5abf1ff7b for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Program Files\dotnet\sdk\5.0.200-preview.20614.14\Current\SolutionFile\ImportAfter\Microsoft.NET.Sdk.Solution.targets(27,5): error NETSDK1134: Building a solution with a specific RuntimeIdentifier is not supported. If you would like to publish for a single RID, specifiy the RID at the individual project level instead. [e:\ConsoleApp1.sln]

Build FAILED.

C:\Program Files\dotnet\sdk\5.0.200-preview.20614.14\Current\SolutionFile\ImportAfter\Microsoft.NET.Sdk.Solution.targets(27,5): error NETSDK1134: Building a solution with a specific RuntimeIdentifier is not supported. If you would like to publish for a single RID, specifiy the RID at the individual project level instead. [e:\ConsoleApp1.sln]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.13

Here is the output of dotnet --info

dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.200-preview.20614.14
 Commit:    863605c8c3

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19042
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.200-preview.20614.14\

Host (useful for support):
  Version: 5.0.1
  Commit:  b02e13abab

.NET SDKs installed:
  3.1.400-preview-015151 [C:\Program Files\dotnet\sdk]
  5.0.101 [C:\Program Files\dotnet\sdk]
  5.0.200-preview.20614.14 [C:\Program Files\dotnet\sdk]

My Console1.csproj looks like:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

I noticed the RID is win-x64 and not sure if that is accurate.

image

Inserting code at the first left brace past where Roslyn claims the entry point is doesn't seem to be very reliable

I've been trying to get 'where Roslyn tells Disasmo the entrypoint is' to match up with 'where the entry point actually is' with a disappointingly low success rate....

    class Program
    {/*disasmo{*/System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(typeof(TestHarness.IndexOfTesting.InvertedIndexOfAdder).GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic), w => w.DeclaringType == typeof(TestHarness.IndexOfTesting.InvertedIndexOfAdder))).ForEach(m => System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(m.MethodHandle));System.Console.WriteLine(" ");System.Console.ReadLine();System.Environment.Exit(0);/*}disasmo*/
        static void Main(string[] args)
		{
    class Program
    {
        static void Main(string[] args)
		{
			//for (int i = 0; i < 1000; i++)
			//{/*disasmo{*/System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(typeof(TestHarness.IndexOfTesting.InvertedIndexOfAdder).GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic), w => w.DeclaringType == typeof(TestHarness.IndexOfTesting.InvertedIndexOfAdder))).ForEach(m => System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(m.MethodHandle));System.Console.WriteLine(" ");System.Console.ReadLine();System.Environment.Exit(0);/*}disasmo*/

Perhaps Mono.Cecil to add a module initializer, or hijacking the entrypoint to a different file, might be more reliable?

Showing methods IL

I would love to be able to see also methods and types IL. Maybe it should not be too difficult. I would just use ILSpy (though I've never used it programmatically).
Are you open to such extensions of Disasmo? I could have a look at it..

Feature request: Support disassembling older tfms' dlls

This is a feature request to add a dropdown box where I can select which dll I want to disassemble. This would not change the disassembler used, but it would instead just change which dll it uses, for example I could select net6.0 and it would decompile my net6.0 dll with the .NET 7.0 disassembler.

This would be very useful to me as I often write very multi-tfm code, with lots of #ifs. It would be most useful to quickly check my net6.0 dll probably actually produces good vectorised code, since in .NET 7+ I am using the new operations on the vector types mostly, therefore this part of my code shares very few similarities between .NET 7 and .NET 6.

Another use would be if the library doesn't support .NET 7 directly, but you want to check what the codegen would be on .NET 7 to see if it should be specialised.

Thanks for making a great extension btw!

.NET CLI tool

Could we make this also as a .NET CLI tool so we can use it on none-Windows platforms?
I tried to look into the code but it's a bit hard for me to understand how it works.

Disasmo overrides project's `DefineConstants`

Since the dotnet build cmdline now includes /p:DefineConstants=DISASMO, this value is taken instead of any value defined in the csproj.

I like being able to detect Disasmo runs from my project and/or code, but maybe an alternate property would be better. We could then bridge that into DefineConstants ourselves if we want that.

VS results in an exception when Alt+Enter (suggested code fix) is pressed with Disasmo installed

  <entry>
    <record>698</record>
    <time>2020/02/09 19:41:59.921</time>
    <type>Error</type>
    <source>Editor or Editor Extension</source>
    <description>System.InvalidOperationException: Can only compare ISuggestedActionCategories defined with SuggestedActionCategoryRegistryService&#x000D;&#x000A;   at Microsoft.VisualStudio.Language.Intellisense.Implementation.SuggestedActionCategoryComparer.Compare(String x, String y)&#x000D;&#x000A;   at System.Linq.EnumerableSorter`2.CompareKeys(Int32 index1, Int32 index2)&#x000D;&#x000A;   at System.Linq.EnumerableSorter`1.QuickSort(Int32[] map, Int32 left, Int32 right)&#x000D;&#x000A;   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)&#x000D;&#x000A;   at System.Linq.OrderedEnumerable`1.&lt;GetEnumerator&gt;d__1.MoveNext()&#x000D;&#x000A;   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()&#x000D;&#x000A;   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)&#x000D;&#x000A;   at Microsoft.VisualStudio.Language.Intellisense.Implementation.DefaultLightBulbPresenterDefaultIconUIElementProvider.GetUIElement(ISuggestedActionCategorySet itemToRender, ILightBulbSession context, UIElementType elementType)&#x000D;&#x000A;   at Microsoft.VisualStudio.Language.Intellisense.Implementation.LightBulb..ctor(LightBulbSession session, LightBulbPresenterStyleFactory presenterStyleFactory)&#x000D;&#x000A;   at Microsoft.VisualStudio.Language.Intellisense.Implementation.LightBulbTagger.&lt;Microsoft.VisualStudio.Text.Tagging.ITagger&lt;Microsoft.VisualStudio.Language.Intellisense.Implementation.LightBulbTag&gt;.GetTags&gt;b__10_1()&#x000D;&#x000A;   at Microsoft.VisualStudio.Language.Intellisense.Implementation.LightBulbTag.get_Glyph()&#x000D;&#x000A;   at Microsoft.VisualStudio.Language.Intellisense.Implementation.LightBulbGlyphFactory.GenerateGlyph(IWpfTextViewLine line, ISuggestionTag tag)&#x000D;&#x000A;   at Microsoft.VisualStudio.Text.Editor.Implementation.CanvasAndGlyphFactory`1.GenerateGlyph(IWpfTextViewLine line, ITag tag)&#x000D;&#x000A;   at Microsoft.VisualStudio.Text.Editor.Implementation.GlyphMarginVisualManager`1.AddGlyph(TGlyphTag tag, SnapshotSpan span)&#x000D;&#x000A;   at Microsoft.VisualStudio.Text.Editor.Implementation.GlyphMargin`1.RefreshGlyphsOver(ITextViewLine textViewLine)&#x000D;&#x000A;   at Microsoft.VisualStudio.Text.Editor.Implementation.GlyphMargin`1.OnBatchedTagsChanged(Object sender, BatchedTagsChangedEventArgs e)&#x000D;&#x000A;   at Microsoft.VisualStudio.Text.Utilities.GuardedOperations.RaiseEvent[TArgs](Object sender, EventHandler`1 eventHandlers, TArgs args)&#x000D;&#x000A;--- End of stack trace from previous location where exception was thrown ---&#x000D;&#x000A;   at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)</description>
  </entry>

I'm using VS2019 16.5 P2, but it used to happen with P1 as well. Can't confirm if it happened before. It appears that this only happens when Alt+Enter (or Ctrl + .) is pressed; this also does not happen with Disasmo disabled / uninstalled.

(Option to) use release runtime instead of checked

21619e8 removed the option "prefer checked runtime" and now disassembly is always done using checked runtime which unfortunately means that various runtime asserts and extra validations are also left in and thus the disassembly isn't always accurate. Only JIT dll needs to be from checked/debug build.

Weird sporadic issue with Disasmo

Sometimes when I open up VS anew and want to disassemble the method I can encounter this strange exception:

System.ArgumentException: The path is not of a legal form.
   at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
   at System.IO.Path.InternalGetDirectoryName(String path)
   at Disasmo.MainViewModel.<RunOperationAsync>d__80.MoveNext()

It fixes up itself eventually but I don't understand how I get to see this problem self-fixed at all and I have no clear reasoning what's wrong about it.
BTW I have tried to try this with local dotnet/runtime build, turned all the switches on/off but it still doesn't work

VS 2017 Support?

This looks amazing, and I don't know why I've never seen it done before.
Unfortunately, I'm stuck in ancient history with Visual Studio 2017.

Is 2017 support possible, and if so would you be willing to add support? I'd be willing to recompile it myself, but I'm willing to bet there's others who would appreciate it too.

Failed to create CoreCLR, HRESULT: 0x80004005

I'm trying to Disasm any .NET Core 3.1 based method as shown in the example (including the example method: InefficientJoin), but I'm getting 0x80004005 error.

  1. I cloned dotnet/runtime.
  2. I installed C++ related payload via VS2019 installer (I skipped Windows 10 SDK)
  3. After I did 2) I got DIA SDK folder so I no longer see the following: Error: DIA SDK is missing.
  4. I installed CMake, Python was already there.
  5. I run runtime\src\coreclr\build-runtime.cmd -all -checked -x64 -x86 (no errors)
  6. When I'm trying to run Disasmo against any method I'm getting 0x80004005. It doesn't say anything about any configuration issues.

I'd like to use this extension since it seems to be helpful is some scenarios, however, I haven't figured out how to make it actually work. I've spent almost two days trying to make it work.

Show overall byte length at the top

When looking for optimizations it's useful to see if a change may have reduced the overall bytes of a method. Currently I have to scroll down to see if it contains less instructions than before. This becomes a pain when a method is long (several hundreds of instructions).

It would be nice if disasmo could show the number of instructions / bytes at the top header.

Doesn't work in projects without entry point method

This is expected from the way how it works now (injecting some code to Main method and then running the executable).
I propose having simple "runner" executable (distributed along side with Disasmo) which would accept arguments telling it which dll/exe to load and which type/methods to prepare (=be JITed). Then there would be no need for code injection used now and it would be possible to disasm even methods from dlls.
It would also solve #3.

I can prepare pull request if you agree.

Build error in Disasmo window, tries to build on .NET 6 on .NET 5 target

Local version of latest master brach dotNET runtime is built (with both .\build.cmd Clr+Libs -c Release -rc Checked and .\build.cmd Clr -c Checked). Upon start, compilation is done but fails with an error about .NET 6.0 (even though my app is targeting .NET 5.0 and Settings->Reload Strategy is set to dotnet publish):

System.InvalidOperationException: ERROR: 'dotnet build' did not produce expected binaries ('C:\Users\uberhalit\AppData\Local\Temp\DisasmoLoader3\4.0.4_5.0.402\out\DisasmoLoader3.dll' and 'C:\Users\uberhalit\AppData\Local\Temp\DisasmoLoader3\4.0.4_5.0.402\out\DisasmoLoader3.runtimeconfig.json'):
Microsoft (R)-Build-Engine, Version 16.11.1+3e40a09f8 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

C:\Program Files\dotnet\sdk\5.0.402\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.TargetFrameworkInference.targets(141,5): error NETSDK1045: The current .NET SDK does not support .NET 6.0 as target. [C:\Users\uberhalit\AppData\Local\Temp\DisasmoLoader3\4.0.4_5.0.402\DisasmoLoader3.csproj]
    0 Warnings
    1 Error

   at Disasmo.Utils.LoaderAppManager.<InitLoaderAndCopyTo>d__2.MoveNext()
---  ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at Disasmo.MainViewModel.<RunFinalExe>d__61.MoveNext()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.