Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__GNUC__ isn't always defined #7318

Closed
Naville opened this issue Jul 31, 2024 · 3 comments · Fixed by #7337
Closed

__GNUC__ isn't always defined #7318

Naville opened this issue Jul 31, 2024 · 3 comments · Fixed by #7337

Comments

@Naville
Copy link
Contributor

Naville commented Jul 31, 2024

We're cross-compiling Z3 for Windows using MSVC Sysroot and clang-cl on Linux.
The compile steps are fine, but linking would fail due to _tzcnt_u64 symbol not defined.

I'm clueless with how MSVC works, so here are some educated assumptions:
From https://github.com/llvm/llvm-project/blob/07d2709a17860a202d91781769a88837e4fb5f2a/clang/lib/Frontend/InitPreprocessor.cpp#L868 we could see that while __clang__ and __llvm__ are always defined, but __GNUC__ is only defined when building with GNU C Version specified, which is not the case when using Clang-CL.

This results in the following Z3 code:

#if defined(__GNUC__)
and
#if defined(__GNUC__)

falls back to using #define _trailing_zeros**(X) _tzcnt_u**(X)

Grepping through Windows SDK:

WinSDK/VC/Tools/MSVC/14.26.28801/include/immintrin.h:extern unsigned int     _tzcnt_u32(unsigned int);
WinSDK/VC/Tools/MSVC/14.26.28801/include/ammintrin.h:unsigned int _tzcnt_u32(unsigned int);
WinSDK/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x86/c1xx.dll: binary file matches
WinSDK/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x86/c1.dll: binary file matches

We can see that these two builtins are listed as an external function, which makes compilation success.
However without c1xx and c1.dll to lower those intrinsics calls, clang generates them to actual lib call, which fails in linking due to those functions only exists as intrinsics

@Naville
Copy link
Contributor Author

Naville commented Jul 31, 2024

I marked those two checks to check for __clang__ too and it worked. which confirmed my guesses

@Naville
Copy link
Contributor Author

Naville commented Jul 31, 2024

For this specific case, another even better alternative would be using __has_builtin

#if defined __has_builtin
#  if __has_builtin (__builtin_ctz)
#    define _trailing_zeros32(X) __builtin_ctz(X)
# endif
#  if __has_builtin (__builtin_ctzll)
#    define _trailing_zeros64(X) __builtin_ctzll(X)
#  endif
#endif

@Naville Naville changed the title __GNUC__ doesn't always imply __clang__ or __llvm__ defined __GNUC__ isn't always defined Aug 1, 2024
@Naville
Copy link
Contributor Author

Naville commented Aug 8, 2024

ping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant