2 /*+-----------------------------------------------------------------**
4 **-----------------------------------------------------------------**
6 **-----------------------------------------------------------------**
7 ** First version: 30/04/2008 **
8 **-----------------------------------------------------------------**
11 *****************************************************************************
12 * OpenScop: Structures and formats for polyhedral tools to talk together *
13 *****************************************************************************
14 * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15 * / / / // // // // / / / // // / / // / /|,_, *
16 * / / / // // // // / / / // // / / // / / / /\ *
17 * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18 * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19 * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20 * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21 * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22 * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23 * | I | | | | e | | | | | | | | | | | | | \ \ \ *
24 * | T | | | | | | | | | | | | | | | | | \ \ \ *
25 * | E | | | | | | | | | | | | | | | | | \ \ \ *
26 * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27 * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
32 * (3-clause BSD license) *
33 * Redistribution and use in source and binary forms, with or without *
34 * modification, are permitted provided that the following conditions *
37 * 1. Redistributions of source code must retain the above copyright notice, *
38 * this list of conditions and the following disclaimer. *
39 * 2. Redistributions in binary form must reproduce the above copyright *
40 * notice, this list of conditions and the following disclaimer in the *
41 * documentation and/or other materials provided with the distribution. *
42 * 3. The name of the author may not be used to endorse or promote products *
43 * derived from this software without specific prior written permission. *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
56 * OpenScop Library, a library to manipulate OpenScop formats and data *
57 * structures. Written by: *
58 * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
61 *****************************************************************************/
68 #include <osl/macros.h>
70 #include <osl/extensions/arrays.h>
71 #include <osl/extensions/textual.h>
72 #include <osl/strings.h>
73 #include <osl/relation.h>
74 #include <osl/interface.h>
75 #include <osl/generic.h>
76 #include <osl/statement.h>
80 /*+***************************************************************************
81 * Structure display functions *
82 *****************************************************************************/
86 * osl_scop_idump function:
87 * this function displays an osl_scop_t structure (*scop) into a
88 * file (file, possibly stdout) in a way that trends to be understandable. It
89 * includes an indentation level (level) in order to work with others
91 * \param file The file where the information has to be printed.
92 * \param scop The scop structure whose information has to be printed.
93 * \param level Number of spaces before printing, for each line.
95 void osl_scop_idump(FILE * file
, osl_scop_p scop
, int level
) {
98 // Go to the right level.
99 for (j
= 0; j
< level
; j
++)
100 fprintf(file
, "|\t");
103 fprintf(file
, "+-- osl_scop_t\n");
105 fprintf(file
, "+-- NULL scop\n");
107 while (scop
!= NULL
) {
109 // Go to the right level.
110 for (j
= 0; j
< level
; j
++)
111 fprintf(file
, "|\t");
112 fprintf(file
, "| osl_scop_t\n");
118 for (j
= 0; j
<= level
+1; j
++)
119 fprintf(file
, "|\t");
122 // Print the version.
123 for (j
= 0; j
< level
; j
++)
124 fprintf(file
, "|\t");
125 fprintf(file
, "|\tVersion: %d\n", scop
->version
);
128 for (j
= 0; j
<= level
+1; j
++)
129 fprintf(file
, "|\t");
132 // Print the language.
133 for (j
= 0; j
< level
; j
++)
134 fprintf(file
, "|\t");
135 fprintf(file
, "|\tLanguage: %s\n", scop
->language
);
138 for (j
= 0; j
<= level
+1; j
++)
139 fprintf(file
, "|\t");
142 // Print the context of the scop.
143 osl_relation_idump(file
, scop
->context
, level
+1);
145 // Print the parameters.
146 osl_generic_idump(file
, scop
->parameters
, level
+1);
148 // Print the statements.
149 osl_statement_idump(file
, scop
->statement
, level
+1);
151 // Print the registered extension interfaces.
152 osl_interface_idump(file
, scop
->registry
, level
+1);
154 // Print the extensions.
155 osl_generic_idump(file
, scop
->extension
, level
+1);
161 for (j
= 0; j
<= level
; j
++)
162 fprintf(file
, "|\t");
163 fprintf(file
, "V\n");
168 for (j
= 0; j
<= level
; j
++)
169 fprintf(file
, "|\t");
175 * osl_scop_dump function:
176 * this function prints the content of an osl_scop_t structure (*scop)
177 * into a file (file, possibly stdout).
178 * \param file The file where the information has to be printed.
179 * \param scop The scop structure whose information has to be printed.
181 void osl_scop_dump(FILE * file
, osl_scop_p scop
) {
182 osl_scop_idump(file
, scop
, 0);
187 * osl_scop_names function:
188 * this function generates as set of names for all the dimensions
189 * involved in a given scop.
190 * \param[in] scop The scop (list) we have to generate names for.
191 * \return A set of generated names for the input scop dimensions.
193 osl_names_p
osl_scop_names(osl_scop_p scop
) {
194 int nb_parameters
= OSL_UNDEFINED
;
195 int nb_iterators
= OSL_UNDEFINED
;
196 int nb_scattdims
= OSL_UNDEFINED
;
197 int nb_localdims
= OSL_UNDEFINED
;
198 int array_id
= OSL_UNDEFINED
;
200 osl_scop_get_attributes(scop
, &nb_parameters
, &nb_iterators
,
201 &nb_scattdims
, &nb_localdims
, &array_id
);
203 return osl_names_generate("P", nb_parameters
,
212 * osl_scop_print function:
213 * this function prints the content of an osl_scop_t structure (*scop)
214 * into a file (file, possibly stdout) in the OpenScop textual format.
215 * \param file The file where the information has to be printed.
216 * \param scop The scop structure whose information has to be printed.
218 void osl_scop_print(FILE * file
, osl_scop_p scop
) {
219 int parameters_backedup
= 0;
220 int arrays_backedup
= 0;
221 osl_strings_p parameters_backup
= NULL
;
222 osl_strings_p arrays_backup
= NULL
;
227 fprintf(file
, "# NULL scop\n");
231 fprintf(file
, "# [File generated by the OpenScop Library %s]\n",
235 if (osl_scop_integrity_check(scop
) == 0)
236 OSL_warning("OpenScop integrity check failed. Something may go wrong.");
238 // Generate the names for the various dimensions.
239 names
= osl_scop_names(scop
);
241 while (scop
!= NULL
) {
242 // If possible, replace parameter names with scop parameter names.
243 if (osl_generic_has_URI(scop
->parameters
, OSL_URI_STRINGS
)) {
244 parameters_backedup
= 1;
245 parameters_backup
= names
->parameters
;
246 names
->parameters
= scop
->parameters
->data
;
249 // If possible, replace array names with arrays extension names.
250 arrays
= osl_generic_lookup(scop
->extension
, OSL_URI_ARRAYS
);
251 if (arrays
!= NULL
) {
253 arrays_backup
= names
->arrays
;
254 names
->arrays
= osl_arrays_to_strings(arrays
);
257 fprintf(file
, "\n<"OSL_URI_SCOP
">\n\n");
258 fprintf(file
, "# =============================================== "
260 fprintf(file
, "# Language\n");
261 fprintf(file
, "%s\n\n", scop
->language
);
263 fprintf(file
, "# Context\n");
264 osl_relation_pprint(file
, scop
->context
, names
);
267 osl_util_print_provided(file
,
268 osl_generic_has_URI(scop
->parameters
, OSL_URI_STRINGS
),
270 osl_generic_print(file
, scop
->parameters
);
272 fprintf(file
, "\n# Number of statements\n");
273 fprintf(file
, "%d\n\n",osl_statement_number(scop
->statement
));
275 osl_statement_pprint(file
, scop
->statement
, names
);
277 if (scop
->extension
) {
278 fprintf(file
, "# =============================================== "
280 osl_generic_print(file
, scop
->extension
);
282 fprintf(file
, "\n</"OSL_URI_SCOP
">\n\n");
284 // If necessary, switch back parameter names.
285 if (parameters_backedup
) {
286 parameters_backedup
= 0;
287 names
->parameters
= parameters_backup
;
290 // If necessary, switch back array names.
291 if (arrays_backedup
) {
293 osl_strings_free(names
->arrays
);
294 names
->arrays
= arrays_backup
;
300 osl_names_free(names
);
305 * osl_scop_print_scoplib function:
306 * this function prints the content of an osl_scop_t structure (*scop)
307 * into a file (file, possibly stdout) in the ScopLib textual format.
308 * \param file The file where the information has to be printed.
309 * \param scop The scop structure whose information has to be printed.
311 void osl_scop_print_scoplib(FILE * file
, osl_scop_p scop
) {
312 int parameters_backedup
= 0;
313 int arrays_backedup
= 0;
314 osl_strings_p parameters_backup
= NULL
;
315 osl_strings_p arrays_backup
= NULL
;
320 fprintf(file
, "# NULL scop\n");
324 fprintf(file
, "# [File generated by the OpenScop Library %s]\n"
325 "# [SCoPLib format]\n",
329 if (osl_scop_check_compatible_scoplib(scop
) == 0) {
330 OSL_error("SCoP integrity check failed. Something may go wrong.");
334 // Generate the names for the various dimensions.
335 names
= osl_scop_names(scop
);
337 while (scop
!= NULL
) {
338 // If possible, replace parameter names with scop parameter names.
339 if (osl_generic_has_URI(scop
->parameters
, OSL_URI_STRINGS
)) {
340 parameters_backedup
= 1;
341 parameters_backup
= names
->parameters
;
342 names
->parameters
= scop
->parameters
->data
;
345 // If possible, replace array names with arrays extension names.
346 arrays
= osl_generic_lookup(scop
->extension
, OSL_URI_ARRAYS
);
347 if (arrays
!= NULL
) {
349 arrays_backup
= names
->arrays
;
350 names
->arrays
= osl_arrays_to_strings(arrays
);
353 fprintf(file
, "\nSCoP\n\n");
354 fprintf(file
, "# =============================================== "
356 fprintf(file
, "# Language\n");
357 fprintf(file
, "%s\n\n", scop
->language
);
359 fprintf(file
, "# Context\n");
361 osl_relation_pprint_scoplib(file
, scop
->context
, names
, 0, 0);
364 osl_util_print_provided(file
,
365 osl_generic_has_URI(scop
->parameters
, OSL_URI_STRINGS
),
368 if (scop
->parameters
) {
369 fprintf(file
, "# Parameter names\n");
370 osl_strings_print(file
, scop
->parameters
->data
);
373 fprintf(file
, "\n# Number of statements\n");
374 fprintf(file
, "%d\n\n",osl_statement_number(scop
->statement
));
376 osl_statement_pprint_scoplib(file
, scop
->statement
, names
);
378 if (scop
->extension
) {
379 fprintf(file
, "# =============================================== "
381 osl_generic_print_options_scoplib(file
, scop
->extension
);
384 // If necessary, switch back parameter names.
385 if (parameters_backedup
) {
386 parameters_backedup
= 0;
387 names
->parameters
= parameters_backup
;
390 // If necessary, switch back array names.
391 if (arrays_backedup
) {
393 osl_strings_free(names
->arrays
);
394 names
->arrays
= arrays_backup
;
400 osl_names_free(names
);
404 /*****************************************************************************
406 *****************************************************************************/
410 * osl_scop_pread function ("precision read"):
411 * this function reads a list of scop structures from a file (possibly stdin)
412 * complying to the OpenScop textual format and returns a pointer to this
413 * scop list. If some relation properties (number of input/output/local
414 * dimensions and number of parameters) are undefined, it will define them
415 * according to the available information.
416 * \param[in] file The file where the scop has to be read.
417 * \param[in] registry The list of known interfaces (others are ignored).
418 * \param[in] precision The precision of the relation elements.
419 * \return A pointer to the scop structure that has been read.
421 osl_scop_p
osl_scop_pread(FILE * file
, osl_interface_p registry
,
423 osl_scop_p list
= NULL
, current
= NULL
, scop
;
424 osl_statement_p stmt
= NULL
;
425 osl_statement_p prev
= NULL
;
426 osl_strings_p language
;
439 tmp
= osl_util_read_uptotag(file
, NULL
, OSL_URI_SCOP
);
441 OSL_debug("no more scop in the file");
448 scop
= osl_scop_malloc();
449 scop
->registry
= osl_interface_clone(registry
);
455 // Read the language.
456 language
= osl_strings_read(file
);
457 if (osl_strings_size(language
) == 0)
458 OSL_error("no language (backend) specified");
460 if (osl_strings_size(language
) > 1)
461 OSL_warning("uninterpreted information (after language)");
463 if (language
!= NULL
) {
464 OSL_strdup(scop
->language
, language
->string
[0]);
465 osl_strings_free(language
);
468 // Read the context domain.
469 scop
->context
= osl_relation_pread(file
, precision
);
471 // Read the parameters.
472 if (osl_util_read_int(file
, NULL
) > 0)
473 scop
->parameters
= osl_generic_read_one(file
, scop
->registry
);
476 // III. STATEMENT PART
479 // Read the number of statements.
480 nb_statements
= osl_util_read_int(file
, NULL
);
482 for (i
= 0; i
< nb_statements
; i
++) {
483 // Read each statement.
484 stmt
= osl_statement_pread(file
, scop
->registry
, precision
);
485 if (scop
->statement
== NULL
)
486 scop
->statement
= stmt
;
493 // IV. EXTENSION PART (TO THE END TAG)
496 // Read up the end tag (if any), and store extensions.
497 scop
->extension
= osl_generic_read(file
, scop
->registry
);
499 // Add the new scop to the list.
505 current
->next
= scop
;
510 if (!osl_scop_integrity_check(list
))
511 OSL_warning("scop integrity check failed");
518 * osl_scop_read function:
519 * this function is equivalent to osl_scop_pread() except that
520 * (1) the precision corresponds to the precision environment variable or
521 * to the highest available precision if it is not defined, and
522 * (2) the list of known interface is set to the default one.
523 * \see{osl_scop_pread}
525 osl_scop_p
osl_scop_read(FILE * foo
) {
526 int precision
= osl_util_get_precision();
527 osl_interface_p registry
= osl_interface_get_default_registry();
528 osl_scop_p scop
= osl_scop_pread(foo
, registry
, precision
);
530 osl_interface_free(registry
);
535 /*+***************************************************************************
536 * Memory allocation/deallocation functions *
537 *****************************************************************************/
541 * osl_scop_malloc function:
542 * this function allocates the memory space for a osl_scop_t structure and
543 * sets its fields with default values. Then it returns a pointer to the
545 * \return A pointer to an empty scop with fields set to default values.
547 osl_scop_p
osl_scop_malloc() {
550 OSL_malloc(scop
, osl_scop_p
, sizeof(osl_scop_t
));
552 scop
->language
= NULL
;
553 scop
->context
= NULL
;
554 scop
->parameters
= NULL
;
555 scop
->statement
= NULL
;
556 scop
->registry
= NULL
;
557 scop
->extension
= NULL
;
566 * osl_scop_free function:
567 * This function frees the allocated memory for a osl_scop_t structure.
568 * \param scop The pointer to the scop we want to free.
570 void osl_scop_free(osl_scop_p scop
) {
573 while (scop
!= NULL
) {
574 if (scop
->language
!= NULL
)
575 free(scop
->language
);
576 osl_generic_free(scop
->parameters
);
577 osl_relation_free(scop
->context
);
578 osl_statement_free(scop
->statement
);
579 osl_interface_free(scop
->registry
);
580 osl_generic_free(scop
->extension
);
589 /*+***************************************************************************
590 * Processing functions *
591 *****************************************************************************/
595 * osl_scop_add function:
596 * this function adds a scop "scop" at the end of the scop list pointed
598 * \param[in,out] location Address of the first element of the scop list.
599 * \param[in] scop The scop to add to the list.
601 void osl_scop_add(osl_scop_p
* location
, osl_scop_p scop
) {
602 while (*location
!= NULL
)
603 location
= &((*location
)->next
);
610 * osl_scop_number function:
611 * this function returns the number of scops in the scop list
612 * provided as parameter.
613 * \param[in] scop The first element of the scop list.
614 * \return The number of scops in the scop list.
616 size_t osl_scop_number(osl_scop_p scop
) {
619 while (scop
!= NULL
) {
628 * osl_scop_clone function:
629 * This functions builds and returns a "hard copy" (not a pointer copy)
630 * of a osl_statement_t data structure provided as parameter.
631 * Note that the usr field is not touched by this function.
632 * \param scop The pointer to the scop we want to clone.
633 * \return A pointer to the full clone of the scop provided as parameter.
635 osl_scop_p
osl_scop_clone(osl_scop_p scop
) {
636 osl_scop_p clone
= NULL
, node
, previous
= NULL
;
639 while (scop
!= NULL
) {
640 node
= osl_scop_malloc();
641 node
->version
= scop
->version
;
642 if (scop
->language
!= NULL
)
643 OSL_strdup(node
->language
, scop
->language
);
644 node
->context
= osl_relation_clone(scop
->context
);
645 node
->parameters
= osl_generic_clone(scop
->parameters
);
646 node
->statement
= osl_statement_clone(scop
->statement
);
647 node
->registry
= osl_interface_clone(scop
->registry
);
648 node
->extension
= osl_generic_clone(scop
->extension
);
656 previous
->next
= node
;
657 previous
= previous
->next
;
668 * osl_scop_equal function:
669 * this function returns true if the two scops are the same, false
670 * otherwise (the usr field is not tested).
671 * \param s1 The first scop.
672 * \param s2 The second scop.
673 * \return 1 if s1 and s2 are the same (content-wise), 0 otherwise.
675 int osl_scop_equal(osl_scop_p s1
, osl_scop_p s2
) {
677 while ((s1
!= NULL
) && (s2
!= NULL
)) {
681 if (s1
->version
!= s2
->version
) {
682 OSL_info("versions are not the same");
686 if (strcmp(s1
->language
, s2
->language
) != 0) {
687 OSL_info("languages are not the same");
691 if (!osl_relation_equal(s1
->context
, s2
->context
)) {
692 OSL_info("contexts are not the same");
696 if (!osl_generic_equal(s1
->parameters
, s2
->parameters
)) {
697 OSL_info("parameters are not the same");
701 if (!osl_statement_equal(s1
->statement
, s2
->statement
)) {
702 OSL_info("statements are not the same");
706 if (!osl_interface_equal(s1
->registry
, s2
->registry
)) {
707 OSL_info("registries are not the same");
711 if (!osl_generic_equal(s1
->extension
, s2
->extension
)) {
712 OSL_info("extensions are not the same");
720 if (((s1
== NULL
) && (s2
!= NULL
)) || ((s1
!= NULL
) && (s2
== NULL
)))
728 * osl_scop_integrity_check function:
729 * This function checks that a scop is "well formed". It returns 0 if the
730 * check failed or 1 if no problem has been detected.
731 * \param scop The scop we want to check.
732 * \return 0 if the integrity check fails, 1 otherwise.
734 int osl_scop_integrity_check(osl_scop_p scop
) {
735 int expected_nb_parameters
;
738 while (scop
!= NULL
) {
739 // Check the language.
740 if ((scop
->language
!= NULL
) &&
741 (!strcmp(scop
->language
, "caml") || !strcmp(scop
->language
, "Caml") ||
742 !strcmp(scop
->language
, "ocaml") || !strcmp(scop
->language
, "OCaml")))
743 fprintf(stderr
, "[OpenScop] Alert: What ?! Caml ?! Are you sure ?!?!\n");
745 // Check the context.
746 if (!osl_relation_integrity_check(scop
->context
,
753 // Get the number of parameters.
754 if (scop
->context
!= NULL
)
755 expected_nb_parameters
= scop
->context
->nb_parameters
;
757 expected_nb_parameters
= OSL_UNDEFINED
;
759 // TODO : check the number of parameter strings.
761 if (!osl_statement_integrity_check(scop
->statement
,
762 expected_nb_parameters
))
773 * osl_scop_check_compatible_scoplib function:
774 * This function checks that a scop is "well formed". It returns 0 if the
775 * check failed or 1 if no problem has been detected.
776 * \param scop The scop we want to check.
777 * \return 0 if the integrity check fails, 1 otherwise.
779 int osl_scop_check_compatible_scoplib(osl_scop_p scop
) {
781 if (!osl_scop_integrity_check(scop
))
783 if (scop
->next
!= NULL
)
785 if (scop
== NULL
|| scop
->statement
== NULL
)
788 osl_relation_p domain
;
789 osl_statement_p statement
;
790 osl_relation_p scattering
;
791 int precision
= scop
->statement
->scattering
->precision
;
794 statement
= scop
->statement
;
795 while (statement
!= NULL
) {
796 scattering
= statement
->scattering
;
798 if (scattering
->nb_local_dims
!= 0) {
799 OSL_error("Local dims in scattering matrix");
803 domain
= statement
->domain
;
804 while (domain
!= NULL
) {
805 if (domain
->nb_local_dims
!= 0) {
806 OSL_error("Local dims in domain matrix");
809 domain
= domain
->next
;
812 // Check if there is only the -Identity in the output_dims
813 // and the lines MUST be in the right order
814 for (i
= 0 ; i
< scattering
->nb_rows
; i
++) {
815 for (j
= 0 ; j
< scattering
->nb_output_dims
; j
++) {
817 if (!osl_int_mone(precision
, scattering
->m
[i
][j
+1])) {
818 OSL_error("Wrong -Identity");
822 if (!osl_int_zero(precision
, scattering
->m
[i
][j
+1])) {
823 OSL_error("Wrong -Identity");
830 statement
= statement
->next
;
838 * osl_scop_get_nb_parameters function:
839 * this function returns the number of global parameters of a given SCoP.
840 * \param scop The scop we want to know the number of global parameters.
841 * \return The number of global parameters in the scop.
843 int osl_scop_get_nb_parameters(osl_scop_p scop
) {
845 if (scop
->context
== NULL
) {
846 OSL_debug("no context domain, assuming 0 parameters");
850 return scop
->context
->nb_parameters
;
856 * osl_scop_register_extension function:
857 * this function registers a list of extension interfaces to a scop, i.e., it
858 * adds them to the scop registry. In addition, it will extract extensions
859 * corresponding to those interfaces from the textual form of the extensions
860 * (if any) and add them to the scop extension list.
861 * \param scop The scop for which an extension has to be registered.
862 * \param interface The extension interface to register within the scop.
864 void osl_scop_register_extension(osl_scop_p scop
, osl_interface_p interface
) {
865 osl_generic_p textual
, new;
866 char * extension_string
;
868 if ((interface
!= NULL
) && (scop
!= NULL
)) {
869 osl_interface_add(&scop
->registry
, interface
);
871 textual
= osl_generic_lookup(scop
->extension
, interface
->URI
);
872 if (textual
!= NULL
) {
873 extension_string
= ((osl_textual_p
)textual
->data
)->textual
;
874 new = osl_generic_sread(&extension_string
, interface
);
875 osl_generic_add(&scop
->extension
, new);
882 * osl_scop_get_attributes function:
883 * this function returns, through its parameters, the maximum values of the
884 * relation attributes (nb_iterators, nb_parameters etc) in the scop.
885 * HOWEVER, it updates the parameter value iff the attribute is greater than
886 * the input parameter value. Hence it may be used to get the attributes as
887 * well as to find the maximum attributes for several scop lists. The array
888 * identifier 0 is used when there is no array identifier (AND this is OK),
889 * OSL_UNDEFINED is used to report it is impossible to provide the property
890 * while it should. This function is not intended for checking, the input
891 * scop should be correct.
892 * \param[in] scop The scop to extract attributes values.
893 * \param[in,out] nb_parameters Number of parameter attribute.
894 * \param[in,out] nb_iterators Number of iterators attribute.
895 * \param[in,out] nb_scattdims Number of scattering dimensions attribute.
896 * \param[in,out] nb_localdims Number of local dimensions attribute.
897 * \param[in,out] array_id Maximum array identifier attribute.
899 void osl_scop_get_attributes(osl_scop_p scop
,
905 int local_nb_parameters
= OSL_UNDEFINED
;
906 int local_nb_iterators
= OSL_UNDEFINED
;
907 int local_nb_scattdims
= OSL_UNDEFINED
;
908 int local_nb_localdims
= OSL_UNDEFINED
;
909 int local_array_id
= OSL_UNDEFINED
;
911 while (scop
!= NULL
) {
912 osl_relation_get_attributes(scop
->context
,
913 &local_nb_parameters
,
919 osl_statement_get_attributes(scop
->statement
,
920 &local_nb_parameters
,
926 *nb_parameters
= OSL_max(*nb_parameters
, local_nb_parameters
);
927 *nb_iterators
= OSL_max(*nb_iterators
, local_nb_iterators
);
928 *nb_scattdims
= OSL_max(*nb_scattdims
, local_nb_scattdims
);
929 *nb_localdims
= OSL_max(*nb_localdims
, local_nb_localdims
);
930 *array_id
= OSL_max(*array_id
, local_array_id
);
937 * osl_scop_normalize_scattering function:
938 * this function modifies a scop such that all scattering relation have
939 * the same number of output dimensions (additional output dimensions are
940 * set as being equal to zero).
941 * \param[in,out] scop The scop to nomalize the scattering functions.
943 void osl_scop_normalize_scattering(osl_scop_p scop
) {
944 int max_scattering_dims
= 0;
945 osl_statement_p statement
;
946 osl_relation_p extended
;
948 if ((scop
!= NULL
) && (scop
->statement
!= NULL
)) {
949 // Get the max number of scattering dimensions.
950 statement
= scop
->statement
;
951 while (statement
!= NULL
) {
952 if (statement
->scattering
!= NULL
) {
953 max_scattering_dims
= OSL_max(max_scattering_dims
,
954 statement
->scattering
->nb_output_dims
);
956 statement
= statement
->next
;
960 statement
= scop
->statement
;
961 while (statement
!= NULL
) {
962 if (statement
->scattering
!= NULL
) {
963 extended
= osl_relation_extend_output(statement
->scattering
,
964 max_scattering_dims
);
965 osl_relation_free(statement
->scattering
);
966 statement
->scattering
= extended
;
968 statement
= statement
->next
;