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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

22#include "llvm/Config/llvm-config.h"

31#include

32#include

33#include

34#include

35

36using namespace llvm;

37

38#define DEBUG_TYPE "lexicalscopes"

39

43

45 FunctionMap.clear();

47}

48

50 MF = nullptr;

51 CurrentFnLexicalScope = nullptr;

52 LexicalScopeMap.clear();

53 AbstractScopeMap.clear();

54 InlinedLexicalScopeMap.clear();

55 AbstractScopesList.clear();

56 DominatedBlocks.clear();

57}

58

63 if (SP && (!SP->getUnit() || skipUnit(SP->getUnit())))

64 FunctionMap[SP] = &F;

65 }

66}

67

70

72 return;

73 MF = &Fn;

76 extractLexicalScopes(MIRanges, MI2ScopeMap);

77 if (CurrentFnLexicalScope) {

78 constructScopeNest(CurrentFnLexicalScope);

79 assignInstructionRanges(MIRanges, MI2ScopeMap);

80 }

81}

82

83

84

85void LexicalScopes::extractLexicalScopes(

88

89 for (const auto &MBB : *MF) {

93 for (const auto &MInsn : MBB) {

94

95

96 if (MInsn.isMetaInstruction())

97 continue;

98

99

100 const DILocation *MIDL = MInsn.getDebugLoc();

101 if (!MIDL) {

102 PrevMI = &MInsn;

103 continue;

104 }

105

106

107 if (MIDL == PrevDL) {

108 PrevMI = &MInsn;

109 continue;

110 }

111

112 if (RangeBeginMI) {

113

114

115

117 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);

119 }

120

121

122 RangeBeginMI = &MInsn;

123

124

125 PrevMI = &MInsn;

126 PrevDL = MIDL;

127 }

128

129

130 if (RangeBeginMI && PrevMI && PrevDL) {

133 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);

134 }

135 }

136}

137

138

139

142 if (!Scope)

143 return nullptr;

144

145

146

147 Scope = Scope->getNonLexicalBlockFileScope();

148

149 if (auto *IA = DL->getInlinedAt()) {

150 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));

151 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;

152 }

154}

155

156

157

160 if (IA) {

161

162 if (skipUnit(Scope->getSubprogram()->getUnit()))

163 return getOrCreateLexicalScope(IA);

164

166

167 return getOrCreateInlinedScope(Scope, IA);

168 }

169

170 return getOrCreateRegularScope(Scope);

171}

172

173

175LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {

176 assert(Scope && "Invalid Scope encoding!");

177 Scope = Scope->getNonLexicalBlockFileScope();

178

179 auto I = LexicalScopeMap.find(Scope);

180 if (I != LexicalScopeMap.end())

181 return &I->second;

182

183

184 LexicalScope *Parent = nullptr;

186 Parent = getOrCreateLexicalScope(Block->getScope());

187 I = LexicalScopeMap.emplace(std::piecewise_construct,

188 std::forward_as_tuple(Scope),

189 std::forward_as_tuple(Parent, Scope, nullptr,

190 false)).first;

191

192 if (!Parent) {

194 assert(!CurrentFnLexicalScope);

195 CurrentFnLexicalScope = &I->second;

196 }

197

198 return &I->second;

199}

200

201

203LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,

205 assert(Scope && "Invalid Scope encoding!");

206 Scope = Scope->getNonLexicalBlockFileScope();

207 std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);

208 auto I = InlinedLexicalScopeMap.find(P);

209 if (I != InlinedLexicalScopeMap.end())

210 return &I->second;

211

212 LexicalScope *Parent;

214 Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);

215 else

216 Parent = getOrCreateLexicalScope(InlinedAt);

217

218 I = InlinedLexicalScopeMap

219 .emplace(std::piecewise_construct, std::forward_as_tuple(P),

220 std::forward_as_tuple(Parent, Scope, InlinedAt, false))

221 .first;

222 return &I->second;

223}

224

225

228 assert(Scope && "Invalid Scope encoding!");

229 Scope = Scope->getNonLexicalBlockFileScope();

230 auto I = AbstractScopeMap.find(Scope);

231 if (I != AbstractScopeMap.end())

232 return &I->second;

233

234

238

239 I = AbstractScopeMap.emplace(std::piecewise_construct,

240 std::forward_as_tuple(Scope),

241 std::forward_as_tuple(Parent, Scope,

242 nullptr, true)).first;

244 AbstractScopesList.push_back(&I->second);

245 return &I->second;

246}

247

248

249

250

251void LexicalScopes::constructScopeNest(LexicalScope *Scope) {

252 assert(Scope && "Unable to calculate scope dominance graph!");

254 WorkStack.push_back(std::make_pair(Scope, 0));

255 unsigned Counter = 0;

256 while (!WorkStack.empty()) {

257 auto &ScopePosition = WorkStack.back();

259 size_t ChildNum = ScopePosition.second++;

261 if (ChildNum < Children.size()) {

262 auto &ChildScope = Children[ChildNum];

263 WorkStack.push_back(std::make_pair(ChildScope, 0));

264 ChildScope->setDFSIn(++Counter);

265 } else {

268 }

269 }

270}

271

272

273

274void LexicalScopes::assignInstructionRanges(

277 LexicalScope *PrevLexicalScope = nullptr;

278 for (const auto &R : MIRanges) {

279 LexicalScope *S = MI2ScopeMap.lookup(R.first);

280 assert(S && "Lost LexicalScope for a machine instruction!");

281 if (PrevLexicalScope && !PrevLexicalScope->dominates(S))

285 PrevLexicalScope = S;

286 }

287

288 if (PrevLexicalScope)

290}

291

292

293

294

297 assert(MF && "Method called on a uninitialized LexicalScopes object!");

299

301 if (!Scope)

302 return;

303

304 if (Scope == CurrentFnLexicalScope) {

306 return;

307 }

308

309

310

311

313 for (auto &R : InsnRanges)

314 for (auto CurMBBIt = R.first->getParent()->getIterator(),

315 EndBBIt = std::next(R.second->getParent()->getIterator());

316 CurMBBIt != EndBBIt; CurMBBIt++)

317 MBBs.insert(&*CurMBBIt);

318}

319

321 assert(MF && "Unexpected uninitialized LexicalScopes object!");

323 if (!Scope)

324 return false;

325

326

327 if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)

328 return true;

329

330

331

332

333

334

335

336 std::unique_ptr &Set = DominatedBlocks[DL];

337 if (!Set) {

338 Set = std::make_unique();

340 }

341 return Set->contains(MBB);

342}

343

344#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

348 err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";

351 N->dump();

352 if (AbstractScope)

353 err << std::string(Indent, ' ') << "Abstract Scope\n";

354

355 if (!Children.empty())

356 err << std::string(Indent + 2, ' ') << "Children ...\n";

358 if (Child != this)

359 Child->dump(Indent + 2);

360}

361#endif

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

This file defines the DenseMap class.

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

static bool skipUnit(const DICompileUnit *CU)

Definition LexicalScopes.cpp:40

This file defines the SmallVector class.

Subprogram description. Uses SubclassData1.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

DISubprogram * getSubprogram() const

Get the attached subprogram.

This class is used to track scope information.

void extendInsnRange(const MachineInstr *MI)

Extend the current instruction range covered by this scope.

SmallVectorImpl< LexicalScope * > & getChildren()

LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A)

void setDFSOut(unsigned O)

void openInsnRange(const MachineInstr *MI)

This scope covers instruction range starting from MI.

LLVM_ABI void dump(unsigned Indent=0) const

Print lexical scope.

Definition LexicalScopes.cpp:345

bool dominates(const LexicalScope *S) const

Return true if current scope dominates given lexical scope.

void closeInsnRange(LexicalScope *NewScope=nullptr)

Create a range based on FirstInsn and LastInsn collected until now.

LLVM_ABI void scanFunction(const MachineFunction &)

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

Definition LexicalScopes.cpp:68

LLVM_ABI LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)

Find or create an abstract lexical scope.

Definition LexicalScopes.cpp:227

LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)

Find lexical scope, either regular or inlined, for the given DebugLoc.

Definition LexicalScopes.cpp:140

LLVM_ABI void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl< const MachineBasicBlock * > &MBBs)

Populate given set using machine basic blocks which have machine instructions that belong to lexical ...

Definition LexicalScopes.cpp:295

LLVM_ABI void initialize(const Module &)

Scan module to build subprogram-to-function map.

Definition LexicalScopes.cpp:59

LLVM_ABI void resetFunction()

Reset the instance so that it's prepared for another function.

Definition LexicalScopes.cpp:49

LLVM_ABI void resetModule()

Reset the instance so that it's prepared for another module.

Definition LexicalScopes.cpp:44

LLVM_ABI bool dominates(const DILocation *DL, MachineBasicBlock *MBB)

Return true if DebugLoc's lexical scope dominates at least one machine instruction's lexical scope in...

Definition LexicalScopes.cpp:320

Function & getFunction()

Return the LLVM function that this machine code represents.

Representation of each machine instruction.

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

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

void insert_range(Range &&R)

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

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

void push_back(const T &Elt)

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

This class implements an extremely fast bulk output stream that can only output to a stream.

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

Scope

Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

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

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

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)