/
BoundNodes.xml
1944 lines (1622 loc) · 90.3 KB
/
BoundNodes.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<!--
To re-generate source from this file, run eng/generate-compiler-code.cmd
Important things to know about reference types, value types, and nulls.
By default, all fields of reference type are checked (in debug) to be non-null.
This can be modified by used the "Null" attribute, which can be one of the following values:
disallow (default) - disallow null values
allow - allow null values
always - always null - only used in an override to indicate that this subclass always sets this field to null.
notApplicable - its a value type, so it cannot be null
In order to generate code, the generator needs to know what types beyond the built-in types are value types. This
is indicated via a "ValueType" declaration.
-->
<Tree Root="BoundNode">
<!-- Don't put ImmutableArray here, that's handled in a special way internally.-->
<ValueType Name="ConversionKind"/>
<ValueType Name="Conversion"/>
<ValueType Name="TextSpan"/>
<ValueType Name="UnaryOperatorKind"/>
<ValueType Name="BinaryOperatorKind"/>
<ValueType Name="LookupResultKind"/>
<ValueType Name="NoOpStatementFlavor"/>
<ValueType Name="RefKind"/>
<ValueType Name="BoundTypeOrValueData"/>
<ValueType Name="BoundLocalDeclarationKind"/>
<ValueType Name="NullableAnnotation"/>
<AbstractNode Name="BoundInitializer" Base="BoundNode"/>
<AbstractNode Name="BoundEqualsValue" Base="BoundInitializer">
<Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/>
<!-- Expression representing the value. -->
<Field Name="Value" Type="BoundExpression"/>
</AbstractNode>
<!--
Bound node that represents the binding of an "= Value" construct in a field declaration.
Appears only in bound trees generated by a SemanticModel.
-->
<Node Name="BoundFieldEqualsValue" Base="BoundEqualsValue">
<!-- Field receiving the value. -->
<Field Name="Field" Type="FieldSymbol"/>
</Node>
<!--
Bound node that represents the binding of an "= Value" construct in a property declaration.
Appears only in bound trees generated by a SemanticModel.
-->
<Node Name="BoundPropertyEqualsValue" Base="BoundEqualsValue">
<!-- Property receiving the value. -->
<Field Name="Property" Type="PropertySymbol"/>
</Node>
<!--
Bound node that represents the binding of an "= Value" construct in a parameter declaration.
Appears only in bound trees generated by a SemanticModel.
-->
<Node Name="BoundParameterEqualsValue" Base="BoundEqualsValue">
<!-- Parameter receiving the value. -->
<Field Name="Parameter" Type="ParameterSymbol"/>
</Node>
<Node Name="BoundGlobalStatementInitializer" Base="BoundInitializer">
<Field Name="Statement" Type="BoundStatement"/>
</Node>
<AbstractNode Name="BoundExpression" Base="BoundNode">
<Field Name="Type" Type="TypeSymbol" Null="allow"/>
</AbstractNode>
<AbstractNode Name="BoundValuePlaceholderBase" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</AbstractNode>
<!--
This node is used to represent an expression returning value of a certain type.
It is used to perform intermediate binding, and will not survive the local rewriting.
-->
<Node Name="BoundDeconstructValuePlaceholder" Base="BoundValuePlaceholderBase">
<Field Name="ValEscape" Type="uint" Null="NotApplicable"/>
</Node>
<!--
In a tuple binary operator, this node is used to represent tuple elements in a tuple binary
operator, and to represent an element-wise comparison result to convert back to bool.
It does not survive the initial binding.
-->
<Node Name="BoundTupleOperandPlaceholder" Base="BoundValuePlaceholderBase">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>
<!--
This node is used to represent an awaitable expression of a certain type, when binding an using-await statement.
It does not survive past initial binding.
-->
<Node Name="BoundAwaitableValuePlaceholder" Base="BoundValuePlaceholderBase">
</Node>
<!--
This node is used to represent an expression of a certain type, when attempting to bind its pattern dispose method
It does not survive past initial binding.
-->
<Node Name="BoundDisposableValuePlaceholder" Base="BoundValuePlaceholderBase">
</Node>
<!-- only used by codegen -->
<Node Name="BoundDup" Base="BoundExpression">
<!-- when duplicating a local or parameter, must remember original ref kind -->
<Field Name="RefKind" Type="RefKind" Null="NotApplicable"/>
</Node>
<!-- Wrapper node used to prevent passing the underlying expression by direct reference -->
<Node Name="BoundPassByCopy" Base="BoundExpression">
<Field Name="Expression" Type="BoundExpression"/>
</Node>
<!--
An expression is classified as one of the following:
A value. Every value has an associated type.
A variable. Every variable has an associated type.
A namespace.
A type.
A method group. ...
A null literal.
An anonymous function.
A property access.
An event access.
An indexer access.
Nothing. (An expression which is a method call that returns void.)
-->
<!-- This node is used when we can't create a real expression node because things are too broken. Example: lookup of a name fails to find anything. -->
<Node Name="BoundBadExpression" Base="BoundExpression">
<!-- Categorizes the way in which "Symbols" is bad. -->
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
<!-- These symbols will be returned from the GetSemanticInfo API if it examines this bound node. -->
<Field Name="Symbols" Type="ImmutableArray<Symbol>"/>
<!-- Any child bound nodes that we need to preserve are put here. -->
<Field Name="ChildBoundNodes" Type="ImmutableArray<BoundExpression>"/>
</Node>
<!-- This node is used when we can't create a real statement because things are too broken. -->
<Node Name="BoundBadStatement" Base="BoundStatement">
<!-- Any child bound nodes that we need to preserve are put here. -->
<Field Name="ChildBoundNodes" Type="ImmutableArray<BoundNode>"/>
</Node>
<!-- This node is used to wrap the BoundBlock for a finally extracted by AsyncExceptionHandlerRewriter.
It is processed and removed by AsyncIteratorRewriter. -->
<Node Name="BoundExtractedFinallyBlock" Base="BoundStatement">
<Field Name="FinallyBlock" Type="BoundBlock"/>
</Node>
<Node Name="BoundTypeExpression" Base="BoundExpression">
<Field Name="AliasOpt" Type="AliasSymbol" Null="allow"/>
<!--
We're going to stash some extra information in the Color Color case
so that the binding API can return the correct information.
Consider the following example:
class C
{
public class Inner
{
public static C M() { return null; }
}
}
class F
{
public C C;
void M(C c)
{
M(/*<bind>*/C/*</bind>*/.Inner.M());
}
}
The bound tree for "C.Inner.M()" is a bound call with a bound type
expression (C.Inner) as its receiver. However, there is no bound node
corresponding to C. As a result, the semantic model will attempt to
bind it and the binder will return F.C, since it will have no context.
That's why we need to have a node for C in the (initial) bound tree.
It could conceivably be useful to store other types of expressions as well
(e.g. BoundNamespaceExpressions), but then it would be much harder to
identify the scenarios in which this property is populated.
-->
<Field Name="BoundContainingTypeOpt" Type="BoundTypeExpression" Null="allow"/>
<!-- The provided dimensions in an array type expression where dimensions were provided in error. -->
<Field Name="BoundDimensionsOpt" Type="ImmutableArray<BoundExpression>" Null="allow"/>
<!-- Non-null type is required for this node kind -->
<Field Name="TypeWithAnnotations" Type="TypeWithAnnotations" Null="allow"/>
</Node>
<!--
When binding "name1.name2" we normally can tell what name1 is.
There is however a case where name1 could be either
a value (field, property, parameter, local) or its type.
This only happens if value named exactly the same as its type -
famous "Color As Color".
That alone is not enough to cause trouble as we can do a lookup for
name2 and see if it requires a receiver (then name1 is a value)
or if it does not (then name1 is a type).
The problem only arises when name2 is an overloaded method or property.
In such case we must defer type/value decision until overload resolution
selects one of the candidates.
As a result we need this node that represents name1 in the state where
we only know its type and syntax, but do not know yet if it is a
Type or Value.
NOTE:
* The node can only be a qualifier of a method or a property group access
as only those may require overload resolution.
* It is possible for a node of this type to appear in a tree where there
are no errors. Consider (Color.M is Object). M may be overloaded to
contain both static and instance methods. In this case the expression is
always *false*, but the left-hand-side of the is operator is a method
group whose receiver is a BoundTypeOrValueExpression.
-->
<Node Name="BoundTypeOrValueExpression" Base="BoundExpression">
<!-- Type is required for this node type; may not be null -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Data" Type="BoundTypeOrValueData"/>
</Node>
<Node Name="BoundNamespaceExpression" Base="BoundExpression">
<!-- Type is not significant for this node type; always null -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="always"/>
<Field Name="NamespaceSymbol" Type="NamespaceSymbol"/>
<Field Name="AliasOpt" Type="AliasSymbol" Null="allow"/>
</Node>
<!-- EricLi thought we might need a node like this to do "Color Color" correctly. Currently we're
handling that in a different way. Dev10 compiler had a node like this.
[removed 3/30/2011 by petergo]
<Node Name="BoundTypeOrName" Base="BoundExpression">
<Field Name="Type" Type="BoundTypeExpression"/>
<Field Name="Name" Type="BoundExpression"/>
</Node>
-->
<Node Name="BoundUnaryOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="OperatorKind" Type="UnaryOperatorKind"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="ConstantValueOpt" Type="ConstantValue" Null="allow"/>
<Field Name="MethodOpt" Type="MethodSymbol" Null="allow"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
</Node>
<Node Name="BoundIncrementOperator" Base="BoundExpression">
<!-- x++ might need a conversion from the type of x to the operand type
of the ++ operator (that produces the incremented value) and a
conversion from the result of the ++ operator back to x. -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="OperatorKind" Type="UnaryOperatorKind"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="MethodOpt" Type="MethodSymbol" Null="allow"/>
<Field Name="OperandConversion" Type="Conversion"/>
<Field Name="ResultConversion" Type="Conversion"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
</Node>
<!-- Not really an operator since overload resolution is never required. -->
<Node Name="BoundAddressOfOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<!-- True only in some lowered/synthesized nodes.
It suppresses conversion of operand reference to unmanaged pointer
(which has effect of losing GC-tracking)
NB: The language does not have a concept of managed pointers.
However, managed (GC-tracked) pointers have some limited support
at IL level and could be used in lowering of certain kinds
of unsafe code - such as fixed field indexing. -->
<Field Name="IsManaged" Type="bool"/>
</Node>
<Node Name="BoundPointerIndirectionOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
</Node>
<Node Name="BoundPointerElementAccess" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Expression" Type="BoundExpression"/>
<Field Name="Index" Type="BoundExpression"/>
<Field Name="Checked" Type="bool"/>
</Node>
<Node Name="BoundRefTypeOperator" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<!-- Well-known member populated during lowering -->
<Field Name="GetTypeFromHandle" Type="MethodSymbol" Null="allow"/>
</Node>
<Node Name="BoundMakeRefOperator" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
</Node>
<Node Name="BoundRefValueOperator" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="NullableAnnotation" Type="NullableAnnotation" />
<Field Name="Operand" Type="BoundExpression"/>
</Node>
<Node Name="BoundFromEndIndexExpression" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="MethodOpt" Type="MethodSymbol" Null="allow"/>
</Node>
<Node Name="BoundRangeExpression" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="LeftOperandOpt" Type="BoundExpression" Null="allow"/>
<Field Name="RightOperandOpt" Type="BoundExpression" Null="allow"/>
<Field Name="MethodOpt" Type="MethodSymbol" Null="allow"/>
</Node>
<AbstractNode Name="BoundBinaryOperatorBase" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Left" Type="BoundExpression"/>
<Field Name="Right" Type="BoundExpression"/>
</AbstractNode>
<Node Name="BoundBinaryOperator" Base="BoundBinaryOperatorBase">
<Field Name="OperatorKind" Type="BinaryOperatorKind"/>
<Field Name="ConstantValueOpt" Type="ConstantValue" Null="allow"/>
<Field Name="MethodOpt" Type="MethodSymbol" Null="allow"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
</Node>
<Node Name="BoundTupleBinaryOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Left" Type="BoundExpression"/>
<Field Name="Right" Type="BoundExpression"/>
<!-- Converted nodes are meant for semantic model and IOperation use only -->
<Field Name="ConvertedLeft" Type="BoundExpression" SkipInVisitor="true"/>
<Field Name="ConvertedRight" Type="BoundExpression" SkipInVisitor="true"/>
<Field Name="OperatorKind" Type="BinaryOperatorKind"/>
<Field Name="Operators" Type="TupleBinaryOperatorInfo.Multiple"/>
</Node>
<Node Name="BoundUserDefinedConditionalLogicalOperator" Base="BoundBinaryOperatorBase">
<Field Name="OperatorKind" Type="BinaryOperatorKind"/>
<Field Name="LogicalOperator" Type="MethodSymbol"/>
<Field Name="TrueOperator" Type="MethodSymbol"/>
<Field Name="FalseOperator" Type="MethodSymbol"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
</Node>
<Node Name="BoundCompoundAssignmentOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<!-- A compound assignment operator has the following facts that must be
deduced about it for codegen to work. Suppose you have shorts
"x |= y;" That will be analyzed as "x = (short)(((int)x)|((int)y));"
We need to know what the left hand and right hand sides are,
what the binary operator is, how the left and right sides are
converted to the types expected by the operator,
whether the operator should check for overflow, and how the
result of the binary operator is converted to the target
variable's type. We'll lower this to operations on temporaries
before codegen.
Thought we can represent the operation as these seven facts,
in fact we can conflate three of them. We need never do the
right-hand-side-of-the-operator conversion during the rewrite.
We can get away with binding the conversion on the right early
and just having the converted right operand in the bound node.
We also conflate whether we should check for overflow with the
identity of the operator.
This makes it a bit easier to handle the lambda case; when we have
something like d += lambda, we want to represent the lambda in its
bound form, not in its unbound form to be converted to the bound form
later. This helps us maintain the invariant that non-error cases
never produce an "unbound" lambda from the initial binding pass.
-->
<Field Name="Operator" Type="BinaryOperatorSignature" Null="NotApplicable"/>
<Field Name="Left" Type="BoundExpression"/>
<Field Name="Right" Type="BoundExpression"/>
<Field Name="LeftConversion" Type="Conversion"/>
<Field Name="FinalConversion" Type="Conversion"/>
<Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/>
</Node>
<Node Name="BoundAssignmentOperator" Base="BoundExpression">
<Field Name="Left" Type="BoundExpression"/>
<Field Name="Right" Type="BoundExpression" Null="NotApplicable"/>
<!-- This is almost always false.
In C# most assignments to a variable are simply writes to the
logical variable. For example, when you say
void M(ref int x){ x = C.y }
that writes the value of C.y to the variable that x is an alias for.
It does not write the address of C.y to the actual underlying storage
of the parameter, which is of course actually a ref to an int variable.
However, in some codegen scenarios we need to distinguish between a
ref local assignment and a value assignment. When you say
int s = 123; s+=10;
then we generate that as
int s = 123; ref int addr = ref s; int sum = addr + 10; addr = sum;
Note that there are two assignment to addr; one assigns the address
of s to addr; the other assigns the value of sum to s, indirectly
through addr. We therefore need to disambiguate what kind of assignment
we are doing based on something other than the refness of the left hand side.
-->
<Field Name="IsRef" Type="bool" Null="NotApplicable"/>
</Node>
<Node Name="BoundDeconstructionAssignmentOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Left" Type="BoundTupleExpression" Null="disallow"/>
<Field Name="Right" Type="BoundConversion" Null="disallow"/>
<Field Name="IsUsed" Type="bool" Null="NotApplicable"/>
</Node>
<Node Name="BoundNullCoalescingOperator" Base="BoundExpression">
<Field Name="LeftOperand" Type="BoundExpression"/>
<Field Name="RightOperand" Type="BoundExpression"/>
<Field Name="LeftConversion" Type="Conversion"/>
<Field Name="OperatorResultKind" Type="BoundNullCoalescingOperatorResultKind" Null="NotApplicable"/>
</Node>
<Node Name="BoundNullCoalescingAssignmentOperator" Base="BoundExpression">
<Field Name="LeftOperand" Type="BoundExpression" />
<Field Name="RightOperand" Type="BoundExpression" />
</Node>
<Node Name="BoundConditionalOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="IsRef" Type="bool"/>
<Field Name="Condition" Type="BoundExpression"/>
<Field Name="Consequence" Type="BoundExpression"/>
<Field Name="Alternative" Type="BoundExpression"/>
<Field Name="ConstantValueOpt" Type="ConstantValue" Null="allow"/>
</Node>
<Node Name="BoundArrayAccess" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Expression" Type="BoundExpression"/>
<Field Name="Indices" Type="ImmutableArray<BoundExpression>"/>
</Node>
<!--
Represents an operation that is special in both IL and Expression trees -
getting length of a one-dimensional 0-based array (vector)
This node should not be produced in initial binding since it is not a part of
language (.Length is just a property on System.Array)
and is normally introduced during the lowering phases.
-->
<Node Name="BoundArrayLength" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Expression" Type="BoundExpression"/>
</Node>
<Node Name="BoundAwaitExpression" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Expression" Type="BoundExpression"/>
<Field Name="AwaitableInfo" Type="AwaitableInfo" Null="disallow"/>
</Node>
<AbstractNode Name="BoundTypeOf" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<!-- Well-known member populated during lowering -->
<Field Name="GetTypeFromHandle" Type="MethodSymbol" Null="allow"/>
</AbstractNode>
<Node Name="BoundTypeOfOperator" Base="BoundTypeOf">
<Field Name="SourceType" Type="BoundTypeExpression"/>
</Node>
<!-- Represents the raw metadata token index value for a method definition.
Used by dynamic instrumentation to index into tables or arrays of per-method information. -->
<Node Name="BoundMethodDefIndex" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Method" Type="MethodSymbol"/>
</Node>
<!-- Represents the maximum raw metadata token index value for any method definition in the current module. -->
<Node Name="BoundMaximumMethodDefIndex" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>
<!-- Represents the dynamic analysis instrumentation payload array for the analysis kind in the current module.
Implemented as a reference to a field of PrivateImplementationDetails, which has no language-level symbol. -->
<Node Name="BoundInstrumentationPayloadRoot" Base="BoundExpression">
<Field Name="AnalysisKind" Type="int"/>
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>
<!-- Represents the GUID that is the current module's MVID.
Implemented as a reference to PrivateImplementationDetails.MVID, which has no language-level symbol. -->
<Node Name="BoundModuleVersionId" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>
<!-- Represents a string encoding of the GUID that is the current module's MVID.
Implemented as a reference to a string constant that is backpatched after the MVID is computed. -->
<Node Name="BoundModuleVersionIdString" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>
<!-- Represents the index in the documents table of the source document containing a method definition.
Used by dynamic instrumentation to identify the source document containing a method. -->
<Node Name="BoundSourceDocumentIndex" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Document" Type="Cci.DebugSourceDocument"/>
</Node>
<Node Name="BoundMethodInfo" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Method" Type="MethodSymbol"/>
<!-- Well-known member populated during lowering -->
<Field Name="GetMethodFromHandle" Type="MethodSymbol" Null="allow"/>
</Node>
<Node Name="BoundFieldInfo" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Field" Type="FieldSymbol"/>
<!-- Well-known member populated during lowering -->
<Field Name="GetFieldFromHandle" Type="MethodSymbol" Null="allow"/>
</Node>
<Node Name="BoundDefaultExpression" Base="BoundExpression">
<!-- Type is null in the case of a default literal, and non-null for default(T). -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="allow"/>
<Field Name="ConstantValueOpt" Type="ConstantValue" Null="allow"/>
</Node>
<Node Name="BoundIsOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="TargetType" Type="BoundTypeExpression"/>
<Field Name="Conversion" Type="Conversion"/>
</Node>
<Node Name="BoundAsOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="TargetType" Type="BoundTypeExpression"/>
<Field Name="Conversion" Type="Conversion"/>
</Node>
<Node Name="BoundSizeOfOperator" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="SourceType" Type="BoundTypeExpression"/>
<Field Name="ConstantValueOpt" Type="ConstantValue" Null="allow"/>
</Node>
<Node Name="BoundConversion" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="Conversion" Type="Conversion"/>
<Field Name="IsBaseConversion" Type="bool"/>
<Field Name="Checked" Type="bool"/>
<Field Name="ExplicitCastInCode" Type="bool"/>
<Field Name="ConstantValueOpt" Type="ConstantValue" Null="allow"/>
<!--
A group instance common to all BoundConversions that represent a single Conversion. The
field is used in NullableWalker to identify the chained conversions in user-defined
conversions in particular. For instance, with the following declarations, an explicit conversion
from B to D: expr -> ImplicitReference conversion -> ExplicitUserDefined conversion ->
ExplicitReference conversion.
class A { public static explicit operator C(A a) => new D(); }
class B : A { }
class C { }
class D : C { }
ConversionGroupOpt also contains the target type specified in source in the case of
explicit conversions. ConversionGroupOpt may be null for implicit conversions if the
Conversion is represented by a single BoundConversion.
-->
<Field Name="ConversionGroupOpt" Type="ConversionGroup" Null="allow"/>
</Node>
<!--
<Node Name="BoundRefValueOperator" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Operand" Type="BoundExpression"/>
<Field Name="SourceType" Type="BoundTypeExpression"/>
</Node>
-->
<Node Name="BoundArgList" Base="BoundExpression">
<!-- This is the "__arglist" expression that may appear inside a varargs method. -->
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>
<Node Name="BoundArgListOperator" Base="BoundExpression">
<!-- This is the "__arglist(x, y, z)" expression that may appear in a call to a varargs method. -->
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="allow"/>
<Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/>
<Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/>
</Node>
<!--
Used when a fixed statement local is initialized with either a string
or an array. Encapsulates extra info that will be required during rewriting.
-->
<Node Name="BoundFixedLocalCollectionInitializer" Base="BoundExpression">
<!-- Either string or an array type. -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<!-- char* for type string, T* for type T[]. -->
<Field Name="ElementPointerType" Type="TypeSymbol" Null="disallow"/>
<!-- Conversion from ElementPointerType to the type of the corresponding local. -->
<Field Name="ElementPointerTypeConversion" Type="Conversion"/>
<!-- Wrapped expression. -->
<Field Name="Expression" Type="BoundExpression" Null="disallow"/>
<!-- optional method that returns a pinnable reference for the instance -->
<Field Name="GetPinnableOpt" Type="MethodSymbol" Null="allow"/>
</Node>
<AbstractNode Name="BoundStatement" Base="BoundNode"/>
<Node Name="BoundSequencePoint" Base="BoundStatement">
<!--
if Statement is null, a NOP may be emitted, to make sure the point is not
associated with next statement (which could be a fairly random statement in random scope).
-->
<Field Name="StatementOpt" Type="BoundStatement" Null="allow"/>
</Node>
<!--EDMAURER Use this in the event that the span you must represent
is not that of a SyntaxNode. If a SyntaxNode captures the correct span,
use a BoundSequencePoint.-->
<Node Name="BoundSequencePointWithSpan" Base="BoundStatement">
<!--
if Statement is null, a NOP may be emitted, to make sure the point is not
associated with next statement (which could be a fairly random statement in random scope).
-->
<Field Name="StatementOpt" Type="BoundStatement" Null="allow"/>
<Field Name="Span" Type="TextSpan"/>
</Node>
<!--
BoundBlock contains
a) Statements - actions performed within the scope of the block
b) Locals - local variable symbols that are visible within the scope of the block
BoundBlock specify SCOPE (visibility) of a variable.
TODO: it appears in C#, variable's extent (life time) never escapes its scope.
Is that always guaranteed or there are exceptions?
Note - in VB variable's extent is the whole method and can be larger than its scope.
That is why unassigned use is just a warning and jumps into blocks are generally allowed.
-->
<Node Name="BoundBlock" Base="BoundStatementList">
<Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="LocalFunctions" Type="ImmutableArray<LocalFunctionSymbol>"/>
</Node>
<!--
This node is used to represent a visibility scope for locals,
for which lifetime is extended beyond the visibility scope.
At the moment, only locals declared within CaseSwitchLabelSyntax
and SwitchExpressionSyntax
have their lifetime expanded to the entire switch body, whereas their
visibility scope is the declaring switch section. The node is added into
the tree during lowering phase.
-->
<Node Name="BoundScope" Base="BoundStatementList">
<Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/>
</Node>
<!--
BoundStateMachineScope represents a scope within a translated iterator/async method.
It is used to emit debugging information that allows the EE to map
fields to locals.
-->
<Node Name="BoundStateMachineScope" Base="BoundStatement">
<Field Name="Fields" Type="ImmutableArray<StateMachineFieldSymbol>"/>
<Field Name="Statement" Type="BoundStatement" Null="disallow"/>
</Node>
<!--
Bound node that represents a single local declaration:
int x = Foo();
NOTE: The node does NOT introduce the referenced local into surrounding scope.
A local must be explicitly declared in a BoundBlock to be usable inside it.
NOTE: In an error recovery scenario we might have a local declaration parsed as
int x[123] - This is an error commonly made by C++ developers who come to
C#. We will give a good error about it at parse time, but we should preserve
the semantic analysis of the argument list in the bound tree.
-->
<Node Name="BoundLocalDeclaration" Base="BoundStatement">
<Field Name="LocalSymbol" Type="LocalSymbol"/>
<!-- Only set for the first declaration in BoundMultipleLocalDeclarations
unless the type is inferred -->
<Field Name="DeclaredTypeOpt" Type="BoundTypeExpression" Null="allow"/>
<Field Name="InitializerOpt" Type="BoundExpression" Null="allow"/>
<Field Name="ArgumentsOpt" Type="ImmutableArray<BoundExpression>" Null="allow"/>
<!-- Was the type inferred via "var"? -->
<Field Name="InferredType" Type="bool"/>
</Node>
<!--
Bound node that represents multiple local declarations:
int x =1, y =2;
Works like multiple BoundLocalDeclaration nodes.
-->
<Node Name="BoundMultipleLocalDeclarations" Base="BoundStatement">
<Field Name="LocalDeclarations" Type="ImmutableArray<BoundLocalDeclaration>"/>
</Node>
<Node Name="BoundUsingLocalDeclarations" Base="BoundMultipleLocalDeclarations">
<Field Name="DisposeMethodOpt" Type="MethodSymbol" Null="Allow"/>
<Field Name="IDisposableConversion" Type="Conversion"/>
<Field Name="AwaitOpt" Type="AwaitableInfo" Null="allow"/>
</Node>
<!--
Bound node that represents a local function declaration:
void Foo() { }
-->
<Node Name="BoundLocalFunctionStatement" Base="BoundStatement">
<Field Name="Symbol" Type="LocalFunctionSymbol"/>
<Field Name="BlockBody" Type="BoundBlock" Null="allow"/>
<Field Name="ExpressionBody" Type="BoundBlock" Null="allow"/>
</Node>
<Node Name="BoundNoOpStatement" Base="BoundStatement">
<!-- No operation. Empty statement. -->
<!-- BoundNoOpStatement node may serve as a vehicle for passing some internal
information between lowering phases and/or codegen; for example, async rewriter
needs to mark some particular places in the emitted code so that we could
emit proper PDB information for generated methods.
-->
<Field Name="Flavor" Type="NoOpStatementFlavor"/>
</Node>
<Node Name="BoundReturnStatement" Base="BoundStatement">
<Field Name="RefKind" Type="RefKind"/>
<Field Name="ExpressionOpt" Type="BoundExpression" Null="allow"/>
</Node>
<Node Name="BoundYieldReturnStatement" Base="BoundStatement">
<Field Name="Expression" Type="BoundExpression" Null="disallow"/>
</Node>
<Node Name="BoundYieldBreakStatement" Base="BoundStatement"/>
<Node Name="BoundThrowStatement" Base="BoundStatement">
<Field Name="ExpressionOpt" Type="BoundExpression" Null="allow"/>
</Node>
<Node Name="BoundExpressionStatement" Base="BoundStatement">
<Field Name="Expression" Type="BoundExpression"/>
</Node>
<Node Name="BoundBreakStatement" Base="BoundStatement">
<Field Name="Label" Type="GeneratedLabelSymbol" />
</Node>
<Node Name="BoundContinueStatement" Base="BoundStatement">
<Field Name="Label" Type="GeneratedLabelSymbol" />
</Node>
<Node Name="BoundSwitchStatement" Base="BoundStatement">
<Field Name="Expression" Type="BoundExpression"/>
<!-- Locals declared immediately within the switch block. -->
<Field Name="InnerLocals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="InnerLocalFunctions" Type="ImmutableArray<LocalFunctionSymbol>"/>
<Field Name="SwitchSections" Type="ImmutableArray<BoundSwitchSection>"/>
<Field Name="DecisionDag" Type="BoundDecisionDag" Null="disallow" SkipInVisitor="true"/>
<Field Name="DefaultLabel" Type="BoundSwitchLabel" Null="allow"/>
<Field Name="BreakLabel" Type="GeneratedLabelSymbol"/>
</Node>
<!-- Part of a lowered integral switch statement. This evaluates Value, and then branches
to the corresponding Target. If no Value is equal to the input, branches to the default label.
The input Value and the constants must be of the same type. Currently emit only supports
integral types and string.
BoundSwitchDispatch is also used to mark labels in the code that will be the target of backward
branches, but should be treated as having the same stack depth as the location where
the BoundForwardLabels appears. Although we will necessarily produce some IL instructions
for this in order to comply with the verifier constraints, the effect of the code shall be
a no-op. The form of the code produced will likely be something of the form
ldc.i4.m1 // load constant -1
switch (
IL_nnnn, // all of the labels of interest
IL_nnnn,
IL_nnnn)
This is needed for the lowering of the pattern switch expression, which produces
a state machine that may contain backward branches. Due to the fact that it is an expression,
it may appear where the stack is not empty. A BoundSwitchDispatch statement (used inside of a
BoundSequence containing the state machine) permits us to (cause the verifier to) classify
all of the labels as forward labels by producing a dummy inoperable forward jump to them.
-->
<Node Name="BoundSwitchDispatch" Base="BoundStatement">
<Field Name="Expression" Type="BoundExpression" Null="disallow" />
<Field Name="Cases" Type="ImmutableArray<(ConstantValue value, LabelSymbol label)>" />
<Field Name="DefaultLabel" Type="LabelSymbol" Null="disallow" />
<!-- Equality method to be used when dispatching on a non-integral type such as string. -->
<Field Name="EqualityMethod" Type="MethodSymbol" Null="allow" />
</Node>
<Node Name="BoundIfStatement" Base="BoundStatement">
<Field Name="Condition" Type="BoundExpression"/>
<Field Name="Consequence" Type="BoundStatement"/>
<Field Name="AlternativeOpt" Type="BoundStatement" Null="allow"/>
</Node>
<AbstractNode Name="BoundLoopStatement" Base="BoundStatement">
<Field Name="BreakLabel" Type="GeneratedLabelSymbol"/>
<Field Name="ContinueLabel" Type="GeneratedLabelSymbol"/>
</AbstractNode>
<AbstractNode Name="BoundConditionalLoopStatement" Base="BoundLoopStatement">
<Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="Condition" Type="BoundExpression"/>
<Field Name="Body" Type="BoundStatement"/>
</AbstractNode>
<Node Name="BoundDoStatement" Base="BoundConditionalLoopStatement">
</Node>
<Node Name="BoundWhileStatement" Base="BoundConditionalLoopStatement">
</Node>
<Node Name="BoundForStatement" Base="BoundLoopStatement">
<!-- OuterLocals are the locals declared within the loop Initializer statement and are in scope throughout the whole loop statement -->
<Field Name="OuterLocals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="Initializer" Type="BoundStatement" Null="allow"/>
<!-- InnerLocals are the locals declared within the loop Condition and are in scope throughout the Condition, Increment and Body.
They are considered to be declared per iteration.
-->
<Field Name="InnerLocals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="Condition" Type="BoundExpression" Null="allow"/>
<Field Name="Increment" Type="BoundStatement" Null="allow"/>
<Field Name="Body" Type="BoundStatement"/>
</Node>
<Node Name="BoundForEachStatement" Base="BoundLoopStatement">
<!-- Extracted information -->
<Field Name="EnumeratorInfoOpt" Type="ForEachEnumeratorInfo" Null="allow"/>
<Field Name="ElementConversion" Type="Conversion"/>
<!-- Pieces corresponding to the syntax -->
<!-- This is so the binding API can find produce semantic info if the type is "var". -->
<!-- If there is a deconstruction, there will be no iteration variable (but we'll still have a type for it). -->
<Field Name="IterationVariableType" Type="BoundTypeExpression"/>
<Field Name="IterationVariables" Type="ImmutableArray<LocalSymbol>"/>
<!-- In error scenarios where the iteration variable is some arbitrary expression, we
stick the error recovery in this node. This will always be null in valid code. -->
<Field Name="IterationErrorExpressionOpt" Type="BoundExpression" Null="allow"/>
<!-- If this node does not have errors, then this is the foreach expression wrapped
in a conversion to the collection type used by the foreach loop. The conversion
is here so that the binding API can return the correct ConvertedType in semantic
info. It will be stripped off in the rewriter if it is redundant or causes extra
boxing. If this node has errors, then the conversion may not be present.-->
<Field Name="Expression" Type="BoundExpression"/>
<Field Name="DeconstructionOpt" Type="BoundForEachDeconstructStep" Null="allow"/>
<Field Name="AwaitOpt" Type="AwaitableInfo" Null="allow"/>
<Field Name="Body" Type="BoundStatement"/>
<Field Name="Checked" Type="bool"/>
</Node>
<!-- All the information need to apply a deconstruction at each iteration of a foreach loop involving a deconstruction-declaration. -->
<Node Name="BoundForEachDeconstructStep" Base="BoundNode">
<Field Name="DeconstructionAssignment" Type="BoundDeconstructionAssignmentOperator" Null="disallow"/>
<Field Name="TargetPlaceholder" Type="BoundDeconstructValuePlaceholder" Null="disallow"/>
</Node>
<Node Name="BoundUsingStatement" Base="BoundStatement">
<!-- DeclarationsOpt and ExpressionOpt cannot both be non-null. -->
<Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="DeclarationsOpt" Type="BoundMultipleLocalDeclarations" Null="allow"/>
<Field Name="ExpressionOpt" Type="BoundExpression" Null="allow"/>
<Field Name="IDisposableConversion" Type="Conversion" />
<Field Name="Body" Type="BoundStatement"/>
<Field Name="AwaitOpt" Type="AwaitableInfo" Null="allow"/>
<Field Name="DisposeMethodOpt" Type="MethodSymbol" Null="allow"/>
</Node>
<Node Name="BoundFixedStatement" Base="BoundStatement">
<Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/>
<Field Name="Declarations" Type="BoundMultipleLocalDeclarations"/>
<Field Name="Body" Type="BoundStatement"/>
</Node>
<Node Name="BoundLockStatement" Base="BoundStatement">
<Field Name="Argument" Type="BoundExpression"/>
<Field Name="Body" Type="BoundStatement"/>
</Node>
<Node Name="BoundTryStatement" Base="BoundStatement">
<Field Name="TryBlock" Type="BoundBlock"/>
<Field Name="CatchBlocks" Type="ImmutableArray<BoundCatchBlock>"/>
<Field Name="FinallyBlockOpt" Type="BoundBlock" Null="allow"/>
<!--
When lowering trys, we sometimes extract the finally clause out of the try.
For example, `try { } finally { await expr; }` becomes something like `try { } catch { ... } finallyLabel: { await expr; ... }`.
We need to save the label for the finally so that async-iterator rewriting can implement proper disposal.
-->
<Field Name="FinallyLabelOpt" Type="LabelSymbol" Null="allow"/>
<!--
PreferFaultHandler is a hint to the codegen to emit Finally in the following shape -
try
{
}
fault
{
finallyBlock
}