class ConstantVisitor extends AbstractConstantSwitch {

  private StmtVisitor stmtV;

  private Register destinationReg;

  private Stmt origStmt;

  public ConstantVisitor(StmtVisitor stmtV) {
    this.stmtV = stmtV;
  }

  public void setDestination(Register destinationReg) {
    this.destinationReg = destinationReg;
  }

  public void setOrigStmt(Stmt stmt) {
    this.origStmt = stmt;
  }

  @Override
  public void defaultCase(Object o) {<FILL_FUNCTION_BODY>}

  @Override
  public void caseStringConstant(StringConstant s) {
    StringReference ref = new ImmutableStringReference(s.value);
    stmtV.addInsn(new Insn21c(Opcode.CONST_STRING, destinationReg, ref), origStmt);
  }

  @Override
  public void caseClassConstant(ClassConstant c) {
    TypeReference referencedClass = new ImmutableTypeReference(c.getValue());
    stmtV.addInsn(new Insn21c(Opcode.CONST_CLASS, destinationReg, referencedClass), origStmt);
  }

  @Override
  public void caseLongConstant(LongConstant l) {
    long constant = l.value;
    stmtV.addInsn(buildConstWideInsn(constant), origStmt);
  }

  private Insn buildConstWideInsn(long literal) {
    if (SootToDexUtils.fitsSigned16(literal)) {
      return new Insn21s(Opcode.CONST_WIDE_16, destinationReg, (short) literal);
    } else if (SootToDexUtils.fitsSigned32(literal)) {
      return new Insn31i(Opcode.CONST_WIDE_32, destinationReg, (int) literal);
    } else {
      return new Insn51l(Opcode.CONST_WIDE, destinationReg, literal);
    }
  }

  @Override
  public void caseDoubleConstant(DoubleConstant d) {
    long longBits = Double.doubleToLongBits(d.value);
    stmtV.addInsn(buildConstWideInsn(longBits), origStmt);
  }

  @Override
  public void caseFloatConstant(FloatConstant f) {
    int intBits = Float.floatToIntBits(f.value);
    stmtV.addInsn(buildConstInsn(intBits), origStmt);
  }

  private Insn buildConstInsn(int literal) {
    if (SootToDexUtils.fitsSigned4(literal)) {
      return new Insn11n(Opcode.CONST_4, destinationReg, (byte) literal);
    } else if (SootToDexUtils.fitsSigned16(literal)) {
      return new Insn21s(Opcode.CONST_16, destinationReg, (short) literal);
    } else {
      return new Insn31i(Opcode.CONST, destinationReg, literal);
    }
  }

  @Override
  public void caseIntConstant(IntConstant i) {
    stmtV.addInsn(buildConstInsn(i.value), origStmt);
  }

  @Override
  public void caseNullConstant(NullConstant v) {
    // dex bytecode spec says: "In terms of bitwise representation, (Object)
    // null == (int) 0."
    stmtV.addInsn(buildConstInsn(0), origStmt);
  }

}

    // const* opcodes not used since there seems to be no point in doing so:
    // CONST_HIGH16, CONST_WIDE_HIGH16
    throw new Error("unknown Object (" + o.getClass() + ") as Constant: " + o);
  
<methods>public non-sealed void <init>() ,public void caseClassConstant(soot.jimple.ClassConstant) ,public void caseDoubleConstant(soot.jimple.DoubleConstant) ,public void caseFloatConstant(soot.jimple.FloatConstant) ,public void caseIntConstant(soot.jimple.IntConstant) ,public void caseLongConstant(soot.jimple.LongConstant) ,public void caseMethodHandle(soot.jimple.MethodHandle) ,public void caseMethodType(soot.jimple.MethodType) ,public void caseNullConstant(soot.jimple.NullConstant) ,public void caseStringConstant(soot.jimple.StringConstant) ,public void defaultCase(java.lang.Object) ,public java.lang.Object getResult() ,public void setResult(java.lang.Object) <variables>java.lang.Object result