Skip to content

Commit d30cb95

Browse files
committed
Merge branch 'main' of https://github.com/llvm/llvm-project into handle_wavefrontsize_early
2 parents ed9f19f + 590f451 commit d30cb95

File tree

2,270 files changed

+152481
-99349
lines changed

Some content is hidden

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

2,270 files changed

+152481
-99349
lines changed

.github/new-issues-labeler.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@
2727

2828
'bolt':
2929
- '/\bbolt(?!\-)\b/i'
30+
31+
'infra:commit-access-request':
32+
- '/Request Commit Access/'

.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/include/bolt/Core/BinarySection.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class BinarySection {
8787
// been renamed)
8888
uint64_t OutputAddress{0}; // Section address for the rewritten binary.
8989
uint64_t OutputSize{0}; // Section size in the rewritten binary.
90+
// Can exceed OutputContents with padding.
9091
uint64_t OutputFileOffset{0}; // File offset in the rewritten binary file.
9192
StringRef OutputContents; // Rewritten section contents.
9293
const uint64_t SectionNumber; // Order in which the section was created.
@@ -474,6 +475,11 @@ class BinarySection {
474475
/// Use name \p SectionName for the section during the emission.
475476
void emitAsData(MCStreamer &Streamer, const Twine &SectionName) const;
476477

478+
/// Write finalized contents of the section. If OutputSize exceeds the size of
479+
/// the OutputContents, append zero padding to the stream and return the
480+
/// number of byte written which should match the OutputSize.
481+
uint64_t write(raw_ostream &OS) const;
482+
477483
using SymbolResolverFuncTy = llvm::function_ref<uint64_t(const MCSymbol *)>;
478484

479485
/// Flush all pending relocations to patch original contents of sections
@@ -497,6 +503,9 @@ class BinarySection {
497503
IsFinalized = true;
498504
}
499505

506+
/// When writing section contents, add \p PaddingSize zero bytes at the end.
507+
void addPadding(uint64_t PaddingSize) { OutputSize += PaddingSize; }
508+
500509
/// Reorder the contents of this section according to /p Order. If
501510
/// /p Inplace is true, the entire contents of the section is reordered,
502511
/// otherwise the new contents contain only the reordered data.

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 70 additions & 41 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
@@ -416,17 +416,6 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
416416
BF.duplicateConstantIslands();
417417
}
418418

419-
if (!FF.empty() && FF.front()->isLandingPad()) {
420-
assert(!FF.front()->isEntryPoint() &&
421-
"Landing pad cannot be entry point of function");
422-
// If the first block of the fragment is a landing pad, it's offset from the
423-
// start of the area that the corresponding LSDA describes is zero. In this
424-
// case, the call site entries in that LSDA have 0 as offset to the landing
425-
// pad, which the runtime interprets as "no handler". To prevent this,
426-
// insert some padding.
427-
Streamer.emitBytes(BC.MIB->getTrapFillValue());
428-
}
429-
430419
// Track the first emitted instruction with debug info.
431420
bool FirstInstr = true;
432421
for (BinaryBasicBlock *const BB : FF) {
@@ -926,39 +915,72 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
926915
// Emit the LSDA header.
927916

928917
// If LPStart is omitted, then the start of the FDE is used as a base for
929-
// landing pad displacements. Then if a cold fragment starts with
918+
// landing pad displacements. Then, if a cold fragment starts with
930919
// a landing pad, this means that the first landing pad offset will be 0.
931-
// As a result, the exception handling runtime will ignore this landing pad
932-
// because zero offset denotes the absence of a landing pad.
933-
// For this reason, when the binary has fixed starting address we emit LPStart
934-
// as 0 and output the absolute value of the landing pad in the table.
920+
// However, C++ runtime will treat 0 as if there is no landing pad, thus we
921+
// cannot emit LP offset as 0.
935922
//
936-
// If the base address can change, we cannot use absolute addresses for
937-
// landing pads (at least not without runtime relocations). Hence, we fall
938-
// back to emitting landing pads relative to the FDE start.
939-
// As we are emitting label differences, we have to guarantee both labels are
940-
// defined in the same section and hence cannot place the landing pad into a
941-
// cold fragment when the corresponding call site is in the hot fragment.
942-
// Because of this issue and the previously described issue of possible
943-
// zero-offset landing pad we have to place landing pads in the same section
944-
// as the corresponding invokes for shared objects.
923+
// As a solution, for fixed-address binaries we set LPStart to 0, and for
924+
// position-independent binaries we offset LP start by one byte.
925+
bool NeedsLPAdjustment = false;
945926
std::function<void(const MCSymbol *)> emitLandingPad;
946-
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+
947941
Streamer.emitIntValue(dwarf::DW_EH_PE_udata4, 1); // LPStart format
948942
Streamer.emitIntValue(0, 4); // LPStart
949943
emitLandingPad = [&](const MCSymbol *LPSymbol) {
950-
if (!LPSymbol)
951-
Streamer.emitIntValue(0, 4);
952-
else
944+
if (LPSymbol)
953945
Streamer.emitSymbolValue(LPSymbol, 4);
946+
else
947+
Streamer.emitIntValue(0, 4);
954948
};
955949
} else {
956-
Streamer.emitIntValue(dwarf::DW_EH_PE_omit, 1); // LPStart format
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) {
957+
Streamer.emitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1);
958+
MCSymbol *DotSymbol = BC.Ctx->createTempSymbol("LPBase");
959+
Streamer.emitLabel(DotSymbol);
960+
961+
const MCExpr *LPStartExpr = MCBinaryExpr::createSub(
962+
MCSymbolRefExpr::create(LPStartSymbol, *BC.Ctx),
963+
MCSymbolRefExpr::create(DotSymbol, *BC.Ctx), *BC.Ctx);
964+
if (NeedsLPAdjustment)
965+
LPStartExpr = MCBinaryExpr::createSub(
966+
LPStartExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx);
967+
Streamer.emitValue(LPStartExpr, 4);
968+
} else {
969+
// DW_EH_PE_omit means FDE start (StartSymbol) will be used as LPStart.
970+
Streamer.emitIntValue(dwarf::DW_EH_PE_omit, 1);
971+
}
957972
emitLandingPad = [&](const MCSymbol *LPSymbol) {
958-
if (!LPSymbol)
959-
Streamer.emitIntValue(0, 4);
960-
else
961-
Streamer.emitAbsoluteSymbolDiff(LPSymbol, StartSymbol, 4);
973+
if (LPSymbol) {
974+
const MCExpr *LPOffsetExpr = MCBinaryExpr::createSub(
975+
MCSymbolRefExpr::create(LPSymbol, *BC.Ctx),
976+
MCSymbolRefExpr::create(LPStartSymbol, *BC.Ctx), *BC.Ctx);
977+
if (NeedsLPAdjustment)
978+
LPOffsetExpr = MCBinaryExpr::createAdd(
979+
LPOffsetExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx);
980+
Streamer.emitULEB128Value(LPOffsetExpr);
981+
} else {
982+
Streamer.emitULEB128IntValue(0);
983+
}
962984
};
963985
}
964986

@@ -972,10 +994,12 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
972994
Streamer.emitLabel(TTBaseRefLabel);
973995
}
974996

975-
// Emit the landing pad call site table. We use signed data4 since we can emit
976-
// a landing pad in a different part of the split function that could appear
977-
// earlier in the address space than LPStart.
978-
Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1);
997+
// Emit encoding of entries in the call site table. The format is used for the
998+
// call site start, length, and corresponding landing pad.
999+
if (!LPStartSymbol)
1000+
Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1);
1001+
else
1002+
Streamer.emitIntValue(dwarf::DW_EH_PE_uleb128, 1);
9791003

9801004
MCSymbol *CSTStartLabel = BC.Ctx->createTempSymbol("CSTStart");
9811005
MCSymbol *CSTEndLabel = BC.Ctx->createTempSymbol("CSTEnd");
@@ -992,8 +1016,13 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
9921016

9931017
// Start of the range is emitted relative to the start of current
9941018
// function split part.
995-
Streamer.emitAbsoluteSymbolDiff(BeginLabel, StartSymbol, 4);
996-
Streamer.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
1019+
if (!LPStartSymbol) {
1020+
Streamer.emitAbsoluteSymbolDiff(BeginLabel, StartSymbol, 4);
1021+
Streamer.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
1022+
} else {
1023+
Streamer.emitAbsoluteSymbolDiffAsULEB128(BeginLabel, StartSymbol);
1024+
Streamer.emitAbsoluteSymbolDiffAsULEB128(EndLabel, BeginLabel);
1025+
}
9971026
emitLandingPad(CallSite.LP);
9981027
Streamer.emitULEB128IntValue(CallSite.Action);
9991028
}

bolt/lib/Core/BinarySection.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@ void BinarySection::emitAsData(MCStreamer &Streamer,
142142
Streamer.emitLabel(BC.Ctx->getOrCreateSymbol("__hot_data_end"));
143143
}
144144

145+
uint64_t BinarySection::write(raw_ostream &OS) const {
146+
const uint64_t NumValidContentBytes =
147+
std::min<uint64_t>(getOutputContents().size(), getOutputSize());
148+
OS.write(getOutputContents().data(), NumValidContentBytes);
149+
if (getOutputSize() > NumValidContentBytes)
150+
OS.write_zeros(getOutputSize() - NumValidContentBytes);
151+
return getOutputSize();
152+
}
153+
145154
void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
146155
SymbolResolverFuncTy Resolver) {
147156
if (PendingRelocations.empty() && Patches.empty())

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)

0 commit comments

Comments
 (0)