Skip to content

aizen218/VMBytecode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VMBytecode

.NET 10 IL virtualization library. Mark methods with [Virtualize] — the build pipeline automatically translates their CIL to a custom VM bytecode and replaces the original method bodies before AOT compilation.

Works with NativeAOT. Zero warnings on dotnet publish /p:PublishAot=true.


How it works

C# source
  │
  ▼  CoreCompile
  IL (readable in ILSpy)
  │
  ▼  VMBytecodeWeave  (AfterTargets="CoreCompile", BeforeTargets="ILLink")
  IL stubs  →  VMDispatcher.Execute(__vmBody, args[])
  VM bytecode stored as byte[] in static fields (not human-readable)
  │
  ▼  ILLink (trimmer)  →  ILCompiler (AOT)
  native binary

The weaver runs as an MSBuild task using Mono.Cecil. It:

  1. Finds all methods tagged [Virtualize]
  2. Translates their CIL to a custom stack-based VM instruction set
  3. Injects AOT-safe call stubs (concrete static methods, no reflection)
  4. Replaces the original method bodies with VMDispatcher.Execute() calls

Usage

Add the reference to your project:

<ItemGroup>
  <PackageReference Include="VMBytecode.Weaver" Version="1.0.0" />
</ItemGroup>

The .targets file inside the package wires the weave step automatically. Tag any method you want to protect:

using VMBytecode;

public class MyService
{
    [Virtualize]
    public int SecretAlgorithm(int input)
    {
        return input * 42 + 7;
    }

    [Virtualize]
    public bool Validate(string key)
    {
        // your logic here
        return key.Length > 8 && key[0] == 'K';
    }
}

Build and publish normally:

# Debug run
dotnet run

# AOT publish
dotnet publish -r linux-x64 -c Release

What ILSpy sees after weaving

Before:

public int Fibonacci(int n)
{
    if (n <= 1) return n;
    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

After:

public int Fibonacci(int n)
{
    return (int)VMDispatcher.Execute(__vmBody_Fibonacci_3, new object[] { this, n });
}

The original logic lives only inside __vmBody_Fibonacci_3 as an opaque byte[].


Project structure

src/
  VMBytecode.Runtime/       Core VM — ships with your app (AOT-safe)
    VirtualizeAttribute.cs  [Virtualize] attribute
    VMOpcode.cs             Custom instruction set
    VMMethodBody.cs         Bytecode + resolved call/field/type tables
    VMDispatcher.cs         Stack-based interpreter

  VMBytecode.Weaver/        MSBuild task — build-time only, not shipped
    WeaverTask.cs           MSBuild Task entry point
    ILTranslator.cs         CIL → VM bytecode (2-pass branch fixup)
    build/
      VMBytecode.Weaver.targets   Auto-imported MSBuild hook

samples/
  SampleApp/                Demo project

Supported CIL operations

Category Operations
Constants ldc.i4, ldc.i8, ldc.r4, ldc.r8, ldstr, ldnull
Args / Locals ldarg, starg, ldloc, stloc
Fields ldfld, stfld, ldsfld, stsfld
Arithmetic add, sub, mul, div, rem, neg
Bitwise and, or, xor, not, shl, shr, shr.un
Comparisons ceq, clt, cgt, clt.un, cgt.un
Branches br, brtrue, brfalse, beq, bne, blt, bgt, ble, bge (and .un variants)
Calls call, callvirt, newobj, ret
Arrays newarr, ldelem, stelem, ldlen
Conversions conv.i1/i2/i4/i8/u1/u2/u4/u8/r4/r8
Type ops box, unbox.any, castclass, isinst
Misc dup, pop, throw, switch, initobj

AOT compatibility

Concern Status
No Reflection.Emit / DynamicMethod
Call stubs are concrete static methods (ldftn) ✅ trimmer-safe
Type references use ldtoken + Type.GetTypeFromHandle
[UnconditionalSuppressMessage] injected into weaved methods
ILLink + ILCompiler see weaved IL, never original

Tested: dotnet publish -r linux-x64 /p:PublishAot=true0 AOT warnings.


MSBuild properties

Property Default Description
VMBytecodeWeaveEnabled true Set to false to skip weaving (e.g. during debugging)
VMBytecodeVerbose false Log each virtualized method name during build
<!-- Disable weaving for Debug config only -->
<VMBytecodeWeaveEnabled Condition="'$(Configuration)' == 'Debug'">false</VMBytecodeWeaveEnabled>

Requirements

  • .NET 10 SDK
  • Mono.Cecil 0.11.6 (weaver dependency, not shipped to end users)

Building from source

git clone https://github.com/aizen218/VMBytecode
cd VMBytecode
dotnet build
dotnet run --project samples/SampleApp

About

.NET 10 IL virtualization library. Mark methods with `[Virtualize]` — the build pipeline automatically translates their CIL to a custom VM bytecode and replaces the original method bodies before AOT compilation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages