OpenScop 0.8.1

scop.c

Go to the documentation of this file.
00001 
00002     /*+-----------------------------------------------------------------**
00003      **                       OpenScop Library                          **
00004      **-----------------------------------------------------------------**
00005      **                            scop.c                               **
00006      **-----------------------------------------------------------------**
00007      **                   First version: 30/04/2008                     **
00008      **-----------------------------------------------------------------**
00009 
00010  
00011  *****************************************************************************
00012  * OpenScop: Structures and formats for polyhedral tools to talk together    *
00013  *****************************************************************************
00014  *    ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__,                *
00015  *    /   / /  //  //  //  // /   / /  //  //   / /  // /  /|,_,             *
00016  *   /   / /  //  //  //  // /   / /  //  //   / /  // /  / / /\             *
00017  *  |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/  \            *
00018  *  | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\  \ /\           *
00019  *  | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\          *
00020  *  | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \  \         *
00021  *  | P |n| l | = | s | t |=| = |d| = | = | = | |   |=| o | | \# \  \        *
00022  *  | H | | y |   | e | o | | = |l|   |   | = | |   | | G | |  \  \  \       *
00023  *  | I | |   |   | e |   | |   | |   |   |   | |   | |   | |   \  \  \      *
00024  *  | T | |   |   |   |   | |   | |   |   |   | |   | |   | |    \  \  \     *
00025  *  | E | |   |   |   |   | |   | |   |   |   | |   | |   | |     \  \  \    *
00026  *  | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | /      \* \  \   *
00027  *  | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/        \  \ /   *
00028  *  '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---'          '--'    *
00029  *                                                                           *
00030  * Copyright (C) 2008 University Paris-Sud 11 and INRIA                      *
00031  *                                                                           *
00032  * (3-clause BSD license)                                                    *
00033  * Redistribution and use in source  and binary forms, with or without       *
00034  * modification, are permitted provided that the following conditions        *
00035  * are met:                                                                  *
00036  *                                                                           *
00037  * 1. Redistributions of source code must retain the above copyright notice, *
00038  *    this list of conditions and the following disclaimer.                  *
00039  * 2. Redistributions in binary form must reproduce the above copyright      *
00040  *    notice, this list of conditions and the following disclaimer in the    *
00041  *    documentation and/or other materials provided with the distribution.   *
00042  * 3. The name of the author may not be used to endorse or promote products  *
00043  *    derived from this software without specific prior written permission.  *
00044  *                                                                           *
00045  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      *
00046  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
00047  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   *
00048  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          *
00049  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  *
00050  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
00051  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     *
00052  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
00053  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  *
00054  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         *
00055  *                                                                           *
00056  * OpenScop Library, a library to manipulate OpenScop formats and data       *
00057  * structures. Written by:                                                   *
00058  * Cedric Bastoul     <Cedric.Bastoul@u-psud.fr> and                         *
00059  * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr>                          *
00060  *                                                                           *
00061  *****************************************************************************/
00062 
00063 # include <stdlib.h>
00064 # include <stdio.h>
00065 # include <ctype.h>
00066 # include <string.h>
00067 
00068 #include <osl/macros.h>
00069 #include <osl/util.h>
00070 #include <osl/extensions/textual.h>
00071 #include <osl/strings.h>
00072 #include <osl/relation.h>
00073 #include <osl/interface.h>
00074 #include <osl/generic.h>
00075 #include <osl/statement.h>
00076 #include <osl/scop.h>
00077 
00078 
00079 /*+***************************************************************************
00080  *                         Structure display functions                       *
00081  *****************************************************************************/
00082 
00083 
00094 void osl_scop_idump(FILE * file, osl_scop_p scop, int level) {
00095   int j, first = 1;
00096 
00097   // Go to the right level.
00098   for (j = 0; j < level; j++)
00099     fprintf(file, "|\t");
00100 
00101   if (scop != NULL)
00102     fprintf(file, "+-- osl_scop_t\n");
00103   else
00104     fprintf(file, "+-- NULL scop\n");
00105 
00106   while (scop != NULL) {
00107     if (!first) {
00108       // Go to the right level.
00109       for (j = 0; j < level; j++)
00110         fprintf(file, "|\t");
00111       fprintf(file, "|   osl_scop_t\n");
00112     }
00113     else
00114       first = 0;
00115 
00116     // A blank line.
00117     for (j = 0; j <= level+1; j++)
00118       fprintf(file, "|\t");
00119     fprintf(file, "\n");
00120 
00121     // Print the version.
00122     for (j = 0; j < level; j++)
00123       fprintf(file, "|\t");
00124     fprintf(file, "|\tVersion: %d\n", scop->version);
00125 
00126     // A blank line.
00127     for (j = 0; j <= level+1; j++)
00128       fprintf(file, "|\t");
00129     fprintf(file, "\n");
00130 
00131     // Print the language.
00132     for (j = 0; j < level; j++)
00133       fprintf(file, "|\t");
00134     fprintf(file, "|\tLanguage: %s\n", scop->language);
00135 
00136     // A blank line.
00137     for (j = 0; j <= level+1; j++)
00138       fprintf(file, "|\t");
00139     fprintf(file, "\n");
00140 
00141     // Print the context of the scop.
00142     osl_relation_idump(file, scop->context, level+1);
00143 
00144     // Print the parameters.
00145     osl_generic_idump(file, scop->parameters, level+1);
00146 
00147     // Print the statements.
00148     osl_statement_idump(file, scop->statement, level+1);
00149 
00150     // Print the registered extension interfaces.
00151     osl_interface_idump(file, scop->registry, level+1);
00152 
00153     // Print the extensions.
00154     osl_generic_idump(file, scop->extension, level+1);
00155 
00156     scop = scop->next;
00157 
00158     // Next line.
00159     if (scop != NULL) {
00160       for (j = 0; j <= level; j++)
00161         fprintf(file, "|\t");
00162       fprintf(file, "V\n");
00163     }
00164   }
00165 
00166   // The last line.
00167   for (j = 0; j <= level; j++)
00168     fprintf(file, "|\t");
00169   fprintf(file, "\n");
00170 }
00171 
00172 
00180 void osl_scop_dump(FILE * file, osl_scop_p scop) {
00181   osl_scop_idump(file, scop, 0);
00182 }
00183 
00184 
00192 static
00193 osl_names_p osl_scop_names(osl_scop_p scop) {
00194   int nb_parameters = OSL_UNDEFINED;
00195   int nb_iterators  = OSL_UNDEFINED;
00196   int nb_scattdims  = OSL_UNDEFINED;
00197   int nb_localdims  = OSL_UNDEFINED;
00198   int array_id      = OSL_UNDEFINED;
00199 
00200   osl_scop_get_attributes(scop, &nb_parameters, &nb_iterators,
00201                           &nb_scattdims,  &nb_localdims, &array_id);
00202   
00203   return osl_names_generate("P", nb_parameters,
00204                             "i", nb_iterators,
00205                             "c", nb_scattdims,
00206                             "l", nb_localdims,
00207                             "A", array_id);
00208 }
00209 
00210 
00218 void osl_scop_print(FILE * file, osl_scop_p scop) {
00219   int parameters_backedup = 0;
00220   osl_strings_p parameters_backup = NULL;
00221   osl_names_p names;
00222 
00223   if (scop == NULL) {
00224     fprintf(file, "# NULL scop\n");
00225     return;
00226   }
00227   else {
00228     fprintf(file, "# [File generated by the OpenScop Library %s]\n",
00229             OSL_RELEASE);
00230   }
00231 
00232   if (osl_scop_integrity_check(scop) == 0)
00233     OSL_warning("OpenScop integrity check failed. "
00234                      "Something may go wrong.");
00235   
00236   // Generate the names for the various dimensions.
00237   names = osl_scop_names(scop);
00238 
00239   while (scop != NULL) {
00240     // If possible, replace parameter names with scop iterator names.
00241     if (osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS)) {
00242       parameters_backedup = 1;
00243       parameters_backup = names->parameters;
00244       names->parameters = scop->parameters->data;
00245     }
00246     
00247     fprintf(file, "\n"OSL_TAG_START_SCOP"\n\n");
00248     fprintf(file, "# =============================================== "
00249                   "Global\n");
00250     fprintf(file, "# Language\n");
00251     fprintf(file, "%s\n\n", scop->language);
00252 
00253     fprintf(file, "# Context\n");
00254     osl_relation_pprint(file, scop->context, names);
00255     fprintf(file, "\n");
00256 
00257     osl_util_print_provided(file,
00258         osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS),
00259         "Parameters are");
00260     osl_generic_print(file, scop->parameters);
00261 
00262     fprintf(file, "\n# Number of statements\n");
00263     fprintf(file, "%d\n\n",osl_statement_number(scop->statement));
00264 
00265     osl_statement_pprint(file, scop->statement, names);
00266 
00267     if (scop->extension) {
00268       fprintf(file, "# =============================================== "
00269                     "Extensions\n");
00270       osl_generic_print(file, scop->extension);
00271     }
00272     fprintf(file, "\n"OSL_TAG_END_SCOP"\n\n");
00273     
00274     // If necessary, switch back parameter names.
00275     if (parameters_backedup) {
00276       parameters_backedup = 0;
00277       names->parameters = parameters_backup;
00278     }
00279 
00280     scop = scop->next;
00281   }
00282 
00283   osl_names_free(names);
00284 }
00285 
00286 
00287 /*****************************************************************************
00288  *                               Reading function                            *
00289  *****************************************************************************/
00290 
00291 
00304 osl_scop_p osl_scop_pread(FILE * file, osl_interface_p registry,
00305                           int precision) {
00306   osl_scop_p list = NULL, current = NULL, scop;
00307   osl_statement_p stmt = NULL;
00308   osl_statement_p prev = NULL;
00309   osl_strings_p language;
00310   int nb_statements;
00311   char * tmp;
00312   int first = 1;
00313   int i;
00314 
00315   if (file == NULL)
00316     return NULL;
00317 
00318   while(1) {
00319     //
00320     // I. START TAG
00321     //
00322     tmp = osl_util_read_uptotag(file, OSL_TAG_START_SCOP);
00323     if (tmp == NULL) {
00324       OSL_debug("no more scop in the file");
00325       break;
00326     }
00327     else {
00328       free(tmp);
00329     }
00330 
00331     scop = osl_scop_malloc();
00332     scop->registry = osl_interface_clone(registry);
00333 
00334     //
00335     // II. CONTEXT PART
00336     //
00337 
00338     // Read the language.
00339     language = osl_strings_read(file);
00340     if (osl_strings_size(language) == 0)
00341       OSL_error("no language (backend) specified");
00342 
00343     if (osl_strings_size(language) > 1)
00344       OSL_warning("uninterpreted information (after language)");
00345 
00346     if (language != NULL) {
00347       scop->language = strdup(language->string[0]);
00348       osl_strings_free(language);
00349     }
00350 
00351     // Read the context domain.
00352     scop->context = osl_relation_pread(file, precision);
00353 
00354     // Read the parameters.
00355     if (osl_util_read_int(file, NULL) > 0)
00356       scop->parameters = osl_generic_read_one(file, scop->registry);
00357 
00358     //
00359     // III. STATEMENT PART
00360     //
00361 
00362     // Read the number of statements.
00363     nb_statements = osl_util_read_int(file, NULL);
00364 
00365     for (i = 0; i < nb_statements; i++) {
00366       // Read each statement.
00367       stmt = osl_statement_pread(file, scop->registry, precision);
00368       if (scop->statement == NULL)
00369         scop->statement = stmt;
00370       else
00371         prev->next = stmt;
00372       prev = stmt;
00373     }
00374 
00375     //
00376     // IV. EXTENSION PART (TO THE END TAG)
00377     //
00378 
00379     // Read up the end tag (if any), and store extensions.
00380     scop->extension = osl_generic_read(file, scop->registry);
00381 
00382     // Add the new scop to the list.
00383     if (first) {
00384       list = scop;
00385       first = 0;
00386     }
00387     else {
00388       current->next = scop;
00389     }
00390     current = scop;    
00391   }
00392   
00393   if (!osl_scop_integrity_check(list))
00394     OSL_warning("scop integrity check failed");
00395 
00396   return list;
00397 }
00398 
00399 
00408 osl_scop_p osl_scop_read(FILE * foo) {
00409   int precision = osl_util_get_precision();
00410   osl_interface_p registry = osl_interface_get_default_registry();
00411   osl_scop_p scop = osl_scop_pread(foo, registry, precision);
00412 
00413   osl_interface_free(registry);
00414   return scop;
00415 }
00416 
00417 
00418 /*+***************************************************************************
00419  *                   Memory allocation/deallocation functions                *
00420  *****************************************************************************/
00421 
00422 
00430 osl_scop_p osl_scop_malloc() {
00431   osl_scop_p scop;
00432 
00433   OSL_malloc(scop, osl_scop_p, sizeof(osl_scop_t));
00434   scop->version        = 1;
00435   scop->language       = NULL;
00436   scop->context        = NULL;
00437   scop->parameters     = NULL;
00438   scop->statement      = NULL;
00439   scop->registry       = NULL;
00440   scop->extension      = NULL;
00441   scop->usr            = NULL;
00442   scop->next           = NULL;
00443 
00444   return scop;
00445 }
00446 
00447 
00453 void osl_scop_free(osl_scop_p scop) {
00454   osl_scop_p tmp;
00455   
00456   while (scop != NULL) {
00457     if (scop->language != NULL)
00458       free(scop->language);
00459     osl_generic_free(scop->parameters);
00460     osl_relation_free(scop->context);
00461     osl_statement_free(scop->statement);
00462     osl_interface_free(scop->registry);
00463     osl_generic_free(scop->extension);
00464 
00465     tmp = scop->next;
00466     free(scop);
00467     scop = tmp;
00468   }
00469 }
00470 
00471 
00472 /*+***************************************************************************
00473  *                            Processing functions                           *
00474  *****************************************************************************/
00475 
00476 
00485 osl_scop_p osl_scop_clone(osl_scop_p scop) {
00486   osl_scop_p clone = NULL, node, previous = NULL;
00487   int first = 1;
00488   
00489   while (scop != NULL) {
00490     node                 = osl_scop_malloc();
00491     node->version        = scop->version;
00492     if (scop->language != NULL)
00493       node->language     = strdup(scop->language);
00494     node->context        = osl_relation_clone(scop->context);
00495     node->parameters     = osl_generic_clone(scop->parameters);
00496     node->statement      = osl_statement_clone(scop->statement);
00497     node->registry       = osl_interface_clone(scop->registry);
00498     node->extension      = osl_generic_clone(scop->extension);
00499     
00500     if (first) {
00501       first = 0;
00502       clone = node;
00503       previous = node;
00504     }
00505     else {
00506       previous->next = node;
00507       previous = previous->next;
00508     }
00509 
00510     scop = scop->next;
00511   }
00512 
00513   return clone;
00514 }
00515 
00516 
00525 int osl_scop_equal(osl_scop_p s1, osl_scop_p s2) {
00526 
00527   while ((s1 != NULL) && (s2 != NULL)) {
00528     if (s1 == s2)
00529       return 1;
00530 
00531     if (s1->version != s2->version) {
00532       OSL_info("versions are not the same"); 
00533       return 0;
00534     }
00535 
00536     if (strcmp(s1->language, s2->language) != 0) {
00537       OSL_info("languages are not the same"); 
00538       return 0;
00539     }
00540 
00541     if (!osl_relation_equal(s1->context, s2->context)) {
00542       OSL_info("contexts are not the same"); 
00543       return 0;
00544     }
00545 
00546     if (!osl_generic_equal(s1->parameters, s2->parameters)) {
00547       OSL_info("parameters are not the same"); 
00548       return 0;
00549     }
00550 
00551     if (!osl_statement_equal(s1->statement, s2->statement)) {
00552       OSL_info("statements are not the same"); 
00553       return 0;
00554     }
00555 
00556     if (!osl_interface_equal(s1->registry, s2->registry)) {
00557       OSL_info("registries are not the same"); 
00558       return 0;
00559     }
00560 
00561     if (!osl_generic_equal(s1->extension, s2->extension)) {
00562       OSL_info("extensions are not the same"); 
00563       return 0;
00564     }
00565 
00566     s1 = s1->next;
00567     s2 = s2->next;
00568   }
00569   
00570   if (((s1 == NULL) && (s2 != NULL)) || ((s1 != NULL) && (s2 == NULL)))
00571     return 0;
00572 
00573   return 1;
00574 }
00575 
00576 
00584 int osl_scop_integrity_check(osl_scop_p scop) {
00585   int expected_nb_parameters;
00586 
00587 
00588   while (scop != NULL) {
00589     // Check the language.
00590     if ((scop->language != NULL) &&
00591         (!strcmp(scop->language, "caml")  || !strcmp(scop->language, "Caml") ||
00592          !strcmp(scop->language, "ocaml") || !strcmp(scop->language, "OCaml")))
00593       fprintf(stderr, "[OpenScop] Alert: What ?! Caml ?! Are you sure ?!?!\n");
00594 
00595     // Check the context.
00596     if (!osl_relation_integrity_check(scop->context,
00597                                       OSL_TYPE_CONTEXT,
00598                                       OSL_UNDEFINED,
00599                                       OSL_UNDEFINED,
00600                                       OSL_UNDEFINED))
00601       return 0;
00602 
00603     // Get the number of parameters.
00604     if (scop->context != NULL) 
00605       expected_nb_parameters = scop->context->nb_parameters;
00606     else
00607       expected_nb_parameters = OSL_UNDEFINED;
00608     
00609     // TODO : check the number of parameter strings.
00610 
00611     if (!osl_statement_integrity_check(scop->statement,
00612                                        expected_nb_parameters))
00613       return 0;
00614 
00615     scop = scop->next;
00616   }
00617 
00618   return 1;
00619 }
00620 
00621 
00628 int osl_scop_get_nb_parameters(osl_scop_p scop) {
00629 
00630   if (scop->context == NULL) {
00631     OSL_debug("no context domain, assuming 0 parameters");
00632     return 0;
00633   }
00634   else {
00635     return scop->context->nb_parameters;
00636   }
00637 }
00638 
00639 
00649 void osl_scop_register_extension(osl_scop_p scop, osl_interface_p interface) {
00650   osl_generic_p textual, new;
00651   char * extension_string;
00652 
00653   if ((interface != NULL) && (scop != NULL)) {
00654     osl_interface_add(&scop->registry, interface);
00655 
00656     textual = osl_generic_lookup(scop->extension, interface->URI);
00657     if (textual != NULL) {
00658       extension_string = ((osl_textual_p)textual->data)->textual;
00659       new = osl_generic_sread(extension_string, interface);
00660       osl_generic_add(&scop->extension, new);
00661     }
00662   }
00663 }
00664 
00665 
00684 void osl_scop_get_attributes(osl_scop_p scop,
00685                              int * nb_parameters,
00686                              int * nb_iterators,
00687                              int * nb_scattdims,
00688                              int * nb_localdims,
00689                              int * array_id) {
00690   int local_nb_parameters = OSL_UNDEFINED;
00691   int local_nb_iterators  = OSL_UNDEFINED;
00692   int local_nb_scattdims  = OSL_UNDEFINED;
00693   int local_nb_localdims  = OSL_UNDEFINED;
00694   int local_array_id      = OSL_UNDEFINED;
00695 
00696   while (scop != NULL) {
00697     osl_relation_get_attributes(scop->context,
00698                                 &local_nb_parameters,
00699                                 &local_nb_iterators,
00700                                 &local_nb_scattdims,
00701                                 &local_nb_localdims,
00702                                 &local_array_id);
00703 
00704     osl_statement_get_attributes(scop->statement,
00705                                 &local_nb_parameters,
00706                                 &local_nb_iterators,
00707                                 &local_nb_scattdims,
00708                                 &local_nb_localdims,
00709                                 &local_array_id);
00710     // Update.
00711     *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters);
00712     *nb_iterators  = OSL_max(*nb_iterators,  local_nb_iterators);
00713     *nb_scattdims  = OSL_max(*nb_scattdims,  local_nb_scattdims);
00714     *nb_localdims  = OSL_max(*nb_localdims,  local_nb_localdims);
00715     *array_id      = OSL_max(*array_id,      local_array_id);
00716     scop = scop->next;
00717   }
00718 }
00719 
00720 
00728 void osl_scop_normalize_scattering(osl_scop_p scop) {
00729   int max_scattering_dims = 0;
00730   osl_statement_p statement;
00731   osl_relation_p extended;
00732 
00733   if ((scop != NULL) && (scop->statement != NULL)) {
00734     // Get the max number of scattering dimensions.
00735     statement = scop->statement;
00736     while (statement != NULL) {
00737       if (statement->scattering != NULL) {
00738         max_scattering_dims = OSL_max(max_scattering_dims,
00739                                       statement->scattering->nb_output_dims);
00740       }
00741       statement = statement->next;
00742     }
00743 
00744     // Normalize.
00745     statement = scop->statement;
00746     while (statement != NULL) {
00747       if (statement->scattering != NULL) {
00748         extended = osl_relation_extend_output(statement->scattering,
00749                                               max_scattering_dims);
00750         osl_relation_free(statement->scattering);
00751         statement->scattering = extended;
00752       }
00753       statement = statement->next;
00754     }
00755   }
00756 }
00757