Inline assembly in C#

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Inline assembly in C#

Alexander Köplinger via Mono-devel-list

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.


_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Alexander Köplinger via Mono-devel-list

I keep thinking about this.

 

I suspect having our own assembler over using LLVM’s assembles has one advantage, we could provide syntax that allows for convenient access of parameters, some globals and some parameters.

 

Miguel.

 

From: Miguel de Icaza <[hidden email]>
Date: Sunday, May 28, 2017 at 10:42 AM
To: "[hidden email]" <[hidden email]>
Subject: Inline assembly in C#

 

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.


_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Jonathan Pryor
Reply inline:

On May 30, 2017, at 11:38 AM, Martin Baulig <[hidden email]> wrote:
> First thing that came to my mind when I read this was how this could possibly be exploited – wouldn’t it cause all kinds of security risks to have unverifiable native code in some assembly?

I think this is no different, security-wise, from writing “unsafe” code or code using IntPtrs or code using P/Invokes or…

It can *absolutely* be exploited and can be a problem, but I think it’s no different from the multitude of existing problems that our existing environment permits.

- Jon

_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Jonathan Pryor
In reply to this post by Alexander Köplinger via Mono-devel-list
Reply inline:

On May 28, 2017, at 10:42 AM, Miguel de Icaza via Mono-devel-list <[hidden email]> wrote:
...

> 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
>    }
> }

Much as I’d hate to start syntax bikeshedding, I don’t like this syntax:

1. It makes it hard to easily grep for uses of inline assembly
2. I think it would require too much “architecture hardcoding” into the compiler
3. As-is, I don’t see how I could provide an “IL fallback” path

(1) and (2) could be solved by using `asm “architecture”` instead:

        asm “x86” {mov $1, rax}

but that leaves (3): how do you support conditional code flow between inline-assembly and “normal” code? How could you have a “fallback” codepath?

The original class-based design supported this:

        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”);
        else {
                // new/unknown architecture; write the code in IL
        }

I can think of two ways to support IL fallbacks:

1. Treat “asm architecture” as an `if`, allowing `else asm:

        asm “x86” { mov $1, rax }
        else asm “ppc” {li r3, 1}
        else { /* IL */ }

2. Instead of `asm architecture`, rely on conditional compilation:

        #if x86
                asm { mov $1, rax }
        #elif ppc
                asm { li r3, 1 }
        #else
                /* new/unknown arch; default IL fallback */
        #endif

This could get ugly quick, but perhaps such ugliness is a *good* thing?

Additionally, “IL fallback” isn’t *just* for IL fallbacks; it’s for *intermixing* inline assembly with normal code within the same body.

Finally, methods should be marked as `unsafe` in order to use inline assembly.

 - Jon

_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Alexander Köplinger via Mono-devel-list
This would actually be a *very* useful tool, even on Windows.

If you made it so whatever pseudo-library got linked returned false for
all of these (and NotSupportedException if assembly was attempted to be
used), if the preprocessor was never run, everything would use the
fallback. This would also make the fallback get testing.

Being able to test for architecture *in a normal, code-based way* is
really important. It isn't just processors. What about SSE, AVX, etc.?
Weird blocks x86 { } ppc { } etc. look pretty but are a million times
worse. Don't choose a platform for me. That's brittle.

For my part, I'd love to be able to embed vector instructions in C# for
various code hotspots, but I'd like to keep my assembly entirely
platform independent otherwise. I would do this by if () around various
platform tests before getting into the serious part of the loop. The
problem with the Mono vector types, when they existed, was typing.
Assembly nicely avoids that.

James


On 5/30/2017 12:16 PM, Jonathan Pryor wrote:
> The original class-based design supported this:
>
> 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”);
> else {
> // new/unknown architecture; write the code in IL
> }
>


On 5/30/2017 12:16 PM, Jonathan Pryor wrote:

> Reply inline:
>
> On May 28, 2017, at 10:42 AM, Miguel de Icaza via Mono-devel-list <[hidden email]> wrote:
> ...
>> 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
>>     }
>> }
> Much as I’d hate to start syntax bikeshedding, I don’t like this syntax:
>
> 1. It makes it hard to easily grep for uses of inline assembly
> 2. I think it would require too much “architecture hardcoding” into the compiler
> 3. As-is, I don’t see how I could provide an “IL fallback” path
>
> (1) and (2) could be solved by using `asm “architecture”` instead:
>
> asm “x86” {mov $1, rax}
>
> but that leaves (3): how do you support conditional code flow between inline-assembly and “normal” code? How could you have a “fallback” codepath?
>
> The original class-based design supported this:
>
> 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”);
> else {
> // new/unknown architecture; write the code in IL
> }
>
> I can think of two ways to support IL fallbacks:
>
> 1. Treat “asm architecture” as an `if`, allowing `else asm:
>
> asm “x86” { mov $1, rax }
> else asm “ppc” {li r3, 1}
> else { /* IL */ }
>
> 2. Instead of `asm architecture`, rely on conditional compilation:
>
> #if x86
> asm { mov $1, rax }
> #elif ppc
> asm { li r3, 1 }
> #else
> /* new/unknown arch; default IL fallback */
> #endif
>
> This could get ugly quick, but perhaps such ugliness is a *good* thing?
>
> Additionally, “IL fallback” isn’t *just* for IL fallbacks; it’s for *intermixing* inline assembly with normal code within the same body.
>
> Finally, methods should be marked as `unsafe` in order to use inline assembly.
>
>   - Jon
>
> _______________________________________________
> Mono-devel-list mailing list
> [hidden email]
> http://lists.dot.net/mailman/listinfo/mono-devel-list

_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Vincent Povirk-2
In reply to this post by Alexander Köplinger via Mono-devel-list
> 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.

What you're suggesting are architecture-specific assemblies, not
platform-specific. So you would be multiplying the platform variations
by the set of architecture variations.

This would be a problem for Wine Mono's use case. Currently we can use
one set of class libraries with 32-bit and 64-bit Mono dll's. We would
need a mechanism to load some different class libraries based on
architecture.

> 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.

You would also have to extend the Mono runtime to support mixed-mode
assemblies on non-Windows platforms.
_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Alexander Köplinger via Mono-devel-list
Hello,

These are good observations.    If we ever do this (I am not saying we are, I just wanted to get this off my head), we would indeed require assemblies for 32/64 on the same system.

Any work that we did to support inline assembly would need some extra work on the runtime, so adding support for mixed-mode execution would fall into the sort of work we would need to do.

Anyways, this is a very good catch, and it means that the original design was probably best.   And it is still an independent issue from having an inline assembler in place.

Miguel.

On 5/30/17, 1:58 PM, "Vincent Povirk" <[hidden email]> wrote:

    > 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.
   
    What you're suggesting are architecture-specific assemblies, not
    platform-specific. So you would be multiplying the platform variations
    by the set of architecture variations.
   
    This would be a problem for Wine Mono's use case. Currently we can use
    one set of class libraries with 32-bit and 64-bit Mono dll's. We would
    need a mechanism to load some different class libraries based on
    architecture.
   
    > 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.
   
    You would also have to extend the Mono runtime to support mixed-mode
    assemblies on non-Windows platforms.
   

_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Alexander Köplinger via Mono-devel-list
Would this be AOT-only? And should a method be allowed to contain a mix of
inline assembly and managed code? These greatly affect whatever design we
might come up with.

If assembly can appear anywhere in a managed method, you need something
like the GCC extended asm notation so you can specify inputs, outputs, and
clobbers to determine things like addressing modes and register allocation
for the surrounding code. It¹s also useful to have ³volatile² (don¹t move
this) and ³goto² (may jump to managed label), but these are maybe less
critical.

I would be in favor of the simpler alternative of restricting inline
assembly to a whole method:

    public unsafe __asm__(x86_64) int ReturnOne ()  {
        "movl $1, %rax"
    }

    public unsafe __asm__(ppc) int ReturnOne () {
        "li r3, 1"
    }

    public __asm__ int ReturnOne () {
        return 1;
    }


The idea is that when you compile (AOT) or load+compile (JIT) this
assembly on x86-64, the __asm__(x86_64) method is selected and the
__asm__(ppc) method is ignored entirely; if you¹re compiling on neither
x86-64 nor PowerPC, the managed fallback is chosen. I suppose the fallback
could also be written in IL:

    public unsafe __asm__(cil) int ReturnOne () {
        "ldc.i4 1"
        "ret"
    }


However, this comes at the cost of some expressiveness and inhibits
optimisations.


On 6/1/17, 6:59 AM, "Mono-devel-list on behalf of Miguel de Icaza via
Mono-devel-list" <[hidden email] on behalf of
[hidden email]> wrote:

>Hello,
>
>These are good observations.    If we ever do this (I am not saying we
>are, I just wanted to get this off my head), we would indeed require
>assemblies for 32/64 on the same system.
>
>Any work that we did to support inline assembly would need some extra
>work on the runtime, so adding support for mixed-mode execution would
>fall into the sort of work we would need to do.
>
>Anyways, this is a very good catch, and it means that the original design
>was probably best.   And it is still an independent issue from having an
>inline assembler in place.
>
>Miguel.
>
>On 5/30/17, 1:58 PM, "Vincent Povirk" <[hidden email]> wrote:
>
>    > 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.
>    
>    What you're suggesting are architecture-specific assemblies, not
>    platform-specific. So you would be multiplying the platform variations
>    by the set of architecture variations.
>    
>    This would be a problem for Wine Mono's use case. Currently we can use
>    one set of class libraries with 32-bit and 64-bit Mono dll's. We would
>    need a mechanism to load some different class libraries based on
>    architecture.
>    
>    > 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.
>    
>    You would also have to extend the Mono runtime to support mixed-mode
>    assemblies on non-Windows platforms.
>    
>
>_______________________________________________
>Mono-devel-list mailing list
>[hidden email]
>https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.dot.
>net%2Fmailman%2Flistinfo%2Fmono-devel-list&data=02%7C01%7Cjopur%40microsof
>t.com%7C8ded07862a7b48c9590608d4a8f667e9%7C72f988bf86f141af91ab2d7cd011db4
>7%7C1%7C0%7C636319223645828454&sdata=4JueGESfWp8sLKAYXKibnUTZQNu1NBcsPwmpB
>lWtaTg%3D&reserved=0

_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Alexander Köplinger via Mono-devel-list
Please make it so all platforms can be embedded in the same assembly.
Separate compilation is a mess. And it's not as simple as 'x86-64' vs
'ppc'. Different CPUs have different instructions.

I can figure out which to call on my own. If I know it's x86-64, beyond
that, one can do tests and build a library to test for additional CPU
features.

A method that just takes pointers, even, would be completely usable for
any game.  Incidentally, if they could all be embedded in this manner,
it'd make SIMD much more powerful and frankly, even be useful outside of
Mono, on Windows.

James


On 6/2/2017 5:49 PM, Jon Purdy via Mono-devel-list wrote:

> Would this be AOT-only? And should a method be allowed to contain a mix of
> inline assembly and managed code? These greatly affect whatever design we
> might come up with.
>
> If assembly can appear anywhere in a managed method, you need something
> like the GCC extended asm notation so you can specify inputs, outputs, and
> clobbers to determine things like addressing modes and register allocation
> for the surrounding code. It¹s also useful to have ³volatile² (don¹t move
> this) and ³goto² (may jump to managed label), but these are maybe less
> critical.
>
> I would be in favor of the simpler alternative of restricting inline
> assembly to a whole method:
>
>      public unsafe __asm__(x86_64) int ReturnOne ()  {
>          "movl $1, %rax"
>      }
>
>      public unsafe __asm__(ppc) int ReturnOne () {
>          "li r3, 1"
>      }
>
>      public __asm__ int ReturnOne () {
>          return 1;
>      }
>
>
> The idea is that when you compile (AOT) or load+compile (JIT) this
> assembly on x86-64, the __asm__(x86_64) method is selected and the
> __asm__(ppc) method is ignored entirely; if you¹re compiling on neither
> x86-64 nor PowerPC, the managed fallback is chosen. I suppose the fallback
> could also be written in IL:
>
>      public unsafe __asm__(cil) int ReturnOne () {
>          "ldc.i4 1"
>          "ret"
>      }
>
>
> However, this comes at the cost of some expressiveness and inhibits
> optimisations.
>
>
> On 6/1/17, 6:59 AM, "Mono-devel-list on behalf of Miguel de Icaza via
> Mono-devel-list" <[hidden email] on behalf of
> [hidden email]> wrote:
>
>> Hello,
>>
>> These are good observations.    If we ever do this (I am not saying we
>> are, I just wanted to get this off my head), we would indeed require
>> assemblies for 32/64 on the same system.
>>
>> Any work that we did to support inline assembly would need some extra
>> work on the runtime, so adding support for mixed-mode execution would
>> fall into the sort of work we would need to do.
>>
>> Anyways, this is a very good catch, and it means that the original design
>> was probably best.   And it is still an independent issue from having an
>> inline assembler in place.
>>
>> Miguel.
>>
>> On 5/30/17, 1:58 PM, "Vincent Povirk" <[hidden email]> wrote:
>>
>>     > 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.
>>    
>>     What you're suggesting are architecture-specific assemblies, not
>>     platform-specific. So you would be multiplying the platform variations
>>     by the set of architecture variations.
>>    
>>     This would be a problem for Wine Mono's use case. Currently we can use
>>     one set of class libraries with 32-bit and 64-bit Mono dll's. We would
>>     need a mechanism to load some different class libraries based on
>>     architecture.
>>    
>>     > 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.
>>    
>>     You would also have to extend the Mono runtime to support mixed-mode
>>     assemblies on non-Windows platforms.
>>    
>>
>> _______________________________________________
>> Mono-devel-list mailing list
>> [hidden email]
>> https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.dot.
>> net%2Fmailman%2Flistinfo%2Fmono-devel-list&data=02%7C01%7Cjopur%40microsof
>> t.com%7C8ded07862a7b48c9590608d4a8f667e9%7C72f988bf86f141af91ab2d7cd011db4
>> 7%7C1%7C0%7C636319223645828454&sdata=4JueGESfWp8sLKAYXKibnUTZQNu1NBcsPwmpB
>> lWtaTg%3D&reserved=0
> _______________________________________________
> Mono-devel-list mailing list
> [hidden email]
> http://lists.dot.net/mailman/listinfo/mono-devel-list

_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inline assembly in C#

Alexander Köplinger via Mono-devel-list
In reply to this post by Alexander Köplinger via Mono-devel-list

If we ever build this, I do not think it should be AOT only.


Inline assembly in a method has the problems that you outlined, namely that we do need to sort out input/output/clobbers.   By isolating this to a method, we can just say "These are the Mono calling conventions, follow these".


The inline method as well as my original proposal have one advantage: both of them can be implemented without requiring changes to the metadata format, the former by having the JIT recognize a special method call sequence, and the latter by leveraging the existing mixed-mode execution that is supported in the file format.   


Your new proposal would allow us to provide multiple implementations, but would require either a file format change.   


Perhaps what we could do is flag the method with "RTSPECIALNAME" or "SPECIALNAME" when we do inline assembly, and only when this flag is set, we could trigger a slower method lookup system that lookups the real method based on the architecture.


So you would write:


public unsafe asm(x86) ReturnOne () { movl $1, %rax }

public unsafe asm(ppc) ReturnOne () { li r3, 1 }

public unsafe asm(default) ReturnOne () { return 1; }


The compiler would generate x86_ReturnOne, ppc_ReturnOne and ReturnOne, the last one with "SPECIALNAME" set and an attribute [AsmImplementations(x86,ppc)] which would trigger the runtime to resolve the call to the right method.


That sounds like it would address all the requirements.


Sent from Outlook


From: Jon Purdy
Sent: Friday, June 2, 2017 4:49:04 PM
To: Miguel de Icaza
Cc: [hidden email]
Subject: Re: [Mono-dev] Inline assembly in C#
 
Would this be AOT-only? And should a method be allowed to contain a mix of
inline assembly and managed code? These greatly affect whatever design we
might come up with.

If assembly can appear anywhere in a managed method, you need something
like the GCC extended asm notation so you can specify inputs, outputs, and
clobbers to determine things like addressing modes and register allocation
for the surrounding code. It¹s also useful to have ³volatile² (don¹t move
this) and ³goto² (may jump to managed label), but these are maybe less
critical.

I would be in favor of the simpler alternative of restricting inline
assembly to a whole method:

    public unsafe __asm__(x86_64) int ReturnOne ()  {
        "movl $1, %rax"
    }

    public unsafe __asm__(ppc) int ReturnOne () {
        "li r3, 1"
    }

    public __asm__ int ReturnOne () {
        return 1;
    }


The idea is that when you compile (AOT) or load+compile (JIT) this
assembly on x86-64, the __asm__(x86_64) method is selected and the
__asm__(ppc) method is ignored entirely; if you¹re compiling on neither
x86-64 nor PowerPC, the managed fallback is chosen. I suppose the fallback
could also be written in IL:

    public unsafe __asm__(cil) int ReturnOne () {
        "ldc.i4 1"
        "ret"
    }


However, this comes at the cost of some expressiveness and inhibits
optimisations.


On 6/1/17, 6:59 AM, "Mono-devel-list on behalf of Miguel de Icaza via
Mono-devel-list" <[hidden email] on behalf of
[hidden email]> wrote:

>Hello,
>
>These are good observations.    If we ever do this (I am not saying we
>are, I just wanted to get this off my head), we would indeed require
>assemblies for 32/64 on the same system.
>
>Any work that we did to support inline assembly would need some extra
>work on the runtime, so adding support for mixed-mode execution would
>fall into the sort of work we would need to do.
>
>Anyways, this is a very good catch, and it means that the original design
>was probably best.   And it is still an independent issue from having an
>inline assembler in place.
>
>Miguel.
>
>On 5/30/17, 1:58 PM, "Vincent Povirk" <[hidden email]> wrote:
>
>    > 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.
>   
>    What you're suggesting are architecture-specific assemblies, not
>    platform-specific. So you would be multiplying the platform variations
>    by the set of architecture variations.
>   
>    This would be a problem for Wine Mono's use case. Currently we can use
>    one set of class libraries with 32-bit and 64-bit Mono dll's. We would
>    need a mechanism to load some different class libraries based on
>    architecture.
>   
>    > 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.
>   
>    You would also have to extend the Mono runtime to support mixed-mode
>    assemblies on non-Windows platforms.
>   
>
>_______________________________________________
>Mono-devel-list mailing list
>[hidden email]
>https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.dot.
>net%2Fmailman%2Flistinfo%2Fmono-devel-list&data=02%7C01%7Cjopur%40microsof
>t.com%7C8ded07862a7b48c9590608d4a8f667e9%7C72f988bf86f141af91ab2d7cd011db4
>7%7C1%7C0%7C636319223645828454&sdata=4JueGESfWp8sLKAYXKibnUTZQNu1NBcsPwmpB
>lWtaTg%3D&reserved=0


_______________________________________________
Mono-devel-list mailing list
[hidden email]
http://lists.dot.net/mailman/listinfo/mono-devel-list
Loading...