<p dir="auto">Hi!</p>
<p dir="auto">Rust ends with an illegal instruction error when I try to compile this:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="let mut c: u64;
asm!(&quot;&quot; : &quot;=m&quot; (c));"><pre class="notranslate"><span class="pl-k">let</span> <span class="pl-k">mut</span> c<span class="pl-kos">:</span> <span class="pl-smi">u64</span><span class="pl-kos">;</span>
<span class="pl-en">asm</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">""</span> : <span class="pl-s">"=m"</span> <span class="pl-kos">(</span>c<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Maybe because it generates wrong LLVM IR.</p>
<p dir="auto">Rust/LLVM IR:</p>
<div class="highlight highlight-source-llvm notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="%1 = call i64 asm &quot;&quot;, &quot;=m,~{dirflag},~{fpsr},~{flags}&quot;(), !srcloc !0
store i64 %1, i64* %c"><pre class="notranslate"><span class="pl-c1">%1</span> = <span class="pl-k">call</span> <span class="pl-k">i64</span> <span class="pl-k">asm</span> <span class="pl-s">""</span>, <span class="pl-s">"=m,~{dirflag},~{fpsr},~{flags}"</span>(), <span class="pl-v">!srcloc</span> <span class="pl-v">!0</span>
<span class="pl-k">store</span> <span class="pl-k">i64</span> <span class="pl-c1">%1</span>, <span class="pl-k">i64*</span> <span class="pl-c1">%c</span></pre></div>
<p dir="auto">Clang/LLVM IR:</p>
<div class="highlight highlight-source-llvm notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="call void asm &quot;&quot;, &quot;=*m,~{dirflag},~{fpsr},~{flags}&quot;(i64* %c) #1, !srcloc !1"><pre class="notranslate"><span class="pl-k">call</span> <span class="pl-k">void</span> <span class="pl-k">asm</span> <span class="pl-s">""</span>, <span class="pl-s">"=*m,~{dirflag},~{fpsr},~{flags}"</span>(<span class="pl-k">i64*</span> <span class="pl-c1">%c</span>) #<span class="pl-c1">1</span>, <span class="pl-v">!srcloc</span> <span class="pl-v">!1</span></pre></div>
<h2 dir="auto">Meta</h2>
<p dir="auto"><code class="notranslate">rustc --version --verbose</code>:<br>
rustc 1.1.0-dev (<a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/rust-lang/rust/commit/2214860d4a979fe24d935277a74bd4d67e9bdb9f/hovercard" href="https://github.com/rust-lang/rust/commit/2214860d4a979fe24d935277a74bd4d67e9bdb9f"><tt>2214860</tt></a> 2015-04-24) (built 2015-04-25)<br>
binary: rustc<br>
commit-hash: <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/rust-lang/rust/commit/2214860d4a979fe24d935277a74bd4d67e9bdb9f/hovercard" href="https://github.com/rust-lang/rust/commit/2214860d4a979fe24d935277a74bd4d67e9bdb9f"><tt>2214860</tt></a><br>
commit-date: 2015-04-24<br>
build-date: 2015-04-25<br>
host: x86_64-unknown-linux-gnu<br>
release: 1.1.0-dev</p>
<p dir="auto"><code class="notranslate">clang --version</code>:<br>
Ubuntu clang version 3.6.0-2ubuntu1 (tags/RELEASE_360/final) (based on LLVM 3.6.0)<br>
Target: x86_64-pc-linux-gnu<br>
Thread model: posix</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#![feature(asm)]

fn main() {
    let foo = 42u;
    unsafe { asm!(&quot;lea rax, $0&quot; :: &quot;m&quot;(foo) : &quot;rax&quot; : &quot;intel&quot;); }
}"><pre class="notranslate"><span class="pl-c1">#!<span class="pl-kos">[</span>feature<span class="pl-kos">(</span>asm<span class="pl-kos">)</span><span class="pl-kos">]</span></span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> foo = <span class="pl-c1">42</span>u<span class="pl-kos">;</span>
    <span class="pl-k">unsafe</span> <span class="pl-kos">{</span> <span class="pl-en">asm</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"lea rax, $0"</span> :: <span class="pl-s">"m"</span><span class="pl-kos">(</span>foo<span class="pl-kos">)</span> : <span class="pl-s">"rax"</span> : <span class="pl-s">"intel"</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Expected result: <code class="notranslate">rax</code> contains the address of <code class="notranslate">foo</code></p>
<p dir="auto">However:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="unknown operand type!
UNREACHABLE executed at /build/buildd/rust-nightly-201408090406~39bafb0~trusty/src/llvm/lib/Target/X86/X86AsmPrinter.cpp:208!
Aborted (core dumped)"><pre class="notranslate"><code class="notranslate">unknown operand type!
UNREACHABLE executed at /build/buildd/rust-nightly-201408090406~39bafb0~trusty/src/llvm/lib/Target/X86/X86AsmPrinter.cpp:208!
Aborted (core dumped)
</code></pre></div>
<p dir="auto">Using a struct instead of an <code class="notranslate">uint</code>:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#![feature(asm)]

struct Foo(u64, u64);

fn main() {
    let foo = Foo(42, 1337);
    unsafe { asm!(&quot;lea rax, $0&quot; :: &quot;m&quot;(foo) : &quot;rax&quot; : &quot;intel&quot;); }
}"><pre class="notranslate"><span class="pl-c1">#!<span class="pl-kos">[</span>feature<span class="pl-kos">(</span>asm<span class="pl-kos">)</span><span class="pl-kos">]</span></span>

<span class="pl-k">struct</span> <span class="pl-smi">Foo</span><span class="pl-kos">(</span><span class="pl-smi">u64</span><span class="pl-kos">,</span> <span class="pl-smi">u64</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> foo = <span class="pl-v">Foo</span><span class="pl-kos">(</span><span class="pl-c1">42</span><span class="pl-kos">,</span> <span class="pl-c1">1337</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">unsafe</span> <span class="pl-kos">{</span> <span class="pl-en">asm</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"lea rax, $0"</span> :: <span class="pl-s">"m"</span><span class="pl-kos">(</span>foo<span class="pl-kos">)</span> : <span class="pl-s">"rax"</span> : <span class="pl-s">"intel"</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Now the compiler doesn't crash. But the emitted <code class="notranslate">lea</code> instruction references the memory location of the address of <code class="notranslate">foo</code> instead of <code class="notranslate">foo</code> itself:</p>
<div class="highlight highlight-source-assembly notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="; create foo
mov    QWORD PTR [rbp-0x10],0x2a
mov    QWORD PTR [rbp-0x8],0x539

; the (broken) implementation of the &quot;m&quot; constraint
lea    rax,[rbp-0x10] ; this instruction should not be emitted
mov    QWORD PTR [rbp-0x18],rax ; this instruction should not be emitted

 ; the actual inline asm
lea    rax,[rbp-0x18] ; this should be: lea rax, [rbp-0x10]"><pre class="notranslate"><span class="pl-c">; create foo</span>
<span class="pl-k">mov</span><span class="pl-en">    QWORD PTR </span><span class="pl-s1">[</span><span class="pl-v">rbp</span><span class="pl-s1">-</span><span class="pl-c1">0x10</span><span class="pl-s1">],</span><span class="pl-c1">0x2a</span>
<span class="pl-k">mov</span><span class="pl-en">    QWORD PTR </span><span class="pl-s1">[</span><span class="pl-v">rbp</span><span class="pl-s1">-</span><span class="pl-c1">0x8</span><span class="pl-s1">],</span><span class="pl-c1">0x539</span>

<span class="pl-c">; the (broken) implementation of the "m" constraint</span>
<span class="pl-k">lea</span><span class="pl-en">    </span><span class="pl-v">rax</span><span class="pl-s1">,[</span><span class="pl-v">rbp</span><span class="pl-s1">-</span><span class="pl-c1">0x10</span><span class="pl-s1">]</span><span class="pl-c"> ; this instruction should not be emitted</span>
<span class="pl-k">mov</span><span class="pl-en">    QWORD PTR </span><span class="pl-s1">[</span><span class="pl-v">rbp</span><span class="pl-s1">-</span><span class="pl-c1">0x18</span><span class="pl-s1">],</span><span class="pl-v">rax</span><span class="pl-c"> ; this instruction should not be emitted</span>

<span class="pl-c"> ; the actual inline asm</span>
<span class="pl-k">lea</span><span class="pl-en">    </span><span class="pl-v">rax</span><span class="pl-s1">,[</span><span class="pl-v">rbp</span><span class="pl-s1">-</span><span class="pl-c1">0x18</span><span class="pl-s1">]</span><span class="pl-c"> ; this should be: lea rax, [rbp-0x10]</span></pre></div>
<p dir="auto">So basically <code class="notranslate">"m"(foo)</code> generates the code for <code class="notranslate">"m"(&amp;foo)</code> if <code class="notranslate">foo</code> is a struct.</p>