[cfe-dev] clang not observing -fno-signed-char, and other triple realted issues

Reid Kleckner via cfe-dev cfe-dev at lists.llvm.org
Thu Dec 3 13:54:55 PST 2020

1. Re: funsigned-char, it seems to work for me:

$ cat t.cpp
static_assert((int)((char)255) == 255, "char should be unsigned");

$ clang -c --target=x86_64-windows-windows-gnu -funsigned-char t.cpp
# success

Removing the flag makes it fail.

2. The meaning of the "ABI" part of the triple

I had not encountered that CrossCompiling.rst document until today. This is
what I see in the Triple.h document:
In the code, the fourth component is referred to as the "environment". The
environment is kind of a catch-all extension of the triple, which normally
has three components: ISA, vendor, OS. The environment allows some more
target customization, and everyone uses it for different purposes. I think
it's hard to come up with a unified theory of what the triple environment
really is. As you can see, we encode the MSVC CRT version in there, because
sometimes the backend needs to know it. Some targets have an object file
format override in the environment. You can see this in triples that end in
-elf or -macho.

So, to answer your question about what part of the triple controls the
object file format, there's no real good answer. It's not a well designed
piece of infrastructure. :( Mainly, though, it's the OS that defines the
object file format.

For Windows, there are two main environments: msvc and gnu. Both use COFF
objects, but with slightly different contents. Generally, for plain C code,
VC link.exe can handle GNU COFF objects. However, if you start doing
interesting things (C++, __attribute__((weak)), some other things)
eventually you will run into some incompatibilities. If you plan to use the
Visual C++ linker, I would recommend using the msvc environment.

3. __chkstk_ms

This is a good example of the ways that -gnu and -msvc change
LLVM's behavior. __chkstk_ms is provided by mingw's version of libgcc, I
believe. Using the gnu environment makes LLVM use this helper.

chkstk and chkst_ms touch all the stack pages, similar to GCC's
-fstack-clash-protector feature. Making objects static moved them from the
stack to globals, reducing your stack frame size, avoiding the need for
this helper.

You could fix this issue by linking against LLVM's compiler-rt which
provides both helpers.

4. fms-compatibility vs fms-extensions

The idea behind these options is that fms-compatibility is the set of
compatibility hacks that we would prefer to avoid, and fms-extensions is
the set of language extensions that fit in the language well. For example,
fms-extensions should enable a variety of builtin intrinsic functions, like
_InterlockedCompareExchange, __fastfail, __noop. It enables

fms-compatibility usually has more to do with forcing the compiler to
accept certain invalid C++ code patterns involving templates. However, in
practice it controls far more than that.

5. Docs on -m* flags

Yeah, I don't know what to say. There isn't really a singular point of
responsibility in the community for keeping the docs up to date,
consistent, and easy to find. As you've seen, things tend to be pretty
spotty. clang --help probably isn't the right place for in-depth
documentation, but there should be some central place that we can hook
everything into. We have a UsersManual, but even a single web page can't
describe every feature of clang. It's certainly an area for improvement.

I think -m micro-architectural flags, in particular, are the kind of thing
that gets added on a case-by-case basis without any documentation or
review. Every architecture has its own world of options.

On Sat, Nov 28, 2020 at 12:53 PM Javier Múgica via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> Hi:
> After successfully and easily compiling a project in Windows with clang-cl
> I wanted to change the command to clang. clang itself lies in Linux (WSL
> 2.0) and the C library to be used is that of MSVC. Eventually I learned
> about the triple, but by that time I had almost succeeded. I run into
> several issues:
> |1.| (Seems a bug). -fno-signed-char (or -funsigned-char) is ignored
> depending on the triple settings:
> targeting Linux, default option for the triple   O.K.
> targeting Windows, x86_64-windows-windows-msvc<xx.xx.x>     O.K.
> targeting Windows, x86_64-windows-windows-gnu     wrong
> and there were some other combination where it was also wrong. The
> compiler insists in char being signed, which generates me hundreds of
> warnings.
> |2.| <abi> in the triple
> According to CrossCompilation.rst, "Finally, the ABI option is something
> that will pick default CPU/FPU,
> define the specific behaviour of your code (PCS, extensions), and also
> choose the correct library calls, etc."
> So, it seems it is not what defines the format of the generated object
> files (what I would expect given its "abi" name). Since I had already
> managed to make clang compile the sources by specifying the -isystem
> directories, and I wanted to avoid any windows related magic as much as
> possible, I tried to specify x86_64-windows-windows-none or
> x86_64-pc-windows-none, but "none" there, or "unknown" always got replaced
> by msvc19.11.0. Maybe it does not make sense to have the abi unknown?
> Therefore I finally compiled with x86_64-windows-windows-gnu, although gnu
> had nothing to do with my compilation.
> I would expect that the application binary interface specification on the
> command line (or elsewhere) is what would make llvm generate object files
> for either or other consumer, but having seen that specifying "gnu" there
> generates .obj files just as specifying "msvc"; i.e., object files that
> Windows' link program handles well, it seems it is not.
> So the question is: what in the triple is what makes the backend generate
> object files in one or the other format?
> Except for the architecture part of the triple, which is clear what it
> means, I have found the documentation for the other parts (when I at last
> could find it) unclear in what they change or determine in a compilation
> process.
> So, compiling with x86_64-windows-windows-gnu -fno-builtin
> -fms-compatibility -fshort-wchar -Wno-pointer-sign -fvisibility-ms-compat
> and a bunch of defines like -D _M_X64=100, everything runs fine and
> linking the objects from Windows, with its link command, works properly,
> just as if I had compiled with x86_64-windows-windows-msvc19.16.00, EXCEPT
> for the function
> ___chk_stk_ms
> which the linker cannot find. This function is inserted by the compiler
> when a function requires a large amount of stack space. I solved this by
> declaring the problematic objects static, but I'd like to know why this
> happens.
> By the way, even without -fms-compatibility, just with -fdeclspec and some
> #defines in the code, I also succeeded in compiling.
> |4.| -fms-compatibility vs. -fms-extensions
> The help which is displayed by clang -help says
>   -fms-compatibility      Enable full Microsoft Visual C++ compatibility
>   -fms-extensions         Accept some non-standard constructs supported by
> the Microsoft compiler
> which is not very informative. Which one enables less stuff? Is one a
> superset of the other. "Enable full Microsoft Visual C++ compatibility"
> seems to imply that this indeed is a superset of the other, but considering
> that even compiling with clang-cl there are the options /Ze and /Za which
> enable o disable Microsoft extensions, one is lead to think that the
> -fms-extensions are beyond the compatibility provided by
> -fms-compatibility. What, then?
> |5.| -m... options.
> I know that once I have specified my architecture to be x86_64 there are
> options that can improve the performance of the binaries: "Once your target
> is specified, it's time to pick the hardware you'll
> be compiling to. For every architecture, a default set of CPU/FPU/ABI will
> be chosen, so you'll almost always have to change it via flags."
> Where can the available flags be found? If they are so important and can
> have such an impact on the program, why is the documentation for them so
> difficult to find? (Specially if you are working off-line as I use to).
> In general, it seems that a good, thought document explaining each of the
> parts of the "triple" AND what the determine in the compilation process,
> and those -m flags would be very welcome, and if clang -help would point
> where that documentation could be found that would be very helpful also.
> Just browse the internet for Q&A related to the triple, and you'll find
> that "official" explanations should definitely be easier to find.
> Thanks in advance
> -- Javier A. Múgica
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20201203/9e152425/attachment.html>

More information about the cfe-dev mailing list