-
Notifications
You must be signed in to change notification settings - Fork 0
/
sprut.sgml.in
1585 lines (1431 loc) · 71.4 KB
/
sprut.sgml.in
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
<!doctype linuxdoc system>
<article>
<!-- Title information -->
<title>SPRUT (internal representation description translator)
<author>Vladimir Makarov, <tt>vmakarov@gcc.gnu.org</tt>
<date>Apr 5, 2001
<abstract>
This document describes SPRUT (translator of a compiler internal
representation into standard procedural interface).
</abstract>
<toc>
<sect>Introduction
<p>
SPRUT is a translator of a compiler internal representation
description (IRD) into Standard Procedural Interface (SPI). The most
convenient form of the internal representation is a directed graph.
IRD defines structure of the graph. SPI provides general graph
manipulating functions. The defined graph nodes can be decorated with
attributes of arbitrary types.
IRD declares types of nodes of the graph. Nodes contains fields, part
of them represents links between nodes, and another part of them
stores attributes of arbitrary types. To make easy describing
internal representation the IRD supports explicitly single inheritance
in node types and also can model multiple inheritance. There can be
several levels of internal representation description in separate
files. The nodes of one level refer to the nodes of previous levels.
Therefore each next level enriches source program internal
representation. For example, the zero level representation may be
internal representation for scanner, the first level may be internal
representation for parser, and so on.
SPI can contains functions to construct and destroy graphs and graph
nodes, to copy graphs or graph nodes, to read and write graphs or
graph nodes from (to) files, to print graphs or graph nodes, to check
up constraints on graph, to traverse graphs, and to transform acyclic
graphs in some commonly used manners. SPI can also check up the most
important constraints on internal representation during work with node
fields. SPI can automatically maintain back links between internal
representation nodes.
Using SPRUT has the following advantages:
<enum>
<item>brief and concise notation for internal representation
<item>improving maintainability and as consequence reliability of
the compiler
<item>user is freed from the task of writing large amounts of
relatively simple code
</enum>
The following sections define the internal representation description
language, explain SPI, and present some examples.
<sect>Internal representation description language
<p>
IRD declares types of nodes of the graph. Nodes contains fields, part
of them represents links between nodes, and another part of them
stores attributes of arbitrary types. To make easy describing
internal representation the IRD supports explicitly single inheritance
in node types and also can model multiple inheritance. There can be
several levels of internal representation description in separate
files. The nodes of one level refer to the nodes of previous levels.
Therefore each next level enriches source program internal
representation.
<sect1>Layout of internal representation description
<p>
To describe internal representation a special language is used. An
internal representation description structure has the following layout
which is similar to one of YACC file.
<tscreen><verb>
DECLARATIONS
%%
TYPES OF NODES
%%
ADDITIONAL C/C++ CODE
</verb></tscreen>
The `%%' serves to separate the sections of description. All sections
are optional. The first `%%' starts section of description of types
of internal representation nodes and is obligatory even if the section
is empty, the second `%%' may be absent if section of additional C/C++
code is absent too.
The section of declarations may contain names of predefined types of
fields of internal representation nodes and names of types of double
linked nodes. The section also contains name of original internal
representation description if given file contains extension of an
internal representation description. And finally the section may
contains sections of code on C/C++.
The next section contains description of types of internal
representation nodes.
The additional C/C++ code can contain any C/C++ code you want to use.
Often functions which are not generated by the translator but are
needed to work with internal representation go here. This code
without changes is placed at the end of file generated by the
translator.
<sect1>Declarations
<p>
The section of declarations may contain the following construction.
<tscreen><verb>
%type IDENTIFIER ...
</verb></tscreen>
All predefined types must be defined in constructions of such kind.
The same name can be defined repeatedly. All references to node whose
type is a sub-type of type with name present in the following
construction will be double linked.
<tscreen><verb>
%double IDENTIFIER ...
</verb></tscreen>
It means that SPI will generates functions (macros) which permit to
examine all fields (may be in other nodes) described as of given node
type (or its subtype) which refer to node of given type (or its
sub-type), i.e. fields which are described as of given node type (or
its subtype) will be double linked (see below). SPI will
automatically maintain such double links. The simplest way to
describe double linked graph is to insert construction
<tscreen><verb>
%double %root
</verb></tscreen>
Last construction in the section of declarations of kind
<tscreen><verb>
%extend IDENTIFIER
</verb></tscreen>
defines name (without suffix) of file containing source internal
representation which is extended by given file. The file contains
original internal representation if there is no one such construction.
The original specification file has level 0, the extensions have level
1, 2, and so on. This feature permits sequentially to develop an
internal representation and to save and restore any its level (see
SPI) to additional tools, e.g. browsers. For example, there may be
three levels of source program internal representation. The zero
level representation may be internal representation for semantic
analysis, the first level may be a low level machine-dependent
internal representation, and the second level may be used to generate
object code. Only first such construction in one file is essential.
All subsequent such constructions are ignored.
There may be also the following constructions in the declaration
section
<tscreen><verb>
%local {
C/C++ DECLARATIONS
}
%import {
C/C++ DECLARATION
}
and
%export {
C/C++ DECLARATION
}
</verb></tscreen>
which contain any C/C++ declarations (types, variables, macros, and so
on) used in the description sections.
The local C/C++ declarations are inserted at the begin of generated
implementation file (see SPI description) but after include-directive
of interface file.
C/C++ declarations which start with `%import' are inserted at the
begin of generated interface file. For example, such C/C++ code may
contain C/C++ definitions of predefined types which are used in field
declarations of node types.
C/C++ declarations which start with `%export' are inserted at the end
of generated interface file. For example, such C/C++ code may contain
definitions of external variables and functions which refer to node
type representation (see type `IR_node_t' in SPI description).
All C/C++ declarations can redefine all type specific and internal
macros (see SPI) because they are placed in implementation file. All
C/C++ declarations are placed in the same order as in the section of
declarations. C/C++ declarations from IRD file with smaller level
number (see construction `%extend') are placed in interface or
implementation files firstly.
<sect1>Types of nodes
<p>
The section of declarations is followed by section defining internal
representation node types. An internal node type is described by the
following construction
<tscreen><verb>
%abstract
IDENTIFIER :: IDENTIFIER (or %root)
CLASS FIELDS
SKELETON FIELDS
OTHER FIELDS
</verb></tscreen>
Keywords `%abstract' is optional. Node type description which starts
with this keyword denotes abstract node type, i.e. node of such type
does not exist in internal representation of any source program.
Abstract nodes types serve only to description of common fields of
several node types.
The first identifier defines name of internal representation node
type, the second defines name of node type all declarations of fields
of which are inherited into the given node type. In this construction
the first node type is so called immediate super type, the second is
immediate sub-type.
Node type A is a super-type of node type B (and node type B is a
sub-type of node type A) iff node type A is immediate super-type of
super-type of node type B. All node types are sub-types of implicitly
declared node type with name `%root'. There are also nodes of special
type (error nodes). Type of these nodes are believed to be sub-type
of all declared node types. The definition of type of error nodes are
absent in any internal representation description.
The identifier of immediate super-type (with `::') can be absent. In
this case the construction is continuation of given type node
declaration. There can be only the single main node type declaration
and many its continuations. The order of main node type declaration
and its continuations can be arbitrary. The continuations can not
start with keyword `%abstract'.
Construction of the following kind
<tscreen><verb>
A, B, ... :: C
DECLARATIONS OF FIELDS
</verb></tscreen>
is abbreviation of the following constructions
<tscreen><verb>
A :: C
DECLARATIONS OF FIELDS
B :: C
DECLARATIONS OF FIELDS
...
</verb></tscreen>
The fields are sub-divided on kinds. There are three kinds of fields.
<enum>
<item>Class fields. There is the single instance of a class field
for all nodes of given type.
<item>Skeleton fields. There is the single instance of a skeleton
fields for each node of given type. The value of skeleton
field is to be given by user at the node creation moment (see
SPI description).
<item>Other fields. This kind of fields is analogous to one of
skeleton fields but value of such field is not given by user
at the node creation moment.
</enum>
Optional sections of declarations of class fields, skeleton fields,
and other fields start correspondingly with keywords `%class',
`%skeleton', and `%other'.
<tscreen><verb>
%class LIST OF DECLARATIONS OF FIELDS
%skeleton LIST OF DECLARATIONS OF FIELDS
%other LIST OF DECLARATIONS OF FIELDS
</verb></tscreen>
These keywords are followed by may be empty list of declarations of
fields. The list elements are field declaration or target code.
Field declaration is described by the following construction:
<tscreen><verb>
IDENTIFIER : FIELD %double TYPE CONSTRAINTS ACTIONS
</verb></tscreen>
Identifier is name of given field. All declarations of fields of a
node type must have unique names. But declarations of fields of
different node types can have the same names if the types of such
fields are the same, the fields are simultaneously described as double
linked or not, and all such fields are class or any non-class fields.
Owing to the feature it is possible to model multiple inheritance.
Semicolon `:' is followed by the field type. There are the following
types of nodes fields:
<enum>
<item>identifier from a clause `%type'. The identifier represents
predefined type and must be declared anywhere by the
construction `typedef' of C/C++.
<item>node name. This type represents arc to a node of given type
or its subtypes and is implemented by pointer of C/C++.
</enum>
These constructions can have optional clause `%double'. Its sense is
slightly different from the one in the declarations section. This
clause means that SPI will generate functions (macros) which permits
to examine all nodes of the declared type (or its sub-type) which
refer through given field to a node of the field type (or its
sub-type). The clause `%double' can not be given for class fields.
The field type may be followed by constraints and actions in any
order. The constraint is usually present for non-null value node
reference. The constraint is a boolean expression on C/C++ in
brackets `[' and `]'. The constraints are tested with the aid of some
generated functions in the same order as they are present in
corresponding type node declaration. The actions can contain any
statements on C/C++ in figure brackets `{' and `}' (the brackets are
also output therefore C/C++ declarations can be in actions). The
actions for skeleton and other fields are fulfilled at the node
creation time in the same order as they are present in corresponding
type node declaration. The actions for class fields are fulfilled at
the internal representation initiation time.
Constructions `$$', `$' in the constraints and the actions represent
correspondingly current node and previous field. But `$' is not
changed by the previous field if the previous field in given node type
declaration is of other kind than the constraint or action (e.g. the
field of skeleton kind and the constraint of class kind) or such field
does not exist in the current node type declaration. Also it should
be remembered that `$' can not be used in left hand side of assignment
if the construction represent double linked fields.
The construction `IDENTIFIER : FIELD TYPE' may be absent. This case
is convenient for definition of additional constraints and actions for
fields which declared in a super-type of given node type.
Construction of kind
<tscreen><verb>
A, B, ... : C ...
</verb></tscreen>
is abbreviation of the following constructions
<tscreen><verb>
A : C ...
B : C ...
</verb></tscreen>
Full YACC syntax of internal representation description language is
placed in Appendix 1.
<sect>Standard Procedural Interface
<p>
An internal representation description is translated by SPRUT
(internal representation definition translator) into a standard
procedural interface (SPI). If the specification file is an extension
(see the language description) of another specification file the later
is also used to SPI generation and so on. SPI consists of interface
and implementation files having the same names as one of the
specification file and correspondingly suffixes `.h' and `.c' (C code)
or `.cpp' (C++ code).
<sect1>C SPI
<p>
By default (when option `-c++' is not present on the command line)
SPRUT generates C SPI. The following subsections describe C SPI.
<sect2>C SPI types, variables, macros
<p>
Interface file of SPI consists of C declarations of the following
types, variables and macros.
<enum>
<item>Type `IR_node_mode_t' is represented by enumeration
definition. There is enumeration constant with node type name
and prefix `IR_NM_' for each node type declaration even for
abstract node type. Also there are enumeration constants with
names `IR_NM__root' and `IR_NM__error' for and predefined type
`%root' and for error nodes. `IR_NM' is abbreviation of
internal representation node mode. There is also the
enumeration name `IR_node_mode_enum' which is convenient to
use in imported section for forward definition of pointer to
this enumeration.
<item>Type `IR_node_t' represents a node (more correctly pointer to
a structure representing node). There are the type value
`NULL' reserved to represent none node.
<p>
The structure of this type is opaque and all work with nodes
are to be fulfilled through macros (or/and functions). But to
show efficacy of types implementation it should be said that
every node type is turned into a structure declaration. All
these structures have first member of type `IR_node_mode_t'.
Other members represent the node fields except for class
field. Depending on SPRUT command line option
`-flat-structure' (see SPRUT usage) this structure can contain
also members corresponding to fields declared in super types
of given node type or member which type is structure
corresponding to immediate super type of given node type.
Class fields for each non-abstract node type are represented
by only one separate structure.
<p>
The fields in different node types with the same name (when it
is consequence of existing common super type with this field)
have the same displacement from the structure begin because
types of previous fields is guaranteed to be the same in these
structures. The fields in different node types with the same
name (when it is not consequence of existing common super type
with this field) may have the different displacement from the
structure begin therefore access to such fields requires
additional indirect addressing.
<p>
Double linked field (see internal representation description
language) requires more memory (about in five times) for its
implementation. Speed of SPI work with double linked fields
is sightly slower. Because additional work is needed only to
setting up the field value and my experience shows that
usually number of setting up fields value is less than number
of their fetching about in ten times.
<p>
Type `IR_node_t' is simply pointer to struct representing node
type `%root'. The name of this structure is `IR_node'.
This name can be used in imported section for forward
reference for nodes (instead of `IR_node_t').
<item>Optional variable `IR_node_name' is array mapping values of type
`IR_node_mode_t' to names (strings) in C. (see also
option -no-node-name in SPRUT usage).
<item>Variable `IR_node_size' is array mapping values of type
`IR_node_mode_t' to size of corresponding structures on C.
<item>Macro `IR_IS_TYPE(type, supertype)' is evaluated as nonzero if
the first argument of type `IR_node_mode_t' is equal to the
second argument or node type represented by the first argument
is a sub-type of node type represented by the second argument.
Otherwise the macro returns zero. But this macro returns
always zero for any error node, i.e. this macro can be used
to define that the node of the first mode has fields of the
node of the second mode.
<item>Macro `IR_NODE_MODE(node)' returns node mode represented by
value of type `IR_node_mode_t' for node given as the macro
argument of type `IR_node_t'.
<item>Macro `IR_IS_OF_TYPE(node, supertype)' is abbreviation of
frequently used `IR_IS_TYPE (IR_NODE_MODE (node), supertype)'.
<item>Macro `IR_NODE_LEVEL(node)' has value which is internal
representation description level in which declaration of given
node type starts.
</enum>
<sect2>C Functions
<p>
SPI interface file also contains definitions of generated functions to
creation, deletion, modification, comparison, copy, check, print, and
binary input/output of internal representation nodes and functions for
access to values of internal representation node fields.
These functions do not permit to work with abstract nodes. Only one
graph function can be active, e.g. call of function `IR_check_graph'
is not permitted during work of any traverse or transformation
function.
Macros can be generated with or instead of the functions for access to
internal representation node fields. This feature should be used if
used C preprocessor has not rigid constraints on number of defined
macros. Because macros arguments may be evaluated many times no
side-effects should be in the arguments.
<enum>
<item>Access functions (or/and macros). These functions are
generated when option `-access' is present in the SPRUT command
line. If option `-macro' is used the access functions and
macros are generated. If option `-only-macro' is used only
access macros are generated. Only option `-macro' or
`-only-macro' can be on the command line of SPRUT. There is
one function for each field with unique name. Access function
has name formed from prefix `IR_' and corresponding field
name. There is one exception. When access functions and
macros are generated, macros have names starting with prefix
`IR_' and the functions have names starting with prefix
`IR_F_'. Access function has one argument of type `IR_node_t'.
The argument represents node which must have such field. Type
of returned value is predefined type (if the field is of such
type) or `IR_node_t' (if the field is of a node type).
<p>
Functions
<tscreen><verb>
`IR_double_link_t IR__first_double_link (IR_node_t node)',
`IR_double_link_t IR__next_double_link
(IR_double_link_t prev_double_link)',
`IR_double_link_t IR__previous_double_link
(IR_double_link_t next_double_link)'
</verb></tscreen>
return references to fields which have double links to given
node. Functions `IR__first_double_link' is always implemented
by function. The node itself which contains such links can be
determined by function
<tscreen><verb>
`IR_node_t IR__owner (IR_double_link_t link)'.
</verb></tscreen>
Here type `IR_double_link_t' represents pointer to double
fields. The functions may also check up that the node has
given field (see SPRUT options).
<item>Modification functions. These functions are generated when
option `-set' is present in the SPRUT command line. There is
one functions for each field with unique name. Modification
function has name formed from prefix `IR_set_' and
corresponding field name.
<p>
Modification function has two arguments. The first argument of
type `IR_node_t' represents node which must have such field.
The second argument of predefined type (if the field is of
such type) or of type `IR_node_t' (if the field is of a node
type) represents new value of the field.
<p>
The function may check up constraint if the field represents
arc to node of a node type or its sub-types (see SPRUT
options). The functions may also check up that the node has
given field.
<p>
There is also function for modification of double links
<tscreen><verb>
`void IR__set_double_link (IR_double_link_t double_link,
IR_node_t value)'
</verb></tscreen>
Remember that values of `IR__next_double_link' and
`IR__previous_double_link' are changed after calling this
function.
<item>Function
<tscreen><verb>
`IR_node_t IR_create_node (IR_node_mode_t node_mode)'
</verb></tscreen>
is generated in any case. This function allocates storage for
node of any type (except for abstract) represented by the
argument (it can be also `IRNM__error), sets up node mode and
node level, fulfills fields assignments (except for class
fields) in the same order as the fields are declared. The
field assignment is fulfilled according to type specific
operation (see section `Type specific macros') and actions
which are defined after given field in sections of skeleton
and other fields of corresponding node type. After that the
function returns the created node. The single way to create
error nodes is to use this function with argument
`IRNM__error'.
<item>Node type specific creation functions. These functions are
generated when option `-new' is present in the SPRUT command
line. There is one function for each node type (except for
abstract). Names of functions are formed from prefix
`IR_new_' and corresponding node type name. The number of
parameters of a function is equal to one of skeleton fields of
corresponding node type. The parameters of these functions
have to be given in the order of the skeleton fields in the
specification. Fields of the super-type (recursively) precede
the ones of the sub-type.
<p>
These functions may check up constraints on skeleton fields
which represent arc to node of a node type or its sub-types
(see SPRUT options). These functions call node creation
function and after that assign parameters values to
corresponding skeleton fields. After that the functions
return the created node. These functions provide a mechanism
similar to record aggregates. Nested calls of such functions
allow programming with terms as in LISP.
<item>Function
<tscreen><verb>
`void IR_free_node (IR_node_t node)'
</verb></tscreen>
is generated when option `-free' or `-free-graph' is present
in the SPRUT command line. This function deletes given node.
The deletion consists of evaluation of finalization macros for
node fields (see field type specific macros) in reverse order
and all node space deallocation. The function also delete
double linked fields of given node from the corresponding
lists of double linked fields. But the user should know that
there may be dangling references to given node itself after
the function call. The function does nothing if the parameter
value is equal to NULL.
<item>Function
<tscreen><verb>
`void IR_free_graph (IR_node_t graph)'
</verb></tscreen>
is generated when option `-free-graph' is present in the SPRUT
command line. This function deletes given node and all nodes
accessible from given node `graph'. The nodes are deleted in
depth first order. The function does nothing if the parameter
value is equal to NULL.
<item>Function
<tscreen><verb>
`void IR_conditional_free_graph
(IR_node_t graph,
int (*guard) (IR_node_t node))'
</verb></tscreen>
is generated when option `-free-graph' is present in the SPRUT
command line. This function deletes given node and all nodes
accessible from given node `graph'. The nodes are deleted in
depth first order. The function does nothing if the parameter
value is equal to NULL. The processing (traversing and
deleting) children of node which is passed to the
parameter-function is not fulfilled if the parameter-function
returns zero. All graph is deleted when the returned value is
always nonzero.
<item>Function
<tscreen><verb>
`IR_node_t IR_copy_node (IR_node_t node)'
</verb></tscreen>
is generated when option `-copy' or `-copy-graph' is present
in the SPRUT command line. This function makes copy of given
node. Field type specific macros are used (see section `Type
specific macros') to make this. The function only returns
NULL if the parameter value is equal to NULL.
<item>Function
<tscreen><verb>
`IR_node_t IR_copy_graph (IR_node_t graph)'
</verb></tscreen>
is generated when option `-copy-graph' is present in the
command line. This function makes copy of graph given by its
node `graph'. The function only returns NULL if the parameter
value is equal to NULL.
<item>Function
<tscreen><verb>
`IR_node_t IR_conditional_copy_graph
(IR_node_t graph,
int (*guard) (IR_node_t node))'
</verb></tscreen>
is generated when option `-copy-graph' is present in the
command line. This function makes copy of graph given by its
node `graph'. The function only returns NULL if the parameter
value is equal to NULL. The processing (traversing and
copying) children of node which is passed to the
parameter-function is not fulfilled if the parameter-function
returns zero. All nodes of graph are copied when the returned
value is always nonzero.
<item>Function
<tscreen><verb>
`int IR_is_equal_node (IR_node_t node_1,
IR_node_t node_2)'.
</verb></tscreen>
is generated when option `-equal' or `-equal-graph' is present
in the SPRUT command line. This function returns nonzero iff
`node_1' is equal to `node_2', i.e. node_1 and node_2 have
the same type and all fields of `node_1' are equal to the
corresponding fields of `node_2'. Field type specific macros
are used (see section `Type specific macros') to make this.
The function return nonzero if parameter values are equal to
NULL.
<item>Function
<tscreen><verb>
`int IR_is_equal_graph (IR_node_t graph_1,
IR_node_t graph_2)'
</verb></tscreen>
is generated when option `-equal-graph' is present in the SPRUT
command line. This function returns nonzero iff graph
starting with node `graph_1' is equal to graph starting with
node `graph_2', i.e. the graphs have the same structure and
all predefined type fields of `graph_1' are equal to the
corresponding fields of `graph_2'. The function returns TRUE
if parameter values are equal to NULL.
<item>Function
<tscreen><verb>
`int IR_is_conditional_equal_graph
(IR_node_t graph_1, IR_node_t graph_2,
int (*guard) (IR_node_t node))'
</verb></tscreen>
is generated when option `-equal-graph' is present in the SPRUT
command line. This function returns nonzero iff graph
starting with node `graph_1' is equal to graph starting with
node `graph_2', i.e. the graphs have the same structure and
all predefined type fields of `graph_1' are equal to the
corresponding fields of `graph_2'. The function returns TRUE
if parameter values are equal to NULL. The processing
(traversing and comparing) children of node which is passed to
the parameter-function is not fulfilled if the
parameter-function returns zero. All nodes of the graphs are
compared when the returned value is always nonzero.
Unprocessed graph nodes are believed to be equal.
<item>Function
<tscreen><verb>
`int IR_check_node (IR_node_t node,
int class_field_flag)'
</verb></tscreen>
This function is generated when option `-check' or
`-check-graph' is present in the SPRUT command line. By
default the most of generated functions (and macros) which
work with internal representation nodes do not check up
constraints which described in the specification.
<p>
There are two kinds of constraints. The first is constraint
on field which represents arc to node of given type or its
sub-types. The second is constraint which defined by target
code (see the internal representation definition language).
The user is responsible to adhere to the constraints.
Function `IR_check_node' can be used to check all constraints
corresponding to given node. The function does nothing if the
parameter value is equal to null. In case of a constraint
violation the involved node and all child nodes are printed on
standard error and the function returns nonzero (error flag).
If the second parameter value is zero then class fields of
given node are not checked up.
<item>Function
<tscreen><verb>
`int IR_check_graph (IR_node_t graph,
int class_field_flag)'
</verb></tscreen>
is generated when option `-check-graph' is present in the sprut
command line. This function checks given node `graph' and all
nodes accessible from given node. It should be known that a
class field is processed only when the second parameter value
is nonzero. The function does nothing if the parameter value
is equal to null. In case of fixing any constraint violation
returns nonzero (error flag).
<item>Function
<tscreen><verb>
`int IR_conditional_check_graph
(IR_node_t graph, int class_field_flag,
int (*guard) (IR_node_t node))'
</verb></tscreen>
is generated when option `-check-graph' is present in the sprut
command line. This function checks given node `graph' and all
nodes accessible from given node. It should be known that a
class field is processed only when the second parameter value
is nonzero. The function does nothing if the parameter value
is equal to null. In case of fixing any constraint violation
returns nonzero (error flag). The processing (traversing and
checking) children of node which is passed to the
parameter-function is not fulfilled if the parameter-function
returns zero. All nodes of graph are checked when the
returned value is always nonzero. It is better to free
changed nodes which are not used after transformation
especially when there are double links to the nodes (otherwise
the nodes can be accessible with the aid of functions for work
with double links).
<item>Function
<tscreen><verb>
`void IR_print_node (IR_node_t node,
int class_field_flag)'
</verb></tscreen>
is generated when option `-print' is present in the sprut
command line or options `-check' or `check-graph' is present
because check functions use this print function. The function
outputs values of node fields with their names to standard
output in readable form. To make this the function outputs
sequentially all the node fields (including class fields if
the second parameter value is nonzero) with the aid of field
type specific macros (see below). The function does nothing
if the parameter value is equal to null.
<item>Functions
<tscreen><verb>
`int IR_output_node (FILE *output_file, IR_node_t node,
int level)',
`IR_node_t IR_input_node (FILE *input_file,
IR_node_t *original_address)'
</verb></tscreen>
are generated when option correspondingly `-output' or
`-input' is present in the SPRUT command line.
<p>
Function `IR_output_node' writes node to given file. To make
this the function outputs the second parameter value, node
address and after that sequentially all the node fields
(except for class fields) whose declarations are present in
internal representation description of `level' or less than
the one (see internal representation description language).
The node type must be also declared in internal representation
description of `level' or less than the one. The function
does nothing if the value of parameter `node' is equal to
NULL. A nonzero function result code means fixing an error
during output.
<p>
Function `IR_input_node' reads node from given file, allocates
space for the node, initiates its fields and changes the node
fields output early. To make this the function uses function
`create_node'. The output level of input node must be less or
equal to the internal representation level of given SPI. Null
value returned by the function means fixing an error during
input. The function returns original address of input node
through the second parameter. The output and input of fields
is fulfilled with the aid of field type specific macros (see
section `Type specific macros').
<item>Function
<tscreen><verb>
`void IR_traverse_depth_first
(IR_node_t graph, int class_field_flag,
void (*function) (IR_node_t node))'
</verb></tscreen>
is generated when option `-traverse' is present in the SPRUT
command line. This function traverses graph given by its node
`graph' depth first (it means bottom up for tree). Arcs
represented by class fields are included in this graph if the
second parameter value is nonzero. At every node a function
given as parameter is executed. Arcs implementing lists of
double linked fields are not traversed. The function does
nothing if the `graph' parameter value is equal to NULL.
<item>Function
<tscreen><verb>
`void IR_traverse_reverse_depth_first
(IR_node_t graph, int class_field_flag,
int (*function) (IR_node_t node))'
</verb></tscreen>
is generated when option `-reverse-traverse' is present in the
SPRUT command line. This function is analogous to the previous
but the graph is traversed in reverse depth first order (it
means top down order for tree). The traverse of children of
node which is passed to the parameter-function is not
fulfilled if the parameter-function returns zero. All graph
is traversed when the returned value is always nonzero.
<item>Function
<tscreen><verb>
`IR_node_t IR_transform_dag
(IR_node_t graph, int class_field_flag,
int (*guard_function) (IR_node_t node),
IR_node_t (*transformation_function) (IR_node_t node))'
</verb></tscreen>
is generated when option `-transform' is present in the SPRUT
command line. This function is used for transformation of
directed acyclic graphs. This is needed for various goals,
e.g. for constant folding optimization. At first the function
calls guard function. If the guard function returns zero, the
function return the first parameter. Otherwise when the guard
function returns nonzero, all fields (including class fields
if parameter `class_field_flag' is nonzero) of given node are
also processed, i.e. the fields values are changed. And
finally the node itself is processed by the transformation
function (remember that the transformation function is never
called for nodes which are parts of a graph cycle), and the
result of transformation function is the result of given
function.
<item>Function
<tscreen><verb>
`void IR_start (void)'
</verb></tscreen>
is generated in any case. This function is to be called
before any work with internal representation. The function
initiates internal representation storage management (see next
section), fulfills class field type specific initializations,
evaluates actions bound to class fields, and make some other
initiations.
<item>Function
<tscreen><verb>
`void IR_stop (void)'
</verb></tscreen>
is generated in any case. The call of this function is to be
last. The function fulfills class field type specific
finalizations and finishes internal representation storage
management.
</enum>
<sect1>C++ SPI
<p>
SPRUT generates C++ SPI only when option `-c++' is present on the
command line. Mainly C++ SPI is analogous to one on C. Major
difference is that `IR_node_t' and `IR_double_link_t' are pointer to
classes not to structures. As the consequence, the most of functions
are public or friend functions of the classes.
<sect2>C++ SPI types, variables, macros
<p>
C++ interface file of SPI consists of C++ declarations of the following
types, variables.
<enum>
<item>Type `IR_node_mode_t' is represented by enumeration
definition. There is enumeration constant with node type name
and prefix `IR_NM_' for each node type declaration even for
abstract node type. Also there are enumeration constants with
names `IR_NM__root' and `IR_NM__error' for and predefined type
`%root' and for error nodes. `IR_NM' is abbreviation of
internal representation node mode. There is also the
enumeration name `IR_node_mode_enum' which is convenient to
use in imported section for forward definition of pointer to
this enumeration.
<item>Type `IR_node_t' represents a node (more correctly pointer to
a class representing node). There are the type value
`NULL' reserved to represent none node.
<p>
The class of this type is opaque (i.e. there are not public
variables in the class) and all work with nodes are to be
fulfilled through public or friend functions. But to show
efficacy of types implementation it should be said that every
node type is turned into a structure declaration. All these
structures have first member of type `IR_node_mode_t'. Other
members represent the node fields except for SPRUT class
field. Depending on SPRUT command line option
`-flat-structure' (see SPRUT usage) this structure can contain
also members corresponding to fields declared in super types
of given node type or member which type is structure
corresponding to immediate super type of given node type.
SPRUT class fields for each non-abstract node type are
represented by only one separate structure.
<p>
The fields in different node types with the same name (when it
is consequence of existing common super type with this field)
have the same displacement from the structure begin because
types of previous fields is guaranteed to be the same in these
structures. The fields in different node types with the same
name (when it is not consequence of existing common super type
with this field) may have the different displacement from the
structure begin therefore access to such fields requires
additional indirect addressing.
<p>
Double linked field (see internal representation description
language) requires more memory (about in five times) for its
implementation. Speed of SPI work with double linked fields
is sightly slower. Because additional work is needed only to
setting up the field value and my experience shows that
usually number of setting up fields value is less than number
of their fetching about in ten times.
<p>
Type `IR_node_t' is simply pointer to class representing node
type `%root'. The name of this class is `IR_node'.
This name can be used in imported section for forward
reference for nodes (instead of `IR_node_t').
<item>Optional variable `IR_node_name' is array mapping values of
type `IR_node_mode_t' to names (strings) in C++ (see also
option -no-node-name in SPRUT usage).
<item>Variable `IR_node_size' is array mapping values of type
`IR_node_mode_t' to size of corresponding structures on C++.
</enum>
<sect2>C++ Functions
<p>
C++ SPI interface file also contains definitions of generated
functions to quering characteritics of nodes, creation, deletion,
modification, comparison, copy, check, print, and binary input/output
of internal representation nodes and functions for access to values of
internal representation node fields.
These functions do not permit to work with abstract nodes. Only one
graph function can be active, e.g. call of function `IR_check_graph'
is not permitted during work of any traverse or transformation
function.
For sake of efficacy, the part of functions (access to internal
representation node fields and quering charateristics of the nodes) is
generated as inline.
<enum>
<item>Function `IR_is_type (IR_node_mode_t type, IR_node_mode_t
super)' which is public static (i.e. which is relative to
class not to a object of the class) function of class
`IR_node' is evaluated as nonzero if the first argument of
type `IR_node_mode_t' is equal to the second argument or node
type represented by the first argument is a sub-type of node
type represented by the second argument. Otherwise the
function returns zero. But this function returns always zero
for any error node, i.e. this function can be used to define
that the node of the first mode has fields of the node of the
second mode.
<item>Function `IR_node_mode (void)' declared as public in the class
`IR_node' returns node mode represented by value of type
`IR_node_mode_t' for given node.
<item>Function `IR_is_of_type (IR_node_mode_t super)' declared as
public in the class `IR_node' is abbreviation of frequently
used `IR_is_type (node->IR_node_mode (), super)'.
<item>Function `IR_node_level (void)' declared as public in the
class `IR_node' has value which is internal representation
description level in which declaration of given node type
starts.
<item>Access functions. These functions declared as public in the
class `IR_node' are generated when option `-access' is present
in the SPRUT command line. There is one function for each
field with unique name. Access function has name formed from
prefix `IR_' and corresponding field name. Access function
has no arguments. Type of returned value is predefined type
(if the field is of such type) or `IR_node_t' (if the field is
of a node type).
<p>
Function declared as public in the class `IR_node'
<tscreen><verb>
`IR_double_link_t IR__first_double_link (void)'
</verb></tscreen>
and functions declared as public in the class for which
pointer of type `IR_double_link_t' refers
<tscreen><verb>
`IR_double_link_t IR__next_double_link (void)',
`IR_double_link_t IR__previous_double_link (void)'
</verb></tscreen>
return pointer to fields which have double links to given
node. The node itself which contains such links can be
determined by function declared as public in the class for
which pointer of type `IR_double_link_t' refers
<tscreen><verb>
`IR_node_t IR__owner (void)'.
</verb></tscreen>
Here type `IR_double_link_t' represents pointer to class
representing double fields. The functions may also check up
that the node has given field (see SPRUT options).