Exemple #1
0
    Object* const_missing(STATE, Symbol* sym) {
      Module* under;

      CallFrame* call_frame = state->vm()->get_ruby_frame();

      LexicalScope* scope = call_frame->lexical_scope();
      if(scope->nil_p()) {
        under = G(object);
      } else {
        under = scope->module();
      }

      Array* args = Array::create(state, 1);
      args->set(state, 0, sym);
      return under->send(state, G(sym_const_missing), args);
    }
/// getMachineBasicBlocks - Populate given set using machine basic blocks which
/// have machine instructions that belong to lexical scope identified by
/// DebugLoc.
void LexicalScopes::getMachineBasicBlocks(
    const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
  MBBs.clear();
  LexicalScope *Scope = getOrCreateLexicalScope(DL);
  if (!Scope)
    return;

  if (Scope == CurrentFnLexicalScope) {
    for (const auto &MBB : *MF)
      MBBs.insert(&MBB);
    return;
  }

  SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
  for (auto &R : InsnRanges)
    MBBs.insert(R.first->getParent());
}
/// dominates - Return true if DebugLoc's lexical scope dominates at least one
/// machine instruction's lexical scope in a given machine basic block.
bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) {
  LexicalScope *Scope = getOrCreateLexicalScope(DL);
  if (!Scope)
    return false;

  // Current function scope covers all basic blocks in the function.
  if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
    return true;

  bool Result = false;
  for (auto &I : *MBB) {
    if (const DILocation *IDL = I.getDebugLoc())
      if (LexicalScope *IScope = getOrCreateLexicalScope(IDL))
        if (Scope->dominates(IScope))
          return true;
  }
  return Result;
}
/// dominates - Return true if DebugLoc's lexical scope dominates at least one
/// machine instruction's lexical scope in a given machine basic block.
bool LexicalScopes::dominates(const MDLocation *DL, MachineBasicBlock *MBB) {
  LexicalScope *Scope = getOrCreateLexicalScope(DL);
  if (!Scope)
    return false;

  // Current function scope covers all basic blocks in the function.
  if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
    return true;

  bool Result = false;
  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
       ++I) {
    if (const MDLocation *IDL = I->getDebugLoc())
      if (LexicalScope *IScope = getOrCreateLexicalScope(IDL))
        if (Scope->dominates(IScope))
          return true;
  }
  return Result;
}
// Each LexicalScope has first instruction and last instruction to mark
// beginning and end of a scope respectively. Create an inverse map that list
// scopes starts (and ends) with an instruction. One instruction may start (or
// end) multiple scopes. Ignore scopes that are not reachable.
void DebugHandlerBase::identifyScopeMarkers() {
  SmallVector<LexicalScope *, 4> WorkList;
  WorkList.push_back(LScopes.getCurrentFunctionScope());
  while (!WorkList.empty()) {
    LexicalScope *S = WorkList.pop_back_val();

    const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
    if (!Children.empty())
      WorkList.append(Children.begin(), Children.end());

    if (S->isAbstractScope())
      continue;

    for (const InsnRange &R : S->getRanges()) {
      assert(R.first && "InsnRange does not have first instruction!");
      assert(R.second && "InsnRange does not have second instruction!");
      requestLabelBeforeInsn(R.first);
      requestLabelAfterInsn(R.second);
    }
  }
}
/// getMachineBasicBlocks - Populate given set using machine basic blocks which
/// have machine instructions that belong to lexical scope identified by
/// DebugLoc.
void LexicalScopes::getMachineBasicBlocks(
    const MDLocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
  MBBs.clear();
  LexicalScope *Scope = getOrCreateLexicalScope(DL);
  if (!Scope)
    return;

  if (Scope == CurrentFnLexicalScope) {
    for (const auto &MBB : *MF)
      MBBs.insert(&MBB);
    return;
  }

  SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
  for (SmallVectorImpl<InsnRange>::iterator I = InsnRanges.begin(),
                                            E = InsnRanges.end();
       I != E; ++I) {
    InsnRange &R = *I;
    MBBs.insert(R.first->getParent());
  }
}
Exemple #7
0
/// constructScopeNest
void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
  assert (Scope && "Unable to calculate scop edominance graph!");
  SmallVector<LexicalScope *, 4> WorkStack;
  WorkStack.push_back(Scope);
  unsigned Counter = 0;
  while (!WorkStack.empty()) {
    LexicalScope *WS = WorkStack.back();
    const SmallVector<LexicalScope *, 4> &Children = WS->getChildren();
    bool visitedChildren = false;
    for (SmallVector<LexicalScope *, 4>::const_iterator SI = Children.begin(),
           SE = Children.end(); SI != SE; ++SI) {
      LexicalScope *ChildScope = *SI;
      if (!ChildScope->getDFSOut()) {
        WorkStack.push_back(ChildScope);
        visitedChildren = true;
        ChildScope->setDFSIn(++Counter);
        break;
      }
    }
    if (!visitedChildren) {
      WorkStack.pop_back();
      WS->setDFSOut(++Counter);
    }
  }
}
Exemple #8
0
void CodeViewDebug::collectVariableInfoFromMMITable(
    DenseSet<InlinedVariable> &Processed) {
  const TargetSubtargetInfo &TSI = Asm->MF->getSubtarget();
  const TargetFrameLowering *TFI = TSI.getFrameLowering();
  const TargetRegisterInfo *TRI = TSI.getRegisterInfo();

  for (const MachineModuleInfo::VariableDbgInfo &VI :
       MMI->getVariableDbgInfo()) {
    if (!VI.Var)
      continue;
    assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
           "Expected inlined-at fields to agree");

    Processed.insert(InlinedVariable(VI.Var, VI.Loc->getInlinedAt()));
    LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);

    // If variable scope is not found then skip this variable.
    if (!Scope)
      continue;

    // Get the frame register used and the offset.
    unsigned FrameReg = 0;
    int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg);
    uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);

    // Calculate the label ranges.
    LocalVarDefRange DefRange = createDefRangeMem(CVReg, FrameOffset);
    for (const InsnRange &Range : Scope->getRanges()) {
      const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
      const MCSymbol *End = getLabelAfterInsn(Range.second);
      End = End ? End : Asm->getFunctionEnd();
      DefRange.Ranges.emplace_back(Begin, End);
    }

    LocalVariable Var;
    Var.DIVar = VI.Var;
    Var.DefRanges.emplace_back(std::move(DefRange));
    recordLocalVariable(std::move(Var), VI.Loc->getInlinedAt());
  }
}
/// constructScopeNest
void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
  assert(Scope && "Unable to calculate scope dominance graph!");
  SmallVector<LexicalScope *, 4> WorkStack;
  WorkStack.push_back(Scope);
  unsigned Counter = 0;
  while (!WorkStack.empty()) {
    LexicalScope *WS = WorkStack.back();
    const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
    bool visitedChildren = false;
    for (auto &ChildScope : Children)
      if (!ChildScope->getDFSOut()) {
        WorkStack.push_back(ChildScope);
        visitedChildren = true;
        ChildScope->setDFSIn(++Counter);
        break;
      }
    if (!visitedChildren) {
      WorkStack.pop_back();
      WS->setDFSOut(++Counter);
    }
  }
}
Exemple #10
0
/// getMachineBasicBlocks - Populate given set using machine basic blocks which
/// have machine instructions that belong to lexical scope identified by 
/// DebugLoc.
void LexicalScopes::
getMachineBasicBlocks(DebugLoc DL, 
                      SmallPtrSet<const MachineBasicBlock*, 4> &MBBs) {
  MBBs.clear();
  LexicalScope *Scope = getOrCreateLexicalScope(DL);
  if (!Scope)
    return;
  
  if (Scope == CurrentFnLexicalScope) {
    for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
         I != E; ++I)
      MBBs.insert(I);
    return;
  }

  SmallVector<InsnRange, 4> &InsnRanges = Scope->getRanges();
  for (SmallVector<InsnRange, 4>::iterator I = InsnRanges.begin(),
         E = InsnRanges.end(); I != E; ++I) {
    InsnRange &R = *I;
    MBBs.insert(R.first->getParent());
  }
}
Exemple #11
0
/// assignInstructionRanges - Find ranges of instructions covered by each
/// lexical scope.
void LexicalScopes::assignInstructionRanges(
    SmallVectorImpl<InsnRange> &MIRanges,
    DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
  LexicalScope *PrevLexicalScope = nullptr;
  for (const auto &R : MIRanges) {
    LexicalScope *S = MI2ScopeMap.lookup(R.first);
    assert(S && "Lost LexicalScope for a machine instruction!");
    if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
      PrevLexicalScope->closeInsnRange(S);
    S->openInsnRange(R.first);
    S->extendInsnRange(R.second);
    PrevLexicalScope = S;
  }

  if (PrevLexicalScope)
    PrevLexicalScope->closeInsnRange();
}
Exemple #12
0
/// assignInstructionRanges - Find ranges of instructions covered by each
/// lexical scope.
void LexicalScopes::
assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
                    DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap)
{
  
  LexicalScope *PrevLexicalScope = NULL;
  for (SmallVectorImpl<InsnRange>::const_iterator RI = MIRanges.begin(),
         RE = MIRanges.end(); RI != RE; ++RI) {
    const InsnRange &R = *RI;
    LexicalScope *S = MI2ScopeMap.lookup(R.first);
    assert (S && "Lost LexicalScope for a machine instruction!");
    if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
      PrevLexicalScope->closeInsnRange(S);
    S->openInsnRange(R.first);
    S->extendInsnRange(R.second);
    PrevLexicalScope = S;
  }

  if (PrevLexicalScope)
    PrevLexicalScope->closeInsnRange();
}
void UserValue::computeIntervals(MachineRegisterInfo &MRI,
                                 const TargetRegisterInfo &TRI,
                                 LiveIntervals &LIS, LexicalScopes &LS) {
  SmallVector<std::pair<SlotIndex, unsigned>, 16> Defs;

  // Collect all defs to be extended (Skipping undefs).
  for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I)
    if (I.value() != UndefLocNo)
      Defs.push_back(std::make_pair(I.start(), I.value()));

  // Extend all defs, and possibly add new ones along the way.
  for (unsigned i = 0; i != Defs.size(); ++i) {
    SlotIndex Idx = Defs[i].first;
    unsigned LocNo = Defs[i].second;
    const MachineOperand &Loc = locations[LocNo];

    if (!Loc.isReg()) {
      extendDef(Idx, LocNo, nullptr, nullptr, nullptr, LIS);
      continue;
    }

    // Register locations are constrained to where the register value is live.
    if (TargetRegisterInfo::isVirtualRegister(Loc.getReg())) {
      LiveInterval *LI = nullptr;
      const VNInfo *VNI = nullptr;
      if (LIS.hasInterval(Loc.getReg())) {
        LI = &LIS.getInterval(Loc.getReg());
        VNI = LI->getVNInfoAt(Idx);
      }
      SmallVector<SlotIndex, 16> Kills;
      extendDef(Idx, LocNo, LI, VNI, &Kills, LIS);
      if (LI)
        addDefsFromCopies(LI, LocNo, Kills, Defs, MRI, LIS);
      continue;
    }

    // For physregs, use the live range of the first regunit as a guide.
    unsigned Unit = *MCRegUnitIterator(Loc.getReg(), &TRI);
    LiveRange *LR = &LIS.getRegUnit(Unit);
    const VNInfo *VNI = LR->getVNInfoAt(Idx);
    // Don't track copies from physregs, it is too expensive.
    extendDef(Idx, LocNo, LR, VNI, nullptr, LIS);
  }

  // Erase all the undefs.
  for (LocMap::iterator I = locInts.begin(); I.valid();)
    if (I.value() == UndefLocNo)
      I.erase();
    else
      ++I;

  // The computed intervals may extend beyond the range of the debug
  // location's lexical scope. In this case, splitting of an interval
  // can result in an interval outside of the scope being created,
  // causing extra unnecessary DBG_VALUEs to be emitted. To prevent
  // this, trim the intervals to the lexical scope.

  LexicalScope *Scope = LS.findLexicalScope(dl);
  if (!Scope)
    return;

  SlotIndex PrevEnd;
  LocMap::iterator I = locInts.begin();

  // Iterate over the lexical scope ranges. Each time round the loop
  // we check the intervals for overlap with the end of the previous
  // range and the start of the next. The first range is handled as
  // a special case where there is no PrevEnd.
  for (const InsnRange &Range : Scope->getRanges()) {
    SlotIndex RStart = LIS.getInstructionIndex(*Range.first);
    SlotIndex REnd = LIS.getInstructionIndex(*Range.second);

    // At the start of each iteration I has been advanced so that
    // I.stop() >= PrevEnd. Check for overlap.
    if (PrevEnd && I.start() < PrevEnd) {
      SlotIndex IStop = I.stop();
      unsigned LocNo = I.value();

      // Stop overlaps previous end - trim the end of the interval to
      // the scope range.
      I.setStopUnchecked(PrevEnd);
      ++I;

      // If the interval also overlaps the start of the "next" (i.e.
      // current) range create a new interval for the remainder (which
      // may be further trimmed).
      if (RStart < IStop)
        I.insert(RStart, IStop, LocNo);
    }

    // Advance I so that I.stop() >= RStart, and check for overlap.
    I.advanceTo(RStart);
    if (!I.valid())
      return;

    if (I.start() < RStart) {
      // Interval start overlaps range - trim to the scope range.
      I.setStartUnchecked(RStart);
      // Remember that this interval was trimmed.
      trimmedDefs.insert(RStart);
    }

    // The end of a lexical scope range is the last instruction in the
    // range. To convert to an interval we need the index of the
    // instruction after it.
    REnd = REnd.getNextIndex();

    // Advance I to first interval outside current range.
    I.advanceTo(REnd);
    if (!I.valid())
      return;

    PrevEnd = REnd;
  }

  // Check for overlap with end of final range.
  if (PrevEnd && I.start() < PrevEnd)
    I.setStopUnchecked(PrevEnd);
}
Exemple #14
0
    Object* const_get(STATE, Symbol* name, ConstantMissingReason* reason, Object* filter, bool replace_autoload) {
      LexicalScope *cur;
      Object* result;

      *reason = vNonExistent;

      CallFrame* frame = state->vm()->get_ruby_frame();

      // Ok, this has to be explained or it will be considered black magic.
      // The scope chain always ends with an entry at the top that contains
      // a parent of nil, and a module of Object. This entry is put in
      // regardless of lexical scoping, it's the fallback scope (the default
      // scope). This is not case when deriving from BasicObject, which is
      // explained later.
      //
      // When looking up a constant, we don't want to consider the fallback
      // scope (ie, Object) initially because we need to lookup up
      // the superclass chain first, because falling back on the default.
      //
      // The rub comes from the fact that if a user explicitly opens up
      // Object in their code, we DO consider it. Like:
      //
      // class Idiot
      //   A = 2
      // end
      //
      // class ::Object
      //   A = 1
      //   class Stupid < Idiot
      //     def foo
      //       p A
      //     end
      //   end
      // end
      //
      // In this code, when A is looked up, Object must be considering during
      // the scope walk, NOT during the superclass walk.
      //
      // So, in this case, foo would print "1", not "2".
      //
      // As indicated above, the fallback scope isn't used when the superclass
      // chain directly rooted from BasicObject. To determine this is the
      // case, we record whether Object is seen when looking up the superclass
      // chain. If Object isn't seen, this means we are directly deriving from
      // BasicObject.

      cur = frame->lexical_scope();
      while(!cur->nil_p()) {
        // Detect the toplevel scope (the default) and get outta dodge.
        if(cur->top_level_p(state)) break;

        result = cur->module()->get_const(state, name, G(sym_private), reason, false, replace_autoload);
        if(*reason == vFound) {
          if(result != filter) return result;
          *reason = vNonExistent;
        }

        cur = cur->parent();
      }

      // Now look up the superclass chain.
      Module *fallback = G(object);

      cur = frame->lexical_scope();
      if(!cur->nil_p()) {
        bool object_seen = false;
        Module* mod = cur->module();
        while(!mod->nil_p()) {
          if(mod == G(object)) {
            object_seen = true;
          }
          if(!object_seen && mod == G(basicobject)) {
            fallback = NULL;
          }

          result = mod->get_const(state, name, G(sym_private), reason, false, replace_autoload);
          if(*reason == vFound) {
            if(result != filter) return result;
            *reason = vNonExistent;
          }

          mod = mod->superclass();
        }
      }

      // Lastly, check the fallback scope (=Object) specifically if needed
      if(fallback) {
        result = fallback->get_const(state, name, G(sym_private), reason, true, replace_autoload);
        if(*reason == vFound) {
          if(result != filter) return result;
          *reason = vNonExistent;
        }
      }

      return cNil;
    }