/** check that the types of all instance keys are assignable to declared type of pointer key */
  private void checkTypes(IntSet b) {
    assert PARANOID;
    if (b == null) return;
    if (!(pointerKey instanceof LocalPointerKey)) {
      return;
    }
    final LocalPointerKey lpk = (LocalPointerKey) pointerKey;
    CGNode node = lpk.getNode();
    final IClassHierarchy cha = node.getClassHierarchy();
    final IR ir = node.getIR();
    if (ir == null) return;
    TypeInference ti = TypeInference.make(ir, false);
    final IClass type = ti.getType(lpk.getValueNumber()).getType();
    if (type == null) return;
    // don't perform checking for exception variables
    if (cha.isAssignableFrom(cha.lookupClass(TypeReference.JavaLangThrowable), type)) {
      return;
    }
    b.foreach(
        new IntSetAction() {

          public void act(int x) {
            InstanceKey ik = instanceKeys.getMappedObject(x);
            IClass concreteType = ik.getConcreteType();
            if (!cha.isAssignableFrom(type, concreteType)) {
              System.err.println("BOOM");
              System.err.println(ir);
              System.err.println(lpk + " type " + type);
              System.err.println(ik + " type " + concreteType);
              Assertions.UNREACHABLE();
            }
          }
        });
  }
  /**
   * Add constraints to represent the flow of exceptions to the exceptional return value for this
   * node
   */
  protected void addNodePassthruExceptionConstraints(CGNode node, IR ir) {
    // add constraints relating to thrown exceptions that reach the exit block.
    List<ProgramCounter> peis =
        SSAPropagationCallGraphBuilder.getIncomingPEIs(ir, ir.getExitBlock());
    PointerKey exception = heapModel.getPointerKeyForExceptionalReturnValue(node);
    IClass c = node.getClassHierarchy().lookupClass(TypeReference.JavaLangThrowable);

    addExceptionDefConstraints(ir, node, peis, exception, Collections.singleton(c));
  }