Git Product home page Git Product logo

ilpack's People

Contributors

aaronrobinsonmsft avatar arlm avatar ericstj avatar ggg-killer avatar gknabe avatar ldj3snud avatar masonwheeler avatar olegra avatar osen1 avatar osman-turan avatar toptensoftware avatar twinside avatar vermorel avatar victornicollet avatar voltage31 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

ilpack's Issues

Type dependency resolution needed

We tries to sort types by dependencies prior to actual serialization:

private void CreateTypes(IEnumerable<Type> types)
{
// Sort types by base types.
var sortedTypes = types.TopologicalSort(GetBaseTypes).ToList();
// First, reserve metadata for all types
ReserveTypes(sortedTypes);

Dependency solver method:

/// <summary>
/// Gets all interfaces and base types of a given type including all of its parents.
/// Referenced types from external assemblies are excluded.
/// </summary>
/// <param name="type">Type to be examined.</param>
/// <returns>All interfaces and base types of given type and its parents recursively.</returns>
private IEnumerable<Type> GetBaseTypes(Type type)
{
foreach (var inf in type.GetInterfaces())
{
if (_metadata.IsReferencedType(inf))
{
continue;
}
yield return inf;
foreach (var innerInf in GetBaseTypes(inf))
{
yield return innerInf;
}
}
var baseType = type.BaseType;
if (baseType != null)
{
while (!_metadata.IsReferencedType(baseType))
{
yield return baseType;
baseType = baseType.BaseType;
}
}
}

As you see, this method should fail to handle constructed generic types correctly (e.g. IPage in class jot_2 : ICompiledJot<IPage> if all dependent types and jot_2 would be in the same assembly) and throw cyclic dependency exception. Since, our current unit tests are more complex, I've tried completely removing the sorting by assuming metadata are already sorted for a given assembly and it worked.

Question: Is my assumption correct? If so, I will remove type dependency resolution completely. If not, I'll improve it.

Can't save assembly with calls to non-public members

I was trying to generate a dynamic assembly containing a type that inherits from another type whose constructor is protected. This fails with an exception in AssemblyMetadata.GetMethodOrConstructorSignature because that method only considers public methods and constructors. The fix is to pass the appropriate flags to GetMethods/GetConstructors. That would probably be BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static for GetMethods and BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance for GetConstructors.

Support entry-point method and executable assemblies

Initial code had some problems to support executable assemblies (e.g. console applications). The main reason was we need to know entry-point method handle ahead of its serialization to able to serialize <Module> type as first type in the assembly. See:

// Add "<Module>" type definition *before* any type definition.
//
// TODO: [osman] methodList argument should be as following:
//
// methodList: entryPoint.IsNil ? MetadataTokens.MethodDefinitionHandle(1) : entryPoint
//
// But, in order to work above code, we need to serialize
// entry point *without* serializing any type definition.
// This is not needed for libraries since they don't have any entry point.
_metadata.Builder.AddTypeDefinition(
default,
default,
_metadata.GetOrAddString("<Module>"),
default,
MetadataTokens.FieldDefinitionHandle(1),
MetadataTokens.MethodDefinitionHandle(1));

With #31, we could reserve metadata tokens prior to serialization. So, this could help us to support executable assemblies.

Incorrect method parameter numbering

I've dumped twice the same generated program in two assemblies, one in net462, the other one with Lokad.ILPack. The problem can be seen by inspecting the jot_2 class in both dumped assemblies.

With the one generated through net462 we have the following decompiled line (from dotpeek):

task1 = page3 = pageRest11.GetPage(obj1, num5 = (int) num3, obj5);

While Lokad.ILPack generates the following.

task1 = page3 = pageRest11.GetPage(_param2, num5 = (int) num3, (CancellationToken) _param5);

_param5 being the last argument of the run method. Attached the copy of the two generated assembly.

jot_dump.zip

peverify fails on emitted assemblies with file not found error

After emitting a fairly trivial assembly using ILPack, running peverify.dll on that assembly produces this output:

peverify D:\git\MessagePack-CSharp\bin\DynamicCodeDumper\Debug\net5.0\DynamicObjectResolver.dll

Copyright (c) Microsoft Corporation.  All rights reserved.

 [HRESULT 0x80070002] - The system cannot find the file specified.

1 Error(s) Verifying D:\git\MessagePack-CSharp\bin\DynamicCodeDumper\Debug\net5.0\DynamicObjectResolver.dll

In contrast, running peverify.dll on the exact same dynamic assembly except written out by AssemblyBuilder.Save, peverify succeeds:

peverify "D:\git\MessagePack-CSharp\bin\DynamicCodeDumper\Debug\net472\MessagePack.Resolvers.DynamicObjectResolver.dll"

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

All Classes and Methods in D:\git\MessagePack-CSharp\bin\DynamicCodeDumper\Debug\net472\MessagePack.Resolvers.DynamicObjectResolver.dll Verified.

Publish a NuGet package

This is a great library to fill the gap of assembly serialization.

Are there any plans to publish it on NuGet?

ILVerification fails on delegate ctor of generated assembly

[IL]: Error [CallCtor]: [.ProcessBookDelegate::.ctor(object, native int)][offset 0x00000001] call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
 [IL]: Error [StackUnexpected]: [.ProcessBookDelegate::.ctor(object, native int)][offset 0x00000007][found ref '[TriAxis.RunSharp.Tests.12_Delegates.GenBookstore]ProcessBookDelegate'] Unexpected type on the stack.
 [IL]: Error [ThisUninitReturn]: [.ProcessBookDelegate::.ctor(object, native int)][offset 0x0000000C] Return from .ctor when this is uninitialized.
 [IL]: Error [CallCtor]: [.ProcessBookDelegate::.ctor(object, native int)][offset 0x00000001] call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
 [IL]: Error [StackUnexpected]: [.ProcessBookDelegate::.ctor(object, native int)][offset 0x00000007][found ref '[TriAxis.RunSharp.Tests.12_Delegates.GenBookstore]ProcessBookDelegate'] Unexpected type on the stack.
 [IL]: Error [ThisUninitReturn]: [.ProcessBookDelegate::.ctor(object, native int)][offset 0x0000000C] Return from .ctor when this is uninitialized.

TriAxis.RunSharp.Tests.12_Delegates.GenBookstore.zip

Source code:

public delegate void ProcessBookDelegate();

public class Test
{
    public static void Main()
    {
    }
}

ildasm:

// =============== CLASS MEMBERS DECLARATION ===================

.class public auto ansi sealed ProcessBookDelegate
       extends [System.Runtime]System.MulticastDelegate
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor(object 'object',
                               native int 'method') runtime managed
  {
  } // end of method ProcessBookDelegate::.ctor

  .method public hidebysig newslot virtual 
          instance class [System.Runtime]System.IAsyncResult 
          BeginInvoke(class [System.Runtime]System.AsyncCallback callback,
                      object 'object') runtime managed
  {
  } // end of method ProcessBookDelegate::BeginInvoke

  .method public hidebysig newslot virtual 
          instance void  EndInvoke(class [System.Runtime]System.IAsyncResult result) runtime managed
  {
  } // end of method ProcessBookDelegate::EndInvoke

  .method public hidebysig newslot virtual 
          instance void  Invoke() runtime managed
  {
  } // end of method ProcessBookDelegate::Invoke

} // end of class ProcessBookDelegate

.class public auto ansi beforefieldinit Test
       extends [System.Runtime]System.Object
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [System.Runtime]System.Object::.ctor()
    IL_0006:  ldarg.0
    IL_0007:  call       instance void Test::$$ctor$PST06000007()
    IL_000c:  ret
  } // end of method Test::.ctor

  .method public hidebysig static void  Main() cil managed
  {
    // Code size       1 (0x1)
    .maxstack  8
    IL_0000:  ret
  } // end of method Test::Main

  .method privatescope hidebysig instance void 
          $$ctor$PST06000007() cil managed
  {
    // Code size       1 (0x1)
    .maxstack  8
    IL_0000:  ret
  } // end of method Test::$$ctor

} // end of class Test

The same code compiled for .NET 5 in VS generates almost same IL but passes ILVerification without errors:

// =============== CLASS MEMBERS DECLARATION ===================

.class public auto ansi sealed ProcessBookDelegate
       extends [System.Runtime]System.MulticastDelegate
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor(object 'object',
                               native int 'method') runtime managed
  {
  } // end of method ProcessBookDelegate::.ctor

  .method public hidebysig newslot virtual 
          instance class [System.Runtime]System.IAsyncResult 
          BeginInvoke(class [System.Runtime]System.AsyncCallback callback,
                      object 'object') runtime managed
  {
  } // end of method ProcessBookDelegate::BeginInvoke

  .method public hidebysig newslot virtual 
          instance void  EndInvoke(class [System.Runtime]System.IAsyncResult result) runtime managed
  {
  } // end of method ProcessBookDelegate::EndInvoke

  .method public hidebysig newslot virtual 
          instance void  Invoke() runtime managed
  {
  } // end of method ProcessBookDelegate::Invoke

} // end of class ProcessBookDelegate

.class public auto ansi beforefieldinit Test
       extends [System.Runtime]System.Object
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [System.Runtime]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Test::.ctor

  .method public hidebysig static void  Main() cil managed
  {
    // Code size       1 (0x1)
    .maxstack  8
    IL_0000:  ret
  } // end of method Test::Main

} // end of class Test

Re-saving the erroneous IL in dnSpy generates assembly that passes ILVerification:
unchanged.zip

// =============== CLASS MEMBERS DECLARATION ===================

.class public auto ansi sealed ProcessBookDelegate
       extends [System.Private.CoreLib]System.MulticastDelegate
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor(object 'object',
                               native int 'method') runtime managed
  {
  } // end of method ProcessBookDelegate::.ctor

  .method public hidebysig newslot virtual 
          instance class [System.Private.CoreLib]System.IAsyncResult 
          BeginInvoke(class [System.Private.CoreLib]System.AsyncCallback callback,
                      object 'object') runtime managed
  {
  } // end of method ProcessBookDelegate::BeginInvoke

  .method public hidebysig newslot virtual 
          instance void  EndInvoke(class [System.Private.CoreLib]System.IAsyncResult result) runtime managed
  {
  } // end of method ProcessBookDelegate::EndInvoke

  .method public hidebysig newslot virtual 
          instance void  Invoke() runtime managed
  {
  } // end of method ProcessBookDelegate::Invoke

} // end of class ProcessBookDelegate

.class public auto ansi beforefieldinit Test
       extends [System.Private.CoreLib]System.Object
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [System.Private.CoreLib]System.Object::.ctor()
    IL_0006:  ldarg.0
    IL_0007:  call       instance void Test::$$ctor$PST06000007()
    IL_000c:  ret
  } // end of method Test::.ctor

  .method public hidebysig static void  Main() cil managed
  {
    // Code size       1 (0x1)
    .maxstack  8
    IL_0000:  ret
  } // end of method Test::Main

  .method privatescope hidebysig instance void 
          $$ctor$PST06000007() cil managed
  {
    // Code size       1 (0x1)
    .maxstack  8
    IL_0000:  ret
  } // end of method Test::$$ctor

} // end of class Test

The only difference in this fix is using System.Private.CoreLib library instead of System.Runtime and that it's a dll, not exe.

Expected behavior: generated by ILPack assembly should pass IL verification without issues.

Manage cyclic type dependencies

During working #9, I realized a major problem in the code architecture. All serialization logic works in-order. With latest fixes serializing a type works like that:

  1. Serialize all fields of the type
  2. Serialize all properties of the type
  3. Serialize all methods of the type
  4. Serialize all constructors of the type
  5. Serialize the type

Meaning that, a simple code which uses singleton pattern cannot be serialized:

public class MyClass {
  private static MyClass _instance;

  public static MyClass GetInstance() {
    if (_instance == null) {
      _instance = new MyClass();
    }
    return _instance;
  }
}

Because, during serializing the GetInstance method (see 3rd step), MyClass type is not added into _typeHandles dictionary which is used for type resolution.

The following code is the root of the problem:

var fields = CreateFields(type.GetFields(AllFields));
var propsHandle = CreatePropertiesForType(type.GetProperties(AllProperties));
var methods = CreateMethods(type.GetMethods(AllMethods));
CreateConstructors(type.GetConstructors());
var def = _metadataBuilder.AddTypeDefinition(
type.Attributes,
GetString(type.Namespace),
GetString(type.Name),
baseType,
fields.IsNil ? MetadataTokens.FieldDefinitionHandle(1) : fields,
methods.IsNil ? MetadataTokens.MethodDefinitionHandle(1) : methods);
// Handle generics type
if (type.IsGenericType)
{
if (type.IsGenericTypeDefinition)
{
var genericType = type.GetGenericTypeDefinition();
var typeInfo = genericType.GetTypeInfo();
for (var i = 0; i < typeInfo.GenericTypeParameters.Length; ++i)
{
var parm = typeInfo.GenericTypeParameters[i];
var attr = parm.GenericParameterAttributes;
var genericParameterHandle =
_metadataBuilder.AddGenericParameter(def, attr, GetString(parm.Name), i);
foreach (var constraint in parm.GetGenericParameterConstraints())
{
_metadataBuilder.AddGenericParameterConstraint(genericParameterHandle,
GetOrCreateType(constraint));
}
}
}
}
_typeHandles[type.GUID] = def;

Relevant unit test can be found in self-reference-unit-test branch. I didn't merge the changes into develop branch incase you set up CI pipeline which relies on all tests passed.

A major refactoring is required to support cyclic-references with placeholder classes to "reserve" metadata tokens. This refactoring will increase the coverage of generic support as well such as:

public class Vector: IEquatable<Vector> {
  // ...
}

API needs to be reviewed

Current API is misleading. Suppose a developer needs to integrate ILPack into a project. Since, generator methods (AssemblyGenerator.GenerateAssemblyBytes and AssemblyGenerator.GenerateAssembly) are instance methods, the developer might assume AssemblyGenerator does some caching between each generator method calls. So, he probably creates a single instance and use it to maximize efficiency. Also, he need to deal with IDisposable pattern for his single instance.

In contrast to above story, let's have a look at the facts:

  • AssemblyGenerator does not cache anything (or at least currently).
  • IDisposable implementation is purely redundant. It's there to dispose a-never-used MemoryStream which was created in constructor.
  • A single instance won't work. Because, all fields which are shared between internal methods are never cleared. Meaning that all types, methods, fields etc. are cumulatively collected between each generator method calls.

So, I suggest to refactor current API or create a clean API from scratch. My suggestions are:

  • Remove IDisposable and unused MemoryStream.
  • Implement clearing logic between generator method calls and document somewhere about generator method calls are not thread safe for a single instance.
  • Don't expose a static method for generating assemblies. Stick to instance class. We will probably need to cache some variables between generator method calls (like core runtime types to core library mapping tables).

some proposal for perfomance opt (small patch)

Hi Vermorel,

please see/use attached patch, if it's desired. It's just a performance improvement as I was profiling around a bit and I noticed,
ReadInstructions will allocate/GC free an enormous amount of GC objects, as the Delegate (Func) uses a boxing for itself each time as it seems.

Unfortunately, I made ByteBuffer and MethodBodyReader public. I know that's not fine.

Maybe you would find a nicer solution, I currently don't have much time :)

Many Thanks

0001-performance-opt-avoid-creation-of-delegates-boxing.zip

Support generic method parameters

ILPack appears to fail at processing types that contains methods with generic parameters. The unit tests RewriteTest.AssemblyName fails with:

 System.TypeInitializationException : The type initializer for 'Lokad.ILPack.Tests.RewriteTest' threw an exception. 
 ---- System.ArgumentException : Type cannot be found: "T" of "TestSubject.MyClass, TestSubject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

Parameter name: type

Yet, attempting to solve the problem by adding the following lines to AssemblyGenerator.Types.cs :

foreach (var inf in type.GetMethods().SelectMany(t => t.GetGenericArguments()))
{
    yield return inf;
}

Generates the exception:

System.TypeInitializationException : The type initializer for 'Lokad.ILPack.Tests.RewriteTest' threw an exception. 
---- System.ArgumentException : Cyclic connections are not allowed

Fix detached methods

Instance methods are serialized as global methods. So, following verification errors are reported by PEVerify for sample_factorial.dll:

[MD]: Error: Global item (field,method) must be Static. [token:0x06000001]
[MD]: Error: Global method marked Abstract,Virtual. [token:0x06000001]
[MD]: Error: Global item (field,method) must be Static. [token:0x06000002]
[MD]: Error: Global constructor. [token:0x06000002]
4 Error(s) Verifying sample_factorial.dll

Related IL DASM dump:

Global functions
-------------------------------------------------------
	Method #1 (06000001) 
	-------------------------------------------------------
		MethodName: myfactorial (06000001)
		Flags     : [Public] [Virtual] [ReuseSlot]  (00000046)
		RVA       : 0x00002050
		ImplFlags : [IL] [Managed]  (00000000)
		CallCnvntn: [DEFAULT]
		hasThis 
		ReturnType: I4
		No arguments.

	Method #2 (06000002) 
	-------------------------------------------------------
		MethodName: .ctor (06000002)
		Flags     : [Public] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor]  (00001806)
		RVA       : 0x00002092
		ImplFlags : [IL] [Managed]  (00000000)
		CallCnvntn: [DEFAULT]
		hasThis 
		ReturnType: Void
		No arguments.

Expected dump:

TypeDef #1 (02000002)
-------------------------------------------------------
	TypDefName: FactorialAssembly.CFactorial  (02000002)
	Flags     : [Public] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit]  (00100001)
	Extends   : 0100000C [TypeRef] System.Object
	Method #1 (06000001) 
	-------------------------------------------------------
		MethodName: myfactorial (06000001)
		Flags     : [Public] [HideBySig] [ReuseSlot]  (00000086)
		RVA       : 0x00002050
		ImplFlags : [IL] [Managed]  (00000000)
		CallCnvntn: [DEFAULT]
		hasThis 
		ReturnType: I4
		No arguments.

	Method #2 (06000002) 
	-------------------------------------------------------
		MethodName: .ctor (06000002)
		Flags     : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor]  (00001886)
		RVA       : 0x0000207c
		ImplFlags : [IL] [Managed]  (00000000)
		CallCnvntn: [DEFAULT]
		hasThis 
		ReturnType: Void
		No arguments.

Fix user string handling

OperandType.InlineString requires user string metadata token which is allocated by GetOrAddUserString (#US in .NET metadata). Current implementation use strings in #Strings heap which is allocated by GetOrAddString.

Metadata ordering issues

Some of the metadata tables have requirements on sort order. ILPack doesn't currently ensure these rules aren't violated. The main two that seem to be causing issues is the order of the generic parameters table and the interface map.

These are difficult to reproduce in the unit tests because the ordering and interleaving of things can be affected by other things in the project. Here's how to reproduce both issues in Sandbox.

Add the following to SandboxSubject\MyClass.cs, just below MyClass:

public class GPOrder1
{
    public void Function1<T>()
    {
    }
    public void Function2<T>()
    {
    }
}

public class GPOrder2<T>
{
}

Result:

Metadata table GenericParam not sorted.
   at System.Reflection.Throw.InvalidOperation_TableNotSorted(TableIndex tableIndex)
   at System.Reflection.Metadata.Ecma335.MetadataBuilder.ValidateGenericParamTable()
   at System.Reflection.Metadata.Ecma335.MetadataBuilder.ValidateOrder()
   at System.Reflection.Metadata.Ecma335.MetadataRootBuilder.Serialize(BlobBuilder builder, Int32 methodBodyStreamRva, Int32 mappedFieldDataStreamRva)

For the interface map problem, remove the above code and add this instead:

interface Itf1
{
}
interface Itf2
{
}
class MyImpl : Itf2, Itf1
{
}

Result:

Metadata table InterfaceImpl not sorted.
   at System.Reflection.Throw.InvalidOperation_TableNotSorted(TableIndex tableIndex)
   at System.Reflection.Metadata.Ecma335.MetadataBuilder.ValidateInterfaceImplTable()
   at System.Reflection.Metadata.Ecma335.MetadataBuilder.ValidateOrder()
   at System.Reflection.Metadata.Ecma335.MetadataRootBuilder.Serialize(BlobBuilder builder, Int32 methodBodyStreamRva, Int32 mappedFieldDataStreamRva)

Pull Request Process

Hi @vermorel,

With the recent pull requests I've been sending I've been trying to keep them narrowly targeted but I realize this is probably causing some merge issues (especially with the unit tests). I just wanted to check if you prefer things less targeted or if there's anything else that'd make the process smoother.

One thing I was thinking is the tests would merge better if they weren't all in one file. After you've merged the current set of PRs I'll split things up into partial classes which should help in future.

Also... is logging an issue the best way to discuss stuff like this?

Brad

`GenerateAssembly` crash if the dynamic assembly references type of another assembly

See the stack trace.

Exception: The given key 'Envision.Back.Pages.IPage result' was not present in the dictionary.

   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Lokad.ILPack.IL.MethodBodyWriter.Write(BlobBuilder writer, IReadOnlyList`1 il, Func`2 getString, IReadOnlyDictionary`2 typeHandles, IReadOnlyDictionary`2 ctorRefHandles, IReadOnlyDictionary`2 fieldHandles, IReadOnlyDictionary`2 methodHandles) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\IL\MethodBodyWriter.cs:line 112
   at Lokad.ILPack.IL.MethodBodyStreamWriter.AddMethodBody(MethodBase methodBase) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\IL\MethodBodyStreamWriter.cs:line 56
   at Lokad.ILPack.AssemblyGenerator.GetOrCreateMethod(MethodInfo methodInfo) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.Methods.cs:line 59
   at Lokad.ILPack.AssemblyGenerator.CreatePropertiesForType(PropertyInfo[] properties) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.Properties.cs:line 64
   at Lokad.ILPack.AssemblyGenerator.GetOrCreateType(Type type) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.Types.cs:line 79
   at Lokad.ILPack.AssemblyGenerator.CreateTypes(Type[] types) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.Types.cs:line 13
   at Lokad.ILPack.AssemblyGenerator.CreateModules(Module[] moduleInfo) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.Modules.cs:line 21
   at Lokad.ILPack.AssemblyGenerator.GenerateAssemblyBytes() in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.cs:line 88
   at Lokad.ILPack.AssemblyGenerator.GenerateAssembly(String path) in D:\rainbow_buildAgent\work\8daee5e699edf9c0\src\AssemblyGenerator.cs:line 115
   at ...

IPage is a type of our runtime system not created in the dynamic assembly.

Fail to serialize: Type cannot be found: System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute

I tried using this in StreamJsonRpc to dump out a dynamically written assembly.

https://github.com/AArnott/vs-streamjsonrpc/blob/c17313e3aed25059de03c3484882729e6c265dff/src/StreamJsonRpc/ProxyGeneration.cs#L362

It failed with the exception below:

Test Name:	JsonRpcProxyGenerationTests.CallMethod_IntInt_Int
Test FullName:	StreamJsonRpc.Tests (netcoreapp2.1).JsonRpcProxyGenerationTests.JsonRpcProxyGenerationTests.CallMethod_IntInt_Int
Test Source:	D:\git\streamjsonrpc\src\StreamJsonRpc.Tests\JsonRpcProxyGenerationTests.cs : line 166
Test Outcome:	Failed
Test Duration:	0:00:00

Test Name:	JsonRpcProxyGenerationTests.CallMethod_IntInt_Int
Test Outcome:	Failed
Result StackTrace:	
at Lokad.ILPack.Metadata.AssemblyMetadata.GetTypeHandle(Type type)
   at Lokad.ILPack.AssemblyGenerator.CreateCustomAttributes(EntityHandle parent, IEnumerable`1 attributes)
   at Lokad.ILPack.AssemblyGenerator.GenerateAssemblyBytes(Assembly assembly)
   at Lokad.ILPack.AssemblyGenerator.GenerateAssembly(Assembly assembly, String path)
   at StreamJsonRpc.ProxyGeneration.Get(TypeInfo serviceInterface) in D:\git\streamjsonrpc\src\StreamJsonRpc\ProxyGeneration.cs:line 362
   at StreamJsonRpc.JsonRpc.Attach[T](Stream sendingStream, Stream receivingStream) in D:\git\streamjsonrpc\src\StreamJsonRpc\JsonRpc.cs:line 573
   at StreamJsonRpc.JsonRpc.Attach[T](Stream stream) in D:\git\streamjsonrpc\src\StreamJsonRpc\JsonRpc.cs:line 556
   at JsonRpcProxyGenerationTests..ctor(ITestOutputHelper logger) in D:\git\streamjsonrpc\src\StreamJsonRpc.Tests\JsonRpcProxyGenerationTests.cs:line 30
Result Message:	
System.ArgumentException : Type cannot be found: "System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute, rpcProxies_cdac9d9d-b20f-49ff-9b2d-330b04eb391c, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
Parameter name: type

Fail to deserialize: nested class reference

Given

namespace NestedClassTest 
{
  public class Outer
  {
     public class Inner
      {
          public static int V;
      }
  }
}

For a reference to Outer.Inner.V, the C# compiler issues:

	IL_0006: ldsfld int32 NestedClassTest.Outer/Inner::V

ILPack issues:

	IL_0005: ldsfld int32 [NestedClassTest]NestedClassTest.Inner::V

At load time, this throws an exception "Could not load type NestedClassTest.Inner".

System.ArgumentNullException on parameter.Name for property setter method

Hello. Recently I've tried to test your implementation of assembly saving logic and found little issue.
When I try to save my type, that works in runtime, I get an exception on saving setter method of my type. Example of my code here. Maybe I've missed something on generation steps of my type. I'm totaly new in this features. :)

parameterDef = _metadataBuilder.AddParameter(parameter.Attributes,GetString(parameter.Name),i);

image

Wrong interpretation of public key token of core library

Initial code used PublicKeyToken to determine if a referenced assembly is actually the core library (e.g. "mscorlib"). This wrong approach is made its way to till to date. PublicKeyToken is actually hash of public key and it's what used during signing. So, PublicKeyToken is actually same for assemblies which Microsoft used same private key.

We should use fully qualified assembly name instead of PublicKeyToken. But, there is another problem that should be fixed as well. For example, System.Random resides in System.Runtime.Extensions assembly. If we try to get the assembly with:

var asm = typeof(System.Random).Assembly.GetName();
Console.WriteLine(asm.FullName);

// On .NET Core, prints:
// System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e

So, mapping System.Private.CoreLib to System.Runtime will lead a crash. Because, System.Runtime does not have any reference for System.Random.

So, correct core library mapping is actually somewhat more complex. One of the possible way is to build a type dictionary for known assemblies like:

var knownAssemblyNames = new []{ "System.Runtime", "System.Runtime.Extensions", /* ... */ };

foreach (var name in knownAssemblyNames) {
  var asm = Assembly.Load(name);
  var types = asm.GetTypes();
  AddKnownTypeReference(name, types);
}

Fix error when accessing full metadata of serialized assembly

When full metadata has accessed of a serialized assembly, an exception is thrown.

Following snippet demonstrate this error.

var asm = Assembly.LoadFile(path);
var types = asm.GetTypes(); // ERROR

Related exception stack trace:

System.Reflection.ReflectionTypeLoadException : Unable to load one or more of the requested types.
Invalid assembly public key. (Exception from HRESULT: 0x8013141E)
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeModule.GetTypes()
   at System.Reflection.Assembly.GetTypes()
   at Lokad.ILPack.Tests.AssemblyGeneratorTest.Test()

Improve basic formatting, naming and code patterns

Improve code quality by applying previously discussed coding conventions of other projects such as including but not limited:

  • Removing unused namespaces
  • Fixing inconsistent naming convention
  • Implementing inline out variables
  • Replacing explicitly typed local variables with implicitly typed local variables (i.e. var keyword)
  • Sorting namespaces, nested-classes and class members
  • Adding explicit access modifiers where implicitly defined (e.g. private)
  • Use of nameof where applicable (such as exceptions)
  • Fixing code indentation

Non-public properties causing failure

var eitherAccessor = propertyInfo.GetGetMethod() ?? propertyInfo.GetSetMethod();

PropertyInfo.GetGetMethod() and PropertyInfo.GetSetMethod() do not return non-public accessors, so for properties that were generated without a public accessor this line causes a failure. Changing this line to the below fixed my use case, would you mind incorporating that into the source? Thanks.
var eitherAccessor = propertyInfo.GetMethod ?? propertyInfo.SetMethod;

(with patch)

Hi,

attached a patch for a little issue in AssemblyMetadata.cs ("HACK: [vermorel] 2019-07-25.").

It will attach a ref to "netstandard" and make sure the ref to the assemblyname "system.private.corelib" is as per loaded in application current domain.

I noticed problems when AOTing with Mono (system.private.corelib not found) and ILSpy couldn't resolve these references either. With this patch, problems are gone.

I cannot say 100% sure if it will work for all NET versions, tested with netcore31, net50, mono. All ok-

0001-patch-for-reference-assemblies-netstandard-unresolve.zip

Best regards,
S.

.NET Core libraries should reference System.Runtime instead of mscorlib

Dynamically generated assemblies reference System.Private.CoreLib assembly first. System.Private.CoreLib public key token is same as mscorlib. Since, .NET Core is fundamentally different from .NET Framework (.NET Core supports side-by-side runtime), we shouldn't reference mscorlib first. Instead, we should reference System.Runtime assembly which we should extract at its metadata at runtime. Also, we should map all mscorlib and System.Private.CoreLib references to System.Runtime.

Fix serializing bare minimum assemblies

Even serializing an assembly with no types does not work. Although, PEVerify cannot find any errors, .NET runtime refuses to load this bare minimum assemblies and throws BadImageFormatException (technically COR_E_BADIMAGEFORMAT). So, there should be an error either in PE structure or metadata.

Generated assembly from a .NET 5 executable is ".NETFramework" instead of ".NETCore"

Using this code from a .NET 5 app:

        var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
        var mb = ab.DefineDynamicModule("test");
        var tb = mb.DefineType("Resources");
        var fb = tb.DefineInitializedData("Something", new byte[] { 1, 2, 3, 4, 5 }, FieldAttributes.Public | FieldAttributes.Static);

        tb.CreateType();

        var ag = new Lokad.ILPack.AssemblyGenerator();
        ag.GenerateAssembly(ab, "test.dll");

generates a .NETFramework-type library:
image
(Taken with ILSpy)

Is there a way to force ILPack to generate .NETCore binaries?

With Patch/Fix: Missing Generic Type arguments in OpCodes.Call(x)

Hi Joannès,

I found a bug and fixed this, however, this time the fix is a bit more sophisticated, so I ask you kindly to review.
I tried to submit a PR but did not find out how, with Github.

Let me explain:

  1. You have an ModuleBuilder and in this single module you create
  • A generic type inheriting from an external, also generic type, with generic params 1:1
  • Another type in this in-memory-module that inherits from this type before and calls methods, for these calls, the 'this pointer' of course must be the constructed type, not the open type.

Currently, with ILPack this is failing. Please see screenshot below with wrongly generated IL, Type arguments are missing

missing_type_inst

To fix, I did the following:

  • changed MethodBodyWriter to make sure constructed types are written, I extended your interface and added some TryGetMethodDefinitionConstructedType etc.

  • I changed IsReferencedType. For this, I ask you kindly to review as this new approach is also just a best guess :)

Good news is, all tests are passing as per before and the problem is gone. I write quite large assemblies, referencing and inheriting e.g. all types in netstandard.

fixed_missing_type_inst

PS: Please let me know if you need something. It may be this problem also exists for generic methods, I will check this at a later time.

Many Thanks

Sascha
ILPack.zip

System.IndexOutOfRangeException at Save

Void .ctor(System.String, AdvancedDLSupport.ImplementationOptions, AdvancedDLSupport.Loaders.ILibraryLoader, AdvancedDLSupport.Loaders.ISymbolLoader)

   at Lokad.ILPack.IL.MethodBodyReader.GetParameter(Int32 index)
   at Lokad.ILPack.IL.MethodBodyReader.GetVariable(Instruction instruction, Int32 index)
   at Lokad.ILPack.IL.MethodBodyReader.ReadOperand(Instruction instruction)
   at Lokad.ILPack.IL.MethodBodyReader.ReadInstructions()
   at Lokad.ILPack.IL.MethodBodyReader.GetInstructions(MethodBase method)
   at Lokad.ILPack.IL.MethodBaseExtensions.GetInstructions(MethodBase self)
   at Lokad.ILPack.IL.MethodBodyStreamWriter.AddMethodBody(MethodBase methodBase, StandaloneSignatureHandle localVariablesSignature)
   at Lokad.ILPack.AssemblyGenerator.CreateConstructor(ConstructorInfo ctor)
   at Lokad.ILPack.AssemblyGenerator.CreateConstructors(IEnumerable`1 constructors)
   at Lokad.ILPack.AssemblyGenerator.CreateType(Type type)
   at Lokad.ILPack.AssemblyGenerator.CreateTypes(IEnumerable`1 types)
   at Lokad.ILPack.AssemblyGenerator.CreateModules(IEnumerable`1 moduleInfo)
   at Lokad.ILPack.AssemblyGenerator.GenerateAssemblyBytes(Assembly assembly)
   at Lokad.ILPack.AssemblyGenerator.GenerateAssembly(Assembly assembly, String path)

It is basically about that code: https://github.com/Lokad/ILPack/blob/master/src/IL/MethodBodyReader.cs#L177
index is 0, while the ctor is not static, therefore it decrements index to the value of -1, which of course results in a IndexOutOfRangeException.

The constructor is in a sealed class and is basically a passthrough constructor to that one:
https://github.com/Firwood-Software/AdvancedDLSupport/blob/master/AdvancedDLSupport/NativeLibraryBase.cs

I don't exactly know what additional information would be helpful?

Fail to correctly serialize reference to (static) field of generic type

A reference to a (static) field of a generic class is not serialized correctly. A MissingFieldException is thrown by the runtime when executing the serialized code. The issue can be reproduced as follows:

Add a class library to the solution named ReferencedSubject. Then add the following class to this project:

using System;

namespace ReferencedSubject
{
   public static class MyReferencedStaticClass<T>
   {
        public static readonly T Instance;

        static MyReferencedStaticClass()
        {
            MyReferencedStaticClass<T>.Instance = default;
        }
    }
}

The project file will look like this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
     <TargetFrameworks>netcoreapp2.1;netstandard2.0;net46</TargetFrameworks>
  </PropertyGroup>
</Project>

Add a project reference to projects TestSubject and Lokad.ILPack.Tests so that they reference project ReferencedSubject .
Add the directive using ReferencedSubject; and the following property to file MyClass.Properties.cs of project TestSubject:

public string FieldAccessOfReferencedType
{
    get
    {
        return MyReferencedStaticClass<string>.Instance;
    }
}

Finally, add the following test method to file RewriteTest.Properties.cs:

[Fact]
public async void StaticProperty()
{
    Assert.Equal(default(string), await Invoke(
        "",
        "x.FieldAccessOfReferencedType"));
}

Executing this test method produces the following output:

Message: 
  System.MissingFieldException : Field not found: 'ReferencedSubject.MyReferencedStaticClass`1.Instance'.
Stack Trace: 
  MyClass.get_FieldAccessOfReferencedType()
  <<Initialize>>d__0.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
  ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)
  Script`1.RunSubmissionsAsync(ScriptExecutionState executionState, ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, Func`2 catchExceptionOpt, CancellationToken cancellationToken)
  RewriteTest.Invoke(String setup, String resultExpression) line 93
  RewriteTest.StaticProperty() line 35

For static fields of non-generic types the serialized assembly does not cause an exception. I suspect that the field signature is not written correctly. I have not tested this for instance fields, but I'm quite sure the error is not limited to static fields.

Fail to deserialize: volatile field reference

Given

class A 
{ 
   volatile int _vfield; 
}

C# will generate for a._vfield the IL

    IL_0008: volatile.
    IL_000a: ldfld int32 modreq([netstandard]System.Runtime.CompilerServices.IsVolatile) VolatileTest.VolClass::_vfield

ILPack generates:

    IL_0007: ldfld int32 [VolatileTest]VolatileTest.VolClass::_vfield

(You can explicitly add the volatile. instruction -- doesn't matter.)

On load, this fails with a "Field not found" exception.

Support to save dynamic methods

Any chance that ILPack could add support for saving a DynamicMethod to disk in a dll form? This would help in analyzing bugs in lightweight code gen.

Fail to serialize: Referenced assembly cannot be found

The failure of Assembly.GetReferencedAssemblies is hinted at here:

https://github.com/Lokad/ILPack/blob/master/src/Metadata/AssemblyMetadata.cs#L67-L74

In my case, the call to CreateType throws from

https://github.com/Lokad/ILPack/blob/master/src/AssemblyGenerator.Types.cs#L111-114 the error

Referenced assembly cannot be found: System.Linq.Expressions, [...]

In this case, the type is a class A derived from an abstract class B that implements System.Dynamic.IDynamicMetaObjectProvider, which is indeed in System.Linq.Expressions. Assembly.GetReferencedAssemblies does not see this reference, leading ultimately to an exception being thrown from AssemblyMetadata.GetReferencedAssemblyForType(Type type).

Add generics type support

Current codebase does not support generic type definitions. We should add generic type definition support with generic parameter constraints. Also, some unit tests are needed.

Support writing version information

AssemblyBuilder.Save was able to write version informations, such as the file version or the product version and so on. This is missing here.
Do you still work on ILPack? Do you accept pull requests?

(with proposed patch), null dereference in TryGetRawMetadata after removed null check

Hi Vermorel,

I have to propose the following diff/patch. I noticed in TryGetRawMetadata there was a null check on 'pi', which has been removed lately (last few days), what causes problems: RuntimeAssembly.GetRawBytes is not present for me, at least not when working on netstandard2.0.

In order to avoid the null deref, we just can 'return false' or apply the proposed attached patch. Proposed only because I just guess that reading the assembly file is the same than what GetRawBytes would do.

Kindest Regards,
Sascha (mf-RDP).

image

0001-fixes-null-dereference-of-pi-resulting-in-unhandled-.zip

Fail to serialize: Method marked runtime has non-zero RVA

Attempting to serialize a class with a constructor that has the implementation attributes MethodImplAttributes.Runtime | MethodImplAttributes.Managed results in the method in the assembly having a non-zero RVA. PEVerify indicates this error in the written assembly. An attempt to load the assembly and access the type throws an Exception with message "Runtime-implemented method with-zero RVA."

Real example: the constructor on a subclass of MulticastDelegate. Of possible interest: the Invoke method also is "runtime managed" but PEVerify does not flag it.

Undecompilable static constructor involving string field

The following program:

using System;
using System.Reflection;
using System.Reflection.Emit;
using Lokad.ILPack;

namespace ilpack_repro
{
    sealed class Program
    {
        static void Main(string[] args)
        {
            var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
                new AssemblyName { Name = "Jot" },
                AssemblyBuilderAccess.Run);

            var moduleBuilder = assemblyBuilder.DefineDynamicModule("JotModule");

            var myType = moduleBuilder.DefineType(
                "Test.Type",
                TypeAttributes.Public | TypeAttributes.BeforeFieldInit,
                typeof(object),
                Array.Empty<Type>());

            var originalNameField = myType.DefineField(
                fieldName: "StringField",
                type: typeof(string),
                attributes: FieldAttributes.Public
                            | FieldAttributes.Static
                            | FieldAttributes.InitOnly);

            var ctorBuilder = myType.DefineConstructor(
                attributes: MethodAttributes.Public | MethodAttributes.Static,
                callingConvention: CallingConventions.Standard,
                parameterTypes: Array.Empty<Type>());

            var il = ctorBuilder.GetILGenerator();
            il.Emit(OpCodes.Ldstr, "foobar");
            il.Emit(OpCodes.Stfld, originalNameField);
            il.Emit(OpCodes.Ret);


            var finalType = myType.CreateType();

            new AssemblyGenerator().GenerateAssembly(moduleBuilder.Assembly, "C:\\LokadData\\test.dll");
        }
    }
}

generates an assembly where various disassembler (dotnetpeek & ilspy) choke on, there is likely something weird behind it.

Missing method override

Based on #84, it seems that we are not emitting the IL that encodes the overriding behavior of a method.

EmitCalli - aware of any problems?

Hi,

I'm on .NET 5.0, creating some Instructions with EmitCalli, e.g.
il.EmitCalli(OpCodes.Calli, CallingConventions.Standard, null, new Type[1] { typeof(double) }, null);

All were void, no varargs, parameter types primitive + some class.

It seems something gets broken in the code stream.

I can Invoke the dynamically created methods but after writing + reading the serialized assembly I get:

  • InvalidProgramExcn.
  • ILSpy cannot decompile the method. Some blob read errors, I did not yet debug this
    The latter happens only to the two methods (of some hundred) where I did Emit OpCodes.Calli

Many Thanks
Sascha

Any method with a local variable crashes

Adding a reference to the rewritten dll from pull request #43 and calling the IntMethod() crashes with System.InvalidProgramException: Common Language Runtime detected an invalid program.

            var x = new MyClass();
            x.IntMethod();

Looking at the ildasm listing shows the locals haven't been defined. Here's the original (note the .locals line)

.method public hidebysig instance int32 
          IntMethod() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  1
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldc.i4.0
    IL_0002:  stloc.0
    IL_0003:  br.s       IL_0005

    IL_0005:  ldloc.0
    IL_0006:  ret
  } // end of method MyClass::IntMethod

here's the rewritten version: (no .locals)

  .method public hidebysig instance int32 
          IntMethod() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldc.i4.0
    IL_0002:  stloc.0
    IL_0003:  br.s       IL_0005

    IL_0005:  ldloc.0
    IL_0006:  ret
  } // end of method MyClass::IntMethod

Also, .maxstack is different and wondering if this is just a default and if there might be issues if the function needs more than 8??

Unable to generate method body?

I just started using ILPack in a repository of mine, but as soon as I tried to generate an assembly, I started to get this error:

System.Collections.Generic.KeyNotFoundException: The given key 'System.Type GetType()' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Lokad.ILPack.IL.MethodBodyWriter.Write(BlobBuilder writer, IReadOnlyList`1 il, Func`2 getString, IReadOnlyDictionary`2 typeHandles, IReadOnlyDictionary`2 ctorRefHandles, IReadOnlyDictionary`2 fieldHandles, IReadOnlyDictionary`2 methodHandles)
   at Lokad.ILPack.IL.MethodBodyStreamWriter.AddMethodBody(MethodBase methodBase)
   at Lokad.ILPack.AssemblyGenerator.GetOrCreateMethod(MethodInfo methodInfo)
   at Lokad.ILPack.AssemblyGenerator.CreateMethods(MethodInfo[] methods)
   at Lokad.ILPack.AssemblyGenerator.GetOrCreateType(Type type)
   at Lokad.ILPack.AssemblyGenerator.CreateTypes(Type[] types)
   at Lokad.ILPack.AssemblyGenerator.CreateModules(Module[] moduleInfo)
   at Lokad.ILPack.AssemblyGenerator.GenerateAssemblyBytes(Assembly assembly)
   at Lokad.ILPack.AssemblyGenerator.GenerateAssembly(Assembly assembly, String path)
   at Broccoli.CauliflowerInterpreter.<>c.<.cctor>b__48_19(Interpreter cauliflower, IValueExpressible[] args) in /home/nick/Desktop/broccoli/Broccoli/CauliflowerBuiltins.cs:line 1381
   at Broccoli.ShortCircuitFunction.Invoke(Interpreter broccoli, IValueExpressible[] args) in /home/nick/Desktop/broccoli/Broccoli/Function.cs:line 101
   at Broccoli.CauliflowerInterpreter.<>c.<.cctor>b__48_1(Interpreter cauliflower, IValueExpressible[] args) in /home/nick/Desktop/broccoli/Broccoli/CauliflowerBuiltins.cs:line 402
   at Broccoli.ShortCircuitFunction.Invoke(Interpreter broccoli, IValueExpressible[] args) in /home/nick/Desktop/broccoli/Broccoli/Function.cs:line 101
   at Broccoli.CauliflowerInterpreter.Run(IValueExpressible expr) in /home/nick/Desktop/broccoli/Broccoli/Cauliflower.cs:line 52
   at Broccoli.CauliflowerInterpreter.Run(ParseNode node) in /home/nick/Desktop/broccoli/Broccoli/Cauliflower.cs:line 31
   at Broccoli.Program.Main(String[] args) in /home/nick/Desktop/broccoli/Broccoli/Program.cs:line 80

After stepping through with a debugger and whatnot, I figured out that the error is happening when it tries to generate the body for this method, specifically the object#GetType() call.

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.