// mips_build_intervals: build intervals for the range [beg_insn,
// end_insn).  Returns the first interval if retFirst is true,
// otherwise returns the last.
static UNW_INTERVAL_t
mips_build_intervals(uint32_t* beg_insn, uint32_t* end_insn, 
		     bool retFirst, int verbose)
{
  UNW_INTERVAL_t beg_ui = NEW_UI(INSN(beg_insn), FrmTy_SP, FrmFlg_RAReg,
				 0, unwarg_NULL, MIPS_REG_RA, NULL);
  UNW_INTERVAL_t ui = beg_ui;
  UNW_INTERVAL_t nxt_ui = UNW_INTERVAL_NULL;

  // canonical intervals
  UNW_INTERVAL_t canon_ui   = beg_ui;
  UNW_INTERVAL_t canonSP_ui = beg_ui;
  UNW_INTERVAL_t canonFP_ui = UNW_INTERVAL_NULL; // currently not needed

  int fp_saved_reg = 0;

  uint32_t* cur_insn = beg_insn;
  while (cur_insn < end_insn) {
    //TMSG(INTV, "insn: 0x%x [%p,%p)", *cur_insn, cur_insn, end_insn);

    //--------------------------------------------------
    // 1. SP-frames
    // 
    // SP-frame --> SP-frame: alloc/dealloc constant-sized frame
    // FP-frame --> FP-frame: additional storage [UNCOMMON]
    //--------------------------------------------------
    if (isAdjustSPByConst(*cur_insn)) {
      int sp_arg, ra_arg;
      
      if (UI_FLD(ui,ty) == FrmTy_SP) {
	//checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);
	int amnt = getAdjustSPByConstAmnt(*cur_insn);
	
	sp_arg = UI_FLD(ui,sp_arg) + amnt;
	checkSPOfst(&sp_arg, UI_FLD(ui,sp_arg));
	
	ra_arg = UI_FLD(ui,ra_arg);
	if (!frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)) {
	  ra_arg += amnt;
	  checkSPOfst(&ra_arg, UI_FLD(ui,ra_arg));
	}
      }
      else {
	sp_arg = UI_FLD(ui,sp_arg);
	ra_arg = UI_FLD(ui,ra_arg);
      }

      nxt_ui = NEW_UI(nextInsn(cur_insn), UI_FLD(ui,ty), UI_FLD(ui,flgs), 
		      sp_arg, UI_FLD(ui,fp_arg), ra_arg, ui);
      ui = nxt_ui;
    }

    //--------------------------------------------------
    // SP-frame --> SP-frame: store RA/FP
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isStoreRegInFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_RA)) {
      checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);

      // store return address
      int ra_arg = getStoreRegInFrameOffset(*cur_insn);
      int16_t flgs = UI_FLD(ui,flgs);
      frameflg_unset(&flgs, FrmFlg_RAReg);

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, flgs,
		      UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg), ra_arg, ui);
      ui = nxt_ui;

      canon_ui = canonSP_ui = nxt_ui;
    }
    else if (isStoreRegInFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_FP)) {
      checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);

      // store frame pointer (N.B. fp may be used as saved reg s8)
      int fp_arg = getStoreRegInFrameOffset(*cur_insn);
      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, UI_FLD(ui,flgs),
		      UI_FLD(ui,sp_arg), fp_arg, UI_FLD(ui,ra_arg), ui);
      ui = nxt_ui;

      canon_ui = canonSP_ui = nxt_ui;
    }

    //--------------------------------------------------
    // SP-frame --> SP-frame: load RA by SP
    //--------------------------------------------------
    else if (isLoadRegFromFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_RA)) {
      checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);

      // sanity check: sp_arg must be positive!
      // TODO: apply this check to other SP-relative ops.  Fix prior intervals
      int sp_arg = UI_FLD(ui,sp_arg);
      if ( !(sp_arg > 0) ) {
	sp_arg = UI_FLD(canonSP_ui,sp_arg);
      }

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, FrmFlg_RAReg,
		      sp_arg, UI_FLD(ui,fp_arg), MIPS_REG_RA, ui);
      ui = nxt_ui;
    }


    //--------------------------------------------------
    // 2. General: interior epilogues before returns
    //--------------------------------------------------
    else if (isJumpToReg(*cur_insn, MIPS_REG_RA)
	     && ((cur_insn + 1/*delay slot*/ + 1) < end_insn)) {
      // An interior return.  Restore the canonical interval if necessary.
      // 
      // N.B.: Although the delay slot instruction may affect the
      // frame, because of the return, we will never see its effect
      // within this procedure.  Therefore, it is harmless to skip
      // processing of this delay slot.
      if (!ui_cmp(UI_ARG(ui), UI_ARG(canon_ui))) {
	nxt_ui = NEW_UI(nextInsn(cur_insn + 1/*delay slot*/),
			UI_FLD(canon_ui,ty), UI_FLD(canon_ui,flgs), 
			UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg),
			UI_FLD(canon_ui,ra_arg), ui);
	ui = nxt_ui;
	cur_insn++; // skip delay slot and align new interval
      }
    }

    //--------------------------------------------------
    // General: interior epilogues before callsites
    //--------------------------------------------------
    else if (isCall(*cur_insn)
	     && frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)) {
      // The callsite (jalr) is clobbering r31, but RA is in r31.  We
      // assume this is an inconsistency arising from control flow
      // jumping around an interior epilogue before the callsite.
      // Restore the canonical interval.
      if (!ui_cmp(UI_ARG(ui), UI_ARG(canon_ui))) {
	nxt_ui = NEW_UI(nextInsn(cur_insn),
			UI_FLD(canon_ui,ty), UI_FLD(canon_ui,flgs), 
			UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg),
			UI_FLD(canon_ui,ra_arg), ui);
	ui = nxt_ui;
      }
    }


    //--------------------------------------------------
    // 3. Basic support for FP frames.
    // 
    // *-frame --> FP-frame: store RA by FP
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isStoreRegInFrame(*cur_insn, MIPS_REG_FP, MIPS_REG_RA)) {
      int sp_arg, fp_arg;
      if (UI_FLD(ui,ty) == FrmTy_SP) {
	sp_arg = unwarg_NULL;
	fp_arg = convertSPToFPOfst(UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg));
      }
      else {
	sp_arg = UI_FLD(ui,sp_arg);
	fp_arg = UI_FLD(ui,fp_arg);
      }
      int ra_arg = getStoreRegInFrameOffset(*cur_insn);

      int16_t flgs = UI_FLD(ui,flgs);
      frameflg_unset(&flgs, FrmFlg_RAReg);

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, flgs,
		      sp_arg, fp_arg, ra_arg, ui);
      ui = nxt_ui;
      
      canon_ui = canonFP_ui = nxt_ui;
    }

    //--------------------------------------------------
    // *-frame --> FP-frame: store parent FP (saved in reg) by FP
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isMoveReg(*cur_insn, MIPS_REG_V0, MIPS_REG_FP)) {
      frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPInV);
      fp_saved_reg = MIPS_REG_V0;
    }
    else if (isMoveReg(*cur_insn, MIPS_REG_V1, MIPS_REG_FP)) {
      frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPInV);
      fp_saved_reg = MIPS_REG_V1;
    }
    else if (frameflg_isset(UI_FLD(ui,flgs), FrmFlg_FPInV) &&
	     isStoreRegInFrame(*cur_insn, MIPS_REG_FP, fp_saved_reg)) {
      int sp_arg, ra_arg;
      if (UI_FLD(ui,ty) == FrmTy_SP) {
	sp_arg = unwarg_NULL;
	ra_arg = convertSPToFPOfst(UI_FLD(ui,sp_arg), UI_FLD(ui,ra_arg));
      }
      else {
	sp_arg = UI_FLD(ui,sp_arg);
	ra_arg = UI_FLD(ui,ra_arg);
      }
      int fp_arg = getStoreRegInFrameOffset(*cur_insn);

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, UI_FLD(ui,flgs),
		      sp_arg, fp_arg, ra_arg, ui);
      ui = nxt_ui;
      
      canon_ui = canonFP_ui = nxt_ui;
    }
    /* else if (store-parent's-SP): useless */

    //--------------------------------------------------
    // *-frame --> FP-frame: allocate variable-sized frame
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isMoveReg(*cur_insn, MIPS_REG_FP, MIPS_REG_SP)) {
      // FP is set to SP, likely meaning it will point to the middle
      // of the frame (pos. offsets) rather than the top (neg. offsets)
      // ??? test that the canonical FP frame has not been set ???
      frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPOfstPos);
    }
    else if (isAdjustSPByVar(*cur_insn)) {
      // TODO: ensure "daddu sp,sp,v0" is allocation rather than deallocation

      // if canonical interval has been set and it is an SP-frame...
      if (!UI_CMP_OPT(canon_ui, beg_ui) && UI_FLD(canon_ui,ty) == FrmTy_SP) {
	int16_t flgs = UI_FLD(ui,flgs);
	int sp_arg, fp_arg, ra_arg;

	if (frameflg_isset(flgs, FrmFlg_FPOfstPos)) {
	  sp_arg = UI_FLD(canon_ui,sp_arg);
	  fp_arg = UI_FLD(canon_ui,fp_arg);
	  ra_arg = UI_FLD(canon_ui,ra_arg);
	}
	else {
	  sp_arg = unwarg_NULL;
	  fp_arg = convertSPToFPOfst(UI_FLD(canon_ui,sp_arg), 
				     UI_FLD(canon_ui,fp_arg));
	  ra_arg = convertSPToFPOfst(UI_FLD(canon_ui,sp_arg), 
				     UI_FLD(canon_ui,ra_arg));
	}
	  
	frameflg_set(&flgs, FrmFlg_FrmSzUnk);
	
	nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, flgs,
			sp_arg, fp_arg, ra_arg, ui);
	ui = nxt_ui;

	canon_ui = canonFP_ui = nxt_ui;
      }
    }

    //--------------------------------------------------
    // FP-frame --> FP-frame: load RA by FP
    //--------------------------------------------------
    else if (isLoadRegFromFrame(*cur_insn, MIPS_REG_FP, MIPS_REG_RA)) {
      checkUI(UI_ARG(ui), FrmTy_FP, cur_insn);
      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, FrmFlg_RAReg,
		      UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg), MIPS_REG_RA, ui);
      ui = nxt_ui;
    }
    /* else if (load-parent's-FP): not needed */
    /* else if (load-parent's-SP): useless */

    //--------------------------------------------------
    // FP-frame --> SP-frame: deallocate (all/part of) frame by restoring SP
    //--------------------------------------------------
    else if (isMoveReg(*cur_insn, MIPS_REG_SP, MIPS_REG_FP)) {
      if (UI_FLD(ui,ty) == FrmTy_FP) {
	bool isFullDealloc = 
	  (!frameflg_isset(UI_FLD(canon_ui,flgs), FrmFlg_RAReg)
	   && frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg));
	
	int flgs = (isFullDealloc) ? FrmFlg_RAReg : UI_FLD(canonSP_ui,flgs);
	int sp_arg, fp_arg, ra_arg;
	sp_arg = (isFullDealloc) ? 0           : UI_FLD(canonSP_ui,sp_arg);
	fp_arg = (isFullDealloc) ? unwarg_NULL : UI_FLD(canonSP_ui,fp_arg);
	ra_arg = (isFullDealloc) ? MIPS_REG_RA : UI_FLD(canonSP_ui,ra_arg);
	nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, flgs,
			sp_arg, fp_arg, ra_arg, ui);
	ui = nxt_ui;
      }
      else {
	// wierd code, e.g., monitor_main! Assume rest of frame will
	// be deallocated normally.  Could restore a canonical frame
	// (FIXME).
      }
    }
    
    cur_insn++;
  }

  HPC_IFNO_UNW_LITE( UI_FLD(ui,common).end = INSN(end_insn); )

#if (!HPC_UNW_LITE)
  if (verbose) {
示例#2
0
void Interpreter::executeFun(uint16_t id)
{

	_bc = ((BytecodeFunction*)_code->functionById(id))->bytecode();
    _insPtr = 0;

	Instruction inst;
    while (true) {
    	inst = nextInsn();
    	//cout << "Current instruction " << inst << endl;
    	//cout << "__STACK:" << endl;
        //printStack();
        switch (inst) {

            case BC_INVALID:
                _out << inst << " Invalid instruction" << endl;
                assert(false);
            	break;
        	case BC_DLOAD:

        		loadDouble();
        		break;
        	case BC_ILOAD:
                loadInt();
        		break;
        	case BC_SLOAD:
                loadString();
        		break;
        	case BC_DLOAD0:

        		_out << inst << " Not implemented" << endl;
        		assert(false);
        		break;
        	case BC_ILOAD0:
            	pushInt(0);
        		break;
        	case BC_SLOAD0:

        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_DLOAD1:

        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_ILOAD1:
                pushInt(1);
            	break;
        	case BC_DLOADM1:

        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_ILOADM1:
        		pushInt(-1);
        		break;
        	case BC_DADD:
        		addDoubles();
        		break;
        	case BC_IADD:
                addInts();
            	break;
        	case BC_DSUB:

        		subDoubles();
        		break;
        	case BC_ISUB:
                subInts();
        		break;
        	case BC_DMUL:
                dMul();
        		break;
        	case BC_IMUL:
                iMul();
        		break;
        	case BC_DDIV:
        		divDoubles();
        		break;
        	case BC_IDIV:
        		divInts();
        		break;
        	case BC_IMOD:

        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_DNEG:
        		dNeg();
        		break;
        	case BC_INEG:
        		iNeg();
        		break;
        	case BC_IPRINT:
        		printInt();
        		break;
        	case BC_DPRINT:
                printDouble();
        		break;
        	case BC_SPRINT:
        		printString();
        		break;
        	case BC_I2D:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_D2I:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_S2I:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_SWAP:
                swap();
        		break;
        	case BC_POP:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADDVAR0:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADDVAR1:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADDVAR2:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADDVAR3:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADIVAR0:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADIVAR1:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADIVAR2:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADIVAR3:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADSVAR0:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADSVAR1:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADSVAR2:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADSVAR3:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREDVAR0:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREDVAR1:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREDVAR2:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREDVAR3:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREIVAR0:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREIVAR1:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREIVAR2:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREIVAR3:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STORESVAR0:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STORESVAR1:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STORESVAR2:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STORESVAR3:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADDVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADIVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADSVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREDVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOREIVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STORESVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_LOADCTXDVAR:
                loadCtxDouble();
        		break;
        	case BC_LOADCTXIVAR:
                loadCtxInt();
        		break;
        	case BC_LOADCTXSVAR:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STORECTXDVAR:
        		storeCtxDouble();
            	break;
        	case BC_STORECTXIVAR:
                storeCtxInt();
        		break;
        	case BC_STORECTXSVAR:
        		_out << inst << " STORE STRING ? Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_DCMP:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_ICMP:
                compareInts();
        		break;
        	case BC_JA:
                jumpAlways();
        		break;
        	case BC_IFICMPNE:
        		intsNotEqualJMP();
        		break;
        	case BC_IFICMPE:
                intsEqualJMP();
        		break;
        	case BC_IFICMPG:
        		GJump();
        		break;
        	case BC_IFICMPGE:
        		GEJump();
        		break;
        	case BC_IFICMPL:
        		//cout << "IFLESS" << endl;
                assert(false);
        		break;
        	case BC_IFICMPLE:
        	    LEJump();
        	    break;
        	case BC_DUMP:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_STOP:
        		this->popContext();
        		return;
        	case BC_CALL:
        		//cout << "CALLING. STACK SIZE: " << _stack.size() << endl;
        		call();
        		break;
        	case BC_CALLNATIVE:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	case BC_RETURN:
        		doReturn();
        		break;
        	case BC_BREAK:
        		_out << inst << " Not implemented" << endl;
                exit(EXIT_FAILURE);
            	break;
        	default:
                _out << "Bad instruction" << endl;
         		break;
        }




    }

    this->popContext();
}