Result bvSignExtendBothWays(vector<FixedBits*>& children, FixedBits& output)
{
  assert(children.size() == 2);
  // The second argument is a junk size arugment.

  FixedBits& input = *children[0];
  const int inputBitWidth = input.getWidth();
  const int outputBitWidth = output.getWidth();
  assert(inputBitWidth <= outputBitWidth);

  Result result = makeEqual(input, output, 0, inputBitWidth);
  if (CONFLICT == result)
    return CONFLICT;

  // If any of the topmost bits of the output are fixed. Then they all should
  // be.
  // They should all be fixed to the same value.
  bool found = false;
  bool setTo;
  for (int i = inputBitWidth - /**/ 1 /**/; i < outputBitWidth; i++)
  {
    if (output.isFixed(i))
    {
      setTo = output.getValue(i);
      found = true;
      break;
    }
  }

  if (found)
  {
    for (int i = inputBitWidth - 1; i < outputBitWidth; i++)
    {
      if (output.isFixed(i) && (output.getValue(i) != setTo))
        return CONFLICT; // if any are set to the wrong value! bad.
      else if (!output.isFixed(i))
      {
        output.setFixed(i, true);
        output.setValue(i, setTo);
        result = CHANGED;
      }
    }

    Result result2 = makeEqual(input, output, 0, inputBitWidth);
    if (CONFLICT == result2)
      return CONFLICT;
  }
  return result;
}
Result bvZeroExtendBothWays(vector<FixedBits*>& children, FixedBits& output)
{
  assert(children.size() == 2);
  // The second argument is a junk size arugment.

  FixedBits& input = *children[0];
  const int inputBitWidth = input.getWidth();
  const int outputBitWidth = output.getWidth();

  Result result = makeEqual(input, output, 0, inputBitWidth);
  if (CONFLICT == result)
    return CONFLICT;

  // Fix all the topmost bits of the output to zero.
  for (int i = inputBitWidth; i < outputBitWidth; i++)
  {
    if (output.isFixed(i) && output.getValue(i))
      return CONFLICT; // set to one. Never right.
    else if (!output.isFixed(i))
    {
      output.setFixed(i, true);
      output.setValue(i, false);
      result = CHANGED;
    }
  }
  return result;
}
// If the guard is fixed, make equal the appropriate input and output.
// If one input can not possibly be the output. Then set the guard to make it
// the other one.
// If both values are the same. Set the output to that value.
Result bvITEBothWays(vector<FixedBits*>& children, FixedBits& output)
{
  Result result = NO_CHANGE;

  assert(3 == children.size());
  const int bitWidth = output.getWidth();
  FixedBits& guard = *children[0];
  FixedBits& c1 = *children[1];
  FixedBits& c2 = *children[2];

  assert(c1.getWidth() == c2.getWidth());
  assert(output.getWidth() == c2.getWidth());

  if (guard.isFixed(0) && guard.getValue(0))
  { // guard fixed to true. So make (first arg == output)
    result = makeEqual(output, c1, 0, bitWidth);
    if (CONFLICT == result)
      return CONFLICT;
  }
  else if (guard.isFixed(0) && !guard.getValue(0))
  {
    result = makeEqual(output, c2, 0, bitWidth);
    if (CONFLICT == result)
      return CONFLICT;
  }
  else
  {
    for (int i = 0; i < bitWidth; i++)
    {
      if (c1.isFixed(i) && c2.isFixed(i) && (c1.getValue(i) == c2.getValue(i)))
      {

        if (output.isFixed(i) && (output.getValue(i) != c1.getValue(i)))
          return CONFLICT;

        if (!output.isFixed(i))
        {
          output.setFixed(i, true);
          output.setValue(i, c1.getValue(i));
          result = CHANGED;
        }
      }
    }
  }

  bool changed = false;
  if (CHANGED == result)
    changed = true;

  for (int i = 0; i < bitWidth; i++)
  {
    if (output.isFixed(i))
    {
      if (c1.isFixed(i) && (c1.getValue(i) != output.getValue(i)))
      {
        // c1 is fixed to a value that's not the same as the output.
        if (!guard.isFixed(0))
        {
          guard.setFixed(0, true);
          guard.setValue(0, false);
          result = bvITEBothWays(children, output);
          if (CONFLICT == result)
            return CONFLICT;
          changed = true;
        }
        else if (guard.getValue(0))
          return CONFLICT;
      }

      if (c2.isFixed(i) && (c2.getValue(i) != output.getValue(i)))
      {
        // c2 is fixed to a value that's not the same as the output.
        if (!guard.isFixed(0))
        {
          guard.setFixed(0, true);
          guard.setValue(0, true);
          result = bvITEBothWays(children, output);
          if (CONFLICT == result)
            return CONFLICT;
          changed = true;
        }
        else if (!guard.getValue(0))
          return CONFLICT;
      }
    }
  }

  if (result == CONFLICT)
    return CONFLICT;
  if (changed)
    return CHANGED;

  return result;
}
Esempio n. 4
0
/** Parse with one token worth of look-ahead, return the expression object representing
    the syntax parsed.
    @param tok next token from the input.
    @param fp file subsequent tokens are being read from.
    @return the expression object constructed from the input.
*/
Expr *parse( char *tok, FILE *fp )
{
  // Create a literal token for anything that looks like a number.
  {
    long dummy;
    int pos;
    // See if the whole token parses as a long int.
    if ( sscanf( tok, "%ld%n", &dummy, &pos ) == 1 &&
         pos == strlen( tok ) ) {
      // Copy the literal to a dynamically allocated string, since makeLiteral wants
      // a string it can keep.
      char *str = (char *) malloc( strlen( tok ) + 1 );
      return makeLiteral( strcpy( str, tok ) );
    }
  }

  // Create a literal token for a quoted string, without the quotes.
  if ( tok[ 0 ] == '"' ) {
    // Same as above, make a dynamically allocated copy of the token that the literal
    // expression can keep as long as at wants to.
    int len = strlen( tok );
    char *str = (char *) malloc( len - 1 );
    strncpy( str, tok + 1, len - 2 );
    str[ len - 2 ] = '\0';
    return makeLiteral( str );
  }

  // Handle compound statements
  if ( strcmp( tok, "{" ) == 0 ) {
    int len = 0;
    int cap = INITIAL_CAPACITY;
    Expr **eList = (Expr **) malloc( cap * sizeof( Expr * ) );

    // Keep parsing subexpressions until we hit the closing curly bracket.
    while ( strcmp( expectToken( tok, fp ), "}" ) != 0 ) {
      if ( len >= cap )
        eList = (Expr **) realloc( eList, ( cap *= 2 ) * sizeof( Expr * ) );
      eList[ len++ ] = parse( tok, fp );
    }

    return makeCompound( eList, len );
  }

  // Handle language operators (reserved words)

  if ( strcmp( tok, "print" ) == 0 ) {
    // Parse the one argument to print, and create a print expression.
    Expr *arg = parse( expectToken( tok, fp ), fp );
    return makePrint( arg );
  }
  
  
  if ( strcmp( tok, "set" ) == 0 ) {
    // Parse the two operands, then make a set expression with them.
    char *str = expectToken( tok, fp );
    int len = strlen( str );
    char *name = (char *) malloc( len + 1 );
    strcpy( name, str );
    name[ len ] = '\0';
    if ( !isalpha(name[0]) || strlen( name ) > MAX_VAR || strchr( name, LEFT_BRACKET ) || strchr( name, RIGHT_BRACKET ) || strchr( name, POUND ) ) {
      // Complain if we can't make sense of the variable.
      fprintf( stderr, "line %d: invalid variable name \"%s\"\n", linesRead(), name );
      exit( EXIT_FAILURE );
    }
    Expr *expr = parse( expectToken( tok, fp ), fp );
    Expr *set = makeSet
    ( name, expr );
    free(name);
    return set;
  }
  
  if ( strcmp( tok, "add" ) == 0 ) {
    // Parse the two operands, then make an add expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeAdd( op1, op2 );
  }
  
  if ( strcmp( tok, "sub" ) == 0 ) {
    // Parse the two operands, then make a sub expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeSub( op1, op2 );
  }
  
  if ( strcmp( tok, "mul" ) == 0 ) {
    // Parse the two operands, then make a mul expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeMul( op1, op2 );
  }
  
  if ( strcmp( tok, "div" ) == 0 ) {
    // Parse the two operands, then make a div expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeDiv
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "equal" ) == 0 ) {
    // Parse the two operands, then make an equal expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeEqual
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "less" ) == 0 ) {
    // Parse the two operands, then make a less expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeLess
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "not" ) == 0 ) {
    // Parse the operand, then make a not expression with it.
    Expr *op = parse( expectToken( tok, fp ), fp );
    return makeNot
    ( op );
  }
  
  if ( strcmp( tok, "and" ) == 0 ) {
    // Parse the two operands, then make an and expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeAnd
    ( op1, op2 );
  }
      
  if ( strcmp( tok, "or" ) == 0 ) {
    // Parse the two operands, then make an or expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeOr
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "if" ) == 0 ) {
    // Parse the two operands, then make an if expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeIf
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "while" ) == 0 ) {
    // Parse the two operands, then make a while expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeWhile
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "concat" ) == 0 ) {
    // Parse the two operands, then make a concatenation expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    return makeConcat
    ( op1, op2 );
  }
  
  if ( strcmp( tok, "substr" ) == 0 ) {
    // Parse the three operands, then make a substring expression with them.
    Expr *op1 = parse( expectToken( tok, fp ), fp );
    Expr *op2 = parse( expectToken( tok, fp ), fp );
    Expr *op3 = parse( expectToken( tok, fp ), fp );
    return makeSubstr
    ( op1, op2, op3 );
  }

  
  // Handle variables
  if ( isalpha(tok[0]) && strlen( tok ) <= MAX_VAR && !strchr( tok, LEFT_BRACKET ) && !strchr( tok, RIGHT_BRACKET ) && !strchr( tok, POUND ) ) {
    // Parse the variable name and make a variable expression.
    char *str = tok;
    int len = strlen( str );
    char *name = (char *) malloc( len + 1 );
    strcpy( name, str );
    name[ len ] = '\0';
    Expr *var = makeVariable( name );
    free(name);
    return var;
  }
  
  // Complain if we can't make sense of the token.
  fprintf( stderr, "line %d: invalid token \"%s\"\n", linesRead(), tok );
  exit( EXIT_FAILURE );
  
  // Never reached.
  return NULL;
}