aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--clang/lib/AST/StmtPrinter.cpp2
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp15
-rw-r--r--clang/lib/CodeGen/CoverageMappingGen.cpp32
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp40
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp19
-rw-r--r--clang/lib/Sema/SemaExpr.cpp5
-rw-r--r--clang/lib/Sema/SemaInit.cpp8
-rw-r--r--clang/lib/Sema/SemaLookup.cpp8
-rw-r--r--clang/lib/Sema/SemaType.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp6
-rw-r--r--clang/lib/Tooling/InterpolatingCompilationDatabase.cpp4
-rw-r--r--clang/lib/Tooling/Syntax/Tokens.cpp222
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc2
-rw-r--r--libcxx/include/__config33
-rw-r--r--libcxx/include/__functional/function.h14
-rw-r--r--libcxx/include/atomic46
-rw-r--r--libcxx/include/stdatomic.h4
-rw-r--r--libcxx/include/vector119
-rw-r--r--libcxx/include/version2
-rw-r--r--lld/COFF/Symbols.h5
-rw-r--r--lld/COFF/Writer.cpp2
-rw-r--r--lld/ELF/Arch/RISCV.cpp9
-rw-r--r--lld/ELF/Driver.cpp9
-rw-r--r--lld/ELF/InputFiles.cpp2
-rw-r--r--lld/MachO/InputFiles.cpp9
-rw-r--r--lld/MachO/UnwindInfoSection.cpp80
-rw-r--r--lld/MachO/UnwindInfoSection.h2
-rw-r--r--lld/MachO/Writer.cpp2
-rw-r--r--lldb/bindings/interfaces.swig3
-rw-r--r--lldb/bindings/python/python-typemaps.swig2
-rw-r--r--lldb/include/lldb/API/SBType.h2
-rw-r--r--lldb/include/lldb/Symbol/CompilerType.h24
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h14
-rw-r--r--lldb/source/API/SBType.cpp12
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp81
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h19
-rw-r--r--lldb/source/Symbol/CompilerType.cpp18
-rw-r--r--lldb/source/Symbol/TypeSystem.cpp12
-rw-r--r--llvm/include/llvm/ADT/GenericCycleImpl.h29
-rw-r--r--llvm/include/llvm/ADT/GenericCycleInfo.h19
-rw-r--r--llvm/include/llvm/DebugInfo/Symbolize/MarkupFilter.h30
-rw-r--r--llvm/include/llvm/Object/ELF.h2
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp7
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp13
-rw-r--r--llvm/lib/Analysis/VectorUtils.cpp7
-rw-r--r--llvm/lib/CodeGen/DwarfEHPrepare.cpp8
-rw-r--r--llvm/lib/CodeGen/PrologEpilogInserter.cpp15
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp3
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp5
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp1
-rw-r--r--llvm/lib/CodeGen/TypePromotion.cpp4
-rw-r--r--llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp302
-rw-r--r--llvm/lib/IR/AutoUpgrade.cpp2
-rw-r--r--llvm/lib/Support/Unix/Signals.inc4
-rw-r--r--llvm/lib/Support/X86TargetParser.cpp10
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelLowering.cpp67
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelLowering.h2
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp11
-rw-r--r--llvm/lib/Target/AMDGPU/SIISelLowering.cpp2
-rw-r--r--llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp2
-rw-r--r--llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp3
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp2
-rw-r--r--llvm/lib/Target/Sparc/SparcCallingConv.td10
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp61
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.h5
-rw-r--r--llvm/lib/Target/X86/X86.td1
-rw-r--r--llvm/lib/Transforms/IPO/GlobalOpt.cpp2
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp4
-rw-r--r--llvm/lib/Transforms/Scalar/SROA.cpp19
-rw-r--r--llvm/lib/Transforms/Utils/LoopVersioning.cpp4
-rw-r--r--llvm/lib/Transforms/Utils/VNCoercion.cpp4
-rw-r--r--llvm/lib/Transforms/Vectorize/LoopVectorize.cpp12
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlan.h8
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp6
-rw-r--r--llvm/tools/llvm-objdump/ELFDump.cpp39
-rw-r--r--llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp28
78 files changed, 1173 insertions, 487 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6ff5b8de57fd..cb460401eb47 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -419,7 +419,7 @@ def warn_implicit_function_decl : Warning<
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
def ext_implicit_function_decl_c99 : ExtWarn<
"call to undeclared function %0; ISO C99 and later do not support implicit "
- "function declarations">, InGroup<ImplicitFunctionDeclare>, DefaultError;
+ "function declarations">, InGroup<ImplicitFunctionDeclare>;
def note_function_suggestion : Note<"did you mean %0?">;
def err_ellipsis_first_param : Error<
@@ -705,7 +705,7 @@ def ext_implicit_lib_function_decl : ExtWarn<
def ext_implicit_lib_function_decl_c99 : ExtWarn<
"call to undeclared library function '%0' with type %1; ISO C99 and later "
"do not support implicit function declarations">,
- InGroup<ImplicitFunctionDeclare>, DefaultError;
+ InGroup<ImplicitFunctionDeclare>;
def note_include_header_or_declare : Note<
"include the header <%0> or explicitly provide a declaration for '%1'">;
def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
@@ -4359,7 +4359,7 @@ def err_ident_list_in_fn_declaration : Error<
"a parameter list without types is only allowed in a function definition">;
def ext_param_not_declared : ExtWarn<
"parameter %0 was not declared, defaults to 'int'; ISO C99 and later do not "
- "support implicit int">, InGroup<ImplicitInt>, DefaultError;
+ "support implicit int">, InGroup<ImplicitInt>;
def err_param_default_argument : Error<
"C does not support default arguments">;
def err_param_default_argument_redefinition : Error<
@@ -10029,7 +10029,7 @@ def warn_receiver_forward_class : Warning<
def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
def ext_missing_type_specifier : ExtWarn<
"type specifier missing, defaults to 'int'; ISO C99 and later do not support "
- "implicit int">, InGroup<ImplicitInt>, DefaultError;
+ "implicit int">, InGroup<ImplicitInt>;
def err_missing_type_specifier : Error<
"a type specifier is required for all declarations">;
def err_decimal_unsupported : Error<
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 8d778500d103..625048c69a86 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1993,7 +1993,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs();
assert(Args);
- if (Args->size() != 1) {
+ if (Args->size() != 1 || Args->get(0).getKind() != TemplateArgument::Pack) {
const TemplateParameterList *TPL = nullptr;
if (!DRE->hadMultipleCandidates())
if (const auto *TD = dyn_cast<TemplateDecl>(DRE->getDecl()))
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 481438de0e53..9935fcc0d3ea 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1509,6 +1509,21 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S,
llvm::ConstantInt *CaseVal =
Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext()));
+
+ // Emit debuginfo for the case value if it is an enum value.
+ const ConstantExpr *CE;
+ if (auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS()))
+ CE = dyn_cast<ConstantExpr>(ICE->getSubExpr());
+ else
+ CE = dyn_cast<ConstantExpr>(S.getLHS());
+ if (CE) {
+ if (auto DE = dyn_cast<DeclRefExpr>(CE->getSubExpr()))
+ if (CGDebugInfo *Dbg = getDebugInfo())
+ if (CGM.getCodeGenOpts().hasReducedDebugInfo())
+ Dbg->EmitGlobalVariable(DE->getDecl(),
+ APValue(llvm::APSInt(CaseVal->getValue())));
+ }
+
if (SwitchLikelihood)
SwitchLikelihood->push_back(Stmt::getLikelihood(Attrs));
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 0fe084b628da..836aabf80179 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1377,19 +1377,23 @@ struct CounterCoverageMappingBuilder
// Extend into the condition before we propagate through it below - this is
// needed to handle macros that generate the "if" but not the condition.
- extendRegion(S->getCond());
+ if (!S->isConsteval())
+ extendRegion(S->getCond());
Counter ParentCount = getRegion().getCounter();
Counter ThenCount = getRegionCounter(S);
- // Emitting a counter for the condition makes it easier to interpret the
- // counter for the body when looking at the coverage.
- propagateCounts(ParentCount, S->getCond());
+ if (!S->isConsteval()) {
+ // Emitting a counter for the condition makes it easier to interpret the
+ // counter for the body when looking at the coverage.
+ propagateCounts(ParentCount, S->getCond());
- // The 'then' count applies to the area immediately after the condition.
- auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
- if (Gap)
- fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
+ // The 'then' count applies to the area immediately after the condition.
+ Optional<SourceRange> Gap =
+ findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
+ }
extendRegion(S->getThen());
Counter OutCount = propagateCounts(ThenCount, S->getThen());
@@ -1398,9 +1402,9 @@ struct CounterCoverageMappingBuilder
if (const Stmt *Else = S->getElse()) {
bool ThenHasTerminateStmt = HasTerminateStmt;
HasTerminateStmt = false;
-
// The 'else' count applies to the area immediately after the 'then'.
- Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
+ Optional<SourceRange> Gap =
+ findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
extendRegion(Else);
@@ -1416,9 +1420,11 @@ struct CounterCoverageMappingBuilder
GapRegionCounter = OutCount;
}
- // Create Branch Region around condition.
- createBranchRegion(S->getCond(), ThenCount,
- subtractCounters(ParentCount, ThenCount));
+ if (!S->isConsteval()) {
+ // Create Branch Region around condition.
+ createBranchRegion(S->getCond(), ThenCount,
+ subtractCounters(ParentCount, ThenCount));
+ }
}
void VisitCXXTryStmt(const CXXTryStmt *S) {
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 36e10e4df4c1..44743fa0206f 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -7047,10 +7047,10 @@ Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
// Empty records are ignored for parameter passing purposes.
if (isEmptyRecord(getContext(), Ty, true)) {
- Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr),
- getVAListElementType(CGF), SlotSize);
- Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
- return Addr;
+ VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy);
+ auto *Load = CGF.Builder.CreateLoad(VAListAddr);
+ Address Addr = Address(Load, CGF.Int8Ty, SlotSize);
+ return CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
}
CharUnits TySize = getContext().getTypeSizeInChars(Ty);
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index f203cae1d329..665cdc3132fb 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2139,31 +2139,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
// and gcc-toolsets.
if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&
D.getVFS().exists("/opt/rh")) {
- // Find the directory in /opt/rh/ starting with gcc-toolset-* or
- // devtoolset-* with the highest version number and add that
- // one to our prefixes.
- std::string ChosenToolsetDir;
- unsigned ChosenToolsetVersion = 0;
- std::error_code EC;
- for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC),
- LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef ToolsetDir = llvm::sys::path::filename(LI->path());
- unsigned ToolsetVersion;
- if ((!ToolsetDir.startswith("gcc-toolset-") &&
- !ToolsetDir.startswith("devtoolset-")) ||
- ToolsetDir.substr(ToolsetDir.rfind('-') + 1)
- .getAsInteger(10, ToolsetVersion))
- continue;
-
- if (ToolsetVersion > ChosenToolsetVersion) {
- ChosenToolsetVersion = ToolsetVersion;
- ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str();
- }
- }
-
- if (ChosenToolsetVersion > 0)
- Prefixes.push_back(ChosenToolsetDir + "/root/usr");
+ // TODO: We may want to remove this, since the functionality
+ // can be achieved using config files.
+ Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr");
+ Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr");
+ Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-12/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-11/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-10/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
}
// Fall back to /usr which is used by most non-Solaris systems.
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 5991cf23d5dc..cf6549e2a5bd 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2329,25 +2329,6 @@ private:
!PrevToken->MatchingParen)
return TT_PointerOrReference;
- // For "} &&"
- if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp)) {
- const FormatToken *MatchingLBrace = PrevToken->MatchingParen;
-
- // We check whether there is a TemplateCloser(">") to indicate it's a
- // template or not. If it's not a template, "&&" is likely a reference
- // operator.
- // struct {} &&ref = {};
- if (!MatchingLBrace)
- return TT_PointerOrReference;
- FormatToken *BeforeLBrace = MatchingLBrace->getPreviousNonComment();
- if (!BeforeLBrace || BeforeLBrace->isNot(TT_TemplateCloser))
- return TT_PointerOrReference;
-
- // If it is a template, "&&" is a binary operator.
- // enable_if<>{} && ...
- return TT_BinaryOperator;
- }
-
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
tok::kw_false, tok::r_brace)) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0e24237faae5..83081bbf0aa0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17600,6 +17600,11 @@ static void RemoveNestedImmediateInvocation(
DRSet.erase(E);
return E;
}
+ ExprResult TransformLambdaExpr(LambdaExpr *E) {
+ // Do not rebuild lambdas to avoid creating a new type.
+ // Lambdas have already been processed inside their eval context.
+ return E;
+ }
bool AlwaysRebuild() { return false; }
bool ReplacingOriginal() { return true; }
bool AllowSkippingCXXConstructExpr() {
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d3b454843234..bf7ca718a36b 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -695,10 +695,10 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
// member of reference type uninitialized, the program is
// ill-formed.
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
- << Field->getType()
- << ILE->getSyntacticForm()->getSourceRange();
- SemaRef.Diag(Field->getLocation(),
- diag::note_uninit_reference_member);
+ << Field->getType()
+ << (ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm())
+ ->getSourceRange();
+ SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member);
}
hadError = true;
return;
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 68158ec977cf..5d0d87fd2422 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -939,11 +939,9 @@ bool Sema::LookupBuiltin(LookupResult &R) {
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
- // In C++, C2x, and OpenCL (spec v1.2 s6.9.f), we don't have any
- // predefined library functions like 'malloc'. Instead, we'll just
- // error.
- if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL ||
- getLangOpts().C2x) &&
+ // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined
+ // library functions like 'malloc'. Instead, we'll just error.
+ if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL) &&
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return false;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3ab5d26a9a75..edcac4d2ee9a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -6443,6 +6443,9 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
+ while (BTFTagAttributedTypeLoc TL = CurrTL.getAs<BTFTagAttributedTypeLoc>())
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+
while (DependentAddressSpaceTypeLoc TL =
CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 19149d079822..ab65612bce90 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2839,6 +2839,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
return;
}
+ if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
+ // FIXME: We should meaningfully implement this.
+ (void)TPO;
+ return;
+ }
+
llvm_unreachable("Support for this Decl not implemented.");
}
diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
index 0143b5f8df6b..655be20572b6 100644
--- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -165,8 +165,8 @@ struct TransferableCommand {
const unsigned OldPos = Pos;
std::unique_ptr<llvm::opt::Arg> Arg(OptTable.ParseOneArg(
ArgList, Pos,
- /* Include */ ClangCLMode ? CoreOption | CLOption : 0,
- /* Exclude */ ClangCLMode ? 0 : CLOption));
+ /* Include */ ClangCLMode ? CoreOption | CLOption | CLDXCOption : 0,
+ /* Exclude */ ClangCLMode ? 0 : CLOption | CLDXCOption));
if (!Arg)
continue;
diff --git a/clang/lib/Tooling/Syntax/Tokens.cpp b/clang/lib/Tooling/Syntax/Tokens.cpp
index e2014f965c90..1fa73c667b7f 100644
--- a/clang/lib/Tooling/Syntax/Tokens.cpp
+++ b/clang/lib/Tooling/Syntax/Tokens.cpp
@@ -55,45 +55,140 @@ getTokensCovering(llvm::ArrayRef<syntax::Token> Toks, SourceRange R,
return {Begin, End};
}
-// Finds the smallest expansion range that contains expanded tokens First and
-// Last, e.g.:
+// Finds the range within FID corresponding to expanded tokens [First, Last].
+// Prev precedes First and Next follows Last, these must *not* be included.
+// If no range satisfies the criteria, returns an invalid range.
+//
// #define ID(x) x
// ID(ID(ID(a1) a2))
// ~~ -> a1
// ~~ -> a2
// ~~~~~~~~~ -> a1 a2
-SourceRange findCommonRangeForMacroArgs(const syntax::Token &First,
- const syntax::Token &Last,
- const SourceManager &SM) {
- SourceRange Res;
- auto FirstLoc = First.location(), LastLoc = Last.location();
- // Keep traversing up the spelling chain as longs as tokens are part of the
- // same expansion.
- while (!FirstLoc.isFileID() && !LastLoc.isFileID()) {
- auto ExpInfoFirst = SM.getSLocEntry(SM.getFileID(FirstLoc)).getExpansion();
- auto ExpInfoLast = SM.getSLocEntry(SM.getFileID(LastLoc)).getExpansion();
- // Stop if expansions have diverged.
- if (ExpInfoFirst.getExpansionLocStart() !=
- ExpInfoLast.getExpansionLocStart())
+SourceRange spelledForExpandedSlow(SourceLocation First, SourceLocation Last,
+ SourceLocation Prev, SourceLocation Next,
+ FileID TargetFile,
+ const SourceManager &SM) {
+ // There are two main parts to this algorithm:
+ // - identifying which spelled range covers the expanded tokens
+ // - validating that this range doesn't cover any extra tokens (First/Last)
+ //
+ // We do these in order. However as we transform the expanded range into the
+ // spelled one, we adjust First/Last so the validation remains simple.
+
+ assert(SM.getSLocEntry(TargetFile).isFile());
+ // In most cases, to select First and Last we must return their expansion
+ // range, i.e. the whole of any macros they are included in.
+ //
+ // When First and Last are part of the *same macro arg* of a macro written
+ // in TargetFile, we that slice of the arg, i.e. their spelling range.
+ //
+ // Unwrap such macro calls. If the target file has A(B(C)), the
+ // SourceLocation stack of a token inside C shows us the expansion of A first,
+ // then B, then any macros inside C's body, then C itself.
+ // (This is the reverse of the order the PP applies the expansions in).
+ while (First.isMacroID() && Last.isMacroID()) {
+ auto DecFirst = SM.getDecomposedLoc(First);
+ auto DecLast = SM.getDecomposedLoc(Last);
+ auto &ExpFirst = SM.getSLocEntry(DecFirst.first).getExpansion();
+ auto &ExpLast = SM.getSLocEntry(DecLast.first).getExpansion();
+
+ if (!ExpFirst.isMacroArgExpansion() || !ExpLast.isMacroArgExpansion())
+ break;
+ // Locations are in the same macro arg if they expand to the same place.
+ // (They may still have different FileIDs - an arg can have >1 chunks!)
+ if (ExpFirst.getExpansionLocStart() != ExpLast.getExpansionLocStart())
break;
- // Do not continue into macro bodies.
- if (!ExpInfoFirst.isMacroArgExpansion() ||
- !ExpInfoLast.isMacroArgExpansion())
+ // Careful, given:
+ // #define HIDE ID(ID(a))
+ // ID(ID(HIDE))
+ // The token `a` is wrapped in 4 arg-expansions, we only want to unwrap 2.
+ // We distinguish them by whether the macro expands into the target file.
+ // Fortunately, the target file ones will always appear first.
+ auto &ExpMacro =
+ SM.getSLocEntry(SM.getFileID(ExpFirst.getExpansionLocStart()))
+ .getExpansion();
+ if (ExpMacro.getExpansionLocStart().isMacroID())
break;
- FirstLoc = SM.getImmediateSpellingLoc(FirstLoc);
- LastLoc = SM.getImmediateSpellingLoc(LastLoc);
- // Update the result afterwards, as we want the tokens that triggered the
- // expansion.
- Res = {FirstLoc, LastLoc};
+ // Replace each endpoint with its spelling inside the macro arg.
+ // (This is getImmediateSpellingLoc without repeating lookups).
+ First = ExpFirst.getSpellingLoc().getLocWithOffset(DecFirst.second);
+ Last = ExpLast.getSpellingLoc().getLocWithOffset(DecLast.second);
+
+ // Now: how do we adjust the previous/next bounds? Three cases:
+ // A) If they are also part of the same macro arg, we translate them too.
+ // This will ensure that we don't select any macros nested within the
+ // macro arg that cover extra tokens. Critical case:
+ // #define ID(X) X
+ // ID(prev target) // selecting 'target' succeeds
+ // #define LARGE ID(prev target)
+ // LARGE // selecting 'target' fails.
+ // B) They are not in the macro at all, then their expansion range is a
+ // sibling to it, and we can safely substitute that.
+ // #define PREV prev
+ // #define ID(X) X
+ // PREV ID(target) // selecting 'target' succeeds.
+ // #define LARGE PREV ID(target)
+ // LARGE // selecting 'target' fails.
+ // C) They are in a different arg of this macro, or the macro body.
+ // Now selecting the whole macro arg is fine, but the whole macro is not.
+ // Model this by setting using the edge of the macro call as the bound.
+ // #define ID2(X, Y) X Y
+ // ID2(prev, target) // selecting 'target' succeeds
+ // #define LARGE ID2(prev, target)
+ // LARGE // selecting 'target' fails
+ auto AdjustBound = [&](SourceLocation &Bound) {
+ if (Bound.isInvalid() || !Bound.isMacroID()) // Non-macro must be case B.
+ return;
+ auto DecBound = SM.getDecomposedLoc(Bound);
+ auto &ExpBound = SM.getSLocEntry(DecBound.first).getExpansion();
+ if (ExpBound.isMacroArgExpansion() &&
+ ExpBound.getExpansionLocStart() == ExpFirst.getExpansionLocStart()) {
+ // Case A: translate to (spelling) loc within the macro arg.
+ Bound = ExpBound.getSpellingLoc().getLocWithOffset(DecBound.second);
+ return;
+ }
+ while (Bound.isMacroID()) {
+ SourceRange Exp = SM.getImmediateExpansionRange(Bound).getAsRange();
+ if (Exp.getBegin() == ExpMacro.getExpansionLocStart()) {
+ // Case B: bounds become the macro call itself.
+ Bound = (&Bound == &Prev) ? Exp.getBegin() : Exp.getEnd();
+ return;
+ }
+ // Either case C, or expansion location will later find case B.
+ // We choose the upper bound for Prev and the lower one for Next:
+ // ID(prev) target ID(next)
+ // ^ ^
+ // new-prev new-next
+ Bound = (&Bound == &Prev) ? Exp.getEnd() : Exp.getBegin();
+ }
+ };
+ AdjustBound(Prev);
+ AdjustBound(Next);
}
- // Normally mapping back to expansion location here only changes FileID, as
- // we've already found some tokens expanded from the same macro argument, and
- // they should map to a consecutive subset of spelled tokens. Unfortunately
- // SourceManager::isBeforeInTranslationUnit discriminates sourcelocations
- // based on their FileID in addition to offsets. So even though we are
- // referring to same tokens, SourceManager might tell us that one is before
- // the other if they've got different FileIDs.
- return SM.getExpansionRange(CharSourceRange(Res, true)).getAsRange();
+
+ // In all remaining cases we need the full containing macros.
+ // If this overlaps Prev or Next, then no range is possible.
+ SourceRange Candidate =
+ SM.getExpansionRange(SourceRange(First, Last)).getAsRange();
+ auto DecFirst = SM.getDecomposedExpansionLoc(Candidate.getBegin());
+ auto DecLast = SM.getDecomposedLoc(Candidate.getEnd());
+ // Can end up in the wrong file due to bad input or token-pasting shenanigans.
+ if (Candidate.isInvalid() || DecFirst.first != TargetFile || DecLast.first != TargetFile)
+ return SourceRange();
+ // Check bounds, which may still be inside macros.
+ if (Prev.isValid()) {
+ auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Prev).getBegin());
+ if (Dec.first != DecFirst.first || Dec.second >= DecFirst.second)
+ return SourceRange();
+ }
+ if (Next.isValid()) {
+ auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Next).getEnd());
+ if (Dec.first != DecLast.first || Dec.second <= DecLast.second)
+ return SourceRange();
+ }
+ // Now we know that Candidate is a file range that covers [First, Last]
+ // without encroaching on {Prev, Next}. Ship it!
+ return Candidate;
}
} // namespace
@@ -363,51 +458,50 @@ TokenBuffer::spelledForExpanded(llvm::ArrayRef<syntax::Token> Expanded) const {
// of the range, bail out in that case.
if (Expanded.empty())
return llvm::None;
-
- const syntax::Token *BeginSpelled;
- const Mapping *BeginMapping;
- std::tie(BeginSpelled, BeginMapping) =
- spelledForExpandedToken(&Expanded.front());
-
- const syntax::Token *LastSpelled;
- const Mapping *LastMapping;
- std::tie(LastSpelled, LastMapping) =
- spelledForExpandedToken(&Expanded.back());
-
- FileID FID = SourceMgr->getFileID(BeginSpelled->location());
+ const syntax::Token *First = &Expanded.front();
+ const syntax::Token *Last = &Expanded.back();
+ const syntax::Token *FirstSpelled, *LastSpelled;
+ const TokenBuffer::Mapping *FirstMapping, *LastMapping;
+ std::tie(FirstSpelled, FirstMapping) = spelledForExpandedToken(First);
+ std::tie(LastSpelled, LastMapping) = spelledForExpandedToken(Last);
+
+ FileID FID = SourceMgr->getFileID(FirstSpelled->location());
// FIXME: Handle multi-file changes by trying to map onto a common root.
if (FID != SourceMgr->getFileID(LastSpelled->location()))
return llvm::None;
const MarkedFile &File = Files.find(FID)->second;
- // If both tokens are coming from a macro argument expansion, try and map to
- // smallest part of the macro argument. BeginMapping && LastMapping check is
- // only for performance, they are a prerequisite for Expanded.front() and
- // Expanded.back() being part of a macro arg expansion.
- if (BeginMapping && LastMapping &&
- SourceMgr->isMacroArgExpansion(Expanded.front().location()) &&
- SourceMgr->isMacroArgExpansion(Expanded.back().location())) {
- auto CommonRange = findCommonRangeForMacroArgs(Expanded.front(),
- Expanded.back(), *SourceMgr);
- // It might be the case that tokens are arguments of different macro calls,
- // in that case we should continue with the logic below instead of returning
- // an empty range.
- if (CommonRange.isValid())
- return getTokensCovering(File.SpelledTokens, CommonRange, *SourceMgr);
+ // If the range is within one macro argument, the result may be only part of a
+ // Mapping. We must use the general (SourceManager-based) algorithm.
+ if (FirstMapping && FirstMapping == LastMapping &&
+ SourceMgr->isMacroArgExpansion(First->location()) &&
+ SourceMgr->isMacroArgExpansion(Last->location())) {
+ // We use excluded Prev/Next token for bounds checking.
+ SourceLocation Prev = (First == &ExpandedTokens.front())
+ ? SourceLocation()
+ : (First - 1)->location();
+ SourceLocation Next = (Last == &ExpandedTokens.back())
+ ? SourceLocation()
+ : (Last + 1)->location();
+ SourceRange Range = spelledForExpandedSlow(
+ First->location(), Last->location(), Prev, Next, FID, *SourceMgr);
+ if (Range.isInvalid())
+ return llvm::None;
+ return getTokensCovering(File.SpelledTokens, Range, *SourceMgr);
}
+ // Otherwise, use the fast version based on Mappings.
// Do not allow changes that doesn't cover full expansion.
- unsigned BeginExpanded = Expanded.begin() - ExpandedTokens.data();
- unsigned EndExpanded = Expanded.end() - ExpandedTokens.data();
- if (BeginMapping && BeginExpanded != BeginMapping->BeginExpanded)
+ unsigned FirstExpanded = Expanded.begin() - ExpandedTokens.data();
+ unsigned LastExpanded = Expanded.end() - ExpandedTokens.data();
+ if (FirstMapping && FirstExpanded != FirstMapping->BeginExpanded)
return llvm::None;
- if (LastMapping && LastMapping->EndExpanded != EndExpanded)
+ if (LastMapping && LastMapping->EndExpanded != LastExpanded)
return llvm::None;
- // All is good, return the result.
return llvm::makeArrayRef(
- BeginMapping ? File.SpelledTokens.data() + BeginMapping->BeginSpelled
- : BeginSpelled,
+ FirstMapping ? File.SpelledTokens.data() + FirstMapping->BeginSpelled
+ : FirstSpelled,
LastMapping ? File.SpelledTokens.data() + LastMapping->EndSpelled
: LastSpelled + 1);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 9af296b1853a..b29665a63390 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -6703,7 +6703,7 @@ INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
// Workaround a bug in glibc's "old" semaphore implementation by
// zero-initializing the sem_t contents. This has to be done here because
- // interceptors bind to the lowest symbols version by default, hitting the
+ // interceptors bind to the lowest version before glibc 2.36, hitting the
// buggy code path while the non-sanitized build of the same code works fine.
REAL(memset)(s, 0, sizeof(*s));
int res = REAL(sem_init)(s, pshared, value);
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 8c2f7614af53..c97cbae96fba 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -22,9 +22,21 @@
# pragma GCC system_header
#endif
+#if defined(__apple_build_version__)
+# define _LIBCPP_COMPILER_CLANG_BASED
+# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000)
+#elif defined(__clang__)
+# define _LIBCPP_COMPILER_CLANG_BASED
+# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
+#elif defined(__GNUC__)
+# define _LIBCPP_COMPILER_GCC
+#elif defined(_MSC_VER)
+# define _LIBCPP_COMPILER_MSVC
+#endif
+
#ifdef __cplusplus
-# define _LIBCPP_VERSION 15000
+# define _LIBCPP_VERSION 15007
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
@@ -198,18 +210,6 @@
# define __has_include(...) 0
# endif
-# if defined(__apple_build_version__)
-# define _LIBCPP_COMPILER_CLANG_BASED
-# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000)
-# elif defined(__clang__)
-# define _LIBCPP_COMPILER_CLANG_BASED
-# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
-# elif defined(__GNUC__)
-# define _LIBCPP_COMPILER_GCC
-# elif defined(_MSC_VER)
-# define _LIBCPP_COMPILER_MSVC
-# endif
-
# if !defined(_LIBCPP_COMPILER_CLANG_BASED) && __cplusplus < 201103L
# error "libc++ only supports C++03 with Clang-based compilers. Please enable C++11"
# endif
@@ -1101,6 +1101,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
# define _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION
# endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES
+// Leave the deprecation notices in by default, but don't remove unary_function and
+// binary_function entirely just yet. That way, folks will have one release to act
+// on the deprecation warnings.
+# ifndef _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION
+# define _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION
+# endif
+
# if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES)
# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS
# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION
diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index db3af6e24101..55b607f3f804 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -883,7 +883,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)>
#endif // _LIBCPP_NO_RTTI
};
-#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) && !defined(_LIBCPP_HAS_OBJC_ARC)
+#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME)
extern "C" void *_Block_copy(const void *);
extern "C" void _Block_release(const void *);
@@ -898,14 +898,22 @@ class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)>
public:
_LIBCPP_INLINE_VISIBILITY
explicit __func(__block_type const& __f)
+#ifdef _LIBCPP_HAS_OBJC_ARC
+ : __f_(__f)
+#else
: __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
+#endif
{ }
// [TODO] add && to save on a retain
_LIBCPP_INLINE_VISIBILITY
explicit __func(__block_type __f, const _Alloc& /* unused */)
+#ifdef _LIBCPP_HAS_OBJC_ARC
+ : __f_(__f)
+#else
: __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
+#endif
{ }
virtual __base<_Rp(_ArgTypes...)>* __clone() const {
@@ -921,8 +929,10 @@ public:
}
virtual void destroy() _NOEXCEPT {
+#ifndef _LIBCPP_HAS_OBJC_ARC
if (__f_)
_Block_release(__f_);
+#endif
__f_ = 0;
}
@@ -950,7 +960,7 @@ public:
#endif // _LIBCPP_NO_RTTI
};
-#endif // _LIBCPP_HAS_EXTENSION_BLOCKS && !_LIBCPP_HAS_OBJC_ARC
+#endif // _LIBCPP_HAS_EXTENSION_BLOCKS
} // namespace __function
diff --git a/libcxx/include/atomic b/libcxx/include/atomic
index 92da4820e928..3a93b9b0a108 100644
--- a/libcxx/include/atomic
+++ b/libcxx/include/atomic
@@ -1113,6 +1113,12 @@ _Tp kill_dependency(_Tp __y) _NOEXCEPT
# define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
#endif
+template <class _Tp>
+struct __libcpp_is_always_lock_free {
+ // __atomic_always_lock_free is available in all Standard modes
+ static const bool __value = __atomic_always_lock_free(sizeof(_Tp), 0);
+};
+
#ifdef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS
template<typename _Tp>
@@ -1404,42 +1410,8 @@ _Tp __cxx_atomic_fetch_xor(__cxx_atomic_lock_impl<_Tp>* __a,
return __old;
}
-#ifdef __cpp_lib_atomic_is_always_lock_free
-
-template<typename _Tp> struct __cxx_is_always_lock_free {
- enum { __value = __atomic_always_lock_free(sizeof(_Tp), 0) }; };
-
-#else
-
-template<typename _Tp> struct __cxx_is_always_lock_free { enum { __value = false }; };
-// Implementations must match the C ATOMIC_*_LOCK_FREE macro values.
-template<> struct __cxx_is_always_lock_free<bool> { enum { __value = 2 == ATOMIC_BOOL_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<char> { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<signed char> { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<unsigned char> { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; };
-#ifndef _LIBCPP_HAS_NO_CHAR8_T
-template<> struct __cxx_is_always_lock_free<char8_t> { enum { __value = 2 == ATOMIC_CHAR8_T_LOCK_FREE }; };
-#endif
-template<> struct __cxx_is_always_lock_free<char16_t> { enum { __value = 2 == ATOMIC_CHAR16_T_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<char32_t> { enum { __value = 2 == ATOMIC_CHAR32_T_LOCK_FREE }; };
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-template<> struct __cxx_is_always_lock_free<wchar_t> { enum { __value = 2 == ATOMIC_WCHAR_T_LOCK_FREE }; };
-#endif
-template<> struct __cxx_is_always_lock_free<short> { enum { __value = 2 == ATOMIC_SHORT_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<unsigned short> { enum { __value = 2 == ATOMIC_SHORT_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<int> { enum { __value = 2 == ATOMIC_INT_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<unsigned int> { enum { __value = 2 == ATOMIC_INT_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<long> { enum { __value = 2 == ATOMIC_LONG_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<unsigned long> { enum { __value = 2 == ATOMIC_LONG_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<long long> { enum { __value = 2 == ATOMIC_LLONG_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<unsigned long long> { enum { __value = 2 == ATOMIC_LLONG_LOCK_FREE }; };
-template<typename _Tp> struct __cxx_is_always_lock_free<_Tp*> { enum { __value = 2 == ATOMIC_POINTER_LOCK_FREE }; };
-template<> struct __cxx_is_always_lock_free<std::nullptr_t> { enum { __value = 2 == ATOMIC_POINTER_LOCK_FREE }; };
-
-#endif //__cpp_lib_atomic_is_always_lock_free
-
template <typename _Tp,
- typename _Base = typename conditional<__cxx_is_always_lock_free<_Tp>::__value,
+ typename _Base = typename conditional<__libcpp_is_always_lock_free<_Tp>::__value,
__cxx_atomic_base_impl<_Tp>,
__cxx_atomic_lock_impl<_Tp> >::type>
#else
@@ -1561,7 +1533,7 @@ struct __atomic_base // false
mutable __cxx_atomic_impl<_Tp> __a_;
#if defined(__cpp_lib_atomic_is_always_lock_free)
- static _LIBCPP_CONSTEXPR bool is_always_lock_free = __atomic_always_lock_free(sizeof(__a_), 0);
+ static _LIBCPP_CONSTEXPR bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value;
#endif
_LIBCPP_INLINE_VISIBILITY
@@ -2664,7 +2636,7 @@ typedef atomic<uintmax_t> atomic_uintmax_t;
// atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type
#ifdef __cpp_lib_atomic_is_always_lock_free
-# define _LIBCPP_CONTENTION_LOCK_FREE __atomic_always_lock_free(sizeof(__cxx_contention_t), 0)
+# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value
#else
# define _LIBCPP_CONTENTION_LOCK_FREE false
#endif
diff --git a/libcxx/include/stdatomic.h b/libcxx/include/stdatomic.h
index d9550c44061c..ff2a5682f5bb 100644
--- a/libcxx/include/stdatomic.h
+++ b/libcxx/include/stdatomic.h
@@ -121,7 +121,7 @@ using std::atomic_signal_fence // see below
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 20
+#if defined(__cplusplus) && _LIBCPP_STD_VER > 20
#include <atomic>
#include <version>
@@ -230,6 +230,6 @@ using std::atomic_thread_fence _LIBCPP_USING_IF_EXISTS;
# include_next <stdatomic.h>
# endif
-#endif // _LIBCPP_STD_VER > 20
+#endif // defined(__cplusplus) && _LIBCPP_STD_VER > 20
#endif // _LIBCPP_STDATOMIC_H
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 252a0f051ff5..63759407ce94 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -297,6 +297,7 @@ erase_if(vector<T, Allocator>& c, Predicate pred); // C++20
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/swap.h>
+#include <__utility/transaction.h>
#include <climits>
#include <cstdlib>
#include <cstring>
@@ -425,18 +426,27 @@ public:
value_type,
typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0);
- _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
- ~vector()
- {
- __annotate_delete();
- std::__debug_db_erase_c(this);
+private:
+ class __destroy_vector {
+ public:
+ _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {}
- if (this->__begin_ != nullptr)
- {
- __clear();
- __alloc_traits::deallocate(__alloc(), this->__begin_, capacity());
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void operator()() {
+ __vec_.__annotate_delete();
+ std::__debug_db_erase_c(std::addressof(__vec_));
+
+ if (__vec_.__begin_ != nullptr) {
+ __vec_.__clear();
+ __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity());
+ }
}
- }
+
+ private:
+ vector& __vec_;
+ };
+
+public:
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector(*this)(); }
_LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x);
_LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x, const __type_identity_t<allocator_type>& __a);
@@ -1075,12 +1085,14 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_AFTER_CXX17
vector<_Tp, _Allocator>::vector(size_type __n)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__n);
}
+ __guard.__complete();
}
#if _LIBCPP_STD_VER > 11
@@ -1089,12 +1101,14 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17
vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a)
: __end_cap_(nullptr, __a)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__n);
}
+ __guard.__complete();
}
#endif
@@ -1102,12 +1116,14 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_AFTER_CXX17
vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__n, __x);
}
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1120,9 +1136,11 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first,
typename iterator_traits<_InputIterator>::reference>::value,
_InputIterator>::type __last)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
for (; __first != __last; ++__first)
emplace_back(*__first);
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1135,9 +1153,11 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, c
typename iterator_traits<_InputIterator>::reference>::value>::type*)
: __end_cap_(nullptr, __a)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
for (; __first != __last; ++__first)
emplace_back(*__first);
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1150,13 +1170,15 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first,
typename iterator_traits<_ForwardIterator>::reference>::value,
_ForwardIterator>::type __last)
{
- _VSTD::__debug_db_insert_c(this);
- size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
+ size_type __n = static_cast<size_type>(std::distance(__first, __last));
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__first, __last, __n);
}
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1169,13 +1191,15 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __las
typename iterator_traits<_ForwardIterator>::reference>::value>::type*)
: __end_cap_(nullptr, __a)
{
- _VSTD::__debug_db_insert_c(this);
- size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
+ size_type __n = static_cast<size_type>(std::distance(__first, __last));
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__first, __last, __n);
}
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1183,13 +1207,15 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17
vector<_Tp, _Allocator>::vector(const vector& __x)
: __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc()))
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
size_type __n = __x.size();
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__x.__begin_, __x.__end_, __n);
}
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1197,13 +1223,15 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17
vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
: __end_cap_(nullptr, __a)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
size_type __n = __x.size();
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__x.__begin_, __x.__end_, __n);
}
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1243,7 +1271,9 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
else
{
typedef move_iterator<iterator> _Ip;
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
assign(_Ip(__x.begin()), _Ip(__x.end()));
+ __guard.__complete();
}
}
@@ -1254,12 +1284,14 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17
inline _LIBCPP_INLINE_VISIBILITY
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
if (__il.size() > 0)
{
__vallocate(__il.size());
__construct_at_end(__il.begin(), __il.end(), __il.size());
}
+ __guard.__complete();
}
template <class _Tp, class _Allocator>
@@ -1268,12 +1300,14 @@ inline _LIBCPP_INLINE_VISIBILITY
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
: __end_cap_(nullptr, __a)
{
- _VSTD::__debug_db_insert_c(this);
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ std::__debug_db_insert_c(this);
if (__il.size() > 0)
{
__vallocate(__il.size());
__construct_at_end(__il.begin(), __il.end(), __il.size());
}
+ __guard.__complete();
}
#endif // _LIBCPP_CXX03_LANG
@@ -2111,8 +2145,26 @@ public:
#else
_NOEXCEPT;
#endif
- _LIBCPP_CONSTEXPR_AFTER_CXX17 ~vector();
- _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n);
+
+private:
+ class __destroy_vector {
+ public:
+ _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {}
+
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void operator()() {
+ if (__vec_.__begin_ != nullptr)
+ __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap());
+ std::__debug_db_invalidate_all(this);
+ }
+
+ private:
+ vector& __vec_;
+ };
+
+public:
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 ~vector() { __destroy_vector(*this)(); }
+
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n);
#if _LIBCPP_STD_VER > 11
_LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n, const allocator_type& __a);
#endif
@@ -2647,12 +2699,14 @@ vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __la
__size_(0),
__cap_alloc_(0, __default_init_tag())
{
- size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ size_type __n = static_cast<size_type>(std::distance(__first, __last));
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__first, __last);
}
+ __guard.__complete();
}
template <class _Allocator>
@@ -2664,12 +2718,14 @@ vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __la
__size_(0),
__cap_alloc_(0, static_cast<__storage_allocator>(__a))
{
- size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
+ auto __guard = std::__make_transaction(__destroy_vector(*this));
+ size_type __n = static_cast<size_type>(std::distance(__first, __last));
if (__n > 0)
{
__vallocate(__n);
__construct_at_end(__first, __last);
}
+ __guard.__complete();
}
#ifndef _LIBCPP_CXX03_LANG
@@ -2708,15 +2764,6 @@ vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const alloca
template <class _Allocator>
_LIBCPP_CONSTEXPR_AFTER_CXX17
-vector<bool, _Allocator>::~vector()
-{
- if (__begin_ != nullptr)
- __storage_traits::deallocate(__alloc(), __begin_, __cap());
- std::__debug_db_invalidate_all(this);
-}
-
-template <class _Allocator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17
vector<bool, _Allocator>::vector(const vector& __v)
: __begin_(nullptr),
__size_(0),
diff --git a/libcxx/include/version b/libcxx/include/version
index 8ffb1747eb27..d0c6fe466e70 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -332,7 +332,7 @@ __cpp_lib_void_t 201411L <type_traits>
# undef __cpp_lib_execution
// # define __cpp_lib_execution 201902L
# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
-# define __cpp_lib_format 202106L
+// # define __cpp_lib_format 202106L
# endif
# define __cpp_lib_generic_unordered_lookup 201811L
# define __cpp_lib_int_pow2 202002L
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index c8865d128fb8..a4c6f893f10c 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -106,7 +106,10 @@ protected:
: symbolKind(k), isExternal(true), isCOMDAT(false),
writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false),
isRuntimePseudoReloc(false), deferUndefined(false), canInline(true),
- nameSize(n.size()), nameData(n.empty() ? nullptr : n.data()) {}
+ nameSize(n.size()), nameData(n.empty() ? nullptr : n.data()) {
+ assert((!n.empty() || k <= LastDefinedCOFFKind) &&
+ "If the name is empty, the Symbol must be a DefinedCOFF.");
+ }
const unsigned symbolKind : 8;
unsigned isExternal : 1;
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index df60c9032b2d..f39697d5d381 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -395,7 +395,7 @@ getThunk(DenseMap<uint64_t, Defined *> &lastThunks, Defined *target, uint64_t p,
default:
llvm_unreachable("Unexpected architecture");
}
- Defined *d = make<DefinedSynthetic>("", c);
+ Defined *d = make<DefinedSynthetic>("range_extension_thunk", c);
lastThunk = d;
return {d, true};
}
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 8fca1a686a79..56a516f9cdc1 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -750,12 +750,13 @@ void elf::riscvFinalizeRelax(int passes) {
p += size;
// For R_RISCV_ALIGN, we will place `offset` in a location (among NOPs)
- // to satisfy the alignment requirement. If `remove` is a multiple of 4,
- // it is as if we have skipped some NOPs. Otherwise we are in the middle
- // of a 4-byte NOP, and we need to rewrite the NOP sequence.
+ // to satisfy the alignment requirement. If both `remove` and r.addend
+ // are multiples of 4, it is as if we have skipped some NOPs. Otherwise
+ // we are in the middle of a 4-byte NOP, and we need to rewrite the NOP
+ // sequence.
int64_t skip = 0;
if (r.type == R_RISCV_ALIGN) {
- if (remove % 4 != 0) {
+ if (remove % 4 || r.addend % 4) {
skip = r.addend - remove;
int64_t j = 0;
for (; j + 4 <= skip; j += 4)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 296fb4220012..58d863776430 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1330,12 +1330,15 @@ static void readConfigs(opt::InputArgList &args) {
parseClangOption(std::string("-") + arg->getValue(), arg->getSpelling());
// GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or
- // relative path. Just ignore. If not ended with "lto-wrapper", consider it an
+ // relative path. Just ignore. If not ended with "lto-wrapper" (or
+ // "lto-wrapper.exe" for GCC cross-compiled for Windows), consider it an
// unsupported LLVMgold.so option and error.
- for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq))
- if (!StringRef(arg->getValue()).endswith("lto-wrapper"))
+ for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) {
+ StringRef v(arg->getValue());
+ if (!v.endswith("lto-wrapper") && !v.endswith("lto-wrapper.exe"))
error(arg->getSpelling() + ": unknown plugin option '" + arg->getValue() +
"'");
+ }
config->passPlugins = args::getStrings(args, OPT_load_pass_plugins);
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 927dc272b532..473809b05e9c 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1157,7 +1157,7 @@ template <class ELFT> void ObjFile<ELFT>::postParse() {
continue;
}
- if (binding == STB_WEAK)
+ if (sym.binding == STB_WEAK || binding == STB_WEAK)
continue;
std::lock_guard<std::mutex> lock(mu);
ctx->duplicates.push_back({&sym, this, sec, eSym.st_value});
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index fd0e4ec8834c..87034d41e87d 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -1587,6 +1587,15 @@ void ObjFile::registerEhFrames(Section &ehFrameSection) {
funcSym->unwindEntry = isec;
ehRelocator.commit();
}
+
+ // __eh_frame is marked as S_ATTR_LIVE_SUPPORT in input files, because FDEs
+ // are normally required to be kept alive if they reference a live symbol.
+ // However, we've explicitly created a dependency from a symbol to its FDE, so
+ // dead-stripping will just work as usual, and S_ATTR_LIVE_SUPPORT will only
+ // serve to incorrectly prevent us from dead-stripping duplicate FDEs for a
+ // live symbol (e.g. if there were multiple weak copies). Remove this flag to
+ // let dead-stripping proceed correctly.
+ ehFrameSection.flags &= ~S_ATTR_LIVE_SUPPORT;
}
std::string ObjFile::sourceFile() const {
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index c3f563d5572b..8f267251b7c0 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -158,7 +158,7 @@ class UnwindInfoSectionImpl final : public UnwindInfoSection {
public:
UnwindInfoSectionImpl() : cuOffsets(target->wordSize) {}
uint64_t getSize() const override { return unwindInfoSize; }
- void prepareRelocations() override;
+ void prepare() override;
void finalize() override;
void writeTo(uint8_t *buf) const override;
@@ -166,6 +166,7 @@ private:
void prepareRelocations(ConcatInputSection *);
void relocateCompactUnwind(std::vector<CompactUnwindEntry> &);
void encodePersonalities();
+ Symbol *canonicalizePersonality(Symbol *);
uint64_t unwindInfoSize = 0;
std::vector<decltype(symbols)::value_type> symbolsVec;
@@ -196,13 +197,13 @@ UnwindInfoSection::UnwindInfoSection()
// Record function symbols that may need entries emitted in __unwind_info, which
// stores unwind data for address ranges.
//
-// Note that if several adjacent functions have the same unwind encoding, LSDA,
-// and personality function, they share one unwind entry. For this to work,
-// functions without unwind info need explicit "no unwind info" unwind entries
-// -- else the unwinder would think they have the unwind info of the closest
-// function with unwind info right before in the image. Thus, we add function
-// symbols for each unique address regardless of whether they have associated
-// unwind info.
+// Note that if several adjacent functions have the same unwind encoding and
+// personality function and no LSDA, they share one unwind entry. For this to
+// work, functions without unwind info need explicit "no unwind info" unwind
+// entries -- else the unwinder would think they have the unwind info of the
+// closest function with unwind info right before in the image. Thus, we add
+// function symbols for each unique address regardless of whether they have
+// associated unwind info.
void UnwindInfoSection::addSymbol(const Defined *d) {
if (d->unwindEntry)
allEntriesAreOmitted = false;
@@ -218,14 +219,24 @@ void UnwindInfoSection::addSymbol(const Defined *d) {
}
}
-void UnwindInfoSectionImpl::prepareRelocations() {
+void UnwindInfoSectionImpl::prepare() {
// This iteration needs to be deterministic, since prepareRelocations may add
// entries to the GOT. Hence the use of a MapVector for
// UnwindInfoSection::symbols.
for (const Defined *d : make_second_range(symbols))
- if (d->unwindEntry &&
- d->unwindEntry->getName() == section_names::compactUnwind)
- prepareRelocations(d->unwindEntry);
+ if (d->unwindEntry) {
+ if (d->unwindEntry->getName() == section_names::compactUnwind) {
+ prepareRelocations(d->unwindEntry);
+ } else {
+ // We don't have to add entries to the GOT here because FDEs have
+ // explicit GOT relocations, so Writer::scanRelocations() will add those
+ // GOT entries. However, we still need to canonicalize the personality
+ // pointers (like prepareRelocations() does for CU entries) in order
+ // to avoid overflowing the 3-personality limit.
+ FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry];
+ fde.personality = canonicalizePersonality(fde.personality);
+ }
+ }
}
// Compact unwind relocations have different semantics, so we handle them in a
@@ -279,6 +290,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
continue;
}
+ // Similar to canonicalizePersonality(), but we also register a GOT entry.
if (auto *defined = dyn_cast<Defined>(s)) {
// Check if we have created a synthetic symbol at the same address.
Symbol *&personality =
@@ -291,6 +303,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
}
continue;
}
+
assert(isa<DylibSymbol>(s));
in.got->addEntry(s);
continue;
@@ -320,6 +333,18 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
}
}
+Symbol *UnwindInfoSectionImpl::canonicalizePersonality(Symbol *personality) {
+ if (auto *defined = dyn_cast_or_null<Defined>(personality)) {
+ // Check if we have created a synthetic symbol at the same address.
+ Symbol *&synth = personalityTable[{defined->isec, defined->value}];
+ if (synth == nullptr)
+ synth = defined;
+ else if (synth != defined)
+ return synth;
+ }
+ return personality;
+}
+
// We need to apply the relocations to the pre-link compact unwind section
// before converting it to post-link form. There should only be absolute
// relocations here: since we are not emitting the pre-link CU section, there
@@ -427,9 +452,9 @@ void UnwindInfoSectionImpl::finalize() {
// assigned, so we can relocate the __LD,__compact_unwind entries
// into a temporary buffer. Relocation is necessary in order to sort
// the CU entries by function address. Sorting is necessary so that
- // we can fold adjacent CU entries with identical
- // encoding+personality+lsda. Folding is necessary because it reduces
- // the number of CU entries by as much as 3 orders of magnitude!
+ // we can fold adjacent CU entries with identical encoding+personality
+ // and without any LSDA. Folding is necessary because it reduces the
+ // number of CU entries by as much as 3 orders of magnitude!
cuEntries.resize(symbols.size());
// The "map" part of the symbols MapVector was only needed for deduplication
// in addSymbol(). Now that we are done adding, move the contents to a plain
@@ -445,7 +470,7 @@ void UnwindInfoSectionImpl::finalize() {
return cuEntries[a].functionAddress < cuEntries[b].functionAddress;
});
- // Fold adjacent entries with matching encoding+personality+lsda
+ // Fold adjacent entries with matching encoding+personality and without LSDA
// We use three iterators on the same cuIndices to fold in-situ:
// (1) `foldBegin` is the first of a potential sequence of matching entries
// (2) `foldEnd` is the first non-matching entry after `foldBegin`.
@@ -455,11 +480,32 @@ void UnwindInfoSectionImpl::finalize() {
auto foldWrite = cuIndices.begin();
for (auto foldBegin = cuIndices.begin(); foldBegin < cuIndices.end();) {
auto foldEnd = foldBegin;
+ // Common LSDA encodings (e.g. for C++ and Objective-C) contain offsets from
+ // a base address. The base address is normally not contained directly in
+ // the LSDA, and in that case, the personality function treats the starting
+ // address of the function (which is computed by the unwinder) as the base
+ // address and interprets the LSDA accordingly. The unwinder computes the
+ // starting address of a function as the address associated with its CU
+ // entry. For this reason, we cannot fold adjacent entries if they have an
+ // LSDA, because folding would make the unwinder compute the wrong starting
+ // address for the functions with the folded entries, which in turn would
+ // cause the personality function to misinterpret the LSDA for those
+ // functions. In the very rare case where the base address is encoded
+ // directly in the LSDA, two functions at different addresses would
+ // necessarily have different LSDAs, so their CU entries would not have been
+ // folded anyway.
while (++foldEnd < cuIndices.end() &&
cuEntries[*foldBegin].encoding == cuEntries[*foldEnd].encoding &&
+ !cuEntries[*foldBegin].lsda && !cuEntries[*foldEnd].lsda &&
+ // If we've gotten to this point, we don't have an LSDA, which should
+ // also imply that we don't have a personality function, since in all
+ // likelihood a personality function needs the LSDA to do anything
+ // useful. It can be technically valid to have a personality function
+ // and no LSDA though (e.g. the C++ personality __gxx_personality_v0
+ // is just a no-op without LSDA), so we still check for personality
+ // function equivalence to handle that case.
cuEntries[*foldBegin].personality ==
cuEntries[*foldEnd].personality &&
- cuEntries[*foldBegin].lsda == cuEntries[*foldEnd].lsda &&
canFoldEncoding(cuEntries[*foldEnd].encoding))
;
*foldWrite++ = *foldBegin;
diff --git a/lld/MachO/UnwindInfoSection.h b/lld/MachO/UnwindInfoSection.h
index c6b334731c75..f2bc3213a127 100644
--- a/lld/MachO/UnwindInfoSection.h
+++ b/lld/MachO/UnwindInfoSection.h
@@ -24,7 +24,7 @@ public:
// section entirely.
bool isNeeded() const override { return !allEntriesAreOmitted; }
void addSymbol(const Defined *);
- virtual void prepareRelocations() = 0;
+ virtual void prepare() = 0;
protected:
UnwindInfoSection();
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 3c44a60f4be2..ce9672dd0b4f 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -675,7 +675,7 @@ void Writer::scanRelocations() {
}
}
- in.unwindInfo->prepareRelocations();
+ in.unwindInfo->prepare();
}
void Writer::scanSymbols() {
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index c9a6d0f06056..021c7683d170 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -1,8 +1,5 @@
/* Various liblldb typedefs that SWIG needs to know about. */
#define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */
-/* The ISO C99 standard specifies that in C++ implementations limit macros such
- as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */
-#define __STDC_LIMIT_MACROS
%include "stdint.i"
%include "lldb/lldb-defines.h"
diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig
index bf3de66b91bf..d45431c771ca 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -435,7 +435,7 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
%typemap(out) lldb::FileSP {
$result = nullptr;
- lldb::FileSP &sp = $1;
+ const lldb::FileSP &sp = $1;
if (sp) {
PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp));
if (!pyfile.IsValid())
diff --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h
index 244d328b51f4..aa45aeeec476 100644
--- a/lldb/include/lldb/API/SBType.h
+++ b/lldb/include/lldb/API/SBType.h
@@ -182,6 +182,8 @@ public:
lldb::SBType GetTemplateArgumentType(uint32_t idx);
+ /// Return the TemplateArgumentKind of the template argument at index idx.
+ /// Variadic argument packs are automatically expanded.
lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx);
lldb::SBType GetFunctionReturnType();
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 0ad05a27570e..aefd19d0a859 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -338,14 +338,28 @@ public:
GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) const;
- size_t GetNumTemplateArguments() const;
-
- lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const;
- CompilerType GetTypeTemplateArgument(size_t idx) const;
+ /// Return the number of template arguments the type has.
+ /// If expand_pack is true, then variadic argument packs are automatically
+ /// expanded to their supplied arguments. If it is false an argument pack
+ /// will only count as 1 argument.
+ size_t GetNumTemplateArguments(bool expand_pack = false) const;
+
+ // Return the TemplateArgumentKind of the template argument at index idx.
+ // If expand_pack is true, then variadic argument packs are automatically
+ // expanded to their supplied arguments. With expand_pack set to false, an
+ // arguement pack will count as 1 argument and return a type of Pack.
+ lldb::TemplateArgumentKind
+ GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const;
+ CompilerType GetTypeTemplateArgument(size_t idx,
+ bool expand_pack = false) const;
/// Returns the value of the template argument and its type.
+ /// If expand_pack is true, then variadic argument packs are automatically
+ /// expanded to their supplied arguments. With expand_pack set to false, an
+ /// arguement pack will count as 1 argument and it is invalid to call this
+ /// method on the pack argument.
llvm::Optional<IntegralTemplateArgument>
- GetIntegralTemplateArgument(size_t idx) const;
+ GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const;
CompilerType GetTypeForFormatters() const;
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index be5783596897..769449a4933b 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -346,14 +346,18 @@ public:
const char *name, bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) = 0;
- virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type);
+ virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
+ bool expand_pack);
virtual lldb::TemplateArgumentKind
- GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx);
- virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx);
+ GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx,
+ bool expand_pack);
+ virtual CompilerType
+ GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
+ bool expand_pack);
virtual llvm::Optional<CompilerType::IntegralTemplateArgument>
- GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx);
+ GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
+ bool expand_pack);
// Dumping types
diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index 533930c0544b..adc60a084367 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -542,7 +542,8 @@ uint32_t SBType::GetNumberOfTemplateArguments() {
LLDB_INSTRUMENT_VA(this);
if (IsValid())
- return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments();
+ return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(
+ /*expand_pack=*/true);
return 0;
}
@@ -553,13 +554,15 @@ lldb::SBType SBType::GetTemplateArgumentType(uint32_t idx) {
return SBType();
CompilerType type;
+ const bool expand_pack = true;
switch(GetTemplateArgumentKind(idx)) {
case eTemplateArgumentKindType:
- type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(idx);
+ type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(
+ idx, expand_pack);
break;
case eTemplateArgumentKindIntegral:
type = m_opaque_sp->GetCompilerType(false)
- .GetIntegralTemplateArgument(idx)
+ .GetIntegralTemplateArgument(idx, expand_pack)
->type;
break;
default:
@@ -574,7 +577,8 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) {
LLDB_INSTRUMENT_VA(this, idx);
if (IsValid())
- return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(idx);
+ return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(
+ idx, /*expand_pack=*/true);
return eTemplateArgumentKindNull;
}
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index c6eb693bba6b..a1ebe5830bb9 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -7096,7 +7096,8 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
}
size_t
-TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
+TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
+ bool expand_pack) {
if (!type)
return 0;
@@ -7111,8 +7112,17 @@ TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
const clang::ClassTemplateSpecializationDecl *template_decl =
llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
cxx_record_decl);
- if (template_decl)
- return template_decl->getTemplateArgs().size();
+ if (template_decl) {
+ const auto &template_arg_list = template_decl->getTemplateArgs();
+ size_t num_args = template_arg_list.size();
+ assert(num_args && "template specialization without any args");
+ if (expand_pack && num_args) {
+ const auto &pack = template_arg_list[num_args - 1];
+ if (pack.getKind() == clang::TemplateArgument::Pack)
+ num_args += pack.pack_size() - 1;
+ }
+ return num_args;
+ }
}
}
break;
@@ -7149,15 +7159,51 @@ TypeSystemClang::GetAsTemplateSpecialization(
}
}
+const TemplateArgument *
+GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl,
+ size_t idx, bool expand_pack) {
+ const auto &args = decl->getTemplateArgs();
+ const size_t args_size = args.size();
+
+ assert(args_size && "template specialization without any args");
+ if (!args_size)
+ return nullptr;
+
+ const size_t last_idx = args_size - 1;
+
+ // We're asked for a template argument that can't be a parameter pack, so
+ // return it without worrying about 'expand_pack'.
+ if (idx < last_idx)
+ return &args[idx];
+
+ // We're asked for the last template argument but we don't want/need to
+ // expand it.
+ if (!expand_pack || args[last_idx].getKind() != clang::TemplateArgument::Pack)
+ return idx >= args.size() ? nullptr : &args[idx];
+
+ // Index into the expanded pack.
+ // Note that 'idx' counts from the beginning of all template arguments
+ // (including the ones preceding the parameter pack).
+ const auto &pack = args[last_idx];
+ const size_t pack_idx = idx - last_idx;
+ const size_t pack_size = pack.pack_size();
+ assert(pack_idx < pack_size && "parameter pack index out-of-bounds");
+ return &pack.pack_elements()[pack_idx];
+}
+
lldb::TemplateArgumentKind
TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
- size_t arg_idx) {
+ size_t arg_idx, bool expand_pack) {
const clang::ClassTemplateSpecializationDecl *template_decl =
GetAsTemplateSpecialization(type);
- if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size())
+ if (!template_decl)
+ return eTemplateArgumentKindNull;
+
+ const auto *arg = GetNthTemplateArgument(template_decl, arg_idx, expand_pack);
+ if (!arg)
return eTemplateArgumentKindNull;
- switch (template_decl->getTemplateArgs()[arg_idx].getKind()) {
+ switch (arg->getKind()) {
case clang::TemplateArgument::Null:
return eTemplateArgumentKindNull;
@@ -7190,35 +7236,32 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
CompilerType
TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx) {
+ size_t idx, bool expand_pack) {
const clang::ClassTemplateSpecializationDecl *template_decl =
GetAsTemplateSpecialization(type);
- if (!template_decl || idx >= template_decl->getTemplateArgs().size())
+ if (!template_decl)
return CompilerType();
- const clang::TemplateArgument &template_arg =
- template_decl->getTemplateArgs()[idx];
- if (template_arg.getKind() != clang::TemplateArgument::Type)
+ const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack);
+ if (!arg || arg->getKind() != clang::TemplateArgument::Type)
return CompilerType();
- return GetType(template_arg.getAsType());
+ return GetType(arg->getAsType());
}
Optional<CompilerType::IntegralTemplateArgument>
TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx) {
+ size_t idx, bool expand_pack) {
const clang::ClassTemplateSpecializationDecl *template_decl =
GetAsTemplateSpecialization(type);
- if (! template_decl || idx >= template_decl->getTemplateArgs().size())
+ if (!template_decl)
return llvm::None;
- const clang::TemplateArgument &template_arg =
- template_decl->getTemplateArgs()[idx];
- if (template_arg.getKind() != clang::TemplateArgument::Integral)
+ const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack);
+ if (!arg || arg->getKind() != clang::TemplateArgument::Integral)
return llvm::None;
- return {
- {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}};
+ return {{arg->getAsIntegral(), GetType(arg->getIntegralType())}};
}
CompilerType TypeSystemClang::GetTypeForFormatters(void *type) {
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 24dbb71c8f4d..7f25a6df548f 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -91,7 +91,7 @@ public:
void SetOwningModule(OptionalClangModuleID id);
/// \}
};
-
+
/// A TypeSystem implementation based on Clang.
///
/// This class uses a single clang::ASTContext as the backend for storing
@@ -334,7 +334,7 @@ public:
llvm::SmallVector<const char *, 2> names;
llvm::SmallVector<clang::TemplateArgument, 2> args;
-
+
const char * pack_name = nullptr;
std::unique_ptr<TemplateParameterInfos> packed_args;
};
@@ -537,7 +537,7 @@ public:
#ifndef NDEBUG
bool Verify(lldb::opaque_compiler_type_t type) override;
#endif
-
+
bool IsArrayType(lldb::opaque_compiler_type_t type,
CompilerType *element_type, uint64_t *size,
bool *is_incomplete) override;
@@ -810,16 +810,17 @@ public:
const char *name, bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) override;
- size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override;
+ size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
+ bool expand_pack) override;
lldb::TemplateArgumentKind
- GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
- size_t idx) override;
+ GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx,
+ bool expand_pack) override;
CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx) override;
+ size_t idx, bool expand_pack) override;
llvm::Optional<CompilerType::IntegralTemplateArgument>
- GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx) override;
+ GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
+ bool expand_pack) override;
CompilerType GetTypeForFormatters(void *type) override;
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index ac98352c235e..bef456583687 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -659,30 +659,32 @@ size_t CompilerType::GetIndexOfChildMemberWithName(
return 0;
}
-size_t CompilerType::GetNumTemplateArguments() const {
+size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const {
if (IsValid()) {
- return m_type_system->GetNumTemplateArguments(m_type);
+ return m_type_system->GetNumTemplateArguments(m_type, expand_pack);
}
return 0;
}
-TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const {
+TemplateArgumentKind
+CompilerType::GetTemplateArgumentKind(size_t idx, bool expand_pack) const {
if (IsValid())
- return m_type_system->GetTemplateArgumentKind(m_type, idx);
+ return m_type_system->GetTemplateArgumentKind(m_type, idx, expand_pack);
return eTemplateArgumentKindNull;
}
-CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const {
+CompilerType CompilerType::GetTypeTemplateArgument(size_t idx,
+ bool expand_pack) const {
if (IsValid()) {
- return m_type_system->GetTypeTemplateArgument(m_type, idx);
+ return m_type_system->GetTypeTemplateArgument(m_type, idx, expand_pack);
}
return CompilerType();
}
llvm::Optional<CompilerType::IntegralTemplateArgument>
-CompilerType::GetIntegralTemplateArgument(size_t idx) const {
+CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const {
if (IsValid())
- return m_type_system->GetIntegralTemplateArgument(m_type, idx);
+ return m_type_system->GetIntegralTemplateArgument(m_type, idx, expand_pack);
return llvm::None;
}
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 3092dc0bf0a4..412373533aab 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -118,23 +118,25 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) {
return CompilerType(this, type);
}
-size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
+size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
+ bool expand_pack) {
return 0;
}
TemplateArgumentKind
-TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) {
+TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
+ bool expand_pack) {
return eTemplateArgumentKindNull;
}
CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
- size_t idx) {
+ size_t idx, bool expand_pack) {
return CompilerType();
}
llvm::Optional<CompilerType::IntegralTemplateArgument>
-TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type,
- size_t idx) {
+TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
+ bool expand_pack) {
return llvm::None;
}
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index ea2847f8c8ee..07ac1768ea27 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -144,8 +144,12 @@ private:
};
template <typename ContextT>
-auto GenericCycleInfo<ContextT>::getTopLevelParentCycle(
- const BlockT *Block) const -> CycleT * {
+auto GenericCycleInfo<ContextT>::getTopLevelParentCycle(BlockT *Block)
+ -> CycleT * {
+ auto Cycle = BlockMapTopLevel.find(Block);
+ if (Cycle != BlockMapTopLevel.end())
+ return Cycle->second;
+
auto MapIt = BlockMap.find(Block);
if (MapIt == BlockMap.end())
return nullptr;
@@ -153,12 +157,15 @@ auto GenericCycleInfo<ContextT>::getTopLevelParentCycle(
auto *C = MapIt->second;
while (C->ParentCycle)
C = C->ParentCycle;
+ BlockMapTopLevel.try_emplace(Block, C);
return C;
}
template <typename ContextT>
-void GenericCycleInfo<ContextT>::moveToNewParent(CycleT *NewParent,
- CycleT *Child) {
+void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
+ CycleT *Child) {
+ assert((!Child->ParentCycle && !NewParent->ParentCycle) &&
+ "NewParent and Child must be both top level cycle!\n");
auto &CurrentContainer =
Child->ParentCycle ? Child->ParentCycle->Children : TopLevelCycles;
auto Pos = llvm::find_if(CurrentContainer, [=](const auto &Ptr) -> bool {
@@ -169,6 +176,13 @@ void GenericCycleInfo<ContextT>::moveToNewParent(CycleT *NewParent,
*Pos = std::move(CurrentContainer.back());
CurrentContainer.pop_back();
Child->ParentCycle = NewParent;
+
+ NewParent->Blocks.insert(NewParent->Blocks.end(), Child->block_begin(),
+ Child->block_end());
+
+ for (auto &It : BlockMapTopLevel)
+ if (It.second == Child)
+ It.second = NewParent;
}
/// \brief Main function of the cycle info computations.
@@ -240,10 +254,7 @@ void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
<< "discovered child cycle "
<< Info.Context.print(BlockParent->getHeader()) << "\n");
// Make BlockParent the child of NewCycle.
- Info.moveToNewParent(NewCycle.get(), BlockParent);
- NewCycle->Blocks.insert(NewCycle->Blocks.end(),
- BlockParent->block_begin(),
- BlockParent->block_end());
+ Info.moveTopLevelCycleToNewParent(NewCycle.get(), BlockParent);
for (auto *ChildEntry : BlockParent->entries())
ProcessPredecessors(ChildEntry);
@@ -257,6 +268,7 @@ void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
assert(!is_contained(NewCycle->Blocks, Block));
NewCycle->Blocks.push_back(Block);
ProcessPredecessors(Block);
+ Info.BlockMapTopLevel.try_emplace(Block, NewCycle.get());
}
} while (!Worklist.empty());
@@ -336,6 +348,7 @@ void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
TopLevelCycles.clear();
BlockMap.clear();
+ BlockMapTopLevel.clear();
}
/// \brief Compute the cycle info for a function.
diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h
index 970664b85715..5f851b795cbc 100644
--- a/llvm/include/llvm/ADT/GenericCycleInfo.h
+++ b/llvm/include/llvm/ADT/GenericCycleInfo.h
@@ -232,15 +232,24 @@ public:
private:
ContextT Context;
- /// Map basic blocks to their inner-most containing loop.
+ /// Map basic blocks to their inner-most containing cycle.
DenseMap<BlockT *, CycleT *> BlockMap;
+ /// Map basic blocks to their top level containing cycle.
+ DenseMap<BlockT *, CycleT *> BlockMapTopLevel;
+
/// Outermost cycles discovered by any DFS.
///
/// Note: The implementation treats the nullptr as the parent of
/// every top-level cycle. See \ref contains for an example.
std::vector<std::unique_ptr<CycleT>> TopLevelCycles;
+ /// Move \p Child to \p NewParent by manipulating Children vectors.
+ ///
+ /// Note: This is an incomplete operation that does not update the depth of
+ /// the subtree.
+ void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);
+
public:
GenericCycleInfo() = default;
GenericCycleInfo(GenericCycleInfo &&) = default;
@@ -254,13 +263,7 @@ public:
CycleT *getCycle(const BlockT *Block) const;
unsigned getCycleDepth(const BlockT *Block) const;
- CycleT *getTopLevelParentCycle(const BlockT *Block) const;
-
- /// Move \p Child to \p NewParent by manipulating Children vectors.
- ///
- /// Note: This is an incomplete operation that does not update the
- /// list of blocks in the new parent or the depth of the subtree.
- void moveToNewParent(CycleT *NewParent, CycleT *Child);
+ CycleT *getTopLevelParentCycle(BlockT *Block);
/// Methods for debug and self-test.
//@{
diff --git a/llvm/include/llvm/DebugInfo/Symbolize/MarkupFilter.h b/llvm/include/llvm/DebugInfo/Symbolize/MarkupFilter.h
index 26686143af95..a54f8f5d2db8 100644
--- a/llvm/include/llvm/DebugInfo/Symbolize/MarkupFilter.h
+++ b/llvm/include/llvm/DebugInfo/Symbolize/MarkupFilter.h
@@ -26,11 +26,14 @@
namespace llvm {
namespace symbolize {
+class LLVMSymbolizer;
+
/// Filter to convert parsed log symbolizer markup elements into human-readable
/// text.
class MarkupFilter {
public:
- MarkupFilter(raw_ostream &OS, Optional<bool> ColorsEnabled = llvm::None);
+ MarkupFilter(raw_ostream &OS, LLVMSymbolizer &Symbolizer,
+ Optional<bool> ColorsEnabled = llvm::None);
/// Filters a line containing symbolizer markup and writes the human-readable
/// results to the output stream.
@@ -57,6 +60,7 @@ private:
uint64_t ModuleRelativeAddr;
bool contains(uint64_t Addr) const;
+ uint64_t getModuleRelativeAddr(uint64_t Addr) const;
};
// An informational module line currently being constructed. As many mmap
@@ -67,6 +71,15 @@ private:
SmallVector<const MMap *> MMaps = {};
};
+ // The semantics of a possible program counter value.
+ enum class PCType {
+ // The address is a return address and must be adjusted to point to the call
+ // itself.
+ ReturnAddress,
+ // The address is the precise location in the code and needs no adjustment.
+ PreciseCode,
+ };
+
bool tryContextualElement(const MarkupNode &Node,
const SmallVector<MarkupNode> &DeferredNodes);
bool tryMMap(const MarkupNode &Element,
@@ -83,6 +96,9 @@ private:
bool tryPresentation(const MarkupNode &Node);
bool trySymbol(const MarkupNode &Node);
+ bool tryPC(const MarkupNode &Node);
+ bool tryBackTrace(const MarkupNode &Node);
+ bool tryData(const MarkupNode &Node);
bool trySGR(const MarkupNode &Node);
@@ -91,6 +107,9 @@ private:
void restoreColor();
void resetColor();
+ void printRawElement(const MarkupNode &Element);
+ void printValue(Twine Value);
+
Optional<Module> parseModule(const MarkupNode &Element) const;
Optional<MMap> parseMMap(const MarkupNode &Element) const;
@@ -99,19 +118,26 @@ private:
Optional<uint64_t> parseSize(StringRef Str) const;
Optional<SmallVector<uint8_t>> parseBuildID(StringRef Str) const;
Optional<std::string> parseMode(StringRef Str) const;
+ Optional<PCType> parsePCType(StringRef Str) const;
+ Optional<uint64_t> parseFrameNumber(StringRef Str) const;
bool checkTag(const MarkupNode &Node) const;
bool checkNumFields(const MarkupNode &Element, size_t Size) const;
bool checkNumFieldsAtLeast(const MarkupNode &Element, size_t Size) const;
+ bool checkNumFieldsAtMost(const MarkupNode &Element, size_t Size) const;
void reportTypeError(StringRef Str, StringRef TypeName) const;
void reportLocation(StringRef::iterator Loc) const;
- const MMap *overlappingMMap(const MMap &Map) const;
+ const MMap *getOverlappingMMap(const MMap &Map) const;
+ const MMap *getContainingMMap(uint64_t Addr) const;
+
+ uint64_t adjustAddr(uint64_t Addr, PCType Type) const;
StringRef lineEnding() const;
raw_ostream &OS;
+ LLVMSymbolizer &Symbolizer;
const bool ColorsEnabled;
MarkupParser Parser;
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 794d29fd9913..5eb43777a951 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -1028,7 +1028,7 @@ ELFFile<ELFT>::getVersionDependencies(const Elf_Shdr &Sec,
VN.Offset = VerneedBuf - Start;
if (Verneed->vn_file < StrTab.size())
- VN.File = std::string(StrTab.drop_front(Verneed->vn_file));
+ VN.File = std::string(StrTab.data() + Verneed->vn_file);
else
VN.File = ("<corrupt vn_file: " + Twine(Verneed->vn_file) + ">").str();
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 2958a5054afc..c784c27d36b4 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -5917,8 +5917,13 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
if (const SCEV *S = createNodeFromSelectLikePHI(PN))
return S;
+ // If the PHI has a single incoming value, follow that value, unless the
+ // PHI's incoming blocks are in a different loop, in which case doing so
+ // risks breaking LCSSA form. Instcombine would normally zap these, but
+ // it doesn't have DominatorTree information, so it may miss cases.
if (Value *V = simplifyInstruction(PN, {getDataLayout(), &TLI, &DT, &AC}))
- return getSCEV(V);
+ if (LI.replacementPreservesLCSSAForm(PN, V))
+ return getSCEV(V);
// If it's not a loop phi, we can't handle it yet.
return getUnknown(PN);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2dd671b4ab9e..569ee6b3ea86 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3593,14 +3593,23 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
// Unsigned integers are always nonnegative.
case Instruction::UIToFP:
return true;
- case Instruction::FMul:
case Instruction::FDiv:
- // X * X is always non-negative or a NaN.
// X / X is always exactly 1.0 or a NaN.
if (I->getOperand(0) == I->getOperand(1) &&
(!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()))
return true;
+ // Set SignBitOnly for RHS, because X / -0.0 is -Inf (or NaN).
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
+ Depth + 1) &&
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI,
+ /*SignBitOnly*/ true, Depth + 1);
+ case Instruction::FMul:
+ // X * X is always non-negative or a NaN.
+ if (I->getOperand(0) == I->getOperand(1) &&
+ (!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()))
+ return true;
+
LLVM_FALLTHROUGH;
case Instruction::FAdd:
case Instruction::FRem:
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index c4795a80ead2..bc20f33f174c 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1110,6 +1110,12 @@ void InterleavedAccessInfo::collectConstStrideAccesses(
continue;
Type *ElementTy = getLoadStoreType(&I);
+ // Currently, codegen doesn't support cases where the type size doesn't
+ // match the alloc size. Skip them for now.
+ uint64_t Size = DL.getTypeAllocSize(ElementTy);
+ if (Size * 8 != DL.getTypeSizeInBits(ElementTy))
+ continue;
+
// We don't check wrapping here because we don't know yet if Ptr will be
// part of a full group or a group with gaps. Checking wrapping for all
// pointers (even those that end up in groups with no gaps) will be overly
@@ -1121,7 +1127,6 @@ void InterleavedAccessInfo::collectConstStrideAccesses(
/*Assume=*/true, /*ShouldCheckWrap=*/false);
const SCEV *Scev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr);
- uint64_t Size = DL.getTypeAllocSize(ElementTy);
AccessStrideInfo[&I] = StrideDescriptor(Stride, Scev, Size,
getLoadStoreAlignment(&I));
}
diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
index fb8a3e383950..aa81f618dc59 100644
--- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
@@ -25,6 +25,7 @@
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
@@ -247,6 +248,13 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() {
// Call the rewind function.
CallInst *CI =
CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);
+ // The verifier requires that all calls of debug-info-bearing functions
+ // from debug-info-bearing functions have a debug location (for inlining
+ // purposes). Assign a dummy location to satisfy the constraint.
+ Function *RewindFn = dyn_cast<Function>(RewindFunction.getCallee());
+ if (RewindFn && RewindFn->getSubprogram())
+ if (DISubprogram *SP = F.getSubprogram())
+ CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP));
CI->setCallingConv(RewindFunctionCallingConv);
// We never expect _Unwind_Resume to return.
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 89a43c4f57f6..a8d40edd88d3 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -1237,7 +1237,13 @@ void PEI::insertZeroCallUsedRegs(MachineFunction &MF) {
if (!MO.isReg())
continue;
- for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(MO.getReg()))
+ MCRegister Reg = MO.getReg();
+
+ // This picks up sibling registers (e.q. %al -> %ah).
+ for (MCRegUnitIterator Unit(Reg, &TRI); Unit.isValid(); ++Unit)
+ RegsToZero.reset(*Unit);
+
+ for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(Reg))
RegsToZero.reset(SReg);
}
}
@@ -1262,9 +1268,10 @@ void PEI::insertZeroCallUsedRegs(MachineFunction &MF) {
}
}
- // Don't clear registers that are reset before exiting.
- for (const CalleeSavedInfo &CSI : MF.getFrameInfo().getCalleeSavedInfo())
- for (MCRegister Reg : TRI.sub_and_superregs_inclusive(CSI.getReg()))
+ // Don't clear registers that must be preserved.
+ for (const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF);
+ MCPhysReg CSReg = *CSRegs; ++CSRegs)
+ for (MCRegister Reg : TRI.sub_and_superregs_inclusive(CSReg))
RegsToZero.reset(Reg);
const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 9e4e26f1392e..cb552f212fbb 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -443,6 +443,9 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
SpilledOperandsMap[MO->getParent()].push_back(MO);
for (auto MISpilledOperands : SpilledOperandsMap) {
MachineInstr &DBG = *MISpilledOperands.first;
+ // We don't have enough support for tracking operands of DBG_VALUE_LISTs.
+ if (DBG.isDebugValueList())
+ continue;
MachineInstr *NewDV = buildDbgValueForSpill(
*MBB, Before, *MISpilledOperands.first, FI, MISpilledOperands.second);
assert(NewDV->getParent() == MBB && "dangling parent pointer");
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 42a141e8876b..a7f9382478d4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -7163,9 +7163,8 @@ static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift,
SDValue ExtractFrom, SDValue &Mask,
const SDLoc &DL) {
assert(OppShift && ExtractFrom && "Empty SDValue");
- assert(
- (OppShift.getOpcode() == ISD::SHL || OppShift.getOpcode() == ISD::SRL) &&
- "Existing shift must be valid as a rotate half");
+ if (OppShift.getOpcode() != ISD::SHL && OppShift.getOpcode() != ISD::SRL)
+ return SDValue();
ExtractFrom = stripConstantMask(DAG, ExtractFrom, Mask);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 35650b9bd00e..ecdaef0442da 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9693,6 +9693,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
Entry.Alignment = Alignment;
CLI.getArgs().insert(CLI.getArgs().begin(), Entry);
CLI.NumFixedArgs += 1;
+ CLI.getArgs()[0].IndirectType = CLI.RetTy;
CLI.RetTy = Type::getVoidTy(CLI.RetTy->getContext());
// sret demotion isn't compatible with tail-calls, since the sret argument
diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp
index 8dc8d381ad16..36e3c1245f1c 100644
--- a/llvm/lib/CodeGen/TypePromotion.cpp
+++ b/llvm/lib/CodeGen/TypePromotion.cpp
@@ -569,7 +569,7 @@ void IRPromoter::TruncateSinks() {
void IRPromoter::Cleanup() {
LLVM_DEBUG(dbgs() << "IR Promotion: Cleanup..\n");
// Some zexts will now have become redundant, along with their trunc
- // operands, so remove them
+ // operands, so remove them.
for (auto *V : Visited) {
if (!isa<ZExtInst>(V))
continue;
@@ -620,6 +620,8 @@ void IRPromoter::ConvertTruncs() {
ConstantInt *Mask =
ConstantInt::get(SrcTy, APInt::getMaxValue(NumBits).getZExtValue());
Value *Masked = Builder.CreateAnd(Trunc->getOperand(0), Mask);
+ if (SrcTy != ExtTy)
+ Masked = Builder.CreateTrunc(Masked, ExtTy);
if (auto *I = dyn_cast<Instruction>(Masked))
NewInsts.insert(I);
diff --git a/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp b/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp
index 91a51485026e..d96c0c85d5bd 100644
--- a/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp
@@ -20,11 +20,14 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/Symbolize/Markup.h"
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
@@ -32,9 +35,11 @@
using namespace llvm;
using namespace llvm::symbolize;
-MarkupFilter::MarkupFilter(raw_ostream &OS, Optional<bool> ColorsEnabled)
- : OS(OS), ColorsEnabled(ColorsEnabled.value_or(
- WithColor::defaultAutoDetectFunction()(OS))) {}
+MarkupFilter::MarkupFilter(raw_ostream &OS, LLVMSymbolizer &Symbolizer,
+ Optional<bool> ColorsEnabled)
+ : OS(OS), Symbolizer(Symbolizer),
+ ColorsEnabled(
+ ColorsEnabled.value_or(WithColor::defaultAutoDetectFunction()(OS))) {}
void MarkupFilter::filter(StringRef Line) {
this->Line = Line;
@@ -94,10 +99,10 @@ bool MarkupFilter::tryMMap(const MarkupNode &Node,
if (!ParsedMMap)
return true;
- if (const MMap *M = overlappingMMap(*ParsedMMap)) {
+ if (const MMap *M = getOverlappingMMap(*ParsedMMap)) {
WithColor::error(errs())
- << formatv("overlapping mmap: #{0:x} [{1:x},{2:x})\n", M->Mod->ID,
- M->Addr, M->Addr + M->Size);
+ << formatv("overlapping mmap: #{0:x} [{1:x}-{2:x}]\n", M->Mod->ID,
+ M->Addr, M->Addr + M->Size - 1);
reportLocation(Node.Fields[0].begin());
return true;
}
@@ -160,18 +165,17 @@ bool MarkupFilter::tryModule(const MarkupNode &Node,
filterNode(Node);
beginModuleInfoLine(&Module);
OS << "; BuildID=";
- highlightValue();
- OS << toHex(Module.BuildID, /*LowerCase=*/true);
- highlight();
+ printValue(toHex(Module.BuildID, /*LowerCase=*/true));
return true;
}
void MarkupFilter::beginModuleInfoLine(const Module *M) {
highlight();
OS << "[[[ELF module";
- highlightValue();
- OS << formatv(" #{0:x} \"{1}\"", M->ID, M->Name);
- highlight();
+ printValue(formatv(" #{0:x} ", M->ID));
+ OS << '"';
+ printValue(M->Name);
+ OS << '"';
MIL = ModuleInfoLine{M};
}
@@ -182,14 +186,13 @@ void MarkupFilter::endAnyModuleInfoLine() {
return A->Addr < B->Addr;
});
for (const MMap *M : MIL->MMaps) {
- OS << (M == MIL->MMaps.front() ? ' ' : '-');
- highlightValue();
- OS << formatv("{0:x}", M->Addr);
- highlight();
- OS << '(';
- highlightValue();
- OS << M->Mode;
- highlight();
+ OS << (M == MIL->MMaps.front() ? ' ' : ',');
+ OS << '[';
+ printValue(formatv("{0:x}", M->Addr));
+ OS << '-';
+ printValue(formatv("{0:x}", M->Addr + M->Size - 1));
+ OS << "](";
+ printValue(M->Mode);
OS << ')';
}
OS << "]]]" << lineEnding();
@@ -210,7 +213,13 @@ void MarkupFilter::filterNode(const MarkupNode &Node) {
}
bool MarkupFilter::tryPresentation(const MarkupNode &Node) {
- return trySymbol(Node);
+ if (trySymbol(Node))
+ return true;
+ if (tryPC(Node))
+ return true;
+ if (tryBackTrace(Node))
+ return true;
+ return tryData(Node);
}
bool MarkupFilter::trySymbol(const MarkupNode &Node) {
@@ -225,6 +234,172 @@ bool MarkupFilter::trySymbol(const MarkupNode &Node) {
return true;
}
+bool MarkupFilter::tryPC(const MarkupNode &Node) {
+ if (Node.Tag != "pc")
+ return false;
+ if (!checkNumFieldsAtLeast(Node, 1))
+ return true;
+ if (!checkNumFieldsAtMost(Node, 2))
+ return true;
+
+ Optional<uint64_t> Addr = parseAddr(Node.Fields[0]);
+ if (!Addr)
+ return true;
+
+ // PC addresses that aren't part of a backtrace are assumed to be precise code
+ // locations.
+ PCType Type = PCType::PreciseCode;
+ if (Node.Fields.size() == 2) {
+ Optional<PCType> ParsedType = parsePCType(Node.Fields[1]);
+ if (!ParsedType)
+ return true;
+ Type = *ParsedType;
+ }
+ *Addr = adjustAddr(*Addr, Type);
+
+ const MMap *MMap = getContainingMMap(*Addr);
+ if (!MMap) {
+ WithColor::error() << "no mmap covers address\n";
+ reportLocation(Node.Fields[0].begin());
+ printRawElement(Node);
+ return true;
+ }
+
+ Expected<DILineInfo> LI = Symbolizer.symbolizeCode(
+ MMap->Mod->BuildID, {MMap->getModuleRelativeAddr(*Addr)});
+ if (!LI) {
+ WithColor::defaultErrorHandler(LI.takeError());
+ printRawElement(Node);
+ return true;
+ }
+ if (!*LI) {
+ printRawElement(Node);
+ return true;
+ }
+
+ highlight();
+ printValue(LI->FunctionName);
+ OS << '[';
+ printValue(LI->FileName);
+ OS << ':';
+ printValue(Twine(LI->Line));
+ OS << ']';
+ restoreColor();
+ return true;
+}
+
+bool MarkupFilter::tryBackTrace(const MarkupNode &Node) {
+ if (Node.Tag != "bt")
+ return false;
+ if (!checkNumFieldsAtLeast(Node, 2))
+ return true;
+ if (!checkNumFieldsAtMost(Node, 3))
+ return true;
+
+ Optional<uint64_t> FrameNumber = parseFrameNumber(Node.Fields[0]);
+ if (!FrameNumber)
+ return true;
+
+ Optional<uint64_t> Addr = parseAddr(Node.Fields[1]);
+ if (!Addr)
+ return true;
+
+ // Backtrace addresses are assumed to be return addresses by default.
+ PCType Type = PCType::ReturnAddress;
+ if (Node.Fields.size() == 3) {
+ Optional<PCType> ParsedType = parsePCType(Node.Fields[2]);
+ if (!ParsedType)
+ return true;
+ Type = *ParsedType;
+ }
+ *Addr = adjustAddr(*Addr, Type);
+
+ const MMap *MMap = getContainingMMap(*Addr);
+ if (!MMap) {
+ WithColor::error() << "no mmap covers address\n";
+ reportLocation(Node.Fields[0].begin());
+ printRawElement(Node);
+ return true;
+ }
+ uint64_t MRA = MMap->getModuleRelativeAddr(*Addr);
+
+ Expected<DIInliningInfo> II =
+ Symbolizer.symbolizeInlinedCode(MMap->Mod->BuildID, {MRA});
+ if (!II) {
+ WithColor::defaultErrorHandler(II.takeError());
+ printRawElement(Node);
+ return true;
+ }
+
+ highlight();
+ for (unsigned I = 0, E = II->getNumberOfFrames(); I != E; ++I) {
+ auto Header = formatv("{0, +6}", formatv("#{0}", FrameNumber)).sstr<16>();
+ // Don't highlight the # sign as a value.
+ size_t NumberIdx = Header.find("#") + 1;
+ OS << Header.substr(0, NumberIdx);
+ printValue(Header.substr(NumberIdx));
+ if (I == E - 1) {
+ OS << " ";
+ } else {
+ OS << '.';
+ printValue(formatv("{0, -2}", I + 1));
+ }
+ printValue(formatv(" {0:x16} ", *Addr));
+
+ DILineInfo LI = II->getFrame(I);
+ if (LI) {
+ printValue(LI.FunctionName);
+ OS << ' ';
+ printValue(LI.FileName);
+ OS << ':';
+ printValue(Twine(LI.Line));
+ OS << ':';
+ printValue(Twine(LI.Column));
+ OS << ' ';
+ }
+ OS << '(';
+ printValue(MMap->Mod->Name);
+ OS << "+";
+ printValue(formatv("{0:x}", MRA));
+ OS << ')';
+ if (I != E - 1)
+ OS << lineEnding();
+ }
+ restoreColor();
+ return true;
+}
+
+bool MarkupFilter::tryData(const MarkupNode &Node) {
+ if (Node.Tag != "data")
+ return false;
+ if (!checkNumFields(Node, 1))
+ return true;
+ Optional<uint64_t> Addr = parseAddr(Node.Fields[0]);
+ if (!Addr)
+ return true;
+
+ const MMap *MMap = getContainingMMap(*Addr);
+ if (!MMap) {
+ WithColor::error() << "no mmap covers address\n";
+ reportLocation(Node.Fields[0].begin());
+ printRawElement(Node);
+ return true;
+ }
+
+ Expected<DIGlobal> Symbol = Symbolizer.symbolizeData(
+ MMap->Mod->BuildID, {MMap->getModuleRelativeAddr(*Addr)});
+ if (!Symbol) {
+ WithColor::defaultErrorHandler(Symbol.takeError());
+ printRawElement(Node);
+ return true;
+ }
+
+ highlight();
+ OS << Symbol->Name;
+ restoreColor();
+ return true;
+}
+
bool MarkupFilter::trySGR(const MarkupNode &Node) {
if (Node.Text == "\033[0m") {
resetColor();
@@ -297,6 +472,24 @@ void MarkupFilter::resetColor() {
OS.resetColor();
}
+void MarkupFilter::printRawElement(const MarkupNode &Element) {
+ highlight();
+ OS << "[[[";
+ printValue(Element.Tag);
+ for (StringRef Field : Element.Fields) {
+ OS << ':';
+ printValue(Field);
+ }
+ OS << "]]]";
+ restoreColor();
+}
+
+void MarkupFilter::printValue(Twine Value) {
+ highlightValue();
+ OS << Value;
+ highlight();
+}
+
// This macro helps reduce the amount of indirection done through Optional
// below, since the usual case upon returning a None Optional is to return None.
#define ASSIGN_OR_RETURN_NONE(TYPE, NAME, EXPR) \
@@ -392,6 +585,16 @@ Optional<uint64_t> MarkupFilter::parseSize(StringRef Str) const {
return ID;
}
+// Parse a frame number (%i in the spec).
+Optional<uint64_t> MarkupFilter::parseFrameNumber(StringRef Str) const {
+ uint64_t ID;
+ if (Str.getAsInteger(10, ID)) {
+ reportTypeError(Str, "frame number");
+ return None;
+ }
+ return ID;
+}
+
// Parse a build ID (%x in the spec).
Optional<SmallVector<uint8_t>> MarkupFilter::parseBuildID(StringRef Str) const {
std::string Bytes;
@@ -430,6 +633,17 @@ Optional<std::string> MarkupFilter::parseMode(StringRef Str) const {
return Str.lower();
}
+Optional<MarkupFilter::PCType> MarkupFilter::parsePCType(StringRef Str) const {
+ Optional<MarkupFilter::PCType> Type =
+ StringSwitch<Optional<MarkupFilter::PCType>>(Str)
+ .Case("ra", MarkupFilter::PCType::ReturnAddress)
+ .Case("pc", MarkupFilter::PCType::PreciseCode)
+ .Default(None);
+ if (!Type)
+ reportTypeError(Str, "PC type");
+ return Type;
+}
+
bool MarkupFilter::checkTag(const MarkupNode &Node) const {
if (any_of(Node.Tag, [](char C) { return C < 'a' || C > 'z'; })) {
WithColor::error(errs()) << "tags must be all lowercase characters\n";
@@ -442,7 +656,7 @@ bool MarkupFilter::checkTag(const MarkupNode &Node) const {
bool MarkupFilter::checkNumFields(const MarkupNode &Element,
size_t Size) const {
if (Element.Fields.size() != Size) {
- WithColor::error(errs()) << "expected " << Size << " fields; found "
+ WithColor::error(errs()) << "expected " << Size << " field(s); found "
<< Element.Fields.size() << "\n";
reportLocation(Element.Tag.end());
return false;
@@ -454,7 +668,19 @@ bool MarkupFilter::checkNumFieldsAtLeast(const MarkupNode &Element,
size_t Size) const {
if (Element.Fields.size() < Size) {
WithColor::error(errs())
- << "expected at least " << Size << " fields; found "
+ << "expected at least " << Size << " field(s); found "
+ << Element.Fields.size() << "\n";
+ reportLocation(Element.Tag.end());
+ return false;
+ }
+ return true;
+}
+
+bool MarkupFilter::checkNumFieldsAtMost(const MarkupNode &Element,
+ size_t Size) const {
+ if (Element.Fields.size() > Size) {
+ WithColor::error(errs())
+ << "expected at most " << Size << " field(s); found "
<< Element.Fields.size() << "\n";
reportLocation(Element.Tag.end());
return false;
@@ -479,7 +705,8 @@ void MarkupFilter::reportLocation(StringRef::iterator Loc) const {
// Checks for an existing mmap that overlaps the given one and returns a
// pointer to one of them.
-const MarkupFilter::MMap *MarkupFilter::overlappingMMap(const MMap &Map) const {
+const MarkupFilter::MMap *
+MarkupFilter::getOverlappingMMap(const MMap &Map) const {
// If the given map contains the start of another mmap, they overlap.
auto I = MMaps.upper_bound(Map.Addr);
if (I != MMaps.end() && Map.contains(I->second.Addr))
@@ -495,6 +722,28 @@ const MarkupFilter::MMap *MarkupFilter::overlappingMMap(const MMap &Map) const {
return nullptr;
}
+// Returns the MMap that contains the given address or nullptr if none.
+const MarkupFilter::MMap *MarkupFilter::getContainingMMap(uint64_t Addr) const {
+ // Find the first mmap starting >= Addr.
+ auto I = MMaps.lower_bound(Addr);
+ if (I != MMaps.end() && I->second.contains(Addr))
+ return &I->second;
+
+ // The previous mmap is the last one starting < Addr.
+ if (I == MMaps.begin())
+ return nullptr;
+ --I;
+ return I->second.contains(Addr) ? &I->second : nullptr;
+}
+
+uint64_t MarkupFilter::adjustAddr(uint64_t Addr, PCType Type) const {
+ // Decrementing return addresses by one moves them into the call instruction.
+ // The address doesn't have to be the start of the call instruction, just some
+ // byte on the inside. Subtracting one avoids needing detailed instruction
+ // length information here.
+ return Type == MarkupFilter::PCType::ReturnAddress ? Addr - 1 : Addr;
+}
+
StringRef MarkupFilter::lineEnding() const {
return Line.endswith("\r\n") ? "\r\n" : "\n";
}
@@ -502,3 +751,8 @@ StringRef MarkupFilter::lineEnding() const {
bool MarkupFilter::MMap::contains(uint64_t Addr) const {
return this->Addr <= Addr && Addr < this->Addr + Size;
}
+
+// Returns the module-relative address for a given virtual address.
+uint64_t MarkupFilter::MMap::getModuleRelativeAddr(uint64_t Addr) const {
+ return Addr - this->Addr + ModuleRelativeAddr;
+}
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 75594f90c926..b9962da1d302 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -1040,7 +1040,7 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
Name, F->getParent());
// The new function may also need remangling.
- if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F))
+ if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn))
NewFn = *Result;
return true;
}
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index bf145bffe8bf..23ac012b9e00 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -432,10 +432,6 @@ void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
}
void llvm::sys::DefaultOneShotPipeSignalHandler() {
- // UNIX03 conformance requires a non-zero exit code and an error message
- // to stderr when writing to a closed stdout fails.
- errs() << "error: write on a pipe with no reader\n";
-
// Send a special return code that drivers can check for, from sysexits.h.
exit(EX_IOERR);
}
diff --git a/llvm/lib/Support/X86TargetParser.cpp b/llvm/lib/Support/X86TargetParser.cpp
index 2567f3ed8034..0daaa6d815bf 100644
--- a/llvm/lib/Support/X86TargetParser.cpp
+++ b/llvm/lib/Support/X86TargetParser.cpp
@@ -203,10 +203,10 @@ constexpr FeatureBitset FeaturesTigerlake =
FeatureCLWB | FeatureMOVDIRI | FeatureSHSTK | FeatureKL | FeatureWIDEKL;
constexpr FeatureBitset FeaturesSapphireRapids =
FeaturesICLServer | FeatureAMX_BF16 | FeatureAMX_INT8 | FeatureAMX_TILE |
- FeatureAVX512BF16 | FeatureAVX512FP16 | FeatureAVX512VP2INTERSECT |
- FeatureAVXVNNI | FeatureCLDEMOTE | FeatureENQCMD | FeatureMOVDIR64B |
- FeatureMOVDIRI | FeaturePTWRITE | FeatureSERIALIZE | FeatureSHSTK |
- FeatureTSXLDTRK | FeatureUINTR | FeatureWAITPKG;
+ FeatureAVX512BF16 | FeatureAVX512FP16 | FeatureAVXVNNI | FeatureCLDEMOTE |
+ FeatureENQCMD | FeatureMOVDIR64B | FeatureMOVDIRI | FeaturePTWRITE |
+ FeatureSERIALIZE | FeatureSHSTK | FeatureTSXLDTRK | FeatureUINTR |
+ FeatureWAITPKG;
// Intel Atom processors.
// Bonnell has feature parity with Core2 and adds MOVBE.
@@ -367,7 +367,7 @@ constexpr ProcInfo Processors[] = {
// Tigerlake microarchitecture based processors.
{ {"tigerlake"}, CK_Tigerlake, FEATURE_AVX512VP2INTERSECT, FeaturesTigerlake },
// Sapphire Rapids microarchitecture based processors.
- { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512VP2INTERSECT, FeaturesSapphireRapids },
+ { {"sapphirerapids"}, CK_SapphireRapids, FEATURE_AVX512BF16, FeaturesSapphireRapids },
// Alderlake microarchitecture based processors.
{ {"alderlake"}, CK_Alderlake, FEATURE_AVX2, FeaturesAlderlake },
// Knights Landing processor.
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index c28216048d7c..06e21f90ebf1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -5805,7 +5805,7 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
assert(!Res && "Call operand has unhandled type");
(void)Res;
}
- SmallVector<SDValue, 16> ArgValues;
+
unsigned ExtraArgLocs = 0;
for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i - ExtraArgLocs];
@@ -6157,17 +6157,10 @@ void AArch64TargetLowering::saveVarArgRegisters(CCState &CCInfo,
/// appropriate copies out of appropriate physical registers.
SDValue AArch64TargetLowering::LowerCallResult(
SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
+ const SmallVectorImpl<CCValAssign> &RVLocs, const SDLoc &DL,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool isThisReturn,
SDValue ThisVal) const {
- CCAssignFn *RetCC = CCAssignFnForReturn(CallConv);
- // Assign locations to each value returned by this call.
- SmallVector<CCValAssign, 16> RVLocs;
DenseMap<unsigned, SDValue> CopiedRegs;
- CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
- *DAG.getContext());
- CCInfo.AnalyzeCallResult(Ins, RetCC);
-
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
CCValAssign VA = RVLocs[i];
@@ -6508,17 +6501,39 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
GuardWithBTI = FuncInfo->branchTargetEnforcement();
}
+ // Analyze operands of the call, assigning locations to each operand.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
+
+ if (IsVarArg) {
+ unsigned NumArgs = Outs.size();
+
+ for (unsigned i = 0; i != NumArgs; ++i) {
+ if (!Outs[i].IsFixed && Outs[i].VT.isScalableVector())
+ report_fatal_error("Passing SVE types to variadic functions is "
+ "currently not supported");
+ }
+ }
+
+ analyzeCallOperands(*this, Subtarget, CLI, CCInfo);
+
+ CCAssignFn *RetCC = CCAssignFnForReturn(CallConv);
+ // Assign locations to each value returned by this call.
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
+ *DAG.getContext());
+ RetCCInfo.AnalyzeCallResult(Ins, RetCC);
+
// Check callee args/returns for SVE registers and set calling convention
// accordingly.
if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) {
- bool CalleeOutSVE = any_of(Outs, [](ISD::OutputArg &Out){
- return Out.VT.isScalableVector();
- });
- bool CalleeInSVE = any_of(Ins, [](ISD::InputArg &In){
- return In.VT.isScalableVector();
- });
-
- if (CalleeInSVE || CalleeOutSVE)
+ auto HasSVERegLoc = [](CCValAssign &Loc) {
+ if (!Loc.isRegLoc())
+ return false;
+ return AArch64::ZPRRegClass.contains(Loc.getLocReg()) ||
+ AArch64::PPRRegClass.contains(Loc.getLocReg());
+ };
+ if (any_of(RVLocs, HasSVERegLoc) || any_of(ArgLocs, HasSVERegLoc))
CallConv = CallingConv::AArch64_SVE_VectorCall;
}
@@ -6540,22 +6555,6 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
report_fatal_error("failed to perform tail call elimination on a call "
"site marked musttail");
- // Analyze operands of the call, assigning locations to each operand.
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
-
- if (IsVarArg) {
- unsigned NumArgs = Outs.size();
-
- for (unsigned i = 0; i != NumArgs; ++i) {
- if (!Outs[i].IsFixed && Outs[i].VT.isScalableVector())
- report_fatal_error("Passing SVE types to variadic functions is "
- "currently not supported");
- }
- }
-
- analyzeCallOperands(*this, Subtarget, CLI, CCInfo);
-
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@@ -6961,7 +6960,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
// Handle result values, copying them out of physregs into vregs that we
// return.
- return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG,
+ return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, RVLocs, DL, DAG,
InVals, IsThisReturn,
IsThisReturn ? OutVals[0] : SDValue());
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 1ba2e2f315ec..ff3bfe897869 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -894,7 +894,7 @@ private:
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins,
+ const SmallVectorImpl<CCValAssign> &RVLocs,
const SDLoc &DL, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals, bool isThisReturn,
SDValue ThisVal) const;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index bf520a560404..c0a94cc758bb 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4600,9 +4600,16 @@ void AMDGPUTargetLowering::computeKnownBitsForTargetNode(
case Intrinsic::amdgcn_mbcnt_hi: {
const GCNSubtarget &ST =
DAG.getMachineFunction().getSubtarget<GCNSubtarget>();
- // These return at most the wavefront size - 1.
+ // These return at most the (wavefront size - 1) + src1
+ // As long as src1 is an immediate we can calc known bits
+ KnownBits Src1Known = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
+ unsigned Src1ValBits = Src1Known.countMaxActiveBits();
+ unsigned MaxActiveBits = std::max(Src1ValBits, ST.getWavefrontSizeLog2());
+ // Cater for potential carry
+ MaxActiveBits += Src1ValBits ? 1 : 0;
unsigned Size = Op.getValueType().getSizeInBits();
- Known.Zero.setHighBits(Size - ST.getWavefrontSizeLog2());
+ if (MaxActiveBits < Size)
+ Known.Zero.setHighBits(Size - MaxActiveBits);
break;
}
case Intrinsic::amdgcn_workitem_id_x:
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index f7d139adc63b..f6b7d1ffc6d2 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -249,6 +249,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
case ISD::STORE:
case ISD::BUILD_VECTOR:
case ISD::BITCAST:
+ case ISD::UNDEF:
case ISD::EXTRACT_VECTOR_ELT:
case ISD::INSERT_VECTOR_ELT:
case ISD::EXTRACT_SUBVECTOR:
@@ -516,6 +517,7 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
case ISD::STORE:
case ISD::BUILD_VECTOR:
case ISD::BITCAST:
+ case ISD::UNDEF:
case ISD::EXTRACT_VECTOR_ELT:
case ISD::INSERT_VECTOR_ELT:
case ISD::INSERT_SUBVECTOR:
diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
index 3c102463ba08..cbfd2bc68f18 100644
--- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
@@ -1036,7 +1036,7 @@ InstructionCost ARMTTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
// split, we may need an expensive shuffle to get two in sync. This has the
// effect of making larger than legal compares (v8i32 for example)
// expensive.
- if (LT.second.getVectorNumElements() > 2) {
+ if (LT.second.isVector() && LT.second.getVectorNumElements() > 2) {
if (LT.first > 1)
return LT.first * BaseCost +
BaseT::getScalarizationOverhead(VecCondTy, true, false);
diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
index bd0232c71d48..f37c50900adb 100644
--- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
@@ -149,6 +149,7 @@ private:
Align H)
: Inst(I), Addr(A), ValTy(T), HaveAlign(H),
NeedAlign(HVC.getTypeAlignment(ValTy)) {}
+ AddrInfo &operator=(const AddrInfo &) = default;
// XXX: add Size member?
Instruction *Inst;
@@ -185,6 +186,7 @@ private:
Segment(Value *Val, int Begin, int Len)
: Val(Val), Start(Begin), Size(Len) {}
Segment(const Segment &Seg) = default;
+ Segment &operator=(const Segment &Seg) = default;
Value *Val; // Value representable as a sequence of bytes.
int Start; // First byte of the value that belongs to the segment.
int Size; // Number of bytes in the segment.
@@ -195,6 +197,7 @@ private:
Block(Value *Val, int Off, int Len, int Pos)
: Seg(Val, Off, Len), Pos(Pos) {}
Block(const Block &Blk) = default;
+ Block &operator=(const Block &Blk) = default;
Segment Seg; // Value segment.
int Pos; // Position (offset) of the segment in the Block.
};
diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp
index 1926977ea66e..2e426bb79cae 100644
--- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp
@@ -70,6 +70,7 @@ void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
}
}
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
if (MMI) {
const Module *M = MMI->getModule();
for (auto F = M->begin(), E = M->end(); F != E; ++F) {
@@ -92,4 +93,5 @@ void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
}
}
}
+#endif
}
diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td
index e6d23f741ea5..8afd0a7fc09a 100644
--- a/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/llvm/lib/Target/Sparc/SparcCallingConv.td
@@ -125,10 +125,14 @@ def CC_Sparc64 : CallingConv<[
def RetCC_Sparc64 : CallingConv<[
// A single f32 return value always goes in %f0. The ABI doesn't specify what
// happens to multiple f32 return values outside a struct.
- CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>,
+ CCIfType<[f32], CCCustom<"RetCC_Sparc64_Half">>,
- // Otherwise, return values are passed exactly like arguments.
- CCDelegateTo<CC_Sparc64>
+ // Otherwise, return values are passed exactly like arguments, except that
+ // returns that are too big to fit into the registers is passed as an sret
+ // instead.
+ CCIfInReg<CCIfType<[i32, f32], CCCustom<"RetCC_Sparc64_Half">>>,
+ CCIfType<[i32], CCPromoteToType<i64>>,
+ CCCustom<"RetCC_Sparc64_Full">
]>;
// Callee-saved registers are handled by the register window mechanism.
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 2cb74e7709c7..f55675089102 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -101,9 +101,9 @@ static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT,
}
// Allocate a full-sized argument for the 64-bit ABI.
-static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,
- MVT &LocVT, CCValAssign::LocInfo &LocInfo,
- ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT,
+ MVT &LocVT, CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
assert((LocVT == MVT::f32 || LocVT == MVT::f128
|| LocVT.getSizeInBits() == 64) &&
"Can't handle non-64 bits locations");
@@ -133,6 +133,11 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,
return true;
}
+ // Bail out if this is a return CC and we run out of registers to place
+ // values into.
+ if (IsReturn)
+ return false;
+
// This argument goes on the stack in an 8-byte slot.
// When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to
// the right-aligned float. The first 4 bytes of the stack slot are undefined.
@@ -146,9 +151,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,
// Allocate a half-sized argument for the 64-bit ABI.
//
// This is used when passing { float, int } structs by value in registers.
-static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT,
- MVT &LocVT, CCValAssign::LocInfo &LocInfo,
- ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT,
+ MVT &LocVT, CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations");
unsigned Offset = State.AllocateStack(4, Align(4));
@@ -174,10 +179,43 @@ static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT,
return true;
}
+ // Bail out if this is a return CC and we run out of registers to place
+ // values into.
+ if (IsReturn)
+ return false;
+
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
return true;
}
+static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+ CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
+ State);
+}
+
+static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+ CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
+ State);
+}
+
+static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+ CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
+ State);
+}
+
+static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+ CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
+ State);
+}
+
#include "SparcGenCallingConv.inc"
// The calling conventions in SparcCallingConv.td are described in terms of the
@@ -191,6 +229,15 @@ static unsigned toCallerWindow(unsigned Reg) {
return Reg;
}
+bool SparcTargetLowering::CanLowerReturn(
+ CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
+ return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64
+ : RetCC_Sparc32);
+}
+
SDValue
SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
bool IsVarArg,
@@ -1031,6 +1078,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
+ assert(RVLocs[i].isRegLoc() && "Can only return in registers!");
if (RVLocs[i].getLocVT() == MVT::v2i32) {
SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32);
SDValue Lo = DAG.getCopyFromReg(
@@ -1346,6 +1394,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
CCValAssign &VA = RVLocs[i];
+ assert(VA.isRegLoc() && "Can only return in registers!");
unsigned Reg = toCallerWindow(VA.getLocReg());
// When returning 'inreg {i32, i32 }', two consecutive i32 arguments can
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 2768bb20566a..16e4f2687054 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -144,6 +144,11 @@ namespace llvm {
SDValue LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const;
+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ LLVMContext &Context) const override;
+
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index fa0a6bd415dc..f98916e81cee 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -909,7 +909,6 @@ def ProcessorFeatures {
FeatureTSXLDTRK,
FeatureENQCMD,
FeatureSHSTK,
- FeatureVP2INTERSECT,
FeatureMOVDIRI,
FeatureMOVDIR64B,
FeatureUINTR];
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index 6df0409256bb..6fc7b29c5b78 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2003,7 +2003,7 @@ OptimizeFunctions(Module &M,
// FIXME: We should also hoist alloca affected by this to the entry
// block if possible.
if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) &&
- !F.hasAddressTaken() && !hasMustTailCallers(&F)) {
+ !F.hasAddressTaken() && !hasMustTailCallers(&F) && !F.isVarArg()) {
RemoveAttribute(&F, Attribute::InAlloca);
Changed = true;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index bc01d2ef7fe2..52596b30494f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3289,6 +3289,10 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
if (CallerPAL.hasParamAttr(i, Attribute::SwiftError))
return false;
+ if (CallerPAL.hasParamAttr(i, Attribute::ByVal) !=
+ Callee->getAttributes().hasParamAttr(i, Attribute::ByVal))
+ return false; // Cannot transform to or from byval.
+
// If the parameter is passed as a byval argument, then we have to have a
// sized type and the sized type has to have the same size as the old type.
if (ParamTy != ActTy && CallerPAL.hasParamAttr(i, Attribute::ByVal)) {
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 143a035749c7..644c5c82e58e 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -1210,8 +1210,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) {
BasicBlock *BB = PN.getParent();
Align MaxAlign;
uint64_t APWidth = DL.getIndexTypeSizeInBits(PN.getType());
- APInt MaxSize(APWidth, 0);
- bool HaveLoad = false;
+ Type *LoadType = nullptr;
for (User *U : PN.users()) {
LoadInst *LI = dyn_cast<LoadInst>(U);
if (!LI || !LI->isSimple())
@@ -1223,21 +1222,27 @@ static bool isSafePHIToSpeculate(PHINode &PN) {
if (LI->getParent() != BB)
return false;
+ if (LoadType) {
+ if (LoadType != LI->getType())
+ return false;
+ } else {
+ LoadType = LI->getType();
+ }
+
// Ensure that there are no instructions between the PHI and the load that
// could store.
for (BasicBlock::iterator BBI(PN); &*BBI != LI; ++BBI)
if (BBI->mayWriteToMemory())
return false;
- uint64_t Size = DL.getTypeStoreSize(LI->getType()).getFixedSize();
MaxAlign = std::max(MaxAlign, LI->getAlign());
- MaxSize = MaxSize.ult(Size) ? APInt(APWidth, Size) : MaxSize;
- HaveLoad = true;
}
- if (!HaveLoad)
+ if (!LoadType)
return false;
+ APInt LoadSize = APInt(APWidth, DL.getTypeStoreSize(LoadType).getFixedSize());
+
// We can only transform this if it is safe to push the loads into the
// predecessor blocks. The only thing to watch out for is that we can't put
// a possibly trapping load in the predecessor if it is a critical edge.
@@ -1259,7 +1264,7 @@ static bool isSafePHIToSpeculate(PHINode &PN) {
// If this pointer is always safe to load, or if we can prove that there
// is already a load in the block, then we can move the load to the pred
// block.
- if (isSafeToLoadUnconditionally(InVal, MaxAlign, MaxSize, DL, TI))
+ if (isSafeToLoadUnconditionally(InVal, MaxAlign, LoadSize, DL, TI))
continue;
return false;
diff --git a/llvm/lib/Transforms/Utils/LoopVersioning.cpp b/llvm/lib/Transforms/Utils/LoopVersioning.cpp
index 97f29527bb95..6309eed7963d 100644
--- a/llvm/lib/Transforms/Utils/LoopVersioning.cpp
+++ b/llvm/lib/Transforms/Utils/LoopVersioning.cpp
@@ -137,8 +137,10 @@ void LoopVersioning::addPHINodes(
// See if we have a single-operand PHI with the value defined by the
// original loop.
for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
- if (PN->getIncomingValue(0) == Inst)
+ if (PN->getIncomingValue(0) == Inst) {
+ SE->forgetValue(PN);
break;
+ }
}
// If not create it.
if (!PN) {
diff --git a/llvm/lib/Transforms/Utils/VNCoercion.cpp b/llvm/lib/Transforms/Utils/VNCoercion.cpp
index 42be67f3cfc0..264da2187754 100644
--- a/llvm/lib/Transforms/Utils/VNCoercion.cpp
+++ b/llvm/lib/Transforms/Utils/VNCoercion.cpp
@@ -356,9 +356,9 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr,
// If this is memset, we just need to see if the offset is valid in the size
// of the memset..
- if (MI->getIntrinsicID() == Intrinsic::memset) {
+ if (const auto *memset_inst = dyn_cast<MemSetInst>(MI)) {
if (DL.isNonIntegralPointerType(LoadTy->getScalarType())) {
- auto *CI = dyn_cast<ConstantInt>(cast<MemSetInst>(MI)->getValue());
+ auto *CI = dyn_cast<ConstantInt>(memset_inst->getValue());
if (!CI || !CI->isZero())
return -1;
}
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 91bc7dbad1d0..5fd4e45d80fb 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8149,9 +8149,15 @@ VPRecipeBase *VPRecipeBuilder::tryToOptimizeInductionPHI(
*PSE.getSE(), *OrigLoop, Range);
// Check if this is pointer induction. If so, build the recipe for it.
- if (auto *II = Legal->getPointerInductionDescriptor(Phi))
- return new VPWidenPointerInductionRecipe(Phi, Operands[0], *II,
- *PSE.getSE());
+ if (auto *II = Legal->getPointerInductionDescriptor(Phi)) {
+ return new VPWidenPointerInductionRecipe(
+ Phi, Operands[0], *II, *PSE.getSE(),
+ LoopVectorizationPlanner::getDecisionAndClampRange(
+ [&](ElementCount VF) {
+ return CM.isScalarAfterVectorization(Phi, VF);
+ },
+ Range));
+ }
return nullptr;
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index f009a7ee6b4b..7a6bc48e2aee 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1187,15 +1187,19 @@ class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe {
/// explicitly.
ScalarEvolution &SE;
+ bool IsScalarAfterVectorization;
+
public:
/// Create a new VPWidenPointerInductionRecipe for \p Phi with start value \p
/// Start.
VPWidenPointerInductionRecipe(PHINode *Phi, VPValue *Start,
const InductionDescriptor &IndDesc,
- ScalarEvolution &SE)
+ ScalarEvolution &SE,
+ bool IsScalarAfterVectorization)
: VPHeaderPHIRecipe(VPVWidenPointerInductionSC, VPWidenPointerInductionSC,
Phi),
- IndDesc(IndDesc), SE(SE) {
+ IndDesc(IndDesc), SE(SE),
+ IsScalarAfterVectorization(IsScalarAfterVectorization) {
addOperand(Start);
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index cb7507264667..9a404640b4b8 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -983,10 +983,8 @@ void VPCanonicalIVPHIRecipe::print(raw_ostream &O, const Twine &Indent,
#endif
bool VPWidenPointerInductionRecipe::onlyScalarsGenerated(ElementCount VF) {
- bool IsUniform = vputils::onlyFirstLaneUsed(this);
- return all_of(users(),
- [&](const VPUser *U) { return U->usesScalars(this); }) &&
- (IsUniform || !VF.isScalable());
+ return IsScalarAfterVectorization &&
+ (!VF.isScalable() || vputils::onlyFirstLaneUsed(this));
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index ca73dafe2b8e..61676b4323d2 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -282,27 +282,28 @@ static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
}
template <class ELFT>
-static void printSymbolVersionDependency(ArrayRef<uint8_t> Contents,
- StringRef StrTab) {
+static void printSymbolVersionDependency(StringRef FileName,
+ const ELFFile<ELFT> &Obj,
+ const typename ELFT::Shdr &Sec) {
outs() << "\nVersion References:\n";
- const uint8_t *Buf = Contents.data();
- while (Buf) {
- auto *Verneed = reinterpret_cast<const typename ELFT::Verneed *>(Buf);
- outs() << " required from "
- << StringRef(StrTab.drop_front(Verneed->vn_file).data()) << ":\n";
+ auto WarningHandler = [&](const Twine &Msg) {
+ reportWarning(Msg, FileName);
+ return Error::success();
+ };
+ Expected<std::vector<VerNeed>> V =
+ Obj.getVersionDependencies(Sec, WarningHandler);
+ if (!V) {
+ reportWarning(toString(V.takeError()), FileName);
+ return;
+ }
- const uint8_t *BufAux = Buf + Verneed->vn_aux;
- while (BufAux) {
- auto *Vernaux = reinterpret_cast<const typename ELFT::Vernaux *>(BufAux);
- outs() << " "
- << format("0x%08" PRIx32 " ", (uint32_t)Vernaux->vna_hash)
- << format("0x%02" PRIx16 " ", (uint16_t)Vernaux->vna_flags)
- << format("%02" PRIu16 " ", (uint16_t)Vernaux->vna_other)
- << StringRef(StrTab.drop_front(Vernaux->vna_name).data()) << '\n';
- BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr;
- }
- Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr;
+ raw_fd_ostream &OS = outs();
+ for (const VerNeed &VN : *V) {
+ OS << " required from " << VN.File << ":\n";
+ for (const VernAux &Aux : VN.AuxV)
+ OS << format(" 0x%08x 0x%02x %02u %s\n", Aux.Hash, Aux.Flags,
+ Aux.Other, Aux.Name.c_str());
}
}
@@ -355,7 +356,7 @@ static void printSymbolVersionInfo(const ELFFile<ELFT> &Elf,
StringRef StrTab = unwrapOrError(Elf.getStringTable(*StrTabSec), FileName);
if (Shdr.sh_type == ELF::SHT_GNU_verneed)
- printSymbolVersionDependency<ELFT>(Contents, StrTab);
+ printSymbolVersionDependency<ELFT>(FileName, Elf, Shdr);
else
printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab);
}
diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 7ec70e42f1c1..34c93be67f80 100644
--- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -366,8 +366,8 @@ static SmallVector<uint8_t> parseBuildIDArg(const opt::InputArgList &Args,
}
// Symbolize markup from stdin and write the result to stdout.
-static void filterMarkup(const opt::InputArgList &Args) {
- MarkupFilter Filter(outs(), parseColorArg(Args));
+static void filterMarkup(const opt::InputArgList &Args, LLVMSymbolizer &Symbolizer) {
+ MarkupFilter Filter(outs(), Symbolizer, parseColorArg(Args));
std::string InputString;
while (std::getline(std::cin, InputString)) {
InputString += '\n';
@@ -437,8 +437,19 @@ int main(int argc, char **argv) {
}
}
+ LLVMSymbolizer Symbolizer(Opts);
+
+ // A debuginfod lookup could succeed if a HTTP client is available and at
+ // least one backing URL is configured.
+ bool ShouldUseDebuginfodByDefault =
+ HTTPClient::isAvailable() &&
+ !ExitOnErr(getDefaultDebuginfodUrls()).empty();
+ if (Args.hasFlag(OPT_debuginfod, OPT_no_debuginfod,
+ ShouldUseDebuginfodByDefault))
+ enableDebuginfod(Symbolizer);
+
if (Args.hasArg(OPT_filter_markup)) {
- filterMarkup(Args);
+ filterMarkup(Args, Symbolizer);
return 0;
}
@@ -458,17 +469,6 @@ int main(int argc, char **argv) {
}
SmallVector<uint8_t> BuildID = parseBuildIDArg(Args, OPT_build_id_EQ);
- LLVMSymbolizer Symbolizer(Opts);
-
- // A debuginfod lookup could succeed if a HTTP client is available and at
- // least one backing URL is configured.
- bool ShouldUseDebuginfodByDefault =
- HTTPClient::isAvailable() &&
- !ExitOnErr(getDefaultDebuginfodUrls()).empty();
- if (Args.hasFlag(OPT_debuginfod, OPT_no_debuginfod,
- ShouldUseDebuginfodByDefault))
- enableDebuginfod(Symbolizer);
-
std::unique_ptr<DIPrinter> Printer;
if (Style == OutputStyle::GNU)
Printer = std::make_unique<GNUPrinter>(outs(), errs(), Config);