In some cases, for example, when automatic instantiation cannot be used effectively, the programmer has the option of using explicit (manual) instantiation in order to extend the sources as required.
To make this process easier, it is possible to create an ETR file (ETR - Explicit Template Request) which contains the instantiation statements for the templates used and which can be incorporated into a source.
The options for creating this ETR file can be specified with the GENERATE-ETR-FILE operand of the SDF statement MODIFY-DIAGNOSTIC-PROPERTIES (see "MODIFY-DIAGNOSTIC-PROPERTIES ").
The important options are *ALL..., which outputs all relevant information and *ASSIGNED..., which only outputs part of this information.
The templates taken into account during the ETR analysis can be divided into the following classes:
Templates that are instantiated explicitly in the compilation unit. These are output with “ALL”.
Templates that are assigned by the prelinker to the compilation unit and then instantiated within the compilation unit. These can be output using both “ALL” and “ASSIGNED”.
Templates that are used in the compilation unit and that can be instantiated here. These are output with “ALL”.
Templates that are used in the compilation unit, but cannot be instantiated here. These are output with “ALL”.
The contents of an ETR file have the following format:
Comments in the header will indicate that the file is a generated file.
Three logical lines are created for each template (see the example below):
a comment line containing the text ’The following template was’
a comment line containing the type of the instance (for example, ’explicitly instantiated’)
a line which describes the explicit instantiation for this instance. This line contains the external name of the instance. This name is the same as the entry in the ii file (see section “The II-UPDATE tool”) and can also be obtained from the binder listing or the binder error listing
Notes
If the lines described above are too long, they will be wrapped in the usual C++ fashion using “Backslash newline”.
The sequence of the output templates is not defined. If recompilation takes place or a source is modified, the sequence may change.
The third logical line is particularly interesting when copying to a source.
The comments are always in English.
The following two scenarios describe sensible uses of an ETR file:
The compiler is called during development using the INSTANTIATION=*AUTO option of the SDF statement MODIFY-SOURCE-PROPERTIES and the GENERATE-ETR-FILE=*ASSIGNED option of the SDF statement MODIFY-DIAGNOSTIC-PROPERTIES.
The instantiation statements output to the ETR files are incorporated into the appropriate sources. Productive operation is then activated using the INSTANTIATION=*NONE or *AUTO option in the SDF statement MODIFY-SOURCE-PROPERTIES the next time the compiler is called.
The advantage of this method is the considerable reduction in the time it takes to complete prelinking during productive operation.The compiler is called during development using the INSTANTIATION=*NONE and GENERATE-ETR-FILE=*ALL-INSTANTIATIONS option (of the SDF statements as described above).
After linking the developer checks each unresolved external reference to see whether it is a template, and if it is a template, when it can be instantiated. Particularly helpful in this case are the output external names. Then, the developer selects a source for the instantiation and inserts the instantiation statements there. In addition, the correct header files must also be included.
This method requires a considerable amount of manual work. But you do not subsequently need to call the prelinker.
This procedure offers you precise control over the placing of instances (which is important when using components with high performance requirements).
Example 1
For a single ETR file compiled using two files, x.c and y.c:
The following statements are used for compilation:
//MOD-DIAG GEN-ETR=ALL
//COMPILE (*LIB(OLIB,X.C), *LIB(OLIB,Y.C)), MODULE-OUTPUT=*SOURCE-LOCATION
Source x.c:
template <class T> void f(T) {} template <class T> void g(T); template void f(long); void foo() { f(5); f(’a’); g(5); }
Source y.c:
template <class T> void f(T) {} void bar() { f(5): }
ETR-File x.etr (is in the OLIB library as a type S member):
// This file is generated and will be changed when the module is compiled // The following template was // explicitly instantiated #pragma instantiate_mangled_id __1f__tm__2_l__FZ1Z_v&_ // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_ // The following template was // used in this module #pragma instantiate_mangled_id __1g__tm__2_i__FZ1Z_v&_
ETR-File y.etr (is in the OLIB library as a type S member):
// This file is generated and will be changed when the module is compiled // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_
The user can now decide in which source they wish to make explicit instantiations (this decision must always be made for entries with “used in this module and can be instantiated here“), see Example 2.
Then you will subsequently not need to use automatic template instantiation.
Example 2
This example uses two file x.c and y.c in a library called test.
Source x.c
template <class T> void f(T){} template <class T> void g(T); template void f(long); void foo() { f(5); f(’a’); g(5); }
Source y.c:
template <class T> void f(T) {} void bar() { f(5): }
These programs are compiled using the following statements and the prelinking carried out:
//mod-source-prop instantiation=*auto //mod-diagnostic-prop generate-etr-file=*assigned-instantiations //compile *lib-elem(test, X.C), module-output=*source-location //compile *lib-elem(test, Y.C), module-output=*source-location //mod-bind-prop start-llm-creation=*yes //mod-bind-prop include=*lib-elem(test,X) //mod-bind-prop include=*lib-elem(test,Y) //bind action=*prelink
This creates a file called x.etr in the library test:
// This file is generated and will be changed when the module is compiled // The following template was // instantiated automatically by the compiler #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ // The following template was // instantiated automatically by the compiler #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_
The important lines are inserted in the file x.c, which creates the file x1.c:
template <class T> void f(T){} template <class T> void g(T); template void f(long); void foo() { f(5); f(’a’); g(5); } #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_
Then you can carry out production using the following commands:
//mod-source-prop instantiation=*none //mod-diagnostic-prop generate-etr-file=*no //compile *lib-elem(test,X1.C), module-output=*source-location //compile *lib-elem(test,Y.C), module-output=*source-location
Example 3
The following example shows the four classes of template that can be output. The same assumptions are made as for example 1.
The following commands are input:
//mod-source-prop instantiation=*auto //mod-diagnostic-prop generate-etr-file=*no //compile *lib-elem(test,Y.C), module-output=*source-location //mod-bind-prop start-llm-creation=*yes //mod-bind-prop include=*lib-elem(test,y) //bind action=*prelink (this will assign y to f(int)) //mod-diagnostic-prop generate-etr-file=*all-instantiations //compile *lib-elem(test,X.C), module-output=*source-location //mod-bind-prop start-llm-creation=*yes //mod-bind-prop include=*lib-elem(test,X) //mod-bind-prop include=*lib-elem(test,Y) //bind action=*prelink
This creates an ETR file x.etr in the library called test:
// This file is generated and will be changed when the module is compiled // The following template was // explicitly instantiated #pragma instantiate_mangled_id __1f__tm__2_l__FZ1Z_v&_ // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ // The following template was // instantiated automatically by the compiler #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_ // The following template was // used in this module #pragma instantiate_mangled_id __1g__tm__2_i__FZ1Z_v&_