public void loadOrStoreVariable(BytecodeVariable variable, boolean useReferenceDirectly) {
    CompileStack compileStack = controller.getCompileStack();

    if (compileStack.isLHS()) {
      storeVar(variable);
    } else {
      MethodVisitor mv = controller.getMethodVisitor();
      int idx = variable.getIndex();
      ClassNode type = variable.getType();

      if (variable.isHolder()) {
        mv.visitVarInsn(ALOAD, idx);
        if (!useReferenceDirectly) {
          mv.visitMethodInsn(
              INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;", false);
          BytecodeHelper.doCast(mv, type);
          push(type);
        } else {
          push(ClassHelper.REFERENCE_TYPE);
        }
      } else {
        load(type, idx);
      }
    }
  }
  private void doConvertAndCast(ClassNode targetType, boolean coerce) {
    int size = stack.size();
    throwExceptionForNoStackElement(size, targetType, coerce);

    ClassNode top = stack.get(size - 1);
    targetType = targetType.redirect();
    if (targetType == top) return;

    if (coerce) {
      controller.getInvocationWriter().coerce(top, targetType);
      return;
    }

    boolean primTarget = ClassHelper.isPrimitiveType(targetType);
    boolean primTop = ClassHelper.isPrimitiveType(top);

    if (primTop && primTarget) {
      // here we box and unbox to get the goal type
      if (convertPrimitive(top, targetType)) {
        replace(targetType);
        return;
      }
      box();
    } else if (primTop) {
      // top is primitive, target is not
      // so box and do groovy cast
      controller.getInvocationWriter().castToNonPrimitiveIfNecessary(top, targetType);
    } else if (primTarget) {
      // top is not primitive so unbox
      // leave that BH#doCast later
    } else {
      controller.getInvocationWriter().castToNonPrimitiveIfNecessary(top, targetType);
    }

    MethodVisitor mv = controller.getMethodVisitor();
    if (primTarget
        && !ClassHelper.boolean_TYPE.equals(targetType)
        && !primTop
        && ClassHelper.getWrapper(targetType).equals(top)) {
      BytecodeHelper.doCastToPrimitive(mv, top, targetType);
    } else {
      top = stack.get(size - 1);
      if (!WideningCategories.implementsInterfaceOrSubclassOf(top, targetType)) {
        BytecodeHelper.doCast(mv, targetType);
      }
    }
    replace(targetType);
  }