LLVM: lib/CodeGen/AsmPrinter/DwarfDebug.cpp File Reference (original) (raw)
Go to the source code of this file.
| Classes | |
|---|---|
| struct | FwdRegParamInfo |
| Represents a parameter whose call site value can be described by applying a debug expression to a register in the forwarded register worklist. More... | |
| struct | ArangeSpan |
| Macros | |
|---|---|
| #define | DEBUG_TYPE "dwarfdebug" |
| #define | HANDLE_MACRO_FLAG(ID, NAME) |
| Functions | |
|---|---|
| STATISTIC (NumCSParams, "Number of dbg call site params created") | |
| static DbgValueLoc | getDebugLocValue (const MachineInstr *MI) |
| Get .debug_loc entry for the instruction range starting at MI. | |
| static uint64_t | getFragmentOffsetInBits (const DIExpression &Expr) |
| static AccelTableKind | computeAccelTableKind (unsigned DwarfVersion, bool GenerateTypeUnits, DebuggerKind Tuning, const Triple &TT) |
| static bool | isObjCClass (StringRef Name) |
| static bool | hasObjCCategory (StringRef Name) |
| static void | getObjCClassCategory (StringRef In, StringRef &Class, StringRef &Category) |
| static StringRef | getObjCMethodName (StringRef In) |
| template | |
| static void | forBothCUs (DwarfCompileUnit &CU, Func F) |
| static const DIExpression * | combineDIExpressions (const DIExpression *Original, const DIExpression *Addition) |
| Append the expression Addition to Original and return the result. | |
| template<typename ValT> | |
| static void | finishCallSiteParams (ValT Val, const DIExpression *Expr, ArrayRef< FwdRegParamInfo > DescribedParams, ParamSet &Params) |
| Emit call site parameter entries that are described by the given value and debug expression. | |
| static void | addToFwdRegWorklist (FwdRegWorklist &Worklist, unsigned Reg, const DIExpression *Expr, ArrayRef< FwdRegParamInfo > ParamsToAdd) |
| Add Reg to the worklist, if it's not already present, and mark that the given parameter registers' values can (potentially) be described using that register and an debug expression. | |
| static void | interpretValues (const MachineInstr *CurMI, FwdRegWorklist &ForwardedRegWorklist, ParamSet &Params, ClobberedRegUnitSet &ClobberedRegUnits) |
| Interpret values loaded into registers by CurMI. | |
| static bool | interpretNextInstr (const MachineInstr *CurMI, FwdRegWorklist &ForwardedRegWorklist, ParamSet &Params, ClobberedRegUnitSet &ClobberedRegUnits) |
| static void | collectCallSiteParameters (const MachineInstr *CallMI, ParamSet &Params) |
| Try to interpret values loaded into registers that forward parameters for CallMI. | |
| static SmallVectorImpl< DwarfCompileUnit::GlobalExpr > & | sortGlobalExprs (SmallVectorImpl< DwarfCompileUnit::GlobalExpr > &GVEs) |
| Sort and unique GVEs by comparing their fragment offset. | |
| static const DILocalScope * | getRetainedNodeScope (const MDNode *N) |
| static bool | validThroughout (LexicalScopes &LScopes, const MachineInstr *DbgValue, const MachineInstr *RangeEnd, const InstructionOrdering &Ordering) |
| Determine whether a singular DBG_VALUE is valid for the entirety of its enclosing lexical scope. | |
| static std::pair< const MachineInstr *, bool > | findPrologueEndLoc (const MachineFunction *MF) |
| static void | recordSourceLine (AsmPrinter &Asm, unsigned Line, unsigned Col, const MDNode *S, unsigned Flags, unsigned CUID, uint16_t DwarfVersion, ArrayRef< std::unique_ptr< DwarfCompileUnit > > DCUs, StringRef Comment={}) |
| Register a source line with debug info. | |
| static dwarf::PubIndexEntryDescriptor | computeIndexValue (DwarfUnit *CU, const DIE *Die) |
| computeIndexValue - Compute the gdb index value for the DIE and CU. | |
| static MCSymbol * | emitRnglistsTableHeader (AsmPrinter *Asm, const DwarfFile &Holder) |
| static MCSymbol * | emitLoclistsTableHeader (AsmPrinter *Asm, const DwarfDebug &DD) |
| template<typename Ranges, typename PayloadEmitter> | |
| static void | emitRangeList (DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R, const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair, unsigned StartxLength, unsigned StartxEndx, unsigned EndOfList, StringRef(*StringifyEnum)(unsigned), bool ShouldUseBaseAddress, PayloadEmitter EmitPayload) |
| static void | emitLocList (DwarfDebug &DD, AsmPrinter *Asm, const DebugLocStream::List &List) |
| static void | emitRangeList (DwarfDebug &DD, AsmPrinter *Asm, const RangeSpanList &List) |
| Emit a single range list. We handle both DWARF v5 and earlier. | |
| static void | emitMacroHeader (AsmPrinter *Asm, const DwarfDebug &DD, const DwarfCompileUnit &CU, uint16_t DwarfVersion) |
| Emit the header of a DWARF 5 macro section, or the GNU extension for DWARF 4. |
| Variables | |
|---|---|
| static cl::opt< bool > | UseDwarfRangesBaseAddressSpecifier ("use-dwarf-ranges-base-address-specifier", cl::Hidden, cl::desc("Use base address specifiers in debug_ranges"), cl::init(false)) |
| static cl::opt< bool > | GenerateARangeSection ("generate-arange-section", cl::Hidden, cl::desc("Generate dwarf aranges"), cl::init(false)) |
| static cl::opt< bool > | GenerateDwarfTypeUnits ("generate-type-units", cl::Hidden, cl::desc("Generate DWARF4 type units."), cl::init(false)) |
| static cl::opt< bool > | SplitDwarfCrossCuReferences ("split-dwarf-cross-cu-references", cl::Hidden, cl::desc("Enable cross-cu references in DWO files"), cl::init(false)) |
| static cl::opt< DefaultOnOff > | UnknownLocations ("use-unknown-locations", cl::Hidden, cl::desc("Make an absence of debug location information explicit."), cl::values(clEnumVal(Default, "At top of block or after label"), clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")), cl::init(Default)) |
| static cl::opt< AccelTableKind > | AccelTables ("accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."), cl::values(clEnumValN(AccelTableKind::Default, "Default", "Default for platform"), clEnumValN(AccelTableKind::None, "Disable", "Disabled."), clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")), cl::init(AccelTableKind::Default)) |
| static cl::opt< DefaultOnOff > | DwarfInlinedStrings ("dwarf-inlined-strings", cl::Hidden, cl::desc("Use inlined strings rather than string section."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default)) |
| static cl::opt< bool > | NoDwarfRangesSection ("no-dwarf-ranges-section", cl::Hidden, cl::desc("Disable emission .debug_ranges section."), cl::init(false)) |
| static cl::opt< DefaultOnOff > | DwarfSectionsAsReferences ("dwarf-sections-as-references", cl::Hidden, cl::desc("Use sections+offset as references rather than labels."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default)) |
| static cl::opt< bool > | UseGNUDebugMacro ("use-gnu-debug-macro", cl::Hidden, cl::desc("Emit the GNU .debug_macro format with DWARF <5"), cl::init(false)) |
| static cl::opt< DefaultOnOff > | DwarfOpConvert ("dwarf-op-convert", cl::Hidden, cl::desc("Enable use of the DWARFv5 DW_OP_convert operator"), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default)) |
| static cl::opt< LinkageNameOption > | DwarfLinkageNames ("dwarf-linkage-names", cl::Hidden, cl::desc("Which DWARF linkage-name attributes to emit."), cl::values(clEnumValN(DefaultLinkageNames, "Default", "Default for platform"), clEnumValN(AllLinkageNames, "All", "All"), clEnumValN(AbstractLinkageNames, "Abstract", "Abstract subprograms")), cl::init(DefaultLinkageNames)) |
| static cl::opt< DwarfDebug::MinimizeAddrInV5 > | MinimizeAddrInV5Option ("minimize-addr-in-v5", cl::Hidden, cl::desc("Always use DW_AT_ranges in DWARFv5 whenever it could allow more " "address pool entry sharing to reduce relocations/object size"), cl::values(clEnumValN(DwarfDebug::MinimizeAddrInV5::Default, "Default", "Default address minimization strategy"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Ranges, "Ranges", "Use rnglists for contiguous ranges if that allows " "using a pre-existing base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Expressions, "Expressions", "Use exprloc addrx+offset expressions for any " "address with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Form, "Form", "Use addrx+offset extension form for any address " "with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Disabled, "Disabled", "Stuff")), cl::init(DwarfDebug::MinimizeAddrInV5::Default)) |
| static cl::opt< bool > | KeyInstructionsAreStmts ("dwarf-use-key-instructions", cl::Hidden, cl::init(true), cl::desc("Set to false to ignore Key Instructions metadata")) |
| Set to false to ignore Key Instructions metadata. | |
| static constexpr unsigned | ULEB128PadSize = 4 |
◆ DEBUG_TYPE
#define DEBUG_TYPE "dwarfdebug"
◆ HANDLE_MACRO_FLAG
| #define HANDLE_MACRO_FLAG | ( | ID, |
|---|---|---|
| NAME ) |
Value:
MACRO_FLAG_##NAME = ID,
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
◆ ClobberedRegUnitSet
Container for the set of register units known to be clobbered on the path to a call site.
Definition at line 594 of file DwarfDebug.cpp.
◆ FwdRegWorklist
◆ DefaultOnOff
◆ LinkageNameOption
| Enumerator |
|---|
| DefaultLinkageNames |
| AllLinkageNames |
| AbstractLinkageNames |
Definition at line 136 of file DwarfDebug.cpp.
◆ addToFwdRegWorklist()
◆ collectCallSiteParameters()
Try to interpret values loaded into registers that forward parameters for CallMI.
Store parameters with interpreted value into Params.
Definition at line 806 of file DwarfDebug.cpp.
References assert(), llvm::MachineFunction::begin(), llvm::MapVector< KeyT, ValueT, MapType, VectorType >::erase(), llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::find(), finishCallSiteParams(), llvm::MDNode::get(), llvm::getBundleEnd(), llvm::MachineFunction::getCallSitesInfo(), llvm::Function::getContext(), llvm::MachineFunction::getFunction(), llvm::ilist_node_impl< OptionsT >::getIterator(), llvm::MachineInstr::getMF(), llvm::MachineInstr::getParent(), llvm::ilist_node_impl< OptionsT >::getReverseIterator(), llvm::MachineInstr::hasDelaySlot(), I, llvm::MapVector< KeyT, ValueT, MapType, VectorType >::insert(), interpretNextInstr(), MBB, and llvm::MachineInstr::uses().
◆ combineDIExpressions()
◆ computeAccelTableKind()
◆ computeIndexValue()
◆ emitLocList()
◆ emitLoclistsTableHeader()
◆ emitMacroHeader()
◆ emitRangeList() [1/2]
◆ emitRangeList() [2/2]
template<typename Ranges, typename PayloadEmitter>
| void emitRangeList ( DwarfDebug & DD, AsmPrinter * Asm, MCSymbol * Sym, const Ranges & R, const DwarfCompileUnit & CU, unsigned BaseAddressx, unsigned OffsetPair, unsigned StartxLength, unsigned StartxEndx, unsigned EndOfList, StringRef(* StringifyEnum )(unsigned), bool ShouldUseBaseAddress, PayloadEmitter EmitPayload ) | static |
|---|
Definition at line 3311 of file DwarfDebug.cpp.
References assert(), llvm::sampleprof::Base, EndOfList, llvm::DwarfDebug::getAddressPool(), llvm::DwarfDebug::getDwarfVersion(), llvm::AddressPool::getIndex(), llvm::MCSymbol::getSection(), llvm::DwarfDebug::getSectionLabel(), llvm::isRangeRelaxable(), P, Range, Size, llvm::DwarfDebug::tuneForGDB(), and llvm::DwarfDebug::useSplitDwarf().
Referenced by emitLocList(), and emitRangeList().
◆ emitRnglistsTableHeader()
◆ findPrologueEndLoc()
Definition at line 2220 of file DwarfDebug.cpp.
References assert(), llvm::MachineFunction::begin(), llvm::MachineFunction::end(), F, llvm::MachineInstr::FrameSetup, llvm::MDNode::get(), llvm::MachineFunction::getFunction(), llvm::TargetSubtargetInfo::getInstrInfo(), llvm::MachineInstr::getParent(), llvm::MachineFunction::getSubtarget(), isCopy(), MI, and TII.
Referenced by llvm::DwarfDebug::emitInitialLocDirective().
◆ finishCallSiteParams()
◆ forBothCUs()
◆ getDebugLocValue()
◆ getFragmentOffsetInBits()
◆ getObjCClassCategory()
◆ getObjCMethodName()
◆ getRetainedNodeScope()
◆ hasObjCCategory()
◆ interpretNextInstr()
◆ interpretValues()
Interpret values loaded into registers by CurMI.
Definition at line 663 of file DwarfDebug.cpp.
References addToFwdRegWorklist(), llvm::MapVector< KeyT, ValueT, MapType, VectorType >::clear(), llvm::SetVector< T, Vector, Set, N >::empty(), llvm::MapVector< KeyT, ValueT, MapType, VectorType >::erase(), finishCallSiteParams(), FP, llvm::MDNode::get(), llvm::Function::getContext(), llvm::MachineFunction::getFunction(), llvm::TargetSubtargetInfo::getInstrInfo(), llvm::MachineInstr::getMF(), llvm::TargetSubtargetInfo::getRegisterInfo(), llvm::MachineFunction::getSubtarget(), llvm::TargetSubtargetInfo::getTargetLowering(), llvm::SmallSet< T, N, C >::insert_range(), MI, Reg, TII, and TRI.
Referenced by interpretNextInstr().
◆ isObjCClass()
◆ recordSourceLine()
Register a source line with debug info.
Returns the unique label that was emitted and which provides correspondence to the source line list.
Definition at line 2365 of file DwarfDebug.cpp.
◆ sortGlobalExprs()
◆ STATISTIC()
| STATISTIC | ( | NumCSParams | , |
|---|---|---|---|
| "Number of dbg call site params created" | ) |
◆ validThroughout()
◆ AccelTables
| cl::opt< AccelTableKind > AccelTables("accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."), cl::values(clEnumValN(AccelTableKind::Default, "Default", "Default for platform"), clEnumValN(AccelTableKind::None, "Disable", "Disabled."), clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")), cl::init(AccelTableKind::Default)) ( "accel-tables" , cl::Hidden , cl::desc("Output dwarf accelerator tables.") , cl::values(clEnumValN(AccelTableKind::Default, "Default", "Default for platform"), clEnumValN(AccelTableKind::None, "Disable", "Disabled."), clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")) , cl::init(AccelTableKind::Default) ) | static |
|---|
◆ DwarfInlinedStrings
| cl::opt< DefaultOnOff > DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, cl::desc("Use inlined strings rather than string section."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default)) ( "dwarf-inlined-strings" , cl::Hidden , cl::desc("Use inlined strings rather than string section.") , cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")) , cl::init(Default) ) | static |
|---|
◆ DwarfLinkageNames
| cl::opt< LinkageNameOption > DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, cl::desc("Which DWARF linkage-name attributes to emit."), cl::values(clEnumValN(DefaultLinkageNames, "Default", "Default for platform"), clEnumValN(AllLinkageNames, "All", "All"), clEnumValN(AbstractLinkageNames, "Abstract", "Abstract subprograms")), cl::init(DefaultLinkageNames)) ( "dwarf-linkage-names" , cl::Hidden , cl::desc("Which DWARF linkage-name attributes to emit.") , cl::values(clEnumValN(DefaultLinkageNames, "Default", "Default for platform"), clEnumValN(AllLinkageNames, "All", "All"), clEnumValN(AbstractLinkageNames, "Abstract", "Abstract subprograms")) , cl::init(DefaultLinkageNames) ) | static |
|---|
◆ DwarfOpConvert
| cl::opt< DefaultOnOff > DwarfOpConvert("dwarf-op-convert", cl::Hidden, cl::desc("Enable use of the DWARFv5 DW_OP_convert operator"), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default)) ( "dwarf-op-convert" , cl::Hidden , cl::desc("Enable use of the DWARFv5 DW_OP_convert operator") , cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")) , cl::init(Default) ) | static |
|---|
◆ DwarfSectionsAsReferences
| cl::opt< DefaultOnOff > DwarfSectionsAsReferences("dwarf-sections-as-references", cl::Hidden, cl::desc("Use sections+offset as references rather than labels."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default)) ( "dwarf-sections-as-references" , cl::Hidden , cl::desc("Use sections+offset as references rather than labels.") , cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")) , cl::init(Default) ) | static |
|---|
◆ GenerateARangeSection
| cl::opt< bool > GenerateARangeSection("generate-arange-section", cl::Hidden, cl::desc("Generate dwarf aranges"), cl::init(false)) ( "generate-arange-section" , cl::Hidden , cl::desc("Generate dwarf aranges") , cl::init(false) ) | static |
|---|
◆ GenerateDwarfTypeUnits
| cl::opt< bool > GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, cl::desc("Generate DWARF4 type units."), cl::init(false)) ( "generate-type-units" , cl::Hidden , cl::desc("Generate DWARF4 type units.") , cl::init(false) ) | static |
|---|
◆ KeyInstructionsAreStmts
| cl::opt< bool > KeyInstructionsAreStmts("dwarf-use-key-instructions", cl::Hidden, cl::init(true), cl::desc("Set to false to ignore Key Instructions metadata")) ( "dwarf-use-key-instructions" , cl::Hidden , cl::init(true) , cl::desc("Set to false to ignore Key Instructions metadata") ) | static |
|---|
◆ MinimizeAddrInV5Option
| cl::opt< DwarfDebug::MinimizeAddrInV5 > MinimizeAddrInV5Option("minimize-addr-in-v5", cl::Hidden, cl::desc("Always use DW_AT_ranges in DWARFv5 whenever it could allow more " "address pool entry sharing to reduce relocations/object size"), cl::values(clEnumValN(DwarfDebug::MinimizeAddrInV5::Default, "Default", "Default address minimization strategy"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Ranges, "Ranges", "Use rnglists for contiguous ranges if that allows " "using a pre-existing base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Expressions, "Expressions", "Use exprloc addrx+offset expressions for any " "address with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Form, "Form", "Use addrx+offset extension form for any address " "with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Disabled, "Disabled", "Stuff")), cl::init(DwarfDebug::MinimizeAddrInV5::Default)) ( "minimize-addr-in-v5" , cl::Hidden , cl::desc("Always use DW_AT_ranges in DWARFv5 whenever it could allow more " "address pool entry sharing to reduce relocations/object size") , cl::values(clEnumValN(DwarfDebug::MinimizeAddrInV5::Default, "Default", "Default address minimization strategy"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Ranges, "Ranges", "Use rnglists for contiguous ranges if that allows " "using a pre-existing base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Expressions, "Expressions", "Use exprloc addrx+offset expressions for any " "address with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Form, "Form", "Use addrx+offset extension form for any address " "with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Disabled, "Disabled", "Stuff")) , cl::init(DwarfDebug::MinimizeAddrInV5::Default) ) | static |
|---|
◆ NoDwarfRangesSection
| cl::opt< bool > NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden, cl::desc("Disable emission .debug_ranges section."), cl::init(false)) ( "no-dwarf-ranges-section" , cl::Hidden , cl::desc("Disable emission .debug_ranges section.") , cl::init(false) ) | static |
|---|
◆ SplitDwarfCrossCuReferences
| cl::opt< bool > SplitDwarfCrossCuReferences("split-dwarf-cross-cu-references", cl::Hidden, cl::desc("Enable cross-cu references in DWO files"), cl::init(false)) ( "split-dwarf-cross-cu-references" , cl::Hidden , cl::desc("Enable cross-cu references in DWO files") , cl::init(false) ) | static |
|---|
◆ ULEB128PadSize
◆ UnknownLocations
| cl::opt< DefaultOnOff > UnknownLocations("use-unknown-locations", cl::Hidden, cl::desc("Make an absence of debug location information explicit."), cl::values(clEnumVal(Default, "At top of block or after label"), clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")), cl::init(Default)) ( "use-unknown-locations" , cl::Hidden , cl::desc("Make an absence of debug location information explicit.") , cl::values(clEnumVal(Default, "At top of block or after label"), clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")) , cl::init(Default) ) | static |
|---|
◆ UseDwarfRangesBaseAddressSpecifier
| cl::opt< bool > UseDwarfRangesBaseAddressSpecifier("use-dwarf-ranges-base-address-specifier", cl::Hidden, cl::desc("Use base address specifiers in debug_ranges"), cl::init(false)) ( "use-dwarf-ranges-base-address-specifier" , cl::Hidden , cl::desc("Use base address specifiers in debug_ranges") , cl::init(false) ) | static |
|---|
◆ UseGNUDebugMacro
| cl::opt< bool > UseGNUDebugMacro("use-gnu-debug-macro", cl::Hidden, cl::desc("Emit the GNU .debug_macro format with DWARF <5"), cl::init(false)) ( "use-gnu-debug-macro" , cl::Hidden , cl::desc("Emit the GNU .debug_macro format with DWARF <5") , cl::init(false) ) | static |
|---|