/*****************************************************************
 *        Failure                                                 *
 *****************************************************************/

#ifdef INDENT_CODE
{
  {
    {
#endif /* INDENT_CODE */

      /* trust_fail                       */
      BOp(trust_fail, e);
      {
	while (POP_CHOICE_POINT(B->cp_b))
	  {
	    POP_EXECUTE();
	  }
      }
#ifdef YAPOR
      {
        choiceptr cut_pt;
        cut_pt = B->cp_b;
        CUT_prune_to(cut_pt);
        B = cut_pt;
      }
#else
      B = B->cp_b;
#endif  /* YAPOR */
      goto fail;
      ENDBOp();

#ifdef YAPOR
    shared_fail:
      B = Get_LOCAL_top_cp();
      SET_BB(PROTECT_FROZEN_B(B));
      goto fail;
#endif  /* YAPOR */

      /* fail                             */
      PBOp(op_fail, e);

      if (PP) {
	UNLOCK(PP->PELock);
	PP = NULL;
      }
#ifdef COROUTINING
      CACHE_Y_AS_ENV(YREG);
      check_stack(NoStackFail, HR);
      ENDCACHE_Y_AS_ENV();
#endif

    fail:
      {
	register tr_fr_ptr pt0 = TR;
#if defined(YAPOR) || defined(THREADS)
	if (PP) {
	  UNLOCK(PP->PELock);
	  PP = NULL;
	}
#endif
	PREG = B->cp_ap;
	save_pc();
	CACHE_TR(B->cp_tr);
	PREFETCH_OP(PREG);
      failloop:
	if (pt0 == S_TR) {
	  SP = SP0;
#ifdef LOW_LEVEL_TRACER
	  if (Yap_do_low_level_trace) {
	    int go_on = true;
	    yamop *ipc = PREG;

	    while (go_on) {
	      op_numbers opnum = Yap_op_from_opcode(ipc->opc);

	      go_on = false;
	      switch (opnum) {
#ifdef TABLING
	      case _table_load_answer:
		low_level_trace(retry_table_loader, LOAD_CP(B)->cp_pred_entry, NULL);
		break;
	      case _table_try_answer:
	      case _table_retry_me:
	      case _table_trust_me:
	      case _table_retry:
	      case _table_trust:
	      case _table_completion:
#ifdef THREADS_CONSUMER_SHARING
	      case _table_answer_resolution_completion:
#endif /* THREADS_CONSUMER_SHARING */
#ifdef DETERMINISTIC_TABLING
		if (IS_DET_GEN_CP(B))
		  low_level_trace(retry_table_generator, DET_GEN_CP(B)->cp_pred_entry, NULL);
		else
#endif /* DETERMINISTIC_TABLING */
		  low_level_trace(retry_table_generator, GEN_CP(B)->cp_pred_entry, (CELL *)(GEN_CP(B) + 1));
		break;
	      case _table_answer_resolution:
		low_level_trace(retry_table_consumer, CONS_CP(B)->cp_pred_entry, NULL);
		break;
	      case _trie_trust_var:
	      case _trie_retry_var:
	      case _trie_trust_var_in_pair:
	      case _trie_retry_var_in_pair:
	      case _trie_trust_val:
	      case _trie_retry_val:
	      case _trie_trust_val_in_pair:
	      case _trie_retry_val_in_pair:
	      case _trie_trust_atom:
	      case _trie_retry_atom:
	      case _trie_trust_atom_in_pair:
	      case _trie_retry_atom_in_pair:
	      case _trie_trust_null:
	      case _trie_retry_null:
	      case _trie_trust_null_in_pair:
	      case _trie_retry_null_in_pair:
	      case _trie_trust_pair:
	      case _trie_retry_pair:
	      case _trie_trust_appl:
	      case _trie_retry_appl:
	      case _trie_trust_appl_in_pair:
	      case _trie_retry_appl_in_pair:
	      case _trie_trust_extension:
	      case _trie_retry_extension:
	      case _trie_trust_double:
	      case _trie_retry_double:
	      case _trie_trust_longint:
	      case _trie_retry_longint:
	      case _trie_trust_gterm:
	      case _trie_retry_gterm:
		low_level_trace(retry_table_loader, UndefCode, NULL);
		break;
#endif /* TABLING */
	      case _or_else:
	      case _or_last:
		low_level_trace(retry_or, (PredEntry *)ipc, &(B->cp_a1));
		break;
	      case _retry2:
	      case _retry3:
	      case _retry4:
		ipc = NEXTOP(ipc,l);
		go_on = true;
		break;
	      case _jump:
		ipc = ipc->y_u.l.l;
		go_on = true;
		break;
	      case _retry_c:
	      case _retry_userc:
		low_level_trace(retry_pred, ipc->y_u.OtapFs.p, B->cp_args);
		break;
	      case _retry_profiled:
	      case _count_retry:
		ipc = NEXTOP(ipc,p);
		go_on = true;
		break;
	      case _retry_me:
	      case _trust_me:
	      case _count_retry_me:
	      case _count_trust_me:
	      case _profiled_retry_me:
	      case _profiled_trust_me:
	      case _retry_and_mark:
	      case _profiled_retry_and_mark:
	      case _retry:
	      case _trust:
		low_level_trace(retry_pred, ipc->y_u.Otapl.p, B->cp_args);
		break;
	      case _try_logical:
	      case _retry_logical:
	      case _profiled_retry_logical:
	      case _count_retry_logical:
	      case _trust_logical:
	      case _profiled_trust_logical:
	      case _count_trust_logical:
		low_level_trace(retry_pred, ipc->y_u.OtILl.d->ClPred, B->cp_args);
		break;
	      case _Nstop:
	      case _Ystop:
		low_level_trace(retry_pred, NULL, B->cp_args);
		break;
	      default:
		break;
	      }
	    }
	  }
#endif  /* LOW_LEVEL_TRACER */
#ifdef FROZEN_STACKS
#ifdef YAPOR_SBA
	  if (pt0 < TR_FZ || pt0 > (ADDR)CurrentTrailTop+MinTrailGap)
#else
	    if (pt0 < TR_FZ)
#endif /* YAPOR_SBA */
	      {
		TR = TR_FZ;
		TRAIL_LINK(pt0);
	      } else
#endif /* FROZEN_STACKS */
	      RESTORE_TR();
	  GONext();
	}
	BEGD(d1);
	d1 = TrailTerm(pt0-1);
	pt0--;
	if (IsVarTerm(d1)) {
#if defined(YAPOR_SBA) && defined(YAPOR)
	  /* clean up the trail when we backtrack */
	  if (Unsigned((Int)(d1)-(Int)(H_FZ)) >
	      Unsigned((Int)(B_FZ)-(Int)(H_FZ))) {
	    RESET_VARIABLE(STACK_TO_SBA(d1));
	  } else
#endif
	    /* normal variable */
	    RESET_VARIABLE(d1);
	  goto failloop;
	}
	/* pointer to code space */
	/* or updatable variable */
#if defined(TERM_EXTENSIONS) || defined(FROZEN_STACKS) || defined(MULTI_ASSIGNMENT_VARIABLES)
	if (IsPairTerm(d1))
#endif /* TERM_EXTENSIONS || FROZEN_STACKS || MULTI_ASSIGNMENT_VARIABLES */
	  {
	    register CELL flags;
	    CELL *pt1 = RepPair(d1);
#ifdef LIMIT_TABLING
	    if ((ADDR) pt1 == LOCAL_TrailBase) {
	      sg_fr_ptr sg_fr = (sg_fr_ptr) TrailVal(pt0);
	      TrailTerm(pt0) = AbsPair((CELL *)(pt0 - 1));
	      SgFr_state(sg_fr)--;  /* complete_in_use --> complete : compiled_in_use --> compiled */
	      insert_into_global_sg_fr_list(sg_fr);
	      goto failloop;
	    }
#endif /* LIMIT_TABLING */
#ifdef FROZEN_STACKS  /* TRAIL */
	    /* avoid frozen segments */
	    if (
#ifdef YAPOR_SBA
		(ADDR) pt1 >= HeapTop
#else
		IN_BETWEEN(LOCAL_TrailBase, pt1, (ADDR)CurrentTrailTop+MinTrailGap)
#endif /* YAPOR_SBA */
		)
	      {
		pt0 = (tr_fr_ptr) pt1;
		goto failloop;
	      } else
#endif /* FROZEN_STACKS */
	      if (IN_BETWEEN(H0,pt1,HR)) {
		if (IsAttVar(pt1)) {
		  goto failloop;
		} else if (*pt1 == (CELL)FunctorBigInt) {
		  Yap_CleanOpaqueVariable(pt1);
		  goto failloop;
		}
	      }
#ifdef FROZEN_STACKS  /* TRAIL */
	    /* don't reset frozen variables */
	    if (pt0 < TR_FZ)
	      goto failloop;
#endif
	    flags = *pt1;
#if MULTIPLE_STACKS
	    if (FlagOn(DBClMask, flags)) {
	      DBRef dbr = DBStructFlagsToDBStruct(pt1);
	      int erase;

	      LOCK(dbr->lock);
	      DEC_DBREF_COUNT(dbr);
	      erase = (dbr->Flags & ErasedMask) && (dbr->ref_count == 0);
	      UNLOCK(dbr->lock);
	      if (erase) {
		saveregs();
		Yap_ErDBE(dbr);
		setregs();
	      }
	    } else {
	      if (flags & LogUpdMask) {
		if (flags & IndexMask) {
		  LogUpdIndex *cl = ClauseFlagsToLogUpdIndex(pt1);
		  int erase;
#if PARALLEL_YAP
		  PredEntry *ap = cl->ClPred;
#endif

		  PELOCK(8,ap);
		  DEC_CLREF_COUNT(cl);
		  erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
		  if (erase) {
		    saveregs();
		    /* at this point,
		       we are the only ones accessing the clause,
		       hence we don't need to have a lock it */
		    Yap_ErLogUpdIndex(cl);
		    setregs();
		  } else if (cl->ClFlags & DirtyMask) {
		    saveregs();
		    /* at this point,
		       we are the only ones accessing the clause,
		       hence we don't need to have a lock it */
		    Yap_CleanUpIndex(cl);
		    setregs();
		  }
		  UNLOCK(ap->PELock);
		} else {
		  LogUpdClause *cl = ClauseFlagsToLogUpdClause(pt1);
		  int erase;
#if PARALLEL_YAP
		  PredEntry *ap = cl->ClPred;
#endif
		  /* BB support */
		  if (ap) {

		    PELOCK(9,ap);
		    DEC_CLREF_COUNT(cl);
		    erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
		    if (erase) {
		      saveregs();
		      /* at this point,
			 we are the only ones accessing the clause,
			 hence we don't need to have a lock it */
		      Yap_ErLogUpdCl(cl);
		      setregs();
		    }
		    UNLOCK(ap->PELock);
		  }
		}
	      } else {
		DynamicClause *cl = ClauseFlagsToDynamicClause(pt1);
		int erase;

		LOCK(cl->ClLock);
		DEC_CLREF_COUNT(cl);
		erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
		UNLOCK(cl->ClLock);
		if (erase) {
		  saveregs();
		  /* at this point,
		     we are the only ones accessing the clause,
		     hence we don't need to have a lock it */
		  Yap_ErCl(cl);
		  setregs();
		}
	      }
	    }
#else
	    ResetFlag(InUseMask, flags);
	    *pt1 = flags;
	    if (FlagOn((ErasedMask|DirtyMask), flags)) {
	      if (FlagOn(DBClMask, flags)) {
		saveregs();
		Yap_ErDBE(DBStructFlagsToDBStruct(pt1));
		setregs();
	      } else {
		saveregs();
		if (flags & LogUpdMask) {
		  if (flags & IndexMask) {
		    if (FlagOn(ErasedMask, flags)) {
		      Yap_ErLogUpdIndex(ClauseFlagsToLogUpdIndex(pt1));
		    } else {
		      Yap_CleanUpIndex(ClauseFlagsToLogUpdIndex(pt1));
		    }
		  } else {
		    Yap_ErLogUpdCl(ClauseFlagsToLogUpdClause(pt1));
		  }
		} else {
		  Yap_ErCl(ClauseFlagsToDynamicClause(pt1));
		}
		setregs();
	      }
	    }
#endif
	    goto failloop;
	  }
#ifdef MULTI_ASSIGNMENT_VARIABLES
	else /* if (IsApplTerm(d1)) */ {
	  CELL *pt = RepAppl(d1);
	  /* AbsAppl means */
	  /* multi-assignment variable */
	  /* so the next cell is the old value */
#ifdef FROZEN_STACKS
	  --pt0;
	  pt[0] = TrailVal(pt0);
#else
	  pt[0] = TrailTerm(pt0-1);
	  pt0 -= 2;
#endif /* FROZEN_STACKS */
	  goto failloop;
	}
#endif
	ENDD(d1);
	ENDCACHE_TR();
      }

#ifdef COROUTINING
    NoStackFail:
      BEGD(d0);
#ifdef SHADOW_S
      Yap_REGS.S_ = SREG;
#endif
      saveregs();
      d0 = interrupt_fail( PASS_REGS1 );
      setregs();
#ifdef SHADOW_S
      SREG = Yap_REGS.S_;
#endif
      if (!d0) FAIL();
      JMPNext();
      ENDD(d0);

#endif /* COROUTINING */
      ENDPBOp();