|  | //===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp -------*- C++ -*--===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Common functionality for different debug information format backends. | 
|  | // LLVM currently supports DWARF and CodeView. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "DebugHandlerBase.h" | 
|  | #include "llvm/ADT/Optional.h" | 
|  | #include "llvm/ADT/Twine.h" | 
|  | #include "llvm/CodeGen/AsmPrinter.h" | 
|  | #include "llvm/CodeGen/MachineFunction.h" | 
|  | #include "llvm/CodeGen/MachineInstr.h" | 
|  | #include "llvm/CodeGen/MachineModuleInfo.h" | 
|  | #include "llvm/CodeGen/TargetSubtargetInfo.h" | 
|  | #include "llvm/IR/DebugInfo.h" | 
|  | #include "llvm/MC/MCStreamer.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "dwarfdebug" | 
|  |  | 
|  | Optional<DbgVariableLocation> | 
|  | DbgVariableLocation::extractFromMachineInstruction( | 
|  | const MachineInstr &Instruction) { | 
|  | DbgVariableLocation Location; | 
|  | if (!Instruction.isDebugValue()) | 
|  | return None; | 
|  | if (!Instruction.getOperand(0).isReg()) | 
|  | return None; | 
|  | Location.Register = Instruction.getOperand(0).getReg(); | 
|  | Location.FragmentInfo.reset(); | 
|  | // We only handle expressions generated by DIExpression::appendOffset, | 
|  | // which doesn't require a full stack machine. | 
|  | int64_t Offset = 0; | 
|  | const DIExpression *DIExpr = Instruction.getDebugExpression(); | 
|  | auto Op = DIExpr->expr_op_begin(); | 
|  | while (Op != DIExpr->expr_op_end()) { | 
|  | switch (Op->getOp()) { | 
|  | case dwarf::DW_OP_constu: { | 
|  | int Value = Op->getArg(0); | 
|  | ++Op; | 
|  | if (Op != DIExpr->expr_op_end()) { | 
|  | switch (Op->getOp()) { | 
|  | case dwarf::DW_OP_minus: | 
|  | Offset -= Value; | 
|  | break; | 
|  | case dwarf::DW_OP_plus: | 
|  | Offset += Value; | 
|  | break; | 
|  | default: | 
|  | continue; | 
|  | } | 
|  | } | 
|  | } break; | 
|  | case dwarf::DW_OP_plus_uconst: | 
|  | Offset += Op->getArg(0); | 
|  | break; | 
|  | case dwarf::DW_OP_LLVM_fragment: | 
|  | Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)}; | 
|  | break; | 
|  | case dwarf::DW_OP_deref: | 
|  | Location.LoadChain.push_back(Offset); | 
|  | Offset = 0; | 
|  | break; | 
|  | default: | 
|  | return None; | 
|  | } | 
|  | ++Op; | 
|  | } | 
|  |  | 
|  | // Do one final implicit DW_OP_deref if this was an indirect DBG_VALUE | 
|  | // instruction. | 
|  | // FIXME: Replace these with DIExpression. | 
|  | if (Instruction.isIndirectDebugValue()) | 
|  | Location.LoadChain.push_back(Offset); | 
|  |  | 
|  | return Location; | 
|  | } | 
|  |  | 
|  | DebugHandlerBase::DebugHandlerBase(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {} | 
|  |  | 
|  | // 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); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Return Label preceding the instruction. | 
|  | MCSymbol *DebugHandlerBase::getLabelBeforeInsn(const MachineInstr *MI) { | 
|  | MCSymbol *Label = LabelsBeforeInsn.lookup(MI); | 
|  | assert(Label && "Didn't insert label before instruction"); | 
|  | return Label; | 
|  | } | 
|  |  | 
|  | // Return Label immediately following the instruction. | 
|  | MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) { | 
|  | return LabelsAfterInsn.lookup(MI); | 
|  | } | 
|  |  | 
|  | /// If this type is derived from a base type then return base type size. | 
|  | uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) { | 
|  | DIType *Ty = TyRef.resolve(); | 
|  | assert(Ty); | 
|  | DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty); | 
|  | if (!DDTy) | 
|  | return Ty->getSizeInBits(); | 
|  |  | 
|  | unsigned Tag = DDTy->getTag(); | 
|  |  | 
|  | if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && | 
|  | Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && | 
|  | Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type) | 
|  | return DDTy->getSizeInBits(); | 
|  |  | 
|  | DIType *BaseType = DDTy->getBaseType().resolve(); | 
|  |  | 
|  | if (!BaseType) | 
|  | return 0; | 
|  |  | 
|  | // If this is a derived type, go ahead and get the base type, unless it's a | 
|  | // reference then it's just the size of the field. Pointer types have no need | 
|  | // of this since they're a different type of qualification on the type. | 
|  | if (BaseType->getTag() == dwarf::DW_TAG_reference_type || | 
|  | BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type) | 
|  | return Ty->getSizeInBits(); | 
|  |  | 
|  | return getBaseTypeSize(BaseType); | 
|  | } | 
|  |  | 
|  | static bool hasDebugInfo(const MachineModuleInfo *MMI, | 
|  | const MachineFunction *MF) { | 
|  | if (!MMI->hasDebugInfo()) | 
|  | return false; | 
|  | auto *SP = MF->getFunction().getSubprogram(); | 
|  | if (!SP) | 
|  | return false; | 
|  | assert(SP->getUnit()); | 
|  | auto EK = SP->getUnit()->getEmissionKind(); | 
|  | if (EK == DICompileUnit::NoDebug) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void DebugHandlerBase::beginFunction(const MachineFunction *MF) { | 
|  | PrevInstBB = nullptr; | 
|  |  | 
|  | if (!Asm || !hasDebugInfo(MMI, MF)) { | 
|  | skippedNonDebugFunction(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Grab the lexical scopes for the function, if we don't have any of those | 
|  | // then we're not going to be able to do anything. | 
|  | LScopes.initialize(*MF); | 
|  | if (LScopes.empty()) { | 
|  | beginFunctionImpl(MF); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Make sure that each lexical scope will have a begin/end label. | 
|  | identifyScopeMarkers(); | 
|  |  | 
|  | // Calculate history for local variables. | 
|  | assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); | 
|  | calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), | 
|  | DbgValues); | 
|  | LLVM_DEBUG(DbgValues.dump()); | 
|  |  | 
|  | // Request labels for the full history. | 
|  | for (const auto &I : DbgValues) { | 
|  | const auto &Ranges = I.second; | 
|  | if (Ranges.empty()) | 
|  | continue; | 
|  |  | 
|  | // The first mention of a function argument gets the CurrentFnBegin | 
|  | // label, so arguments are visible when breaking at function entry. | 
|  | const DILocalVariable *DIVar = Ranges.front().first->getDebugVariable(); | 
|  | if (DIVar->isParameter() && | 
|  | getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())) { | 
|  | LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin(); | 
|  | if (Ranges.front().first->getDebugExpression()->isFragment()) { | 
|  | // Mark all non-overlapping initial fragments. | 
|  | for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { | 
|  | const DIExpression *Fragment = I->first->getDebugExpression(); | 
|  | if (std::all_of(Ranges.begin(), I, | 
|  | [&](DbgValueHistoryMap::InstrRange Pred) { | 
|  | return !Fragment->fragmentsOverlap( | 
|  | Pred.first->getDebugExpression()); | 
|  | })) | 
|  | LabelsBeforeInsn[I->first] = Asm->getFunctionBegin(); | 
|  | else | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | for (const auto &Range : Ranges) { | 
|  | requestLabelBeforeInsn(Range.first); | 
|  | if (Range.second) | 
|  | requestLabelAfterInsn(Range.second); | 
|  | } | 
|  | } | 
|  |  | 
|  | PrevInstLoc = DebugLoc(); | 
|  | PrevLabel = Asm->getFunctionBegin(); | 
|  | beginFunctionImpl(MF); | 
|  | } | 
|  |  | 
|  | void DebugHandlerBase::beginInstruction(const MachineInstr *MI) { | 
|  | if (!MMI->hasDebugInfo()) | 
|  | return; | 
|  |  | 
|  | assert(CurMI == nullptr); | 
|  | CurMI = MI; | 
|  |  | 
|  | // Insert labels where requested. | 
|  | DenseMap<const MachineInstr *, MCSymbol *>::iterator I = | 
|  | LabelsBeforeInsn.find(MI); | 
|  |  | 
|  | // No label needed. | 
|  | if (I == LabelsBeforeInsn.end()) | 
|  | return; | 
|  |  | 
|  | // Label already assigned. | 
|  | if (I->second) | 
|  | return; | 
|  |  | 
|  | if (!PrevLabel) { | 
|  | PrevLabel = MMI->getContext().createTempSymbol(); | 
|  | Asm->OutStreamer->EmitLabel(PrevLabel); | 
|  | } | 
|  | I->second = PrevLabel; | 
|  | } | 
|  |  | 
|  | void DebugHandlerBase::endInstruction() { | 
|  | if (!MMI->hasDebugInfo()) | 
|  | return; | 
|  |  | 
|  | assert(CurMI != nullptr); | 
|  | // Don't create a new label after DBG_VALUE and other instructions that don't | 
|  | // generate code. | 
|  | if (!CurMI->isMetaInstruction()) { | 
|  | PrevLabel = nullptr; | 
|  | PrevInstBB = CurMI->getParent(); | 
|  | } | 
|  |  | 
|  | DenseMap<const MachineInstr *, MCSymbol *>::iterator I = | 
|  | LabelsAfterInsn.find(CurMI); | 
|  | CurMI = nullptr; | 
|  |  | 
|  | // No label needed. | 
|  | if (I == LabelsAfterInsn.end()) | 
|  | return; | 
|  |  | 
|  | // Label already assigned. | 
|  | if (I->second) | 
|  | return; | 
|  |  | 
|  | // We need a label after this instruction. | 
|  | if (!PrevLabel) { | 
|  | PrevLabel = MMI->getContext().createTempSymbol(); | 
|  | Asm->OutStreamer->EmitLabel(PrevLabel); | 
|  | } | 
|  | I->second = PrevLabel; | 
|  | } | 
|  |  | 
|  | void DebugHandlerBase::endFunction(const MachineFunction *MF) { | 
|  | if (hasDebugInfo(MMI, MF)) | 
|  | endFunctionImpl(MF); | 
|  | DbgValues.clear(); | 
|  | LabelsBeforeInsn.clear(); | 
|  | LabelsAfterInsn.clear(); | 
|  | } |