@@ -320,6 +320,10 @@
Loading
320 320
321 321
        //! Prints the given node with this context representation
322 322
        TRITON_EXPORT std::ostream& print(std::ostream& stream, AbstractNode* node);
323 +
324 +
      private:
325 +
        //! Return simplified extraction.
326 +
        SharedAbstractNode simplify_extract(triton::uint32 high, triton::uint32 low, const SharedAbstractNode& expr);
323 327
    };
324 328
325 329
    //! Shared AST context

@@ -789,6 +789,13 @@
Loading
789 789
      if (low == 0 && (high + 1) == expr->getBitvectorSize())
790 790
        return expr;
791 791
792 +
      if (this->modes->isModeEnabled(triton::modes::AST_OPTIMIZATIONS)) {
793 +
        auto n = this->simplify_extract(high, low, expr);
794 +
        if (n) {
795 +
          return n;
796 +
        }
797 +
      }
798 +
792 799
      SharedAbstractNode node = std::make_shared<ExtractNode>(high, low, expr);
793 800
      if (node == nullptr)
794 801
        throw triton::exceptions::Ast("AstContext::extract(): Not enough memory.");
@@ -1051,5 +1058,114 @@
Loading
1051 1058
      return this->astRepresentation.print(stream, node);
1052 1059
    }
1053 1060
1061 +
1062 +
    SharedAbstractNode AstContext::simplify_extract(triton::uint32 high, triton::uint32 low, const SharedAbstractNode& expr) {
1063 +
      auto size = expr->getBitvectorSize();
1064 +
1065 +
      if (high <= low || high >= size) {
1066 +
        return 0;
1067 +
      }
1068 +
1069 +
      auto node = expr;
1070 +
      while (true) {
1071 +
        /* Unroll references, n will contain unrolled node */
1072 +
        auto n = node;
1073 +
        while (n->getType() == REFERENCE_NODE) {
1074 +
          auto ref = reinterpret_cast<ReferenceNode*>(n.get());
1075 +
          n = ref->getSymbolicExpression()->getAst();
1076 +
        }
1077 +
1078 +
        if (n->getType() == CONCAT_NODE) {
1079 +
          /*
1080 +
           * Optimization: If we extract the full part of concatenation, just
1081 +
           * return the part. We are trying to find a part of concatenation
1082 +
           * that we can extract from. Thus, we can extract from only one part
1083 +
           * of concatenation.
1084 +
           *
1085 +
           * ((_ extract 11 9) (concat (_ bv1 8) (_ bv2 8) (_ bv3 8) (_ bv4 8))) =>
1086 +
           * ((_ extract 3 1) (_ bv3 8))
1087 +
           */
1088 +
          auto hi = n->getBitvectorSize() - 1;
1089 +
          bool found = false;
1090 +
          /* Search for part of concatenation we can extract from. Iterate
1091 +
           * from the left to the right. */
1092 +
          for (const auto& part : n->getChildren()) {
1093 +
            if (hi < high) {
1094 +
              /* Did not find a part we can extract from */
1095 +
              break;
1096 +
            }
1097 +
            auto sz = part->getBitvectorSize();
1098 +
            auto lo = hi + 1 - sz;
1099 +
            if (hi == high && lo == low) {
1100 +
              /* We are extracting the full part, just return it */
1101 +
              return part;
1102 +
            }
1103 +
            if (hi >= high && lo <= low) {
1104 +
              /* Extract from part: ((_ extract high-lo low-lo) part) */
1105 +
              node = part;
1106 +
              high -= lo;
1107 +
              low -= lo;
1108 +
              found = true;
1109 +
              break;
1110 +
            }
1111 +
            hi -= sz;
1112 +
          }
1113 +
          if (found) {
1114 +
            /* Optimize ((_ extract high low) node) one more time */
1115 +
            continue;
1116 +
          }
1117 +
        }
1118 +
        else if (n->getType() == ZX_NODE || n->getType() == SX_NODE) {
1119 +
          /*
1120 +
           * Optimization: If we extract from the node being extended, just
1121 +
           * return the node
1122 +
           *
1123 +
           * ((_ extract 31 0) ((_ zero_extend 32) (_ bv1 32))) => (_ bv1 32)
1124 +
           *
1125 +
           * ((_ extract 7 0) ((_ sign_extend 32) (_ bv1 32))) =>
1126 +
           * ((_ extract 7 0) (_ bv1 32))
1127 +
           **/
1128 +
          n = n->getChildren()[1];
1129 +
          auto sz = n->getBitvectorSize();
1130 +
          if (low == 0 && high + 1 == sz) {
1131 +
            /* Just return the node being extended */
1132 +
            return n;
1133 +
          }
1134 +
          if (high < sz) {
1135 +
            /* Optimize ((_ extract high low) n) one more time */
1136 +
            node = n;
1137 +
            continue;
1138 +
          }
1139 +
        }
1140 +
        break;
1141 +
      }
1142 +
1143 +
      /* Unroll references, n will contain unrolled node */
1144 +
      auto n = node;
1145 +
      while (n->getType() == REFERENCE_NODE) {
1146 +
        auto ref = reinterpret_cast<ReferenceNode*>(n.get());
1147 +
        n = ref->getSymbolicExpression()->getAst();
1148 +
      }
1149 +
1150 +
      /*
1151 +
       * Optimization: extract from extract is one extract
1152 +
       *
1153 +
       * ((_ extract high low) ((_ extract hi lo) a)) =>
1154 +
       * ((_ extract high+lo low+lo) a)
1155 +
       **/
1156 +
      if (n->getType() == EXTRACT_NODE) {
1157 +
        const auto& childs = n->getChildren();
1158 +
        auto hi = reinterpret_cast<IntegerNode*>(childs[0].get())->getInteger().convert_to<uint32>();
1159 +
        auto lo = reinterpret_cast<IntegerNode*>(childs[1].get())->getInteger().convert_to<uint32>();
1160 +
        if (lo + high <= hi) {
1161 +
          node = childs[2];
1162 +
          high += lo;
1163 +
          low += lo;
1164 +
        }
1165 +
      }
1166 +
1167 +
      return node == expr ? 0 : this->extract(high, low, node);
1168 +
    }
1169 +
1054 1170
  }; /* ast namespace */
1055 1171
}; /* triton namespace */
Files Coverage
src/libtriton 86.14%
Project Totals (107 files) 86.14%
2813.3
TRAVIS_OS_NAME=linux
1
coverage:
2
  range: 70..100
3
  round: nearest
4
  precision: 2
5

6
ignore:
7
  - "**/examples/cpp" # ignore folders and all its contents
8
  - "/src/tracer"     # ignore folders and all its contents
9
  - "**/*.spec"       # glob accepted
10

11
comment: false
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading