<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Clang considers extended asm empty input constraint to be invalid"
href="https://bugs.llvm.org/show_bug.cgi?id=48605">48605</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Clang considers extended asm empty input constraint to be invalid
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>-New Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>nsajko@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>The issue is that Clang does not accept the GCC extended asm empty input
constraint, giving the error "error: invalid input constraint '' in asm".
Note that <a href="https://clang.llvm.org/compatibility.html#inline-asm">https://clang.llvm.org/compatibility.html#inline-asm</a> says that all
constraints allowed by GCC are also allowed by Clang:
<span class="quote">> In general, Clang is highly compatible with the GCC inline assembly extensions, allowing the same set of constraints, modifiers and operands as GCC inline assembly.</span >
The use case for this feature is when the user wants to prevent the compiler
from optimizing away a piece of code (the relevant asm declaration effectively
pretends to be a live store), but without causing unnecessary additional code
generation. This is desirable in, e.g., benchmarking and testing.
The following code should illustrate the issue and the desired behavior:
<span class="quote">> #include <vector></span >
>
<span class="quote">> int
> main() {
> // Greater than or equal to zero.
> constexpr int asmV = ASM_V;</span >
>
<span class="quote">> std::vector<char> v{7, 6, 9, 3, 2, 0};
> for (int i{0}; i < (1 << 28); i++) {
> for (int j{0}; j < 6; j++) {
> v[j]++;</span >
>
<span class="quote">> if constexpr (1 <= asmV) {
> asm volatile ("" :: ""(v.size()));
> for (auto x: v) {
> asm volatile ("" :: ""(x));
> }
> }
> if constexpr (2 <= asmV) {
> asm volatile ("" :: ""(v.size()));
> for (auto x: v) {
> asm volatile ("" :: ""(x));
> }
> }
> if constexpr (3 <= asmV) {
> asm volatile ("" :: ""(v.size()));
> for (auto x: v) {
> asm volatile ("" :: ""(x));
> }
> }
> }
> }</span >
>
<span class="quote">> return 0;
> }</span >
Built with (try replacing "=0" with "=1", "=2", "=3":
<span class="quote">> clang++ clang++ -std=c++20 -D ASM_V=0 asm.cc</span >
This is the Radare2 graph view of the disassembly for the main function with
ASM_V defined as 1, 2 or 3:
[0x00001050]> 0x1050 # int main (int argc, char **argv, char **envp);
┌─────────────────────────────────────────────────────┐
│ [0x1050] │
│ ; [13] -r-x section size 517 named .text │
│ ; DATA XREF from entry0 @ 0x1101 │
│ ;-- section..text: │
│ ;-- .text: │
│ 129: int main (int argc, char **argv, char **envp); │
│ movl $6, %edi │
│ subq $8, %rsp │
│ callq sym operator new(unsigned long);[oa] │
│ ; [0x3090607:4]=-1 │
│ movl $0x3090607, (%rax) │
│ movq %rax, %r9 │
│ movl $2, %eax │
│ movw %ax, 4(%r9) │
│ movl $0x10000000, %r10d │
│ movl $6, %r8d │
│ movl $9, %edi │
│ movl $3, %esi │
│ movl $2, %ecx │
│ xorl %edx, %edx │
│ nop │
└─────────────────────────────────────────────────────┘
v
│
└──────────────────────┐
│
│
│
┌──────────┘
┌───────────────────┐
│ │ │
│ ┌────────────────────────────────┐
│ │ 0x1090 [oc] │
│ │ ; CODE XREF from main @ 0x10bb │
│ │ movzbl (%r9), %eax │
│ │ incl %eax │
│ │ movb %al, (%r9) │
│ │ incl %r8d │
│ │ movb %r8b, 1(%r9) │
│ │ incl %edi │
│ │ movb %dil, 2(%r9) │
│ │ incl %esi │
│ │ movb %sil, 3(%r9) │
│ │ incl %ecx │
│ │ movb %cl, 4(%r9) │
│ │ incl %edx │
│ │ movb %dl, 5(%r9) │
│ │ decl %r10d │
│ │ jne 0x1090 │
│ └────────────────────────────────┘
│ f t
│ │ │
└─────────────────────┘
┌──────────────┘
│
┌──────────────────────────────────────────────────────┐
│ 0x10bd [oe] │
│ movl $6, %esi │
│ movq %r9, %rdi │
│ callq sym operator delete(void*, unsigned long);[od] │
│ xorl %eax, %eax │
│ addq $8, %rsp │
│ retq │
└──────────────────────────────────────────────────────┘
This is the main function with ASM_V defined as 0, notice how the loop is gone:
[0x00001050]> 0x1050 # int main (int argc, char **argv, char **envp);
┌──────────────────────────────────────────────────────┐
│ [0x1050] │
│ ; [13] -r-x section size 437 named .text │
│ ; DATA XREF from entry0 @ 0x10b1 │
│ ;-- section..text: │
│ ;-- .text: │
│ 49: int main (int argc, char **argv, char **envp); │
│ subq $8, %rsp │
│ movl $6, %edi │
│ callq sym operator new(unsigned long);[oa] │
│ ; [0x3090607:4]=-1 │
│ movl $0x3090607, (%rax) │
│ movq %rax, %rdi │
│ movl $2, %eax │
│ movw %ax, 4(%rdi) │
│ movl $6, %esi │
│ callq sym operator delete(void*, unsigned long);[ob] │
│ xorl %eax, %eax │
│ addq $8, %rsp │
│ retq │
└──────────────────────────────────────────────────────┘</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>