Пример #1
0
 /**
  * This method updates the source attributes for all statements in a block. This is typically done
  * in conjunction with a substitution, when we're inlining constraints from e.g. pre- and
  * post-conditions.
  *
  * @param block
  * @param nsrc
  * @return
  */
 public static Block resource(Block block, Attribute.Source nsrc) {
   if (block == null) {
     return null;
   }
   Block nblock = new Block(block.numInputs());
   for (Entry e : block) {
     nblock.append(e.code, nsrc);
   }
   return nblock;
 }
Пример #2
0
  /**
   * Import an external block into this one, using a given <i>binding</i>. The binding indicates how
   * the input variables for the external block should be mapped into the variables of this block.
   *
   * <p>
   *
   * <p>Every input variable in the block must be bound to something in the binding. Otherwise, an
   * IllegalArgumentException is raised. In the case of an input bound to a slot >= numSlots(), then
   * the number of slots is increased automatically. <b>NOTE:</b> temporary variables used in the
   * external block will be mapped automatically to unused slots in this environment to prevent
   * collisions. Therefore, temporary variables should not be specified in the binding.
   */
  public void importExternal(Block block, Map<Integer, Integer> binding) {
    int freeSlot = numSlots();

    // First, sanity check that all input variables are bound
    HashMap<Integer, Integer> nbinding = new HashMap<Integer, Integer>();
    for (int i = 0; i != block.numInputs; ++i) {
      Integer target = binding.get(i);
      if (target == null) {
        throw new IllegalArgumentException("Input not mapped by input");
      }
      nbinding.put(i, target);
      freeSlot = Math.max(target + 1, freeSlot);
    }

    // Second, determine binding for temporary variables
    for (int i = block.numInputs; i != block.numSlots(); ++i) {
      nbinding.put(i, i + freeSlot);
    }

    // Third, determine relabelling
    HashMap<String, String> labels = new HashMap<String, String>();

    for (Entry s : block) {
      if (s.code instanceof Code.Label) {
        Code.Label l = (Code.Label) s.code;
        labels.put(l.label, freshLabel());
      }
    }

    // Finally, apply the binding and relabel any labels as well.
    for (Entry s : block) {
      Code ncode = s.code.remap(nbinding).relabel(labels);
      append(ncode, s.attributes());
    }
  }
Пример #3
0
  public Block relabel() {
    HashMap<String, String> labels = new HashMap<String, String>();

    for (Entry s : this) {
      if (s.code instanceof Code.Label) {
        Code.Label l = (Code.Label) s.code;
        labels.put(l.label, freshLabel());
      }
    }

    Block block = new Block(numInputs);
    // Finally, apply the binding and relabel any labels as well.
    for (Entry s : this) {
      Code ncode = s.code.relabel(labels);
      block.append(ncode, s.attributes());
    }

    return block;
  }
Пример #4
0
  private Block readCodeBlock(int numInputs) throws IOException {
    Block block = new Block(numInputs);
    int nCodes = input.read_uv();
    HashMap<Integer, Code.Label> labels = new HashMap<Integer, Code.Label>();

    for (int i = 0; i != nCodes; ++i) {
      Code code = readCode(i, labels);
      block.append(code);
    }

    // NOTE: we must go up to nCodes+1 because of the possibility of a label
    // occurring after the very last bytecode instruction.
    for (int i = 0, j = 0; i != nCodes + 1; ++i, ++j) {
      Code.Label label = labels.get(i);
      if (label != null) {
        block.insert(j++, label);
      }
    }

    input.pad_u8(); // necessary

    return block;
  }
Пример #5
0
  protected T propagate(int start, int end, T store, List<Pair<Type, String>> handlers) {
    for (int i = start; i < end; ++i) {
      Entry entry = block.get(i);
      try {
        Code code = entry.code;

        // First, check for a label which may have incoming information.
        if (code instanceof Code.Label) {
          Code.Label l = (Code.Label) code;
          T tmp = stores.get(l.label);
          if (tmp != null && store != null) {
            store = join(store, tmp);
          } else if (tmp != null) {
            store = tmp;
          }
        }

        T oldStore = store;

        if (store == null) {
          // this indicates dead-code has been reached.
          continue;
        } else if (code instanceof Code.Loop) {
          Code.Loop loop = (Code.Loop) code;
          Block.Entry nEntry = entry;
          int s = i;
          // Note, I could make this more efficient!
          while (++i < block.size()) {
            nEntry = block.get(i);
            if (nEntry.code instanceof Code.Label) {
              Code.Label l = (Code.Label) nEntry.code;
              if (l.label.equals(loop.target)) {
                // end of loop body found
                break;
              }
            }
          }
          store = propagate(s, i, loop, entry, store, handlers);
          continue;
        } else if (code instanceof Code.IfGoto) {
          Code.IfGoto ifgoto = (Code.IfGoto) code;
          Pair<T, T> r = propagate(i, ifgoto, entry, store);
          store = r.second();
          merge(ifgoto.target, r.first(), stores);
        } else if (code instanceof Code.IfType) {
          Code.IfType ifgoto = (Code.IfType) code;
          Pair<T, T> r = propagate(i, ifgoto, entry, store);
          store = r.second();
          merge(ifgoto.target, r.first(), stores);
        } else if (code instanceof Code.Switch) {
          Code.Switch sw = (Code.Switch) code;

          List<T> r = propagate(i, sw, entry, store);

          // assert r.second().size() == nsw.branches.size()
          Code.Switch nsw = (Code.Switch) entry.code;
          for (int j = 0; j != nsw.branches.size(); ++j) {
            String target = nsw.branches.get(j).second();
            T nstore = r.get(j);
            merge(target, nstore, stores);
          }
          merge(sw.defaultTarget, store, stores);
          store = null;
        } else if (code instanceof Code.TryCatch) {
          Code.TryCatch sw = (Code.TryCatch) code;
          int s = i;

          // Note, I could make this more efficient!
          while (++i < block.size()) {
            entry = block.get(i);
            if (entry.code instanceof Code.Label) {
              Code.Label l = (Code.Label) entry.code;
              if (l.label.equals(sw.target)) {
                // end of loop body found
                break;
              }
            }
          }

          ArrayList<Pair<Type, String>> nhandlers = new ArrayList<Pair<Type, String>>(handlers);
          nhandlers.addAll(0, sw.catches);
          store = propagate(s + 1, i, store, nhandlers);
          i = i - 1; // this is necessary since last label of
          // try-catch is first label of catch handler
        } else if (code instanceof Code.Goto) {
          Code.Goto gto = (Code.Goto) entry.code;
          merge(gto.target, store, stores);
          store = null;
        } else {
          // This indicates a sequential statement was encountered.
          store = propagate(i, entry, store);
          if (entry.code instanceof Code.Return || entry.code instanceof Code.Throw) {
            store = null;
          }
        }

        mergeHandlers(i, code, oldStore, handlers, stores);

      } catch (SyntaxError se) {
        throw se;
      } catch (Throwable ex) {
        internalFailure("internal failure", filename, entry, ex);
      }
    }

    return store;
  }