Skip to content

\@ in two inline assembly expressions are parsed in isolation; so may lead to the same value, different from GCC #60792

Open
@andyhhp

Description

@andyhhp

\@ is the macro expansion count, and is supposed to be unique in each expansion inside a translation unit. It is commonly used to generate unique local named labels.

However, Clang IAS doesn't get this quite right. https://godbolt.org/z/reedx7Gsr

Given:

asm ("toplevel:\n\t"
     ".macro M\n\t"
     ".L\\@: add $\\@, %eax\n\t"
     ".endm\n\t");

asm ("M"); // \@ = 0
asm ("M"); // \@ = 1

void a(void)
{
    asm ("M"); // \@ should be 2, actually 0
    asm ("M"); // \@ should be 3, actually 0
}

GCC/Binutils, and Clang without IAS (not surprising - it hands of to GAS) expand M with 4 different numbers. However, Clang IAS does something a bit more weird.

(warning - stdout and stderr are mixed in the following transcript, but it's reasonably easy to follow)

$ clang -S m.c -o /dev/stdout 
	.text
	.file	"m.c"
                                        # Start of file scope inline assembly
toplevel:


.L0:
	addl	$0, %eax

.L1:
	addl	$1, %eax


                                        # End of file scope inline assembly
	.globl	a                       # -- Begin function a
	.p2align	4, 0x90
	.type	a,@function
a:                                      # @a
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	#APP
<instantiation>:1:1: error: invalid symbol redefinition
.L0: add $0, %eax
^
.L0:
	addl	$0, %eax

	#NO_APP
	#APP
<instantiation>:1:1: error: invalid symbol redefinition
.L0: add $0, %eax
^
.L0:
	addl	$0, %eax

	#NO_APP
	popq	%rbp
	.cfi_def_cfa %rsp, 8
	retq
.Lfunc_end0:
	.size	a, .Lfunc_end0-a
	.cfi_endproc
                                        # -- End function
	.ident	"clang version 10.0.0-4ubuntu1 "
	.section	".note.GNU-stack","",@progbits
	.addrsig
2 errors generated.

At the top level, it maintains an incrementing expansion count across separate asm(), so the 0 and 1 case expand correctly. However, when we come to the first asm() in a(), the expansion count resets back to 0.

This causes what should be unique local symbols to not be unique, and then suffer error: invalid symbol redefinition.

For completeness, the second asm() in a() also resets back to 0 again, which is why we end up with two duplicate symbol redefinitions.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions