Skip to content

Commit 5a791ee

Browse files
committedMar 15, 2018
Re-land r327620 "[CodeView] Initial support for emitting S_BLOCK32 symbols for lexical scopes"
This is safe to land now that we don't copy FunctionInfo when rehashing the DenseMap. llvm-svn: 327670
1 parent e9dc30d commit 5a791ee

File tree

5 files changed

+514
-14
lines changed

5 files changed

+514
-14
lines changed
 

‎llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

+141-6
Original file line numberDiff line numberDiff line change
@@ -365,15 +365,15 @@ unsigned CodeViewDebug::getPointerSizeInBytes() {
365365
}
366366

367367
void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
368-
const DILocation *InlinedAt) {
369-
if (InlinedAt) {
368+
const LexicalScope *LS) {
369+
if (const DILocation *InlinedAt = LS->getInlinedAt()) {
370370
// This variable was inlined. Associate it with the InlineSite.
371371
const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
372372
InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
373373
Site.InlinedLocals.emplace_back(Var);
374374
} else {
375-
// This variable goes in the main ProcSym.
376-
CurFn->Locals.emplace_back(Var);
375+
// This variable goes into the corresponding lexical scope.
376+
ScopeVariables[LS].emplace_back(Var);
377377
}
378378
}
379379

@@ -905,6 +905,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
905905
OS.EmitLabel(ProcRecordEnd);
906906

907907
emitLocalVariableList(FI.Locals);
908+
emitLexicalBlockList(FI.ChildBlocks, FI);
908909

909910
// Emit inlined call site information. Only emit functions inlined directly
910911
// into the parent function. We'll emit the other sites recursively as part
@@ -1025,7 +1026,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
10251026
LocalVariable Var;
10261027
Var.DIVar = VI.Var;
10271028
Var.DefRanges.emplace_back(std::move(DefRange));
1028-
recordLocalVariable(std::move(Var), VI.Loc->getInlinedAt());
1029+
recordLocalVariable(std::move(Var), Scope);
10291030
}
10301031
}
10311032

@@ -1156,7 +1157,7 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
11561157
Var.DIVar = DIVar;
11571158

11581159
calculateRanges(Var, Ranges);
1159-
recordLocalVariable(std::move(Var), InlinedAt);
1160+
recordLocalVariable(std::move(Var), Scope);
11601161
}
11611162
}
11621163

@@ -2363,13 +2364,147 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
23632364
}
23642365
}
23652366

2367+
void CodeViewDebug::emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
2368+
const FunctionInfo& FI) {
2369+
for (LexicalBlock *Block : Blocks)
2370+
emitLexicalBlock(*Block, FI);
2371+
}
2372+
2373+
/// Emit an S_BLOCK32 and S_END record pair delimiting the contents of a
2374+
/// lexical block scope.
2375+
void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
2376+
const FunctionInfo& FI) {
2377+
MCSymbol *RecordBegin = MMI->getContext().createTempSymbol(),
2378+
*RecordEnd = MMI->getContext().createTempSymbol();
2379+
2380+
// Lexical block symbol record.
2381+
OS.AddComment("Record length");
2382+
OS.emitAbsoluteSymbolDiff(RecordEnd, RecordBegin, 2); // Record Length
2383+
OS.EmitLabel(RecordBegin);
2384+
OS.AddComment("Record kind: S_BLOCK32");
2385+
OS.EmitIntValue(SymbolKind::S_BLOCK32, 2); // Record Kind
2386+
OS.AddComment("PtrParent");
2387+
OS.EmitIntValue(0, 4); // PtrParent
2388+
OS.AddComment("PtrEnd");
2389+
OS.EmitIntValue(0, 4); // PtrEnd
2390+
OS.AddComment("Code size");
2391+
OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4); // Code Size
2392+
OS.AddComment("Function section relative address");
2393+
OS.EmitCOFFSecRel32(Block.Begin, /*Offset=*/0); // Func Offset
2394+
OS.AddComment("Function section index");
2395+
OS.EmitCOFFSectionIndex(FI.Begin); // Func Symbol
2396+
OS.AddComment("Lexical block name");
2397+
emitNullTerminatedSymbolName(OS, Block.Name); // Name
2398+
OS.EmitLabel(RecordEnd);
2399+
2400+
// Emit variables local to this lexical block.
2401+
emitLocalVariableList(Block.Locals);
2402+
2403+
// Emit lexical blocks contained within this block.
2404+
emitLexicalBlockList(Block.Children, FI);
2405+
2406+
// Close the lexical block scope.
2407+
OS.AddComment("Record length");
2408+
OS.EmitIntValue(2, 2); // Record Length
2409+
OS.AddComment("Record kind: S_END");
2410+
OS.EmitIntValue(SymbolKind::S_END, 2); // Record Kind
2411+
}
2412+
2413+
/// Convenience routine for collecting lexical block information for a list
2414+
/// of lexical scopes.
2415+
void CodeViewDebug::collectLexicalBlockInfo(
2416+
SmallVectorImpl<LexicalScope *> &Scopes,
2417+
SmallVectorImpl<LexicalBlock *> &Blocks,
2418+
SmallVectorImpl<LocalVariable> &Locals) {
2419+
for (LexicalScope *Scope : Scopes)
2420+
collectLexicalBlockInfo(*Scope, Blocks, Locals);
2421+
}
2422+
2423+
/// Populate the lexical blocks and local variable lists of the parent with
2424+
/// information about the specified lexical scope.
2425+
void CodeViewDebug::collectLexicalBlockInfo(
2426+
LexicalScope &Scope,
2427+
SmallVectorImpl<LexicalBlock *> &ParentBlocks,
2428+
SmallVectorImpl<LocalVariable> &ParentLocals) {
2429+
if (Scope.isAbstractScope())
2430+
return;
2431+
2432+
auto LocalsIter = ScopeVariables.find(&Scope);
2433+
if (LocalsIter == ScopeVariables.end()) {
2434+
// This scope does not contain variables and can be eliminated.
2435+
collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
2436+
return;
2437+
}
2438+
SmallVectorImpl<LocalVariable> &Locals = LocalsIter->second;
2439+
2440+
const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(Scope.getScopeNode());
2441+
if (!DILB) {
2442+
// This scope is not a lexical block and can be eliminated, but keep any
2443+
// local variables it contains.
2444+
ParentLocals.append(Locals.begin(), Locals.end());
2445+
collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
2446+
return;
2447+
}
2448+
2449+
const SmallVectorImpl<InsnRange> &Ranges = Scope.getRanges();
2450+
if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) {
2451+
// This lexical block scope has too many address ranges to represent in the
2452+
// current CodeView format or does not have a valid address range.
2453+
// Eliminate this lexical scope and promote any locals it contains to the
2454+
// parent scope.
2455+
//
2456+
// For lexical scopes with multiple address ranges you may be tempted to
2457+
// construct a single range covering every instruction where the block is
2458+
// live and everything in between. Unfortunately, Visual Studio only
2459+
// displays variables from the first matching lexical block scope. If the
2460+
// first lexical block contains exception handling code or cold code which
2461+
// is moved to the bottom of the routine creating a single range covering
2462+
// nearly the entire routine, then it will hide all other lexical blocks
2463+
// and the variables they contain.
2464+
//
2465+
ParentLocals.append(Locals.begin(), Locals.end());
2466+
collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
2467+
return;
2468+
}
2469+
2470+
// Create a new CodeView lexical block for this lexical scope. If we've
2471+
// seen this DILexicalBlock before then the scope tree is malformed and
2472+
// we can handle this gracefully by not processing it a second time.
2473+
auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
2474+
if (!BlockInsertion.second)
2475+
return;
2476+
2477+
// Create a lexical block containing the local variables and collect the
2478+
// the lexical block information for the children.
2479+
const InsnRange &Range = Ranges.front();
2480+
assert(Range.first && Range.second);
2481+
LexicalBlock &Block = BlockInsertion.first->second;
2482+
Block.Begin = getLabelBeforeInsn(Range.first);
2483+
Block.End = getLabelAfterInsn(Range.second);
2484+
assert(Block.Begin && "missing label for scope begin");
2485+
assert(Block.End && "missing label for scope end");
2486+
Block.Name = DILB->getName();
2487+
Block.Locals = std::move(Locals);
2488+
ParentBlocks.push_back(&Block);
2489+
collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals);
2490+
}
2491+
23662492
void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
23672493
const Function &GV = MF->getFunction();
23682494
assert(FnDebugInfo.count(&GV));
23692495
assert(CurFn == FnDebugInfo[&GV].get());
23702496

23712497
collectVariableInfo(GV.getSubprogram());
23722498

2499+
// Build the lexical block structure to emit for this routine.
2500+
if (LexicalScope *CFS = LScopes.getCurrentFunctionScope())
2501+
collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals);
2502+
2503+
// Clear the scope and variable information from the map which will not be
2504+
// valid after we have finished processing this routine. This also prepares
2505+
// the map for the subsequent routine.
2506+
ScopeVariables.clear();
2507+
23732508
// Don't emit anything if we don't have any line tables.
23742509
if (!CurFn->HaveLineInfo) {
23752510
FnDebugInfo.erase(&GV);

‎llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h

+37-1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
107107
unsigned SiteFuncId = 0;
108108
};
109109

110+
// Combines information from DILexicalBlock and LexicalScope.
111+
struct LexicalBlock {
112+
SmallVector<LocalVariable, 1> Locals;
113+
SmallVector<LexicalBlock *, 1> Children;
114+
const MCSymbol *Begin;
115+
const MCSymbol *End;
116+
StringRef Name;
117+
};
118+
110119
// For each function, store a vector of labels to its instructions, as well as
111120
// to the end of the function.
112121
struct FunctionInfo {
@@ -124,6 +133,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
124133

125134
SmallVector<LocalVariable, 1> Locals;
126135

136+
std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks;
137+
138+
// Lexical blocks containing local variables.
139+
SmallVector<LexicalBlock *, 1> ChildBlocks;
140+
127141
std::vector<std::pair<MCSymbol *, MDNode *>> Annotations;
128142

129143
const MCSymbol *Begin = nullptr;
@@ -134,6 +148,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
134148
};
135149
FunctionInfo *CurFn = nullptr;
136150

151+
// Map used to seperate variables according to the lexical scope they belong
152+
// in. This is populated by recordLocalVariable() before
153+
// collectLexicalBlocks() separates the variables between the FunctionInfo
154+
// and LexicalBlocks.
155+
DenseMap<const LexicalScope *, SmallVector<LocalVariable, 1>> ScopeVariables;
156+
137157
/// The set of comdat .debug$S sections that we've seen so far. Each section
138158
/// must start with a magic version number that must only be emitted once.
139159
/// This set tracks which sections we've already opened.
@@ -258,16 +278,32 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
258278

259279
void collectVariableInfoFromMFTable(DenseSet<InlinedVariable> &Processed);
260280

281+
// Construct the lexical block tree for a routine, pruning emptpy lexical
282+
// scopes, and populate it with local variables.
283+
void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes,
284+
SmallVectorImpl<LexicalBlock *> &Blocks,
285+
SmallVectorImpl<LocalVariable> &Locals);
286+
void collectLexicalBlockInfo(LexicalScope &Scope,
287+
SmallVectorImpl<LexicalBlock *> &ParentBlocks,
288+
SmallVectorImpl<LocalVariable> &ParentLocals);
289+
261290
/// Records information about a local variable in the appropriate scope. In
262291
/// particular, locals from inlined code live inside the inlining site.
263-
void recordLocalVariable(LocalVariable &&Var, const DILocation *Loc);
292+
void recordLocalVariable(LocalVariable &&Var, const LexicalScope *LS);
264293

265294
/// Emits local variables in the appropriate order.
266295
void emitLocalVariableList(ArrayRef<LocalVariable> Locals);
267296

268297
/// Emits an S_LOCAL record and its associated defined ranges.
269298
void emitLocalVariable(const LocalVariable &Var);
270299

300+
/// Emits a sequence of lexical block scopes and their children.
301+
void emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
302+
const FunctionInfo& FI);
303+
304+
/// Emit a lexical block scope and its children.
305+
void emitLexicalBlock(const LexicalBlock &Block, const FunctionInfo& FI);
306+
271307
/// Translates the DIType to codeview if necessary and returns a type index
272308
/// for it.
273309
codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,

‎llvm/lib/MC/MCObjectStreamer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
5555
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
5656
static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
5757
const MCSymbol *Lo) {
58+
assert(Hi && Lo);
5859
if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
5960
Hi->isVariable() || Lo->isVariable())
6061
return None;
+328
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
2+
;
3+
; -- lexicablock.cxx begin ----------------------------------------------------
4+
; int main(int argc, char *argv[]) {
5+
; int localA = 1;
6+
;
7+
; { // S_BLOCK32 not emitted because it has multiple address ranges.
8+
; int localB = 2;
9+
;
10+
; if (__builtin_expect(argc != 1, 0)) { // S_BLOCK32 containing 'localC'
11+
; int localC = 3;
12+
; }
13+
; }
14+
;
15+
; { // S_BLOCK32 containing 'localD'
16+
; int localD = 4;
17+
; localA = localD;
18+
; }
19+
;
20+
; { // S_BLOCK32 not emitted
21+
; { // S_BLOCK32 containing 'localE'
22+
; int localE = 5;
23+
; localA = localE;
24+
; }
25+
; }
26+
;
27+
; { // S_BLOCK32 containing 'localF'
28+
; int localF = 6;
29+
; localA = localF;
30+
;
31+
; { // S_BLOCK32 containing 'localG'
32+
; int localG = 7;
33+
; localA = localG;
34+
; }
35+
; }
36+
;
37+
; if (localA == 7) { // S_BLOCK32 containing 'localH'
38+
; int localH = 8;
39+
; localA = localH;
40+
; }
41+
;
42+
; return localA != 8 ? -1 : 0;
43+
; }
44+
; -- lexicalblock.cxx end -----------------------------------------------------
45+
;
46+
; To regenerate the IR below:
47+
; $ clang -cc1 -triple i686-pc-windows -emit-llvm -o lexicalblock.tmp -debug-info-kind=limited -gcodeview lexicablock.cxx -O1 -disable-llvm-passes
48+
; $ opt -lower-expect -S -o lexicalblock.ll < lexicalblock.tmp
49+
;
50+
; The commands above split the lexical block containing localB and localC into
51+
; two parts, thus creating multiple ranges for the containing lexical block
52+
; without optimizing out the whole thing.
53+
;
54+
; CHECK: {{.*}}Proc{{.*}}Sym {
55+
; CHECK: DisplayName: main
56+
; CHECK: }
57+
; CHECK: LocalSym {
58+
; CHECK: VarName: argc
59+
; CHECK: }
60+
; CHECK: LocalSym {
61+
; CHECK: VarName: argv
62+
; CHECK: }
63+
; CHECK: LocalSym {
64+
; CHECK: VarName: localA
65+
; CHECK: }
66+
; CHECK: LocalSym {
67+
; CHECK: VarName: localB
68+
; CHECK: }
69+
; CHECK: BlockSym {
70+
; CHECK: Kind: S_BLOCK32 {{.*}}
71+
; CHECK: BlockName:
72+
; CHECK: }
73+
; CHECK: LocalSym {
74+
; CHECK: VarName: localC
75+
; CHECK: }
76+
; CHECK: ScopeEndSym {
77+
; CHECK: Kind: S_END {{.*}}
78+
; CHECK: }
79+
; CHECK: BlockSym {
80+
; CHECK: Kind: S_BLOCK32 {{.*}}
81+
; CHECK: BlockName:
82+
; CHECK: }
83+
; CHECK: LocalSym {
84+
; CHECK: VarName: localD
85+
; CHECK: }
86+
; CHECK: ScopeEndSym {
87+
; CHECK: Kind: S_END {{.*}}
88+
; CHECK: }
89+
; CHECK: BlockSym {
90+
; CHECK: Kind: S_BLOCK32 {{.*}}
91+
; CHECK: BlockName:
92+
; CHECK: }
93+
; CHECK: LocalSym {
94+
; CHECK: VarName: localE
95+
; CHECK: }
96+
; CHECK: ScopeEndSym {
97+
; CHECK: }
98+
; CHECK: BlockSym {
99+
; CHECK: Kind: S_BLOCK32 {{.*}}
100+
; CHECK: BlockName:
101+
; CHECK: }
102+
; CHECK: LocalSym {
103+
; CHECK: VarName: localF
104+
; CHECK: }
105+
; CHECK: BlockSym {
106+
; CHECK: Kind: S_BLOCK32 {{.*}}
107+
; CHECK: BlockName:
108+
; CHECK: }
109+
; CHECK: LocalSym {
110+
; CHECK: VarName: localG
111+
; CHECK: }
112+
; CHECK: ScopeEndSym {
113+
; CHECK: Kind: S_END {{.*}}
114+
; CHECK: }
115+
; CHECK: ScopeEndSym {
116+
; CHECK: Kind: S_END {{.*}}
117+
; CHECK: }
118+
; CHECK: BlockSym {
119+
; CHECK: Kind: S_BLOCK32 {{.*}}
120+
; CHECK: BlockName:
121+
; CHECK: }
122+
; CHECK: LocalSym {
123+
; CHECK: VarName: localH
124+
; CHECK: }
125+
; CHECK: ScopeEndSym {
126+
; CHECK: Kind: S_END {{.*}}
127+
; CHECK: }
128+
; CHECK: ProcEnd {
129+
; CHECK: }
130+
;
131+
; ModuleID = 'lexicalblock.cxx'
132+
source_filename = "lexicalblock.cxx"
133+
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
134+
target triple = "i686-pc-windows-msvc"
135+
136+
; Function Attrs: norecurse nounwind
137+
define i32 @main(i32 %argc, i8** %argv) #0 !dbg !8 {
138+
entry:
139+
%retval = alloca i32, align 4
140+
%argv.addr = alloca i8**, align 4
141+
%argc.addr = alloca i32, align 4
142+
%localA = alloca i32, align 4
143+
%localB = alloca i32, align 4
144+
%localC = alloca i32, align 4
145+
%localD = alloca i32, align 4
146+
%localE = alloca i32, align 4
147+
%localF = alloca i32, align 4
148+
%localG = alloca i32, align 4
149+
%localH = alloca i32, align 4
150+
store i32 0, i32* %retval, align 4
151+
store i8** %argv, i8*** %argv.addr, align 4, !tbaa !37
152+
call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !17, metadata !DIExpression()), !dbg !41
153+
store i32 %argc, i32* %argc.addr, align 4, !tbaa !42
154+
call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !18, metadata !DIExpression()), !dbg !41
155+
%0 = bitcast i32* %localA to i8*, !dbg !44
156+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #4, !dbg !44
157+
call void @llvm.dbg.declare(metadata i32* %localA, metadata !19, metadata !DIExpression()), !dbg !44
158+
store i32 1, i32* %localA, align 4, !dbg !44, !tbaa !42
159+
%1 = bitcast i32* %localB to i8*, !dbg !45
160+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #4, !dbg !45
161+
call void @llvm.dbg.declare(metadata i32* %localB, metadata !20, metadata !DIExpression()), !dbg !45
162+
store i32 2, i32* %localB, align 4, !dbg !45, !tbaa !42
163+
%2 = load i32, i32* %argc.addr, align 4, !dbg !46, !tbaa !42
164+
%cmp = icmp ne i32 %2, 1, !dbg !46
165+
%conv = zext i1 %cmp to i32, !dbg !46
166+
%tobool = icmp ne i32 %conv, 0, !dbg !46
167+
br i1 %tobool, label %if.then, label %if.end, !dbg !46, !prof !47
168+
169+
if.then: ; preds = %entry
170+
%3 = bitcast i32* %localC to i8*, !dbg !48
171+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %3) #4, !dbg !48
172+
call void @llvm.dbg.declare(metadata i32* %localC, metadata !22, metadata !DIExpression()), !dbg !48
173+
store i32 3, i32* %localC, align 4, !dbg !48, !tbaa !42
174+
%4 = bitcast i32* %localC to i8*, !dbg !49
175+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %4) #4, !dbg !49
176+
br label %if.end, !dbg !49
177+
178+
if.end: ; preds = %if.then, %entry
179+
%5 = bitcast i32* %localB to i8*, !dbg !50
180+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %5) #4, !dbg !50
181+
%6 = bitcast i32* %localD to i8*, !dbg !51
182+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %6) #4, !dbg !51
183+
call void @llvm.dbg.declare(metadata i32* %localD, metadata !25, metadata !DIExpression()), !dbg !51
184+
store i32 4, i32* %localD, align 4, !dbg !51, !tbaa !42
185+
%7 = load i32, i32* %localD, align 4, !dbg !52, !tbaa !42
186+
store i32 %7, i32* %localA, align 4, !dbg !52, !tbaa !42
187+
%8 = bitcast i32* %localD to i8*, !dbg !53
188+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %8) #4, !dbg !53
189+
%9 = bitcast i32* %localE to i8*, !dbg !54
190+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %9) #4, !dbg !54
191+
call void @llvm.dbg.declare(metadata i32* %localE, metadata !27, metadata !DIExpression()), !dbg !54
192+
store i32 5, i32* %localE, align 4, !dbg !54, !tbaa !42
193+
%10 = load i32, i32* %localE, align 4, !dbg !55, !tbaa !42
194+
store i32 %10, i32* %localA, align 4, !dbg !55, !tbaa !42
195+
%11 = bitcast i32* %localE to i8*, !dbg !56
196+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %11) #4, !dbg !56
197+
%12 = bitcast i32* %localF to i8*, !dbg !57
198+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %12) #4, !dbg !57
199+
call void @llvm.dbg.declare(metadata i32* %localF, metadata !30, metadata !DIExpression()), !dbg !57
200+
store i32 6, i32* %localF, align 4, !dbg !57, !tbaa !42
201+
%13 = load i32, i32* %localF, align 4, !dbg !58, !tbaa !42
202+
store i32 %13, i32* %localA, align 4, !dbg !58, !tbaa !42
203+
%14 = bitcast i32* %localG to i8*, !dbg !59
204+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %14) #4, !dbg !59
205+
call void @llvm.dbg.declare(metadata i32* %localG, metadata !32, metadata !DIExpression()), !dbg !59
206+
store i32 7, i32* %localG, align 4, !dbg !59, !tbaa !42
207+
%15 = load i32, i32* %localG, align 4, !dbg !60, !tbaa !42
208+
store i32 %15, i32* %localA, align 4, !dbg !60, !tbaa !42
209+
%16 = bitcast i32* %localG to i8*, !dbg !61
210+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %16) #4, !dbg !61
211+
%17 = bitcast i32* %localF to i8*, !dbg !62
212+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %17) #4, !dbg !62
213+
%18 = load i32, i32* %localA, align 4, !dbg !63, !tbaa !42
214+
%cmp1 = icmp eq i32 %18, 7, !dbg !63
215+
br i1 %cmp1, label %if.then2, label %if.end3, !dbg !63
216+
217+
if.then2: ; preds = %if.end
218+
%19 = bitcast i32* %localH to i8*, !dbg !64
219+
call void @llvm.lifetime.start.p0i8(i64 4, i8* %19) #4, !dbg !64
220+
call void @llvm.dbg.declare(metadata i32* %localH, metadata !34, metadata !DIExpression()), !dbg !64
221+
store i32 8, i32* %localH, align 4, !dbg !64, !tbaa !42
222+
%20 = load i32, i32* %localH, align 4, !dbg !65, !tbaa !42
223+
store i32 %20, i32* %localA, align 4, !dbg !65, !tbaa !42
224+
%21 = bitcast i32* %localH to i8*, !dbg !66
225+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %21) #4, !dbg !66
226+
br label %if.end3, !dbg !66
227+
228+
if.end3: ; preds = %if.then2, %if.end
229+
%22 = load i32, i32* %localA, align 4, !dbg !67, !tbaa !42
230+
%cmp4 = icmp ne i32 %22, 8, !dbg !67
231+
%23 = zext i1 %cmp4 to i64, !dbg !67
232+
%cond = select i1 %cmp4, i32 -1, i32 0, !dbg !67
233+
%24 = bitcast i32* %localA to i8*, !dbg !68
234+
call void @llvm.lifetime.end.p0i8(i64 4, i8* %24) #4, !dbg !68
235+
ret i32 %cond, !dbg !67
236+
}
237+
238+
; Function Attrs: nounwind readnone speculatable
239+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
240+
241+
; Function Attrs: argmemonly nounwind
242+
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #2
243+
244+
; Function Attrs: nounwind readnone
245+
declare i32 @llvm.expect.i32(i32, i32) #3
246+
247+
; Function Attrs: argmemonly nounwind
248+
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #2
249+
250+
attributes #0 = { norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
251+
attributes #1 = { nounwind readnone speculatable }
252+
attributes #2 = { argmemonly nounwind }
253+
attributes #3 = { nounwind readnone }
254+
attributes #4 = { nounwind }
255+
256+
!llvm.dbg.cu = !{!0}
257+
!llvm.module.flags = !{!3, !4, !5, !6}
258+
!llvm.ident = !{!7}
259+
260+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 7.0.0 (trunk)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
261+
!1 = !DIFile(filename: "<stdin>", directory: "C:/path/to/directory", checksumkind: CSK_MD5, checksum: "169b810b4f895de9a9e19d8d0634af5d")
262+
!2 = !{}
263+
!3 = !{i32 1, !"NumRegisterParameters", i32 0}
264+
!4 = !{i32 2, !"CodeView", i32 1}
265+
!5 = !{i32 2, !"Debug Info Version", i32 3}
266+
!6 = !{i32 1, !"wchar_size", i32 2}
267+
!7 = !{!"clang version 7.0.0 (trunk)"}
268+
!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !16)
269+
!9 = !DIFile(filename: "lexicalblock.cxx", directory: "C:/path/to/directory", checksumkind: CSK_MD5, checksum: "169b810b4f895de9a9e19d8d0634af5d")
270+
!10 = !DISubroutineType(types: !11)
271+
!11 = !{!12, !12, !13}
272+
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
273+
!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 32)
274+
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 32)
275+
!15 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
276+
!16 = !{!17, !18, !19, !20, !22, !25, !27, !30, !32, !34}
277+
!17 = !DILocalVariable(name: "argv", arg: 2, scope: !8, file: !9, line: 1, type: !13)
278+
!18 = !DILocalVariable(name: "argc", arg: 1, scope: !8, file: !9, line: 1, type: !12)
279+
!19 = !DILocalVariable(name: "localA", scope: !8, file: !9, line: 2, type: !12)
280+
!20 = !DILocalVariable(name: "localB", scope: !21, file: !9, line: 5, type: !12)
281+
!21 = distinct !DILexicalBlock(scope: !8, file: !9, line: 4)
282+
!22 = !DILocalVariable(name: "localC", scope: !23, file: !9, line: 8, type: !12)
283+
!23 = distinct !DILexicalBlock(scope: !24, file: !9, line: 7)
284+
!24 = distinct !DILexicalBlock(scope: !21, file: !9, line: 7)
285+
!25 = !DILocalVariable(name: "localD", scope: !26, file: !9, line: 13, type: !12)
286+
!26 = distinct !DILexicalBlock(scope: !8, file: !9, line: 12)
287+
!27 = !DILocalVariable(name: "localE", scope: !28, file: !9, line: 19, type: !12)
288+
!28 = distinct !DILexicalBlock(scope: !29, file: !9, line: 18)
289+
!29 = distinct !DILexicalBlock(scope: !8, file: !9, line: 17)
290+
!30 = !DILocalVariable(name: "localF", scope: !31, file: !9, line: 25, type: !12)
291+
!31 = distinct !DILexicalBlock(scope: !8, file: !9, line: 24)
292+
!32 = !DILocalVariable(name: "localG", scope: !33, file: !9, line: 29, type: !12)
293+
!33 = distinct !DILexicalBlock(scope: !31, file: !9, line: 28)
294+
!34 = !DILocalVariable(name: "localH", scope: !35, file: !9, line: 35, type: !12)
295+
!35 = distinct !DILexicalBlock(scope: !36, file: !9, line: 34)
296+
!36 = distinct !DILexicalBlock(scope: !8, file: !9, line: 34)
297+
!37 = !{!38, !38, i64 0}
298+
!38 = !{!"any pointer", !39, i64 0}
299+
!39 = !{!"omnipotent char", !40, i64 0}
300+
!40 = !{!"Simple C++ TBAA"}
301+
!41 = !DILocation(line: 1, scope: !8)
302+
!42 = !{!43, !43, i64 0}
303+
!43 = !{!"int", !39, i64 0}
304+
!44 = !DILocation(line: 2, scope: !8)
305+
!45 = !DILocation(line: 5, scope: !21)
306+
!46 = !DILocation(line: 7, scope: !21)
307+
!47 = !{!"branch_weights", i32 1, i32 2000}
308+
!48 = !DILocation(line: 8, scope: !23)
309+
!49 = !DILocation(line: 9, scope: !23)
310+
!50 = !DILocation(line: 10, scope: !21)
311+
!51 = !DILocation(line: 13, scope: !26)
312+
!52 = !DILocation(line: 14, scope: !26)
313+
!53 = !DILocation(line: 15, scope: !26)
314+
!54 = !DILocation(line: 19, scope: !28)
315+
!55 = !DILocation(line: 20, scope: !28)
316+
!56 = !DILocation(line: 21, scope: !28)
317+
!57 = !DILocation(line: 25, scope: !31)
318+
!58 = !DILocation(line: 26, scope: !31)
319+
!59 = !DILocation(line: 29, scope: !33)
320+
!60 = !DILocation(line: 30, scope: !33)
321+
!61 = !DILocation(line: 31, scope: !33)
322+
!62 = !DILocation(line: 32, scope: !31)
323+
!63 = !DILocation(line: 34, scope: !8)
324+
!64 = !DILocation(line: 35, scope: !35)
325+
!65 = !DILocation(line: 36, scope: !35)
326+
!66 = !DILocation(line: 37, scope: !35)
327+
!67 = !DILocation(line: 39, scope: !8)
328+
!68 = !DILocation(line: 40, scope: !8)

‎llvm/test/DebugInfo/COFF/register-variables.ll

+7-7
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@
6161
; ASM: .cv_def_range .Lfunc_begin0 [[p_ecx_esi]], "A\021\022\000\000\000"
6262
; ASM: .cv_def_range [[p_ecx_esi]] [[func_end]], "A\021\027\000\000\000"
6363
; ASM: .short 4414 # Record kind: S_LOCAL
64-
; ASM: .asciz "a"
65-
; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000"
66-
; ASM: .short 4414 # Record kind: S_LOCAL
6764
; ASM: .asciz "c"
6865
; ASM: .cv_def_range [[after_getint]] [[after_je]], "A\021\021\000\000\000"
6966
; ASM: .short 4414 # Record kind: S_LOCAL
67+
; ASM: .asciz "a"
68+
; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000"
69+
; ASM: .short 4414 # Record kind: S_LOCAL
7070
; ASM: .asciz "b"
7171
; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], "A\021\021\000\000\000"
7272

@@ -111,28 +111,28 @@
111111
; OBJ: Type: int (0x74)
112112
; OBJ: Flags [ (0x0)
113113
; OBJ: ]
114-
; OBJ: VarName: a
114+
; OBJ: VarName: c
115115
; OBJ: }
116116
; OBJ: DefRangeRegisterSym {
117117
; OBJ: Register: EAX (0x11)
118118
; OBJ: LocalVariableAddrRange {
119119
; OBJ: OffsetStart: .text+0xC
120120
; OBJ: ISectStart: 0x0
121-
; OBJ: Range: 0x7
121+
; OBJ: Range: 0x4
122122
; OBJ: }
123123
; OBJ: }
124124
; OBJ: LocalSym {
125125
; OBJ: Type: int (0x74)
126126
; OBJ: Flags [ (0x0)
127127
; OBJ: ]
128-
; OBJ: VarName: c
128+
; OBJ: VarName: a
129129
; OBJ: }
130130
; OBJ: DefRangeRegisterSym {
131131
; OBJ: Register: EAX (0x11)
132132
; OBJ: LocalVariableAddrRange {
133133
; OBJ: OffsetStart: .text+0xC
134134
; OBJ: ISectStart: 0x0
135-
; OBJ: Range: 0x4
135+
; OBJ: Range: 0x7
136136
; OBJ: }
137137
; OBJ: }
138138
; OBJ: LocalSym {

0 commit comments

Comments
 (0)
Please sign in to comment.