Skip to content

Commit

Permalink
Merge pull request #106 from vext01/call-conflation
Browse files Browse the repository at this point in the history
Don't conflate a call with an unknown target with an indirect call.
  • Loading branch information
ltratt authored Nov 27, 2023
2 parents 668b215 + 4796e16 commit 9813084
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 7 deletions.
6 changes: 3 additions & 3 deletions llvm/include/llvm/CodeGen/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,10 @@ class AsmPrinter : public MachineFunctionPass {
/// - A symbol marking the call instruction.
/// - A symbol marking the return address of the call (if it were to return
/// by conventional means)
/// - If it's a direct call, a symbol marking the target of the call, or
/// `nullptr` if the call is indirect.
/// - A symbol marking the target of the call, if known.
/// - A boolean indicating if it's a direct call (true) or not (false).
std::map<const MachineBasicBlock *,
SmallVector<std::tuple<MCSymbol *, MCSymbol *, MCSymbol *>>>
SmallVector<std::tuple<MCSymbol *, MCSymbol *, MCSymbol *, bool>>>
YkCallMarkerSyms;

protected:
Expand Down
29 changes: 25 additions & 4 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
}
}
// Emit the number of corresponding BasicBlocks.
OutStreamer->AddComment("num corresponding blocks");
OutStreamer->emitULEB128IntValue(CorrBBs.size());
// Emit the corresponding block indices.
for (auto CorrBB : CorrBBs) {
Expand All @@ -1513,6 +1514,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
}
if (!Found)
OutContext.reportError(SMLoc(), "Couldn't find the block's index");
OutStreamer->AddComment("corresponding block");
OutStreamer->emitULEB128IntValue(I);
}

Expand All @@ -1524,18 +1526,25 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
// compute the distance from the start of the block and use uleb128
// encoding.
const size_t NumCalls = YkCallMarkerSyms[&MBB].size();
OutStreamer->AddComment("num calls");
OutStreamer->emitULEB128IntValue(NumCalls);
for (auto Tup : YkCallMarkerSyms[&MBB]) {
// Emit address of the call instruction.
OutStreamer->AddComment("call offset");
OutStreamer->emitSymbolValue(std::get<0>(Tup), getPointerSize());
// Emit the return address of the call.
OutStreamer->AddComment("return offset");
OutStreamer->emitSymbolValue(std::get<1>(Tup), getPointerSize());
// Emit address of target if known, or 0.
OutStreamer->AddComment("target offset");
MCSymbol *Target = std::get<2>(Tup);
if (Target)
OutStreamer->emitSymbolValue(Target, getPointerSize());
else
OutStreamer->emitIntValue(0, getPointerSize());
// Emit whether it's a direct call.
OutStreamer->AddComment("direct?");
OutStreamer->emitIntValue(std::get<3>(Tup), 1);
}

// Emit successor information.
Expand Down Expand Up @@ -2009,14 +2018,25 @@ void AsmPrinter::emitFunctionBody() {
// If it's direct, then we know the call's target from the first
// operand alone.
const MachineOperand CallOpnd = MI.getOperand(0);
std::optional<bool> DirectCall;
MCSymbol *CallTargetSym = nullptr;
if (CallOpnd.isGlobal()) {
// Direct call.
// Global: direct call, known target.
DirectCall = true;
CallTargetSym = getSymbol(CallOpnd.getGlobal());
} else if (CallOpnd.isMCSymbol()) {
// Also a direct call.
// MCSymbol: direct call, known target.
DirectCall = true;
CallTargetSym = CallOpnd.getMCSymbol();
} // Otherwise it's an indirect call.
} else if (CallOpnd.isSymbol()) {
// Symbol: direct call, unknown target.
DirectCall = true;
// CallTargetSym remains null.
} else {
// Otherwise: indirect call, therefore unknown target.
DirectCall = false;
// CallTargetSym remains null.
}

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

assert(YkCallMarkerSyms.find(&MBB) != YkCallMarkerSyms.end());
YkCallMarkerSyms[&MBB].push_back({YkPreCallSym, YkPostCallSym, CallTargetSym});
YkCallMarkerSyms[&MBB].push_back({
YkPreCallSym, YkPostCallSym, CallTargetSym, DirectCall.value()});
} else {
emitInstruction(&MI);
}
Expand Down
51 changes: 51 additions & 0 deletions llvm/test/CodeGen/X86/yk-basic-block-sections.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
; RUN: llc < %s -mtriple=x86_64 -function-sections -basic-block-sections=labels -yk-extended-llvmbbaddrmap-section -emulated-tls | FileCheck %s

@G = thread_local global i32 0

declare void @foo(ptr)

define void @bar() noinline {
ret void
}

declare void @baz()

define dso_local void @the_func(ptr %0) {
; Note that the emulated TLS access will make an extra direct call with an
; unknown target.
call void @foo(ptr @G)
call void @bar()
call void %0()
ret void
}

; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text.the_func{{$}}
; CHECK-NEXT: .byte 2 # version
; CHECK-NEXT: .byte 0 # feature
; CHECK-NEXT: .quad .Lfunc_begin1 # function address
; CHECK-NEXT: .byte 1 # number of basic blocks
; CHECK-NEXT: .byte 0 # BB id
; CHECK-NEXT: .uleb128 .Lfunc_begin1-.Lfunc_begin1
; CHECK-NEXT: .uleb128 .LBB_END1_0-.Lfunc_begin1
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 1 # num corresponding blocks
; CHECK-NEXT: .byte 0 # corresponding block
; CHECK-NEXT: .byte 4 # num calls
; CHECK-NEXT: .quad .Lyk_precall0 # call offset
; CHECK-NEXT: .quad .Lyk_postcall0 # return offset
; CHECK-NEXT: .quad 0 # target offset
; CHECK-NEXT: .byte 1 # direct?
; CHECK-NEXT: .quad .Lyk_precall1 # call offset
; CHECK-NEXT: .quad .Lyk_postcall1 # return offset
; CHECK-NEXT: .quad foo # target offset
; CHECK-NEXT: .byte 1 # direct?
; CHECK-NEXT: .quad .Lyk_precall2 # call offset
; CHECK-NEXT: .quad .Lyk_postcall2 # return offset
; CHECK-NEXT: .quad bar # target offset
; CHECK-NEXT: .byte 1 # direct?
; CHECK-NEXT: .quad .Lyk_precall3 # call offset
; CHECK-NEXT: .quad .Lyk_postcall3 # return offset
; CHECK-NEXT: .quad 0 # target offset
; CHECK-NEXT: .byte 0 # direct?

; FIXME: test our other extensions to the blockmap.

0 comments on commit 9813084

Please sign in to comment.