[RFC] Syncing Asm Goto with Outputs with GCC

Clang’s extension of “asm goto” to support output constraints prompted GCC to
do the same. However, there are some differences between the two
implementations. In particular, GCC allows output constraints to be used on the
indirect branches, while Clang doesn’t.

GCC’s implementation of inline assembly is typically seen as the definitive
implementation. So I believe that we should sync our implementation to align
with GCC’s implementation.

The main difference between Clang’s and GCC’s implementations is how C labels
are handled. Clang allows them to be treated as data. GCC does to a certain
extent, but doesn’t guarantee that the value for a specific label will be the
same in all cases. This was the main reason why Clang chose not to support
output constraints on indirect branches.

Here’s a simple example.

$ cat asm-goto.c
int foo(int a)
{
	int b = 0;

	if (a)
		asm goto ("mov %l1, %0" : "=r" (b) : : : err);
	else
		asm goto ("mov %l1, %0" : "=r" (b) : : : err);

	return b;
err:
	return b;
}

GCC emits this:

$ gcc -o - -S asm-goto.c -O2
	.file	"asm-goto.c"
	.text
	.p2align 4
	.globl	foo
	.type	foo, @function
foo:
.LFB0:
	.cfi_startproc
	testl	%edi, %edi
	je	.L2
#APP
# 6 "asm-goto.c" 1
	mov .L3, %eax
# 0 "" 2
#NO_APP
.L3:
	ret
	.p2align 4,,10
	.p2align 3
.L2:
#APP
# 8 "asm-goto.c" 1
	mov .L5, %eax
# 0 "" 2
#NO_APP
.L5:
	ret
	.cfi_endproc
.LFE0:
	.size	foo, .-foo
	.ident	"GCC: (Debian 12.2.0-1) 12.2.0"
	.section	.note.GNU-stack,"",@progbits

Note that even though the original “asm goto” statements refer to the same C
label, the values stored in “b” aren’t the same.

Implementation

Clang doesn’t have a restriction from using the output of an asm goto on the
indirect branch. I.e., there’s nothing that checks and warns about doing so.
The bulk of the implementation work will be in verifying that the code Clang
emits is correct for all situations. Given how asm goto is implemented in LLVM,
most changes will be in the back-end. (I know this is a bit hand-wavy, but it’s
difficult to estimate how much work it will take until implementation starts.)

-bw

We’ve basically already moved away from the whole “labels as data” thing, in anticipation of this, and because blockaddresses are hard to optimize. clang doesn’t emit blockaddresses for asm goto anymore. Given we’ve already done that, supporting the gcc semantics is basically just implementation work; there aren’t any interesting semantic questions.

Overall, the proposal seems fine.

Completely agree. My naïve wish is that it will “just work” with only a few kinks to work out.