Skip to content

Clang-Cl __declspec(naked) inline assembly fails with __declspec(dllimport) while MSVC succeeds #106887

Open
@higher-performance

Description

@higher-performance

(I'm not sure if this issue is 1 bug underneath, or 2 bugs.)

Godbolt link

If you call a dllimport function from a naked assembly function on x86:

__declspec(dllimport) void bar();
__declspec(naked) void foo()
{
	__asm
	{
		mov eax, 0
		mov ebx, 0
		mov ecx, 0
		mov edx, 0
		mov esi, 0
		mov edi, 0
		jmp bar
	}
}

this causes Clang to attempt to pick an unused general-purpose register to load the associated __imp_... symbol into, before the naked body executes.

  1. The fact that Clang even attempts to do this is itself a bug, because naked's entire purpose is to avoid extra instructions from being inserted into the function in the first place. This causes registers to be clobbered that the callees don't expect!

  2. In the above example, Clang's attempt fails, because it fails to find an unused general-purpose register. (Whereas if you comment out one of the movs, it succeeds.) It therefore errors, when it shouldn't:

<source>(5,9): error: inline assembly requires more registers than available
    5 |         __asm
      |         ^

In fact, MSVC compiles this entirely correctly, as intended:

?foo@@YAXXZ PROC
	mov eax, 0
	mov ebx, 0
	mov ecx, 0
	mov edx, 0
	mov esi, 0
	mov edi, 0
	jmp (null) PTR __imp_?bar@@YAXXZ
?foo@@YAXXZ ENDP

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang-cl`clang-cl` driver. Don't use for other compiler parts

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions