<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/59038>59038</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            llvm-mc miscompiles some indirect jumps and calls in Intel syntax
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          LegionMammal978
      </td>
    </tr>
</table>

<pre>
    As a minimal example:
```asm
.intel_syntax noprefix
.text
jmp [addr]
.data
addr: .4byte 0x01234567
```

This is the observed output from `llvm-mc --arch=x86 --filetype=obj -o=example.o example.s` (commit e989b8bb5fb36abac6e8f82809f06144dd762113), using `objdump -dr`:
```
example.o:     file format elf32-i386


Disassembly of section .text:

00000000 <.text>:
   0:   e9 fc ff ff ff          jmp    1 <.text+0x1>
                        1: R_386_PC32   .data
```

But this is the expected output from `as -o example.o --32 example.s` (binutils 2.38-4ubuntu2):
```
example.o:     file format elf32-i386


Disassembly of section .text:

00000000 <.text>:
   0:   ff 25 00 00 00 00       jmp    *0x0
                        2: R_386_32     .data
```

llvm-mc is converting the indirect `jmp [addr]` to a direct `jmp addr`, contrary to GNU as. This issue extends to all absolute indirect jumps and calls which refer to a displacement with no segment override.

In particular, llvm-mc produces direct jumps and calls for these syntaxes, contrary to GNU as:
```asm
jmp [addr]
jmp word ptr addr
jmp word ptr [addr]
jmp dword ptr addr   // 32-bit
jmp dword ptr [addr] // 32-bit
jmp qword ptr addr   // 64-bit
jmp qword ptr [addr] // 64-bit
jmp fword ptr addr
jmp fword ptr [addr]
call [addr]
call word ptr addr
call word ptr [addr]
call dword ptr addr   // 32-bit
call dword ptr [addr] // 32-bit
call qword ptr addr   // 64-bit
call qword ptr [addr] // 64-bit
call fword ptr addr
call fword ptr [addr]
```

(As a side note, GNU as recognizes these syntaxes, but llvm-mc does not:)
```asm
jmp near [addr]
jmp near ptr addr // direct
jmp near ptr ds:addr
jmp near ptr [addr]
jmp near ptr ds:[addr]
jmp far [addr]
jmp far ptr ds:addr
jmp far ptr [addr]
jmp far ptr ds:[addr]
call near [addr]
call near ptr addr // direct
call near ptr ds:addr
call near ptr [addr]
call near ptr ds:[addr]
call far [addr]
call far ptr ds:addr
call far ptr [addr]
call far ptr ds:[addr]
```

This issue can also be observed from inline assembly in C. This program compiles and runs successfully with `gcc -m32 -masm=intel -no-pie -o example example.c`, but produces a segmentation fault with `clang -m32 -masm=intel -no-pie -o example example.c`:
```c
#include <stdio.h>

static void target(void) {
    puts("Hello, world!");
}
void (*target_addr)(void) = target;

void indirect(void);
__asm__ (
    ".text\n"
    "indirect:\n\t"
    "jmp [target_addr]"
);

int main(void) {
    indirect();
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzNV0uvqzYQ_jVkMwLxSAhZZJGT9LRXaquq6l1HBpvER8am2Jyb9Nd3bAghCYmOuipCJHjG8_jm4SFX9LzeaCBQcckrIoCdSFUL5iUbL9x54cZLw-4muupWAi4NE3t9loacQKq6YSU_9TTDTqb7-1HV4C3eCKWNt9j1ZEoM6f669WQDwTw_GwbhKYziZL5Il3dq-1f3_OvINeBtjgxUrlnzySio1tStgbJRFSC_EJ-VXxXg-6Qpjl6yO2UpvpRcMHOu0a-dyj_AV_indzVQF6cDjQLAi7NCVRU3wFbZKs_yfFHmSUpyUqQsK7M4C1dlmEbzOaXLNI6ixItXXryFVnN5sDagBtqi-z66iB48QNm9DuotDPayNkKpmoqgalEmsc-TLB0D0D13XBOtWZWLM6gSNCsMVxI67JMb1rC_wEu2Pf2ngQVVdsat2ArKAsqyv7sL120M8Yqu2-O38BRZIb2SVXdH1oc_92ju_o9tEuPKKNSTsXzDmJlRPNmpRj8e40k0BguuofL9JH6IV85la7jQEAdJ5s_bvJWmjW1Y_v_YI97xApBtuG-w9-IN1sYd3PEV7i-BfSkKxLpQ8pM1xmaqhZ1Lyht0wkJ9V7EIrVHYGW4ZHBWlY76jKNOQ5mzZfv79OxAdQF-iurURNUxS7YQIASTXSrRmpPIDawRbj6RQIIOGH0deHAG7CWsumnUtSMEqJg384OaI3QYhP7h3hW40nLJg7Og3CTVB74pWkMbaePG8bhRtC6bhiW4MvcVDM-j6GtPTHr7oi1MNz679UA2F2jQddI_LU3vozSaXBu94A-Zlzs0U31XKM96_n8hM58_4HmXe85ZPnCufemfhnl6cEHW7PrnrK0jdMb6GyjF_Bas7xtdgOeYptO4I9z5OljN2PHdma0x_LAnDbK52-YnlU6iD5P8wPZHPOTbWS0VQhSy42WY0NsoXSS0Zmc5SRxhA6r3uCmyCidriuU2TgfZSuts4xVE-sat8rrF8obB8pc_FaRKJK-UVFLdcd5bdEl8reG7dFBwD4ZnWZ4A8bvxSao76f0EkNn6tIB9Na-5Y51JwyWA4SLmEbX90YJ8-NKTCzlvVeCR3LbpppQbdFti_ddkK3OEOA1R9KHDSq3Ai8CubssnOzabgS-XXnI0mh2FkKPrDy5bCcCiQy6lC3GleklaYQUchCB6W_0HLw1FRXMo34bIQLRYvjgbaUK6C42imsk9tTSngU3EKhjQHhqNXZt-wVsFbvg1TBOCwhLWdeXH8CxNCWd-wmwhkjHDNzUA9t7fsI-ekuj2bTvbeBdZOsVcdye6ieNh_3Xw5w68bBq79HjHa7538wUi0pBuBFltprRoTBlk2xZC82Jp7lv5oHRuLWXhhuvHRPTE-UBEun2E2Mn8SoCFiM7aO0jRL4-VinszoOqGrZEVmhhvB1pdOWnE9pKtW1YsJBxP9m0udrinP2kasj8bUrrxczzhg0rV5gPLwxSrof3zM1Q9n8burLgz5-2IVJtnsuF6GJUvCPEtXUbZkGVlQGs_ny_k8LfOYZtFMkJwJvUYEEbYZX8dhjJ8tURqhM2ESEJrnLMvwgyaNSppTbx4yRE8EVnGgmsOs6XzN24NGouDa6CsRy5gfJGMX-aQ1R9Wsf2UHrKXfSIVflatlNnNmr53N_wIiDE-H">