Skip to content

Commit 562c0c6

Browse files
authored
[HLSL][Docs] Update function calls docs (llvm#106860)
Update the function calls documentation to match the newly landed implementation.
1 parent 1f51038 commit 562c0c6

File tree

1 file changed

+60
-35
lines changed

1 file changed

+60
-35
lines changed

clang/docs/HLSL/FunctionCalls.rst

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,14 @@ which is a term made up for HLSL. A cx-value is a temporary value which may be
248248
the result of a cast, and stores its value back to an lvalue when the value
249249
expires.
250250

251-
To represent this concept in Clang we introduce a new ``HLSLOutParamExpr``. An
252-
``HLSLOutParamExpr`` has two forms, one with a single sub-expression and one
253-
with two sub-expressions.
251+
To represent this concept in Clang we introduce a new ``HLSLOutArgExpr``. An
252+
``HLSLOutArgExpr`` has three sub-expressions:
254253

255-
The single sub-expression form is used when the argument expression and the
256-
function parameter are the same type, so no cast is required. As in this
257-
example:
254+
* An OpaqueValueExpr of the argument lvalue expression.
255+
* An OpaqueValueExpr of the copy-initialized parameter temporary.
256+
* A BinaryOpExpr assigning the first with the value of the second.
257+
258+
Given this example:
258259

259260
.. code-block:: c++
260261

@@ -267,23 +268,36 @@ example:
267268
Init(V);
268269
}
269270

270-
The expected AST formulation for this code would be something like:
271+
The expected AST formulation for this code would be something like the example
272+
below. Due to the nature of OpaqueValueExpr nodes, the nodes repeat in the AST
273+
dump. The fake addresses ``0xSOURCE`` and ``0xTEMPORARY`` denote the source
274+
lvalue and argument temporary lvalue expressions.
271275

272276
.. code-block:: text
273277
274278
CallExpr 'void'
275279
|-ImplicitCastExpr 'void (*)(int &)' <FunctionToPointerDecay>
276280
| `-DeclRefExpr 'void (int &)' lvalue Function 'Init' 'void (int &)'
277-
|-HLSLOutParamExpr 'int' lvalue inout
278-
`-DeclRefExpr 'int' lvalue Var 'V' 'int'
279-
280-
The ``HLSLOutParamExpr`` captures that the value is ``inout`` vs ``out`` to
281-
denote whether or not the temporary is initialized from the sub-expression. If
282-
no casting is required the sub-expression denotes the lvalue expression that the
283-
cx-value will be copied to when the value expires.
284-
285-
The two sub-expression form of the AST node is required when the argument type
286-
is not the same as the parameter type. Given this example:
281+
`-HLSLOutArgExpr <col:10> 'int' lvalue inout
282+
|-OpaqueValueExpr 0xSOURCE <col:10> 'int' lvalue
283+
| `-DeclRefExpr <col:10> 'int' lvalue Var 'V' 'int'
284+
|-OpaqueValueExpr 0xTEMPORARY <col:10> 'int' lvalue
285+
| `-ImplicitCastExpr <col:10> 'int' <LValueToRValue>
286+
| `-OpaqueValueExpr 0xSOURCE <col:10> 'int' lvalue
287+
| `-DeclRefExpr <col:10> 'int' lvalue Var 'V' 'int'
288+
`-BinaryOperator <col:10> 'int' lvalue '='
289+
|-OpaqueValueExpr 0xSOURCE <col:10> 'int' lvalue
290+
| `-DeclRefExpr <col:10> 'int' lvalue Var 'V' 'int'
291+
`-ImplicitCastExpr <col:10> 'int' <LValueToRValue>
292+
`-OpaqueValueExpr 0xTEMPORARY <col:10> 'int' lvalue
293+
`-ImplicitCastExpr <col:10> 'int' <LValueToRValue>
294+
`-OpaqueValueExpr 0xSOURCE <col:10> 'int' lvalue
295+
`-DeclRefExpr <col:10> 'int' lvalue Var 'V' 'int'
296+
297+
The ``HLSLOutArgExpr`` captures that the value is ``inout`` vs ``out`` to
298+
denote whether or not the temporary is initialized from the sub-expression.
299+
300+
The example below demonstrates argument casting:
287301

288302
.. code-block:: c++
289303

@@ -295,28 +309,39 @@ is not the same as the parameter type. Given this example:
295309
Trunc(F);
296310
}
297311

298-
For this case the ``HLSLOutParamExpr`` will have sub-expressions to record both
312+
For this case the ``HLSLOutArgExpr`` will have sub-expressions to record both
299313
casting expression sequences for the initialization and write back:
300314

301315
.. code-block:: text
302316
303317
-CallExpr 'void'
304318
|-ImplicitCastExpr 'void (*)(int3 &)' <FunctionToPointerDecay>
305319
| `-DeclRefExpr 'void (int3 &)' lvalue Function 'inc_i32' 'void (int3 &)'
306-
`-HLSLOutParamExpr 'int3' lvalue inout
307-
|-ImplicitCastExpr 'float3' <IntegralToFloating>
308-
| `-ImplicitCastExpr 'int3' <LValueToRValue>
309-
| `-OpaqueValueExpr 'int3' lvalue
310-
`-ImplicitCastExpr 'int3' <FloatingToIntegral>
311-
`-ImplicitCastExpr 'float3' <LValueToRValue>
312-
`-DeclRefExpr 'float3' lvalue 'F' 'float3'
313-
314-
In this formation the write-back casts are captured as the first sub-expression
315-
and they cast from an ``OpaqueValueExpr``. In IR generation we can use the
316-
``OpaqueValueExpr`` as a placeholder for the ``HLSLOutParamExpr``'s temporary
317-
value on function return.
318-
319-
In code generation this can be implemented with some targeted extensions to the
320-
Objective-C write-back support. Specifically extending CGCall.cpp's
321-
``EmitWriteback`` function to support casting expressions and emission of
322-
aggregate lvalues.
320+
`-HLSLOutArgExpr <col:11> 'int3':'vector<int, 3>' lvalue inout
321+
|-OpaqueValueExpr 0xSOURCE <col:11> 'float3':'vector<float, 3>' lvalue
322+
| `-DeclRefExpr <col:11> 'float3':'vector<float, 3>' lvalue Var 'F' 'float3':'vector<float, 3>'
323+
|-OpaqueValueExpr 0xTEMPORARY <col:11> 'int3':'vector<int, 3>' lvalue
324+
| `-ImplicitCastExpr <col:11> 'vector<int, 3>' <FloatingToIntegral>
325+
| `-ImplicitCastExpr <col:11> 'float3':'vector<float, 3>' <LValueToRValue>
326+
| `-OpaqueValueExpr 0xSOURCE <col:11> 'float3':'vector<float, 3>' lvalue
327+
| `-DeclRefExpr <col:11> 'float3':'vector<float, 3>' lvalue Var 'F' 'float3':'vector<float, 3>'
328+
`-BinaryOperator <col:11> 'float3':'vector<float, 3>' lvalue '='
329+
|-OpaqueValueExpr 0xSOURCE <col:11> 'float3':'vector<float, 3>' lvalue
330+
| `-DeclRefExpr <col:11> 'float3':'vector<float, 3>' lvalue Var 'F' 'float3':'vector<float, 3>'
331+
`-ImplicitCastExpr <col:11> 'vector<float, 3>' <IntegralToFloating>
332+
`-ImplicitCastExpr <col:11> 'int3':'vector<int, 3>' <LValueToRValue>
333+
`-OpaqueValueExpr 0xTEMPORARY <col:11> 'int3':'vector<int, 3>' lvalue
334+
`-ImplicitCastExpr <col:11> 'vector<int, 3>' <FloatingToIntegral>
335+
`-ImplicitCastExpr <col:11> 'float3':'vector<float, 3>' <LValueToRValue>
336+
`-OpaqueValueExpr 0xSOURCE <col:11> 'float3':'vector<float, 3>' lvalue
337+
`-DeclRefExpr <col:11> 'float3':'vector<float, 3>' lvalue Var 'F' 'float3':'vector<float, 3>'
338+
339+
The AST representation is the same whether casting is required or not, which
340+
simplifies the code generation. IR generation does the following:
341+
342+
* Emit the argument lvalue expression.
343+
* Initialize the argument:
344+
* For ``inout`` arguments, emit the copy-initialization expression.
345+
* For ``out`` arguments, emit an uninitialized temporary.
346+
* Emit the call
347+
* Emit the write-back BinaryOperator expression.

0 commit comments

Comments
 (0)