Files
sdk/tools/verify_docs
Daco Harkes 6ef57b86c1 [vm/ffi] Support varargs
This CL introduces `VarArgs` to `NativeFunction` signatures. The
`VarArgs` type takes a single type argument. This type argument is a
subtype of `NativeType` if there is a single variadic argument, and a
record with native types if there are multiple variadic arguments.
For example:
`NativeFunction<Void Function(Pointer<Char>, VarArgs<(Int32,Int32)>)>`
for calling refering to a `printf` binding with two `int32_t` arguments
passed as variadic arguments.

The logic of the native calling conventions are detailed in
https://dart-review.googlesource.com/c/sdk/+/278342.
Here we explain how this influences the FFI pipeline.

First, now that `VarArgs` is part of signatures, we have to unwrap
that when with the C types in the CFE transform and checking (analyzer
is in a separate CL), and also in the marshaller when looking up the
C type of arguments.

Second, we have to deal with `BothNativeLocations`. On windows x64,
floating point arguments must be passed both in FPU _and_ CPU
registers. For FFI calls, we solve this in the argument moves by just
copying to both locations. For FFI callbacks, we just take the FPU
register location (which avoids an extra bitcast).

Third, on System-V, we have to pass an upper bound of the number of
XMM registers used in AL. This means we instead RAX, we use R13 for the
target address. For variadic calls, we always pass 8 in AL as the valid
upper bound. We could consider passing the actual number of XMM
registers used.
We keep using RAX as default register for the function address on non-
variadic calls, because changing to R13 (the first free) register
creates more spilling in leaf calls. R13 is callee-saved while RAX is
not, so using R13 instead of RAX causes us to have to spill the value
from RAX on leaf calls.

Fourth, on both x64 and RISC-V, we pass floats in integer locations.
`EmitNativeMove` has been modified to deal with this, so that we do not
have to insert more `BitCastInstr`s.

The tests are generated by a test generator: `tests/ffi/generator/`.

The formatter doesn't support records yet, so the tests are not properly
formatted.
Bug: https://github.com/dart-lang/sdk/issues/50798

TEST=tests/ffi/*_varargs_*

Closes: https://github.com/dart-lang/sdk/issues/38578
Closes: https://github.com/dart-lang/sdk/issues/49460
Closes: https://github.com/dart-lang/sdk/issues/50858

Change-Id: I6a6296fe972527f8a54ac75a630131769e3cc540
Cq-Include-Trybots: luci.dart.try:vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-win-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-nnbd-win-release-ia32-try,vm-kernel-nnbd-win-debug-x64-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try,vm-kernel-precomp-android-release-arm64c-try,vm-kernel-precomp-android-release-arm_x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-precomp-ffi-qemu-linux-release-riscv64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-precomp-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,app-kernel-linux-debug-x64-try,vm-kernel-mac-release-arm64-try,vm-kernel-nnbd-mac-debug-arm64-try,vm-kernel-nnbd-mac-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/276921
Reviewed-by: Devon Carew <devoncarew@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2023-01-20 10:30:41 +00:00
..
2023-01-20 10:30:41 +00:00

Whats this?

A tool to validate the documentation comments for the dart: libraries.

Running the tool

To validate all the dart: libraries, run:

dart tools/verify_docs/bin/verify_docs.dart

Or to validate an individual library (async, collection, js_util, ...), run either of:

dart tools/verify_docs/bin/verify_docs.dart sdk/lib/<lib-name>
dart tools/verify_docs/bin/verify_docs.dart dart:<lib-name>

The tool should be run from the root of the sdk repository.

Authoring code samples

What gets analyzed

This tool will walk all DartDoc API docs looking for code samples in doc comments. It will analyze any code sample in a dart code fence. For example:

/// ```dart
/// print('hello world!');
/// ```

By default, an import for that library is added to the sample being analyzed, e.g., import 'dart:async";.

Excluding code samples from analysis

In order to exclude a code sample from analysis, change it to a plain code fence style:

/// ```
/// print("I'm not analyzed :(");
/// ```

Specifying templates

The analysis tool can inject the code sample into a template before analyzing the sample. This allows the author to focus on the important parts of the API being documented with less boilerplate in the generated docs.

The template includes an automatic import of the library containing the example, so an example in, say, the documentation of StreamController.add would have dart:async imported automatically.

The tool will try and automatically detect the right template to use based on code patterns within the sample itself. In order to explicitly indicate which template to use, you can specify it as part of the code fence line. For example:

/// ```dart template:main
/// print('hello world ${Timer()}');
/// ```

The current templates are:

  • none: Do not wrap the code sample in any template, including no imports.
  • top: The code sample is top level code, preceded only by imports.
  • main: The code sample is one or more statements in a simple asynchronous main() function.
  • expression: The code sample is an expression within a simple asynchronous main() method.

For most code samples, the auto-detection code will select template:main or template:expression.

If the example contains any library declarations, the template becomes none.

Specifying additional imports

If your example contains any library, the default import of the current library is omitted. To avoid that, you can declare extra automatic imports in the code fence like:

/// ```dart import:async
/// print('hello world ${Timer()}');
/// ```

Multiple imports can be specified like this if desired, e.g., " ```dart import:async import:convert".

Does not work if combined with template:none, whether the none template is specified explicitly or auto-detected.

Splitting examples

Some examples may be split into separate code blocks, but should be seen as continuing the same running example.

If the following code blocks are marked as continued as shown below, they are included into the previous code block instead of being treated as a new example.

/// ```dart
/// var list = [1, 2, 3];
/// ```
/// And then you can also do the following:
/// ```dart continued
/// list.forEach(print);
/// ```

A continued code block cannot have any other flags in the fence.

Including additional code for analysis

You can declare code that should be included in the analysis but not shown in the API docs by adding a comment "// Examples can assume:" to the file (usually at the top of the file, after the imports), following by one or more commented-out lines of code. That code is included verbatim in the analysis, at top-level after the automatic imports. Does not work with template:none.

For example:

// Examples can assume:
// final BuildContext context;
// final String userAvatarUrl;