{"id":3198,"date":"2010-11-26T17:04:00","date_gmt":"2010-11-26T17:04:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/subterranean-il-custom-modifiers\/"},"modified":"2021-04-29T15:30:55","modified_gmt":"2021-04-29T15:30:55","slug":"subterranean-il-custom-modifiers","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/subterranean-il-custom-modifiers\/","title":{"rendered":"Subterranean IL: Custom modifiers"},"content":{"rendered":"<p>In IL, <code>volatile<\/code> is an instruction prefix used to set a memory barrier at that instruction. However, in C#, <code>volatile<\/code> is applied to a field to indicate that all accesses on that field should be prefixed with <code>volatile<\/code>. As I mentioned in my previous post, this means that the field definition needs to store this information somehow, as such a field could be accessed from another assembly. However, IL does not have a concept of a &#8216;volatile field&#8217;. How is this information stored?<\/p>\n<p><b>Attributes<\/b><\/p>\n<p>The standard way of solving this is to apply a <code>VolatileAttribute<\/code> or similar to the field; this extra metadata notifies the C# compiler that all loads and stores to that field should use the <code>volatile<\/code> prefix. However, there is a problem with this approach, namely, the .NET C++ compiler. C++ allows methods to be overloaded using properties, like <code>volatile<\/code> or <code>const<\/code>, on the parameters; this is perfectly legal C++: <\/p>\n<pre>public ref class VolatileMethods {\n    void Method(int *i) {}\n    void Method(volatile int *i) {}\n}<\/pre>\n<p> If <code>volatile<\/code> was specified using a custom attribute, then the <code>VolatileMethods<\/code> class wouldn&#8217;t be compilable to IL, as there is nothing to differentiate the two methods from each other. This is where custom modifiers come in.<\/p>\n<p><b>Custom modifiers<\/b><\/p>\n<p>Custom modifiers are similar to custom attributes, but instead of being applied to an IL element separately to its declaration, they are embedded within the field or parameter&#8217;s type signature itself. The <code>VolatileMethods<\/code> class would be compiled to the following IL: <\/p>\n<pre>.class public VolatileMethods {\n    .method public instance void Method(int32* i) {}\n    .method public instance void Method(\n        int32 modreq(        [mscorlib]System.Runtime.CompilerServices.IsVolatile)* i) {}\n}<\/pre>\n<p> The <code>modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile)<\/code> is the custom modifier. This adds a <code>TypeDef<\/code> or <code>TypeRef<\/code> token to the signature of the field or parameter, and even though they are mostly ignored by the CLR when it&#8217;s executing the program, this allows methods and fields to be overloaded in ways that wouldn&#8217;t be allowed using attributes. Because the modifiers are part of the signature, they need to be fully specified when calling such a method in IL: <\/p>\n<pre>call instance void Method(\n    int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile)*)<\/pre>\n<\/p>\n<p>There are two ways of applying modifiers; <code>modreq<\/code> specifies required modifiers (like <code>IsVolatile<\/code>), and <code>modopt<\/code> specifies optional modifiers that can be ignored by compilers (like <code>IsLong<\/code> or <code>IsConst<\/code>). The type specified as the modifier argument are simple placeholders; if you have a look at the definitions of <code>IsVolatile<\/code> and <code>IsLong<\/code> they are completely empty. They exist solely to be referenced by a modifier.<\/p>\n<p>Custom modifiers are used extensively by the C++ compiler to specify concepts that aren&#8217;t expressible in IL, but still need to be taken into account when calling method overloads.<\/p>\n<p><b>C++ and C#<\/b><\/p>\n<p>That&#8217;s all very well and good, but how does this affect C#? Well, the C++ compiler uses <code>modreq(IsVolatile)<\/code> to specify volatility on both method parameters and fields, as it would be slightly odd to have the same concept represented using a modifier or attribute depending on what it was applied to. Once you&#8217;ve compiled your C++ project, it can then be referenced and used from C#, so the C# compiler has to recognise the <code>modreq(IsVolatile)<\/code> custom modifier applied to fields, and vice versa.<\/p>\n<p>So, even though you can&#8217;t overload fields or parameters with <code>volatile<\/code> using C#, <code>volatile<\/code> needs to be expressed using a custom modifier rather than an attribute to guarentee correct interoperability and behaviour with any C++ dlls that happen to come along.<\/p>\n<p><a href=\"https:\/\/www.simple-talk.com\/community\/blogs\/simonc\/archive\/2010\/11\/30\/95936.aspx\">Next up<\/a>: a closer look at attributes, and how certain attributes compile in unexpected ways.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In IL, volatile is an instruction prefix used to set a memory barrier at that instruction. However, in C#, volatile is applied to a field to indicate that all accesses on that field should be prefixed with volatile. As I mentioned in my previous post, this means that the field definition needs to store this&#8230;&hellip;<\/p>\n","protected":false},"author":186659,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,2],"tags":[],"coauthors":[],"class_list":["post-3198","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/186659"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3198"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3198\/revisions"}],"predecessor-version":[{"id":75609,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3198\/revisions\/75609"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3198"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}