Skip to content

Commit b27b0ed

Browse files
authored
Merge branch 'main' into vplan-simple-scalar-phi-recipe
2 parents ae79f52 + c4d656a commit b27b0ed

File tree

707 files changed

+31646
-15357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

707 files changed

+31646
-15357
lines changed

.github/workflows/libcxx-build-and-test.yaml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,6 @@ concurrency:
3333
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
3434
cancel-in-progress: true
3535

36-
37-
env:
38-
# LLVM POST-BRANCH bump version
39-
# LLVM POST-BRANCH add compiler test for ToT - 1, e.g. "Clang 17"
40-
# LLVM RELEASE bump remove compiler ToT - 3, e.g. "Clang 15"
41-
LLVM_HEAD_VERSION: "19" # Used compiler, update POST-BRANCH.
42-
LLVM_PREVIOUS_VERSION: "18"
43-
LLVM_OLDEST_VERSION: "17"
44-
GCC_STABLE_VERSION: "13"
45-
LLVM_SYMBOLIZER_PATH: "/usr/bin/llvm-symbolizer-19"
46-
CLANG_CRASH_DIAGNOSTICS_DIR: "crash_diagnostics"
47-
4836
jobs:
4937
stage1:
5038
if: github.repository_owner == 'llvm'

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,11 @@ class BinaryFunction {
527527
/// fragment of the function.
528528
SmallVector<MCSymbol *, 0> LSDASymbols;
529529

530+
/// Each function fragment may have another fragment containing all landing
531+
/// pads for it. If that's the case, the LP fragment will be stored in the
532+
/// vector below with indexing starting with the main fragment.
533+
SmallVector<std::optional<FragmentNum>, 0> LPFragments;
534+
530535
/// Map to discover which CFIs are attached to a given instruction offset.
531536
/// Maps an instruction offset into a FrameInstructions offset.
532537
/// This is only relevant to the buildCFG phase and is discarded afterwards.
@@ -1885,6 +1890,42 @@ class BinaryFunction {
18851890
return LSDASymbols[F.get()];
18861891
}
18871892

1893+
/// If all landing pads for the function fragment \p F are located in fragment
1894+
/// \p LPF, designate \p LPF as a landing-pad fragment for \p F. Passing
1895+
/// std::nullopt in LPF, means that landing pads for \p F are located in more
1896+
/// than one fragment.
1897+
void setLPFragment(const FragmentNum F, std::optional<FragmentNum> LPF) {
1898+
if (F.get() >= LPFragments.size())
1899+
LPFragments.resize(F.get() + 1);
1900+
1901+
LPFragments[F.get()] = LPF;
1902+
}
1903+
1904+
/// If function fragment \p F has a designated landing pad fragment, i.e. a
1905+
/// fragment that contains all landing pads for throwers in \p F, then return
1906+
/// that landing pad fragment number. If \p F does not need landing pads,
1907+
/// return \p F. Return nullptr if landing pads for \p F are scattered among
1908+
/// several function fragments.
1909+
std::optional<FragmentNum> getLPFragment(const FragmentNum F) {
1910+
if (!isSplit()) {
1911+
assert(F == FragmentNum::main() && "Invalid fragment number");
1912+
return FragmentNum::main();
1913+
}
1914+
1915+
if (F.get() >= LPFragments.size())
1916+
return std::nullopt;
1917+
1918+
return LPFragments[F.get()];
1919+
}
1920+
1921+
/// Return a symbol corresponding to a landing pad fragment for fragment \p F.
1922+
/// See getLPFragment().
1923+
MCSymbol *getLPStartSymbol(const FragmentNum F) {
1924+
if (std::optional<FragmentNum> LPFragment = getLPFragment(F))
1925+
return getSymbol(*LPFragment);
1926+
return nullptr;
1927+
}
1928+
18881929
void setOutputDataAddress(uint64_t Address) { OutputDataOffset = Address; }
18891930

18901931
uint64_t getOutputDataAddress() const { return OutputDataOffset; }

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class BinaryEmitter {
140140

141141
void emitCFIInstruction(const MCCFIInstruction &Inst) const;
142142

143-
/// Emit exception handling ranges for the function.
143+
/// Emit exception handling ranges for the function fragment.
144144
void emitLSDA(BinaryFunction &BF, const FunctionFragment &FF);
145145

146146
/// Emit line number information corresponding to \p NewLoc. \p PrevLoc
@@ -915,17 +915,29 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
915915
// Emit the LSDA header.
916916

917917
// If LPStart is omitted, then the start of the FDE is used as a base for
918-
// landing pad displacements. Then, if a cold fragment starts with a landing
919-
// pad, this means that the first landing pad offset will be 0. However, C++
920-
// runtime treats 0 as if there is no landing pad present, thus we *must* emit
921-
// non-zero offsets for all valid LPs.
918+
// landing pad displacements. Then, if a cold fragment starts with
919+
// a landing pad, this means that the first landing pad offset will be 0.
920+
// However, C++ runtime will treat 0 as if there is no landing pad, thus we
921+
// cannot emit LP offset as 0.
922922
//
923923
// As a solution, for fixed-address binaries we set LPStart to 0, and for
924-
// position-independent binaries we set LP start to FDE start minus one byte
925-
// for FDEs that start with a landing pad.
926-
const bool NeedsLPAdjustment = !FF.empty() && FF.front()->isLandingPad();
924+
// position-independent binaries we offset LP start by one byte.
925+
bool NeedsLPAdjustment = false;
927926
std::function<void(const MCSymbol *)> emitLandingPad;
928-
if (BC.HasFixedLoadAddress) {
927+
928+
// Check if there's a symbol associated with a landing pad fragment.
929+
const MCSymbol *LPStartSymbol = BF.getLPStartSymbol(FF.getFragmentNum());
930+
if (!LPStartSymbol) {
931+
// Since landing pads are not in the same fragment, we fall back to emitting
932+
// absolute addresses for this FDE.
933+
if (opts::Verbosity >= 2) {
934+
BC.outs() << "BOLT-INFO: falling back to generating absolute-address "
935+
<< "exception ranges for " << BF << '\n';
936+
}
937+
938+
assert(BC.HasFixedLoadAddress &&
939+
"Cannot emit absolute-address landing pads for PIE/DSO");
940+
929941
Streamer.emitIntValue(dwarf::DW_EH_PE_udata4, 1); // LPStart format
930942
Streamer.emitIntValue(0, 4); // LPStart
931943
emitLandingPad = [&](const MCSymbol *LPSymbol) {
@@ -935,17 +947,23 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
935947
Streamer.emitIntValue(0, 4);
936948
};
937949
} else {
938-
if (NeedsLPAdjustment) {
939-
// Use relative LPStart format and emit LPStart as [SymbolStart - 1].
950+
std::optional<FragmentNum> LPFN = BF.getLPFragment(FF.getFragmentNum());
951+
const FunctionFragment &LPFragment = BF.getLayout().getFragment(*LPFN);
952+
NeedsLPAdjustment =
953+
(!LPFragment.empty() && LPFragment.front()->isLandingPad());
954+
955+
// Emit LPStart encoding and optionally LPStart.
956+
if (NeedsLPAdjustment || LPStartSymbol != StartSymbol) {
940957
Streamer.emitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1);
941958
MCSymbol *DotSymbol = BC.Ctx->createTempSymbol("LPBase");
942959
Streamer.emitLabel(DotSymbol);
943960

944961
const MCExpr *LPStartExpr = MCBinaryExpr::createSub(
945-
MCSymbolRefExpr::create(StartSymbol, *BC.Ctx),
962+
MCSymbolRefExpr::create(LPStartSymbol, *BC.Ctx),
946963
MCSymbolRefExpr::create(DotSymbol, *BC.Ctx), *BC.Ctx);
947-
LPStartExpr = MCBinaryExpr::createSub(
948-
LPStartExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx);
964+
if (NeedsLPAdjustment)
965+
LPStartExpr = MCBinaryExpr::createSub(
966+
LPStartExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx);
949967
Streamer.emitValue(LPStartExpr, 4);
950968
} else {
951969
// DW_EH_PE_omit means FDE start (StartSymbol) will be used as LPStart.
@@ -955,7 +973,7 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
955973
if (LPSymbol) {
956974
const MCExpr *LPOffsetExpr = MCBinaryExpr::createSub(
957975
MCSymbolRefExpr::create(LPSymbol, *BC.Ctx),
958-
MCSymbolRefExpr::create(StartSymbol, *BC.Ctx), *BC.Ctx);
976+
MCSymbolRefExpr::create(LPStartSymbol, *BC.Ctx), *BC.Ctx);
959977
if (NeedsLPAdjustment)
960978
LPOffsetExpr = MCBinaryExpr::createAdd(
961979
LPOffsetExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx);
@@ -978,7 +996,7 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
978996

979997
// Emit encoding of entries in the call site table. The format is used for the
980998
// call site start, length, and corresponding landing pad.
981-
if (BC.HasFixedLoadAddress)
999+
if (!LPStartSymbol)
9821000
Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1);
9831001
else
9841002
Streamer.emitIntValue(dwarf::DW_EH_PE_uleb128, 1);
@@ -998,7 +1016,7 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
9981016

9991017
// Start of the range is emitted relative to the start of current
10001018
// function split part.
1001-
if (BC.HasFixedLoadAddress) {
1019+
if (!LPStartSymbol) {
10021020
Streamer.emitAbsoluteSymbolDiff(BeginLabel, StartSymbol, 4);
10031021
Streamer.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
10041022
} else {

bolt/lib/Passes/SplitFunctions.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,47 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
901901
// have to be placed in the same fragment. When we split them, create
902902
// trampoline landing pads that will redirect the execution to real LPs.
903903
TrampolineSetType Trampolines;
904-
if (!BC.HasFixedLoadAddress && BF.hasEHRanges() && BF.isSplit())
905-
Trampolines = createEHTrampolines(BF);
904+
if (BF.hasEHRanges() && BF.isSplit()) {
905+
// If all landing pads for this fragment are grouped in one (potentially
906+
// different) fragment, we can set LPStart to the start of that fragment
907+
// and avoid trampoline code.
908+
bool NeedsTrampolines = false;
909+
for (FunctionFragment &FF : BF.getLayout().fragments()) {
910+
// Vector of fragments that contain landing pads for this fragment.
911+
SmallVector<FragmentNum, 4> LandingPadFragments;
912+
for (const BinaryBasicBlock *BB : FF)
913+
for (const BinaryBasicBlock *LPB : BB->landing_pads())
914+
LandingPadFragments.push_back(LPB->getFragmentNum());
915+
916+
// Eliminate duplicate entries from the vector.
917+
llvm::sort(LandingPadFragments);
918+
auto Last = llvm::unique(LandingPadFragments);
919+
LandingPadFragments.erase(Last, LandingPadFragments.end());
920+
921+
if (LandingPadFragments.size() == 0) {
922+
// If the fragment has no landing pads, we can safely set itself as its
923+
// landing pad fragment.
924+
BF.setLPFragment(FF.getFragmentNum(), FF.getFragmentNum());
925+
} else if (LandingPadFragments.size() == 1) {
926+
BF.setLPFragment(FF.getFragmentNum(), LandingPadFragments.front());
927+
} else {
928+
if (!BC.HasFixedLoadAddress) {
929+
NeedsTrampolines = true;
930+
break;
931+
} else {
932+
BF.setLPFragment(FF.getFragmentNum(), std::nullopt);
933+
}
934+
}
935+
}
936+
937+
// Trampolines guarantee that all landing pads for any given fragment will
938+
// be contained in the same fragment.
939+
if (NeedsTrampolines) {
940+
for (FunctionFragment &FF : BF.getLayout().fragments())
941+
BF.setLPFragment(FF.getFragmentNum(), FF.getFragmentNum());
942+
Trampolines = createEHTrampolines(BF);
943+
}
944+
}
906945

907946
// Check the new size to see if it's worth splitting the function.
908947
if (BC.isX86() && LayoutUpdated) {
@@ -933,6 +972,10 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
933972
}
934973
}
935974

975+
// Restore LP fragment for the main fragment if the splitting was undone.
976+
if (BF.hasEHRanges() && !BF.isSplit())
977+
BF.setLPFragment(FragmentNum::main(), FragmentNum::main());
978+
936979
// Fix branches if the splitting decision of the pass after function
937980
// reordering is different from that of the pass before function reordering.
938981
if (LayoutUpdated && BC.HasFinalizedFunctionOrder)

bolt/test/X86/exceptions-compact.s

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## Check that llvm-bolt is able to overwrite LSDA in ULEB128 format in-place for
2+
## all types of binaries.
3+
4+
# REQUIRES: system-linux
5+
6+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o
7+
# RUN: ld.lld --no-pie %t.o -o %t.exe -q
8+
# RUN: ld.lld --pie %t.o -o %t.pie -q
9+
# RUN: ld.lld --shared %t.o -o %t.so -q
10+
# RUN: llvm-bolt %t.exe -o %t.bolt --strict \
11+
# RUN: | FileCheck --check-prefix=CHECK-BOLT %s
12+
# RUN: llvm-bolt %t.pie -o %t.pie.bolt --strict \
13+
# RUN: | FileCheck --check-prefix=CHECK-BOLT %s
14+
# RUN: llvm-bolt %t.so -o %t.so.bolt --strict \
15+
# RUN: | FileCheck --check-prefix=CHECK-BOLT %s
16+
17+
# CHECK-BOLT: rewriting .gcc_except_table in-place
18+
19+
# RUN: llvm-readelf -WS %t.bolt | FileCheck --check-prefix=CHECK-ELF %s
20+
# RUN: llvm-readelf -WS %t.pie.bolt | FileCheck --check-prefix=CHECK-ELF %s
21+
# RUN: llvm-readelf -WS %t.so.bolt | FileCheck --check-prefix=CHECK-ELF %s
22+
23+
# CHECK-ELF-NOT: .bolt.org.gcc_except_table
24+
25+
.text
26+
.global foo
27+
.type foo, %function
28+
foo:
29+
.cfi_startproc
30+
ret
31+
.cfi_endproc
32+
.size foo, .-foo
33+
34+
.globl _start
35+
.type _start, %function
36+
_start:
37+
.Lfunc_begin0:
38+
.cfi_startproc
39+
.cfi_lsda 27, .Lexception0
40+
call foo
41+
.Ltmp0:
42+
call foo
43+
.Ltmp1:
44+
ret
45+
46+
## Landing pads.
47+
.LLP1:
48+
ret
49+
.LLP0:
50+
ret
51+
52+
.cfi_endproc
53+
.Lfunc_end0:
54+
.size _start, .-_start
55+
56+
## EH table.
57+
.section .gcc_except_table,"a",@progbits
58+
.p2align 2
59+
GCC_except_table0:
60+
.Lexception0:
61+
.byte 255 # @LPStart Encoding = omit
62+
.byte 255 # @TType Encoding = omit
63+
.byte 1 # Call site Encoding = uleb128
64+
.uleb128 .Lcst_end0-.Lcst_begin0
65+
.Lcst_begin0:
66+
.uleb128 .Lfunc_begin0-.Lfunc_begin0 # >> Call Site 1 <<
67+
.uleb128 .Ltmp0-.Lfunc_begin0 # Call between .Lfunc_begin0 and .Ltmp0
68+
.uleb128 .LLP0-.Lfunc_begin0 # jumps to .LLP0
69+
.byte 0 # On action: cleanup
70+
.uleb128 .Ltmp0-.Lfunc_begin0 # >> Call Site 2 <<
71+
.uleb128 .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1
72+
.uleb128 .LLP1-.Lfunc_begin0 # jumps to .LLP1
73+
.byte 0 # On action: cleanup
74+
.Lcst_end0:
75+

0 commit comments

Comments
 (0)