Added support for bitwise operators.
authorDavid Anderson <dvander@alliedmods.net>
Thu Jun 28 00:26:55 2012 -0700 (2012-06-28)
changeset 8069d207a8f2a
parent 7 0478c27ba82c
child 9 73781c5a59d7
Added support for bitwise operators.
jitcraft/BytecodeCompiler.cpp
jitcraft/Interpreter.cpp
jitcraft/Opcodes.cpp
jitcraft/Opcodes.tbl
jitcraft/Parser.cpp
jitcraft/Parser.h
jitcraft/Scanner.cpp
jitcraft/SemanticAnalysis.cpp
jitcraft/Token.h
jitcraft/Types.h
jitcraft/main.cpp
tests/prototype/bitops.sp
     1.1 --- a/jitcraft/BytecodeCompiler.cpp	Wed Jun 27 22:02:40 2012 -0700
     1.2 +++ b/jitcraft/BytecodeCompiler.cpp	Thu Jun 28 00:26:55 2012 -0700
     1.3 @@ -76,6 +76,18 @@
     1.4          return OP_MUL;
     1.5        case TOK_SLASH:
     1.6          return OP_DIV;
     1.7 +      case TOK_SHR:
     1.8 +        return OP_SHR;
     1.9 +      case TOK_USHR:
    1.10 +        return OP_USHR;
    1.11 +      case TOK_SHL:
    1.12 +        return OP_SHL;
    1.13 +      case TOK_BITAND:
    1.14 +        return OP_BITAND;
    1.15 +      case TOK_BITOR:
    1.16 +        return OP_BITOR;
    1.17 +      case TOK_BITXOR:
    1.18 +        return OP_BITXOR;
    1.19      }
    1.20      assert(false);
    1.21      return OP_NOP;
     2.1 --- a/jitcraft/Interpreter.cpp	Wed Jun 27 22:02:40 2012 -0700
     2.2 +++ b/jitcraft/Interpreter.cpp	Thu Jun 28 00:26:55 2012 -0700
     2.3 @@ -366,6 +366,60 @@
     2.4      break;
     2.5  }
     2.6  
     2.7 +case OP_SHL:
     2.8 +{
     2.9 +    int right = POP_I32(top);
    2.10 +    int left = POP_I32(top);
    2.11 +    int result = left << right;
    2.12 +    PUSH_I32(top, result);
    2.13 +    break;
    2.14 +}
    2.15 +
    2.16 +case OP_SHR:
    2.17 +{
    2.18 +    int right = POP_I32(top);
    2.19 +    int left = POP_I32(top);
    2.20 +    int result = left >> right;
    2.21 +    PUSH_I32(top, result);
    2.22 +    break;
    2.23 +}
    2.24 +
    2.25 +case OP_USHR:
    2.26 +{
    2.27 +    int right = POP_I32(top);
    2.28 +    int left = POP_I32(top);
    2.29 +    int result = unsigned(left) >> unsigned(right);
    2.30 +    PUSH_I32(top, result);
    2.31 +    break;
    2.32 +}
    2.33 +
    2.34 +case OP_BITAND:
    2.35 +{
    2.36 +    int right = POP_I32(top);
    2.37 +    int left = POP_I32(top);
    2.38 +    int result = left & right;
    2.39 +    PUSH_I32(top, result);
    2.40 +    break;
    2.41 +}
    2.42 +
    2.43 +case OP_BITOR:
    2.44 +{
    2.45 +    int right = POP_I32(top);
    2.46 +    int left = POP_I32(top);
    2.47 +    int result = left | right;
    2.48 +    PUSH_I32(top, result);
    2.49 +    break;
    2.50 +}
    2.51 +
    2.52 +case OP_BITXOR:
    2.53 +{
    2.54 +    int right = POP_I32(top);
    2.55 +    int left = POP_I32(top);
    2.56 +    int result = left ^ right;
    2.57 +    PUSH_I32(top, result);
    2.58 +    break;
    2.59 +}
    2.60 +
    2.61  case OP_POP:
    2.62      top.sp--;
    2.63      break;
     3.1 --- a/jitcraft/Opcodes.cpp	Wed Jun 27 22:02:40 2012 -0700
     3.2 +++ b/jitcraft/Opcodes.cpp	Thu Jun 28 00:26:55 2012 -0700
     3.3 @@ -67,6 +67,12 @@
     3.4            case OP_SETARRAY_F:
     3.5            case OP_GETARRAY_P:
     3.6            case OP_BOUNDS_STA:
     3.7 +          case OP_SHL:
     3.8 +          case OP_SHR:
     3.9 +          case OP_USHR:
    3.10 +          case OP_BITAND:
    3.11 +          case OP_BITOR:
    3.12 +          case OP_BITXOR:
    3.13              break;
    3.14  
    3.15            case OP_STOP:
     4.1 --- a/jitcraft/Opcodes.tbl	Wed Jun 27 22:02:40 2012 -0700
     4.2 +++ b/jitcraft/Opcodes.tbl	Thu Jun 28 00:26:55 2012 -0700
     4.3 @@ -89,8 +89,8 @@
     4.4  //
     4.5  OPDEF(OP_GETARRAY_I,    23,         "getarray.i",   1,      2,  1)
     4.6  OPDEF(OP_SETARRAY_I,    24,         "setarray.i",   1,      3,  1)
     4.7 -OPDEF(OP_GETARRAY_F,    25,         "getarray.i",   1,      2,  1)
     4.8 -OPDEF(OP_SETARRAY_F,    26,         "setarray.i",   1,      3,  1)
     4.9 +OPDEF(OP_GETARRAY_F,    25,         "getarray.f",   1,      2,  1)
    4.10 +OPDEF(OP_SETARRAY_F,    26,         "setarray.f",   1,      3,  1)
    4.11  OPDEF(OP_GETARRAY_P,    27,         "getarray.p",   1,      2,  1)
    4.12  
    4.13  // Allocate an array of N dimensions into unsafe memory. Each dimension size
    4.14 @@ -134,3 +134,10 @@
    4.15  OPDEF(OP_MUL_F,         35,         "mul.f",        1,      2,  1)
    4.16  OPDEF(OP_DIV_F,         36,         "div.f",        1,      2,  1)
    4.17  
    4.18 +// Bitwise operators.
    4.19 +OPDEF(OP_SHL,           37,         "shl",          1,      2,  1)
    4.20 +OPDEF(OP_SHR,           38,         "shr",          1,      2,  1)
    4.21 +OPDEF(OP_USHR,          39,         "ushr",         1,      2,  1)
    4.22 +OPDEF(OP_BITAND,        40,         "bitand",       1,      2,  1)
    4.23 +OPDEF(OP_BITOR,         41,         "bitor",        1,      2,  1)
    4.24 +OPDEF(OP_BITXOR,        42,         "bitxor",       1,      2,  1)
     5.1 --- a/jitcraft/Parser.cpp	Wed Jun 27 22:02:40 2012 -0700
     5.2 +++ b/jitcraft/Parser.cpp	Thu Jun 28 00:26:55 2012 -0700
     5.3 @@ -251,7 +251,7 @@
     5.4  {
     5.5      Expression *left = addition();
     5.6      while (left) {
     5.7 -        if (!match(TOK_SHL))
     5.8 +        if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
     5.9              break;
    5.10          TokenKind kind = scanner_.last();
    5.11          Expression *right = addition();
    5.12 @@ -263,9 +263,54 @@
    5.13  }
    5.14  
    5.15  Expression *
    5.16 +Parser::bitand()
    5.17 +{
    5.18 +    Expression *left = shift();
    5.19 +    while (left) {
    5.20 +        if (!match(TOK_BITAND))
    5.21 +            break;
    5.22 +        Expression *right = shift();
    5.23 +        if (!right)
    5.24 +            return NULL;
    5.25 +        left = new (pool_) BinaryExpression(TOK_BITAND, left, right);
    5.26 +    }
    5.27 +    return left;
    5.28 +}
    5.29 +
    5.30 +Expression *
    5.31 +Parser::bitxor()
    5.32 +{
    5.33 +    Expression *left = bitand();
    5.34 +    while (left) {
    5.35 +        if (!match(TOK_BITXOR))
    5.36 +            break;
    5.37 +        Expression *right = shift();
    5.38 +        if (!right)
    5.39 +            return NULL;
    5.40 +        left = new (pool_) BinaryExpression(TOK_BITXOR, left, right);
    5.41 +    }
    5.42 +    return left;
    5.43 +}
    5.44 +
    5.45 +Expression *
    5.46 +Parser::bitor()
    5.47 +{
    5.48 +    Expression *left = bitxor();
    5.49 +    while (left) {
    5.50 +        if (!match(TOK_BITOR))
    5.51 +            break;
    5.52 +        Expression *right = shift();
    5.53 +        if (!right)
    5.54 +            return NULL;
    5.55 +        left = new (pool_) BinaryExpression(TOK_BITOR, left, right);
    5.56 +    }
    5.57 +    return left;
    5.58 +}
    5.59 +
    5.60 +Expression *
    5.61  Parser::relational()
    5.62  {
    5.63 -    Expression *left = shift();
    5.64 +    Expression *left = bitor();
    5.65      while (left) {
    5.66          TokenKind kind = scanner_.peek();
    5.67          if (kind < TOK_LT || kind > TOK_GE)
     6.1 --- a/jitcraft/Parser.h	Wed Jun 27 22:02:40 2012 -0700
     6.2 +++ b/jitcraft/Parser.h	Thu Jun 28 00:26:55 2012 -0700
     6.3 @@ -55,8 +55,11 @@
     6.4      Expression *primary();
     6.5      Expression *unary();
     6.6      Expression *multiplication();
     6.7 +    Expression *addition();
     6.8      Expression *shift();
     6.9 -    Expression *addition();
    6.10 +    Expression *bitand();
    6.11 +    Expression *bitxor();
    6.12 +    Expression *bitor();
    6.13      Expression *relational();
    6.14      Expression *equals();
    6.15      Expression *expression();
     7.1 --- a/jitcraft/Scanner.cpp	Wed Jun 27 22:02:40 2012 -0700
     7.2 +++ b/jitcraft/Scanner.cpp	Thu Jun 28 00:26:55 2012 -0700
     7.3 @@ -274,6 +274,15 @@
     7.4              putChar(c);
     7.5              return TOK_PLUS;
     7.6  
     7.7 +          case '&':
     7.8 +            return TOK_BITAND;
     7.9 +
    7.10 +          case '|':
    7.11 +            return TOK_BITOR;
    7.12 +
    7.13 +          case '^':
    7.14 +            return TOK_BITXOR;
    7.15 +
    7.16            case '-': return TOK_MINUS;
    7.17            case ',': return TOK_COMMA;
    7.18            case '\0': return TOK_EOF;
    7.19 @@ -302,6 +311,12 @@
    7.20              c = getChar();
    7.21              if (c == '=')
    7.22                  return TOK_GE;
    7.23 +            if (c == '>') {
    7.24 +                c = getChar();
    7.25 +                if (c == '>')
    7.26 +                    return TOK_USHR;
    7.27 +                return TOK_SHR;
    7.28 +            }
    7.29              putChar(c);
    7.30              return TOK_GT;
    7.31  
     8.1 --- a/jitcraft/SemanticAnalysis.cpp	Wed Jun 27 22:02:40 2012 -0700
     8.2 +++ b/jitcraft/SemanticAnalysis.cpp	Thu Jun 28 00:26:55 2012 -0700
     8.3 @@ -183,12 +183,12 @@
     8.4              node->setType(left->isFloat() ? left : right);
     8.5              return;
     8.6          }
     8.7 +    }
     8.8  
     8.9 -        // Otherwise, both sides must be integer.
    8.10 -        assert(left->isInt() && right->isInt());
    8.11 -        node->setType(left);
    8.12 -        return;
    8.13 -    }
    8.14 +    // For now, assert everything else is integer and untagged.
    8.15 +    assert(left->isInt() && right->isInt());
    8.16 +    assert(!left->tag() && !right->tag());
    8.17 +    node->setType(left);
    8.18  }
    8.19  
    8.20  void
    8.21 @@ -257,6 +257,9 @@
    8.22  
    8.23              type = Type::NewUnsafeArray(type, size);
    8.24          }
    8.25 +    } else {
    8.26 +        Type *right = visitForLoad(node->initialization());
    8.27 +        assert(TypeCheck(type, right));
    8.28      }
    8.29  
    8.30      node->variable()->setType(type);
     9.1 --- a/jitcraft/Token.h	Wed Jun 27 22:02:40 2012 -0700
     9.2 +++ b/jitcraft/Token.h	Thu Jun 28 00:26:55 2012 -0700
     9.3 @@ -36,6 +36,11 @@
     9.4      _(MINUS,              "-")                          \
     9.5      _(STAR,               "*")                          \
     9.6      _(SLASH,              "/")                          \
     9.7 +    _(BITAND,             "&")                          \
     9.8 +    _(BITOR,              "|")                          \
     9.9 +    _(BITXOR,             "^")                          \
    9.10 +    _(SHR,                ">>")                         \
    9.11 +    _(USHR,               ">>>")                        \
    9.12      _(SHL,                "<<")                         \
    9.13      _(ASSIGN,             "=")                          \
    9.14      _(SEMICOLON,          ";")                          \
    10.1 --- a/jitcraft/Types.h	Wed Jun 27 22:02:40 2012 -0700
    10.2 +++ b/jitcraft/Types.h	Thu Jun 28 00:26:55 2012 -0700
    10.3 @@ -68,6 +68,10 @@
    10.4          assert(isArray());
    10.5          return levels_;
    10.6      }
    10.7 +    Name *tag() const {
    10.8 +        assert(isPrimitive());
    10.9 +        return tag_;
   10.10 +    }
   10.11      Type *innermost() const {
   10.12          assert(isArray());
   10.13          Type *temp = contained();
    11.1 --- a/jitcraft/main.cpp	Wed Jun 27 22:02:40 2012 -0700
    11.2 +++ b/jitcraft/main.cpp	Thu Jun 28 00:26:55 2012 -0700
    11.3 @@ -96,7 +96,7 @@
    11.4      if (!Interpret(frame, &result))
    11.5          return false;
    11.6  
    11.7 -    printf("Result: %f\n", result.f);
    11.8 +    printf("Result: %d\n", result.i32);
    11.9  
   11.10      return true;
   11.11  }
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tests/prototype/bitops.sp	Thu Jun 28 00:26:55 2012 -0700
    12.3 @@ -0,0 +1,14 @@
    12.4 +main()
    12.5 +{
    12.6 +    new result = 5192342;
    12.7 +    for (new i = 0; i < 100000; i = i + 1) {
    12.8 +        result = result | i;
    12.9 +        result = result & 9129345;
   12.10 +        result = result ^ (i * 73);
   12.11 +
   12.12 +        new bit = result & 1;
   12.13 +        result = (result >>> 1) | (bit << 31);
   12.14 +        result = result | (i >> 6);
   12.15 +    }
   12.16 +    return result;
   12.17 +}