Improper code for _byteswap_uint64() with clang-cl - visual-c++

If I use the _byteswap_uint64() intrinsic of MSVC with the mostly MSVC compatible compiler clang-cl the code generates a call to the external library function _byteswap_uint64() which does the well known mask and shift orgy. Whith MSVC I simply get a x86 BSWAP instruction which is there since the 486 so there shouldn't be any processor optimization level relevant here. clang-cl understands a lot of command line options MSVC doesn't understand, even -march=native. So if I have -march=native the code is still a call to the mentioned function.
I use clang-cl 13 through the IDE (installed from the Visual Studio installer).
Is there a way to get proper code like with MSVC ?

I've got it. Simply use the clang specific intrinsics with conditional compilation:
#include <cstdint>
#include <intrin.h>
uint64_t swapThis( uint64_t value )
{
#if defined(__llvm__)
return __builtin_bswap64( value );
#elif defined(_MSC_VER)
return _byteswap_uint64( value );
#endif
}
clang_ isn't defined with clang-cl under Windows but only with clang++ under Windows, so I had to use _llvm.

Related

Which library do I have to link for the GNU libc extension tdestroy

I am trying to link a c program that I compiled with the gcc compiler. The linker does not find the symbol tdestroy which is a gnu extension to libc (#define __USE_GNU followed by #include <search.h>). Is there an additional library that I have to link with in order for the linker to find this symbol?
~Update~: I just realized that it does indeed link on my Linux environment but on Windows, I still get a undefined reference to 'tdestroy' error with mingw/gcc, even after using _GNU_SOURCE instead of __USE_GNU.
Don't use __USE_GNU. That's an internal GLIBc macro. The tdestroy man page says the macro you need
to define at the beginning is _GNU_SOURCE.
#define _GNU_SOURCE
#include <search.h>
void *td = tdestroy;
int main(){}
compiles with no linker error (no extra libraries needed).
You should never define __USE_GNU (sic), it is an internal symbol. You need to define _GNU_SOURCE, see Feature Test Macros.
If you do that, the tdestroy function will become available.
It is also a good idea to build with -Werror=implicit-function-declaration, so that missing prototypes lead to a compiler failure, and not later to a linker failure.

wchar_t is not treated as built-in type even when the option is enabled

So here is the preprocessed output of a struct:
typedef struct RPT_Item
{
wchar_t *fullPath;
RPT_ItemFlags_t itemFlags;
int isComposite;
const void *reserved;
} RPT_Item_t;
Visual Studio complains because wchar_t is not defined, its own cryptic way:
error C2016: C requires that a struct or union has at least one member
I looked at the project files and also at the particular C file where the error appears and I can confirm that "Treat wchar_t as built-in type is set to YES".
If I define the type using a typedef it compiles fine.
I used the preprocessor output so I can exclude that some nasty preprocessor #define trick play the main role.
This project contains many low-level hacks, for example the CRT is not linked (/NODEFAULTLIB).
Most of the code is not written by me, and I'm tasked to remove reference to wchar.h from a public header that uses wchar_t, because VS treats it as a built in type default. (This particular module is built only on Windows.)
I totally ran out of ideas. Is there a compiler option or a pragma that can interfere? Or could it be even a compiler bug?
Microsoft didn't explicitly document this until VS 2013, but the docs for /Zc:wchar_t says
The wchar_t type is not supported when you compile C code.
It seems that including nearly any header from the runtime or from the SDK will typedef wchar_t tounsigned short using the following sequence:
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
you might want to do something similar in your file that uses wchar_t.
Note that when compiling a C++ file, if /Zc:wchar_t is in effect then the compiler pre-defines _WCHAR_T_DEFINED. If /Zc:wchar_t- is in effect it doesn't - so the above snippet should work nicely with C++ as well (for MSVC anyway - I don't know how other compilers might deal with this if you're looking for something portable).
The _WCHAR_T_DEFINED macro is documented:
MSVC Predefined Macros

How to check compiler at compile time?

If I'm going to disable warnings specific to compiler say VC++ and run this:
#pragma warning( disable : xxxx )
on comeau or g++, how do i make sure the preprocessor won't be executed it?
To detect the MSVC compiler you can see if _MSC_VER is defined so you could do something like
#ifdef _MSC_VER
#pragma warning( disable : xxxx )
#endif
Predefined Macros gives information about predefined VS macros
See this resource for a list of macros to identify which compiler is being used. Use them as follows (for MS VC):
#ifdef _MSC_VER
#pragma warning( disable : xxxx )
#endif

Standard Template Library using g++

While migrating a program from windows in linux I encountered a problem using the c++ standard template library. I am trying to typedef a template and I am getting the error 'expected initializer before '<' token on this line
typedef std::list< std::pair< int,double> > PairList;
Any ideas why this would work using mvc++ and not using g++ and how I can fix it?
I think this is about #includes.
The following really minimal piece of code compiles perfectly here with g++ on Linux
#include <utility>
#include <list>
typedef std::list< std::pair< int,double> > PairList;
PairList x;
One thing to remember about standard include files is that they are allowed but not required to call each other. (It's not like they're potentially polluting the namespace by this, since they all use namespace std, which you aren't supposed to mess with.)
It is possible that, in MSVC++, includes , or vice versa, but this is not the case in the g++ headers. Therefore, a program might compile in MSVC++ and not in g++, with a required header missing in the source.
Make sure all of your required headers are actually included, and you should be fine.
Did you #include <utility> for pair?
I have had no problems with the code in G++, and generally found its STL support to be superb. Do you have all the #include directives there? Sometimes those differ from platform to platform (even when they shouldn't).

OpenMP in Visual Studio 2005 Standard

I have used OpenMP with gcc for writing parallel code. I am now using Visual C++ 2005 and am trying to figure out how to use OpenMP. There is a compiler option in the Properties->C/C++/Language menu but then it complains the library is missing. Is there a 3rd party implementation for OpenMP or am i just configuring Visual C++ incorrectly?
After some research I found out that the OpenMP libs and dlls are not included with Visual C++ 2005 or Visual C++ Express Edition 2008. But with a few workarounds you can get it working.
First you need to download the lib files from microsoft which can be found at the Windows SDK for Windows Server 2008 and .NET framework 3.5. After you download it you need to make sure that either vcomp.lib or vcompd.lib is being linked to your program.
Next you need to have the dll which can be found in the Visual C++ Redistributable Packkage. Then make sure that vcomp90.dll is somewhere in your path.
You also need to have the OpenMP compiler option enabled which can be found in the Properties->C/C++/Language menu of Visual C++.
After that you should be able to use OpenMP just fine.
I think t works out of the box with VC 2005 but I am not sure if they are provided with all versions.
If you jsut attach the
/openmp
option you also have to include the open mp header
#include <omp.h>
This is important because this header will add the manifest to your application which
enables it to load the vcomp.dll from the correct system path. So it is normally no longer
allowed to copy vcomp.dll or other system dlls beneath your executable but you have to pimp the manifest of your application to load the dll from the correct location.
This is none automatically by the omp.h header.
So the minimum code if you do not want to modyfy your manifest on your own is:
#include <omp.h> // has to include this header to build the correct manifest to find vcom.dll or vcompd.dll
int main(int argc, char* argv[])
{
double sum;
#pragma omp parallel for
for(int i = 0; i < 10000; ++i) {
}
return 0;
}
You need to add:
/openmp
To your compiler options.
More information is available on MSDN

Resources