Skip to content

[LangRef] allow omitting va_end#203087

Merged
folkertdev merged 4 commits into
llvm:mainfrom
folkertdev:va-end-langref
Jun 15, 2026
Merged

[LangRef] allow omitting va_end#203087
folkertdev merged 4 commits into
llvm:mainfrom
folkertdev:va-end-langref

Conversation

@folkertdev

Copy link
Copy Markdown
Contributor

In Rust we'd like to be able to omit va_end: it is a no-op on all currently supported targets, and the requirement that it is paired exactly with va_start and va_copy (in the same frame) cannot be unified with a language with move semantics.

cc rust-lang/rust#157627 rust-lang/rust#155697

@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-llvm-ir

Author: Folkert de Vries (folkertdev)

Changes

In Rust we'd like to be able to omit va_end: it is a no-op on all currently supported targets, and the requirement that it is paired exactly with va_start and va_copy (in the same frame) cannot be unified with a language with move semantics.

cc rust-lang/rust#157627 rust-lang/rust#155697


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

1 Files Affected:

  • (modified) llvm/docs/LangRef.rst (+6-3)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index cf052513c5ef8..fa363f77c4485 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14631,10 +14631,13 @@ Semantics:
 
 The '``llvm.va_end``' intrinsic works just like the ``va_end`` macro
 available in C. In a target-dependent way, it destroys the ``va_list``
-element to which the argument points. Calls to
+element to which the argument points. Calls to ``llvm.va_end`` can be
+omitted when they are a no-op for the given target. ``llvm.va_end``
+is a no-op for all currently supported targets.
+
+When used, calls to ``llvm.va_end`` must be matched exactly with calls to
 :ref:`llvm.va_start <int_va_start>` and
-:ref:`llvm.va_copy <int_va_copy>` must be matched exactly with calls to
-``llvm.va_end``.
+:ref:`llvm.va_copy <int_va_copy>`.
 
 .. _int_va_copy:
 

@nikic nikic requested a review from efriedma-quic June 10, 2026 19:54

@efriedma-quic efriedma-quic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

https://groups.google.com/g/comp.std.c/c/cld4zwoKaFw indicates that some very old compilers might have needed va_end, but I don't know of any specific ABI that needs it. It's probably fine to loosen the rules like this.

We probably want to mention somewhere that the underlying argument list is destroyed when the function returns.

We probably also want to modify the description of va_copy to make it clear that it's okay to just memcpy on targets where va_list is trivially copyable.

@folkertdev

Copy link
Copy Markdown
Contributor Author

Yes, we found https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol which has this bit of code:

#define         va_start(ap, parmN)     {\
        va_buf  _va;\
        _vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define         va_end(ap)      }
#define         va_arg(ap, mode)        *((mode *)_vaarg(ap, sizeof (mode)))

With this expansion it's crucial that va_end is matched with va_start.

I'll have a look at the other updates.

- the argument list getting destroyed
- memcpy being OK when the va_list is trivially copyable
Comment thread llvm/docs/LangRef.rst Outdated
@@ -14671,6 +14677,10 @@ available in C. In a target-dependent way, it copies the source
intrinsic is necessary because the ``llvm.va_start`` intrinsic may be
arbitrarily complex and require, for example, memory allocation.

On targets where ``va_list`` is trivially copyable, ``memcpy`` can be

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We probably don't want to use the exact phrase "trivially copyable" to describe this, because it overlaps with the term in the C++ standard (and the C++ standard semantics isn't quite what we want).

Maybe just say "On targets where va_copy is equivalent to 'memcpy'"?

@folkertdev folkertdev requested a review from efriedma-quic June 12, 2026 08:45

@efriedma-quic efriedma-quic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment thread llvm/docs/LangRef.rst Outdated
@@ -14671,6 +14677,10 @@ available in C. In a target-dependent way, it copies the source
intrinsic is necessary because the ``llvm.va_start`` intrinsic may be
arbitrarily complex and require, for example, memory allocation.

On targets where ``llvm.va_copy`` is equivalent to ``memcpy``, ``memcpy``
can be used instead to duplicate a ``va_list``. ``llvm.va_copy`` is
equivalent to ``memcpy`` on all currently supported targets implement

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
equivalent to ``memcpy`` on all currently supported targets implement
equivalent to ``memcpy`` on all currently supported targets.

@nikic nikic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@folkertdev folkertdev merged commit b31c239 into llvm:main Jun 15, 2026
12 checks passed
@llvm-ci

llvm-ci commented Jun 15, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder lldb-aarch64-windows running on linaro-armv8-windows-msvc-05 while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/141/builds/19593

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: functionalities/breakpoint/move_nearest/TestMoveNearest.py (370 of 2570)
PASS: lldb-api :: functionalities/breakpoint/nested_breakpoint_commands/TestNestedBreakpointCommands.py (371 of 2570)
UNSUPPORTED: lldb-api :: functionalities/breakpoint/objc/TestObjCBreakpoints.py (372 of 2570)
PASS: lldb-api :: functionalities/breakpoint/same_cu_name/TestFileBreakpointsSameCUName.py (373 of 2570)
PASS: lldb-api :: functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py (374 of 2570)
XFAIL: lldb-api :: functionalities/breakpoint/scripted_bkpt/overrides_resolver/TestOverridesResolver.py (375 of 2570)
XFAIL: lldb-api :: functionalities/breakpoint/scripted_bkpt/was_hit/TestWasHit.py (376 of 2570)
PASS: lldb-api :: functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py (377 of 2570)
PASS: lldb-api :: functionalities/breakpoint/serialize/TestBreakpointSerialization.py (378 of 2570)
PASS: lldb-api :: functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py (379 of 2570)
FAIL: lldb-api :: functionalities/breakpoint/two_hits_one_actual/TestTwoHitsOneActual.py (380 of 2570)
******************** TEST 'lldb-api :: functionalities/breakpoint/two_hits_one_actual/TestTwoHitsOneActual.py' FAILED ********************
Script:
--
C:/Users/tcwg/scoop/apps/python/current/python.exe C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/llvm-project/lldb\test\API\dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --env LLVM_INCLUDE_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/include --env LLVM_TOOLS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --triple aarch64-pc-windows-msvc --build-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex --lldb-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-lldb\lldb-api --clang-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-clang\lldb-api --executable C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/lldb.exe --compiler C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/clang.exe --dsymutil C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/dsymutil.exe --make C:/Users/tcwg/scoop/shims/make.exe --llvm-tools-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --lldb-obj-root C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/tools/lldb --lldb-libs-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --cmake-build-type Release --skip-category=watchpoint --env LLDB_LAUNCH_FLAG_USE_PIPES=1 C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\test\API\functionalities\breakpoint\two_hits_one_actual -p TestTwoHitsOneActual.py
--
Exit Code: 1

Command Output (stdout):
--
Skipping the following test categories: watchpoint, libc++, libstdcxx, dwo, dsym, gmodules, debugserver, objc, fork, pexpect


--
Command Output (stderr):
--
FAIL: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_two_hits_one_actual (TestTwoHitsOneActual.TestTwoHitsOneActual.test_two_hits_one_actual)

Log Files:

 - C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\lldb-test-build.noindex\functionalities\breakpoint\two_hits_one_actual\TestTwoHitsOneActual\Failure_test_two_hits_one_actual.log

======================================================================

FAIL: test_two_hits_one_actual (TestTwoHitsOneActual.TestTwoHitsOneActual.test_two_hits_one_actual)

   There can be many tests in a test case - describe this test here.

----------------------------------------------------------------------

Traceback (most recent call last):

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\decorators.py", line 160, in wrapper

    return func(*args, **kwargs)

           ^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\test\API\functionalities\breakpoint\two_hits_one_actual\TestTwoHitsOneActual.py", line 23, in test_two_hits_one_actual

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants