/*********************************************************************** COPYRIGHT The following is a notice of limited availability of the code and Government license and disclaimer which must be included in the prologue of the code and in all source listings of the code. Copyright notice (c) 1977 University of Chicago Permission is hereby granted to use, reproduce, prepare derivative works, and to redistribute to others at no charge. If you distribute a copy or copies of the Software, or you modify a copy or copies of the Software or any portion of it, thus forming a work based on the Software and make and/or distribute copies of such work, you must meet the following conditions: a) If you make a copy of the Software (modified or verbatim) it must include the copyright notice and Government license and disclaimer. b) You must cause the modified Software to carry prominent notices stating that you changed specified portions of the Software. This software was authored by: Argonne National Laboratory J. Michalakes: (630) 252-6646; email: michalak@mcs.anl.gov Mathematics and Computer Science Division Argonne National Laboratory, Argonne, IL 60439 ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES OF ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, AND OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A CONTRACT WITH THE DEPARTMENT OF ENERGY. GOVERNMENT LICENSE AND DISCLAIMER This computer code material was prepared, in part, as an account of work sponsored by an agency of the United States Government. The Government is granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable worldwide license in this data to reproduce, prepare derivative works, distribute copies to the public, perform publicly and display publicly, and to permit others to do so. NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. ***************************************************************************/ #include #include "n32.h" #include "sym.h" #include "dm.h" #include "twst.h" static int in_id_ref = 0 ; static int doing_lhs = 0 ; void * firsttok(), *my_malloc(), *malloc(), *strip_nl(), *strip_lead(), *index(), *newTokNode() ; char* make_upper(s) char *s ; { char *p ; for ( p = s ; *p ; p++ ) { if (( *p >= 'a' ) && ( *p <= 'z' )) *p = ( *p - 'a' + 'A' ) ; } return(s) ; } /* 970910 */ collapse_idrefs( node ) NodePtr node ; { int d ; NodePtr dex, elder, paren ; sym_nodeptr id ; if (node == NULL) return ; if ( MINORKIND(node) == idrefK ) { if ( getclass(node) == ARRAY ) { if ((id=sym_get(TOKSTRING(CHILD(node,0)))) != NULL ) { if ((paren = CHILD(node,1)) != NULL) { for ( d=0 , dex=CHILD(paren,1) ; dex!=NULL; dex=SIBLING(dex) ) { if ( MINORKIND(dex) == TCOMMA ) continue ; if (!strcmp( id->dimname[d],"REMOVED" )) { /* snip it out of the list */ if (elder=ELDER(dex)) SIBLING(elder) = SIBLING(dex) ; else /* must be number one */ { CHILD(PARENT(dex),1) = SIBLING(dex) ; if (SIBLING(dex)) ELDER(SIBLING(dex)) = NULL ; } } d++ ; } /* get rid of extra commas */ for ( dex=CHILD(paren,1) ; dex!=NULL; dex=SIBLING(dex) ) { if ( MINORKIND(dex) == TCOMMA ) { if (elder=ELDER(dex)) { if (SIBLING(dex)) { if (MINORKIND(SIBLING(dex)) == TCOMMA) { SIBLING(elder) = SIBLING(dex) ; } } else /* trailing */ { SIBLING(elder) = NULL ; } } else /* must be number one */ { CHILD(PARENT(dex),1) = SIBLING(dex) ; if (SIBLING(dex)) ELDER(SIBLING(dex)) = NULL ; } } } /* get rid of () thingies */ if ((dex=CHILD(paren,1)) == NULL) { CHILD(node,1) = NULL ; } } } } } } handle_executable( node ) NodePtr node ; { sym_nodeptr x ; loop_t * LOOP ; array_t * AR ; NodePtr p, firstt, sib ; int var_child, body_child, range_child, d ; char loopbeginline[1024] ; if (node == NULL) return ; if (p = (NodePtr) firsttok(node)) statement_line_number = atoi(TOKBEGIN(p)) ; if (statement_line_number == 0) statement_line_number = atoi(TOKBEGIN(p)) ; if (statement_line_number == 0) statement_line_number = last_statement_line_number ; /* last resort -- this can happen for artificial nodes, like enddo nodes that were put in to change labeled doK blocks */ last_statement_line_number = statement_line_number ; switch (MINORKIND(node)) { case gotoK : /* check for the case we don't handle: where a goto references a do loop label. */ if ((x=sym_get(TOKSTRING(CHILD(node,2)))) != NULL) { /* we're going to just have to allow this; it's quite prevalent in MM5 */ #if 0 fprintf(stderr,"DM Error line %s: GOTO end of do loop label: %s\n", TOKBEGIN(CHILD(node,2)), TOKSTRING(CHILD(node,2))) ; #endif } break ; case doenddoK : var_child = 3 ; /* which child of node is loop var */ body_child = 6 ; /* which child of node is loop body */ range_child = 5 ; /* which child of node has ranges */ /* FALL THROUGH */ case doK : if ( MINORKIND(node) == doK ) { var_child = 4 ; body_child = 7 ; range_child = 6 ; /* store label reference in symbol table */ x = sym_add(TOKSTRING(CHILD(node,2))) ; } loop_level++ ; LOOP = (loop_t *)my_malloc(sizeof(loop_t)); LOOP->ARLIST = NULL; LOOP->LI_IS = 0 ; LOOP->loop = node ; LOOP->indentation = atoi(TOKCOLS(CHILD(node,1)))-1 ; /* column of DO */ strcpy(LOOP->LI,TOKSTRING(CHILD(node,var_child))) ; LOOP->next = LOOPLIST ; /* push loop onto stack */ LOOPLIST = LOOP ; /* mark the loop variable as assigned -- this terminates the set/def chains that will be checked later for dependencies on loop vars */ x = sym_add(LOOP->LI) ; node->user_def = (NodePtr)x->assigned ; x->assigned = (unsigned long)node ; x->thisif = (unsigned long)thisif ; x->iflev = iflev ; if ( sw_write_db ) { sprintf(loopbeginline,"stmtline %d loopvar %s",statement_line_number,LOOP->LI) ; } walk_statements1( CHILD(node,body_child),handle_executable, loop_level,loop_level ) ; /* make global, the bare (non index) instances of the loop variable */ LOOP = LOOPLIST ; switch ( LOOP->LI_IS ) { case MDIM : if ( sw_write_db ) { fprintf(db_file,"LOOPBEGIN: M %s\n",loopbeginline) ; fprintf(db_file,"LOOPEND: M stmtline %d loopvar %s\n",statement_line_number,LOOP->LI) ; } p = (NodePtr)firsttok(node) ; surgery_add_loop_begin( MDIM, LOOP, node, range_child, body_child ) ; li_loc2glob( CHILD(node,body_child), LOOP->LI, MDIM ) ; break ; case NDIM : if ( sw_write_db ) { fprintf(db_file,"LOOPBEGIN: N %s\n",loopbeginline) ; fprintf(db_file,"LOOPEND: N stmtline %d loopvar %s\n", statement_line_number,LOOP->LI) ; } p = (NodePtr)firsttok(node) ; surgery_add_loop_begin( NDIM, LOOP, node, range_child, body_child ) ; li_loc2glob( CHILD(node,body_child), LOOP->LI, NDIM ) ; break ; default : if ( sw_write_db ) { fprintf(db_file,"LOOPBEGIN: ? %s\n",loopbeginline) ; fprintf(db_file,"LOOPEND: ? stmtline %d loopvar %s\n", statement_line_number,LOOP->LI) ; } if ( LOOP->LI_IS == (MDIM | NDIM) ) { NodePtr frstt ; int linex ; linex = -1 ; if (( frstt = (NodePtr)firsttok(node)) != NULL ) linex=atoi(TOKBEGIN(frstt)) ; fprintf(stderr,"line %d: %s Loop over both dimensions. %d\n",linex,LOOP->LI,LOOP->LI_IS) ; exit(2);} /* this removes the statement label and puts an enddo on the loop */ if ( MINORKIND(node) == doK ) { surgery_add_loop_begin( 0, LOOP, node, range_child, body_child ) ; } break ; } LOOPLIST = LOOPLIST->next ; loop_level-- ; break ; case endK: LOOP = LOOPLIST ; /* handle references to arrays in the loop that are over the classified dimension but that are indexed by an expression that is not a function of LOOP->LI . */ /* reverse the lst so traversal is in correct order of occurrence in file */ { array_t * Z, * TEMPLIST ; TEMPLIST = NULL ; for ( AR = LOOP->ARLIST, Z = AR ; AR != NULL ; ) { Z = AR->next ; AR->next = TEMPLIST ; TEMPLIST = AR ; AR = Z ; } LOOP->ARLIST = TEMPLIST ; } for ( AR = LOOP->ARLIST ; AR != NULL ; AR = AR->next ) { for ( d = 0 ; d < AR->ndim ; d++ ) { if ( AR->SYM->dims[d] != AR->Index_IS[d] ) { if (AR->SYM->dims[d] == MDIM) { surgery_addset_constants( AR, d, MDIM, body_child ) ; } else if (AR->SYM->dims[d] == NDIM ) { surgery_addset_constants( AR, d, NDIM, body_child ) ; } } } } #if 1 /* make global, the bare (non index) instances of the loop variable */ LOOP = LOOPLIST ; switch ( LOOP->LI_IS ) { case MDIM : li_loc2glob( first_statement, LOOP->LI, MDIM ) ; /* 970225 */ break ; case NDIM : li_loc2glob( first_statement, LOOP->LI, NDIM ) ; /* 970225 */ break ; default : break ; } #endif cleanup(LOOP) ; break ; /********************************************************************** The rest of these need to be handled because descent into loop bodies is cut short by the last argument of zero in the call to walk_statements in the file dm.c */ case iflogicalK : node->user_def = (NodePtr) thisif ; thisif = node ; iflev++ ; walk_depth( CHILD(node,3), handle_refs, 0 ) ; walk_statements1( CHILD(node,5),handle_executable,loop_level,loop_level ) ; iflev-- ; thisif = node->user_def ; break ; case ifthenelseK : node->user_def = (NodePtr) thisif ; thisif = node ; iflev++ ; walk_depth( CHILD(node,3), handle_refs, 0 ) ; walk_statements1( CHILD(node,6),handle_executable,loop_level,loop_level ) ; walk_statements1( CHILD(node,8),handle_executable,loop_level,loop_level ) ; iflev-- ; thisif = node->user_def ; break ; case ifthenelseifK : node->user_def = (NodePtr) thisif ; thisif = node ; iflev++ ; walk_depth( CHILD(node,3), handle_refs, 0 ) ; walk_statements1( CHILD(node,6),handle_executable,loop_level,loop_level ) ; walk_statements1( CHILD(node,7),handle_executable,loop_level,loop_level ) ; iflev-- ; thisif = node->user_def ; break ; case dowhileK : walk_depth( CHILD(node,3), handle_refs, 0 ) ; walk_statements1( CHILD(node,5),handle_executable,loop_level,loop_level ) ; break ; case readK : case writeK : walk_depth( CHILD(node,3), handle_refs, 0 ) ; break ; case stopK : if ( sw_change_stops ) { char pp[1024] ; MINORKIND(node) = 9001 ; /* morph the node */ node->user_def = (NodePtr) my_malloc( 1024 ) ; if ( CHILD(node,2) != NULL ) { int pplen, chlen ; char *p, *q ; strcpy( pp, TOKSTRING(CHILD(node,2)) ) ; chlen = strlen(sw_change_stops_string) ; for ( p = pp, q = pp ; *q ; ) /* remove quotes */ { while ( *q == '\'' || *q == '"' ) q++ ; *p++ = *q++ ; } *p = '\0' ; pplen = strlen(pp) ; if ( pplen+chlen > 50 ) pp[50-chlen] = '\0' ; /* wtch length */ if ( MINORKIND(CHILD(node,2)) == TICON ) { sprintf((char *)node->user_def," CALL %s('%s') \n",sw_change_stops_string,pp) ; } if ( MINORKIND(CHILD(node,2)) == TSTRING ) { sprintf((char *)node->user_def," CALL %s('%s') \n",sw_change_stops_string,pp) ; } } else { sprintf((char *)node->user_def," CALL %s('BARE STOP %s')\n",sw_change_stops_string, modulename ) ; } } break ; case assignK : /* we're interested in where int scalars, which may be used for indexes, are assigned in the program (we don't look at arrays because it's not likely they'd be used as indeces, plus we wouldn't necessarily know which element. */ { if ( getclass(CHILD(node,1)) == VARIABLE ) { x = sym_add(TOKSTRING(CHILD(CHILD(node,1),0))) ; node->user_def = (NodePtr)x->assigned ; x->assigned = (unsigned long)node ; x->thisif = (unsigned long) thisif ; x->iflev = iflev ; } } sib = SIBLING(node) ; SIBLING(node) = NULL ; doing_lhs = 1 ; walk_depth( CHILD(node,1), handle_refs, 0 ) ; doing_lhs = 0 ; walk_depth( CHILD(node,3), handle_refs, 0 ) ; SIBLING(node) = sib ; break ; case callK : if ( sw_addargs || sw_addgenericargs ) { NodePtr q, p, prev_q ; sym_nodeptr x ; char tmp[256] ; for ( q = CHILD(node,4) ; q != NULL ; prev_q = q , q = SIBLING(q) ) { if ( MINORKIND(q) == TCOMMA ) continue ; if ( MINORKIND(q) == idrefK ) { if ((x = sym_get( TOKSTRING(CHILD(q,0)) )) != NULL ) { /* This handles instances where the argument is one of the identifiers that have been listed using -mdim or -mdim directives. It inserts a macro around the argument to allow adding arguments. */ if ( x->dim == MDIM || x->dim == NDIM ) { p = CHILD(q,0) ; MINORKIND(p) = 9009 ; /* morph the node */ sprintf(tmp,"D_ARG_%c(%s)",(x->dim==MDIM)?'M':'N', TOKSTRING(p)) ; p->user_def = (NodePtr) malloc(strlen(tmp)+1) ; strcpy(p->user_def,tmp) ; } /* We want to be able to handle cases where a decomposed array is passed to a subroutine, but with index arguments. If the index argument to a decomposed dimension is '1', and all the index arguments to the left are also '1', then the intention on the part of the user is assumed to be that they want a pointer to the first element of the array. We need to adjust the arguments so that they point to the first element in the local array, not just the first element of the partition. Do this by inserting a macro around the argument. */ { NodePtr paren, arg, node ; int keepgoing, i; keepgoing = 1 ; i = 0 ; if (( paren = CHILD(q,1)) != NULL ) { for (arg = CHILD(paren,1); arg != NULL && keepgoing ; arg = SIBLING(arg)) { if ( MINORKIND(arg) == TCOMMA ) continue ; if ( MINORKIND(arg) == TICON ) { if (!strcmp(TOKSTRING(arg),"1")) { if (x->dims[i] == MDIM || x->dims[i] == NDIM ) { MINORKIND(arg) = 9009 ; /* morph the node */ sprintf(tmp,"D_BASEDEX_%c(%s)",(x->dims[i]==MDIM)?'M':'N', TOKSTRING(arg)) ; arg->user_def = (NodePtr) malloc(strlen(tmp)+1) ; strcpy(arg->user_def,tmp) ; } } else { keepgoing = 0 ; } } else { keepgoing = 0 ; } i++ ; } } } } } } if ( sw_addgenericargs && prev_q != NULL ) { q = prev_q ; if ( SIBLING(q) == NULL ) { NodePtr NewNode ; TokInfoPtr p ; p = (TokInfoPtr)malloc(sizeof(*p)) ; NewNode = (NodePtr) newTokNode( p ) ; SIBLING(NewNode) = NULL ; ELDER(NewNode) = q ; MINORKIND(NewNode) = 9009 ; /* morph the node */ sprintf(tmp,",D_ARG_G") ; NewNode->user_def = (NodePtr) malloc(strlen(tmp)+1) ; strcpy(NewNode->user_def,tmp) ; SIBLING(q) = NewNode ; } } } /* FALL THROUGH */ default : sib = SIBLING(node) ; SIBLING(node) = NULL ; walk_depth( node, handle_refs, 0 ) ; SIBLING(node) = sib ; break ; } } handle_refs( node ) NodePtr node ; { NodePtr paren, dex, elder ; array_t * AR, * p ; loop_t * LOOP ; NodePtr firstt, dummy[DEPENDS_MAXRET] ; int nret ; int d, linex ; char outstr[1024], tmpstr[1024] ; if (node == NULL) return ; if ( MINORKIND(node) != idrefK ) return ; if (( firstt = (NodePtr) firsttok(node)) != NULL ) linex = atoi(TOKBEGIN(firstt)) ; switch (getclass(node)) { case ARRAY: AR = (array_t *)my_malloc(sizeof(array_t)) ; if ((AR->SYM=sym_get(TOKSTRING(CHILD(node,0)))) == NULL ) { if ( ! sw_quiet ) { fprintf(stderr,"Advisory: Line %s: No declaration for %s.\n", TOKBEGIN(CHILD(node,0)),TOKSTRING(CHILD(node,0))) ; } return ; } AR->Ref = node ; AR->iflev = iflev ; if ((paren = CHILD(node,1)) != NULL) { for ( AR->ndim=0, dex = CHILD(paren,1) ; dex != NULL; dex = SIBLING(dex) ) { if (MINORKIND(dex) == TCOMMA) continue ; AR->ndim++ ; } outstr[0] = '\0' ; for ( LOOP = LOOPLIST ; LOOP != NULL ; LOOP=LOOP->next ) { for ( d=0 , dex=CHILD(paren,1) ; dex!=NULL; dex=SIBLING(dex) ) { if (MINORKIND(dex) == TCOMMA) continue ; AR->Index[d] = dex ; if ( depends_on(dex, LOOP->LI, linex, dummy, 0)) { if (sw_write_db &&((AR->SYM->dims[d] == MDIM)||(AR->SYM->dims[d] == NDIM))) { int ofst ; int ifull ; char * fullorpart ; int i ; ofst = offset(dex, LOOP->LI, linex) ; if ( 1 ) /* doing_lhs || ofst != 0 ) */ { ifull = 0 ; for ( i = 0 ; i < AR->ndim ; i++ ) { if ( AR->SYM->dims[i] == MDIM ) ifull |= 1 ; if ( AR->SYM->dims[i] == NDIM ) ifull |= 2 ; } switch ( ifull ) { case 1: fullorpart = "partM" ; break ; case 2: fullorpart = "partN" ; break ; case 3: fullorpart = "full" ; break ; default : fullorpart ="?" ; break ; } if ( ifull > 0 ) { if ( strlen(outstr) == 0 ) { sprintf(outstr,"%s: %c stmtline %d arr %s %s ndim %d <", (doing_lhs)?"SET":"USE", (AR->SYM->dims[d] == MDIM)?'M':'N', statement_line_number, TOKSTRING(CHILD(node,0)), showstorage(getstorage(node)), AR->ndim) ; for ( i = 0 ; i < AR->ndim ; i++ ) { sprintf(tmpstr,"%c", (AR->SYM->dims[i] == MDIM)?'M':((AR->SYM->dims[i] == NDIM)?'N':'?') ) ; strcat( outstr, tmpstr ) ; } sprintf(tmpstr,"> <") ; strcat( outstr, tmpstr ) ; for ( i = 0 ; i < AR->ndim ; i++ ) { if ( AR->SYM->dims[i] == MDIM || AR->SYM->dims[i] == NDIM ) { sprintf(tmpstr,"%c", (AR->SYM->dims[i] == MDIM)?'M':((AR->SYM->dims[i] == NDIM)?'N':'?') ) ; strcat( outstr, tmpstr ) ; } } sprintf(tmpstr,"> %s ", fullorpart ) ; strcat( outstr, tmpstr ) ; } sprintf(tmpstr,"%d ",ofst) ; strcat( outstr, tmpstr ) ; } } } if (AR->SYM->dims[d] == MDIM) { LOOP->LI_IS |= MDIM ; AR->Index_IS[d] = LOOP->LI_IS ; strcpy(AR->INDEX[d], LOOP->LI); } else if (AR->SYM->dims[d] == NDIM) { LOOP->LI_IS |= NDIM ; AR->Index_IS[d] = LOOP->LI_IS ; strcpy(AR->INDEX[d], LOOP->LI); } } d++; } } if (sw_write_db && outstr[0]) fprintf(db_file,"%s\n", outstr) ; for ( LOOP = LOOPLIST ; LOOP != NULL ; LOOP=LOOP->next ) { p = (array_t *)my_malloc(sizeof(array_t)) ; bcopy(AR,p,sizeof(array_t)) ; p->next = LOOP->ARLIST ; LOOP->ARLIST=p ; } } break ; default : break ; } } is_expr_of(LI,dex) char * LI ; NodePtr dex ; { int i ; if (dex == NULL) return(0) ; if ( MAJORKIND(dex) != exK ) return(0) ; if ( MINORKIND(dex) == idrefK ) { return ( (strcmp(TOKSTRING(CHILD(dex,0)),LI) == 0) ) ; } else { for ( i = 0 ; i < maxChildren ; i++ ) { if (is_expr_of(LI,CHILD(dex,i))) /* recursion */ { return(1) ; } } } return(0) ; } /* given a node pointing to an index expression, find all the id references therein, and pass back a pointer to the latest assigment before this statement */ NodePtr last_def(node, highest, retsym ) NodePtr node ; int * highest ; sym_nodeptr *retsym ; { sym_nodeptr x ; NodePtr firstt, retnode ; int curr_line ; int linex ; *highest = 0 ; *retsym = NULL ; if ( node == NULL ) return(NULL) ; /* find this statement number */ if ((firstt = (NodePtr)firsttok( node )) != NULL ) curr_line = atoi(TOKBEGIN(firstt)) ; else return(NULL) ; return(last_def1( node, curr_line, highest, retsym )) ; } NodePtr last_def1( node, curr_line, highest, retsym ) NodePtr node ; int curr_line ; int * highest ; sym_nodeptr *retsym ; /* return pointer to sym entry that found retnode */ { int i, hi ; sym_nodeptr x ; NodePtr firstt, p, retnode ; int linex ; retnode = NULL ; hi = 0 ; if ( node == NULL ) return(NULL) ; #if 0 printf("curr_line %d, highest %d\n",curr_line, *highest ) ; print_info(stdout,node) ; #endif switch( MINORKIND(node) ) { case idrefK : if ( getclass(node) == VARIABLE ) { if ((x=sym_get(TOKSTRING(CHILD(node,0)))) != NULL ) { NodePtr q ; for ( q = (NodePtr)x->assigned ; q != NULL ; q = q->user_def ) { firstt = (NodePtr)firsttok( q ) ; linex = atoi(TOKBEGIN(firstt)) ; if ( linex <= curr_line && linex > *highest ) { *highest = linex ; retnode = q ; *retsym = x ; } } } } return(retnode) ; break ; default : for ( i = 0 ; i < maxChildren ; i++ ) { if ((p=last_def1( CHILD(node,i), curr_line, &hi, retsym )) != NULL ) { retnode = p ; *highest = hi ; } } return(retnode) ; break ; } return(NULL) ; } surgery_add_loop_begin( dim, LOOP, node, range_child, body_child ) unsigned long dim ; loop_t * LOOP ; NodePtr node ; int range_child ; int body_child ; { NodePtr p, q ; NodePtr LSNode, LENode, PrevStat, Parent, dummy[DEPENDS_MAXRET] ; NodePtr firstt ; int linex ; char ranges[256] ; char spacing[256] ; int i ; int nret ; char * collapsestr ; /* 970206 if loop range contains an expression of a decomposed loop dimension -- for example, mix -- ignore it. */ for ( p = CHILD(node,range_child) ; p!=NULL ; p = SIBLING(p)) { if (( q = CHILD(p,2) ) != NULL ) { linex = 999999 ; if ((firstt = (NodePtr)firsttok(q)) != NULL ) linex = atoi(TOKBEGIN(firstt)) ; for ( i = 0 ; i < cursor_dimtab ; i++ ) { if (depends_on(q, dimtab[i], linex, dummy, 0)) { if ( sw_allloops==0 ) { if ( ! sw_quiet ) { fprintf(stderr, "Advisory: loop at line %d not converted. Loop range depends on %s\n", linex, dimtab[i]) ; } dim = 0 ; } #if 0 /* 970529 instead of ignoring it, make the loop range global */ else if ( sw_treatlocal ) { } #endif } } } } /* end 970206 */ /* handle loop ending */ for ( q = NULL, p = CHILD(node,body_child) ; p != NULL ; p = SIBLING(p) ) { q = p ; } if ( q == NULL ) { fprintf(stderr,"Internal error: no ending statement in loop?\n") ; exit(2) ; } linex = -1 ; if ((firstt = (NodePtr)firsttok(q)) != NULL ) linex = atoi(TOKBEGIN(firstt)) ; /* simplified 970605 -- we're converting all the loops to do-enddo anyway, so there's no reason to eliminate the continue statements. Just put the ENDDO at the end */ if (MINORKIND(q) == enddoK ) { LSNode = q ; MINORKIND(q) = 9001 ; /* morph the node */ } else { LSNode = newExNode( 9001 ) ; /* add a node */ SIBLING(q) = LSNode ; ELDER(LSNode) = q ; } LSNode->user_def = (NodePtr) my_malloc( 1024 ) ; spacing[0] = '\0' ; for ( i = 0 ; i < LOOP->indentation ; i++ ) strcat(spacing," ") ; if ( dim == MDIM || dim == NDIM ) { char dimtag[4] ; dimtag[0] = '\0' ; if ( sw_tag_enddos ) sprintf(dimtag,"_%c",(dim==MDIM)?'M':'N') ; if ((dim == MDIM && sw_collapse_loops_m)||(dim == NDIM && sw_collapse_loops_n)) collapsestr = "COLLAPSE_" ; else collapsestr = "" ; if ( sw_L && linex != -1 ) sprintf((char *)LSNode->user_def,"%4d\t%s%s_%sENDDO%s\n",linex,spacing,toolname,collapsestr,dimtag) ; else sprintf((char *)LSNode->user_def,"%s%s_%sENDDO%s\n",spacing,toolname,collapsestr,dimtag) ; } else { sprintf((char *)LSNode->user_def,"%sENDDO\n",spacing) ; if ( MINORKIND(node) == doK ) { sprintf(TOKSTRING(CHILD(node,2)),"") ; /* get rid of label */ } } linex = -1 ; if ((firstt = (NodePtr)firsttok(node)) != NULL ) linex = atoi(TOKBEGIN(firstt)) ; if ( dim == MDIM || dim == NDIM ) { /* handle loop beginning */ if ((PrevStat = ELDER(node)) != NULL ) { NodePtr x ; /* not the first statement */ LSNode = newExNode( 9000 ) ; CHILD(LSNode,0) = CHILD(node, 0) ; CHILD(LSNode,1) = CHILD(node, body_child) ; x = CHILD(node, body_child) ; PARENT(x) = LSNode ; SIBLING(LSNode) = SIBLING(node) ; SIBLING(PrevStat) = LSNode ; ELDER(LSNode) = PrevStat ; if ((x = SIBLING(node)) != NULL ) ELDER(x) = LSNode ; } else { int i ; NodePtr x ; /* first statement; hence, the child of a node */ if (( Parent = PARENT(node)) == NULL ) { fprintf(stderr,"Internal error: huh?\n") ; exit(2) ; } for( i = 0 ; i < maxChildren ; i++ ) { if ( CHILD(Parent,i) == node ) break ; } if ( i == maxChildren ) { fprintf(stderr,"Internal error: unknown child\n") ; exit(2) ; } LSNode = newExNode( 9000 ) ; CHILD(Parent,i) = LSNode ; PARENT(LSNode) = Parent ; CHILD(LSNode,0) = CHILD(node, 0) ; CHILD(LSNode,1) = CHILD(node, body_child) ; x = CHILD(node, body_child) ; PARENT(x) = LSNode ; SIBLING(LSNode) = SIBLING(node) ; ELDER(LSNode) = NULL ; if ((x = SIBLING(node)) != NULL ) ELDER(x) = LSNode ; } if ( first_e == node ) first_e = LSNode ; /* we're gonna cheat and use the user_def field (a NodePtr) in this new node to store a string we'll construct that will be put as-is into the program for the statement. Since it will actually point to a char*, casting will be used */ LSNode->user_def = (NodePtr) my_malloc( 1024 ) ; getstat( CHILD(node, range_child), 1, ranges ) ; spacing[0] = '\0' ; for ( i = 0 ; i < LOOP->indentation ; i++ ) strcat(spacing," ") ; if ((dim == MDIM && sw_collapse_loops_m)||(dim == NDIM && sw_collapse_loops_n)) collapsestr = "COLLAPSE_" ; else collapsestr = "" ; if ( sw_L && linex != -1 ) { sprintf((char *)LSNode->user_def, "%4d\t%s%s_%sDO_%c( %s, %s )\n", linex, spacing, toolname, collapsestr, dim==MDIM?'M':'N', LOOP->LI, make_upper((char*)strip_nl(strip_lead( ranges ))) ) ; } else { sprintf((char *)LSNode->user_def, "%s%s_%sDO_%c( %s, %s )\n", spacing, toolname, collapsestr, dim==MDIM?'M':'N', LOOP->LI, make_upper((char*)strip_nl(strip_lead( ranges ))) ) ; } } } surgery_addset_constants( AR, d, whichdim, body_child ) array_t * AR ; int d ; int whichdim ; int body_child ; { NodePtr firstt, ttt ; int i ; NodePtr Tvar, Idx, Parent, x ; NodePtr place, PrevStat, NewNode ; char expr[1024] ; char dc ; char * ds ; sym_nodeptr sx, retsym ; char varx[32] ; /* temporary variable name */ char vx[64] ; int new_varx ; int linex ; int thisline, thatline ; firstt = (NodePtr) firsttok(AR->Index[AR->SYM->MDEX]) ; if ( firstt != NULL ) { /* fprintf(stderr,"... tokbegin %s\n",TOKBEGIN(firstt)) ; */ thisline = atoi(TOKBEGIN(firstt)) ; } else { /* fprintf(stderr,"... tokbegin ?\n") ; */ thisline = 9999999 ; } switch(whichdim) { case MDIM : Idx = AR->Index[AR->SYM->MDEX] ; dc = 'I' ; ds = "M" ; break ; case NDIM : Idx = AR->Index[AR->SYM->NDEX] ; dc = 'J' ; ds = "N" ; break ; default : fprintf(stderr,"bad dim arg %d\n",whichdim); exit(10) ; break ; } /* replace the expression with a temporary variable and assign the temporary variable with the correct value prior to the loop */ x = SIBLING(Idx) ; SIBLING(Idx) = NULL ; getstat( Idx, 1, expr ) ; /* if the Idx expression is protected leave it alone 3/1/97 */ if ( MINORKIND(Idx) == idrefK ) { if (!strncmp(TOKSTRING(CHILD(Idx,0)),"noflic",6)) { SIBLING(Idx) = x ; if ( !sw_quiet ) { fprintf(stderr,"Advisory: Protected index line %d: %s\n", getlinenumber(Idx),expr) ; } return ; } } if ((place = last_def( Idx, &linex, &retsym )) != NULL ) { int ifl ; NodePtr ifn ; /* at this point, place contains a pointer to the node that was the most recent definition for a term in the index expression. retsym contains a pointer to a symbol table entry for the identifier in the expression that was defined at place. this symbol table entry also contains iflev, which tells the number of conditional level's place was on, and thisif, a pointer to the node for the "if" node at that level (the one who's body contains the node for place). Each of the if nodes uses the field user_def to link to it's next level up and so on, until NULL. Thus, by following this chain up we can get up to a statement that's at the same level as the current global iflev so that the setting of the constant won't be subject to a conditional. */ for ( ifl = retsym->iflev, ifn =(NodePtr)(retsym->thisif); ifl>(AR->iflev+1); ifl--, ifn=ifn->user_def ) { place = place ; } if ( ifl < 0 ) { fprintf(stderr,"internal error\n") ; exit(23) ; } /* at this point, ifn will point to the if statement at the same level or lower than us, or it will be null */ /* test the line number of sibling of IFN */ if ( ifn != NULL ) { place = ifn ; if ( getlinenumber(SIBLING(ifn)) >= getlinenumber( Idx ) ) { /* generate the expression in place */ /* splice Tvar into list in place of Idx */ Tvar = copy_tok_node( firsttok(Idx) ) ; TOKSTRING(Tvar) = (char*)my_malloc(256) ; sprintf(TOKSTRING(Tvar), "\n +%s_G2L_%s(%s,%s)\n +", toolname,ds,strip_nl(strip_lead(expr)),AR->SYM->dimname[d]) ; SIBLING(Idx) = x ; goto expinplace ; /* >>>>> GOTO GOTO GOTO !!!!! <<<<< */ } } /* fprintf(stderr,"place 1 %08x\n", place ) ; */ if ( place != NULL ) place = SIBLING(place) ; /* fprintf(stderr,"place 2 %08x\n", place ) ; */ } SIBLING(Idx) = x ; sprintf(vx,"%s,%s|%d",strip_nl(strip_lead(expr)),AR->SYM->dimname[d],linex) ; if (( sx = sym_get(vx) ) == NULL ) { sx = sym_add(vx) ; sprintf(varx, "%c%sT_%d", dc, toolname, tvarcnt++ ) ; strcpy(sx->varx,varx) ; new_varx = 1 ; } else { strcpy(varx,sx->varx) ; new_varx = 0 ; } { char * p ; if ((p = (char *)index(vx,'|')) != NULL ) *p = '\0' ; } if ( new_varx ) { if ( place == NULL ) { #if 0 place = first_e ; fprintf(stderr,"%s, place was NULL, set to first_e\n",__FILE__ ) ; #else /* step place forward through assigns and calls and stop at the first non assign or call or at the statement before one we are generating this for in the first place. The idea is to put the translations as late as possible in the routine but before anything that can change flow of control through this routine. */ for ( place = first_e ; place != NULL ; place = SIBLING(place) ) { ttt = (NodePtr) firsttok( place ) ; if ( ttt != NULL ) { thatline = atoi( TOKBEGIN( ttt ) ) ; } else { thatline = 999999999 ; } /* fprintf(stderr,"thatline %d thisline %d\n", thatline, thisline ) ; */ if ( thatline >= thisline ) break ; if ( SIBLING(place) != NULL ) { if ( MINORKIND(place) != assignK && MINORKIND(place) != callK ) { break ; } } } #endif } if (( PrevStat = ELDER(place)) != NULL ) { NewNode = newExNode( 9001 ) ; SIBLING(NewNode) = place ; SIBLING(PrevStat) = NewNode ; ELDER(NewNode) = PrevStat ; if (place != NULL) ELDER(place) = NewNode ; } else { if (( Parent = PARENT(place)) == NULL ) { fprintf(stderr,"Internal error: huh?\n") ; exit(2) ; } for( i = 0 ; i < maxChildren ; i++ ) { if ( CHILD(Parent,i) == place ) break ; } if ( i == maxChildren ) { fprintf(stderr,"error: unknown child 2\n") ; exit(2) ; } NewNode = newExNode( 9001 ) ; CHILD(Parent,i) = NewNode ; PARENT(NewNode) = Parent ; SIBLING(NewNode) = place ; ELDER(NewNode) = NULL ; if ( place != NULL ) ELDER(place) = NewNode ; } /* 970228 first_e = NewNode ; */ NewNode->user_def = (NodePtr) my_malloc( 1024 ) ; sprintf((char *)NewNode->user_def," %s=%s_G2L_%s(%s)\n",varx,toolname,ds,vx) ; /* add declaration of temp var to module after last decl. Note that it's possible there is no last decl. In that case, don't do anything -- the variables don't need to be declared because the program is (apparently) using implicit typing anyway. */ place = last_d ; if ( place != NULL ) { NewNode = newExNode( 9001 ) ; SIBLING(NewNode) = SIBLING(place) ; ELDER(NewNode) = place ; x = SIBLING(place) ; if ( x != NULL ) ELDER(x) = NewNode ; SIBLING(place) = NewNode ; last_d = NewNode ; NewNode->user_def = (NodePtr) my_malloc( 1024 ) ; sprintf((char *)NewNode->user_def, " INTEGER %s\n", varx) ; } } /* splice Tvar into list in place of Idx */ Tvar = copy_tok_node( firsttok(Idx) ) ; TOKSTRING(Tvar) = (char*)my_malloc(256) ; sprintf(TOKSTRING(Tvar), "%s",varx) ; expinplace: /* target of >>>>> GOTO GOTO GOTO !!!!! <<<<< */ SIBLING(Tvar) = SIBLING(Idx) ; ELDER(Tvar) = ELDER(Idx) ; PARENT(Tvar) = PARENT(Idx) ; if ((x = ELDER(Idx)) != NULL) { SIBLING(x) = Tvar ; } if ((x = PARENT(Idx)) != NULL) { for (i = 0 ; i < maxChildren ; i++) { if ( CHILD(x,i) == Idx ) break ; } if ( i < maxChildren ) { CHILD(x,i) = Tvar ; } } SIBLING(Idx) = NULL ; ELDER(Idx) = NULL ; PARENT(Idx) = NULL ; } static int li_dim ; static char* li_LI ; li_loc2glob2( node ) NodePtr node ; { NodePtr firstt, rettok[DEPENDS_MAXRET], tok, newnode ; char stat[256] ; int i, itok ; if ( node == NULL ) return ; firstt = (NodePtr) firsttok(node) ; switch (MINORKIND(node)) { case 9000 : li_loc2glob( CHILD(node,1), li_LI, li_dim ) ; break ; case ifthenelseK : case ifthenelseifK : case iflogicalK : for ( itok = 0 ; itok < DEPENDS_MAXRET ; itok++ ) rettok[itok] = NULL; if ( depends_on( CHILD(node,3), li_LI, atoi(TOKBEGIN(firstt)), rettok, 1)) { for ( itok = 0 ; itok < DEPENDS_MAXRET ; itok++ ) { NodePtr ft ; TokInfoPtr q ; if ((tok = rettok[itok]) == NULL ) continue ; getstat( tok, 1, stat ) ; ft=(NodePtr)firsttok( CHILD(node,3) ) ;/* get a token to copy */ newnode = (NodePtr) copy_tok_node( ft ) ; if ((SIBLING(newnode) = SIBLING(tok)) != NULL) ELDER(SIBLING(newnode)) = newnode ; if ((ELDER(newnode) = ELDER(tok)) != NULL ) SIBLING(ELDER(newnode)) = newnode ; PARENT(newnode) = PARENT(tok) ; if ( PARENT(tok) != NULL ) { for (i = 0 ; i < maxChildren ; i++ ) if ( CHILD(PARENT(tok),i) == tok ) break ; CHILD(PARENT(tok),i) = newnode ; } TOKSTRING(newnode) = (char*)my_malloc(64) ; /* sprintf(TOKSTRING(newnode),"((%s)-%cdif)", strip_nl(strip_lead(stat)), li_dim==MDIM?'i':'j') ; */ sprintf(TOKSTRING(newnode),"(%s_L2G_%c(%s))", toolname, li_dim==MDIM?'M':'N', strip_nl(strip_lead(stat))) ; } } break ; } } li_loc2glob( node, LI, dim ) NodePtr node ; char * LI ; int dim ; { NodePtr tok ; int i ; if ( node == NULL ) return ; li_LI = LI ; li_dim = dim ; walk_statements1( node, li_loc2glob2, 999, 0) ; } NodePtr copy_tok_node( node ) NodePtr node ; { NodePtr p, newNode() ; TokInfoPtr q ; if ( node == NULL ) return(NULL) ; if ( MAJORKIND(node) != tokenK ) return(NULL) ; q = (struct TokenRecType * ) my_malloc(sizeof(struct TokenRecType)) ; *q = *(node->u.Token) ; p = (NodePtr) newNode() ; *p = *node ; p->u.Token = q ; return(p) ; } cleanup( loop ) loop_t *loop ; { array_t *ar, *deadar ; for ( ar = (loop)->ARLIST ; ar != NULL ; ) { deadar = ar ; ar = ar->next ; free(deadar) ; } free(loop) ; } getlinenumber( node ) NodePtr node ; { NodePtr firstt ; if ((firstt=(NodePtr)firsttok(node)) != NULL) { return(atoi(TOKBEGIN(firstt))) ; } else { return(-1) ; } }