sendDesc* frame::send_desc() { assert(RecompilationInProgress || is_self_frame(), "Only Self frames have sendDescs"); if (is_interpreted_self_frame()) return sendDesc::sendDesc_from_return_PC( return_addr()); // for Conversion::convert (& new_dummy_vframe) # if defined(FAST_COMPILER) || defined(SIC_COMPILER) int32* callp = (int32*)sendDesc::sendDesc_from_return_PC( return_addr())->call_instruction_addr(); if (!isCall(callp)) { callp--; // prim frames get ret pc bumped so C can return } if (!isCall(callp)) { // nlr code callp -= 2; // 2 instructions if (!isCall(callp)) { // usually an error, but some callers tolerate it so don't break here return NULL; } } else if (isCall(callp - 2)) { // the "call" might be the register mask of a send/prim call return slow_send_desc(callp); } // assert(((sendDesc*)callp)->verify(), "doesn't verify"); // wouldn't always work (e.g. during GCs) return sendDesc::sendDesc_from_call_instruction(callp); # else ShouldNotReachHere(); // compiled frame but no compiler? return NULL; # endif }
static bool hasBarrier(const DataflowGraph::iterator &block) { for (auto instruction = block->instructions().begin(); instruction != block->instructions().end(); ++instruction) { if (typeid(ir::PTXInstruction) == typeid(*(instruction->i))) { auto ptxInstruction = static_cast<ir::PTXInstruction*>(instruction->i); if (ptxInstruction->opcode == ir::PTXInstruction::Bar) return true; // texture instruction intrinsics if (ptxInstruction->isCall()) { if (ptxInstruction->a.addressMode != ir::PTXOperand::FunctionName) { continue; } if (ptxInstruction->a.identifier.find( "_Z_intrinsic_pseudo_tex") != 0) { continue; } return true; } } } return false; }
static BlockSet getBlocksWithCallsToFuctionsThatObserveSideEffects( ir::IRKernel& k) { BlockSet blocks; report(" Getting functions that can observe side-effects"); for(auto block = k.cfg()->begin(); block != k.cfg()->end(); ++block) { for(auto instruction : block->instructions) { auto ptxInstruction = static_cast<ir::PTXInstruction*>(instruction); // TODO: Check that the target can observe side effects if(ptxInstruction->isCall()) { report(" " << ptxInstruction->toString()); blocks.insert(block); break; } } } return blocks; }
void InterruptedContext::set_continuation_address(char *addr, bool mustWork, bool setSema) { InterruptedContext::the_interrupted_context->must_be_in_self_thread(); assert(!continuePC, "continuePC already set"); if (setSema) processSemaphore = true; if (the_interrupted_context->next_pc() == the_interrupted_context->pc() + 4) { // normal case continuePC = the_interrupted_context->pc(); the_interrupted_context->set_pc(addr); the_interrupted_context->set_next_pc(addr + 4); } else { // Instruction at pc is in delay slot; next instr. is non-sequential // Execute delay slot instruction before jumping to continuation int32* instp = (int32*)the_interrupted_context->pc(); if (isCall(instp) || isJump(instp)) { // back-to-back CTI - shouldn't happen for Self code warning("setContinuationAddress: can't handle back-to-back CTI;\n"); warning4("pc=%#lx (%lx), npc=%#lx (%lx)", the_interrupted_context->pc(), *(int*)the_interrupted_context->pc(), the_interrupted_context->next_pc(), *(int*)the_interrupted_context->next_pc()); if (mustWork) fatal("couldn't set continuation address"); } else { continuePC = the_interrupted_context->next_pc(); the_interrupted_context->set_next_pc(addr); } } }
char* frame::c_entry_point() { frame* s = sender(); if ( s == NULL ) return NULL; char* r = s->real_return_addr(); // where sender will return into if (Memory->code->contains(r)) return NULL; int32* callp = (int32*) r; if (callp == NULL || !isCall(callp)) return NULL; return (char*)getCallImm(callp); }
/// Replace pseudo store instructions that pass arguments through the stack with /// real instructions. If insertPushes is true then all instructions are /// replaced with push instructions, otherwise regular std instructions are /// inserted. static void fixStackStores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const TargetInstrInfo &TII, bool insertPushes) { const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>(); const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); // Iterate through the BB until we hit a call instruction or we reach the end. for (auto I = MI, E = MBB.end(); I != E && !I->isCall();) { MachineBasicBlock::iterator NextMI = std::next(I); MachineInstr &MI = *I; unsigned Opcode = I->getOpcode(); // Only care of pseudo store instructions where SP is the base pointer. if (Opcode != AVR::STDSPQRr && Opcode != AVR::STDWSPQRr) { I = NextMI; continue; } assert(MI.getOperand(0).getReg() == AVR::SP && "Invalid register, should be SP!"); if (insertPushes) { // Replace this instruction with a push. unsigned SrcReg = MI.getOperand(2).getReg(); bool SrcIsKill = MI.getOperand(2).isKill(); // We can't use PUSHWRr here because when expanded the order of the new // instructions are reversed from what we need. Perform the expansion now. if (Opcode == AVR::STDWSPQRr) { BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr)) .addReg(TRI.getSubReg(SrcReg, AVR::sub_hi), getKillRegState(SrcIsKill)); BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr)) .addReg(TRI.getSubReg(SrcReg, AVR::sub_lo), getKillRegState(SrcIsKill)); } else { BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr)) .addReg(SrcReg, getKillRegState(SrcIsKill)); } MI.eraseFromParent(); I = NextMI; continue; } // Replace this instruction with a regular store. Use Y as the base // pointer since it is guaranteed to contain a copy of SP. unsigned STOpc = (Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr; MI.setDesc(TII.get(STOpc)); MI.getOperand(0).setReg(AVR::R29R28); I = NextMI; } }
void Token::print() const { if( eol() ) std::cout << "NEWLINE" ; else if( eof() ) std::cout << "ENDMARKER" ; else if( indent() ) std::cout << "INDENT"; else if( dedent() ) std::cout << "DEDENT"; else if( isOpenBrace() ) std::cout << " { "; else if( isCloseBrace() ) std::cout << " } "; else if( isComma() ) std::cout << " , "; else if( isPeriod()) std::cout<< "."; else if( isEqual() ) std::cout << " == "; else if( isNotEqual() ) std::cout << " != "; else if( isLessThan() ) std::cout << " < "; else if( isGreaterThan() ) std::cout << " > "; else if( isLessThanEqual() ) std::cout << " <= "; else if( isGreaterThanEqual() ) std::cout << " >= "; else if( isOpenParen() ) std::cout << " ( " ; else if( isCloseParen() ) std::cout << " ) " ; else if( isAssignmentOperator() ) std::cout << " = "; else if( isColon() ) std::cout << " : " ; else if( isMultiplicationOperator() ) std::cout << " * " ; else if( isAdditionOperator() ) std::cout << " + "; else if( isSubtractionOperator() ) std::cout << " - "; else if( isModuloOperator() ) std::cout << " % "; else if( isDivisionOperator() ) std::cout << " / "; else if( isFloorDivision() ) std::cout << " // "; else if( isOpenBrack() ) std::cout<< "["; else if( isCloseBrack() ) std::cout<< "]"; else if( isName() ) std::cout << getName(); else if( isKeyword() ) std::cout << getKeyword(); else if( isWholeNumber() ) std::cout << getWholeNumber(); else if( isFloat() ) std::cout << getFloat(); else if( isString() ) std::cout << getString(); else if( isCall() ) std::cout << "CALL " << getName(); else if( isSub() ) std::cout << "ARRAY SUB " << getName(); else if( isAppend() ) std::cout << "ARRAY APPEND " << getName(); else if( isPop() ) std::cout << "ARRAY POP " << getName(); else std::cout << "Uninitialized token.\n"; }
// Statements bool isSimpleStatement() const { return isPrintKeyword() || isName() || isArrayOp() || isCall() || isReturnKeyword(); }
bool isName() const { return _name.length() > 0 && !isArrayOp() && !isCall(); }
const ValueArray& Value::callParameters() const { assert(isCall()); return impl_->valueArray; }
const Value& Value::callValue() const { assert(isCall()); return impl_->value0; }
// 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) {
bool isMsgRegister(bfd_byte *p, uint32_t **rcv, uint8_t *rcvCount, uint32_t **snd, uint8_t *sndCount, uint32_t **callPtr) { bfd_byte *oldp= p; uint32_t p1, p2, p3, p4, dest; if (isPush(&p, p1) && isPush(&p, p2) && isPush(&p, p3) && isPush(&p, p4) && isXor(&p) && isCall(&p, dest)) { *callPtr = (uint32_t *)dest; if ( (p1 < 0x1000 || p1 == 0 ) && (p2 > 0x1000 || p2 == 0 ) && (p3 < 0x1000 || p3 == 0 ) && (p4 > 0x1000 || p4 == 0) ) { *rcvCount= (uint8_t)p1; *rcv = (uint32_t *)p2; *sndCount= (uint8_t)p3; *snd = (uint32_t *)p4; } else if ( (p1 > 0x1000 || p1 == 0) && (p2 < 0x1000 || p2 == 0) && (p3 > 0x1000 || p3 == 0) && (p4 < 0x1000 || p4 == 0)) { *rcv = (uint32_t *)p1; *rcvCount= (uint8_t)p2; *snd = (uint32_t *)p3; *sndCount= (uint8_t)p4; } else return false; return true; } p = oldp; if (isPush(&p, p1) && isPush(&p, p2) && isPush(&p, p3) && isXorEDX(&p) && isPush(&p, p4) && isLeaECX(&p) && isCall(&p, dest)) { *callPtr = (uint32_t *)dest; if ( (p1 < 0x1000 || p1 == 0 ) && (p2 > 0x1000 || p2 == 0 ) && (p3 < 0x1000 || p3 == 0 ) && (p4 > 0x1000 || p4 == 0) ) { *rcvCount= (uint8_t)p1; *rcv = (uint32_t *)p2; *sndCount= (uint8_t)p3; *snd = (uint32_t *)p4; } else if ( (p1 > 0x1000 || p1 == 0) && (p2 < 0x1000 || p2 == 0) && (p3 > 0x1000 || p3 == 0) && (p4 < 0x1000 || p4 == 0)) { *rcv = (uint32_t *)p1; *rcvCount= (uint8_t)p2; *snd = (uint32_t *)p3; *sndCount= (uint8_t)p4; } else return false; return true; } return false; }
/** * * @brief test whether the given call transition is in this collection of * transitions * * @param - from: the state the edge departs from * @param - sym: the symbol labeling the edge * @param - to: the state the edge arrives to * @return true if the given call transition is in this collection of * transitions * */ bool TransitionStorage::isCall( State from, Symbol sym, State to ) const { Call ct(from,sym,to); return isCall(ct); }