{"id":44813,"date":"2015-01-28T07:00:00","date_gmt":"2015-01-28T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2015\/01\/28\/the-compiler-can-make-up-its-own-calling-conventions-within-limits\/"},"modified":"2019-03-13T12:12:23","modified_gmt":"2019-03-13T19:12:23","slug":"20150128-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20150128-00\/?p=44813","title":{"rendered":"The compiler can make up its own calling conventions, within limits"},"content":{"rendered":"<p>A customer was confused by what they were seeing when debugging. <\/p>\n<blockquote CLASS=\"q\">\n<p>It is our understanding that the Windows x86-64 calling convention passes the first four parameters in registers <code>rcx<\/code>, <code>rdx<\/code>, <code>r8<\/code>, and <code>r9<\/code>. But we&#8217;re seeing the parameters being passed some other way. Given the function prototype <\/p>\n<pre>\nint LogFile::Open(wchar_t *path, LogFileInfo *info, bool verbose);\n<\/pre>\n<p>we would expect to see the parameters passed as <\/p>\n<ul>\n<li><code>rcx<\/code> = <code>this<\/code> \n<li><code>rdx<\/code> = <code>path<\/code> \n<li><code>r8<\/code> = <code>info<\/code> \n<li><code>r9<\/code> = <code>verbose<\/code> <\/ul>\n<p>but instead we&#8217;re seeing this: <\/p>\n<pre>\nrax=0000000001399020 rbx=0000000003baf238 rcx=00000000013c3260\nrdx=0000000003baf158 rsi=000000000139abf0 rdi=00000000013c3260\nrip=00007ffd69b71724 rsp=0000000003baf038 rbp=0000000003baf0d1\nr8=0000000001377870  r9=0000000000000000 r10=000000007fffffb9\nr11=00007ffd69af08e8 r12=00000000013a3b80 r13=0000000000000000\nr14=0000000001399010 r15=00000000013a3b90\ncontoso!LogFile::Open:\n00007ffd`69b71724 fff3        push rbx\n0:001&gt; du @rdx          \/\/ path should be in rdx\n00000000`03baf158  \"`\"\n0:001&gt; du @r8           \/\/ but instead it's in r8\n00000000`01377870  \"C:\\Logs\\Contoso.txt\"\n<\/pre>\n<p>Is our understanding of the calling convention incomplete? <\/p>\n<\/blockquote>\n<p>There are three parties to a calling convention. <\/p>\n<ol>\n<li>The function doing the calling. \n<li>The function being called. \n<li>The operating system. <\/ol>\n<p>The operating system needs to get involved if something unusual occurs, like an exception, and it needs to go walking up the stack looking for a handler. <\/p>\n<p>The catch is that if a compiler knows that it controls all the callers of a function, then it can modify the calling convention as long as the modified convention still observes the operating system rules. After all, the operating system doesn&#8217;t see your source code. As long as the object code satisfies the calling convention rules, everything is fine. (This typically means that the modification needs to respect unwind codes and stack usage.) <\/p>\n<p>For example, suppose you had code like this: <\/p>\n<pre>\nextern void bar(int b, int a);\n\nstatic void foo(int a, int b)\n{\n  return bar(b + 1, a);\n}\n\nint __cdecl main(int argc, char **argv)\n{\n foo(10, 20);\n foo(30, 40);\n return 0;\n}\n<\/pre>\n<p>A clever compiler could make the following analysis: Since <code>foo<\/code> is a static function, it can be called only from this file. And in this file, the address of the function is never taken, so the compiler knows that it controls all the callers. Therefore, it optimizes the function <code>foo<\/code> by rewriting it as <\/p>\n<pre>\nstatic void foo(<font COLOR=\"blue\">int b, int a<\/font>)\n{\n  return bar(b + 1, a);\n}\n<\/pre>\n<p>It makes corresponding changes to main: <\/p>\n<pre>\nint __cdecl main(int argc, char *argv)\n{\n <font COLOR=\"blue\">foo(20, 10); \/\/ flip the parameters\n foo(40, 30); \/\/ flip the parameters<\/font>\n return 0;\n}\n<\/pre>\n<p>By doing this, the compiler can generate the code for <code>foo<\/code> like this: <\/p>\n<pre>\nfoo:\n        inc     ecx\n        jmp     bar\n<\/pre>\n<p>rather than the more conventional <\/p>\n<pre>\nfoo:\n        mov     eax, edx\n        inc     eax\n        mov     ecx, edx\n        mov     edx, eax\n        jmp     bar\n<\/pre>\n<p>You can look at this transformation in one of two ways. You can say, &#8220;The compiler rewrote my function prototype to be more efficient.&#8221; Or you can say, &#8220;The compiler is using a custom calling convention for <code>foo<\/code> which passes the parameters in reverse order.&#8221; <\/p>\n<p>Both interpretations are just two ways of viewing the same thing. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Global optimizations.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-44813","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Global optimizations.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44813","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=44813"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44813\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=44813"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=44813"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=44813"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}