Skip to content

Commit 56aca88

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merge amd-gfx13 and amd-gfx into amd-gfx-gfx13
3 parents aab7f7a + e18d8b6 + 346fa70 commit 56aca88

File tree

63 files changed

+2328
-272
lines changed

Some content is hidden

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

63 files changed

+2328
-272
lines changed

bolt/runtime/instr.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -672,14 +672,15 @@ bool parseAddressRange(const char *Str, uint64_t &StartAddress,
672672
return true;
673673
}
674674

675+
static constexpr uint32_t NameMax = 4096;
676+
static char TargetPath[NameMax] = {};
677+
675678
/// Get full path to the real binary by getting current virtual address
676679
/// and searching for the appropriate link in address range in
677680
/// /proc/self/map_files
678681
static char *getBinaryPath() {
679682
const uint32_t BufSize = 1024;
680-
const uint32_t NameMax = 4096;
681683
const char DirPath[] = "/proc/self/map_files/";
682-
static char TargetPath[NameMax] = {};
683684
char Buf[BufSize];
684685

685686
if (__bolt_instr_binpath[0] != '\0')
@@ -719,22 +720,31 @@ static char *getBinaryPath() {
719720
return nullptr;
720721
}
721722

722-
ProfileWriterContext readDescriptions() {
723+
ProfileWriterContext readDescriptions(const uint8_t *BinContents,
724+
uint64_t Size) {
723725
ProfileWriterContext Result;
724-
const char *BinPath = getBinaryPath();
725-
assert(BinPath && BinPath[0] != '\0', "failed to find binary path");
726726

727-
uint64_t FD = __open(BinPath, O_RDONLY,
728-
/*mode=*/0666);
729-
assert(static_cast<int64_t>(FD) >= 0, "failed to open binary path");
727+
assert((BinContents == nullptr) == (Size == 0),
728+
"either empty or valid library content buffer");
729+
730+
if (BinContents) {
731+
Result.FileDesc = -1;
732+
} else {
733+
const char *BinPath = getBinaryPath();
734+
assert(BinPath && BinPath[0] != '\0', "failed to find binary path");
730735

731-
Result.FileDesc = FD;
736+
uint64_t FD = __open(BinPath, O_RDONLY,
737+
/*mode=*/0666);
738+
assert(static_cast<int64_t>(FD) >= 0, "failed to open binary path");
732739

733-
// mmap our binary to memory
734-
uint64_t Size = __lseek(FD, 0, SEEK_END);
735-
const uint8_t *BinContents = reinterpret_cast<uint8_t *>(
736-
__mmap(0, Size, PROT_READ, MAP_PRIVATE, FD, 0));
737-
assert(BinContents != MAP_FAILED, "readDescriptions: Failed to mmap self!");
740+
Result.FileDesc = FD;
741+
742+
// mmap our binary to memory
743+
Size = __lseek(FD, 0, SEEK_END);
744+
BinContents = reinterpret_cast<uint8_t *>(
745+
__mmap(0, Size, PROT_READ, MAP_PRIVATE, FD, 0));
746+
assert(BinContents != MAP_FAILED, "readDescriptions: Failed to mmap self!");
747+
}
738748
Result.MMapPtr = BinContents;
739749
Result.MMapSize = Size;
740750
const Elf64_Ehdr *Hdr = reinterpret_cast<const Elf64_Ehdr *>(BinContents);
@@ -1509,7 +1519,7 @@ extern "C" void __bolt_instr_clear_counters() {
15091519
}
15101520

15111521
/// This is the entry point for profile writing.
1512-
/// There are three ways of getting here:
1522+
/// There are four ways of getting here:
15131523
///
15141524
/// * Program execution ended, finalization methods are running and BOLT
15151525
/// hooked into FINI from your binary dynamic section;
@@ -1518,9 +1528,18 @@ extern "C" void __bolt_instr_clear_counters() {
15181528
/// * BOLT prints this function address so you can attach a debugger and
15191529
/// call this function directly to get your profile written to disk
15201530
/// on demand.
1531+
/// * Application can, at interesting runtime point, iterate through all
1532+
/// the loaded native libraries and for each call dlopen() and dlsym()
1533+
/// to get a pointer to this function and call through the acquired
1534+
/// function pointer to dump profile data.
15211535
///
15221536
extern "C" void __attribute((force_align_arg_pointer))
1523-
__bolt_instr_data_dump(int FD) {
1537+
__bolt_instr_data_dump(int FD, const char *LibPath = nullptr,
1538+
const uint8_t *LibContents = nullptr,
1539+
uint64_t LibSize = 0) {
1540+
if (LibPath)
1541+
strCopy(TargetPath, LibPath, NameMax);
1542+
15241543
// Already dumping
15251544
if (!GlobalWriteProfileMutex->acquire())
15261545
return;
@@ -1531,7 +1550,7 @@ __bolt_instr_data_dump(int FD) {
15311550
assert(ret == 0, "Failed to ftruncate!");
15321551
BumpPtrAllocator HashAlloc;
15331552
HashAlloc.setMaxSize(0x6400000);
1534-
ProfileWriterContext Ctx = readDescriptions();
1553+
ProfileWriterContext Ctx = readDescriptions(LibContents, LibSize);
15351554
Ctx.CallFlowTable = new (HashAlloc, 0) CallFlowHashTable(HashAlloc);
15361555

15371556
DEBUG(printStats(Ctx));
@@ -1551,8 +1570,10 @@ __bolt_instr_data_dump(int FD) {
15511570
Ctx.CallFlowTable->forEachElement(visitCallFlowEntry, FD, &Ctx);
15521571

15531572
__fsync(FD);
1554-
__munmap((void *)Ctx.MMapPtr, Ctx.MMapSize);
1555-
__close(Ctx.FileDesc);
1573+
if (Ctx.FileDesc != -1) {
1574+
__munmap((void *)Ctx.MMapPtr, Ctx.MMapSize);
1575+
__close(Ctx.FileDesc);
1576+
}
15561577
HashAlloc.destroy();
15571578
GlobalWriteProfileMutex->release();
15581579
DEBUG(report("Finished writing profile.\n"));

clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,45 @@ void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
7878
if (!MatchedDecl)
7979
return;
8080

81-
if (Tracer.analyze(MatchedDecl).getBehaviour() ==
82-
utils::ExceptionAnalyzer::State::Throwing)
83-
// FIXME: We should provide more information about the exact location where
84-
// the exception is thrown, maybe the full path the exception escapes
85-
diag(MatchedDecl->getLocation(), "an exception may be thrown in function "
86-
"%0 which should not throw exceptions")
87-
<< MatchedDecl;
81+
const utils::ExceptionAnalyzer::ExceptionInfo Info =
82+
Tracer.analyze(MatchedDecl);
83+
84+
if (Info.getBehaviour() != utils::ExceptionAnalyzer::State::Throwing)
85+
return;
86+
87+
diag(MatchedDecl->getLocation(), "an exception may be thrown in function "
88+
"%0 which should not throw exceptions")
89+
<< MatchedDecl;
90+
91+
const auto &[ThrowType, ThrowInfo] = *Info.getExceptions().begin();
92+
93+
if (ThrowInfo.Loc.isInvalid())
94+
return;
95+
96+
const utils::ExceptionAnalyzer::CallStack &Stack = ThrowInfo.Stack;
97+
diag(ThrowInfo.Loc,
98+
"frame #0: unhandled exception of type %0 may be thrown in function %1 "
99+
"here",
100+
DiagnosticIDs::Note)
101+
<< QualType(ThrowType, 0U) << Stack.back().first;
102+
103+
size_t FrameNo = 1;
104+
for (auto CurrIt = ++Stack.rbegin(), PrevIt = Stack.rbegin();
105+
CurrIt != Stack.rend(); ++CurrIt, ++PrevIt) {
106+
const FunctionDecl *CurrFunction = CurrIt->first;
107+
const FunctionDecl *PrevFunction = PrevIt->first;
108+
const SourceLocation PrevLocation = PrevIt->second;
109+
if (PrevLocation.isValid()) {
110+
diag(PrevLocation, "frame #%0: function %1 calls function %2 here",
111+
DiagnosticIDs::Note)
112+
<< FrameNo << CurrFunction << PrevFunction;
113+
} else {
114+
diag(CurrFunction->getLocation(),
115+
"frame #%0: function %1 calls function %2", DiagnosticIDs::Note)
116+
<< FrameNo << CurrFunction << PrevFunction;
117+
}
118+
++FrameNo;
119+
}
88120
}
89121

90122
} // namespace clang::tidy::bugprone

clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ This option overrides the 'UseColor' option in
328328

329329
static cl::opt<bool> VerifyConfig("verify-config", desc(R"(
330330
Check the config files to ensure each check and
331-
option is recognized.
331+
option is recognized without running any checks.
332332
)"),
333333
cl::init(false), cl::cat(ClangTidyCategory));
334334

clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
namespace clang::tidy::utils {
1212

1313
void ExceptionAnalyzer::ExceptionInfo::registerException(
14-
const Type *ExceptionType) {
14+
const Type *ExceptionType, const ThrowInfo &ThrowInfo) {
1515
assert(ExceptionType != nullptr && "Only valid types are accepted");
1616
Behaviour = State::Throwing;
17-
ThrownExceptions.insert(ExceptionType);
17+
ThrownExceptions.insert({ExceptionType, ThrowInfo});
1818
}
1919

2020
void ExceptionAnalyzer::ExceptionInfo::registerExceptions(
@@ -356,10 +356,12 @@ static bool canThrow(const FunctionDecl *Func) {
356356
};
357357
}
358358

359-
bool ExceptionAnalyzer::ExceptionInfo::filterByCatch(
360-
const Type *HandlerTy, const ASTContext &Context) {
359+
ExceptionAnalyzer::ExceptionInfo::Throwables
360+
ExceptionAnalyzer::ExceptionInfo::filterByCatch(const Type *HandlerTy,
361+
const ASTContext &Context) {
361362
llvm::SmallVector<const Type *, 8> TypesToDelete;
362-
for (const Type *ExceptionTy : ThrownExceptions) {
363+
for (const auto &ThrownException : ThrownExceptions) {
364+
const Type *ExceptionTy = ThrownException.getFirst();
363365
CanQualType ExceptionCanTy = ExceptionTy->getCanonicalTypeUnqualified();
364366
CanQualType HandlerCanTy = HandlerTy->getCanonicalTypeUnqualified();
365367

@@ -409,11 +411,18 @@ bool ExceptionAnalyzer::ExceptionInfo::filterByCatch(
409411
}
410412
}
411413

412-
for (const Type *T : TypesToDelete)
413-
ThrownExceptions.erase(T);
414+
Throwables DeletedExceptions;
415+
416+
for (const Type *TypeToDelete : TypesToDelete) {
417+
const auto DeleteIt = ThrownExceptions.find(TypeToDelete);
418+
if (DeleteIt != ThrownExceptions.end()) {
419+
DeletedExceptions.insert(*DeleteIt);
420+
ThrownExceptions.erase(DeleteIt);
421+
}
422+
}
414423

415424
reevaluateBehaviour();
416-
return !TypesToDelete.empty();
425+
return DeletedExceptions;
417426
}
418427

419428
ExceptionAnalyzer::ExceptionInfo &
@@ -422,7 +431,8 @@ ExceptionAnalyzer::ExceptionInfo::filterIgnoredExceptions(
422431
llvm::SmallVector<const Type *, 8> TypesToDelete;
423432
// Note: Using a 'SmallSet' with 'llvm::remove_if()' is not possible.
424433
// Therefore this slightly hacky implementation is required.
425-
for (const Type *T : ThrownExceptions) {
434+
for (const auto &ThrownException : ThrownExceptions) {
435+
const Type *T = ThrownException.getFirst();
426436
if (const auto *TD = T->getAsTagDecl()) {
427437
if (TD->getDeclName().isIdentifier()) {
428438
if ((IgnoreBadAlloc &&
@@ -454,16 +464,15 @@ void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() {
454464
else
455465
Behaviour = State::Throwing;
456466
}
457-
458467
ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
459468
const FunctionDecl *Func, const ExceptionInfo::Throwables &Caught,
460-
llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
469+
CallStack &CallStack, SourceLocation CallLoc) {
461470
if (!Func || CallStack.contains(Func) ||
462471
(!CallStack.empty() && !canThrow(Func)))
463472
return ExceptionInfo::createNonThrowing();
464473

465474
if (const Stmt *Body = Func->getBody()) {
466-
CallStack.insert(Func);
475+
CallStack.insert({Func, CallLoc});
467476
ExceptionInfo Result = throwsException(Body, Caught, CallStack);
468477

469478
// For a constructor, we also have to check the initializers.
@@ -481,17 +490,23 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
481490

482491
auto Result = ExceptionInfo::createUnknown();
483492
if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
484-
for (const QualType &Ex : FPT->exceptions())
485-
Result.registerException(Ex.getTypePtr());
493+
for (const QualType &Ex : FPT->exceptions()) {
494+
CallStack.insert({Func, CallLoc});
495+
Result.registerException(
496+
Ex.getTypePtr(),
497+
{Func->getExceptionSpecSourceRange().getBegin(), CallStack});
498+
CallStack.erase(Func);
499+
}
486500
}
487501
return Result;
488502
}
489503

490504
/// Analyzes a single statement on it's throwing behaviour. This is in principle
491505
/// possible except some 'Unknown' functions are called.
492-
ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
493-
const Stmt *St, const ExceptionInfo::Throwables &Caught,
494-
llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
506+
ExceptionAnalyzer::ExceptionInfo
507+
ExceptionAnalyzer::throwsException(const Stmt *St,
508+
const ExceptionInfo::Throwables &Caught,
509+
CallStack &CallStack) {
495510
auto Results = ExceptionInfo::createNonThrowing();
496511
if (!St)
497512
return Results;
@@ -505,7 +520,8 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
505520
->getPointeeType()
506521
->getUnqualifiedDesugaredType();
507522
Results.registerException(
508-
ThrownExpr->getType()->getUnqualifiedDesugaredType());
523+
ThrownExpr->getType()->getUnqualifiedDesugaredType(),
524+
{Throw->getBeginLoc(), CallStack});
509525
} else
510526
// A rethrow of a caught exception happens which makes it possible
511527
// to throw all exception that are caught in the 'catch' clause of
@@ -520,7 +536,7 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
520536
// Everything is caught through 'catch(...)'.
521537
if (!Catch->getExceptionDecl()) {
522538
ExceptionInfo Rethrown = throwsException(
523-
Catch->getHandlerBlock(), Uncaught.getExceptionTypes(), CallStack);
539+
Catch->getHandlerBlock(), Uncaught.getExceptions(), CallStack);
524540
Results.merge(Rethrown);
525541
Uncaught.clear();
526542
} else {
@@ -536,25 +552,26 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
536552
// thrown types (because it's sensitive to inheritance) the throwing
537553
// situation changes. First of all filter the exception types and
538554
// analyze if the baseclass-exception is rethrown.
539-
if (Uncaught.filterByCatch(
540-
CaughtType, Catch->getExceptionDecl()->getASTContext())) {
541-
ExceptionInfo::Throwables CaughtExceptions;
542-
CaughtExceptions.insert(CaughtType);
543-
ExceptionInfo Rethrown = throwsException(Catch->getHandlerBlock(),
544-
CaughtExceptions, CallStack);
555+
const ExceptionInfo::Throwables FilteredExceptions =
556+
Uncaught.filterByCatch(CaughtType,
557+
Catch->getExceptionDecl()->getASTContext());
558+
if (!FilteredExceptions.empty()) {
559+
ExceptionInfo Rethrown = throwsException(
560+
Catch->getHandlerBlock(), FilteredExceptions, CallStack);
545561
Results.merge(Rethrown);
546562
}
547563
}
548564
}
549565
Results.merge(Uncaught);
550566
} else if (const auto *Call = dyn_cast<CallExpr>(St)) {
551567
if (const FunctionDecl *Func = Call->getDirectCallee()) {
552-
ExceptionInfo Excs = throwsException(Func, Caught, CallStack);
568+
ExceptionInfo Excs =
569+
throwsException(Func, Caught, CallStack, Call->getBeginLoc());
553570
Results.merge(Excs);
554571
}
555572
} else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
556-
ExceptionInfo Excs =
557-
throwsException(Construct->getConstructor(), Caught, CallStack);
573+
ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught,
574+
CallStack, Construct->getBeginLoc());
558575
Results.merge(Excs);
559576
} else if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(St)) {
560577
ExceptionInfo Excs =
@@ -569,11 +586,12 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
569586
}
570587
ExceptionInfo Excs = throwsException(Coro->getBody(), Caught, CallStack);
571588
Results.merge(throwsException(Coro->getExceptionHandler(),
572-
Excs.getExceptionTypes(), CallStack));
573-
for (const Type *Throwable : Excs.getExceptionTypes()) {
574-
if (const auto *ThrowableRec = Throwable->getAsCXXRecordDecl()) {
575-
ExceptionInfo DestructorExcs =
576-
throwsException(ThrowableRec->getDestructor(), Caught, CallStack);
589+
Excs.getExceptions(), CallStack));
590+
for (const auto &Exception : Excs.getExceptions()) {
591+
const Type *ExcType = Exception.getFirst();
592+
if (const CXXRecordDecl *ThrowableRec = ExcType->getAsCXXRecordDecl()) {
593+
ExceptionInfo DestructorExcs = throwsException(
594+
ThrowableRec->getDestructor(), Caught, CallStack, SourceLocation{});
577595
Results.merge(DestructorExcs);
578596
}
579597
}
@@ -593,9 +611,9 @@ ExceptionAnalyzer::analyzeImpl(const FunctionDecl *Func) {
593611
// Check if the function has already been analyzed and reuse that result.
594612
const auto CacheEntry = FunctionCache.find(Func);
595613
if (CacheEntry == FunctionCache.end()) {
596-
llvm::SmallSet<const FunctionDecl *, 32> CallStack;
597-
ExceptionList =
598-
throwsException(Func, ExceptionInfo::Throwables(), CallStack);
614+
CallStack CallStack;
615+
ExceptionList = throwsException(Func, ExceptionInfo::Throwables(),
616+
CallStack, Func->getLocation());
599617

600618
// Cache the result of the analysis. This is done prior to filtering
601619
// because it is best to keep as much information as possible.
@@ -610,7 +628,7 @@ ExceptionAnalyzer::analyzeImpl(const FunctionDecl *Func) {
610628

611629
ExceptionAnalyzer::ExceptionInfo
612630
ExceptionAnalyzer::analyzeImpl(const Stmt *Stmt) {
613-
llvm::SmallSet<const FunctionDecl *, 32> CallStack;
631+
CallStack CallStack;
614632
return throwsException(Stmt, ExceptionInfo::Throwables(), CallStack);
615633
}
616634

0 commit comments

Comments
 (0)