[clang] [HLSL][Docs] Add documentation for HLSL functions (PR #75397)
Damyan Pepper via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 13 15:13:41 PST 2023
================
@@ -0,0 +1,300 @@
+===================
+HLSL Function Calls
+===================
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+This document descries the design and implementation of HLSL's function call
+semantics in Clang. This includes details related to argument conversion and
+parameter lifetimes.
+
+This document does not seek to serve as official documentation for HLSL's
+call semantics, but does provide an overview to assist a reader. The
+authoritative documentation for HLSL's language semantics is the `draft language
+specification<https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf>`_.
+
+Argument Semantics
+==================
+
+In HLSL, all function arguments are passed by value in and out of functions.
+HLSL has 3 keywords which denote the parameter semantics (``in``, ``out`` and
+``inout``). In a function declaration a parameter may be annotated any of the
+following ways:
+
+#. <no parameter annotation> - denotes input
+#. ``in`` - denotes input
+#. ``out`` - denotes output
+#. ``in out`` - denotes input and output
+#. ``out in`` - denotes input and output
+#. ``inout`` - denotes input and output
+
+Parameters that are exclusively input behave like C/C++ parameters that are
+passed by value.
+
+For parameters that are output (or input and output), a temporary value is
+created in the caller. The temporary value is then passed by-address. For
+output-only parameters, the temporary is uninitialized when passed (it is
+undefined behavior to not explicitly initialize an ``out`` parameter inside a
+function). For input and output parameters, the temporary is initialized from
+the lvalue argument expression through implicit or explicit casting from the
+lvalue argument type to the parameter type.
+
+On return of the function, the values of any parameter temporaries are written
+back to the argument expression through an inverted conversion sequence (if an
+``out`` parameter was not initialized in the function, the uninitialized value
+may be written back).
+
+Parameters of constant-sized array type, are also passed with value semantics.
+This requires input parameters of arrays to construct temporaries and the
+temporaries go through array-to-pointer decay when initializing parameters.
+
+Implementations are allowed to avoid unnecessary temporaries, and HLSL's strict
+no-alias rules can enable some trivial optimizations.
+
+Array Temporaries
+-----------------
+
+Given the following example:
+
+.. code-block:: c++
+ void fn(float a[4]) {
+ a[0] = a[1] + a[2] + a[3];
+ }
+
+ float4 main() : SV_Target {
+ float arr[4] = {1, 1, 1, 1};
+ fn(arr);
+ return float4(a[0], a[1], a[2], a[3]);
+ }
+
+In C or C++, the array parameter decays to a pointer, so after the call to
+``fn``, the value of ``a[0]`` is ``3``. In HLSL, the array is passed by value,
+so modifications inside ``fn`` do not propagate out.
+
+.. note::
+ DXC supports unsized arrays passed directly as decayed pointers, which is an
+ unfortunate behavior divergence.
+
+Out Parameter Temporaries
+-------------------------
+
+.. code-block:: c++
+ void Init(inout int X, inout int Y) {
+ Y = 2;
+ X = 1;
+ }
+
+ void main() {
+ int V;
+ Init(V, V); // MSVC ABI V == 2, Itanium V == 1
+ }
+
+In the above example the ``Init`` function's behavior depends on the C++ ABI
+implementation. In the MSVC C++ ABI (used for the HLSL DXIL target), call
----------------
damyanp wrote:
Is this defined behavior that we have to ensure continues to work so HLSL developers targeting DXIL can depend on it?
https://github.com/llvm/llvm-project/pull/75397
More information about the cfe-commits
mailing list