Skip to content

[Docs] Document freestanding requirements #132232

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

Merged

Conversation

AaronBallman
Copy link
Collaborator

This adds some initial documentation about freestanding requirements for Clang. The most critical part of the documentation is spelling out that a conforming freestanding C Standard Library is required; Clang will not be providing the headers for <string.h> in C23 which expose a number of symbols in freestanding mode.

The docs also make it clear that in addition to a conforming freestanding C standard library, the library must provide some additional symbols which LLVM requires.

These docs are not comprehensive, this is just getting the bare bones in place so that they can be expanded later.

This also updates the C status page to make it clear that we don't have anything to do for WG14 N2524 which adds string interfaces to freestanding mode.

This adds some initial documentation about freestanding requirements
for Clang. The most critical part of the documentation is spelling out
that a conforming freestanding C Standard Library is required; Clang
will not be providing the headers for <string.h> in C23 which expose a
number of symbols in freestanding mode.

The docs also make it clear that in addition to a conforming
freestanding C standard library, the library must provide some
additional symbols which LLVM requires.

These docs are not comprehensive, this is just getting the bare bones
in place so that they can be expanded later.

This also updates the C status page to make it clear that we don't have
anything to do for WG14 N2524 which adds string interfaces to
freestanding mode.
@AaronBallman AaronBallman added documentation clang Clang issues not falling into any other category c23 labels Mar 20, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 20, 2025

@llvm/pr-subscribers-clang

Author: Aaron Ballman (AaronBallman)

Changes

This adds some initial documentation about freestanding requirements for Clang. The most critical part of the documentation is spelling out that a conforming freestanding C Standard Library is required; Clang will not be providing the headers for <string.h> in C23 which expose a number of symbols in freestanding mode.

The docs also make it clear that in addition to a conforming freestanding C standard library, the library must provide some additional symbols which LLVM requires.

These docs are not comprehensive, this is just getting the bare bones in place so that they can be expanded later.

This also updates the C status page to make it clear that we don't have anything to do for WG14 N2524 which adds string interfaces to freestanding mode.


Full diff: https://github.com/llvm/llvm-project/pull/132232.diff

3 Files Affected:

  • (modified) clang/docs/CommandGuide/clang.rst (+4-3)
  • (modified) clang/docs/UsersManual.rst (+24)
  • (modified) clang/www/c_status.html (-5)
diff --git a/clang/docs/CommandGuide/clang.rst b/clang/docs/CommandGuide/clang.rst
index f0d94a4e628b0..dfe28fc5d2bcb 100644
--- a/clang/docs/CommandGuide/clang.rst
+++ b/clang/docs/CommandGuide/clang.rst
@@ -262,9 +262,10 @@ Language Selection and Mode Options
 .. option:: -ffreestanding
 
  Indicate that the file should be compiled for a freestanding, not a hosted,
- environment. Note that it is assumed that a freestanding environment will
- additionally provide `memcpy`, `memmove`, `memset` and `memcmp`
- implementations, as these are needed for efficient codegen for many programs.
+ environment. Note that a freestanding build still requires linking against a C
+ Standard Library which supports the freestanding interfaces for the specified
+ language mode and target environment. This includes functions like `memcpy`,
+ `memmove`, `memset` and `memcmp`.
 
 .. option:: -fno-builtin
 
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 2ea4b9d90ad34..d73e8eb78dbf6 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -1073,6 +1073,30 @@ inputs. Here is some example of ``$``-prefixed options:
 Language and Target-Independent Features
 ========================================
 
+Freestanding Builds
+-------------------
+Passing the ``-ffreestanding`` flag causes Clang to build for a freestanding
+(rather than a hosted) environment. The ``__STDC_HOSTED__`` predefined macro
+will expand to ``0`` in a freestanding environment. In such an environment,
+execution of the program may happen without an operating system and so a
+startup function (e.g., ``main``) may not be automatically called, though file
+scope objects which need to run startup code (constructors in C++,
+``__attribute__((constructor))``, etc) are executed via implementation-defined
+means such as ``__cxx_global_var_init``.
+
+A freestanding environment is not one which has no C standard library support.
+A conforming freestanding C standard library implementation is required. Clang
+supplies some of the header files needed for a freestanding execution, such as
+``<stdarg.h>``, ``<limits.h>``, ``<stdint.h>``, etc. However, Clang still
+requires the runtime freestanding library to provide the interfaces required by
+Clause 4 (Conformance) of the C standard. Additionally, Clang requires the
+following runtime interfaces to be provided:
+
+  * `memcpy`,
+  * `memmove`,
+  * `memset`, and
+  * `memcmp`.
+
 Controlling Errors and Warnings
 -------------------------------
 
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index c9e2eda4304f3..ee0cd057916ba 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -534,11 +534,6 @@ <h2 id="c2x">C23 implementation status</h2>
       <td class="full" align="center">Clang 16</td>
     </tr>
     <!-- Apr 2021 Papers -->
-    <tr>
-      <td>String functions for freestanding implementations</td>
-      <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2524.htm">N2524</a></td>
-      <td class="none" align="center">No</td>
-    </tr>
     <tr>
       <td>Digit separators</td>
       <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2626.pdf">N2626</a></td>

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text reads fine, though I cannot approve accuracy :D

@jyknight
Copy link
Member

This looks potentially-reasonable from the Clang subproject POV, but from a whole-project POV, I think we ought to actually provide a conforming freestanding mode somehow, probably via llvm-libc.

So I'd kinda like to hear from llvm-libc folks what they're thinking here. @jhuber6 @michaelrj-google any thoughts?

@AaronBallman
Copy link
Collaborator Author

This looks potentially-reasonable from the Clang subproject POV, but from a whole-project POV, I think we ought to actually provide a conforming freestanding mode somehow, probably via llvm-libc.

+1

So I'd kinda like to hear from llvm-libc folks what they're thinking here. @jhuber6 @michaelrj-google any thoughts?

My understanding (and correct me if I'm wrong!) is that llvm-libc aims to provide both a hosted and a freestanding mode.

Copy link
Contributor

@jhuber6 jhuber6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be more specific on what -ffreestanding actually does. Namely, removed implicit search paths, link libraries, passes -fno-builtin and lets int main function as a normal function.

For the libc side, I don't think this makes much of a difference, but it's nice to see the function requirements documented.

@michaelrj-google
Copy link
Contributor

Right now we don't really have a "freestanding" mode, we've got "baremetal" targets which are meant for systems without an OS but they have a lot more than just those four memory functions. You may be thinking of "fullbuild" vs "overlay", which determines if we provide our own libc headers or use the ones provided by the system's existing libc respectively. That's interesting, but seems orthogonal to this specific change.

Similar to jhuber, I'm curious about what freestanding means for the library. Is the expectation that a freestanding c library provide just the four listed memory functions, or is it expected to provide a more complete runtime. I'm not sure how/why we'd provide startup code that initializes C++ variables but can't also call main. Also what's the linking expectations? Is it required to be fully static or is the libc expected to provide a loader?

@efriedma-quic
Copy link
Collaborator

-ffreestanding currently has the following effects:

  • Disables builtins recognition (-fno-builtins)
  • Sets __STDC_HOSTED__ to 0.
  • Disables unwind tables (-fno-asynchronous-unwind-tables -fno-unwind-tables) (refer to df50259)

Maybe we should explicitly list this out in the documentation.

We might want to check existing uses of __STDC_HOSTED__ to see if we need to modify the interaction if we have a libc. A few of the headers in clang/lib/Headers/ make assumptions about the presence of libc based on __STDC_HOSTED__. At first glance, we're probably fine, but we might want to come up with some sort of policy.

As a practical matter, nobody really cares what the C committee has to say about freestanding implementations; everyone makes different tradeoffs depending on the constraints of their environment. Some "baremetal" environments have an extremely complete C library including I/O, and the usual "main" function. Some have absolutely nothing (even less than what we say clang requires). And everything in between.

I don't think we need to say anything about how startup works in a freestanding environment; I think we just refer people to their environment's documentation.

We say "memcpy, memmove, memset, memcmp" because that's what the corresponding gcc documentation says, but I don't think clang has ever generated calls to memcmp in -fno-builtins mode.

@jyknight
Copy link
Member

The intent of this standards change is that everyone should be able to depend on library functions from string.h, no matter how minimal or bare-metal their environment.

The requirement is now:

  • <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbit.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>.
  • <string.h>, except strcoll, strdup, strerror, strndup, strtok, strxfrm
  • memalignment from <stdlib.h>

Clang provides most of the required functionality already, other than stdbit.h, string.h, and stdlib.h. (assuming the freestanding versions the other headers are compliant, which I haven't verified).

The standard doesn't specify compiler command-line-options, and -ffreestanding has an existing meaning which doesn't involve pulling in library code, so possibly we shouldn't modify that flag's behavior.

But, what I would like is that we somehow make it trivial for users to get an implementation of the required functionality without requiring an externally-provided libc. Some way for users to trivially build and link against implementations of those functions for their minimal target, without depending on anything else.

@efriedma-quic
Copy link
Collaborator

We could theoretically ship some sort of "freestanding" libc in lib/clang/$VERSION/lib/$TRIPLE, the same way we ship compiler-rt. It's not clear to me anyone would actually want to use it; anyone who is actually building a real environment will probably be unhappy with some aspect of the way we build our freestanding libc, and provide their own replacement.

@AaronBallman
Copy link
Collaborator Author

But, what I would like is that we somehow make it trivial for users to get an implementation of the required functionality without requiring an externally-provided libc. Some way for users to trivially build and link against implementations of those functions for their minimal target, without depending on anything else.

I had originally thought that was the direction we would go (effectively, Clang-supplied headers would start to provide <string.h> and <stdbit.h> with implementations for the functionality). However, the consensus position at the time was that we expect the user to link against whatever C standard library they want, and that library has to supply those symbols. In effect, Clang would only be responsible for providing macros and typedefs that only the compiler can provide.

So I was trying to document that expectation.

@AaronBallman
Copy link
Collaborator Author

I tried to address some of the feedback with some changes, please let me know if you'd like to see additional information.

Comment on lines -537 to -541
<tr>
<td>String functions for freestanding implementations</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2524.htm">N2524</a></td>
<td class="none" align="center">No</td>
</tr>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the PR description said:

This also updates the C status page to make it clear that we don't have anything to do for WG14 N2524 which adds string interfaces to freestanding mode.

It seem to me that the status will become less clear due to removal of the entry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't typically document anything which the compiler isn't required to provide (for example, we don't really list other things from the C standard library). We could add an N/A status like we have for DRs, but I think that would start to drown out the relevant information due to talking about editorial changes as well as library changes.

WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW we list all the LWG papers and issues in the libc++ docs, and IMO it's useful. That makes it clear whether we've considered the paper/issue and what our conclusion was. Since most papers by far require changes, it's also really not cluttering the list too much.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit different though -- libc++ lists library issues and papers, not Core issues and papers, because it's an implementation of the library. In this case, Clang doesn't provide any libc functionality, so we typically do not list any C Standard Library papers (just the core wording papers). But freestanding can either be "the compiler provides this" or "the library provides this". In this case, the library provides this, so I don't think it makes sense to list it as a feature the compiler needs to provide.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that c_status.html is currently listing some library-only changes (e.g. N2359 and possibly N2951). Perhaps a thorough cleanup (in a later PR) is desired?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N2359 applies to the compiler because it introduces new potentially reserved identifiers we may want to diagnose and it changes behavior of limits.h which Clang provides.

N2951 applies to the compiler because it imposes some requirements on freestanding regarding FENV_ACCESS. It's questionable whether this one belongs on the list or not. It's marked as "Unknown" currently because I've not spent the time trying to figure out whether we have anything to do here or not.

But yes, cleaning these up in a later PR is a good idea. FWIW, I've been removing ones as I realize they don't impact the compiler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yeah. I guess the call what is compiler and library is a bit less explicit in C, since there isn't a CWG/LWG distinction. I guess we also only list CWG papers that affect the library in some way and not all of them.

* unwind tables are disabled (``fno-asynchronous-unwind-tables -fno-unwind-tables``), and
* allows ``main`` to be used as a regular symbol.

A freestanding environment is not one which has no C standard library support.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we distinguish standard conforming freestanding implementation vs what Clang expects of you when you use -ffreestanding? Or, do we intend to unify the two concepts?

Unification would imply (to me) that codegen in -ffreestanding is allowed to generate new calls to anything that the standards-conforming freestanding implementation is required to provide. And that we ought to treat calls to the freestanding-required functions as builtins for optimization purposes.

Also, I think we wouldn't need the callout for memcpy/memmove/memset, since all of those are in string.h which is already required of a freestanding implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the optimizations/warnings disabled by -fno-builtin turn out to be an issue, we can consider adding some additional flag which considers some functions builtin, or something like that. But we'll have to be careful how we expose it: people don't want to be on the treadmill of messing with their environment every time the C committee decides to expand the list of required functions for freestanding implementations.

I think it makes sense to specifically call out memcpy/memmove/memset because calls to them can show up even if you don't explicitly write them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was aiming to let users know what Clang does & expects of you when -ffreestanding is passed. The primary thing is: freestanding does not mean "I don't need any C standard library", it means "I need a freestanding-compatible C standard library that includes a few functions that are expected to be available even in older language modes where they weren't in freestanding before."

Copy link
Member

@jyknight jyknight Mar 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I find the wording now a bit unclear because the new paragraph discusses standards conformance, in the middle of discussing Clang's expectations.

I think those two concepts need to clearly distinguished.

How about rewording something like:

An implementation of the following runtime library functions must always be provided with the usual semantics, as Clang will generate calls to them:

  • memcpy,
  • memmove, and
  • memset.

Clang does not, by itself, provide a full "conforming freestanding implementation". If you wish to have a conforming freestanding implementation, you must provide a freestanding C library. While Clang provides some of the required header files, it does not provide all of them, nor any library implementations.

Conversely, when -ffreestanding is specified, Clang does not require you to provide a conforming freestanding implementation library. Clang will not make any assumptions as to the availability or semantics of standard-library, functions other than those mentioned above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing there's a full list of functions that we need to provide. Wonder how difficult it would be to just stash those in compiler-rt or something.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the wording along the lines of what @jyknight proposed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I think that list will need to be expanded (in a future patch?). For example, we support _Complex in freestanding mode and that will emit a call to __divsc3 on complex division, that sort of thing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I summarized the functionality required from a conforming freestanding implementation in a previous comment on this PR.

I think we should also assume that future C standards may further increase the set of freestanding functions, towards inclusion of any function which doesn't require a runtime environment (e.g. memory allocator, system calls, or other global state).

Copy link
Member

@jyknight jyknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM to me now. I hope we will eventually provide a conforming freestanding implementation, but that's future work.

@AaronBallman AaronBallman merged commit 85c54a5 into llvm:main Mar 27, 2025
10 of 12 checks passed
@AaronBallman AaronBallman deleted the aballman-freestanding-requirements branch March 27, 2025 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c23 clang Clang issues not falling into any other category documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants