Issue
From the following link, https://www.ibm.com/developerworks/library/l-ia/index.html
a single variable may serve as both the input and the output operand.
I wrote the following code:
#include <stdio.h>
int main()
{
int num = 1;
asm volatile ("incl %0"
:"=a"(num)
:"0"(num));
printf("num:%d\n", num);
return 0;
}
The above code increments the value of num.
What is the use of matching constraints, if i don't use matching constraints, the code does not work as expected.
asm volatile ("incl %0"
:"=a"(num));
Solution
why and when should we use matching constraints
That's not the question you asked; you asked why you need an input at all, which should be fairly obvious when you know what the syntax actually means. (That "=r"(var)
is a pure output, independent of any previous value the C variable had, like var = 123;
would be). So "=r"
with an inc
instruction is like var = stale_garbage + 1;
But anyway, as I commented, the interesting question is "why do matching constraints exist when you can just use "+r"(var)
for a read/write operand, instead of the more complicated matching-constraint syntax?"
They're rarely useful; usually you can use the same variable for input and output especially if you have your asm inside a C wrapper function. But if you don't want to use the same C var for input and output, but still need them to pick the same register or memory, then you want a matching constraint. One use-case might be wrapping a system call is one use-case; you might want to use a different C variable for the call number vs. the return value. (Except you could just use "=a"
and "a"
instead of a matching constraint; the compiler doesn't have a choice.) Or maybe an output var of a narrower or different type than the input var could be another use-case.
IIRC, x87 is another use-case; I seem to recall "+t"
not working.
I think that "+r"
RMW constraints are internally implemented as an output with a "hidden" matching constraint. But while %1
normally errors in an asm template that only has one operand, if that operand is an in/out "+something"
then GCC doesn't reject %1
as being too high an operand number. And if you look at the asm to see which register or memory it actually chose for that out-of-bounds operand number, it does match the in/out operand.
So "+r"
is basically syntactic sugar for matching constraints. I'm not sure if it was new at some point, and before GCC version x.y you had to use matching constraints? It's not rare to see tutorial examples that use matching constraints with the same var for both input and output that would simpler to read with "+"
RMW constraints.
Basics:
With constraints like "a"
and "=a"
you don't need a matching constraint; the compiler only has 1 choice anyway. Where it's useful is "=r"
where the compiler could pick any register, and you need it to pick the same register for an input operand.
If you just used "=r"
and a separate "r"
input, you'd be telling the compiler that it can use this as a copy-and-whatever operation, leaving the original input unmodified and producing the output in a new register. Or overwriting the input if it wants to. That would be appropriate for lea 1(%[srcreg]), %[dstreg]
but not inc %0
. The latter would assume that %0 and %1 are the same register, therefore you need to do something to make sure that's true!
Answered By - Peter Cordes