[cfe-dev] [libc++] RFC: Add Windows kernel support and partial MSVC 2015 support
Eric Fiselier via cfe-dev
cfe-dev at lists.llvm.org
Mon Mar 27 16:37:13 PDT 2017
On Sat, Mar 25, 2017 at 9:18 AM, Ben Craig <ben.craig at ni.com> wrote:
> Abstract:
> I would like to add Windows x86 and x64 kernel support to libc++. My
> initial
> compiler would be MSVC 2015 Update 3, though MSVC 2017 shouldn't be
> difficult to
> add after the fact.
>
> I would like to know if this is a port that the libc++ maintainers are
> willing
> to accept.
>
Before responding in depth I need to ask this question: Why not use
Clang/C2 or simply Clang+LLVM?
I'm assuming they don't support targeting the kernel?
There seem to be three separate changes going on here, and each of the
changes
will benefits and challenges. For that reason I think it's best to consider
them
separately.
(1) Porting to MSVC
(2) Supporting the Windows Kernel C library.
(3) Implementation a Freestanding configuration of libc++
(4) Implementing the Kernel-space compatible configuration described in the
original email.
In general I'm happy to accept specific or niche libc++ changes as long as
they
aren't detrimental to the overall libc++ quality and implementation
complexity.
Changes to better support (1) or (3) would be beneficial to the larger
libc++ audience and I would b
happy to upstream them. However I have large concerns regarding the changes
required for (2) and (4)
as I suspect they won't satisfy the above requirement.
For example What if the Windows Kernel C library is incomplete, or
significantly different from
existing implementations, and supporting it requires re-implementing the
missing parts within libc++?
These portions would be virtually untestable outside of the Windows Kernel
environment and would
quickly become unmaintained. Having such code in Libc++ could quickly
become a detriment.
My main concern with (4) is the limited feature set that has been proposed.
Specifically
how it limits the libc++ internals to the same feature set and the changes
that would be
needed to support and maintain it.
First Libc++ cannot reasonably limit itself to the proposed language and
library feature set since
it must be free to use "restricted" features within the implementation of
non-restricted ones whenever
it is beneficial to the implementation. The burden of maintaining a working
restricted feature set could
not fall on upstream maintainers.
Second, the changes required to either guard restricted features using
#ifdef or remove restricted features
by re-structuring the headers would be vast and would require constant
maintenance. Frankly I don't
see how libc++ or its existing users could benefit from upstreaming these
changes (For example adding
#ifdef guards for every usage of `operator new`).
I think it would be much better to get as much of libc++ compiling as
possible, even if it depends on restricted
features, and then finding another mechanism to restrict the features
end-users are allowed to use (Such as clang-tidy).
This would eliminate the need to restructure headers or spam out internal
#ifdef guards.
> This means that string, vector, and the non-array containers won't be
> ported.
> Any class or function that requires throwing exceptions to meet their
> standards
> required behavior will be omitted. That rules out a lot of classes that
> allocate memory.
There are often ways to safely use STL containers w/o exceptions
(Especially when
custom allocators are provided).
Avoiding allocations allows us to sidestep one other large issue. In the
> kernel, not all memory is equal. There are several memory pools to choose
> from,
> but the two most common memory pools are the pageable pool and the
> non-pageable
> pool. There is no clear correct answer for which pool a global operator
> new
> should use, so we simply won't require an allocating new to be present for
> our
> implementation. Placement new shall remain though.
Containers don't use new/delete directly but instead go through the
specified allocator,
allowing containers to change the allocation behavior on a per-object
basis. Not
supporting containers because of global operator new's behavior seems
misguided.
My employer has significant experience using C++ in the kernel. We have
> been
> using a modified version of STLPort for quite some time and learned a lot
> about
> C++ library usage in the kernel, often the hard way. The big, obvious
> lesson
> is that a lot of the STL is either difficult, or impossible to work with
> when
> exceptions are off and std::terminate is undesired. There's nothing wrong
> with
> sorting in the kernel though.
> Challenges:
> * Header partitioning.
>
Libc++ prefers larger monolithic headers over many well-partitioned
headers. The idea is that hitting the filesystem
multiple times is slower than processing the single include file. Any
proposed changes should keep this in mind.
> * I don't have an exact list of what functions and classes I will be
> keeping. I do know that some of the headers I want to bring along
> have
> parts that I won't be keeping. For instance, many of the algorithms
> allocate a temporary buffer in order to meet performance
> requirements.
>
I don't think partitioning <algorithm> into smaller headers would be
beneficial
to existing libc++ users (If that's what you're suggesting).
> * I'll also need to figure out how to not drag along unwanted header
> dependencies.
>
I don't see how libc++ could upstream changes since it requires every header
it currently includes (modulo bugs).
* Testing.
> * Installing code so that it can be run in the kernel takes several
> seconds
> for each binary.
* There is no facility in the Windows kernel for running a program
> starting
> at "main" in the context of the kernel.
>
I suspect this will be the largest hurdle to get the test-suite running. My
only
idea for handling this would be to write a script to rename main() to some
unique function name and creating a separate test-driver that calls the
re-named main.
This could also allow us to combine multiple tests into a single
executable, avoiding
the cost of installing every test manually.
> * The 32-bit Windows kernel requires a default calling convention of
> stdcall, but warns if "main" is not cdecl.
> * A common failure mode for libc++ tests is to crash or assert. That
> will "blue-screen" a machine.
>
I could envision a fix which replaces `<assert.h>` when compiling the
tests, but that
would be a hack. Maybe the Windows Kernel C library provides a mechanism
for replacing
the assert handler?
.
> * MSVC compiler feature set
> * No #include_next. I'll need to use computed include paths, like an
> STL using caveman.
>
Using hard-coded kernel paths is not a change I see being upstream-able.
However
we might be able to convince MSVC to implement #include_next if we can
provide
strong enough rational for why we need it.
> * Limited expression SFINAE. Some areas in the code are
> straightforward
> to fix, and others are not.
>
I'm violently against working around MSVC template bugs. Every time I've
seen
it done it makes the implementation worse.
Another point is that libc++ doesn't have an <atomic> implementation for
MSVC
so adding MSVC support would required adding one.
> * C-runtime
> * The Windows kernel has its own implementation of the C-runtime. I
> don't
> know all the details on it. I suspect (but don't know) that it is
> derived from Dinkumware, but I know that it is not the same C-runtime
> as used in user mode.
>
I'm very curious to know the changes required to support the kernel C
runtime.
Hopefully it's similar enough to other supported C libraries that very few
changes
are needed.
I hope my response has been helpful, and it hasn't scared you away from
using libc++.
These are my initial reactions and are in no way absolute. Please let me
know if I can
clarify anything or if I got anything wrong.
/Eric
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170327/0e6ceaf2/attachment.html>
More information about the cfe-dev
mailing list