Skip to content

Commit 9813084

Browse files
authored
Merge pull request rust-lang#106 from vext01/call-conflation
Don't conflate a call with an unknown target with an indirect call.
2 parents 668b215 + 4796e16 commit 9813084

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,10 @@ class AsmPrinter : public MachineFunctionPass {
254254
/// - A symbol marking the call instruction.
255255
/// - A symbol marking the return address of the call (if it were to return
256256
/// by conventional means)
257-
/// - If it's a direct call, a symbol marking the target of the call, or
258-
/// `nullptr` if the call is indirect.
257+
/// - A symbol marking the target of the call, if known.
258+
/// - A boolean indicating if it's a direct call (true) or not (false).
259259
std::map<const MachineBasicBlock *,
260-
SmallVector<std::tuple<MCSymbol *, MCSymbol *, MCSymbol *>>>
260+
SmallVector<std::tuple<MCSymbol *, MCSymbol *, MCSymbol *, bool>>>
261261
YkCallMarkerSyms;
262262

263263
protected:

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
14981498
}
14991499
}
15001500
// Emit the number of corresponding BasicBlocks.
1501+
OutStreamer->AddComment("num corresponding blocks");
15011502
OutStreamer->emitULEB128IntValue(CorrBBs.size());
15021503
// Emit the corresponding block indices.
15031504
for (auto CorrBB : CorrBBs) {
@@ -1513,6 +1514,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
15131514
}
15141515
if (!Found)
15151516
OutContext.reportError(SMLoc(), "Couldn't find the block's index");
1517+
OutStreamer->AddComment("corresponding block");
15161518
OutStreamer->emitULEB128IntValue(I);
15171519
}
15181520

@@ -1524,18 +1526,25 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
15241526
// compute the distance from the start of the block and use uleb128
15251527
// encoding.
15261528
const size_t NumCalls = YkCallMarkerSyms[&MBB].size();
1529+
OutStreamer->AddComment("num calls");
15271530
OutStreamer->emitULEB128IntValue(NumCalls);
15281531
for (auto Tup : YkCallMarkerSyms[&MBB]) {
15291532
// Emit address of the call instruction.
1533+
OutStreamer->AddComment("call offset");
15301534
OutStreamer->emitSymbolValue(std::get<0>(Tup), getPointerSize());
15311535
// Emit the return address of the call.
1536+
OutStreamer->AddComment("return offset");
15321537
OutStreamer->emitSymbolValue(std::get<1>(Tup), getPointerSize());
15331538
// Emit address of target if known, or 0.
1539+
OutStreamer->AddComment("target offset");
15341540
MCSymbol *Target = std::get<2>(Tup);
15351541
if (Target)
15361542
OutStreamer->emitSymbolValue(Target, getPointerSize());
15371543
else
15381544
OutStreamer->emitIntValue(0, getPointerSize());
1545+
// Emit whether it's a direct call.
1546+
OutStreamer->AddComment("direct?");
1547+
OutStreamer->emitIntValue(std::get<3>(Tup), 1);
15391548
}
15401549

15411550
// Emit successor information.
@@ -2009,14 +2018,25 @@ void AsmPrinter::emitFunctionBody() {
20092018
// If it's direct, then we know the call's target from the first
20102019
// operand alone.
20112020
const MachineOperand CallOpnd = MI.getOperand(0);
2021+
std::optional<bool> DirectCall;
20122022
MCSymbol *CallTargetSym = nullptr;
20132023
if (CallOpnd.isGlobal()) {
2014-
// Direct call.
2024+
// Global: direct call, known target.
2025+
DirectCall = true;
20152026
CallTargetSym = getSymbol(CallOpnd.getGlobal());
20162027
} else if (CallOpnd.isMCSymbol()) {
2017-
// Also a direct call.
2028+
// MCSymbol: direct call, known target.
2029+
DirectCall = true;
20182030
CallTargetSym = CallOpnd.getMCSymbol();
2019-
} // Otherwise it's an indirect call.
2031+
} else if (CallOpnd.isSymbol()) {
2032+
// Symbol: direct call, unknown target.
2033+
DirectCall = true;
2034+
// CallTargetSym remains null.
2035+
} else {
2036+
// Otherwise: indirect call, therefore unknown target.
2037+
DirectCall = false;
2038+
// CallTargetSym remains null.
2039+
}
20202040

20212041
// Ensure we are only working with near calls. This matters because
20222042
// Intel PT optimises near calls, and it simplifies our implementation
@@ -2025,7 +2045,8 @@ void AsmPrinter::emitFunctionBody() {
20252045
assert(!MF->getSubtarget().getInstrInfo()->isFarCall(MI));
20262046

20272047
assert(YkCallMarkerSyms.find(&MBB) != YkCallMarkerSyms.end());
2028-
YkCallMarkerSyms[&MBB].push_back({YkPreCallSym, YkPostCallSym, CallTargetSym});
2048+
YkCallMarkerSyms[&MBB].push_back({
2049+
YkPreCallSym, YkPostCallSym, CallTargetSym, DirectCall.value()});
20292050
} else {
20302051
emitInstruction(&MI);
20312052
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; RUN: llc < %s -mtriple=x86_64 -function-sections -basic-block-sections=labels -yk-extended-llvmbbaddrmap-section -emulated-tls | FileCheck %s
2+
3+
@G = thread_local global i32 0
4+
5+
declare void @foo(ptr)
6+
7+
define void @bar() noinline {
8+
ret void
9+
}
10+
11+
declare void @baz()
12+
13+
define dso_local void @the_func(ptr %0) {
14+
; Note that the emulated TLS access will make an extra direct call with an
15+
; unknown target.
16+
call void @foo(ptr @G)
17+
call void @bar()
18+
call void %0()
19+
ret void
20+
}
21+
22+
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text.the_func{{$}}
23+
; CHECK-NEXT: .byte 2 # version
24+
; CHECK-NEXT: .byte 0 # feature
25+
; CHECK-NEXT: .quad .Lfunc_begin1 # function address
26+
; CHECK-NEXT: .byte 1 # number of basic blocks
27+
; CHECK-NEXT: .byte 0 # BB id
28+
; CHECK-NEXT: .uleb128 .Lfunc_begin1-.Lfunc_begin1
29+
; CHECK-NEXT: .uleb128 .LBB_END1_0-.Lfunc_begin1
30+
; CHECK-NEXT: .byte 1
31+
; CHECK-NEXT: .byte 1 # num corresponding blocks
32+
; CHECK-NEXT: .byte 0 # corresponding block
33+
; CHECK-NEXT: .byte 4 # num calls
34+
; CHECK-NEXT: .quad .Lyk_precall0 # call offset
35+
; CHECK-NEXT: .quad .Lyk_postcall0 # return offset
36+
; CHECK-NEXT: .quad 0 # target offset
37+
; CHECK-NEXT: .byte 1 # direct?
38+
; CHECK-NEXT: .quad .Lyk_precall1 # call offset
39+
; CHECK-NEXT: .quad .Lyk_postcall1 # return offset
40+
; CHECK-NEXT: .quad foo # target offset
41+
; CHECK-NEXT: .byte 1 # direct?
42+
; CHECK-NEXT: .quad .Lyk_precall2 # call offset
43+
; CHECK-NEXT: .quad .Lyk_postcall2 # return offset
44+
; CHECK-NEXT: .quad bar # target offset
45+
; CHECK-NEXT: .byte 1 # direct?
46+
; CHECK-NEXT: .quad .Lyk_precall3 # call offset
47+
; CHECK-NEXT: .quad .Lyk_postcall3 # return offset
48+
; CHECK-NEXT: .quad 0 # target offset
49+
; CHECK-NEXT: .byte 0 # direct?
50+
51+
; FIXME: test our other extensions to the blockmap.

0 commit comments

Comments
 (0)