Skip to content

Commit 6d9b075

Browse files
committed
[MC] Allow .pushsection between .cfi_startproc/.cfi_endproc
This follows the behavior of gnu assemblers. This is useful when writing inline assembly. Differential Revision: https://reviews.llvm.org/D141893
1 parent 155e0cf commit 6d9b075

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ class MCStreamer {
214214
std::unique_ptr<MCTargetStreamer> TargetStreamer;
215215

216216
std::vector<MCDwarfFrameInfo> DwarfFrameInfos;
217+
// This is a pair of index into DwarfFrameInfos and the MCSection associated
218+
// with the frame. Note, we use an index instead of an iterator because they
219+
// can be invalidated in std::vector.
220+
SmallVector<std::pair<size_t, MCSection *>, 1> FrameInfoStack;
217221
MCDwarfFrameInfo *getCurrentDwarfFrameInfo();
218222

219223
/// Similar to DwarfFrameInfos, but for SEH unwind info. Chained frames may

llvm/lib/MC/MCStreamer.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) {
278278
}
279279

280280
bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
281-
return !DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End;
281+
return !FrameInfoStack.empty();
282282
}
283283

284284
MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
@@ -288,7 +288,7 @@ MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
288288
".cfi_startproc and .cfi_endproc directives");
289289
return nullptr;
290290
}
291-
return &DwarfFrameInfos.back();
291+
return &DwarfFrameInfos[FrameInfoStack.back().first];
292292
}
293293

294294
bool MCStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,
@@ -445,7 +445,8 @@ void MCStreamer::emitConditionalAssignment(MCSymbol *Symbol,
445445
void MCStreamer::emitCFISections(bool EH, bool Debug) {}
446446

447447
void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
448-
if (hasUnfinishedDwarfFrameInfo())
448+
if (!FrameInfoStack.empty() &&
449+
getCurrentSectionOnly() == FrameInfoStack.back().second)
449450
return getContext().reportError(
450451
Loc, "starting new .cfi frame before finishing the previous one");
451452

@@ -464,6 +465,7 @@ void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
464465
}
465466
}
466467

468+
FrameInfoStack.emplace_back(DwarfFrameInfos.size(), getCurrentSectionOnly());
467469
DwarfFrameInfos.push_back(Frame);
468470
}
469471

@@ -475,6 +477,7 @@ void MCStreamer::emitCFIEndProc() {
475477
if (!CurFrame)
476478
return;
477479
emitCFIEndProcImpl(*CurFrame);
480+
FrameInfoStack.pop_back();
478481
}
479482

480483
void MCStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: llvm-mc -filetype=obj -triple x86_64-linux %s -o - | llvm-dwarfdump --eh-frame - | FileCheck %s
2+
3+
.section .text.a, "ax", %progbits
4+
.cfi_startproc
5+
.cfi_def_cfa %rsp, 0
6+
7+
.pushsection .text.b, "ax", %progbits
8+
.cfi_startproc simple
9+
.cfi_def_cfa %rsp, 8
10+
nop
11+
ret
12+
13+
.pushsection .text.c, "ax", %progbits
14+
.cfi_startproc simple
15+
.cfi_def_cfa %rsp, 16
16+
nop
17+
nop
18+
ret
19+
.cfi_endproc
20+
.popsection
21+
22+
.cfi_endproc
23+
.popsection
24+
25+
.pushsection .text.d, "ax", %progbits
26+
.cfi_startproc simple
27+
.cfi_def_cfa %rsp, 24
28+
nop
29+
nop
30+
nop
31+
ret
32+
.cfi_endproc
33+
.popsection
34+
35+
ret
36+
.cfi_endproc
37+
38+
// CHECK: pc=00000000...00000001
39+
// CHECK: RSP +0
40+
// CHECK: pc=00000000...00000002
41+
// CHECK: RSP +8
42+
// CHECK: pc=00000000...00000003
43+
// CHECK: RSP +16
44+
// CHECK: pc=00000000...00000004
45+
// CHECK: RSP +24

0 commit comments

Comments
 (0)