LLVM: lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

24

25using namespace llvm;

26

27#define DEBUG_TYPE "dwarfdebug"

28

29

30

32

33std::optional

37

38 if (Instruction.getNumDebugOperands() != 1)

39 return std::nullopt;

40 if (Instruction.getDebugOperand(0).isReg())

41 return std::nullopt;

42 Location.Register = Instruction.getDebugOperand(0).getReg();

43 Location.FragmentInfo.reset();

44

45

49

50

52 if (Instruction.getNumDebugOperands() == 1 &&

55 else

56 return std::nullopt;

57 }

59 switch (Op->getOp()) {

60 case dwarf::DW_OP_constu: {

61 int Value = Op->getArg(0);

64 switch (Op->getOp()) {

65 case dwarf::DW_OP_minus:

67 break;

68 case dwarf::DW_OP_plus:

70 break;

71 default:

72 continue;

73 }

74 }

75 } break;

76 case dwarf::DW_OP_plus_uconst:

78 break;

80 Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)};

81 break;

82 case dwarf::DW_OP_deref:

83 Location.LoadChain.push_back(Offset);

85 break;

86 default:

87 return std::nullopt;

88 }

90 }

91

92

93

94

96 Location.LoadChain.push_back(Offset);

97

98 return Location;

99}

100

102

104

106 if (M->debug_compile_units().empty())

107 Asm = nullptr;

108}

109

110

111

112

113

117 while (!WorkList.empty()) {

119

121 if (!Children.empty())

122 WorkList.append(Children.begin(), Children.end());

123

125 continue;

126

128 assert(R.first && "InsnRange does not have first instruction!");

129 assert(R.second && "InsnRange does not have second instruction!");

132 }

133 }

134}

135

136

139 assert(Label && "Didn't insert label before instruction");

140 return Label;

141}

142

143

146}

147

148

151 const DIDerivedType *DDTy = dyn_cast(Ty);

152 if (!DDTy)

154

156

157 if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&

158 Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&

159 Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&

160 Tag != dwarf::DW_TAG_immutable_type &&

161 Tag != dwarf::DW_TAG_template_alias)

163

165

167 return 0;

168

169

170

171

172 if (BaseType->getTag() == dwarf::DW_TAG_reference_type ||

173 BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type)

175

177}

178

180 if (isa(Ty)) {

181

182

183

184

185

186

187 return true;

188 }

189

190 if (auto *CTy = dyn_cast(Ty)) {

191 if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) {

192 if (!(Ty = CTy->getBaseType()))

193

194

195 return false;

196 } else

197

198

199 return true;

200 }

201

202 if (auto *DTy = dyn_cast(Ty)) {

204

205

206

207

208

209 if (T == dwarf::DW_TAG_pointer_type ||

210 T == dwarf::DW_TAG_ptr_to_member_type ||

211 T == dwarf::DW_TAG_reference_type ||

212 T == dwarf::DW_TAG_rvalue_reference_type)

213 return true;

214 assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||

215 T == dwarf::DW_TAG_volatile_type ||

216 T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type ||

217 T == dwarf::DW_TAG_immutable_type ||

218 T == dwarf::DW_TAG_template_alias);

219 assert(DTy->getBaseType() && "Expected valid base type");

221 }

222

223 auto *BTy = cast(Ty);

224 unsigned Encoding = BTy->getEncoding();

225 assert((Encoding == dwarf::DW_ATE_unsigned ||

226 Encoding == dwarf::DW_ATE_unsigned_char ||

227 Encoding == dwarf::DW_ATE_signed ||

228 Encoding == dwarf::DW_ATE_signed_char ||

229 Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||

230 Encoding == dwarf::DW_ATE_boolean ||

231 Encoding == dwarf::DW_ATE_complex_float ||

232 Encoding == dwarf::DW_ATE_signed_fixed ||

233 Encoding == dwarf::DW_ATE_unsigned_fixed ||

234 (Ty->getTag() == dwarf::DW_TAG_unspecified_type &&

235 Ty->getName() == "decltype(nullptr)")) &&

236 "Unsupported encoding");

237 return Encoding == dwarf::DW_ATE_unsigned ||

238 Encoding == dwarf::DW_ATE_unsigned_char ||

239 Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||

240 Encoding == llvm::dwarf::DW_ATE_unsigned_fixed ||

241 Ty->getTag() == dwarf::DW_TAG_unspecified_type;

242}

243

246 if (!SP)

247 return false;

248 assert(SP->getUnit());

249 auto EK = SP->getUnit()->getEmissionKind();

251 return false;

252 return true;

253}

254

257

260 return;

261 }

262

263

264

268 return;

269 }

270

271

273

274

283

284

286 const auto &Entries = I.second;

287 if (Entries.empty())

288 continue;

289

291 return any_of(MI->debug_operands(),

292 [](auto &MO) { return MO.isReg() && MO.getReg(); });

293 };

294

295

296

297

298

299

300

301

302

303

305 Entries.front().getInstr()->getDebugVariable();

308 if (!IsDescribedByReg(Entries.front().getInstr()))

310 if (Entries.front().getInstr()->getDebugExpression()->isFragment()) {

311

312 for (const auto *I = Entries.begin(); I != Entries.end(); ++I) {

313 if (I->isDbgValue())

314 continue;

315 const DIExpression *Fragment = I->getInstr()->getDebugExpression();

316 if (std::any_of(Entries.begin(), I,

318 return Pred.isDbgValue() &&

319 Fragment->fragmentsOverlap(

320 Pred.getInstr()->getDebugExpression());

321 }))

322 break;

323

324

325

326

327 if (IsDescribedByReg(I->getInstr()))

328 break;

330 }

331 }

332 }

333

334 for (const auto &Entry : Entries) {

335 if (Entry.isDbgValue())

337 else

339 }

340 }

341

342

346 }

347

351}

352

355 return;

356

359

360

363

364

366 return;

367

368

369 if (I->second)

370 return;

371

375 }

377}

378

381 return;

382

384

385

389 }

390

393

394

397 return;

398 }

399

400

401

402

403

409 }

412}

413

421 InstOrdering.clear();

422}

423

428}

429

432}

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static cl::opt< bool > TrimVarLocs("trim-var-locs", cl::Hidden, cl::init(true))

If true, we drop variable location ranges which exist entirely outside the variable's lexical scope i...

static bool hasDebugInfo(const MachineFunction *MF)

Module.h This file contains the declarations for the Module class.

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This class is intended to be used as a driving class for all asm writers.

MCSymbol * getFunctionBegin() const

MachineFunction * MF

The current machine function.

bool hasDebugInfo() const

Returns true if valid debug info is present.

std::unique_ptr< MCStreamer > OutStreamer

This is the MCStreamer object for the file we are generating.

expr_op_iterator expr_op_begin() const

Visit the elements via ExprOperand wrappers.

expr_op_iterator expr_op_end() const

DILocalScope * getScope() const

Get the local scope for this variable.

dwarf::Tag getTag() const

StringRef getName() const

uint64_t getSizeInBits() const

This class represents an Operation in the Expression.

Specifies a change in a variable's debug value history.

void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, const InstructionOrdering &Ordering)

Drop location ranges which exist entirely outside each variable's scope.

LLVM_DUMP_METHOD void dump(StringRef FuncName) const

static bool isUnsignedDIType(const DIType *Ty)

Return true if type encoding is unsigned.

const MachineInstr * CurMI

If nonnull, stores the current machine instruction we're processing.

AsmPrinter * Asm

Target of debug info emission.

virtual void endFunctionImpl(const MachineFunction *MF)=0

MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)

Return Label preceding the instruction.

MachineModuleInfo * MMI

Collected machine module information.

void endBasicBlockSection(const MachineBasicBlock &MBB) override

Process the end of a basic-block-section within a function.

void identifyScopeMarkers()

Indentify instructions that are marking the beginning of or ending of a scope.

virtual void skippedNonDebugFunction()

void endFunction(const MachineFunction *MF) override

Gather post-function debug information.

DebugLoc PrevInstLoc

Previous instruction's location information.

void beginFunction(const MachineFunction *MF) override

Gather pre-function debug information.

void endInstruction() override

Process end of an instruction.

virtual ~DebugHandlerBase() override

MCSymbol * getLabelAfterInsn(const MachineInstr *MI)

Return Label immediately following the instruction.

DebugHandlerBase(AsmPrinter *A)

void beginInstruction(const MachineInstr *MI) override

Process beginning of an instruction.

const MachineBasicBlock * PrevInstBB

virtual void beginFunctionImpl(const MachineFunction *MF)=0

void requestLabelAfterInsn(const MachineInstr *MI)

Ensure that a label will be emitted after MI.

void beginBasicBlockSection(const MachineBasicBlock &MBB) override

Process the beginning of a new basic-block-section within a function.

DbgValueHistoryMap DbgValues

History of DBG_VALUE and clobber instructions for each user variable.

DbgLabelInstrMap DbgLabels

Mapping of inlined labels and DBG_LABEL machine instruction.

DenseMap< const MachineInstr *, MCSymbol * > LabelsBeforeInsn

Maps instruction with label emitted before instruction.

void beginModule(Module *M) override

DenseMap< const MachineInstr *, MCSymbol * > LabelsAfterInsn

Maps instruction with label emitted after instruction.

void requestLabelBeforeInsn(const MachineInstr *MI)

Ensure that a label will be emitted before MI.

const MachineBasicBlock * EpilogBeginBlock

This block includes epilogue instructions.

static uint64_t getBaseTypeSize(const DIType *Ty)

If this type is derived from a base type then return base type size.

DISubprogram * getSubprogram() const

Get the attached subprogram.

void initialize(const MachineFunction &MF)

LexicalScope - This class is used to track scope information.

SmallVectorImpl< LexicalScope * > & getChildren()

SmallVectorImpl< InsnRange > & getRanges()

bool isAbstractScope() const

void initialize(const MachineFunction &)

initialize - Scan machine function and constuct lexical scope nest, resets the instance if necessary.

bool empty()

empty - Return true if there is any lexical scope information available.

LexicalScope * getCurrentFunctionScope() const

getCurrentFunctionScope - Return lexical scope for the current function.

MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

MCSymbol * getSymbol() const

Return the MCSymbol for this basic block.

MCSymbol * getEndSymbol() const

Returns the MCSymbol marking the end of this basic block.

bool isEntryBlock() const

Returns true if this is the entry block of the function.

bool isEndSection() const

Returns true if this block ends any section.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

Function & getFunction()

Return the LLVM function that this machine code represents.

Representation of each machine instruction.

const MachineBasicBlock * getParent() const

bool isMetaInstruction(QueryType Type=IgnoreBundle) const

Return true if this instruction doesn't produce any output in the form of executable instructions.

const MCContext & getContext() const

A Module instance is used to store all the information related to an LLVM module.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

LLVM Value Representation.

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

initializer< Ty > init(const Ty &Val)

@ DW_OP_LLVM_fragment

Only used in LLVM metadata.

@ DW_OP_LLVM_arg

Only used in LLVM metadata.

This is an optimization pass for GlobalISel generic memory operations.

void calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels)

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

DWARFExpression::Operation Op

std::pair< const MachineInstr *, const MachineInstr * > InsnRange

InsnRange - This is used to track range of instructions with identical lexical scope.

DISubprogram * getDISubprogram(const MDNode *Scope)

Find subprogram that is enclosing this scope.

Represents the location at which a variable is stored.

static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)

Extract a VariableLocation from a MachineInstr.