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; }
/** 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; }