[Mono-dev] Inline assembly in C#

Miguel de Icaza miguel at microsoft.com
Sun May 28 14:42:34 UTC 2017


Hello team,


For the last couple of nights, this has been bothering me at night time, so I figured I would take this out of my head.


A couple of years ago Paolo put together a design for inline assembly from C#.


At the time, the design had the following constrains:


  *   It had to work with an out-of-the-box C# compiler, no changes to the language were needed.

  *   We wanted a single source file to allow multiple architectures in one place

  *   It was intended to be similar to the way inline assembly works in GNU C: you can drop some assembly language code that can be inlined in the body of a method.

We ended up with something like this that you could insert in your C# code: asm.x64 ("mov $1, rax"), this was a method call in the class "asm" to the method x64 with a string.   Then a post-processor would have to extract the string, use a system assembler and then inject the resulting bytes into the body of the code.   The idea being that this call would be ignored in other platforms, so you could write code like:


// this would be a constant at runtime, so there is no actual probing/branching:

if (asm.x64supported) {

   asm.x64 ("mov $1, rax");

} else if (asm.x86supported) {

   asm.x86 ("mov $1,eax");

} else if (asm.ppcsupported){

   asm.ppc ("li r3,1");

}


The post-processor had to rewrite calls to asm.x64 (string) with asm.x64 (token) and inject the blob with the assembly code with the token inside.

Now that Mono is switching to platform-specific assemblies for the core assemblies as opposed to cross-platform assemblies that work across Windows, Mac and Linux (a price we pay to converge with CoreFX) it made me wonder if we could not reuse instead the existing support for mixed-mode assemblies in the CLR.

Essentially, instead of having inline assembly in the body of a method, we could define entire method as inline assembly, and set the method implementation flags in the ECMA metadata to be native and point to the code.   It is not as flexible, but would eliminate the need for a post-processor, and would merely require the C# compiler to perform the assembly code generation and injection.

This would require some changes to the language, but it would look something like this:


public int ReturnOne ()  {

   x86 {

      mov $1, rax

   }

   ppc {

      li r3, 1

   }

}

The difference being that we would be doing assembly-language blocks at the method level.

This does not solve the issue of which assembler to use, nor which style of assembly to use.

What we had considered in the past is to take a dependency on the LLVM assembler, another option was to write our own assembler in managed code to reduce the dependencies.

The assembly style comes down to whether we want raw assembly language, or we want a Go-like assembly language, where they introduced sort of an abstraction layer to the underlying assembly language exposing things like "MOV" as an operation, regardless of what the actual underlying platform likes to call their stuff.

Miguel.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dot.net/pipermail/mono-devel-list/attachments/20170528/6f4c4779/attachment.html>


More information about the Mono-devel-list mailing list