@@ -248,13 +248,14 @@ which is a term made up for HLSL. A cx-value is a temporary value which may be
248
248
the result of a cast, and stores its value back to an lvalue when the value
249
249
expires.
250
250
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:
254
253
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:
258
259
259
260
.. code-block :: c++
260
261
@@ -267,23 +268,36 @@ example:
267
268
Init(V);
268
269
}
269
270
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.
271
275
272
276
.. code-block :: text
273
277
274
278
CallExpr 'void'
275
279
|-ImplicitCastExpr 'void (*)(int &)' <FunctionToPointerDecay>
276
280
| `-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:
287
301
288
302
.. code-block :: c++
289
303
@@ -295,28 +309,39 @@ is not the same as the parameter type. Given this example:
295
309
Trunc(F);
296
310
}
297
311
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
299
313
casting expression sequences for the initialization and write back:
300
314
301
315
.. code-block :: text
302
316
303
317
-CallExpr 'void'
304
318
|-ImplicitCastExpr 'void (*)(int3 &)' <FunctionToPointerDecay>
305
319
| `-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