next up previous contents
Next: References Up: Application Examples Previous: Local Reordering

Local Label Renaming

Label renaming is typically needed when replicating code. The modifications must be applied at two distinct types of locations: in label declarations, and in the references to the labels in instructions.

To rename label references, we have to modify expressions appearing in instruction arguments. This is performed using the expression substitution primitive on operand abstractions. Labels themselves are replaced with new labels, built from scratch using the new name.

The application code in the example below performs a brute-force, substring-based renaming of all labels and symbols appearing in the code sections of the assembly file. However, it is presented for illustrative purposes and does not handle the directives and labels which are located in sections other than "text", thus potentially introducing inconsistencies between declarations and uses of data labels.

#include "salto.h"

// replace all non-overlapping occurrences of oldTxt with newTxt in
// src, leaving hte result in dst.  NO CHECKS FOR OVERFLOWS ARE MADE.
// NOTE: the argument order follows the conventions of str...() functions.

unsigned int
strSubstitute(char *dst, char *src, char *newTxt, char
			   *oldTxt)
{
  unsigned int res = 0 ;
  char *occurrence ;

  while ((occurrence = strstr(src, oldTxt))) {
    strncpy(dst, src, occurrence - src) ; // leading common text
    dst += occurrence - src ;
    strcpy(dst, newTxt) ;	// new text where old one should be
    dst += strlen(newTxt) ;
    src = occurrence + strlen(oldTxt) ; // new begin of common txt
    res++ ;
  }
  strcpy(dst, src) ;		// final step: txt past last occurrence

  return res ;			// number of substitutions performed
}

char *oldText, *newText;


void usage(void)
{
  fprintf(stderr,
	  "Simple renaming module. Module-specific parameters (after '--'):"
	  "\n\n"
	  "  -h                 print this help message and exit\n"
	  "  -from <word>       label (sub-)string to be replaced\n"
	  "  -to <word>         label (sub-)string to use instead\n\n"
	  "Both '-from' and '-to' arguments must be given.\n") ;
}


void Salto_init_hook(int argc, char **argv)
{
  int i;
  oldText = NULL ;
  newText = NULL ;

  for (i = 0; i < argc - 1; i++) { // we leave out the last arg
				   // (should be a value, not an option)
    if (!strcmp(argv[i], "-from")) // (sub-)string to be replaced
      oldText = argv[i + 1] ;	// it necessarily exists...
      
    if (!strcmp(argv[i], "-to")) // new value to be used in renaming
      newText = argv[i + 1] ;	// it necessarily exists...

    if (!strcmp(argv[i], "-h")) {
      usage() ;			// print help message and exit
      exit (0) ;		// successfully
    }
  }

  if (!strcmp(argv[i], "-h")) {	// help asked for ==> exit successfully
    usage() ;
    exit (0) ;
  }

  if ((!oldText)
      ||
      (!newText)) {		// help badly needed ==> fail
    usage() ;
    exit (1) ;
  }

  // here, things go ahead normally
}

// user application entry point... Either linked dynamically
// (default), or statically (through "make static")

void Salto_hook(void)
{
  BB *bb;
  CFG *cfg;
  INST *insn, *label, *directive;
  unsigned int ncfg, nbb, ninsts, nopds, i, j, k, l;
  int substitutions;

  ncfg = numberOfCFG() ;	// number of CFG in program
  if (!ncfg) return ;		// nothing to do if no procedures found

  for (i = 0; i < ncfg; i++) {	// FOR ALL PROCEDURES
    cfg = getCFG(i) ;           // get current CFG
  
    nbb = cfg -> numberOfBB() ; // number of basic blocks

    for (j = 0; j < nbb; j++) {	// FOR ALL BASIC BLOCKS
      bb = cfg -> getBB(j) ;    // get current BB

      ninsts = bb -> numberOfInstructions(); // number of insns in BB

      for (k = 1; k < ninsts - 1; k++) { // FOR ALL INSTRUCTIONS...
					 // NOTE: first and last insn are
                                         // reserved oned and shouldn't be
                                         // scanned, hence the range 1..n-2

        insn = bb -> getInstruction(k) ; // get current instruction

        if (insn -> isAsm()) {

	  // for ASM insns, replace name substring in operands by
	  // substituting all non-overlapping occurrences of oldText with
	  // newText.  The replacement is performed on operand abstractions.

          nopds = insn -> numberOfOperands() ;

          // scan all operands of the instruction
          for (l = 0; l < nopds; l++) {
            OperandInfo &op = insn -> getOperand(l) ;
            
            if (op . isExpr()) { // only for expressions
	      // substitute the strings; retvalue is number of substits
	      substitutions = op . substitute(oldText, newText) ;
              if (substitutions) {
                insn -> setOperand(l, op) ; // make it effective
                fprintf(stderr,
                        "Operand substitution succeeded @"
                        " CFG/BB/INST/OPD=%d/%d/%d/%d...\n",
                        i,j,k,l) ;
	      }
	    }
	  }
	}
	else if (insn -> isLabel()) {

	  // for labels, replace the label by a new one, whose name
	  // results from the substitution of oldText with newText...

          char *oldLabelName, newLabelName[80];
	  
          oldLabelName = insn -> getName() ; // get name of label
	  
          // replace all non-overlapping occurrences of oldText with
          // newText.  Note the the str...() argument ordering.

	  substitutions =
	    strSubstitute(newLabelName, oldLabelName, newText, oldText) ;

          // if at least one substitution succeeded
          if (substitutions) {
            label = newLabel(newLabelName) ; // make a new label
            bb -> insertInstruction(k, label) ; // insert in place
				// of original insn at pos k (= old label).
				// The old label gets shifted by 1 position
            bb -> removeInstruction(k + 1) ;    // remove the old label
            fprintf(stderr,
                    "Label replacement succeeded @"
                    " CFG/BB/INST = %d/%d/%d...\n",
                    i, j, k) ;
          } // if (substitutions)
        } // if (insn -> isLabel())

	else if (insn -> isPseudo()) {

	  // for directives, we have to go a little bit into Salto
	  // internals (note the type cast :-)

	  char *oldDirective, newDirective[256] ;

	  // get the full text of the directive
	  oldDirective = ((xPseudo *) insn) -> getText() ;

	  // substitute strings
	  substitutions =
	    strSubstitute(newDirective, oldDirective, newText, oldText) ;

	  // process if successful
	  if (substitutions) {
	    directive = newPseudo(newDirective) ; // make the new one
	    bb -> insertInstruction(k, directive) ; // insert in BB
	    bb -> removeInstruction(k + 1) ;    // remove the old label
            fprintf(stderr,
                    "Directive replacement succeeded @"
                    " CFG/BB/INST = %d/%d/%d...\n",
                    i, j, k) ;
	  } // if (substitutions)
	} // if (insn -> isPseudo())
      } // for all insns
    } // for all basic blocks
  } // for all procedures

  // generate the modified code...
  produceCode(stdout) ;
}


next up previous contents
Next: References Up: Application Examples Previous: Local Reordering

Erven Rohou
Fri Oct 17 09:15:29 MET DST 1997