@Override
  public void computeDataOffsets(DexBody body) {
    Debug.printDbg("compute data offset");
    if (!(instruction instanceof Instruction31t))
      throw new IllegalArgumentException(
          "Expected Instruction31t but got: " + instruction.getClass());

    Instruction31t fillArrayInstr = (Instruction31t) instruction;
    int offset = fillArrayInstr.getCodeOffset();
    int targetAddress = codeAddress + offset;

    Instruction referenceTable = body.instructionAtAddress(targetAddress).instruction;

    if (!(referenceTable instanceof ArrayPayload)) {
      throw new RuntimeException(
          "Address 0x"
              + Integer.toHexString(targetAddress)
              + " refers to an invalid PseudoInstruction ("
              + referenceTable.getClass()
              + ").");
    }

    ArrayPayload arrayTable = (ArrayPayload) referenceTable;
    int numElements = arrayTable.getArrayElements().size();
    int widthElement = arrayTable.getElementWidth();
    int size = (widthElement * numElements) / 2; // addresses are on 16bits

    // From org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction we learn
    // that there are 6 bytes after the magic number that we have to jump.
    // 6 bytes to jump = address + 3
    //
    //    out.writeByte(0x00); // magic
    //    out.writeByte(0x03); // number
    //    out.writeShort(elementWidth); // 2 bytes
    //    out.writeInt(elementCount); // 4 bytes
    //    out.write(encodedValues);
    //

    setDataFirstByte(targetAddress + 3); // address for 16 bits elements not 8 bits
    setDataLastByte(targetAddress + 3 + size); // - 1);
    setDataSize(size);

    // TODO: how to handle this with dexlib2 ?
    //    ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
    //    arrayTable.write(out, targetAddress);
    //
    //    byte[] outa = out.getArray();
    //    byte[] data = new byte[outa.length-6];
    //    for (int i=6; i<outa.length; i++) {
    //      data[i-6] = outa[i];
    //    }
    //    setData (data);
  }
  private NumericConstant getArrayElement(Number element, DexBody body, int arrayRegister) {

    List<DexlibAbstractInstruction> instructions = body.instructionsBefore(this);
    Set<Integer> usedRegisters = new HashSet<Integer>();
    usedRegisters.add(arrayRegister);

    Type elementType = null;
    Outer:
    for (DexlibAbstractInstruction i : instructions) {
      if (usedRegisters.isEmpty()) break;

      for (int reg : usedRegisters)
        if (i instanceof NewArrayInstruction) {
          NewArrayInstruction newArrayInstruction = (NewArrayInstruction) i;
          Instruction22c instruction22c = (Instruction22c) newArrayInstruction.instruction;
          if (instruction22c.getRegisterA() == reg) {
            ArrayType arrayType =
                (ArrayType) DexType.toSoot((TypeReference) instruction22c.getReference());
            elementType = arrayType.getElementType();
            break Outer;
          }
        }

      //        // look for obsolete registers
      //        for (int reg : usedRegisters) {
      //          if (i.overridesRegister(reg)) {
      //            usedRegisters.remove(reg);
      //            break;      // there can't be more than one obsolete
      //          }
      //        }

      // look for new registers
      for (int reg : usedRegisters) {
        int newRegister = i.movesToRegister(reg);
        if (newRegister != -1) {
          usedRegisters.add(newRegister);
          usedRegisters.remove(reg);
          break; // there can't be more than one new
        }
      }
    }

    if (elementType == null) {
      // throw new InternalError("Unable to find array type to type array elements!");
      G.v()
          .out
          .println(
              "Warning: Unable to find array type to type array elements! Array was not defined! (obfuscated bytecode?)");
      return null;
    }

    NumericConstant value;

    if (elementType instanceof BooleanType) {
      value = IntConstant.v(element.intValue());
      IntConstant ic = (IntConstant) value;
      if (!(ic.value == 0 || ic.value == 1)) {
        throw new RuntimeException("ERROR: Invalid value for boolean: " + value);
      }
    } else if (elementType instanceof ByteType) {
      value = IntConstant.v(element.byteValue());
    } else if (elementType instanceof CharType || elementType instanceof ShortType) {
      value = IntConstant.v(element.shortValue());
    } else if (elementType instanceof DoubleType) {
      value = DoubleConstant.v(Double.longBitsToDouble(element.longValue()));
    } else if (elementType instanceof FloatType) {
      value = FloatConstant.v(Float.intBitsToFloat(element.intValue()));
    } else if (elementType instanceof IntType) {
      value = IntConstant.v(element.intValue());
    } else if (elementType instanceof LongType) {
      value = LongConstant.v(element.longValue());
    } else {
      throw new RuntimeException(
          "Invalid Array Type occured in FillArrayDataInstruction: " + elementType);
    }
    Debug.printDbg("array element: ", value);
    return value;
  }