Skip to content

Commit e4a35ec

Browse files
committed
Merge from 'main' to 'sycl-web' (7 commits)
CONFLICT (content): Merge conflict in clang/lib/Driver/ToolChains/Gnu.cpp
2 parents 3e4624f + 9b1897b commit e4a35ec

File tree

20 files changed

+380
-2038
lines changed

20 files changed

+380
-2038
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,9 @@ class BinaryContext {
585585
/// Indicates if relocations are available for usage.
586586
bool HasRelocations{false};
587587

588+
/// Indicates if the binary is stripped
589+
bool IsStripped{false};
590+
588591
/// Is the binary always loaded at a fixed address. Shared objects and
589592
/// position-independent executables (PIEs) are examples of binaries that
590593
/// will have HasFixedLoadAddress set to false.

bolt/lib/Core/BinaryContext.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,10 @@ bool BinaryContext::analyzeJumpTable(
622622
void BinaryContext::populateJumpTables() {
623623
LLVM_DEBUG(dbgs() << "DataPCRelocations: " << DataPCRelocations.size()
624624
<< '\n');
625+
626+
// Collect jump tables that pass the analyzeJumpTable's first check,
627+
// but fail the analyzeJumpTable's second check
628+
SmallVector<JumpTable *, 1> AbortedJTs;
625629
for (auto JTI = JumpTables.begin(), JTE = JumpTables.end(); JTI != JTE;
626630
++JTI) {
627631
JumpTable *JT = JTI->second;
@@ -640,6 +644,13 @@ void BinaryContext::populateJumpTables() {
640644
const bool Success =
641645
analyzeJumpTable(JT->getAddress(), JT->Type, *(JT->Parents[0]),
642646
NextJTAddress, &JT->EntriesAsAddress);
647+
// !Success means a false positive from earlier analysis run due to
648+
// different context. A possible culprit is instruction bounds check.
649+
// Previous run happens during disassembly. If the target function
650+
// is not disassembled, the check will be skipped, leading to a false
651+
// positive
652+
//
653+
// Solution: Ignore fragments accessing JT that fails the check
643654
if (!Success) {
644655
LLVM_DEBUG(ListSeparator LS;
645656
dbgs() << "failed to analyze jump table in function ";
@@ -659,7 +670,8 @@ void BinaryContext::populateJumpTables() {
659670
dbgs() << "\n";);
660671
NextJTI->second->print(dbgs());
661672
}
662-
llvm_unreachable("jump table heuristic failure");
673+
AbortedJTs.push_back(JT);
674+
continue;
663675
}
664676
for (BinaryFunction *Frag : JT->Parents) {
665677
for (uint64_t EntryAddress : JT->EntriesAsAddress)
@@ -689,6 +701,15 @@ void BinaryContext::populateJumpTables() {
689701
addFragmentsToSkip(Frag);
690702
}
691703

704+
// Ignore fragments accessing JT that fails analyzeJumpTable check
705+
for (JumpTable *JT : AbortedJTs) {
706+
for (BinaryFunction *Frag : JT->Parents) {
707+
Frag->setIgnored();
708+
Frag->JumpTables.erase(Frag->JumpTables.find(JT->getAddress()));
709+
}
710+
JumpTables.erase(JumpTables.find(JT->getAddress()));
711+
}
712+
692713
if (opts::StrictMode && DataPCRelocations.size()) {
693714
LLVM_DEBUG({
694715
dbgs() << DataPCRelocations.size()

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,6 @@ cl::opt<std::string>
9292
"output binary via bolt info section"),
9393
cl::cat(BoltCategory));
9494

95-
cl::opt<bool>
96-
AllowStripped("allow-stripped",
97-
cl::desc("allow processing of stripped binaries"),
98-
cl::Hidden,
99-
cl::cat(BoltCategory));
100-
10195
cl::opt<bool> DumpDotAll(
10296
"dump-dot-all",
10397
cl::desc("dump function CFGs to graphviz format after each stage;"
@@ -1562,6 +1556,7 @@ Error RewriteInstance::readSpecialSections() {
15621556
TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
15631557

15641558
bool HasTextRelocations = false;
1559+
bool HasSymbolTable = false;
15651560
bool HasDebugInfo = false;
15661561

15671562
// Process special sections.
@@ -1593,6 +1588,7 @@ Error RewriteInstance::readSpecialSections() {
15931588
}
15941589

15951590
HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text");
1591+
HasSymbolTable = (bool)BC->getUniqueSectionByName(".symtab");
15961592
LSDASection = BC->getUniqueSectionByName(".gcc_except_table");
15971593
EHFrameSection = BC->getUniqueSectionByName(".eh_frame");
15981594
GOTPLTSection = BC->getUniqueSectionByName(".got.plt");
@@ -1629,6 +1625,8 @@ Error RewriteInstance::readSpecialSections() {
16291625
BC->HasRelocations =
16301626
HasTextRelocations && (opts::RelocationMode != cl::BOU_FALSE);
16311627

1628+
BC->IsStripped = !HasSymbolTable;
1629+
16321630
// Force non-relocation mode for heatmap generation
16331631
if (opts::HeatmapMode)
16341632
BC->HasRelocations = false;
@@ -1637,6 +1635,10 @@ Error RewriteInstance::readSpecialSections() {
16371635
outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "")
16381636
<< "relocation mode\n";
16391637

1638+
if (BC->IsStripped)
1639+
outs() << "BOLT-INFO: input binary is stripped. The support is limited and "
1640+
<< "is considered experimental.\n";
1641+
16401642
// Read EH frame for function boundaries info.
16411643
Expected<const DWARFDebugFrame *> EHFrameOrError = BC->DwCtx->getEHFrame();
16421644
if (!EHFrameOrError)
@@ -2805,13 +2807,11 @@ void RewriteInstance::preprocessProfileData() {
28052807
if (Error E = ProfileReader->preprocessProfile(*BC.get()))
28062808
report_error("cannot pre-process profile", std::move(E));
28072809

2808-
if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName() &&
2809-
!opts::AllowStripped) {
2810+
if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName()) {
28102811
errs() << "BOLT-ERROR: input binary does not have local file symbols "
28112812
"but profile data includes function names with embedded file "
28122813
"names. It appears that the input binary was stripped while a "
2813-
"profiled binary was not. If you know what you are doing and "
2814-
"wish to proceed, use -allow-stripped option.\n";
2814+
"profiled binary was not\n";
28152815
exit(1);
28162816
}
28172817
}

bolt/test/X86/fake_jump_table.s

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Currently disassembly is not decoupled from branch target analysis.
2+
# This causes a few checks related to availability of target insn to
3+
# fail for stripped binaries:
4+
# (a) analyzeJumpTable
5+
# (b) postProcessEntryPoints
6+
# This test checks if BOLT can safely support instruction bounds check
7+
# for cross-function targets.
8+
9+
# REQUIRES: system-linux
10+
11+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
12+
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
13+
# RUN: llvm-bolt %t.exe -o %t.out -v=1 -print-cfg
14+
15+
.text
16+
.globl main
17+
.type main, %function
18+
.p2align 2
19+
main:
20+
LBB0:
21+
.cfi_startproc
22+
andl $0xf, %ecx
23+
cmpb $0x4, %cl
24+
ja .main.cold.1
25+
LBB1:
26+
leaq FAKE_JUMP_TABLE(%rip), %r8
27+
cmpq %r8, %r9
28+
LBB2:
29+
xorq %rax, %rax
30+
ret
31+
.cfi_endproc
32+
.size main, .-main
33+
34+
.globl main.cold.1
35+
.type main.cold.1, %function
36+
.p2align 2
37+
main.cold.1:
38+
.cfi_startproc
39+
nop
40+
LBB3:
41+
callq abort
42+
.cfi_endproc
43+
.size main.cold.1, .-main.cold.1
44+
45+
.rodata
46+
.globl FAKE_JUMP_TABLE
47+
FAKE_JUMP_TABLE:
48+
.long LBB2-FAKE_JUMP_TABLE
49+
.long LBB3-FAKE_JUMP_TABLE+0x1

bolt/test/X86/is-strip.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This test checks whether a binary is stripped or not.
2+
3+
# RUN: %clang++ %p/Inputs/linenumber.cpp -o %t -Wl,-q
4+
# RUN: llvm-bolt %t -o %t.out 2>&1 | FileCheck %s -check-prefix=CHECK-NOSTRIP
5+
# RUN: cp %t %t.stripped
6+
# RUN: llvm-strip -s %t.stripped
7+
# RUN: llvm-bolt %t.stripped -o %t.out 2>&1 | FileCheck %s -check-prefix=CHECK-STRIP
8+
9+
# CHECK-NOSTRIP-NOT: BOLT-INFO: input binary is stripped. The support is limited and is considered experimental.
10+
# CHECK-STRIP: BOLT-INFO: input binary is stripped. The support is limited and is considered experimental.

clang/include/clang/Basic/Module.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@ class Module {
525525
Parent->SubModules.push_back(this);
526526
}
527527

528+
/// Is this module have similar semantics as headers.
529+
bool isHeaderLikeModule() const {
530+
return isModuleMapModule() || isHeaderUnit();
531+
}
532+
528533
/// Is this a module partition.
529534
bool isModulePartition() const {
530535
return Kind == ModulePartitionInterface ||

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4739,6 +4739,8 @@ class Sema final {
47394739
bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old);
47404740
bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old);
47414741
bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old);
4742+
bool IsRedefinitionInModule(const NamedDecl *New,
4743+
const NamedDecl *Old) const;
47424744

47434745
void DiagnoseAmbiguousLookup(LookupResult &Result);
47444746
//@}

clang/lib/Driver/ToolChains/Gnu.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
699699
CmdArgs.push_back("-lOpenCL");
700700
}
701701

702+
// LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
703+
// forcibly link with libatomic as a workaround.
704+
// TODO: Issue #41880 and D118021.
705+
if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
706+
CmdArgs.push_back("--push-state");
707+
CmdArgs.push_back("--as-needed");
708+
CmdArgs.push_back("-latomic");
709+
CmdArgs.push_back("--pop-state");
710+
}
711+
702712
if (WantPthread && !isAndroid)
703713
CmdArgs.push_back("-lpthread");
704714

clang/lib/Sema/SemaDecl.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,80 @@ bool Sema::CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old) {
17191719
return false;
17201720
}
17211721

1722+
// Check the redefinition in C++20 Modules.
1723+
//
1724+
// [basic.def.odr]p14:
1725+
// For any definable item D with definitions in multiple translation units,
1726+
// - if D is a non-inline non-templated function or variable, or
1727+
// - if the definitions in different translation units do not satisfy the
1728+
// following requirements,
1729+
// the program is ill-formed; a diagnostic is required only if the definable
1730+
// item is attached to a named module and a prior definition is reachable at
1731+
// the point where a later definition occurs.
1732+
// - Each such definition shall not be attached to a named module
1733+
// ([module.unit]).
1734+
// - Each such definition shall consist of the same sequence of tokens, ...
1735+
// ...
1736+
//
1737+
// Return true if the redefinition is not allowed. Return false otherwise.
1738+
bool Sema::IsRedefinitionInModule(const NamedDecl *New,
1739+
const NamedDecl *Old) const {
1740+
assert(getASTContext().isSameEntity(New, Old) &&
1741+
"New and Old are not the same definition, we should diagnostic it "
1742+
"immediately instead of checking it.");
1743+
assert(const_cast<Sema *>(this)->isReachable(New) &&
1744+
const_cast<Sema *>(this)->isReachable(Old) &&
1745+
"We shouldn't see unreachable definitions here.");
1746+
1747+
Module *NewM = New->getOwningModule();
1748+
Module *OldM = Old->getOwningModule();
1749+
1750+
// We only checks for named modules here. The header like modules is skipped.
1751+
// FIXME: This is not right if we import the header like modules in the module
1752+
// purview.
1753+
//
1754+
// For example, assuming "header.h" provides definition for `D`.
1755+
// ```C++
1756+
// //--- M.cppm
1757+
// export module M;
1758+
// import "header.h"; // or #include "header.h" but import it by clang modules
1759+
// actually.
1760+
//
1761+
// //--- Use.cpp
1762+
// import M;
1763+
// import "header.h"; // or uses clang modules.
1764+
// ```
1765+
//
1766+
// In this case, `D` has multiple definitions in multiple TU (M.cppm and
1767+
// Use.cpp) and `D` is attached to a named module `M`. The compiler should
1768+
// reject it. But the current implementation couldn't detect the case since we
1769+
// don't record the information about the importee modules.
1770+
//
1771+
// But this might not be painful in practice. Since the design of C++20 Named
1772+
// Modules suggests us to use headers in global module fragment instead of
1773+
// module purview.
1774+
if (NewM && NewM->isHeaderLikeModule())
1775+
NewM = nullptr;
1776+
if (OldM && OldM->isHeaderLikeModule())
1777+
OldM = nullptr;
1778+
1779+
if (!NewM && !OldM)
1780+
return true;
1781+
1782+
// [basic.def.odr]p14.3
1783+
// Each such definition shall not be attached to a named module
1784+
// ([module.unit]).
1785+
if ((NewM && NewM->isModulePurview()) || (OldM && OldM->isModulePurview()))
1786+
return true;
1787+
1788+
// Then New and Old lives in the same TU if their share one same module unit.
1789+
if (NewM)
1790+
NewM = NewM->getTopLevelModule();
1791+
if (OldM)
1792+
OldM = OldM->getTopLevelModule();
1793+
return OldM == NewM;
1794+
}
1795+
17221796
static bool isUsingDecl(NamedDecl *D) {
17231797
return isa<UsingShadowDecl>(D) ||
17241798
isa<UnresolvedUsingTypenameDecl>(D) ||

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8724,7 +8724,7 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl,
87248724
if (Previous.empty())
87258725
return;
87268726

8727-
auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl());
8727+
auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
87288728
if (!OldConcept) {
87298729
auto *Old = Previous.getRepresentativeDecl();
87308730
Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
@@ -8742,7 +8742,8 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl,
87428742
AddToScope = false;
87438743
return;
87448744
}
8745-
if (hasReachableDefinition(OldConcept)) {
8745+
if (hasReachableDefinition(OldConcept) &&
8746+
IsRedefinitionInModule(NewDecl, OldConcept)) {
87468747
Diag(NewDecl->getLocation(), diag::err_redefinition)
87478748
<< NewDecl->getDeclName();
87488749
notePreviousDefinition(OldConcept, NewDecl->getLocation());

0 commit comments

Comments
 (0)