OpenScop 0.8.1
|
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