@Override
 public void emitUnwind(Value exception) {
   ForeignCallLinkage linkage =
       getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER);
   CallingConvention outgoingCc = linkage.getOutgoingCallingConvention();
   assert outgoingCc.getArgumentCount() == 2;
   RegisterValue exceptionParameter = (RegisterValue) outgoingCc.getArgument(0);
   emitMove(exceptionParameter, exception);
   append(new AArch64HotSpotUnwindOp(config, exceptionParameter));
 }
  @Override
  public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
    HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
    Variable result;
    LIRFrameState debugInfo = null;
    if (hotspotLinkage.needsDebugInfo()) {
      debugInfo = state;
      assert debugInfo != null || getStub() != null;
    }

    if (linkage.destroysRegisters() || hotspotLinkage.needsJavaFrameAnchor()) {
      HotSpotRegistersProvider registers = getProviders().getRegisters();
      Register thread = registers.getThreadRegister();
      Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind()));

      // We need a label for the return address.
      label = new Label();

      append(
          new AArch64HotSpotCRuntimeCallPrologueOp(
              config.threadLastJavaSpOffset(),
              config.threadLastJavaPcOffset(),
              config.threadLastJavaFpOffset(),
              thread,
              scratch,
              label));
      result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
      append(
          new AArch64HotSpotCRuntimeCallEpilogueOp(
              config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread));

      // Clear it out so it's not being reused later.
      label = null;
    } else {
      result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
    }

    return result;
  }