diff --git a/clang-tools-extra/clangd/FileDistance.h b/clang-tools-extra/clangd/FileDistance.h
index e7174bccb9ddb..88bb30c142702 100644
--- a/clang-tools-extra/clangd/FileDistance.h
+++ b/clang-tools-extra/clangd/FileDistance.h
@@ -43,6 +43,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Path.h"
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 37dbac30901f6..298d793a0de46 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -56,6 +56,14 @@ Improvements to Clang's diagnostics
- -Wtautological-compare for self comparisons and
-Wtautological-overlap-compare will now look through member and array
access to determine if two operand expressions are the same.
+- -Wtautological-bitwise-compare is a new warning group. This group has the
+ current warning which diagnoses the tautological comparison of a bitwise
+ operation and a constant. The group also has the new warning which diagnoses
+ when a bitwise-or with a non-negative value is converted to a bool, since
+ that bool will always be true.
+- -Wbitwise-conditional-parentheses will warn on operator precedence issues
+ when mixing bitwise-and (&) and bitwise-or (|) operator with the
+ conditional operator (?:).
Non-comprehensive list of changes in this release
-------------------------------------------------
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 0c6c2846c9b8b..66212f72b7875 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -389,9 +389,12 @@ class CXXRecordDecl : public RecordDecl {
/// The number of explicit captures in this lambda.
unsigned NumExplicitCaptures : 13;
+ /// Has known `internal` linkage.
+ unsigned HasKnownInternalLinkage : 1;
+
/// The number used to indicate this lambda expression for name
/// mangling in the Itanium C++ ABI.
- unsigned ManglingNumber = 0;
+ unsigned ManglingNumber : 31;
/// The declaration that provides context for this lambda, if the
/// actual DeclContext does not suffice. This is used for lambdas that
@@ -406,12 +409,12 @@ class CXXRecordDecl : public RecordDecl {
/// The type of the call method.
TypeSourceInfo *MethodTyInfo;
- LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
- bool Dependent, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault)
- : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
- CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
- MethodTyInfo(Info) {
+ LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent,
+ bool IsGeneric, LambdaCaptureDefault CaptureDefault)
+ : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
+ CaptureDefault(CaptureDefault), NumCaptures(0),
+ NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0),
+ MethodTyInfo(Info) {
IsLambda = true;
// C++1z [expr.prim.lambda]p4:
@@ -1705,6 +1708,13 @@ class CXXRecordDecl : public RecordDecl {
return getLambdaData().ManglingNumber;
}
+ /// The lambda is known to has internal linkage no matter whether it has name
+ /// mangling number.
+ bool hasKnownLambdaInternalLinkage() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ return getLambdaData().HasKnownInternalLinkage;
+ }
+
/// Retrieve the declaration that provides additional context for a
/// lambda, when the normal declaration context is not specific enough.
///
@@ -1718,9 +1728,12 @@ class CXXRecordDecl : public RecordDecl {
/// Set the mangling number and context declaration for a lambda
/// class.
- void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
+ void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl,
+ bool HasKnownInternalLinkage = false) {
+ assert(isLambda() && "Not a lambda closure type!");
getLambdaData().ManglingNumber = ManglingNumber;
getLambdaData().ContextDecl = ContextDecl;
+ getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage;
}
/// Returns the inheritance model used for this record.
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 7b7ca9bf8f0f0..2152e108c7cba 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -262,8 +262,8 @@ class CUDAKernelCallExpr final : public CallExpr {
/// - a != b -> !(a == b)
/// - a != b -> !(b == a)
/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>:
-/// - a @ b -> (a <=> b) @ 0
-/// - a @ b -> 0 @ (b <=> a)
+/// - a @ b -> (a <=> b) @ 0
+/// - a @ b -> 0 @ (b <=> a)
///
/// This expression provides access to both the original syntax and the
/// rewritten expression.
diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index b24e32c966777..a8301a0e0063f 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -1213,6 +1213,7 @@ class CFGCallback {
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
virtual void compareBitwiseEquality(const BinaryOperator *B,
bool isAlwaysTrue) {}
+ virtual void compareBitwiseOr(const BinaryOperator *B) {}
};
/// Represents a source-level, intra-procedural CFG that represents the
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index f267f4d92b287..0daad2ba759bc 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -296,6 +296,7 @@ def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
def GlobalConstructors : DiagGroup<"global-constructors">;
+def BitwiseConditionalParentheses: DiagGroup<"bitwise-conditional-parentheses">;
def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
@@ -516,12 +517,14 @@ def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare",
[TautologicalOutOfRangeCompare]>;
def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
+def TautologicalBitwiseCompare : DiagGroup<"tautological-bitwise-compare">;
def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
def TautologicalObjCBoolCompare : DiagGroup<"tautological-objc-bool-compare">;
def TautologicalCompare : DiagGroup<"tautological-compare",
[TautologicalConstantCompare,
TautologicalPointerCompare,
TautologicalOverlapCompare,
+ TautologicalBitwiseCompare,
TautologicalUndefinedCompare,
TautologicalObjCBoolCompare]>;
def HeaderHygiene : DiagGroup<"header-hygiene">;
@@ -735,6 +738,7 @@ def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
def Parentheses : DiagGroup<"parentheses",
[LogicalOpParentheses,
LogicalNotParentheses,
+ BitwiseConditionalParentheses,
BitwiseOpParentheses,
ShiftOpParentheses,
OverloadedShiftOpParentheses,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7be237a821311..2a19317b148f7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5771,6 +5771,9 @@ def note_precedence_silence : Note<
def warn_precedence_conditional : Warning<
"operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
InGroup;
+def warn_precedence_bitwise_conditional : Warning<
+ "operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
+ InGroup;
def note_precedence_conditional_first : Note<
"place parentheses around the '?:' expression to evaluate it first">;
@@ -8358,7 +8361,10 @@ def warn_comparison_always : Warning<
InGroup;
def warn_comparison_bitwise_always : Warning<
"bitwise comparison always evaluates to %select{false|true}0">,
- InGroup;
+ InGroup, DefaultIgnore;
+def warn_comparison_bitwise_or : Warning<
+ "bitwise or with non-zero value always evaluates to true">,
+ InGroup, DefaultIgnore;
def warn_tautological_overlap_comparison : Warning<
"overlapping comparisons always evaluate to %select{false|true}0">,
InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b9874158686ba..49d3789822fd1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6056,12 +6056,17 @@ class Sema {
LambdaCaptureDefault CaptureDefault);
/// Start the definition of a lambda expression.
- CXXMethodDecl *
- startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange,
- TypeSourceInfo *MethodType, SourceLocation EndLoc,
- ArrayRef Params,
- ConstexprSpecKind ConstexprKind,
- Optional> Mangling = None);
+ CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ TypeSourceInfo *MethodType,
+ SourceLocation EndLoc,
+ ArrayRef Params,
+ ConstexprSpecKind ConstexprKind);
+
+ /// Number lambda for linkage purposes if necessary.
+ void handleLambdaNumbering(
+ CXXRecordDecl *Class, CXXMethodDecl *Method,
+ Optional> Mangling = None);
/// Endow the lambda scope info with the relevant properties.
void buildLambdaScope(sema::LambdaScopeInfo *LSI,
@@ -10553,11 +10558,11 @@ class Sema {
Ref_Compatible
};
- ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
- QualType T1, QualType T2,
- bool &DerivedToBase,
- bool &ObjCConversion,
- bool &ObjCLifetimeConversion);
+ ReferenceCompareResult
+ CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
+ bool &DerivedToBase, bool &ObjCConversion,
+ bool &ObjCLifetimeConversion,
+ bool &FunctionConversion);
ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
Expr *CastExpr, CastKind &CastKind,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index a549cf9f899ee..54acca7dc62cc 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -2694,7 +2694,8 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl());
if (!CDeclOrErr)
return CDeclOrErr.takeError();
- D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr);
+ D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr,
+ DCXX->hasKnownLambdaInternalLinkage());
} else if (DCXX->isInjectedClassName()) {
// We have to be careful to do a similar dance to the one in
// Sema::ActOnStartCXXMemberDeclarations
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 9ebf1c32629fe..80235d8496d22 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1385,7 +1385,8 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
case Decl::CXXRecord: {
const auto *Record = cast(D);
if (Record->isLambda()) {
- if (!Record->getLambdaManglingNumber()) {
+ if (Record->hasKnownLambdaInternalLinkage() ||
+ !Record->getLambdaManglingNumber()) {
// This lambda has no mangling number, so it's internal.
return getInternalLinkageFor(D);
}
@@ -1402,7 +1403,8 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
// };
const CXXRecordDecl *OuterMostLambda =
getOutermostEnclosingLambda(Record);
- if (!OuterMostLambda->getLambdaManglingNumber())
+ if (OuterMostLambda->hasKnownLambdaInternalLinkage() ||
+ !OuterMostLambda->getLambdaManglingNumber())
return getInternalLinkageFor(D);
return getLVForClosure(
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 54fb388b0c6c1..a533a8d97b848 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1139,6 +1139,31 @@ class CFGBuilder {
return {};
}
+ /// A bitwise-or with a non-zero constant always evaluates to true.
+ TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) {
+ const Expr *LHSConstant =
+ tryTransformToIntOrEnumConstant(B->getLHS()->IgnoreParenImpCasts());
+ const Expr *RHSConstant =
+ tryTransformToIntOrEnumConstant(B->getRHS()->IgnoreParenImpCasts());
+
+ if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
+ return {};
+
+ const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
+
+ Expr::EvalResult Result;
+ if (!Constant->EvaluateAsInt(Result, *Context))
+ return {};
+
+ if (Result.Val.getInt() == 0)
+ return {};
+
+ if (BuildOpts.Observer)
+ BuildOpts.Observer->compareBitwiseOr(B);
+
+ return TryResult(true);
+ }
+
/// Try and evaluate an expression to an integer constant.
bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
if (!BuildOpts.PruneTriviallyFalseEdges)
@@ -1156,7 +1181,7 @@ class CFGBuilder {
return {};
if (BinaryOperator *Bop = dyn_cast(S)) {
- if (Bop->isLogicalOp()) {
+ if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
// Check the cache first.
CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
if (I != CachedBoolEvals.end())
@@ -1240,6 +1265,10 @@ class CFGBuilder {
TryResult BopRes = checkIncorrectRelationalOperator(Bop);
if (BopRes.isKnown())
return BopRes.isTrue();
+ } else if (Bop->getOpcode() == BO_Or) {
+ TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
+ if (BopRes.isKnown())
+ return BopRes.isTrue();
}
}
@@ -2340,6 +2369,9 @@ CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U,
appendStmt(Block, U);
}
+ if (U->getOpcode() == UO_LNot)
+ tryEvaluateBool(U->getSubExpr()->IgnoreParens());
+
return Visit(U->getSubExpr(), AddStmtChoice());
}
@@ -2474,6 +2506,9 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
appendStmt(Block, B);
}
+ if (B->isEqualityOp() || B->isRelationalOp())
+ tryEvaluateBool(B);
+
CFGBlock *RBlock = Visit(B->getRHS());
CFGBlock *LBlock = Visit(B->getLHS());
// If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr
@@ -4527,6 +4562,10 @@ CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
autoCreateBlock();
appendStmt(Block, E);
}
+
+ if (E->getCastKind() == CK_IntegralToBoolean)
+ tryEvaluateBool(E->getSubExpr()->IgnoreParens());
+
return Visit(E->getSubExpr(), AddStmtChoice());
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 294d54e37883f..7c63743f3b43d 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -539,11 +539,11 @@ void CGDebugInfo::CreateCompileUnit() {
// file to determine the real absolute path for the file.
std::string MainFileDir;
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- MainFileDir = remapDIPath(MainFile->getDir()->getName());
- if (MainFileDir != ".") {
+ MainFileDir = MainFile->getDir()->getName();
+ if (!llvm::sys::path::is_absolute(MainFileName)) {
llvm::SmallString<1024> MainFileDirSS(MainFileDir);
llvm::sys::path::append(MainFileDirSS, MainFileName);
- MainFileName = MainFileDirSS.str();
+ MainFileName = llvm::sys::path::remove_leading_dotslash(MainFileDirSS);
}
// If the main file name provided is identical to the input file name, and
// if the input file is a preprocessed source, use the module name for
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 5d177d028f32d..7eff7787fa29b 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3586,7 +3586,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
// Make a new global with the correct type, this is now guaranteed
// to work.
auto *NewGV = cast(
- GetAddrOfGlobalVar(D, InitType, IsForDefinition));
+ GetAddrOfGlobalVar(D, InitType, IsForDefinition)
+ ->stripPointerCasts());
// Erase the old global, since it is no longer used.
GV->eraseFromParent();
@@ -4076,14 +4077,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
llvm::Constant *Entry =
GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative));
- // Strip off a bitcast if we got one back.
- if (auto *CE = dyn_cast(Entry)) {
- assert(CE->getOpcode() == llvm::Instruction::BitCast ||
- CE->getOpcode() == llvm::Instruction::AddrSpaceCast ||
- // All zero index gep.
- CE->getOpcode() == llvm::Instruction::GetElementPtr);
- Entry = CE->getOperand(0);
- }
+ // Strip off pointer casts if we got them.
+ Entry = Entry->stripPointerCasts();
// Entry is now either a Function or GlobalVariable.
auto *GV = dyn_cast(Entry);
@@ -4106,7 +4101,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// Make a new global with the correct type, this is now guaranteed to work.
GV = cast(
- GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative)));
+ GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative))
+ ->stripPointerCasts());
// Replace all uses of the old global with the new global
llvm::Constant *NewPtrForOldDecl =
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 253bc95e5a6d3..3b4a26830fdc5 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2036,23 +2036,36 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return true;
}
+enum {
+ TopLevelAction = 0,
+ HeadSibAction = 1,
+ OtherSibAction = 2,
+};
+
// Display an action graph human-readably. Action A is the "sink" node
// and latest-occuring action. Traversal is in pre-order, visiting the
// inputs to each action before printing the action itself.
static unsigned PrintActions1(const Compilation &C, Action *A,
- std::map &Ids) {
+ std::map &Ids,
+ Twine Indent = {}, int Kind = TopLevelAction) {
if (Ids.count(A)) // A was already visited.
return Ids[A];
std::string str;
llvm::raw_string_ostream os(str);
+ auto getSibIndent = [](int K) -> Twine {
+ return (K == HeadSibAction) ? " " : (K == OtherSibAction) ? "| " : "";
+ };
+
+ Twine SibIndent = Indent + getSibIndent(Kind);
+ int SibKind = HeadSibAction;
os << Action::getClassName(A->getKind()) << ", ";
if (InputAction *IA = dyn_cast(A)) {
os << "\"" << IA->getInputArg().getValue() << "\"";
} else if (BindArchAction *BIA = dyn_cast(A)) {
os << '"' << BIA->getArchName() << '"' << ", {"
- << PrintActions1(C, *BIA->input_begin(), Ids) << "}";
+ << PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}";
} else if (OffloadAction *OA = dyn_cast(A)) {
bool IsFirst = true;
OA->doOnEachDependence(
@@ -2075,8 +2088,9 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
os << ":" << BoundArch;
os << ")";
os << '"';
- os << " {" << PrintActions1(C, A, Ids) << "}";
+ os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}";
IsFirst = false;
+ SibKind = OtherSibAction;
});
} else {
const ActionList *AL = &A->getInputs();
@@ -2084,8 +2098,9 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
if (AL->size()) {
const char *Prefix = "{";
for (Action *PreRequisite : *AL) {
- os << Prefix << PrintActions1(C, PreRequisite, Ids);
+ os << Prefix << PrintActions1(C, PreRequisite, Ids, SibIndent, SibKind);
Prefix = ", ";
+ SibKind = OtherSibAction;
}
os << "}";
} else
@@ -2106,9 +2121,13 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
}
}
+ auto getSelfIndent = [](int K) -> Twine {
+ return (K == HeadSibAction) ? "+- " : (K == OtherSibAction) ? "|- " : "";
+ };
+
unsigned Id = Ids.size();
Ids[A] = Id;
- llvm::errs() << Id << ": " << os.str() << ", "
+ llvm::errs() << Indent + getSelfIndent(Kind) << Id << ": " << os.str() << ", "
<< types::getTypeName(A->getType()) << offload_os.str() << "\n";
return Id;
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 35d11f4e2d3b3..3a5fe6ddeaed5 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -12,6 +12,7 @@
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index b99a1b4d36949..68a57310ad402 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 59ff7cbc787c7..3e02e57e0f6c7 100644
--- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -13,6 +13,7 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 34be226b69e98..d2b97bf6ad719 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -13,6 +13,7 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 01648fea8dd8e..2c70c0599ecfa 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -159,6 +159,20 @@ class LogicalErrorHandler : public CFGCallback {
S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)
<< DiagRange << isAlwaysTrue;
}
+
+ void compareBitwiseOr(const BinaryOperator *B) override {
+ if (HasMacroID(B))
+ return;
+
+ SourceRange DiagRange = B->getSourceRange();
+ S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_or) << DiagRange;
+ }
+
+ static bool hasActiveDiagnostics(DiagnosticsEngine &Diags,
+ SourceLocation Loc) {
+ return !Diags.isIgnored(diag::warn_tautological_overlap_comparison, Loc) ||
+ !Diags.isIgnored(diag::warn_comparison_bitwise_or, Loc);
+ }
};
} // anonymous namespace
@@ -2070,10 +2084,9 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
.setAlwaysAdd(Stmt::AttributedStmtClass);
}
- // Install the logical handler for -Wtautological-overlap-compare
+ // Install the logical handler.
llvm::Optional LEH;
- if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,
- D->getBeginLoc())) {
+ if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
LEH.emplace(S);
AC.getCFGBuildOptions().Observer = &*LEH;
}
@@ -2222,9 +2235,8 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
checkThrowInNonThrowingFunc(S, FD, AC);
// If none of the previous checks caused a CFG build, trigger one here
- // for -Wtautological-overlap-compare
- if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,
- D->getBeginLoc())) {
+ // for the logical error handler.
+ if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
AC.getCFG();
}
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 8c6abc448d977..0ebb5c68f7c23 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1304,6 +1304,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
bool DerivedToBase;
bool ObjCConversion;
bool ObjCLifetimeConversion;
+ bool FunctionConversion;
QualType FromType = SrcExpr->getType();
QualType ToType = R->getPointeeType();
if (CStyle) {
@@ -1313,7 +1314,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship(
SrcExpr->getBeginLoc(), ToType, FromType, DerivedToBase, ObjCConversion,
- ObjCLifetimeConversion);
+ ObjCLifetimeConversion, FunctionConversion);
if (RefResult != Sema::Ref_Compatible) {
if (CStyle || RefResult == Sema::Ref_Incompatible)
return TC_NotApplicable;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b0d700cb660b0..74dcac7ecb774 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7686,7 +7686,12 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc,
static bool IsArithmeticOp(BinaryOperatorKind Opc) {
return BinaryOperator::isAdditiveOp(Opc) ||
BinaryOperator::isMultiplicativeOp(Opc) ||
- BinaryOperator::isShiftOp(Opc);
+ BinaryOperator::isShiftOp(Opc) || Opc == BO_And || Opc == BO_Or;
+ // This only checks for bitwise-or and bitwise-and, but not bitwise-xor and
+ // not any of the logical operators. Bitwise-xor is commonly used as a
+ // logical-xor because there is no logical-xor operator. The logical
+ // operators, including uses of xor, have a high false positive rate for
+ // precedence warnings.
}
/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary
@@ -7776,7 +7781,11 @@ static void DiagnoseConditionalPrecedence(Sema &Self,
// The condition is an arithmetic binary expression, with a right-
// hand side that looks boolean, so warn.
- Self.Diag(OpLoc, diag::warn_precedence_conditional)
+ unsigned DiagID = BinaryOperator::isBitwiseOp(CondOpcode)
+ ? diag::warn_precedence_bitwise_conditional
+ : diag::warn_precedence_conditional;
+
+ Self.Diag(OpLoc, DiagID)
<< Condition->getSourceRange()
<< BinaryOperator::getOpcodeStr(CondOpcode);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index bb2b445bf58f2..e6491e4f67249 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5862,20 +5862,21 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
LVK == RVK && LVK != VK_RValue) {
// DerivedToBase was already handled by the class-specific case above.
// FIXME: Should we allow ObjC conversions here?
- bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion;
- if (CompareReferenceRelationship(
- QuestionLoc, LTy, RTy, DerivedToBase,
- ObjCConversion, ObjCLifetimeConversion) == Ref_Compatible &&
+ bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
+ FunctionConversion;
+ if (CompareReferenceRelationship(QuestionLoc, LTy, RTy, DerivedToBase,
+ ObjCConversion, ObjCLifetimeConversion,
+ FunctionConversion) == Ref_Compatible &&
!DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion &&
// [...] subject to the constraint that the reference must bind
// directly [...]
- !RHS.get()->refersToBitField() &&
- !RHS.get()->refersToVectorElement()) {
+ !RHS.get()->refersToBitField() && !RHS.get()->refersToVectorElement()) {
RHS = ImpCastExprToType(RHS.get(), LTy, CK_NoOp, RVK);
RTy = RHS.get()->getType();
} else if (CompareReferenceRelationship(
- QuestionLoc, RTy, LTy, DerivedToBase,
- ObjCConversion, ObjCLifetimeConversion) == Ref_Compatible &&
+ QuestionLoc, RTy, LTy, DerivedToBase, ObjCConversion,
+ ObjCLifetimeConversion,
+ FunctionConversion) == Ref_Compatible &&
!DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion &&
!LHS.get()->refersToBitField() &&
!LHS.get()->refersToVectorElement()) {
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 38de136503bf6..43c47c38e6f6f 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4229,10 +4229,10 @@ static void TryReferenceListInitialization(Sema &S,
return;
SourceLocation DeclLoc = Initializer->getBeginLoc();
- bool dummy1, dummy2, dummy3;
+ bool dummy1, dummy2, dummy3, dummy4;
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1,
- dummy2, dummy3);
+ dummy2, dummy3, dummy4);
if (RefRelationship >= Sema::Ref_Related) {
// Try to bind the reference here.
TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
@@ -4472,13 +4472,15 @@ static OverloadingResult TryRefInitWithConversionFunction(
bool DerivedToBase;
bool ObjCConversion;
bool ObjCLifetimeConversion;
- assert(!S.CompareReferenceRelationship(Initializer->getBeginLoc(), T1, T2,
- DerivedToBase, ObjCConversion,
- ObjCLifetimeConversion) &&
+ bool FunctionConversion;
+ assert(!S.CompareReferenceRelationship(
+ Initializer->getBeginLoc(), T1, T2, DerivedToBase, ObjCConversion,
+ ObjCLifetimeConversion, FunctionConversion) &&
"Must have incompatible references when binding via conversion");
(void)DerivedToBase;
(void)ObjCConversion;
(void)ObjCLifetimeConversion;
+ (void)FunctionConversion;
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
@@ -4605,10 +4607,11 @@ static OverloadingResult TryRefInitWithConversionFunction(
bool NewDerivedToBase = false;
bool NewObjCConversion = false;
bool NewObjCLifetimeConversion = false;
- Sema::ReferenceCompareResult NewRefRelationship
- = S.CompareReferenceRelationship(DeclLoc, T1, cv3T3,
- NewDerivedToBase, NewObjCConversion,
- NewObjCLifetimeConversion);
+ bool NewFunctionConversion = false;
+ Sema::ReferenceCompareResult NewRefRelationship =
+ S.CompareReferenceRelationship(
+ DeclLoc, T1, cv3T3, NewDerivedToBase, NewObjCConversion,
+ NewObjCLifetimeConversion, NewFunctionConversion);
// Add the final conversion sequence, if necessary.
if (NewRefRelationship == Sema::Ref_Incompatible) {
@@ -4642,6 +4645,8 @@ static OverloadingResult TryRefInitWithConversionFunction(
Sequence.AddDerivedToBaseCastStep(cv1T1, VK);
else if (NewObjCConversion)
Sequence.AddObjCObjectConversionStep(cv1T1);
+ else if (NewFunctionConversion)
+ Sequence.AddQualificationConversionStep(cv1T1, VK);
return OR_Success;
}
@@ -4701,10 +4706,11 @@ static void TryReferenceInitializationCore(Sema &S,
bool DerivedToBase = false;
bool ObjCConversion = false;
bool ObjCLifetimeConversion = false;
+ bool FunctionConversion = false;
Expr::Classification InitCategory = Initializer->Classify(S.Context);
- Sema::ReferenceCompareResult RefRelationship
- = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
- ObjCConversion, ObjCLifetimeConversion);
+ Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(
+ DeclLoc, cv1T1, cv2T2, DerivedToBase, ObjCConversion,
+ ObjCLifetimeConversion, FunctionConversion);
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression of type
@@ -4735,6 +4741,8 @@ static void TryReferenceInitializationCore(Sema &S,
Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue);
else if (ObjCConversion)
Sequence.AddObjCObjectConversionStep(cv1T1);
+ else if (FunctionConversion)
+ Sequence.AddQualificationConversionStep(cv1T1, VK_LValue);
// We only create a temporary here when binding a reference to a
// bit-field or vector element. Those cases are't supposed to be
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index df4f0ddc6c37d..749b0f2caaa03 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -335,7 +335,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
case StaticDataMember:
// -- the initializers of nonspecialized static members of template classes
if (!IsInNonspecializedTemplate)
- return std::make_tuple(nullptr, nullptr);
+ return std::make_tuple(nullptr, ManglingContextDecl);
// Fall through to get the current context.
LLVM_FALLTHROUGH;
@@ -356,14 +356,15 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
llvm_unreachable("unexpected context");
}
-CXXMethodDecl *Sema::startLambdaDefinition(
- CXXRecordDecl *Class, SourceRange IntroducerRange,
- TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc,
- ArrayRef Params, ConstexprSpecKind ConstexprKind,
- Optional> Mangling) {
+CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ TypeSourceInfo *MethodTypeInfo,
+ SourceLocation EndLoc,
+ ArrayRef Params,
+ ConstexprSpecKind ConstexprKind) {
QualType MethodType = MethodTypeInfo->getType();
TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(getCurLambda(), *this);
+ getGenericLambdaTemplateParameterList(getCurLambda(), *this);
// If a lambda appears in a dependent context or is a generic lambda (has
// template parameters) and has an 'auto' return type, deduce it to a
// dependent type.
@@ -425,20 +426,55 @@ CXXMethodDecl *Sema::startLambdaDefinition(
P->setOwningFunction(Method);
}
+ return Method;
+}
+
+void Sema::handleLambdaNumbering(
+ CXXRecordDecl *Class, CXXMethodDecl *Method,
+ Optional> Mangling) {
if (Mangling) {
- Class->setLambdaMangling(Mangling->first, Mangling->second);
- } else {
- MangleNumberingContext *MCtx;
+ unsigned ManglingNumber;
+ bool HasKnownInternalLinkage;
Decl *ManglingContextDecl;
- std::tie(MCtx, ManglingContextDecl) =
- getCurrentMangleNumberContext(Class->getDeclContext());
- if (MCtx) {
- unsigned ManglingNumber = MCtx->getManglingNumber(Method);
- Class->setLambdaMangling(ManglingNumber, ManglingContextDecl);
- }
+ std::tie(ManglingNumber, HasKnownInternalLinkage, ManglingContextDecl) =
+ Mangling.getValue();
+ Class->setLambdaMangling(ManglingNumber, ManglingContextDecl,
+ HasKnownInternalLinkage);
+ return;
}
- return Method;
+ auto getMangleNumberingContext =
+ [this](CXXRecordDecl *Class, Decl *ManglingContextDecl) -> MangleNumberingContext * {
+ // Get mangle numbering context if there's any extra decl context.
+ if (ManglingContextDecl)
+ return &Context.getManglingNumberContext(
+ ASTContext::NeedExtraManglingDecl, ManglingContextDecl);
+ // Otherwise, from that lambda's decl context.
+ auto DC = Class->getDeclContext();
+ while (auto *CD = dyn_cast(DC))
+ DC = CD->getParent();
+ return &Context.getManglingNumberContext(DC);
+ };
+
+ MangleNumberingContext *MCtx;
+ Decl *ManglingContextDecl;
+ std::tie(MCtx, ManglingContextDecl) =
+ getCurrentMangleNumberContext(Class->getDeclContext());
+ bool HasKnownInternalLinkage = false;
+ if (!MCtx && getLangOpts().CUDA) {
+ // Force lambda numbering in CUDA/HIP as we need to name lambdas following
+ // ODR. Both device- and host-compilation need to have a consistent naming
+ // on kernel functions. As lambdas are potential part of these `__global__`
+ // function names, they needs numbering following ODR.
+ MCtx = getMangleNumberingContext(Class, ManglingContextDecl);
+ assert(MCtx && "Retrieving mangle numbering context failed!");
+ HasKnownInternalLinkage = true;
+ }
+ if (MCtx) {
+ unsigned ManglingNumber = MCtx->getManglingNumber(Method);
+ Class->setLambdaMangling(ManglingNumber, ManglingContextDecl,
+ HasKnownInternalLinkage);
+ }
}
void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
@@ -951,6 +987,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (getLangOpts().CUDA)
CUDASetLambdaAttrs(Method);
+ // Number the lambda for linkage purposes if necessary.
+ handleLambdaNumbering(Class, Method);
+
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index af70bcaa28874..cfd891ba6a6c0 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -4372,7 +4372,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
bool &DerivedToBase,
bool &ObjCConversion,
- bool &ObjCLifetimeConversion) {
+ bool &ObjCLifetimeConversion,
+ bool &FunctionConversion) {
assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
@@ -4402,15 +4403,16 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
ObjCConversion = true;
else if (UnqualT2->isFunctionType() &&
- IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2))
+ IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) {
// C++1z [dcl.init.ref]p4:
// cv1 T1" is reference-compatible with "cv2 T2" if [...] T2 is "noexcept
// function" and T1 is "function"
//
// We extend this to also apply to 'noreturn', so allow any function
// conversion between function types.
+ FunctionConversion = true;
return Ref_Compatible;
- else
+ } else
return Ref_Incompatible;
// At this point, we know that T1 and T2 are reference-related (at
@@ -4491,6 +4493,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
bool DerivedToBase = false;
bool ObjCConversion = false;
bool ObjCLifetimeConversion = false;
+ bool FunctionConversion = false;
// If we are initializing an rvalue reference, don't permit conversion
// functions that return lvalues.
@@ -4503,12 +4506,13 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
if (!ConvTemplate &&
S.CompareReferenceRelationship(
- DeclLoc,
- Conv->getConversionType().getNonReferenceType()
- .getUnqualifiedType(),
- DeclType.getNonReferenceType().getUnqualifiedType(),
- DerivedToBase, ObjCConversion, ObjCLifetimeConversion) ==
- Sema::Ref_Incompatible)
+ DeclLoc,
+ Conv->getConversionType()
+ .getNonReferenceType()
+ .getUnqualifiedType(),
+ DeclType.getNonReferenceType().getUnqualifiedType(),
+ DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
+ FunctionConversion) == Sema::Ref_Incompatible)
continue;
} else {
// If the conversion function doesn't return a reference type,
@@ -4612,11 +4616,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
bool DerivedToBase = false;
bool ObjCConversion = false;
bool ObjCLifetimeConversion = false;
+ bool FunctionConversion = false;
Expr::Classification InitCategory = Init->Classify(S.Context);
- Sema::ReferenceCompareResult RefRelationship
- = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase,
- ObjCConversion, ObjCLifetimeConversion);
-
+ Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(
+ DeclLoc, T1, T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
+ FunctionConversion);
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression
@@ -5041,9 +5045,10 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
bool dummy1 = false;
bool dummy2 = false;
bool dummy3 = false;
+ bool dummy4 = false;
Sema::ReferenceCompareResult RefRelationship =
S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2, dummy1,
- dummy2, dummy3);
+ dummy2, dummy3, dummy4);
if (RefRelationship >= Sema::Ref_Related) {
return TryReferenceInit(S, Init, ToType, /*FIXME*/ From->getBeginLoc(),
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 89a7b8cc845e6..4b3a6708717c2 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -11497,17 +11497,18 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) {
E->getCaptureDefault());
getDerived().transformedLocalDecl(OldClass, {Class});
- Optional> Mangling;
+ Optional> Mangling;
if (getDerived().ReplacingOriginal())
- Mangling = std::make_pair(OldClass->getLambdaManglingNumber(),
- OldClass->getLambdaContextDecl());
+ Mangling = std::make_tuple(OldClass->getLambdaManglingNumber(),
+ OldClass->hasKnownLambdaInternalLinkage(),
+ OldClass->getLambdaContextDecl());
// Build the call operator.
CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
Class, E->getIntroducerRange(), NewCallOpTSI,
E->getCallOperator()->getEndLoc(),
NewCallOpTSI->getTypeLoc().castAs().getParams(),
- E->getCallOperator()->getConstexprKind(), Mangling);
+ E->getCallOperator()->getConstexprKind());
LSI->CallOperator = NewCallOperator;
@@ -11527,6 +11528,9 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) {
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
+ // Number the lambda for linkage purposes if necessary.
+ getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), NewCallOperator,
/*NewThisContext*/false);
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 65d62524e22f7..9aa8c77c62319 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1690,6 +1690,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
Lambda.CaptureDefault = Record.readInt();
Lambda.NumCaptures = Record.readInt();
Lambda.NumExplicitCaptures = Record.readInt();
+ Lambda.HasKnownInternalLinkage = Record.readInt();
Lambda.ManglingNumber = Record.readInt();
Lambda.ContextDecl = ReadDeclID();
Lambda.Captures = (Capture *)Reader.getContext().Allocate(
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index c6b05c9a17987..28affedbbb30f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6224,6 +6224,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Lambda.CaptureDefault);
Record->push_back(Lambda.NumCaptures);
Record->push_back(Lambda.NumExplicitCaptures);
+ Record->push_back(Lambda.HasKnownInternalLinkage);
Record->push_back(Lambda.ManglingNumber);
AddDeclRef(D->getLambdaContextDecl());
AddTypeSourceInfo(Lambda.MethodTyInfo);
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index f1592ebff669d..7ba93b858baf5 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1418,14 +1418,19 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (Optional CE = Succ->getLocationAs()) {
if (const auto *VR = dyn_cast(R)) {
- const auto *Param = cast(VR->getDecl());
+ if (const auto *Param = dyn_cast(VR->getDecl())) {
+ ProgramStateManager &StateMgr = BRC.getStateManager();
+ CallEventManager &CallMgr = StateMgr.getCallEventManager();
- ProgramStateManager &StateMgr = BRC.getStateManager();
- CallEventManager &CallMgr = StateMgr.getCallEventManager();
-
- CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
- Succ->getState());
- InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
+ CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
+ Succ->getState());
+ InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
+ } else {
+ // Handle Objective-C 'self'.
+ assert(isa(VR->getDecl()));
+ InitE = cast(CE->getCalleeContext()->getCallSite())
+ ->getInstanceReceiver()->IgnoreParenCasts();
+ }
IsParam = true;
}
}
@@ -2029,8 +2034,6 @@ bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
// Is it a symbolic value?
if (auto L = V.getAs()) {
- report.addVisitor(std::make_unique(L->getRegion()));
-
// FIXME: this is a hack for fixing a later crash when attempting to
// dereference a void* pointer.
// We should not try to dereference pointers at all when we don't care
@@ -2051,10 +2054,14 @@ bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
else if (CanDereference)
RVal = LVState->getSVal(L->getRegion());
- if (CanDereference)
+ if (CanDereference) {
+ report.addVisitor(
+ std::make_unique(L->getRegion()));
+
if (auto KV = RVal.getAs())
report.addVisitor(std::make_unique(
*KV, L->getRegion(), EnableNullFPSuppression, TKind, SFC));
+ }
const MemRegion *RegionRVal = RVal.getAsRegion();
if (RegionRVal && isa(RegionRVal)) {
diff --git a/clang/lib/Tooling/AllTUsExecution.cpp b/clang/lib/Tooling/AllTUsExecution.cpp
index 267f945f567b7..d85075f596079 100644
--- a/clang/lib/Tooling/AllTUsExecution.cpp
+++ b/clang/lib/Tooling/AllTUsExecution.cpp
@@ -8,6 +8,7 @@
#include "clang/Tooling/AllTUsExecution.h"
#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/VirtualFileSystem.h"
diff --git a/clang/test/Analysis/cast-value-logic.cpp b/clang/test/Analysis/cast-value-logic.cpp
index 221ae7f9ae38b..1411ede92e366 100644
--- a/clang/test/Analysis/cast-value-logic.cpp
+++ b/clang/test/Analysis/cast-value-logic.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 \
+// RUN: %clang_analyze_cc1 -std=c++14 \
// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
// RUN: -verify %s
diff --git a/clang/test/Analysis/cast-value-notes.cpp b/clang/test/Analysis/cast-value-notes.cpp
index a0eaeae8ba483..eb5d1b3d3fe27 100644
--- a/clang/test/Analysis/cast-value-notes.cpp
+++ b/clang/test/Analysis/cast-value-notes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 \
+// RUN: %clang_analyze_cc1 -std=c++14 \
// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
// RUN: -analyzer-output=text -verify %s
diff --git a/clang/test/Analysis/cast-value-state-dump.cpp b/clang/test/Analysis/cast-value-state-dump.cpp
index b8152d46da47d..9abdaae0d4592 100644
--- a/clang/test/Analysis/cast-value-state-dump.cpp
+++ b/clang/test/Analysis/cast-value-state-dump.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 \
+// RUN: %clang_analyze_cc1 -std=c++14 \
// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
// RUN: -analyzer-output=text -verify %s 2>&1 | FileCheck %s
diff --git a/clang/test/Analysis/ctu-different-triples.cpp b/clang/test/Analysis/ctu-different-triples.cpp
index dbfa82fb483d9..20acc318e2e72 100644
--- a/clang/test/Analysis/ctu-different-triples.cpp
+++ b/clang/test/Analysis/ctu-different-triples.cpp
@@ -1,9 +1,9 @@
// RUN: rm -rf %t && mkdir %t
// RUN: mkdir -p %t/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
// RUN: -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
// RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.txt %t/ctudir/externalDefMap.txt
-// RUN: %clang_analyze_cc1 -triple powerpc64-montavista-linux-gnu \
+// RUN: %clang_analyze_cc1 -std=c++14 -triple powerpc64-montavista-linux-gnu \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
// RUN: -analyzer-config ctu-dir=%t/ctudir \
diff --git a/clang/test/Analysis/ctu-main.cpp b/clang/test/Analysis/ctu-main.cpp
index abfacfbdae5d7..3f095a0aabc30 100644
--- a/clang/test/Analysis/ctu-main.cpp
+++ b/clang/test/Analysis/ctu-main.cpp
@@ -1,16 +1,16 @@
// RUN: rm -rf %t && mkdir %t
// RUN: mkdir -p %t/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
// RUN: -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
// RUN: -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
// RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.txt %t/ctudir/externalDefMap.txt
-// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
// RUN: -analyzer-config ctu-dir=%t/ctudir \
// RUN: -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
// RUN: -analyzer-config ctu-dir=%t/ctudir \
diff --git a/clang/test/Analysis/ctu-unknown-parts-in-triples.cpp b/clang/test/Analysis/ctu-unknown-parts-in-triples.cpp
index 5e643c164dd7d..6bcbd709b5ef7 100644
--- a/clang/test/Analysis/ctu-unknown-parts-in-triples.cpp
+++ b/clang/test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -3,10 +3,10 @@
// RUN: rm -rf %t && mkdir %t
// RUN: mkdir -p %t/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
// RUN: -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
// RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.txt %t/ctudir/externalDefMap.txt
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu \
+// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-linux-gnu \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
// RUN: -analyzer-config ctu-dir=%t/ctudir \
diff --git a/clang/test/Analysis/deadstores-driverkit.cpp b/clang/test/Analysis/deadstores-driverkit.cpp
index 0885367b1b9bf..9c423fc6ff218 100644
--- a/clang/test/Analysis/deadstores-driverkit.cpp
+++ b/clang/test/Analysis/deadstores-driverkit.cpp
@@ -5,7 +5,7 @@
// It needs to be on the top.
// Run-lines can wait.
-// RUN: %clang_analyze_cc1 -w -triple x86_64-apple-driverkit19.0 \
+// RUN: %clang_analyze_cc1 -std=c++17 -w -triple x86_64-apple-driverkit19.0 \
// RUN: -analyzer-checker=deadcode -verify %s
// expected-no-diagnostics
diff --git a/clang/test/Analysis/diagnostics/dtors.cpp b/clang/test/Analysis/diagnostics/dtors.cpp
index 18bedc61f98e8..6a8349da9d78c 100644
--- a/clang/test/Analysis/diagnostics/dtors.cpp
+++ b/clang/test/Analysis/diagnostics/dtors.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -std=c++14 -w -analyzer-checker=core,cplusplus -analyzer-output=text -verify %s
namespace no_crash_on_delete_dtor {
// We were crashing when producing diagnostics for this code, but not for the
diff --git a/clang/test/Analysis/domtest.cpp b/clang/test/Analysis/domtest.cpp
index 078117ef85dc1..2a2caed130d79 100644
--- a/clang/test/Analysis/domtest.cpp
+++ b/clang/test/Analysis/domtest.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 %s \
+// RUN: %clang_analyze_cc1 -std=c++14 %s \
// RUN: -analyzer-checker=debug.DumpDominators \
// RUN: -analyzer-checker=debug.DumpPostDominators \
// RUN: -analyzer-checker=debug.DumpControlDependencies \
diff --git a/clang/test/Analysis/explain-svals.cpp b/clang/test/Analysis/explain-svals.cpp
index c1b5200eb8e92..9c37642758bb9 100644
--- a/clang/test/Analysis/explain-svals.cpp
+++ b/clang/test/Analysis/explain-svals.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core.builtin,debug.ExprInspection,unix.cstring -verify %s
+// RUN: %clang_analyze_cc1 -std=c++14 -triple i386-apple-darwin10 -analyzer-checker=core.builtin,debug.ExprInspection,unix.cstring -verify %s
typedef unsigned long size_t;
diff --git a/clang/test/Analysis/initialization.cpp b/clang/test/Analysis/initialization.cpp
index db765930b6e5e..dd622e077e934 100644
--- a/clang/test/Analysis/initialization.cpp
+++ b/clang/test/Analysis/initialization.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -std=c++14 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
void clang_analyzer_eval(int);
diff --git a/clang/test/Analysis/inlining/placement-new-fp-suppression.cpp b/clang/test/Analysis/inlining/placement-new-fp-suppression.cpp
index 5f75411716836..5a99ad11cc17e 100644
--- a/clang/test/Analysis/inlining/placement-new-fp-suppression.cpp
+++ b/clang/test/Analysis/inlining/placement-new-fp-suppression.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_analyze_cc1 \
+// RUN: %clang_analyze_cc1 -std=c++14 \
// RUN: -analyzer-checker=core.CallAndMessage \
// RUN: -analyzer-config suppress-null-return-paths=false \
// RUN: -verify %s
-// RUN: %clang_analyze_cc1 \
+// RUN: %clang_analyze_cc1 -std=c++14 \
// RUN: -analyzer-checker=core.CallAndMessage \
// RUN: -DSUPPRESSED \
// RUN: -verify %s
diff --git a/clang/test/Analysis/inner-pointer.cpp b/clang/test/Analysis/inner-pointer.cpp
index 5cee0bfbcca60..d8b011a7aa64e 100644
--- a/clang/test/Analysis/inner-pointer.cpp
+++ b/clang/test/Analysis/inner-pointer.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer \
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=cplusplus.InnerPointer \
// RUN: -Wno-dangling -Wno-dangling-field -Wno-return-stack-address \
// RUN: %s -analyzer-output=text -verify
diff --git a/clang/test/Analysis/malloc.mm b/clang/test/Analysis/malloc.mm
index d7bfbf3f34f33..e84644b9dd732 100644
--- a/clang/test/Analysis/malloc.mm
+++ b/clang/test/Analysis/malloc.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s
#import "Inputs/system-header-simulator-objc.h"
#import "Inputs/system-header-simulator-for-malloc.h"
diff --git a/clang/test/Analysis/mig.mm b/clang/test/Analysis/mig.mm
index 0c7d729e9375d..e8d08f355d3ea 100644
--- a/clang/test/Analysis/mig.mm
+++ b/clang/test/Analysis/mig.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,osx.MIG\
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,osx.MIG -std=c++14 \
// RUN: -analyzer-output=text -fblocks -verify %s
typedef unsigned uint32_t;
diff --git a/clang/test/Analysis/new-ctor-null-throw.cpp b/clang/test/Analysis/new-ctor-null-throw.cpp
index dfa7cba763fcf..28922c0fad4b7 100644
--- a/clang/test/Analysis/new-ctor-null-throw.cpp
+++ b/clang/test/Analysis/new-ctor-null-throw.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core \
// RUN: -analyzer-config suppress-null-return-paths=false \
// RUN: -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core \
// RUN: -DSUPPRESSED \
// RUN: -verify %s
diff --git a/clang/test/Analysis/new-ctor-null.cpp b/clang/test/Analysis/new-ctor-null.cpp
index 32f2f9500cce3..f3c07e2123731 100644
--- a/clang/test/Analysis/new-ctor-null.cpp
+++ b/clang/test/Analysis/new-ctor-null.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 \
+// RUN: %clang_analyze_cc1 -std=c++14 \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -verify %s
diff --git a/clang/test/Analysis/novoidtypecrash.c b/clang/test/Analysis/novoidtypecrash.c
index c04cfca29b4f1..b19990a2791b0 100644
--- a/clang/test/Analysis/novoidtypecrash.c
+++ b/clang/test/Analysis/novoidtypecrash.c
@@ -1,8 +1,27 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core %s
+x;
+y(void **z) { // no-crash
+ *z = x;
+ int *w;
+ y(&w);
+ *w;
+}
+
a;
-b(void **c) { // no-crash
- *c = a;
- int *d;
- b(&d);
- *d;
+b(*c) {}
+e(*c) {
+ void *d = f();
+ b(d);
+ *c = d;
+}
+void *g() {
+ e(&a);
+ return a;
+}
+j() {
+ int h;
+ char i = g();
+ if (i)
+ for (; h;)
+ ;
}
diff --git a/clang/test/Analysis/osobject-retain-release.cpp b/clang/test/Analysis/osobject-retain-release.cpp
index afcc242583588..42675fc70e785 100644
--- a/clang/test/Analysis/osobject-retain-release.cpp
+++ b/clang/test/Analysis/osobject-retain-release.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-output=text\
+// RUN: %clang_analyze_cc1 -std=c++14 -fblocks -analyze -analyzer-output=text\
// RUN: -analyzer-checker=core,osx,debug.ExprInspection -verify %s
#include "os_object_base.h"
diff --git a/clang/test/Analysis/osobjectcstylecastchecker_test.cpp b/clang/test/Analysis/osobjectcstylecastchecker_test.cpp
index 07f878cd39d55..fabed7ee34b1b 100644
--- a/clang/test/Analysis/osobjectcstylecastchecker_test.cpp
+++ b/clang/test/Analysis/osobjectcstylecastchecker_test.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=optin.osx.OSObjectCStyleCast %s -verify
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=optin.osx.OSObjectCStyleCast %s -verify
#include "os_object_base.h"
struct OSArray : public OSObject {
diff --git a/clang/test/Analysis/plist-macros-with-expansion.cpp b/clang/test/Analysis/plist-macros-with-expansion.cpp
index e836c78b4bb35..e07747eaec74d 100644
--- a/clang/test/Analysis/plist-macros-with-expansion.cpp
+++ b/clang/test/Analysis/plist-macros-with-expansion.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core -verify %s
//
-// RUN: %clang_analyze_cc1 -analyzer-checker=core %s \
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core %s \
// RUN: -analyzer-output=plist -o %t.plist \
// RUN: -analyzer-config expand-macros=true
//
diff --git a/clang/test/Analysis/ptr-iter.cpp b/clang/test/Analysis/ptr-iter.cpp
index a35fae470a7ef..a94288cd1c8cc 100644
--- a/clang/test/Analysis/ptr-iter.cpp
+++ b/clang/test/Analysis/ptr-iter.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 %s -analyzer-output=text -verify \
+// RUN: %clang_analyze_cc1 %s -std=c++14 -analyzer-output=text -verify \
// RUN: -analyzer-checker=core,alpha.nondeterminism.PointerIteration
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/clang/test/Analysis/ptr-sort.cpp b/clang/test/Analysis/ptr-sort.cpp
index a4f94817f13b3..d238b390bdc23 100644
--- a/clang/test/Analysis/ptr-sort.cpp
+++ b/clang/test/Analysis/ptr-sort.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 %s -analyzer-output=text -verify \
+// RUN: %clang_analyze_cc1 %s -std=c++14 -analyzer-output=text -verify \
// RUN: -analyzer-checker=core,alpha.nondeterminism.PointerSorting
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/clang/test/Analysis/rvo.cpp b/clang/test/Analysis/rvo.cpp
index cf06a9570b368..7215fbbded461 100644
--- a/clang/test/Analysis/rvo.cpp
+++ b/clang/test/Analysis/rvo.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker core,cplusplus \
+// RUN: %clang_analyze_cc1 -analyzer-checker core,cplusplus -std=c++14 \
// RUN: -analyzer-checker debug.ExprInspection -verify %s
void clang_analyzer_eval(bool);
diff --git a/clang/test/Analysis/sizeofpack.cpp b/clang/test/Analysis/sizeofpack.cpp
index 44c3bba3a8ae4..8c0ca02b0710a 100644
--- a/clang/test/Analysis/sizeofpack.cpp
+++ b/clang/test/Analysis/sizeofpack.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection \
-// RUN: -verify %s
+// RUN: -std=c++14 -verify %s
typedef __typeof(sizeof(int)) size_t;
diff --git a/clang/test/Analysis/stack-frame-context-revision.cpp b/clang/test/Analysis/stack-frame-context-revision.cpp
index 8c119f50c141e..51f86defe3154 100644
--- a/clang/test/Analysis/stack-frame-context-revision.cpp
+++ b/clang/test/Analysis/stack-frame-context-revision.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -verify %s
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,cplusplus.NewDelete -verify %s
// expected-no-diagnostics:
// From now the profile of the 'StackFrameContext' also contains the
diff --git a/clang/test/Analysis/temporaries.mm b/clang/test/Analysis/temporaries.mm
index 43546ae3441d8..44d30d5d7d535 100644
--- a/clang/test/Analysis/temporaries.mm
+++ b/clang/test/Analysis/temporaries.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker core,cplusplus -verify %s
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker core,cplusplus -verify %s
// expected-no-diagnostics
diff --git a/clang/test/Analysis/test-separate-retaincount.cpp b/clang/test/Analysis/test-separate-retaincount.cpp
index 5fda2b2e22112..621e1d120bbb2 100644
--- a/clang/test/Analysis/test-separate-retaincount.cpp
+++ b/clang/test/Analysis/test-separate-retaincount.cpp
@@ -1,12 +1,12 @@
-// RUN: %clang_analyze_cc1 -DNO_CF_OBJECT -verify %s \
+// RUN: %clang_analyze_cc1 -std=c++14 -DNO_CF_OBJECT -verify %s \
// RUN: -analyzer-checker=core,osx \
// RUN: -analyzer-disable-checker osx.cocoa.RetainCount
//
-// RUN: %clang_analyze_cc1 -DNO_OS_OBJECT -verify %s \
+// RUN: %clang_analyze_cc1 -std=c++14 -DNO_OS_OBJECT -verify %s \
// RUN: -analyzer-checker=core,osx \
// RUN: -analyzer-disable-checker osx.OSObjectRetainCount
//
-// RUN: %clang_analyze_cc1 -DNO_OS_OBJECT -verify %s \
+// RUN: %clang_analyze_cc1 -std=c++14 -DNO_OS_OBJECT -verify %s \
// RUN: -analyzer-checker=core,osx \
// RUN: -analyzer-config "osx.cocoa.RetainCount:CheckOSObject=false"
diff --git a/clang/test/Analysis/track-control-dependency-conditions.cpp b/clang/test/Analysis/track-control-dependency-conditions.cpp
index 737620f4c31e4..11eb1c56a0388 100644
--- a/clang/test/Analysis/track-control-dependency-conditions.cpp
+++ b/clang/test/Analysis/track-control-dependency-conditions.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_analyze_cc1 %s \
+// RUN: %clang_analyze_cc1 %s -std=c++14 \
// RUN: -verify=expected,tracking \
// RUN: -analyzer-config track-conditions=true \
// RUN: -analyzer-output=text \
// RUN: -analyzer-checker=core
-// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: not %clang_analyze_cc1 -std=c++14 -verify %s \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-config track-conditions=false \
// RUN: -analyzer-config track-conditions-debug=true \
@@ -14,14 +14,14 @@
// CHECK-INVALID-DEBUG-SAME: 'track-conditions-debug', that expects
// CHECK-INVALID-DEBUG-SAME: 'track-conditions' to also be enabled
//
-// RUN: %clang_analyze_cc1 %s \
+// RUN: %clang_analyze_cc1 %s -std=c++14 \
// RUN: -verify=expected,tracking,debug \
// RUN: -analyzer-config track-conditions=true \
// RUN: -analyzer-config track-conditions-debug=true \
// RUN: -analyzer-output=text \
// RUN: -analyzer-checker=core
-// RUN: %clang_analyze_cc1 %s -verify \
+// RUN: %clang_analyze_cc1 %s -std=c++14 -verify \
// RUN: -analyzer-output=text \
// RUN: -analyzer-config track-conditions=false \
// RUN: -analyzer-checker=core
diff --git a/clang/test/Analysis/track-control-dependency-conditions.m b/clang/test/Analysis/track-control-dependency-conditions.m
new file mode 100644
index 0000000000000..05b0638a5eb56
--- /dev/null
+++ b/clang/test/Analysis/track-control-dependency-conditions.m
@@ -0,0 +1,32 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,nullability -verify %s
+
+// expected-no-diagnostics
+
+@class C;
+
+#pragma clang assume_nonnull begin
+@interface I
+- foo:(C *)c;
+@end
+#pragma clang assume_nonnull end
+
+@interface J
+@property C *c;
+@end
+
+J *conjure_J();
+
+@implementation I
+- (void)bar {
+ if (self) { // no-crash
+ J *j = conjure_J();
+ if (j.c)
+ [self bar];
+ // FIXME: Should warn.
+ [self foo:j.c]; // no-warning
+ }
+}
+@end
+
+@implementation J
+@end
diff --git a/clang/test/Analysis/unions.cpp b/clang/test/Analysis/unions.cpp
index 6fd35d1a43f4a..76eb20550fdb4 100644
--- a/clang/test/Analysis/unions.cpp
+++ b/clang/test/Analysis/unions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -analyzer-config eagerly-assume=false -verify
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -analyzer-config eagerly-assume=false -verify
extern void clang_analyzer_eval(bool);
extern void clang_analyzer_warnIfReached();
diff --git a/clang/test/CodeGenCUDA/unnamed-types.cu b/clang/test/CodeGenCUDA/unnamed-types.cu
new file mode 100644
index 0000000000000..81557817e42eb
--- /dev/null
+++ b/clang/test/CodeGenCUDA/unnamed-types.cu
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++11 -x hip -triple x86_64-linux-gnu -aux-triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s --check-prefix=HOST
+// RUN: %clang_cc1 -std=c++11 -x hip -triple amdgcn-amd-amdhsa -fcuda-is-device -emit-llvm %s -o - | FileCheck %s --check-prefix=DEVICE
+
+#include "Inputs/cuda.h"
+
+// HOST: @0 = private unnamed_addr constant [43 x i8] c"_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_\00", align 1
+
+__device__ float d0(float x) {
+ return [](float x) { return x + 2.f; }(x);
+}
+
+__device__ float d1(float x) {
+ return [](float x) { return x * 2.f; }(x);
+}
+
+// DEVICE: amdgpu_kernel void @_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_(
+template
+__global__ void k0(float *p, F f) {
+ p[0] = f(p[0]) + d0(p[1]) + d1(p[2]);
+}
+
+void f0(float *p) {
+ [](float *p) {
+ *p = 1.f;
+ }(p);
+}
+
+// The inner/outer lambdas are required to be mangled following ODR but their
+// linkages are still required to keep the original `internal` linkage.
+
+// HOST: define internal void @_ZZ2f1PfENKUlS_E_clES_(
+// DEVICE: define internal float @_ZZZ2f1PfENKUlS_E_clES_ENKUlfE_clEf(
+void f1(float *p) {
+ [](float *p) {
+ k0<<<1,1>>>(p, [] __device__ (float x) { return x + 1.f; });
+ }(p);
+}
+// HOST: @__hip_register_globals
+// HOST: __hipRegisterFunction{{.*}}@_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_{{.*}}@0
diff --git a/clang/test/CodeGenCXX/cxx11-extern-constexpr.cpp b/clang/test/CodeGenCXX/cxx11-extern-constexpr.cpp
index 6c520038e9415..0688d7bead087 100644
--- a/clang/test/CodeGenCXX/cxx11-extern-constexpr.cpp
+++ b/clang/test/CodeGenCXX/cxx11-extern-constexpr.cpp
@@ -1,10 +1,13 @@
-// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CXX11
-// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CXX17
+// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=X86,CXX11X86
+// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=X86,CXX17X86
+// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple amdgcn-amd-amdhsa | FileCheck %s --check-prefixes=AMD,CXX11AMD
+// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple amdgcn-amd-amdhsa | FileCheck %s --check-prefixes=AMD,CXX17AMD
struct A {
static const int Foo = 123;
};
-// CHECK: @_ZN1A3FooE = constant i32 123, align 4
+// X86: @_ZN1A3FooE = constant i32 123, align 4
+// AMD: @_ZN1A3FooE = addrspace(4) constant i32 123, align 4
const int *p = &A::Foo; // emit available_externally
const int A::Foo; // convert to full definition
@@ -16,7 +19,8 @@ struct CreatePOD {
// Deferred initialization of the structure here requires changing
// the type of the global variable: the initializer list does not include
// the tail padding.
- // CXX11: @_ZN9CreatePOD3podE = available_externally constant { i32, i8 } { i32 42, i8 43 },
+ // CXX11X86: @_ZN9CreatePOD3podE = available_externally constant { i32, i8 } { i32 42, i8 43 },
+ // CXX11AMD: @_ZN9CreatePOD3podE = available_externally addrspace(1) constant { i32, i8 } { i32 42, i8 43 },
static constexpr PODWithInit pod{};
};
const int *p_pod = &CreatePOD::pod.g;
@@ -30,29 +34,40 @@ struct MutableBar {
};
struct Foo {
- // CXX11: @_ZN3Foo21ConstexprStaticMemberE = available_externally constant i32 42,
- // CXX17: @_ZN3Foo21ConstexprStaticMemberE = linkonce_odr constant i32 42,
+ // CXX11X86: @_ZN3Foo21ConstexprStaticMemberE = available_externally constant i32 42,
+ // CXX17X86: @_ZN3Foo21ConstexprStaticMemberE = linkonce_odr constant i32 42,
+ // CXX11AMD: @_ZN3Foo21ConstexprStaticMemberE = available_externally addrspace(4) constant i32 42,
+ // CXX17AMD: @_ZN3Foo21ConstexprStaticMemberE = linkonce_odr addrspace(4) constant i32 42,
static constexpr int ConstexprStaticMember = 42;
- // CHECK: @_ZN3Foo17ConstStaticMemberE = available_externally constant i32 43,
+ // X86: @_ZN3Foo17ConstStaticMemberE = available_externally constant i32 43,
+ // AMD: @_ZN3Foo17ConstStaticMemberE = available_externally addrspace(4) constant i32 43,
static const int ConstStaticMember = 43;
- // CXX11: @_ZN3Foo23ConstStaticStructMemberE = available_externally constant %struct.Bar { i32 44 },
- // CXX17: @_ZN3Foo23ConstStaticStructMemberE = linkonce_odr constant %struct.Bar { i32 44 },
+ // CXX11X86: @_ZN3Foo23ConstStaticStructMemberE = available_externally constant %struct.Bar { i32 44 },
+ // CXX17X86: @_ZN3Foo23ConstStaticStructMemberE = linkonce_odr constant %struct.Bar { i32 44 },
+ // CXX11AMD: @_ZN3Foo23ConstStaticStructMemberE = available_externally addrspace(1) constant %struct.Bar { i32 44 },
+ // CXX17AMD: @_ZN3Foo23ConstStaticStructMemberE = linkonce_odr addrspace(1) constant %struct.Bar { i32 44 },
static constexpr Bar ConstStaticStructMember = {44};
- // CXX11: @_ZN3Foo34ConstexprStaticMutableStructMemberE = external global %struct.MutableBar,
- // CXX17: @_ZN3Foo34ConstexprStaticMutableStructMemberE = linkonce_odr global %struct.MutableBar { i32 45 },
+ // CXX11X86: @_ZN3Foo34ConstexprStaticMutableStructMemberE = external global %struct.MutableBar,
+ // CXX17X86: @_ZN3Foo34ConstexprStaticMutableStructMemberE = linkonce_odr global %struct.MutableBar { i32 45 },
+ // CXX11AMD: @_ZN3Foo34ConstexprStaticMutableStructMemberE = external addrspace(1) global %struct.MutableBar,
+ // CXX17AMD: @_ZN3Foo34ConstexprStaticMutableStructMemberE = linkonce_odr addrspace(1) global %struct.MutableBar { i32 45 },
static constexpr MutableBar ConstexprStaticMutableStructMember = {45};
};
-// CHECK: @_ZL15ConstStaticexpr = internal constant i32 46,
+// X86: @_ZL15ConstStaticexpr = internal constant i32 46,
+// AMD: @_ZL15ConstStaticexpr = internal addrspace(4) constant i32 46,
static constexpr int ConstStaticexpr = 46;
-// CHECK: @_ZL9ConstExpr = internal constant i32 46, align 4
+// X86: @_ZL9ConstExpr = internal constant i32 46, align 4
+// AMD: @_ZL9ConstExpr = internal addrspace(4) constant i32 46, align 4
static const int ConstExpr = 46;
-// CHECK: @_ZL21ConstexprStaticStruct = internal constant %struct.Bar { i32 47 },
+// X86: @_ZL21ConstexprStaticStruct = internal constant %struct.Bar { i32 47 },
+// AMD: @_ZL21ConstexprStaticStruct = internal addrspace(1) constant %struct.Bar { i32 47 },
static constexpr Bar ConstexprStaticStruct = {47};
-// CHECK: @_ZL28ConstexprStaticMutableStruct = internal global %struct.MutableBar { i32 48 },
+// X86: @_ZL28ConstexprStaticMutableStruct = internal global %struct.MutableBar { i32 48 },
+// AMD: @_ZL28ConstexprStaticMutableStruct = internal addrspace(1) global %struct.MutableBar { i32 48 },
static constexpr MutableBar ConstexprStaticMutableStruct = {48};
void use(const int &);
diff --git a/clang/test/CodeGenCXX/implicit-function-conversion.cpp b/clang/test/CodeGenCXX/implicit-function-conversion.cpp
new file mode 100644
index 0000000000000..2d14c6ae519f5
--- /dev/null
+++ b/clang/test/CodeGenCXX/implicit-function-conversion.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-unknown-linux -std=c++17 | FileCheck %s
+
+double a(double) noexcept;
+int b(double (&)(double));
+
+// CHECK: call i32 @_Z1bRFddE(double (double)* @_Z1ad)
+int c = b(a);
diff --git a/clang/test/PCH/debug-info-pch-container-path.c b/clang/test/PCH/debug-info-pch-container-path.c
new file mode 100644
index 0000000000000..efe49e48e2dc5
--- /dev/null
+++ b/clang/test/PCH/debug-info-pch-container-path.c
@@ -0,0 +1,22 @@
+// REQUIRES: asserts
+
+// Modules:
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -fmodule-format=obj -emit-pch \
+// RUN: -triple %itanium_abi_triple \
+// RUN: -fdebug-prefix-map=%t=BUILD \
+// RUN: -fdebug-prefix-map=%S=SOURCE \
+// RUN: -o %t/prefix.ll %S/debug-info-limited-struct.h \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-container.ll
+// RUN: cat %t-container.ll | FileCheck %s
+
+// CHECK: distinct !DICompileUnit(
+// CHECK-SAME: language: DW_LANG_C99,
+// CHECK-SAME: file: ![[FILE:[0-9]+]],
+// CHECK: ![[FILE]] = !DIFile(
+// CHECK-SAME: filename: "SOURCE/debug-info-limited-struct.h",
+// CHECK-SAME: directory: "BUILD"
+
diff --git a/clang/test/Sema/parentheses.c b/clang/test/Sema/parentheses.c
index 0dabc11d39136..047bcbfe6cafd 100644
--- a/clang/test/Sema/parentheses.c
+++ b/clang/test/Sema/parentheses.c
@@ -93,6 +93,28 @@ void conditional_op(int x, int y, _Bool b, void* p) {
(void)(x + y > 0 ? 1 : 2); // no warning
(void)(x + (y > 0) ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '+'}} expected-note 2{{place parentheses}}
+
+ (void)(b ? 0xf0 : 0x10 | b ? 0x5 : 0x2); // expected-warning {{operator '?:' has lower precedence than '|'}} expected-note 2{{place parentheses}}
+
+ (void)((b ? 0xf0 : 0x10) | (b ? 0x5 : 0x2)); // no warning, has parentheses
+ (void)(b ? 0xf0 : (0x10 | b) ? 0x5 : 0x2); // no warning, has parentheses
+
+ (void)(x | b ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '|'}} expected-note 2{{place parentheses}}
+ (void)(x & b ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '&'}} expected-note 2{{place parentheses}}
+
+ (void)((x | b) ? 1 : 2); // no warning, has parentheses
+ (void)(x | (b ? 1 : 2)); // no warning, has parentheses
+ (void)((x & b) ? 1 : 2); // no warning, has parentheses
+ (void)(x & (b ? 1 : 2)); // no warning, has parentheses
+
+ // Only warn on uses of the bitwise operators, and not the logical operators.
+ // The bitwise operators are more likely to be bugs while the logical
+ // operators are more likely to be used correctly. Since there is no
+ // explicit logical-xor operator, the bitwise-xor is commonly used instead.
+ // For this warning, treat the bitwise-xor as if it were a logical operator.
+ (void)(x ^ b ? 1 : 2); // no warning, ^ is often used as logical xor
+ (void)(x || b ? 1 : 2); // no warning, logical operator
+ (void)(x && b ? 1 : 2); // no warning, logical operator
}
// RUN: not %clang_cc1 -fsyntax-only -Wparentheses -Werror -fdiagnostics-show-option %s 2>&1 | FileCheck %s -check-prefix=CHECK-FLAG
diff --git a/clang/test/Sema/warn-bitwise-compare.c b/clang/test/Sema/warn-bitwise-compare.c
index 175f8f5367f33..d08f1bf13f20b 100644
--- a/clang/test/Sema/warn-bitwise-compare.c
+++ b/clang/test/Sema/warn-bitwise-compare.c
@@ -1,7 +1,12 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wtautological-compare %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wtautological-bitwise-compare %s
#define mydefine 2
+enum {
+ ZERO,
+ ONE,
+};
+
void f(int x) {
if ((8 & x) == 3) {} // expected-warning {{bitwise comparison always evaluates to false}}
if ((x & 8) == 4) {} // expected-warning {{bitwise comparison always evaluates to false}}
@@ -13,6 +18,9 @@ void f(int x) {
if ((x & 0x15) == 0x13) {} // expected-warning {{bitwise comparison always evaluates to false}}
if ((0x23 | x) == 0x155){} // expected-warning {{bitwise comparison always evaluates to false}}
+ if (!!((8 & x) == 3)) {} // expected-warning {{bitwise comparison always evaluates to false}}
+ int y = ((8 & x) == 3) ? 1 : 2; // expected-warning {{bitwise comparison always evaluates to false}}
+
if ((x & 8) == 8) {}
if ((x & 8) != 8) {}
if ((x | 4) == 4) {}
@@ -26,3 +34,14 @@ void f(int x) {
if ((x & mydefine) == 8) {}
if ((x | mydefine) == 4) {}
}
+
+void g(int x) {
+ if (x | 5) {} // expected-warning {{bitwise or with non-zero value always evaluates to true}}
+ if (5 | x) {} // expected-warning {{bitwise or with non-zero value always evaluates to true}}
+ if (!((x | 5))) {} // expected-warning {{bitwise or with non-zero value always evaluates to true}}
+
+ if (x | -1) {} // expected-warning {{bitwise or with non-zero value always evaluates to true}}
+ if (x | ONE) {} // expected-warning {{bitwise or with non-zero value always evaluates to true}}
+
+ if (x | ZERO) {}
+}
diff --git a/clang/test/SemaCXX/warn-bitwise-compare.cpp b/clang/test/SemaCXX/warn-bitwise-compare.cpp
new file mode 100644
index 0000000000000..894d4c581e6f0
--- /dev/null
+++ b/clang/test/SemaCXX/warn-bitwise-compare.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wtautological-bitwise-compare %s
+
+void test(int x) {
+ bool b1 = (8 & x) == 3;
+ // expected-warning@-1 {{bitwise comparison always evaluates to false}}
+ bool b2 = x | 5;
+ // expected-warning@-1 {{bitwise or with non-zero value always evaluates to true}}
+ bool b3 = (x | 5);
+ // expected-warning@-1 {{bitwise or with non-zero value always evaluates to true}}
+ bool b4 = !!(x | 5);
+ // expected-warning@-1 {{bitwise or with non-zero value always evaluates to true}}
+}
diff --git a/compiler-rt/test/profile/instrprof-get-filename-merge-mode.c b/compiler-rt/test/profile/Posix/instrprof-get-filename-merge-mode.c
similarity index 86%
rename from compiler-rt/test/profile/instrprof-get-filename-merge-mode.c
rename to compiler-rt/test/profile/Posix/instrprof-get-filename-merge-mode.c
index c6e2fca22d194..7e26e3e6b5dd3 100644
--- a/compiler-rt/test/profile/instrprof-get-filename-merge-mode.c
+++ b/compiler-rt/test/profile/Posix/instrprof-get-filename-merge-mode.c
@@ -1,6 +1,6 @@
// Test __llvm_profile_get_filename when the on-line merging mode is enabled.
//
-// RUN: %clang_pgogen -dynamiclib -o %t.dso %p/Inputs/instrprof-get-filename-dso.c
+// RUN: %clang_pgogen -fPIC -shared -o %t.dso %p/../Inputs/instrprof-get-filename-dso.c
// RUN: %clang_pgogen -o %t %s %t.dso
// RUN: env LLVM_PROFILE_FILE="%t-%m.profraw" %run %t
diff --git a/libcxx/include/__config b/libcxx/include/__config
index ee7351e9313d5..044cd0ceb0073 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -242,6 +242,7 @@
#ifdef __FreeBSD__
# include
+# include
# if _BYTE_ORDER == _LITTLE_ENDIAN
# define _LIBCPP_LITTLE_ENDIAN
# else // _BYTE_ORDER == _LITTLE_ENDIAN
@@ -963,6 +964,20 @@ typedef unsigned int char32_t;
# define _LIBCPP_DEPRECATED_IN_CXX17
#endif
+// Macros to enter and leave a state where deprecation warnings are suppressed.
+#if !defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) && \
+ (defined(_LIBCPP_COMPILER_CLANG) || defined(_LIBCPP_COMPILER_GCC))
+# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated\"")
+# define _LIBCPP_SUPPRESS_DEPRECATED_POP \
+ _Pragma("GCC diagnostic pop")
+#endif
+#if !defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH)
+# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH
+# define _LIBCPP_SUPPRESS_DEPRECATED_POP
+#endif
+
#if _LIBCPP_STD_VER <= 11
# define _LIBCPP_EXPLICIT_AFTER_CXX11
#else
@@ -1164,7 +1179,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
// Some systems do not provide gets() in their C library, for security reasons.
#ifndef _LIBCPP_C_HAS_NO_GETS
-# if defined(_LIBCPP_MSVCRT) || (defined(__FreeBSD__) && __FreeBSD__ >= 13)
+# if defined(_LIBCPP_MSVCRT) || \
+ (defined(__FreeBSD_version) && __FreeBSD_version >= 1300043)
# define _LIBCPP_C_HAS_NO_GETS
# endif
#endif
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 77dcc2321d991..77b57a41e418a 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -1119,8 +1119,12 @@ template struct _LIBCPP_TEMPLATE_VIS add_rvalue_reference
template using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
#endif
+// Suppress deprecation notice for volatile-qualified return type resulting
+// from volatile-qualified types _Tp.
+_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template _Tp&& __declval(int);
template _Tp __declval(long);
+_LIBCPP_SUPPRESS_DEPRECATED_POP
template
decltype(_VSTD::__declval<_Tp>(0))
diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
index 2128590047d67..595989c4f3fa4 100644
--- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
@@ -55,6 +55,9 @@ void test_result_of_imp()
#endif
}
+// Do not warn on deprecated uses of 'volatile' below.
+_LIBCPP_SUPPRESS_DEPRECATED_PUSH
+
int main(int, char**)
{
{
@@ -171,3 +174,5 @@ int main(int, char**)
return 0;
}
+
+_LIBCPP_SUPPRESS_DEPRECATED_POP
diff --git a/libcxxabi/test/unwind_06.pass.cpp b/libcxxabi/test/unwind_06.pass.cpp
index e4c04e837451e..7d67f52f8e02d 100644
--- a/libcxxabi/test/unwind_06.pass.cpp
+++ b/libcxxabi/test/unwind_06.pass.cpp
@@ -24,7 +24,7 @@ volatile int counter;
double try1(bool v) {
double a = get(0);
double b = get(1);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b;
if (v) throw 10;
return get(0)+a+b;
@@ -34,7 +34,7 @@ double try2(bool v) {
double a = get(0);
double b = get(1);
double c = get(2);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b + c;
if (v) throw 10;
return get(0)+a+b+c;
@@ -45,7 +45,7 @@ double try3(bool v) {
double b = get(1);
double c = get(2);
double d = get(3);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b + c + d;
if (v) throw 10;
return get(0)+a+b+c+d;
@@ -57,7 +57,7 @@ double try4(bool v) {
double c = get(0);
double d = get(0);
double e = get(0);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b+c+d+e;
if (v) throw 10;
return get(0)+a+b+c+d+e;
@@ -70,7 +70,7 @@ double try5(bool v) {
double d = get(0);
double e = get(0);
double f = get(0);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b+c+d+e+f;
if (v) throw 10;
return get(0)+a+b+c+d+e+f;
@@ -84,7 +84,7 @@ double try6(bool v) {
double e = get(0);
double f = get(0);
double g = get(0);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b+c+d+e+f+g;
if (v) throw 10;
return get(0)+a+b+c+d+e+f+g;
@@ -99,7 +99,7 @@ double try7(bool v) {
double f = get(0);
double g = get(0);
double h = get(0);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b+c+d+e+f+g+h;
if (v) throw 10;
return get(0)+a+b+c+d+e+f+g+h;
@@ -115,7 +115,7 @@ double try8(bool v) {
double g = get(0);
double h = get(0);
double i = get(0);
- for (counter = 100; counter; --counter)
+ for (counter = 100; counter; counter = counter - 1)
a += get(1) + b+c+d+e+f+g+h+i;
if (v) throw 10;
return get(0)+a+b+c+d+e+f+g+h+i;
diff --git a/lld/COFF/CMakeLists.txt b/lld/COFF/CMakeLists.txt
index a30df7c4faac7..7c5e8b79b7fe8 100644
--- a/lld/COFF/CMakeLists.txt
+++ b/lld/COFF/CMakeLists.txt
@@ -38,7 +38,6 @@ add_lld_library(lldCOFF
Object
Option
Support
- Symbolize
WindowsManifest
LINK_LIBS
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index cd597ddca4fa4..309e1fbf99e3b 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -18,12 +18,6 @@
#include
#include
-namespace llvm {
-namespace symbolize {
-class LLVMSymbolizer;
-}
-} // namespace llvm
-
namespace lld {
namespace coff {
@@ -232,8 +226,6 @@ struct Configuration {
bool swaprunNet = false;
bool thinLTOEmitImportsFiles;
bool thinLTOIndexOnly;
-
- llvm::symbolize::LLVMSymbolizer *symbolizer = nullptr;
};
extern Configuration *config;
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 8770a870ddb8f..faec3ba160a56 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -795,81 +795,29 @@ void ObjFile::initializeDependencies() {
Optional>
ObjFile::getVariableLocation(StringRef var) {
if (!dwarf) {
- dwarf = DWARFContext::create(*getCOFFObj());
+ dwarf = make(DWARFContext::create(*getCOFFObj()));
if (!dwarf)
return None;
- initializeDwarf();
}
if (config->machine == I386)
var.consume_front("_");
- auto it = variableLoc.find(var);
- if (it == variableLoc.end())
+ Optional> ret = dwarf->getVariableLoc(var);
+ if (!ret)
return None;
-
- // Take file name string from line table.
- std::string fileName;
- if (!it->second.lt->getFileNameByIndex(
- it->second.file, {},
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
- return None;
-
- return std::make_pair(saver.save(fileName), it->second.line);
+ return std::make_pair(saver.save(ret->first), ret->second);
}
// Used only for DWARF debug info, which is not common (except in MinGW
-// environments). This initializes the dwarf, lineTables and variableLoc
-// members.
-void ObjFile::initializeDwarf() {
- for (std::unique_ptr &cu : dwarf->compile_units()) {
- auto report = [](Error err) {
- handleAllErrors(std::move(err),
- [](ErrorInfoBase &info) { warn(info.message()); });
- };
- Expected expectedLT =
- dwarf->getLineTableForUnit(cu.get(), report);
- const DWARFDebugLine::LineTable *lt = nullptr;
- if (expectedLT)
- lt = *expectedLT;
- else
- report(expectedLT.takeError());
- if (!lt)
- continue;
- lineTables.push_back(lt);
-
- // Loop over variable records and insert them to variableLoc.
- for (const auto &entry : cu->dies()) {
- DWARFDie die(cu.get(), &entry);
- // Skip all tags that are not variables.
- if (die.getTag() != dwarf::DW_TAG_variable)
- continue;
-
- // Skip if a local variable because we don't need them for generating
- // error messages. In general, only non-local symbols can fail to be
- // linked.
- if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
- continue;
-
- // Get the source filename index for the variable.
- unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
- if (!lt->hasFileAtIndex(file))
- continue;
-
- // Get the line number on which the variable is declared.
- unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
-
- // Here we want to take the variable name to add it into variableLoc.
- // Variable can have regular and linkage name associated. At first, we try
- // to get linkage name as it can be different, for example when we have
- // two variables in different namespaces of the same object. Use common
- // name otherwise, but handle the case when it also absent in case if the
- // input object file lacks some debug info.
- StringRef name =
- dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
- dwarf::toString(die.find(dwarf::DW_AT_name), ""));
- if (!name.empty())
- variableLoc.insert({name, {lt, file, line}});
- }
+// environments).
+Optional ObjFile::getDILineInfo(uint32_t offset,
+ uint32_t sectionIndex) {
+ if (!dwarf) {
+ dwarf = make(DWARFContext::create(*getCOFFObj()));
+ if (!dwarf)
+ return None;
}
+
+ return dwarf->getDILineInfo(offset, sectionIndex);
}
StringRef ltrim1(StringRef s, const char *chars) {
diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index d3f4cd7bb2f56..672461cd84baf 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -10,13 +10,13 @@
#define LLD_COFF_INPUT_FILES_H
#include "Config.h"
+#include "lld/Common/DWARF.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
@@ -26,6 +26,7 @@
#include
namespace llvm {
+struct DILineInfo;
namespace pdb {
class DbiModuleDescriptorBuilder;
}
@@ -206,6 +207,9 @@ class ObjFile : public InputFile {
llvm::Optional>
getVariableLocation(StringRef var);
+ llvm::Optional getDILineInfo(uint32_t offset,
+ uint32_t sectionIndex);
+
private:
const coff_section* getSection(uint32_t i);
const coff_section *getSection(COFFSymbolRef sym) {
@@ -216,7 +220,6 @@ class ObjFile : public InputFile {
void initializeSymbols();
void initializeFlags();
void initializeDependencies();
- void initializeDwarf();
SectionChunk *
readSection(uint32_t sectionNumber,
@@ -291,14 +294,7 @@ class ObjFile : public InputFile {
// symbols in the real symbol table) are filled with null pointers.
std::vector symbols;
- std::unique_ptr dwarf;
- std::vector lineTables;
- struct VarLoc {
- const llvm::DWARFDebugLine::LineTable *lt;
- unsigned file;
- unsigned line;
- };
- llvm::DenseMap variableLoc;
+ DWARFCache *dwarf = nullptr;
};
// This type represents import library members that contain DLL names
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 183761f1c1983..869dfc7a2ee5f 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -110,13 +110,11 @@ static std::vector getSymbolLocations(BitcodeFile *file) {
static Optional>
getFileLineDwarf(const SectionChunk *c, uint32_t addr) {
- if (!config->symbolizer)
- config->symbolizer = make();
- Expected expectedLineInfo = config->symbolizer->symbolizeCode(
- *c->file->getCOFFObj(), {addr, c->getSectionNumber() - 1});
- if (!expectedLineInfo)
+ Optional optionalLineInfo =
+ c->file->getDILineInfo(addr, c->getSectionNumber() - 1);
+ if (!optionalLineInfo)
return None;
- const DILineInfo &lineInfo = *expectedLineInfo;
+ const DILineInfo &lineInfo = *optionalLineInfo;
if (lineInfo.FileName == DILineInfo::BadString)
return None;
return std::make_pair(saver.save(lineInfo.FileName), lineInfo.Line);
diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt
index 70849cc7b94b2..1a04a8074bed0 100644
--- a/lld/Common/CMakeLists.txt
+++ b/lld/Common/CMakeLists.txt
@@ -29,6 +29,7 @@ set_property(SOURCE Version.cpp APPEND PROPERTY
add_lld_library(lldCommon
Args.cpp
+ DWARF.cpp
ErrorHandler.cpp
Filesystem.cpp
Memory.cpp
@@ -46,6 +47,7 @@ add_lld_library(lldCommon
LINK_COMPONENTS
Codegen
Core
+ DebugInfoDWARF
Demangle
MC
Option
diff --git a/lld/Common/DWARF.cpp b/lld/Common/DWARF.cpp
new file mode 100644
index 0000000000000..077adbcaf8581
--- /dev/null
+++ b/lld/Common/DWARF.cpp
@@ -0,0 +1,103 @@
+//===- DWARF.cpp ----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Common/DWARF.h"
+#include "lld/Common/ErrorHandler.h"
+
+using namespace llvm;
+
+namespace lld {
+
+DWARFCache::DWARFCache(std::unique_ptr d)
+ : dwarf(std::move(d)) {
+ for (std::unique_ptr &cu : dwarf->compile_units()) {
+ auto report = [](Error err) {
+ handleAllErrors(std::move(err),
+ [](ErrorInfoBase &info) { warn(info.message()); });
+ };
+ Expected expectedLT =
+ dwarf->getLineTableForUnit(cu.get(), report);
+ const DWARFDebugLine::LineTable *lt = nullptr;
+ if (expectedLT)
+ lt = *expectedLT;
+ else
+ report(expectedLT.takeError());
+ if (!lt)
+ continue;
+ lineTables.push_back(lt);
+
+ // Loop over variable records and insert them to variableLoc.
+ for (const auto &entry : cu->dies()) {
+ DWARFDie die(cu.get(), &entry);
+ // Skip all tags that are not variables.
+ if (die.getTag() != dwarf::DW_TAG_variable)
+ continue;
+
+ // Skip if a local variable because we don't need them for generating
+ // error messages. In general, only non-local symbols can fail to be
+ // linked.
+ if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
+ continue;
+
+ // Get the source filename index for the variable.
+ unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
+ if (!lt->hasFileAtIndex(file))
+ continue;
+
+ // Get the line number on which the variable is declared.
+ unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
+
+ // Here we want to take the variable name to add it into variableLoc.
+ // Variable can have regular and linkage name associated. At first, we try
+ // to get linkage name as it can be different, for example when we have
+ // two variables in different namespaces of the same object. Use common
+ // name otherwise, but handle the case when it also absent in case if the
+ // input object file lacks some debug info.
+ StringRef name =
+ dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
+ dwarf::toString(die.find(dwarf::DW_AT_name), ""));
+ if (!name.empty())
+ variableLoc.insert({name, {lt, file, line}});
+ }
+ }
+}
+
+// Returns the pair of file name and line number describing location of data
+// object (variable, array, etc) definition.
+Optional>
+DWARFCache::getVariableLoc(StringRef name) {
+ // Return if we have no debug information about data object.
+ auto it = variableLoc.find(name);
+ if (it == variableLoc.end())
+ return None;
+
+ // Take file name string from line table.
+ std::string fileName;
+ if (!it->second.lt->getFileNameByIndex(
+ it->second.file, {},
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
+ return None;
+
+ return std::make_pair(fileName, it->second.line);
+}
+
+// Returns source line information for a given offset
+// using DWARF debug info.
+Optional DWARFCache::getDILineInfo(uint64_t offset,
+ uint64_t sectionIndex) {
+ DILineInfo info;
+ for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
+ if (lt->getFileLineInfoForAddress(
+ {offset, sectionIndex}, nullptr,
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
+ return info;
+ }
+ return None;
+}
+
+} // namespace lld
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index b0389ccf100af..fdf935a30856a 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -17,7 +17,6 @@
#include "lld/Common/Memory.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/Analysis.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/LTO/LTO.h"
@@ -265,57 +264,8 @@ std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
}
template void ObjFile::initializeDwarf() {
- dwarf = std::make_unique(std::make_unique>(this));
- for (std::unique_ptr &cu : dwarf->compile_units()) {
- auto report = [](Error err) {
- handleAllErrors(std::move(err),
- [](ErrorInfoBase &info) { warn(info.message()); });
- };
- Expected expectedLT =
- dwarf->getLineTableForUnit(cu.get(), report);
- const DWARFDebugLine::LineTable *lt = nullptr;
- if (expectedLT)
- lt = *expectedLT;
- else
- report(expectedLT.takeError());
- if (!lt)
- continue;
- lineTables.push_back(lt);
-
- // Loop over variable records and insert them to variableLoc.
- for (const auto &entry : cu->dies()) {
- DWARFDie die(cu.get(), &entry);
- // Skip all tags that are not variables.
- if (die.getTag() != dwarf::DW_TAG_variable)
- continue;
-
- // Skip if a local variable because we don't need them for generating
- // error messages. In general, only non-local symbols can fail to be
- // linked.
- if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
- continue;
-
- // Get the source filename index for the variable.
- unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
- if (!lt->hasFileAtIndex(file))
- continue;
-
- // Get the line number on which the variable is declared.
- unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
-
- // Here we want to take the variable name to add it into variableLoc.
- // Variable can have regular and linkage name associated. At first, we try
- // to get linkage name as it can be different, for example when we have
- // two variables in different namespaces of the same object. Use common
- // name otherwise, but handle the case when it also absent in case if the
- // input object file lacks some debug info.
- StringRef name =
- dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
- dwarf::toString(die.find(dwarf::DW_AT_name), ""));
- if (!name.empty())
- variableLoc.insert({name, {lt, file, line}});
- }
- }
+ dwarf = make(std::make_unique(
+ std::make_unique>(this)));
}
// Returns the pair of file name and line number describing location of data
@@ -325,19 +275,7 @@ Optional>
ObjFile::getVariableLoc(StringRef name) {
llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });
- // Return if we have no debug information about data object.
- auto it = variableLoc.find(name);
- if (it == variableLoc.end())
- return None;
-
- // Take file name string from line table.
- std::string fileName;
- if (!it->second.lt->getFileNameByIndex(
- it->second.file, {},
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
- return None;
-
- return std::make_pair(fileName, it->second.line);
+ return dwarf->getVariableLoc(name);
}
// Returns source line information for a given offset
@@ -359,14 +297,7 @@ Optional ObjFile::getDILineInfo(InputSectionBase *s,
// Use fake address calcuated by adding section file offset and offset in
// section. See comments for ObjectInfo class.
- DILineInfo info;
- for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
- if (lt->getFileLineInfoForAddress(
- {s->getOffsetInFile() + offset, sectionIndex}, nullptr,
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
- return info;
- }
- return None;
+ return dwarf->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex);
}
ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) {
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 1c78654d00fc6..cde6bc617764d 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -10,13 +10,13 @@
#define LLD_ELF_INPUT_FILES_H
#include "Config.h"
+#include "lld/Common/DWARF.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/LLVM.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/IR/Comdat.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
@@ -26,7 +26,6 @@
namespace llvm {
class TarWriter;
-struct DILineInfo;
namespace lto {
class InputFile;
}
@@ -282,14 +281,7 @@ template class ObjFile : public ELFFileBase {
// reporting. Linker may find reasonable number of errors in a
// single object file, so we cache debugging information in order to
// parse it only once for each object file we link.
- std::unique_ptr dwarf;
- std::vector lineTables;
- struct VarLoc {
- const llvm::DWARFDebugLine::LineTable *lt;
- unsigned file;
- unsigned line;
- };
- llvm::DenseMap variableLoc;
+ DWARFCache *dwarf;
llvm::once_flag initDwarfLine;
};
diff --git a/lld/include/lld/Common/DWARF.h b/lld/include/lld/Common/DWARF.h
new file mode 100644
index 0000000000000..f0d3d2fbda775
--- /dev/null
+++ b/lld/include/lld/Common/DWARF.h
@@ -0,0 +1,47 @@
+//===- DWARF.h --------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DWARF_H
+#define LLD_DWARF_H
+
+#include "lld/Common/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include
+#include
+
+namespace llvm {
+struct DILineInfo;
+} // namespace llvm
+
+namespace lld {
+
+class DWARFCache {
+public:
+ DWARFCache(std::unique_ptr dwarf);
+ llvm::Optional getDILineInfo(uint64_t offset,
+ uint64_t sectionIndex);
+ llvm::Optional>
+ getVariableLoc(StringRef name);
+
+private:
+ std::unique_ptr dwarf;
+ std::vector lineTables;
+ struct VarLoc {
+ const llvm::DWARFDebugLine::LineTable *lt;
+ unsigned file;
+ unsigned line;
+ };
+ llvm::DenseMap variableLoc;
+};
+
+} // namespace lld
+
+#endif
diff --git a/lld/include/lld/Common/LLVM.h b/lld/include/lld/Common/LLVM.h
index f7ed1d793ca7b..34b7b0d194ab4 100644
--- a/lld/include/lld/Common/LLVM.h
+++ b/lld/include/lld/Common/LLVM.h
@@ -17,6 +17,7 @@
// This should be the only #include, force #includes of all the others on
// clients.
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h
index 492f35989f166..df014669eb628 100644
--- a/lld/include/lld/Core/File.h
+++ b/lld/include/lld/Core/File.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorHandling.h"
#include
#include
diff --git a/lld/lib/ReaderWriter/MachO/DebugInfo.h b/lld/lib/ReaderWriter/MachO/DebugInfo.h
index 959e10f9a0735..591dd1ebad86c 100644
--- a/lld/lib/ReaderWriter/MachO/DebugInfo.h
+++ b/lld/lib/ReaderWriter/MachO/DebugInfo.h
@@ -12,6 +12,7 @@
#include "lld/Core/Atom.h"
#include
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/lld/test/ELF/invalid/bad-reloc-target.test b/lld/test/ELF/invalid/bad-reloc-target.test
index 05aa2e5d6fae7..9ab5d9c22580f 100644
--- a/lld/test/ELF/invalid/bad-reloc-target.test
+++ b/lld/test/ELF/invalid/bad-reloc-target.test
@@ -68,7 +68,6 @@ Sections:
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .rela.text
Type: SHT_RELA
- Link: .symtab
Info: .text
Relocations:
- Offset: 0x0000000000000000
diff --git a/lld/test/ELF/invalid/sht-group.test b/lld/test/ELF/invalid/sht-group.test
index c91e649e26434..ac155fa08ba6c 100644
--- a/lld/test/ELF/invalid/sht-group.test
+++ b/lld/test/ELF/invalid/sht-group.test
@@ -12,7 +12,6 @@ FileHeader:
Sections:
- Name: .group
Type: SHT_GROUP
- Link: .symtab
Info: 12345
Members:
- SectionOrType: GRP_COMDAT
diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp
index 37ef260495e9b..14dcc95899e99 100644
--- a/lld/tools/lld/lld.cpp
+++ b/lld/tools/lld/lld.cpp
@@ -33,6 +33,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include
diff --git a/lldb/include/lldb/Utility/UUID.h b/lldb/include/lldb/Utility/UUID.h
index cb2e051a4569c..0284357be44a2 100644
--- a/lldb/include/lldb/Utility/UUID.h
+++ b/lldb/include/lldb/Utility/UUID.h
@@ -9,14 +9,11 @@
#ifndef LLDB_UTILITY_UUID_H
#define LLDB_UTILITY_UUID_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include
#include
#include
-#include "llvm/ADT/ArrayRef.h"
-
-namespace llvm {
- class StringRef;
-}
namespace lldb_private {
diff --git a/lldb/packages/Python/lldbsuite/test/commands/command/script/TestCommandScript.py b/lldb/packages/Python/lldbsuite/test/commands/command/script/TestCommandScript.py
index 6531cd672792e..9542d0264a6bd 100644
--- a/lldb/packages/Python/lldbsuite/test/commands/command/script/TestCommandScript.py
+++ b/lldb/packages/Python/lldbsuite/test/commands/command/script/TestCommandScript.py
@@ -4,7 +4,7 @@
from __future__ import print_function
-
+import sys
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -22,6 +22,21 @@ def test(self):
def pycmd_tests(self):
self.runCmd("command source py_import")
+ # Test a bunch of different kinds of python callables with
+ # both 4 and 5 positional arguments.
+ self.expect("foobar", substrs=["All good"])
+ self.expect("foobar4", substrs=["All good"])
+ self.expect("vfoobar", substrs=["All good"])
+ self.expect("v5foobar", substrs=["All good"])
+ self.expect("sfoobar", substrs=["All good"])
+ self.expect("cfoobar", substrs=["All good"])
+ self.expect("ifoobar", substrs=["All good"])
+ self.expect("sfoobar4", substrs=["All good"])
+ self.expect("cfoobar4", substrs=["All good"])
+ self.expect("ifoobar4", substrs=["All good"])
+ self.expect("ofoobar", substrs=["All good"])
+ self.expect("ofoobar4", substrs=["All good"])
+
# Verify command that specifies eCommandRequiresTarget returns failure
# without a target.
self.expect('targetname',
diff --git a/lldb/packages/Python/lldbsuite/test/commands/command/script/callables.py b/lldb/packages/Python/lldbsuite/test/commands/command/script/callables.py
new file mode 100644
index 0000000000000..21e599b82e5be
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/commands/command/script/callables.py
@@ -0,0 +1,63 @@
+
+from __future__ import print_function
+
+import lldb
+
+# bunch of different kinds of python callables that should
+# all work as commands.
+
+def check(debugger, command, context, result, internal_dict):
+ if (not isinstance(debugger, lldb.SBDebugger) or
+ not isinstance(command, str) or
+ not isinstance(result, lldb.SBCommandReturnObject) or
+ not isinstance(internal_dict, dict) or
+ (not context is None and
+ not isinstance(context, lldb.SBExecutionContext))):
+ raise Exception()
+ result.AppendMessage("All good.")
+
+def vfoobar(*args):
+ check(*args)
+
+def v5foobar(debugger, command, context, result, internal_dict, *args):
+ check(debugger, command, context, result, internal_dict)
+
+def foobar(debugger, command, context, result, internal_dict):
+ check(debugger, command, context, result, internal_dict)
+
+def foobar4(debugger, command, result, internal_dict):
+ check(debugger, command, None, result, internal_dict)
+
+class FooBar:
+ @staticmethod
+ def sfoobar(debugger, command, context, result, internal_dict):
+ check(debugger, command, context, result, internal_dict)
+
+ @classmethod
+ def cfoobar(cls, debugger, command, context, result, internal_dict):
+ check(debugger, command, context, result, internal_dict)
+
+ def ifoobar(self, debugger, command, context, result, internal_dict):
+ check(debugger, command, context, result, internal_dict)
+
+ def __call__(self, debugger, command, context, result, internal_dict):
+ check(debugger, command, context, result, internal_dict)
+
+ @staticmethod
+ def sfoobar4(debugger, command, result, internal_dict):
+ check(debugger, command, None, result, internal_dict)
+
+ @classmethod
+ def cfoobar4(cls, debugger, command, result, internal_dict):
+ check(debugger, command, None, result, internal_dict)
+
+ def ifoobar4(self, debugger, command, result, internal_dict):
+ check(debugger, command, None, result, internal_dict)
+
+class FooBar4:
+ def __call__(self, debugger, command, result, internal_dict):
+ check(debugger, command, None, result, internal_dict)
+
+FooBarObj = FooBar()
+
+FooBar4Obj = FooBar4()
\ No newline at end of file
diff --git a/lldb/packages/Python/lldbsuite/test/commands/command/script/py_import b/lldb/packages/Python/lldbsuite/test/commands/command/script/py_import
index 6c1f7b8185f6d..4372d32b0ad11 100644
--- a/lldb/packages/Python/lldbsuite/test/commands/command/script/py_import
+++ b/lldb/packages/Python/lldbsuite/test/commands/command/script/py_import
@@ -11,3 +11,22 @@ command script add tell_async --function welcome.check_for_synchro --synchronici
command script add tell_curr --function welcome.check_for_synchro --synchronicity curr
command script add takes_exe_ctx --function welcome.takes_exe_ctx
command script import decorated.py
+
+
+command script import callables.py
+
+command script add -f callables.foobar foobar
+command script add -f callables.foobar4 foobar4
+command script add -f callables.vfoobar vfoobar
+command script add -f callables.v5foobar v5foobar
+
+command script add -f callables.FooBar.sfoobar sfoobar
+command script add -f callables.FooBar.cfoobar cfoobar
+command script add -f callables.FooBarObj.ifoobar ifoobar
+
+command script add -f callables.FooBar.sfoobar4 sfoobar4
+command script add -f callables.FooBar.cfoobar4 cfoobar4
+command script add -f callables.FooBarObj.ifoobar4 ifoobar4
+
+command script add -f callables.FooBarObj ofoobar
+command script add -f callables.FooBar4Obj ofoobar4
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py
index b13d6555f33bf..011dabce6e9dd 100644
--- a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py
+++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py
@@ -74,6 +74,21 @@ def cleanup():
# EXPR-TYPES-NEW-FOO-NEXT: }
# EXPR-TYPES-NEW-FOO-NEXT: }
+
+ self.runCmd("type summary add -F formatters.foo_SummaryProvider3 foo")
+ self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1opts')
+ # EXPR-FOO1opts: (foo) $
+ # EXPR-FOO1opts-SAME: a = 12
+ # EXPR-FOO1opts-SAME: a_ptr = {{[0-9]+}} -> 13
+ # EXPR-FOO1opts-SAME: i = 24
+ # EXPR-FOO1opts-SAME: i_ptr = {{[0-9]+}} -> 25
+ # EXPR-FOO1opts-SAME: b_ref = {{[0-9]+}}
+ # EXPR-FOO1opts-SAME: h = 27
+ # EXPR-FOO1opts-SAME: k = 29
+ # EXPR-FOO1opts-SAME: WITH_OPTS
+
+ self.runCmd("type summary delete foo")
+
self.runCmd("type summary add -F formatters.foo_SummaryProvider foo")
self.expect("expression new int(12)",
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py
index dae84988af9e2..ac2888bd203f7 100644
--- a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py
+++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py
@@ -1,3 +1,5 @@
+import lldb
+
def foo_SummaryProvider(valobj, dict):
a = valobj.GetChildMemberWithName('a')
a_ptr = valobj.GetChildMemberWithName('a_ptr')
@@ -15,3 +17,8 @@ def foo_SummaryProvider(valobj, dict):
', i_ptr = ' + str(i_ptr.GetValueAsUnsigned(0)) + ' -> ' + str(i_ptr.Dereference().GetValueAsUnsigned(0)) + \
', b_ref = ' + str(b_ref.GetValueAsUnsigned(0)) + \
', h = ' + str(h.GetValueAsUnsigned(0)) + ' , k = ' + str(k.GetValueAsUnsigned(0))
+
+def foo_SummaryProvider3(valobj, dict, options):
+ if not isinstance(options, lldb.SBTypeSummaryOptions):
+ raise Exception()
+ return foo_SummaryProvider(valobj, dict) + ", WITH_OPTS"
\ No newline at end of file
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/TestStaticInitializers.py b/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/TestStaticInitializers.py
new file mode 100644
index 0000000000000..e350e6ef930f9
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/TestStaticInitializers.py
@@ -0,0 +1,31 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class StaticInitializers(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test(self):
+ """ Test a static initializer. """
+ self.build()
+
+ lldbutil.run_to_source_breakpoint(self, '// break here',
+ lldb.SBFileSpec("main.cpp", False))
+
+ # We use counter to observe if the initializer was called.
+ self.expect("expr counter", substrs=["(int) $", " = 0"])
+ self.expect("expr -p -- struct Foo { Foo() { inc_counter(); } }; Foo f;")
+ self.expect("expr counter", substrs=["(int) $", " = 1"])
+
+ def test_failing_init(self):
+ """ Test a static initializer that fails to execute. """
+ self.build()
+
+ lldbutil.run_to_source_breakpoint(self, '// break here',
+ lldb.SBFileSpec("main.cpp", False))
+
+ # FIXME: This error message is not even remotely helpful.
+ self.expect("expr -p -- struct Foo2 { Foo2() { do_abort(); } }; Foo2 f;", error=True,
+ substrs=["error: couldn't run static initializers: couldn't run static initializer:"])
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/main.cpp
new file mode 100644
index 0000000000000..0bcf1eb3edafb
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/commands/expression/static-initializers/main.cpp
@@ -0,0 +1,11 @@
+#include
+
+int counter = 0;
+
+void inc_counter() { ++counter; }
+
+void do_abort() { abort(); }
+
+int main() {
+ return 0; // break here
+}
diff --git a/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py b/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py
index d202887902e90..b485851463743 100644
--- a/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py
+++ b/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py
@@ -13,6 +13,9 @@ class IOHandlerCompletionTest(PExpectTest):
mydir = TestBase.compute_mydir(__file__)
+ # PExpect uses many timeouts internally and doesn't play well
+ # under ASAN on a loaded machine..
+ @skipIfAsan
def test_completion(self):
self.launch(dimensions=(100,500))
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py
index 5a3ae926896a9..70cc25520608b 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py
@@ -53,7 +53,7 @@ def attach_commandline_qProcessInfo_reports_correct_pid(self):
self.add_process_info_collection_packets()
# Run the stream
- context = self.expect_gdbremote_sequence(timeout_seconds=8)
+ context = self.expect_gdbremote_sequence(timeout_seconds=self._DEFAULT_TIMEOUT)
self.assertIsNotNone(context)
# Gather process info response
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
index 1d3a63d27b76d..0944ba5d0510a 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
@@ -52,7 +52,7 @@ def gather_stop_replies_via_qThreadStopInfo(self, thread_count):
self.assertIsNotNone(context)
# Wait until all threads have started.
- threads = self.wait_for_thread_count(thread_count, timeout_seconds=3)
+ threads = self.wait_for_thread_count(thread_count, timeout_seconds=self._WAIT_TIMEOUT)
self.assertIsNotNone(threads)
# On Windows, there could be more threads spawned. For example, DebugBreakProcess will
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
index a3abe203a9874..1b30718f74815 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
@@ -639,7 +639,7 @@ def Hg_switches_to_3_threads(self):
self.run_process_then_stop(run_seconds=1)
# Wait at most x seconds for 3 threads to be present.
- threads = self.wait_for_thread_count(3, timeout_seconds=5)
+ threads = self.wait_for_thread_count(3, timeout_seconds=self._WAIT_TIMEOUT)
self.assertEqual(len(threads), 3)
# verify we can $H to each thead, and $qC matches the thread we set.
@@ -735,7 +735,7 @@ def Hc_then_Csignal_signals_correct_thread(self, segfault_signo):
2: "thread_id"}}],
True)
- context = self.expect_gdbremote_sequence(timeout_seconds=10)
+ context = self.expect_gdbremote_sequence(timeout_seconds=self._DEFAULT_TIMEOUT)
self.assertIsNotNone(context)
signo = context.get("signo")
self.assertEqual(int(signo, 16), segfault_signo)
@@ -771,7 +771,8 @@ def Hc_then_Csignal_signals_correct_thread(self, segfault_signo):
True)
# Run the sequence.
- context = self.expect_gdbremote_sequence(timeout_seconds=10)
+ context = self.expect_gdbremote_sequence(
+ timeout_seconds=self._DEFAULT_TIMEOUT)
self.assertIsNotNone(context)
# Ensure the stop signal is the signal we delivered.
@@ -1485,7 +1486,7 @@ def P_and_p_thread_suffix_work(self):
self.assertIsNotNone(context)
# Wait for 3 threads to be present.
- threads = self.wait_for_thread_count(3, timeout_seconds=5)
+ threads = self.wait_for_thread_count(3, timeout_seconds=self._WAIT_TIMEOUT)
self.assertEqual(len(threads), 3)
expected_reg_values = []
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py
index 18efbf9d650f9..664b6001d8dae 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py
@@ -14,7 +14,7 @@ class TestStubReverseConnect(gdbremote_testcase.GdbRemoteTestCaseBase):
mydir = TestBase.compute_mydir(__file__)
- _DEFAULT_TIMEOUT = 20
+ _DEFAULT_TIMEOUT = 20 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
def setUp(self):
# Set up the test.
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
index 670d770f88194..ac611bcca1695 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
@@ -32,8 +32,9 @@ class GdbRemoteTestCaseBase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
_TIMEOUT_SECONDS = 120 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
+ _DEFAULT_TIMEOUT = 10 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
_READ_TIMEOUT = 5 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
- _WAIT_TIMEOUT = 3 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
+ _WAIT_TIMEOUT = 5 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
_GDBREMOTE_KILL_PACKET = "$k#6b"
diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig
index 7d507b31c5cd8..277b8657d3441 100644
--- a/lldb/scripts/Python/python-wrapper.swig
+++ b/lldb/scripts/Python/python-wrapper.swig
@@ -163,14 +163,19 @@ LLDBSwigPythonCallTypeScript
}
PythonObject result;
- auto argc = pfunc.GetNumArguments();
- // if the third argument is supported, or varargs are allowed
+ auto argc = pfunc.GetArgInfo();
+ if (!argc) {
+ llvm::consumeError(argc.takeError());
+ return false;
+ }
+
PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value));
PythonObject options_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_options));
- if (argc.count == 3 || argc.has_varargs)
- result = pfunc(value_arg,dict,options_arg);
- else
+
+ if (argc.get().max_positional_args < 3)
result = pfunc(value_arg,dict);
+ else
+ result = pfunc(value_arg,dict,options_arg);
retval = result.Str().GetString().str();
@@ -696,15 +701,19 @@ LLDBSwigPythonCallCommand
// pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
// see comment above for SBCommandReturnObjectReleaser for further details
- auto argc = pfunc.GetNumArguments();
+ auto argc = pfunc.GetArgInfo();
+ if (!argc) {
+ llvm::consumeError(argc.takeError());
+ return false;
+ }
PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb));
- if (argc.count == 5 || argc.is_bound_method || argc.has_varargs)
- pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict);
- else
+ if (argc.get().max_positional_args < 5u)
pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict);
+ else
+ pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict);
return true;
}
diff --git a/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt b/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
index d0d3fcbee6f4d..876bc8cab966a 100644
--- a/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
@@ -4,6 +4,7 @@ add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN
LocalDebugDelegate.cpp
NativeProcessWindows.cpp
NativeRegisterContextWindows.cpp
+ NativeRegisterContextWindows_arm.cpp
NativeRegisterContextWindows_arm64.cpp
NativeRegisterContextWindows_i386.cpp
NativeRegisterContextWindows_WoW64.cpp
@@ -14,10 +15,10 @@ add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN
ProcessWindowsLog.cpp
RegisterContextWindows.cpp
TargetThreadWindows.cpp
+ arm/RegisterContextWindows_arm.cpp
arm64/RegisterContextWindows_arm64.cpp
x64/RegisterContextWindows_x64.cpp
x86/RegisterContextWindows_x86.cpp
- # TODO add support for ARM (NT)
LINK_LIBS
lldbCore
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
new file mode 100644
index 0000000000000..d25b08f7ecbac
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
@@ -0,0 +1,644 @@
+//===-- NativeRegisterContextWindows_arm.cpp --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__) || defined(_M_ARM)
+
+#include "NativeRegisterContextWindows_arm.h"
+#include "NativeThreadWindows.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+#include "ProcessWindowsLog.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
+
+namespace {
+static const uint32_t g_gpr_regnums_arm[] = {
+ gpr_r0_arm, gpr_r1_arm, gpr_r2_arm, gpr_r3_arm, gpr_r4_arm,
+ gpr_r5_arm, gpr_r6_arm, gpr_r7_arm, gpr_r8_arm, gpr_r9_arm,
+ gpr_r10_arm, gpr_r11_arm, gpr_r12_arm, gpr_sp_arm, gpr_lr_arm,
+ gpr_pc_arm, gpr_cpsr_arm,
+ LLDB_INVALID_REGNUM // Register set must be terminated with this flag
+};
+static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) ==
+ k_num_gpr_registers_arm,
+ "g_gpr_regnums_arm has wrong number of register infos");
+
+static const uint32_t g_fpr_regnums_arm[] = {
+ fpu_s0_arm, fpu_s1_arm, fpu_s2_arm, fpu_s3_arm, fpu_s4_arm,
+ fpu_s5_arm, fpu_s6_arm, fpu_s7_arm, fpu_s8_arm, fpu_s9_arm,
+ fpu_s10_arm, fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm,
+ fpu_s15_arm, fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm,
+ fpu_s20_arm, fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm,
+ fpu_s25_arm, fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm,
+ fpu_s30_arm, fpu_s31_arm,
+
+ fpu_d0_arm, fpu_d1_arm, fpu_d2_arm, fpu_d3_arm, fpu_d4_arm,
+ fpu_d5_arm, fpu_d6_arm, fpu_d7_arm, fpu_d8_arm, fpu_d9_arm,
+ fpu_d10_arm, fpu_d11_arm, fpu_d12_arm, fpu_d13_arm, fpu_d14_arm,
+ fpu_d15_arm, fpu_d16_arm, fpu_d17_arm, fpu_d18_arm, fpu_d19_arm,
+ fpu_d20_arm, fpu_d21_arm, fpu_d22_arm, fpu_d23_arm, fpu_d24_arm,
+ fpu_d25_arm, fpu_d26_arm, fpu_d27_arm, fpu_d28_arm, fpu_d29_arm,
+ fpu_d30_arm, fpu_d31_arm,
+
+ fpu_q0_arm, fpu_q1_arm, fpu_q2_arm, fpu_q3_arm, fpu_q4_arm,
+ fpu_q5_arm, fpu_q6_arm, fpu_q7_arm, fpu_q8_arm, fpu_q9_arm,
+ fpu_q10_arm, fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm,
+ fpu_q15_arm,
+
+ fpu_fpscr_arm,
+ LLDB_INVALID_REGNUM // Register set must be terminated with this flag
+};
+static_assert(((sizeof g_fpr_regnums_arm / sizeof g_fpr_regnums_arm[0]) - 1) ==
+ k_num_fpr_registers_arm,
+ "g_fpu_regnums_arm has wrong number of register infos");
+
+static const RegisterSet g_reg_sets_arm[] = {
+ {"General Purpose Registers", "gpr",
+ llvm::array_lengthof(g_gpr_regnums_arm) - 1, g_gpr_regnums_arm},
+ {"Floating Point Registers", "fpr",
+ llvm::array_lengthof(g_fpr_regnums_arm) - 1, g_fpr_regnums_arm},
+};
+
+enum { k_num_register_sets = 2 };
+
+} // namespace
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ return new RegisterInfoPOSIX_arm(target_arch);
+}
+
+static Status GetThreadContextHelper(lldb::thread_t thread_handle,
+ PCONTEXT context_ptr,
+ const DWORD control_flag) {
+ Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+ Status error;
+
+ memset(context_ptr, 0, sizeof(::CONTEXT));
+ context_ptr->ContextFlags = control_flag;
+ if (!::GetThreadContext(thread_handle, context_ptr)) {
+ error.SetError(GetLastError(), eErrorTypeWin32);
+ LLDB_LOG(log, "{0} GetThreadContext failed with error {1}", __FUNCTION__,
+ error);
+ return error;
+ }
+ return Status();
+}
+
+static Status SetThreadContextHelper(lldb::thread_t thread_handle,
+ PCONTEXT context_ptr) {
+ Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+ Status error;
+ // It's assumed that the thread has stopped.
+ if (!::SetThreadContext(thread_handle, context_ptr)) {
+ error.SetError(GetLastError(), eErrorTypeWin32);
+ LLDB_LOG(log, "{0} SetThreadContext failed with error {1}", __FUNCTION__,
+ error);
+ return error;
+ }
+ return Status();
+}
+
+std::unique_ptr
+NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ // TODO: Register context for a WoW64 application?
+
+ // Register context for a native 64-bit application.
+ return std::make_unique(target_arch,
+ native_thread);
+}
+
+NativeRegisterContextWindows_arm::NativeRegisterContextWindows_arm(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextWindows(native_thread,
+ CreateRegisterInfoInterface(target_arch)) {}
+
+bool NativeRegisterContextWindows_arm::IsGPR(uint32_t reg_index) const {
+ return (reg_index >= k_first_gpr_arm && reg_index <= k_last_gpr_arm);
+}
+
+bool NativeRegisterContextWindows_arm::IsFPR(uint32_t reg_index) const {
+ return (reg_index >= k_first_fpr_arm && reg_index <= k_last_fpr_arm);
+}
+
+uint32_t NativeRegisterContextWindows_arm::GetRegisterSetCount() const {
+ return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextWindows_arm::GetRegisterSet(uint32_t set_index) const {
+ if (set_index >= k_num_register_sets)
+ return nullptr;
+ return &g_reg_sets_arm[set_index];
+}
+
+Status NativeRegisterContextWindows_arm::GPRRead(const uint32_t reg,
+ RegisterValue ®_value) {
+ ::CONTEXT tls_context;
+ DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER;
+ Status error =
+ GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
+ if (error.Fail())
+ return error;
+
+ switch (reg) {
+ case gpr_r0_arm:
+ reg_value.SetUInt32(tls_context.R0);
+ break;
+ case gpr_r1_arm:
+ reg_value.SetUInt32(tls_context.R1);
+ break;
+ case gpr_r2_arm:
+ reg_value.SetUInt32(tls_context.R2);
+ break;
+ case gpr_r3_arm:
+ reg_value.SetUInt32(tls_context.R3);
+ break;
+ case gpr_r4_arm:
+ reg_value.SetUInt32(tls_context.R4);
+ break;
+ case gpr_r5_arm:
+ reg_value.SetUInt32(tls_context.R5);
+ break;
+ case gpr_r6_arm:
+ reg_value.SetUInt32(tls_context.R6);
+ break;
+ case gpr_r7_arm:
+ reg_value.SetUInt32(tls_context.R7);
+ break;
+ case gpr_r8_arm:
+ reg_value.SetUInt32(tls_context.R8);
+ break;
+ case gpr_r9_arm:
+ reg_value.SetUInt32(tls_context.R9);
+ break;
+ case gpr_r10_arm:
+ reg_value.SetUInt32(tls_context.R10);
+ break;
+ case gpr_r11_arm:
+ reg_value.SetUInt32(tls_context.R11);
+ break;
+ case gpr_r12_arm:
+ reg_value.SetUInt32(tls_context.R12);
+ break;
+ case gpr_sp_arm:
+ reg_value.SetUInt32(tls_context.Sp);
+ break;
+ case gpr_lr_arm:
+ reg_value.SetUInt32(tls_context.Lr);
+ break;
+ case gpr_pc_arm:
+ reg_value.SetUInt32(tls_context.Pc);
+ break;
+ case gpr_cpsr_arm:
+ reg_value.SetUInt32(tls_context.Cpsr);
+ break;
+ }
+
+ return error;
+}
+
+Status
+NativeRegisterContextWindows_arm::GPRWrite(const uint32_t reg,
+ const RegisterValue ®_value) {
+ ::CONTEXT tls_context;
+ DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER;
+ auto thread_handle = GetThreadHandle();
+ Status error =
+ GetThreadContextHelper(thread_handle, &tls_context, context_flag);
+ if (error.Fail())
+ return error;
+
+ switch (reg) {
+ case gpr_r0_arm:
+ tls_context.R0 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r1_arm:
+ tls_context.R1 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r2_arm:
+ tls_context.R2 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r3_arm:
+ tls_context.R3 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r4_arm:
+ tls_context.R4 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r5_arm:
+ tls_context.R5 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r6_arm:
+ tls_context.R6 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r7_arm:
+ tls_context.R7 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r8_arm:
+ tls_context.R8 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r9_arm:
+ tls_context.R9 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r10_arm:
+ tls_context.R10 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r11_arm:
+ tls_context.R11 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r12_arm:
+ tls_context.R12 = reg_value.GetAsUInt32();
+ break;
+ case gpr_sp_arm:
+ tls_context.Sp = reg_value.GetAsUInt32();
+ break;
+ case gpr_lr_arm:
+ tls_context.Lr = reg_value.GetAsUInt32();
+ break;
+ case gpr_pc_arm:
+ tls_context.Pc = reg_value.GetAsUInt32();
+ break;
+ case gpr_cpsr_arm:
+ tls_context.Cpsr = reg_value.GetAsUInt32();
+ break;
+ }
+
+ return SetThreadContextHelper(thread_handle, &tls_context);
+}
+
+Status NativeRegisterContextWindows_arm::FPRRead(const uint32_t reg,
+ RegisterValue ®_value) {
+ ::CONTEXT tls_context;
+ DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
+ Status error =
+ GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
+ if (error.Fail())
+ return error;
+
+ switch (reg) {
+ case fpu_s0_arm:
+ case fpu_s1_arm:
+ case fpu_s2_arm:
+ case fpu_s3_arm:
+ case fpu_s4_arm:
+ case fpu_s5_arm:
+ case fpu_s6_arm:
+ case fpu_s7_arm:
+ case fpu_s8_arm:
+ case fpu_s9_arm:
+ case fpu_s10_arm:
+ case fpu_s11_arm:
+ case fpu_s12_arm:
+ case fpu_s13_arm:
+ case fpu_s14_arm:
+ case fpu_s15_arm:
+ case fpu_s16_arm:
+ case fpu_s17_arm:
+ case fpu_s18_arm:
+ case fpu_s19_arm:
+ case fpu_s20_arm:
+ case fpu_s21_arm:
+ case fpu_s22_arm:
+ case fpu_s23_arm:
+ case fpu_s24_arm:
+ case fpu_s25_arm:
+ case fpu_s26_arm:
+ case fpu_s27_arm:
+ case fpu_s28_arm:
+ case fpu_s29_arm:
+ case fpu_s30_arm:
+ case fpu_s31_arm:
+ reg_value.SetUInt32(tls_context.S[reg - fpu_s0_arm],
+ RegisterValue::eTypeFloat);
+ break;
+
+ case fpu_d0_arm:
+ case fpu_d1_arm:
+ case fpu_d2_arm:
+ case fpu_d3_arm:
+ case fpu_d4_arm:
+ case fpu_d5_arm:
+ case fpu_d6_arm:
+ case fpu_d7_arm:
+ case fpu_d8_arm:
+ case fpu_d9_arm:
+ case fpu_d10_arm:
+ case fpu_d11_arm:
+ case fpu_d12_arm:
+ case fpu_d13_arm:
+ case fpu_d14_arm:
+ case fpu_d15_arm:
+ case fpu_d16_arm:
+ case fpu_d17_arm:
+ case fpu_d18_arm:
+ case fpu_d19_arm:
+ case fpu_d20_arm:
+ case fpu_d21_arm:
+ case fpu_d22_arm:
+ case fpu_d23_arm:
+ case fpu_d24_arm:
+ case fpu_d25_arm:
+ case fpu_d26_arm:
+ case fpu_d27_arm:
+ case fpu_d28_arm:
+ case fpu_d29_arm:
+ case fpu_d30_arm:
+ case fpu_d31_arm:
+ reg_value.SetUInt64(tls_context.D[reg - fpu_d0_arm],
+ RegisterValue::eTypeDouble);
+ break;
+
+ case fpu_q0_arm:
+ case fpu_q1_arm:
+ case fpu_q2_arm:
+ case fpu_q3_arm:
+ case fpu_q4_arm:
+ case fpu_q5_arm:
+ case fpu_q6_arm:
+ case fpu_q7_arm:
+ case fpu_q8_arm:
+ case fpu_q9_arm:
+ case fpu_q10_arm:
+ case fpu_q11_arm:
+ case fpu_q12_arm:
+ case fpu_q13_arm:
+ case fpu_q14_arm:
+ case fpu_q15_arm:
+ reg_value.SetBytes(&tls_context.Q[reg - fpu_q0_arm], 16,
+ endian::InlHostByteOrder());
+ break;
+
+ case fpu_fpscr_arm:
+ reg_value.SetUInt32(tls_context.Fpscr);
+ break;
+ }
+
+ return error;
+}
+
+Status
+NativeRegisterContextWindows_arm::FPRWrite(const uint32_t reg,
+ const RegisterValue ®_value) {
+ ::CONTEXT tls_context;
+ DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
+ auto thread_handle = GetThreadHandle();
+ Status error =
+ GetThreadContextHelper(thread_handle, &tls_context, context_flag);
+ if (error.Fail())
+ return error;
+
+ switch (reg) {
+ case fpu_s0_arm:
+ case fpu_s1_arm:
+ case fpu_s2_arm:
+ case fpu_s3_arm:
+ case fpu_s4_arm:
+ case fpu_s5_arm:
+ case fpu_s6_arm:
+ case fpu_s7_arm:
+ case fpu_s8_arm:
+ case fpu_s9_arm:
+ case fpu_s10_arm:
+ case fpu_s11_arm:
+ case fpu_s12_arm:
+ case fpu_s13_arm:
+ case fpu_s14_arm:
+ case fpu_s15_arm:
+ case fpu_s16_arm:
+ case fpu_s17_arm:
+ case fpu_s18_arm:
+ case fpu_s19_arm:
+ case fpu_s20_arm:
+ case fpu_s21_arm:
+ case fpu_s22_arm:
+ case fpu_s23_arm:
+ case fpu_s24_arm:
+ case fpu_s25_arm:
+ case fpu_s26_arm:
+ case fpu_s27_arm:
+ case fpu_s28_arm:
+ case fpu_s29_arm:
+ case fpu_s30_arm:
+ case fpu_s31_arm:
+ tls_context.S[reg - fpu_s0_arm] = reg_value.GetAsUInt32();
+ break;
+
+ case fpu_d0_arm:
+ case fpu_d1_arm:
+ case fpu_d2_arm:
+ case fpu_d3_arm:
+ case fpu_d4_arm:
+ case fpu_d5_arm:
+ case fpu_d6_arm:
+ case fpu_d7_arm:
+ case fpu_d8_arm:
+ case fpu_d9_arm:
+ case fpu_d10_arm:
+ case fpu_d11_arm:
+ case fpu_d12_arm:
+ case fpu_d13_arm:
+ case fpu_d14_arm:
+ case fpu_d15_arm:
+ case fpu_d16_arm:
+ case fpu_d17_arm:
+ case fpu_d18_arm:
+ case fpu_d19_arm:
+ case fpu_d20_arm:
+ case fpu_d21_arm:
+ case fpu_d22_arm:
+ case fpu_d23_arm:
+ case fpu_d24_arm:
+ case fpu_d25_arm:
+ case fpu_d26_arm:
+ case fpu_d27_arm:
+ case fpu_d28_arm:
+ case fpu_d29_arm:
+ case fpu_d30_arm:
+ case fpu_d31_arm:
+ tls_context.D[reg - fpu_d0_arm] = reg_value.GetAsUInt64();
+ break;
+
+ case fpu_q0_arm:
+ case fpu_q1_arm:
+ case fpu_q2_arm:
+ case fpu_q3_arm:
+ case fpu_q4_arm:
+ case fpu_q5_arm:
+ case fpu_q6_arm:
+ case fpu_q7_arm:
+ case fpu_q8_arm:
+ case fpu_q9_arm:
+ case fpu_q10_arm:
+ case fpu_q11_arm:
+ case fpu_q12_arm:
+ case fpu_q13_arm:
+ case fpu_q14_arm:
+ case fpu_q15_arm:
+ memcpy(&tls_context.Q[reg - fpu_q0_arm], reg_value.GetBytes(), 16);
+ break;
+
+ case fpu_fpscr_arm:
+ tls_context.Fpscr = reg_value.GetAsUInt32();
+ break;
+ }
+
+ return SetThreadContextHelper(thread_handle, &tls_context);
+}
+
+Status
+NativeRegisterContextWindows_arm::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ Status error;
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg == LLDB_INVALID_REGNUM) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+ "register, cannot read directly",
+ reg_info->name);
+ return error;
+ }
+
+ if (IsGPR(reg))
+ return GPRRead(reg, reg_value);
+
+ if (IsFPR(reg))
+ return FPRRead(reg, reg_value);
+
+ return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_arm::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg == LLDB_INVALID_REGNUM) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly written.
+ error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+ "register, cannot write directly",
+ reg_info->name);
+ return error;
+ }
+
+ if (IsGPR(reg))
+ return GPRWrite(reg, reg_value);
+
+ if (IsFPR(reg))
+ return FPRWrite(reg, reg_value);
+
+ return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_arm::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ const size_t data_size = REG_CONTEXT_SIZE;
+ data_sp = std::make_shared(data_size, 0);
+ ::CONTEXT tls_context;
+ Status error =
+ GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
+ if (error.Fail())
+ return error;
+
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, &tls_context, data_size);
+ return error;
+}
+
+Status NativeRegisterContextWindows_arm::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+ const size_t data_size = REG_CONTEXT_SIZE;
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextWindows_arm::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != data_size) {
+ error.SetErrorStringWithFormatv(
+ "data_sp contained mismatched data size, expected {0}, actual {1}",
+ data_size, data_sp->GetByteSize());
+ return error;
+ }
+
+ ::CONTEXT tls_context;
+ memcpy(&tls_context, data_sp->GetBytes(), data_size);
+ return SetThreadContextHelper(GetThreadHandle(), &tls_context);
+}
+
+Status NativeRegisterContextWindows_arm::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
+ return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_arm::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_arm::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
+ return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_arm::SetHardwareWatchpointWithIndex(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+ return Status("unimplemented");
+}
+
+bool NativeRegisterContextWindows_arm::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ return false;
+}
+
+Status NativeRegisterContextWindows_arm::ClearAllHardwareWatchpoints() {
+ return Status("unimplemented");
+}
+
+uint32_t NativeRegisterContextWindows_arm::SetHardwareWatchpoint(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextWindows_arm::GetWatchpointAddress(uint32_t wp_index) {
+ return LLDB_INVALID_ADDRESS;
+}
+
+uint32_t NativeRegisterContextWindows_arm::NumSupportedHardwareWatchpoints() {
+ // Not implemented
+ return 0;
+}
+
+#endif // defined(__arm__) || defined(_M_ARM)
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.h b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.h
new file mode 100644
index 0000000000000..2778bed9a78de
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.h
@@ -0,0 +1,80 @@
+//===-- NativeRegisterContextWindows_arm.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__) || defined(_M_ARM)
+#ifndef liblldb_NativeRegisterContextWindows_arm_h_
+#define liblldb_NativeRegisterContextWindows_arm_h_
+
+#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
+
+#include "NativeRegisterContextWindows.h"
+
+namespace lldb_private {
+
+class NativeThreadWindows;
+
+class NativeRegisterContextWindows_arm : public NativeRegisterContextWindows {
+public:
+ NativeRegisterContextWindows_arm(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+ Status GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
+
+ Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+ bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+ Status ClearAllHardwareWatchpoints() override;
+
+ Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags,
+ uint32_t wp_index);
+
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
+
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+ uint32_t NumSupportedHardwareWatchpoints() override;
+
+protected:
+ Status GPRRead(const uint32_t reg, RegisterValue ®_value);
+
+ Status GPRWrite(const uint32_t reg, const RegisterValue ®_value);
+
+ Status FPRRead(const uint32_t reg, RegisterValue ®_value);
+
+ Status FPRWrite(const uint32_t reg, const RegisterValue ®_value);
+
+private:
+ bool IsGPR(uint32_t reg_index) const;
+
+ bool IsFPR(uint32_t reg_index) const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NativeRegisterContextWindows_arm_h_
+#endif // defined(__arm__) || defined(_M_ARM)
diff --git a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
index 416abed882309..86a302a87b86d 100644
--- a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
@@ -20,13 +20,14 @@
#include "ProcessWindowsLog.h"
#include "TargetThreadWindows.h"
-// TODO support _M_ARM
#if defined(__x86_64__) || defined(_M_AMD64)
#include "x64/RegisterContextWindows_x64.h"
#elif defined(__i386__) || defined(_M_IX86)
#include "x86/RegisterContextWindows_x86.h"
#elif defined(__aarch64__) || defined(_M_ARM64)
#include "arm64/RegisterContextWindows_arm64.h"
+#elif defined(__arm__) || defined(_M_ARM)
+#include "arm/RegisterContextWindows_arm.h"
#endif
using namespace lldb;
@@ -71,7 +72,12 @@ TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
switch (arch.GetMachine()) {
case llvm::Triple::arm:
case llvm::Triple::thumb:
- LLDB_LOG(log, "debugging ARM (NT) targets is currently unsupported");
+#if defined(__arm__) || defined(_M_ARM)
+ m_thread_reg_ctx_sp.reset(
+ new RegisterContextWindows_arm(*this, concrete_frame_idx));
+#else
+ LLDB_LOG(log, "debugging foreign targets is currently unsupported");
+#endif
break;
case llvm::Triple::aarch64:
diff --git a/lldb/source/Plugins/Process/Windows/Common/arm/RegisterContextWindows_arm.cpp b/lldb/source/Plugins/Process/Windows/Common/arm/RegisterContextWindows_arm.cpp
new file mode 100644
index 0000000000000..c8bcf71c7f6dd
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/Common/arm/RegisterContextWindows_arm.cpp
@@ -0,0 +1,432 @@
+//===-- RegisterContextWindows_arm.cpp --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__) || defined(_M_ARM)
+
+#include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-private-types.h"
+
+#include "RegisterContextWindows_arm.h"
+#include "TargetThreadWindows.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define GPR_OFFSET(idx) 0
+#define FPU_OFFSET(idx) 0
+#define FPSCR_OFFSET 0
+#define EXC_OFFSET(reg) 0
+#define DBG_OFFSET_NAME(reg) 0
+
+#define DEFINE_DBG(reg, i) \
+ #reg, NULL, \
+ 0, DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM }, \
+ NULL, NULL, NULL, 0
+
+// Include RegisterInfos_arm to declare our g_register_infos_arm structure.
+#define DECLARE_REGISTER_INFOS_ARM_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_arm.h"
+#undef DECLARE_REGISTER_INFOS_ARM_STRUCT
+
+static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm);
+
+// Array of lldb register numbers used to define the set of all General Purpose
+// Registers
+uint32_t g_gpr_reg_indices[] = {
+ gpr_r0, gpr_r1, gpr_r2, gpr_r3, gpr_r4, gpr_r5, gpr_r6, gpr_r7, gpr_r8,
+ gpr_r9, gpr_r10, gpr_r11, gpr_r12, gpr_sp, gpr_lr, gpr_pc, gpr_cpsr,
+};
+
+uint32_t g_fpu_reg_indices[] = {
+ fpu_s0, fpu_s1, fpu_s2, fpu_s3, fpu_s4, fpu_s5, fpu_s6, fpu_s7,
+ fpu_s8, fpu_s9, fpu_s10, fpu_s11, fpu_s12, fpu_s13, fpu_s14, fpu_s15,
+ fpu_s16, fpu_s17, fpu_s18, fpu_s19, fpu_s20, fpu_s21, fpu_s22, fpu_s23,
+ fpu_s24, fpu_s25, fpu_s26, fpu_s27, fpu_s28, fpu_s29, fpu_s30, fpu_s31,
+
+ fpu_d0, fpu_d1, fpu_d2, fpu_d3, fpu_d4, fpu_d5, fpu_d6, fpu_d7,
+ fpu_d8, fpu_d9, fpu_d10, fpu_d11, fpu_d12, fpu_d13, fpu_d14, fpu_d15,
+ fpu_d16, fpu_d17, fpu_d18, fpu_d19, fpu_d20, fpu_d21, fpu_d22, fpu_d23,
+ fpu_d24, fpu_d25, fpu_d26, fpu_d27, fpu_d28, fpu_d29, fpu_d30, fpu_d31,
+
+ fpu_q0, fpu_q1, fpu_q2, fpu_q3, fpu_q4, fpu_q5, fpu_q6, fpu_q7,
+ fpu_q8, fpu_q9, fpu_q10, fpu_q11, fpu_q12, fpu_q13, fpu_q14, fpu_q15,
+
+ fpu_fpscr,
+};
+
+RegisterSet g_register_sets[] = {
+ {"General Purpose Registers", "gpr",
+ llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
+ {"Floating Point Registers", "fpu", llvm::array_lengthof(g_fpu_reg_indices),
+ g_fpu_reg_indices},
+};
+
+// Constructors and Destructors
+RegisterContextWindows_arm::RegisterContextWindows_arm(
+ Thread &thread, uint32_t concrete_frame_idx)
+ : RegisterContextWindows(thread, concrete_frame_idx) {}
+
+RegisterContextWindows_arm::~RegisterContextWindows_arm() {}
+
+size_t RegisterContextWindows_arm::GetRegisterCount() {
+ return llvm::array_lengthof(g_register_infos_arm);
+}
+
+const RegisterInfo *
+RegisterContextWindows_arm::GetRegisterInfoAtIndex(size_t reg) {
+ if (reg < k_num_register_infos)
+ return &g_register_infos_arm[reg];
+ return NULL;
+}
+
+size_t RegisterContextWindows_arm::GetRegisterSetCount() {
+ return llvm::array_lengthof(g_register_sets);
+}
+
+const RegisterSet *RegisterContextWindows_arm::GetRegisterSet(size_t reg_set) {
+ return &g_register_sets[reg_set];
+}
+
+bool RegisterContextWindows_arm::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ if (!CacheAllRegisterValues())
+ return false;
+
+ if (reg_info == nullptr)
+ return false;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ switch (reg) {
+ case gpr_r0:
+ reg_value.SetUInt32(m_context.R0);
+ break;
+ case gpr_r1:
+ reg_value.SetUInt32(m_context.R1);
+ break;
+ case gpr_r2:
+ reg_value.SetUInt32(m_context.R2);
+ break;
+ case gpr_r3:
+ reg_value.SetUInt32(m_context.R3);
+ break;
+ case gpr_r4:
+ reg_value.SetUInt32(m_context.R4);
+ break;
+ case gpr_r5:
+ reg_value.SetUInt32(m_context.R5);
+ break;
+ case gpr_r6:
+ reg_value.SetUInt32(m_context.R6);
+ break;
+ case gpr_r7:
+ reg_value.SetUInt32(m_context.R7);
+ break;
+ case gpr_r8:
+ reg_value.SetUInt32(m_context.R8);
+ break;
+ case gpr_r9:
+ reg_value.SetUInt32(m_context.R9);
+ break;
+ case gpr_r10:
+ reg_value.SetUInt32(m_context.R10);
+ break;
+ case gpr_r11:
+ reg_value.SetUInt32(m_context.R11);
+ break;
+ case gpr_r12:
+ reg_value.SetUInt32(m_context.R12);
+ break;
+ case gpr_sp:
+ reg_value.SetUInt32(m_context.Sp);
+ break;
+ case gpr_lr:
+ reg_value.SetUInt32(m_context.Lr);
+ break;
+ case gpr_pc:
+ reg_value.SetUInt32(m_context.Pc);
+ break;
+ case gpr_cpsr:
+ reg_value.SetUInt32(m_context.Cpsr);
+ break;
+
+ case fpu_s0:
+ case fpu_s1:
+ case fpu_s2:
+ case fpu_s3:
+ case fpu_s4:
+ case fpu_s5:
+ case fpu_s6:
+ case fpu_s7:
+ case fpu_s8:
+ case fpu_s9:
+ case fpu_s10:
+ case fpu_s11:
+ case fpu_s12:
+ case fpu_s13:
+ case fpu_s14:
+ case fpu_s15:
+ case fpu_s16:
+ case fpu_s17:
+ case fpu_s18:
+ case fpu_s19:
+ case fpu_s20:
+ case fpu_s21:
+ case fpu_s22:
+ case fpu_s23:
+ case fpu_s24:
+ case fpu_s25:
+ case fpu_s26:
+ case fpu_s27:
+ case fpu_s28:
+ case fpu_s29:
+ case fpu_s30:
+ case fpu_s31:
+ reg_value.SetUInt32(m_context.S[reg - fpu_s0], RegisterValue::eTypeFloat);
+ break;
+
+ case fpu_d0:
+ case fpu_d1:
+ case fpu_d2:
+ case fpu_d3:
+ case fpu_d4:
+ case fpu_d5:
+ case fpu_d6:
+ case fpu_d7:
+ case fpu_d8:
+ case fpu_d9:
+ case fpu_d10:
+ case fpu_d11:
+ case fpu_d12:
+ case fpu_d13:
+ case fpu_d14:
+ case fpu_d15:
+ case fpu_d16:
+ case fpu_d17:
+ case fpu_d18:
+ case fpu_d19:
+ case fpu_d20:
+ case fpu_d21:
+ case fpu_d22:
+ case fpu_d23:
+ case fpu_d24:
+ case fpu_d25:
+ case fpu_d26:
+ case fpu_d27:
+ case fpu_d28:
+ case fpu_d29:
+ case fpu_d30:
+ case fpu_d31:
+ reg_value.SetUInt64(m_context.D[reg - fpu_d0], RegisterValue::eTypeDouble);
+ break;
+
+ case fpu_q0:
+ case fpu_q1:
+ case fpu_q2:
+ case fpu_q3:
+ case fpu_q4:
+ case fpu_q5:
+ case fpu_q6:
+ case fpu_q7:
+ case fpu_q8:
+ case fpu_q9:
+ case fpu_q10:
+ case fpu_q11:
+ case fpu_q12:
+ case fpu_q13:
+ case fpu_q14:
+ case fpu_q15:
+ reg_value.SetBytes(&m_context.Q[reg - fpu_q0], reg_info->byte_size,
+ endian::InlHostByteOrder());
+ break;
+
+ case fpu_fpscr:
+ reg_value.SetUInt32(m_context.Fpscr);
+ break;
+
+ default:
+ reg_value.SetValueToInvalid();
+ return false;
+ }
+ return true;
+}
+
+bool RegisterContextWindows_arm::WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) {
+ // Since we cannot only write a single register value to the inferior, we
+ // need to make sure our cached copy of the register values are fresh.
+ // Otherwise when writing EAX, for example, we may also overwrite some other
+ // register with a stale value.
+ if (!CacheAllRegisterValues())
+ return false;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ switch (reg) {
+ case gpr_r0:
+ m_context.R0 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r1:
+ m_context.R1 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r2:
+ m_context.R2 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r3:
+ m_context.R3 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r4:
+ m_context.R4 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r5:
+ m_context.R5 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r6:
+ m_context.R6 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r7:
+ m_context.R7 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r8:
+ m_context.R8 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r9:
+ m_context.R9 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r10:
+ m_context.R10 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r11:
+ m_context.R11 = reg_value.GetAsUInt32();
+ break;
+ case gpr_r12:
+ m_context.R12 = reg_value.GetAsUInt32();
+ break;
+ case gpr_sp:
+ m_context.Sp = reg_value.GetAsUInt32();
+ break;
+ case gpr_lr:
+ m_context.Lr = reg_value.GetAsUInt32();
+ break;
+ case gpr_pc:
+ m_context.Pc = reg_value.GetAsUInt32();
+ break;
+ case gpr_cpsr:
+ m_context.Cpsr = reg_value.GetAsUInt32();
+ break;
+
+ case fpu_s0:
+ case fpu_s1:
+ case fpu_s2:
+ case fpu_s3:
+ case fpu_s4:
+ case fpu_s5:
+ case fpu_s6:
+ case fpu_s7:
+ case fpu_s8:
+ case fpu_s9:
+ case fpu_s10:
+ case fpu_s11:
+ case fpu_s12:
+ case fpu_s13:
+ case fpu_s14:
+ case fpu_s15:
+ case fpu_s16:
+ case fpu_s17:
+ case fpu_s18:
+ case fpu_s19:
+ case fpu_s20:
+ case fpu_s21:
+ case fpu_s22:
+ case fpu_s23:
+ case fpu_s24:
+ case fpu_s25:
+ case fpu_s26:
+ case fpu_s27:
+ case fpu_s28:
+ case fpu_s29:
+ case fpu_s30:
+ case fpu_s31:
+ m_context.S[reg - fpu_s0] = reg_value.GetAsUInt32();
+ break;
+
+ case fpu_d0:
+ case fpu_d1:
+ case fpu_d2:
+ case fpu_d3:
+ case fpu_d4:
+ case fpu_d5:
+ case fpu_d6:
+ case fpu_d7:
+ case fpu_d8:
+ case fpu_d9:
+ case fpu_d10:
+ case fpu_d11:
+ case fpu_d12:
+ case fpu_d13:
+ case fpu_d14:
+ case fpu_d15:
+ case fpu_d16:
+ case fpu_d17:
+ case fpu_d18:
+ case fpu_d19:
+ case fpu_d20:
+ case fpu_d21:
+ case fpu_d22:
+ case fpu_d23:
+ case fpu_d24:
+ case fpu_d25:
+ case fpu_d26:
+ case fpu_d27:
+ case fpu_d28:
+ case fpu_d29:
+ case fpu_d30:
+ case fpu_d31:
+ m_context.D[reg - fpu_d0] = reg_value.GetAsUInt64();
+ break;
+
+ case fpu_q0:
+ case fpu_q1:
+ case fpu_q2:
+ case fpu_q3:
+ case fpu_q4:
+ case fpu_q5:
+ case fpu_q6:
+ case fpu_q7:
+ case fpu_q8:
+ case fpu_q9:
+ case fpu_q10:
+ case fpu_q11:
+ case fpu_q12:
+ case fpu_q13:
+ case fpu_q14:
+ case fpu_q15:
+ memcpy(&m_context.Q[reg - fpu_q0], reg_value.GetBytes(), 16);
+ break;
+
+ case fpu_fpscr:
+ m_context.Fpscr = reg_value.GetAsUInt32();
+ break;
+
+ default:
+ return false;
+ }
+
+ // Physically update the registers in the target process.
+ return ApplyAllRegisterValues();
+}
+
+#endif // defined(__arm__) || defined(_M_ARM)
diff --git a/lldb/source/Plugins/Process/Windows/Common/arm/RegisterContextWindows_arm.h b/lldb/source/Plugins/Process/Windows/Common/arm/RegisterContextWindows_arm.h
new file mode 100644
index 0000000000000..57050671d40c2
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/Common/arm/RegisterContextWindows_arm.h
@@ -0,0 +1,47 @@
+//===-- RegisterContextWindows_arm.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextWindows_arm_H_
+#define liblldb_RegisterContextWindows_arm_H_
+
+#if defined(__arm__) || defined(_M_ARM)
+
+#include "RegisterContextWindows.h"
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private {
+
+class Thread;
+
+class RegisterContextWindows_arm : public RegisterContextWindows {
+public:
+ // Constructors and Destructors
+ RegisterContextWindows_arm(Thread &thread, uint32_t concrete_frame_idx);
+
+ virtual ~RegisterContextWindows_arm();
+
+ // Subclasses must override these functions
+ size_t GetRegisterCount() override;
+
+ const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+ size_t GetRegisterSetCount() override;
+
+ const RegisterSet *GetRegisterSet(size_t reg_set) override;
+
+ bool ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override;
+
+ bool WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override;
+};
+} // namespace lldb_private
+
+#endif // defined(__arm__) || defined(_M_ARM)
+
+#endif // #ifndef liblldb_RegisterContextWindows_arm_H_
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 1fb9355b9ee32..d0d593656efd2 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -34,6 +34,7 @@ using namespace lldb_private::python;
using llvm::cantFail;
using llvm::Error;
using llvm::Expected;
+using llvm::Twine;
template <> Expected python::As(Expected &&obj) {
if (!obj)
@@ -278,7 +279,7 @@ PythonByteArray::PythonByteArray(llvm::ArrayRef bytes)
PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
const char *str = reinterpret_cast(bytes);
- Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
+ *this = Take(PyByteArray_FromStringAndSize(str, length));
}
bool PythonByteArray::Check(PyObject *py_obj) {
@@ -522,11 +523,11 @@ StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
PythonList::PythonList(PyInitialValue value) {
if (value == PyInitialValue::Empty)
- Reset(PyRefType::Owned, PyList_New(0));
+ *this = Take(PyList_New(0));
}
PythonList::PythonList(int list_size) {
- Reset(PyRefType::Owned, PyList_New(list_size));
+ *this = Take(PyList_New(list_size));
}
bool PythonList::Check(PyObject *py_obj) {
@@ -578,11 +579,11 @@ StructuredData::ArraySP PythonList::CreateStructuredArray() const {
PythonTuple::PythonTuple(PyInitialValue value) {
if (value == PyInitialValue::Empty)
- Reset(PyRefType::Owned, PyTuple_New(0));
+ *this = Take(PyTuple_New(0));
}
PythonTuple::PythonTuple(int tuple_size) {
- Reset(PyRefType::Owned, PyTuple_New(tuple_size));
+ *this = Take(PyTuple_New(tuple_size));
}
PythonTuple::PythonTuple(std::initializer_list objects) {
@@ -649,7 +650,7 @@ StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
PythonDictionary::PythonDictionary(PyInitialValue value) {
if (value == PyInitialValue::Empty)
- Reset(PyRefType::Owned, PyDict_New());
+ *this = Take(PyDict_New());
}
bool PythonDictionary::Check(PyObject *py_obj) {
@@ -696,10 +697,10 @@ PythonDictionary::GetItem(const PythonObject &key) const {
return Retain(o);
}
-Expected PythonDictionary::GetItem(const char *key) const {
+Expected PythonDictionary::GetItem(const Twine &key) const {
if (!IsValid())
return nullDeref();
- PyObject *o = PyDict_GetItemString(m_py_obj, key);
+ PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
if (PyErr_Occurred())
return exception();
if (!o)
@@ -717,11 +718,11 @@ Error PythonDictionary::SetItem(const PythonObject &key,
return Error::success();
}
-Error PythonDictionary::SetItem(const char *key,
+Error PythonDictionary::SetItem(const Twine &key,
const PythonObject &value) const {
if (!IsValid() || !value.IsValid())
return nullDeref();
- int r = PyDict_SetItemString(m_py_obj, key, value.get());
+ int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
if (r < 0)
return exception();
return Error::success();
@@ -763,20 +764,20 @@ PythonModule PythonModule::AddModule(llvm::StringRef module) {
return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
}
-Expected PythonModule::Import(const char *name) {
- PyObject *mod = PyImport_ImportModule(name);
+Expected PythonModule::Import(const Twine &name) {
+ PyObject *mod = PyImport_ImportModule(NullTerminated(name));
if (!mod)
return exception();
return Take(mod);
}
-Expected PythonModule::Get(const char *name) {
+Expected PythonModule::Get(const Twine &name) {
if (!IsValid())
return nullDeref();
PyObject *dict = PyModule_GetDict(m_py_obj);
if (!dict)
return exception();
- PyObject *item = PyDict_GetItemString(dict, name);
+ PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
if (!item)
return exception();
return Retain(item);
@@ -790,7 +791,9 @@ bool PythonModule::Check(PyObject *py_obj) {
}
PythonDictionary PythonModule::GetDictionary() const {
- return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
+ if (!IsValid())
+ return PythonDictionary();
+ return Retain(PyModule_GetDict(m_py_obj));
}
bool PythonCallable::Check(PyObject *py_obj) {
@@ -876,21 +879,23 @@ Expected PythonCallable::GetArgInfo() const {
result.count = cantFail(As(pyarginfo.get().GetAttribute("count")));
result.has_varargs =
cantFail(As(pyarginfo.get().GetAttribute("has_varargs")));
- result.is_bound_method =
+ bool is_method =
cantFail(As(pyarginfo.get().GetAttribute("is_bound_method")));
+ result.max_positional_args =
+ result.has_varargs ? ArgInfo::UNBOUNDED : result.count;
// FIXME emulate old broken behavior
- if (result.is_bound_method)
+ if (is_method)
result.count++;
#else
-
+ bool is_bound_method = false;
PyObject *py_func_obj = m_py_obj;
if (PyMethod_Check(py_func_obj)) {
py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
PythonObject im_self = GetAttributeValue("im_self");
if (im_self.IsValid() && !im_self.IsNone())
- result.is_bound_method = true;
+ is_bound_method = true;
} else {
// see if this is a callable object with an __call__ method
if (!PyFunction_Check(py_func_obj)) {
@@ -899,9 +904,9 @@ Expected PythonCallable::GetArgInfo() const {
auto __callable__ = __call__.AsType();
if (__callable__.IsValid()) {
py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
- PythonObject im_self = GetAttributeValue("im_self");
+ PythonObject im_self = __callable__.GetAttributeValue("im_self");
if (im_self.IsValid() && !im_self.IsNone())
- result.is_bound_method = true;
+ is_bound_method = true;
}
}
}
@@ -916,12 +921,18 @@ Expected PythonCallable::GetArgInfo() const {
result.count = code->co_argcount;
result.has_varargs = !!(code->co_flags & CO_VARARGS);
+ result.max_positional_args = result.has_varargs
+ ? ArgInfo::UNBOUNDED
+ : (result.count - (int)is_bound_method);
#endif
return result;
}
+constexpr unsigned
+ PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
+
PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
auto arginfo = GetArgInfo();
if (!arginfo) {
@@ -1084,6 +1095,8 @@ template class OwnedPythonFile : public Base {
assert(m_py_obj);
GIL takeGIL;
Close();
+ // we need to ensure the python object is released while we still
+ // hold the GIL
m_py_obj.Reset();
}
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 5823f740a5302..634d6e896015f 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -151,6 +151,30 @@ template T Retain(PyObject *obj) {
return std::move(thing);
}
+// This class can be used like a utility function to convert from
+// a llvm-friendly Twine into a null-terminated const char *,
+// which is the form python C APIs want their strings in.
+//
+// Example:
+// const llvm::Twine &some_twine;
+// PyFoo_Bar(x, y, z, NullTerminated(some_twine));
+//
+// Why a class instead of a function? If the twine isn't already null
+// terminated, it will need a temporary buffer to copy the string
+// into. We need that buffer to stick around for the lifetime of the
+// statement.
+class NullTerminated {
+ const char *str;
+ llvm::SmallString<32> storage;
+
+public:
+ NullTerminated(const llvm::Twine &twine) {
+ llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
+ str = ref.begin();
+ }
+ operator const char *() { return str; }
+};
+
} // namespace python
enum class PyInitialValue { Invalid, Empty };
@@ -323,10 +347,11 @@ class PythonObject {
return python::Take(obj);
}
- llvm::Expected GetAttribute(const char *name) const {
+ llvm::Expected GetAttribute(const llvm::Twine &name) const {
+ using namespace python;
if (!m_py_obj)
return nullDeref();
- PyObject *obj = PyObject_GetAttrString(m_py_obj, name);
+ PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
if (!obj)
return exception();
return python::Take(obj);
@@ -392,10 +417,11 @@ template class TypedPythonObject : public PythonObject {
// This can be eliminated once we drop python 2 support.
static void Convert(PyRefType &type, PyObject *&py_obj) {}
- using PythonObject::Reset;
+ void Reset() { PythonObject::Reset(); }
- void Reset(PyRefType type, PyObject *py_obj) {
- Reset();
+ void Reset(PyRefType type, PyObject *py_obj) = delete;
+
+ TypedPythonObject(PyRefType type, PyObject *py_obj) {
if (!py_obj)
return;
T::Convert(type, py_obj);
@@ -405,8 +431,6 @@ template class TypedPythonObject : public PythonObject {
Py_DECREF(py_obj);
}
- TypedPythonObject(PyRefType type, PyObject *py_obj) { Reset(type, py_obj); }
-
TypedPythonObject() {}
};
@@ -562,9 +586,9 @@ class PythonDictionary : public TypedPythonObject {
const PythonObject &value); // DEPRECATED
llvm::Expected GetItem(const PythonObject &key) const;
- llvm::Expected GetItem(const char *key) const;
+ llvm::Expected GetItem(const llvm::Twine &key) const;
llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
- llvm::Error SetItem(const char *key, const PythonObject &value) const;
+ llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
StructuredData::DictionarySP CreateStructuredDictionary() const;
};
@@ -592,9 +616,9 @@ class PythonModule : public TypedPythonObject {
return std::move(mod.get());
}
- static llvm::Expected Import(const char *name);
+ static llvm::Expected Import(const llvm::Twine &name);
- llvm::Expected Get(const char *name);
+ llvm::Expected Get(const llvm::Twine &name);
PythonDictionary GetDictionary() const;
};
@@ -604,6 +628,11 @@ class PythonCallable : public TypedPythonObject {
using TypedPythonObject::TypedPythonObject;
struct ArgInfo {
+ /* the largest number of positional arguments this callable
+ * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
+ * function and can accept an arbitrary number */
+ unsigned max_positional_args;
+ static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
/* the number of positional arguments, including optional ones,
* and excluding varargs. If this is a bound method, then the
* count will still include a +1 for self.
@@ -614,8 +643,6 @@ class PythonCallable : public TypedPythonObject {
int count;
/* does the callable have positional varargs? */
bool has_varargs : 1; // FIXME delete this
- /* is the callable a bound method written in python? */
- bool is_bound_method : 1; // FIXME delete this
};
static bool Check(PyObject *py_obj);
@@ -705,6 +732,17 @@ template T unwrapOrSetPythonException(llvm::Expected expected) {
return T();
}
+namespace python {
+// This is only here to help incrementally migrate old, exception-unsafe
+// code.
+template T unwrapIgnoringErrors(llvm::Expected expected) {
+ if (expected)
+ return std::move(expected.get());
+ llvm::consumeError(expected.takeError());
+ return T();
+}
+} // namespace python
+
} // namespace lldb_private
#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 70654a423848c..8f71335241639 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -55,6 +55,7 @@
using namespace lldb;
using namespace lldb_private;
+using namespace lldb_private::python;
// Defined in the SWIG source file
#if PY_MAJOR_VERSION >= 3
@@ -765,19 +766,16 @@ PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() {
if (!main_dict.IsValid())
return m_session_dict;
- PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
- m_session_dict.Reset(PyRefType::Borrowed, item.get());
+ m_session_dict = unwrapIgnoringErrors(
+ As(main_dict.GetItem(m_dictionary_name)));
return m_session_dict;
}
PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
if (m_sys_module_dict.IsValid())
return m_sys_module_dict;
-
- PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys"));
- if (sys_module.IsValid())
- m_sys_module_dict.Reset(PyRefType::Borrowed,
- PyModule_GetDict(sys_module.get()));
+ PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys"));
+ m_sys_module_dict = sys_module.GetDictionary();
return m_sys_module_dict;
}
@@ -1053,9 +1051,8 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
PythonDictionary locals = GetSessionDictionary();
if (!locals.IsValid()) {
- locals.Reset(
- PyRefType::Owned,
- PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+ locals = unwrapIgnoringErrors(
+ As(globals.GetAttribute(m_dictionary_name)));
}
if (!locals.IsValid())
@@ -1204,9 +1201,8 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
PythonDictionary locals = GetSessionDictionary();
if (!locals.IsValid())
- locals.Reset(
- PyRefType::Owned,
- PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+ locals = unwrapIgnoringErrors(
+ As(globals.GetAttribute(m_dictionary_name)));
if (!locals.IsValid())
locals = globals;
diff --git a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-corrupt-xz.yaml b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-corrupt-xz.yaml
index cec34b9c62332..938688cdfe617 100644
--- a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-corrupt-xz.yaml
+++ b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-corrupt-xz.yaml
@@ -5,11 +5,6 @@
# RUN: yaml2obj %s > %t.obj
-# TODO(kwk): once yaml2obj doesn't auto-generate a .symtab section
-# when there's none in YAML, remove the following line:
-
-# RUN: llvm-objcopy --remove-section=.symtab %t.obj
-
# RUN: %lldb -b -o 'image dump symtab' %t.obj 2>&1 | FileCheck %s
# CHECK: warning: (x86_64) {{.*}}.obj An error occurred while decompression the section .gnu_debugdata: lzma_stream_buffer_decode()=lzma error: LZMA_DATA_ERROR
diff --git a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-find-symbols.yaml b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-find-symbols.yaml
index 230ce8bb1c338..e6ebb03814396 100644
--- a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-find-symbols.yaml
+++ b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-find-symbols.yaml
@@ -2,11 +2,6 @@
# RUN: yaml2obj %s > %t.obj
-# TODO(kwk): once yaml2obj doesn't auto-generate a .symtab section
-# when there's none in YAML, remove the following line:
-
-# RUN: llvm-objcopy --remove-section=.symtab %t.obj
-
# RUN: %lldb -b -o 'image dump symtab' %t.obj | FileCheck %s
# CHECK: [ 0] 1 X Code 0x00000000004005b0 0x000000000000000f 0x00000012 multiplyByFour
diff --git a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-no-lzma.yaml b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-no-lzma.yaml
index a127109e991ab..63c82baf07e2a 100644
--- a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-no-lzma.yaml
+++ b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-no-lzma.yaml
@@ -5,11 +5,6 @@
# RUN: yaml2obj %s > %t.obj
-# TODO(kwk): once yaml2obj doesn't auto-generate a .symtab section
-# when there's none in YAML, remove the following line:
-
-# RUN: llvm-objcopy --remove-section=.symtab %t.obj
-
# RUN: %lldb -b -o 'image dump symtab' %t.obj 2>&1 | FileCheck %s
# CHECK: warning: (x86_64) {{.*}}.obj No LZMA support found for reading .gnu_debugdata section
diff --git a/lldb/test/Shell/Register/Inputs/arm-fp-read.cpp b/lldb/test/Shell/Register/Inputs/arm-fp-read.cpp
new file mode 100644
index 0000000000000..2dce2ed2d7532
--- /dev/null
+++ b/lldb/test/Shell/Register/Inputs/arm-fp-read.cpp
@@ -0,0 +1,19 @@
+int main() {
+ asm volatile(
+ "vmov.f64 d0, #0.5\n\t"
+ "vmov.f64 d1, #1.5\n\t"
+ "vmov.f64 d2, #2.5\n\t"
+ "vmov.f64 d3, #3.5\n\t"
+ "vmov.f32 s8, #4.5\n\t"
+ "vmov.f32 s9, #5.5\n\t"
+ "vmov.f32 s10, #6.5\n\t"
+ "vmov.f32 s11, #7.5\n\t"
+ "\n\t"
+ "bkpt #0\n\t"
+ :
+ :
+ : "d0", "d1", "d2", "d3", "s8", "s9", "s10", "s11"
+ );
+
+ return 0;
+}
diff --git a/lldb/test/Shell/Register/Inputs/arm-gp-read.cpp b/lldb/test/Shell/Register/Inputs/arm-gp-read.cpp
new file mode 100644
index 0000000000000..fd891c49c09aa
--- /dev/null
+++ b/lldb/test/Shell/Register/Inputs/arm-gp-read.cpp
@@ -0,0 +1,44 @@
+#include
+
+struct alignas(16) vec_t {
+ uint64_t a, b;
+};
+
+int main() {
+ constexpr uint32_t gprs[] = {
+ 0x00010203,
+ 0x10111213,
+ 0x20212223,
+ 0x30313233,
+ 0x40414243,
+ 0x50515253,
+ 0x60616263,
+ 0x70717273,
+ };
+
+ constexpr vec_t vecs[] = {
+ { 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
+ { 0x100F0E0D0C0B0A09, 0x1817161514131211, },
+ { 0x11100F0E0D0C0B0A, 0x1918171615141312, },
+ { 0x1211100F0E0D0C0B, 0x1A19181716151413, },
+ };
+ const vec_t *vec_ptr = vecs;
+
+ asm volatile(
+ "ldrd r0, r1, [%1]\n\t"
+ "ldrd r2, r3, [%1, #8]\n\t"
+ "ldrd r4, r5, [%1, #16]\n\t"
+ "ldrd r6, r7, [%1, #24]\n\t"
+ "\n\t"
+ "vld1.64 {q0, q1}, [%0]!\n\t"
+ "vld1.64 {q2, q3}, [%0]!\n\t"
+ "\n\t"
+ "bkpt #0\n\t"
+ : "+r"(vec_ptr)
+ : "r"(gprs)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "q0", "q1", "q2", "q3"
+ );
+
+ return 0;
+}
diff --git a/lldb/test/Shell/Register/arm-fp-read.test b/lldb/test/Shell/Register/arm-fp-read.test
new file mode 100644
index 0000000000000..21af9074e3b31
--- /dev/null
+++ b/lldb/test/Shell/Register/arm-fp-read.test
@@ -0,0 +1,21 @@
+# REQUIRES: native && target-arm
+# RUN: %clangxx -fomit-frame-pointer %p/Inputs/arm-fp-read.cpp -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+process launch
+
+register read d0
+register read d1
+register read d2
+register read d3
+register read s8
+register read s9
+register read s10
+register read s11
+# CHECK-DAG: d0 = 0.5
+# CHECK-DAG: d1 = 1.5
+# CHECK-DAG: d2 = 2.5
+# CHECK-DAG: d3 = 3.5
+# CHECK-DAG: s8 = 4.5
+# CHECK-DAG: s9 = 5.5
+# CHECK-DAG: s10 = 6.5
+# CHECK-DAG: s11 = 7.5
diff --git a/lldb/test/Shell/Register/arm-gp-read.test b/lldb/test/Shell/Register/arm-gp-read.test
new file mode 100644
index 0000000000000..73c1034b6e23b
--- /dev/null
+++ b/lldb/test/Shell/Register/arm-gp-read.test
@@ -0,0 +1,19 @@
+# REQUIRES: native && target-arm
+# RUN: %clangxx -fomit-frame-pointer %p/Inputs/arm-gp-read.cpp -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+process launch
+
+register read --all
+# CHECK-DAG: r0 = 0x00010203
+# CHECK-DAG: r1 = 0x10111213
+# CHECK-DAG: r2 = 0x20212223
+# CHECK-DAG: r3 = 0x30313233
+# CHECK-DAG: r4 = 0x40414243
+# CHECK-DAG: r5 = 0x50515253
+# CHECK-DAG: r6 = 0x60616263
+# CHECK-DAG: r7 = 0x70717273
+
+# CHECK-DAG: q0 = {0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17}
+# CHECK-DAG: q1 = {0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18}
+# CHECK-DAG: q2 = {0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19}
+# CHECK-DAG: q3 = {0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a}
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
index d9e4435bf93e9..c01dade444081 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -27,8 +27,7 @@ class PythonDataObjectsTest : public PythonTestSuite {
void SetUp() override {
PythonTestSuite::SetUp();
- PythonString sys_module("sys");
- m_sys_module.Reset(PyRefType::Owned, PyImport_Import(sys_module.get()));
+ m_sys_module = unwrapIgnoringErrors(PythonModule::Import("sys"));
m_main_module = PythonModule::MainModule();
m_builtins_module = PythonModule::BuiltinsModule();
}
@@ -70,13 +69,10 @@ TEST_F(PythonDataObjectsTest, TestResetting) {
PythonDictionary dict(PyInitialValue::Empty);
PyObject *new_dict = PyDict_New();
- dict.Reset(PyRefType::Owned, new_dict);
+ dict = Take(new_dict);
EXPECT_EQ(new_dict, dict.get());
- dict.Reset(PyRefType::Owned, nullptr);
- EXPECT_EQ(nullptr, dict.get());
-
- dict.Reset(PyRefType::Owned, PyDict_New());
+ dict = Take(PyDict_New());
EXPECT_NE(nullptr, dict.get());
dict.Reset();
EXPECT_EQ(nullptr, dict.get());
@@ -643,8 +639,8 @@ TEST_F(PythonDataObjectsTest, TestCallable) {
auto arginfo = lambda.GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 1);
+ EXPECT_EQ(arginfo.get().max_positional_args, 1u);
EXPECT_EQ(arginfo.get().has_varargs, false);
- EXPECT_EQ(arginfo.get().is_bound_method, false);
}
{
@@ -655,8 +651,8 @@ TEST_F(PythonDataObjectsTest, TestCallable) {
auto arginfo = lambda.GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 2);
+ EXPECT_EQ(arginfo.get().max_positional_args, 2u);
EXPECT_EQ(arginfo.get().has_varargs, false);
- EXPECT_EQ(arginfo.get().is_bound_method, false);
}
{
@@ -667,6 +663,7 @@ TEST_F(PythonDataObjectsTest, TestCallable) {
auto arginfo = lambda.GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 2);
+ EXPECT_EQ(arginfo.get().max_positional_args, 2u);
EXPECT_EQ(arginfo.get().has_varargs, false);
}
@@ -678,8 +675,9 @@ TEST_F(PythonDataObjectsTest, TestCallable) {
auto arginfo = lambda.GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 2);
+ EXPECT_EQ(arginfo.get().max_positional_args,
+ PythonCallable::ArgInfo::UNBOUNDED);
EXPECT_EQ(arginfo.get().has_varargs, true);
- EXPECT_EQ(arginfo.get().is_bound_method, false);
}
{
@@ -690,6 +688,8 @@ TEST_F(PythonDataObjectsTest, TestCallable) {
auto arginfo = lambda.GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 2);
+ EXPECT_EQ(arginfo.get().max_positional_args,
+ PythonCallable::ArgInfo::UNBOUNDED);
EXPECT_EQ(arginfo.get().has_varargs, true);
}
@@ -698,7 +698,18 @@ TEST_F(PythonDataObjectsTest, TestCallable) {
class Foo:
def bar(self, x):
return x
+ @classmethod
+ def classbar(cls, x):
+ return x
+ @staticmethod
+ def staticbar(x):
+ return x
+ def __call__(self, x):
+ return x
+obj = Foo()
bar_bound = Foo().bar
+bar_class = Foo().classbar
+bar_static = Foo().staticbar
bar_unbound = Foo.bar
)";
PyObject *o =
@@ -711,16 +722,37 @@ bar_unbound = Foo.bar
auto arginfo = bar_bound.get().GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 2); // FIXME, wrong
+ EXPECT_EQ(arginfo.get().max_positional_args, 1u);
EXPECT_EQ(arginfo.get().has_varargs, false);
- EXPECT_EQ(arginfo.get().is_bound_method, true);
auto bar_unbound = As(globals.GetItem("bar_unbound"));
ASSERT_THAT_EXPECTED(bar_unbound, llvm::Succeeded());
arginfo = bar_unbound.get().GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 2);
+ EXPECT_EQ(arginfo.get().max_positional_args, 2u);
+ EXPECT_EQ(arginfo.get().has_varargs, false);
+
+ auto bar_class = As(globals.GetItem("bar_class"));
+ ASSERT_THAT_EXPECTED(bar_class, llvm::Succeeded());
+ arginfo = bar_class.get().GetArgInfo();
+ ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
+ EXPECT_EQ(arginfo.get().max_positional_args, 1u);
+ EXPECT_EQ(arginfo.get().has_varargs, false);
+
+ auto bar_static = As(globals.GetItem("bar_static"));
+ ASSERT_THAT_EXPECTED(bar_static, llvm::Succeeded());
+ arginfo = bar_static.get().GetArgInfo();
+ ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
+ EXPECT_EQ(arginfo.get().max_positional_args, 1u);
+ EXPECT_EQ(arginfo.get().has_varargs, false);
+
+ auto obj = As(globals.GetItem("obj"));
+ ASSERT_THAT_EXPECTED(obj, llvm::Succeeded());
+ arginfo = obj.get().GetArgInfo();
+ ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
+ EXPECT_EQ(arginfo.get().max_positional_args, 1u);
EXPECT_EQ(arginfo.get().has_varargs, false);
- EXPECT_EQ(arginfo.get().is_bound_method, false);
}
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
@@ -734,8 +766,8 @@ bar_unbound = Foo.bar
auto arginfo = hex.get().GetArgInfo();
ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded());
EXPECT_EQ(arginfo.get().count, 1);
+ EXPECT_EQ(arginfo.get().max_positional_args, 1u);
EXPECT_EQ(arginfo.get().has_varargs, false);
- EXPECT_EQ(arginfo.get().is_bound_method, false);
}
#endif
diff --git a/llvm-spirv/include/LLVMSPIRVLib.h b/llvm-spirv/include/LLVMSPIRVLib.h
index 0c775c1f98e57..d71eaed382e78 100644
--- a/llvm-spirv/include/LLVMSPIRVLib.h
+++ b/llvm-spirv/include/LLVMSPIRVLib.h
@@ -50,6 +50,7 @@ namespace llvm {
// Pass initialization functions need to be declared before inclusion of
// PassSupport.h.
class PassRegistry;
+class ModulePass;
void initializeLLVMToSPIRVPass(PassRegistry &);
void initializeOCL20ToSPIRVPass(PassRegistry &);
void initializeOCL21ToSPIRVPass(PassRegistry &);
diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst
index 9cc5f63bec91a..3fd3ee3130740 100644
--- a/llvm/docs/CMake.rst
+++ b/llvm/docs/CMake.rst
@@ -369,11 +369,13 @@ LLVM-specific variables
**LLVM_ENABLE_PROJECTS**:STRING
Semicolon-separated list of projects to build, or *all* for building all
- (clang, libcxx, libcxxabi, lldb, compiler-rt, lld, polly) projects.
+ (clang, libcxx, libcxxabi, lldb, compiler-rt, lld, polly, etc) projects.
This flag assumes that projects are checked out side-by-side and not nested,
i.e. clang needs to be in parallel of llvm instead of nested in `llvm/tools`.
This feature allows to have one build for only LLVM and another for clang+llvm
using the same source checkout.
+ The full list is:
+ ``clang;clang-tools-extra;compiler-rt;debuginfo-tests;libc;libclc;libcxx;libcxxabi;libunwind;lld;lldb;llgo;openmp;parallel-libs;polly;pstl``
**LLVM_EXTERNAL_PROJECTS**:STRING
Semicolon-separated list of additional external projects to build as part of
diff --git a/llvm/docs/CommandGuide/llvm-ar.rst b/llvm/docs/CommandGuide/llvm-ar.rst
index 8a36a407e39a9..60187d8e44423 100644
--- a/llvm/docs/CommandGuide/llvm-ar.rst
+++ b/llvm/docs/CommandGuide/llvm-ar.rst
@@ -6,297 +6,342 @@ llvm-ar - LLVM archiver
SYNOPSIS
--------
-**llvm-ar** [-]{dmpqrtx}[Rabfikou] [relpos] [count] [files...]
+:program:`llvm-ar` [-]{dmpqrstx}[abcDilLNoOPsSTuUvV] [relpos] [count] archive [files...]
DESCRIPTION
-----------
-The **llvm-ar** command is similar to the common Unix utility, ``ar``. It
-archives several files together into a single file. The intent for this is
-to produce archive libraries by LLVM bitcode that can be linked into an
-LLVM program. However, the archive can contain any kind of file. By default,
-**llvm-ar** generates a symbol table that makes linking faster because
-only the symbol table needs to be consulted, not each individual file member
-of the archive.
+The :program:`llvm-ar` command is similar to the common Unix utility,
+:program:`ar`. It archives several files, such as objects and LLVM bitcode
+files into a single archive library that can be linked into a program. However,
+the archive can contain any kind of file. By default, :program:`llvm-ar`
+generates a symbol table that makes linking faster because only the symbol
+table needs to be consulted, not each individual file member of the archive.
-The **llvm-ar** command can be used to *read* SVR4, GNU and BSD style archive
-files. However, right now it can only write in the GNU format. If an
-SVR4 or BSD style archive is used with the ``r`` (replace) or ``q`` (quick
-update) operations, the archive will be reconstructed in GNU format.
+The :program:`llvm-ar` command can be used to *read* archive files in SVR4,
+GNU, BSD and Darwin format, and *write* in the GNU, BSD, and Darwin style
+archive files. If an SVR4 format archive is used with the :option:`r`
+(replace), :option:`d` (delete), :option:`m` (move) or :option:`q`
+(quick update) operations, the archive will be reconstructed in the format
+defined by :option:`--format`.
-Here's where **llvm-ar** departs from previous ``ar`` implementations:
+Here's where :program:`llvm-ar` departs from previous :program:`ar`
+implementations:
-*Symbol Table*
+*The following option is not supported*
+
+ [f] - truncate inserted filenames
+
+*The following options are ignored for compatibility*
- Since **llvm-ar** supports bitcode files. The symbol table it creates
- is in GNU format and includes both native and bitcode files.
+ --plugin= - load a plugin which adds support for other file formats
+
+ [l] - ignored in :program:`ar`
-*Long Paths*
+*Symbol Table*
- Currently **llvm-ar** can read GNU and BSD long file names, but only writes
- archives with the GNU format.
+ Since :program:`llvm-ar` supports bitcode files, the symbol table it creates
+ includes both native and bitcode symbols.
+
+*Deterministic Archives*
+
+ By default, :program:`llvm-ar` always uses zero for timestamps and UIDs/GIDs
+ to write archives in a deterministic mode. This is equivalent to the
+ :option:`D` modifier being enabled by default. If you wish to maintain
+ compatibility with other :program:`ar` implementations, you can pass the
+ :option:`U` modifier to write actual timestamps and UIDs/GIDs.
*Windows Paths*
- When on Windows **llvm-ar** treats the names of archived *files* in the same
+ When on Windows :program:`llvm-ar` treats the names of archived *files* in the same
case sensitive manner as the operating system. When on a non-Windows machine
- **llvm-ar** does not consider character case.
+ :program:`llvm-ar` does not consider character case.
OPTIONS
-------
-The options to **llvm-ar** are compatible with other ``ar`` implementations.
-However, there are a few modifiers (*R*) that are not found in other ``ar``
-implementations. The options to **llvm-ar** specify a single basic operation to
-perform on the archive, a variety of modifiers for that operation, the name of
-the archive file, and an optional list of file names. These options are used to
-determine how **llvm-ar** should process the archive file.
+:program:`llvm-ar` operations are compatible with other :program:`ar`
+implementations. However, there are a few modifiers (:option:`L`) that are not
+found in other :program:`ar` implementations. The options for
+:program:`llvm-ar` specify a single basic Operation to perform on the archive,
+a variety of Modifiers for that Operation, the name of the archive file, and an
+optional list of file names. If the *files* option is not specified, it
+generally means either "none" or "all" members, depending on the operation. The
+Options, Operations and Modifiers are explained in the sections below.
-The Operations and Modifiers are explained in the sections below. The minimal
-set of options is at least one operator and the name of the archive. Typically
-archive files end with a ``.a`` suffix, but this is not required. Following
-the *archive-name* comes a list of *files* that indicate the specific members
-of the archive to operate on. If the *files* option is not specified, it
-generally means either "none" or "all" members, depending on the operation.
+The minimal set of options is at least one operator and the name of the
+archive.
Operations
~~~~~~~~~~
-d
+.. option:: d [NT]
+
+ Delete files from the ``archive``. The :option:`N` and :option:`T` modifiers
+ apply to this operation. The *files* options specify which members should be
+ removed from the archive. It is not an error if a specified file does not
+ appear in the archive. If no *files* are specified, the archive is not
+ modified.
+
+.. option:: m [abi]
- Delete files from the archive. No modifiers are applicable to this operation.
- The *files* options specify which members should be removed from the
- archive. It is not an error if a specified file does not appear in the archive.
- If no *files* are specified, the archive is not modified.
+ Move files from one location in the ``archive`` to another. The :option:`a`,
+ :option:`b`, and :option:`i` modifiers apply to this operation. The *files*
+ will all be moved to the location given by the modifiers. If no modifiers are
+ used, the files will be moved to the end of the archive. If no *files* are
+ specified, the archive is not modified.
-m[abi]
+.. option:: p [v]
- Move files from one location in the archive to another. The *a*, *b*, and
- *i* modifiers apply to this operation. The *files* will all be moved
- to the location given by the modifiers. If no modifiers are used, the files
- will be moved to the end of the archive. If no *files* are specified, the
- archive is not modified.
+ Print *files* to the standard output stream. If no *files* are specified, the
+ entire ``archive`` is printed. With the :option:`v` modifier,
+ :program:`llvm-ar` also prints out the name of the file being output. Printing
+ binary files is ill-advised as they might confuse your terminal settings. The
+ :option:`p` operation never modifies the archive.
-p
+.. option:: q [LT]
- Print files to the standard output. This operation simply prints the
- *files* indicated to the standard output. If no *files* are
- specified, the entire archive is printed. Printing bitcode files is
- ill-advised as they might confuse your terminal settings. The *p*
- operation never modifies the archive.
+ Quickly append files to the end of the ``archive`` without removing
+ duplicates. If no *files* are specified, the archive is not modified. The
+ behavior when appending one archive to another depends upon whether the
+ :option:`L` and :option:`T` modifiers are used:
-q
+ * Appending a regular archive to a regular archive will append the archive
+ file. If the :option:`L` modifier is specified the members will be appended
+ instead.
- Quickly append files to the end of the archive. This operation quickly adds the
- *files* to the archive without checking for duplicates that should be
- removed first. If no *files* are specified, the archive is not modified.
- Because of the way that **llvm-ar** constructs the archive file, its dubious
- whether the *q* operation is any faster than the *r* operation.
+ * Appending a regular archive to a thin archive requires the :option:`T`
+ modifier and will append the archive file. The :option:`L` modifier is not
+ supported.
-r[abu]
+ * Appending a thin archive to a regular archive will append the archive file.
+ If the :option:`L` modifier is specified the members will be appended
+ instead.
- Replace or insert file members. The *a*, *b*, and *u*
- modifiers apply to this operation. This operation will replace existing
- *files* or insert them at the end of the archive if they do not exist. If no
- *files* are specified, the archive is not modified.
+ * Appending a thin archive to a thin archive will always quick append its
+ members.
-t[vO]
+.. option:: r [abTu]
+
+ Replace existing *files* or insert them at the end of the ``archive`` if
+ they do not exist. The :option:`a`, :option:`b`, :option:`T` and :option:`u`
+ modifiers apply to this operation. If no *files* are specified, the archive
+ is not modified.
+
+t[v]
+.. option:: t [vO]
Print the table of contents. Without any modifiers, this operation just prints
- the names of the members to the standard output. With the *v* modifier,
- **llvm-ar** also prints out the file type (B=bitcode, S=symbol
- table, blank=regular file), the permission mode, the owner and group, the
- size, and the date. With the :option:`O` modifier, display member offsets.
- If any *files* are specified, the listing is only for those files. If no
- *files* are specified, the table of contents for the whole archive is printed.
+ the names of the members to the standard output stream. With the :option:`v`
+ modifier, :program:`llvm-ar` also prints out the file type (B=bitcode,
+ S=symbol table, blank=regular file), the permission mode, the owner and group,
+ are ignored when extracting *files* and set to placeholder values when adding
+ size, and the date. With the :option:`O` modifier, display member offsets. If
+ any *files* are specified, the listing is only for those files. If no *files*
+ are specified, the table of contents for the whole archive is printed.
+
+.. option:: V
-x[oP]
+ A synonym for the :option:`--version` option.
- Extract archive members back to files. The *o* modifier applies to this
- operation. This operation retrieves the indicated *files* from the archive
- and writes them back to the operating system's file system. If no
- *files* are specified, the entire archive is extract.
+.. option:: x [oP]
+
+ Extract ``archive`` members back to files. The :option:`o` modifier applies
+ to this operation. This operation retrieves the indicated *files* from the
+ archive and writes them back to the operating system's file system. If no
+ *files* are specified, the entire archive is extracted.
Modifiers (operation specific)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The modifiers below are specific to certain operations. See the Operations
-section (above) to determine which modifiers are applicable to which operations.
+section to determine which modifiers are applicable to which operations.
+
+.. option:: a
-[a]
+ When inserting or moving member files, this option specifies the destination
+ of the new files as being after the *relpos* member. If *relpos* is not found,
+ the files are placed at the end of the ``archive``. *relpos* cannot be
+ consumed without either :option:`a`, :option:`b` or :option:`i`.
- When inserting or moving member files, this option specifies the destination of
- the new files as being after the *relpos* member. If *relpos* is not found,
- the files are placed at the end of the archive.
+.. option:: b
-[b]
+ When inserting or moving member files, this option specifies the destination
+ of the new files as being before the *relpos* member. If *relpos* is not
+ found, the files are placed at the end of the ``archive``. *relpos* cannot
+ be consumed without either :option:`a`, :option:`b` or :option:`i`. This
+ modifier is identical to the :option:`i` modifier.
- When inserting or moving member files, this option specifies the destination of
- the new files as being before the *relpos* member. If *relpos* is not
- found, the files are placed at the end of the archive. This modifier is
- identical to the *i* modifier.
+.. option:: i
-[i]
+ A synonym for the :option:`b` option.
- A synonym for the *b* option.
+.. option:: L
-[o]
+ When quick appending an ``archive``, instead quick append its members. This
+ is a feature for :program:`llvm-ar` that is not found in gnu-ar.
- When extracting files, this option will cause **llvm-ar** to preserve the
- original modification times of the files it writes.
+.. option:: N
+ When extracting or deleting a member that shares its name with another member,
+ the *count* parameter allows you to supply a positive whole number that
+ selects the instance of the given name, with "1" indicating the first
+ instance. If :option:`N` is not specified the first member of that name will
+ be selected. If *count* is not supplied, the operation fails.*count* cannot be
+
+.. option:: o
+
+ When extracting files, use the modification times of any *files* as they
+ appear in the ``archive``. By default *files* extracted from the archive
+ use the time of extraction.
+
.. option:: O
Display member offsets inside the archive.
-[u]
+.. option:: T
+
+ When creating or modifying an archive, this option specifies that the
+ ``archive`` will be thin. By default, archives are not created as thin
+ archives and when modifying a thin archive, it will be converted to a regular
+ archive.
- When replacing existing files in the archive, only replace those files that have
- a time stamp than the time stamp of the member in the archive.
+.. option:: v
+
+ When printing *files* or the ``archive`` table of contents, this modifier
+ instructs :program:`llvm-ar` to include additional information in the output.
Modifiers (generic)
~~~~~~~~~~~~~~~~~~~
The modifiers below may be applied to any operation.
-[c]
+.. option:: c
+
+ For the :option:`r` (replace)and :option:`q` (quick update) operations,
+ :program:`llvm-ar` will always create the archive if it doesn't exist.
+ Normally, :program:`llvm-ar` will print a warning message indicating that the
+ ``archive`` is being created. Using this modifier turns off
+ that warning.
+
+.. option:: D
- For all operations, **llvm-ar** will always create the archive if it doesn't
- exist. Normally, **llvm-ar** will print a warning message indicating that the
- archive is being created. Using this modifier turns off that warning.
+ Use zero for timestamps and UIDs/GIDs. This is set by default.
+.. option:: P
-[s]
+ Use full paths when matching member names rather than just the file name.
+ This can be useful when manipulating an ``archive`` generated by another
+ archiver, as some allow paths as member names. This is the default behavior
+ for thin archives.
+
+.. option:: s
This modifier requests that an archive index (or symbol table) be added to the
- archive. This is the default mode of operation. The symbol table will contain
- all the externally visible functions and global variables defined by all the
- bitcode files in the archive.
+ ``archive``, as if using ranlib. The symbol table will contain all the
+ externally visible functions and global variables defined by all the bitcode
+ files in the archive. By default :program:`llvm-ar` generates symbol tables in
+ archives. This can also be used as an operation.
-[S]
+.. option:: S
- This modifier is the opposite of the *s* modifier. It instructs **llvm-ar** to
- not build the symbol table. If both *s* and *S* are used, the last modifier to
- occur in the options will prevail.
+ This modifier is the opposite of the :option:`s` modifier. It instructs
+ :program:`llvm-ar` to not build the symbol table. If both :option:`s` and
+ :option:`S` are used, the last modifier to occur in the options will prevail.
+
+.. option:: u
-[v]
+ Only update ``archive`` members with *files* that have more recent
+ timestamps.
+
+.. option:: U
- This modifier instructs **llvm-ar** to be verbose about what it is doing. Each
- editing operation taken against the archive will produce a line of output saying
- what is being done.
+ Use actual timestamps and UIDs/GIDs.
-STANDARDS
----------
+Other
+~~~~~
-The **llvm-ar** utility is intended to provide a superset of the IEEE Std 1003.2
-(POSIX.2) functionality for ``ar``. **llvm-ar** can read both SVR4 and BSD4.4 (or
-macOS) archives. If the ``f`` modifier is given to the ``x`` or ``r`` operations
-then **llvm-ar** will write SVR4 compatible archives. Without this modifier,
-**llvm-ar** will write BSD4.4 compatible archives that have long names
-immediately after the header and indicated using the "#1/ddd" notation for the
-name in the header.
+.. option:: --format=
-FILE FORMAT
------------
+ This option allows for default, gnu, darwin or bsd ```` to be selected.
+ When creating an ``archive``, ```` will default to that of the host
+ machine.
-The file format for LLVM Archive files is similar to that of BSD 4.4 or macOS
-archive files. In fact, except for the symbol table, the ``ar`` commands on those
-operating systems should be able to read LLVM archive files. The details of the
-file format follow.
+.. option:: -h, --help
-Each archive begins with the archive magic number which is the eight printable
-characters "!\n" where \n represents the newline character (0x0A).
-Following the magic number, the file is composed of even length members that
-begin with an archive header and end with a \n padding character if necessary
-(to make the length even). Each file member is composed of a header (defined
-below), an optional newline-terminated "long file name" and the contents of
-the file.
+ Print a summary of command-line options and their meanings.
-The fields of the header are described in the items below. All fields of the
-header contain only ASCII characters, are left justified and are right padded
-with space characters.
+.. option:: -M
-name - char[16]
+ This option allows for MRI scripts to be read through the standard input
+ stream. No other options are compatible with this option.
- This field of the header provides the name of the archive member. If the name is
- longer than 15 characters or contains a slash (/) character, then this field
- contains ``#1/nnn`` where ``nnn`` provides the length of the name and the ``#1/``
- is literal. In this case, the actual name of the file is provided in the ``nnn``
- bytes immediately following the header. If the name is 15 characters or less, it
- is contained directly in this field and terminated with a slash (/) character.
+.. option:: --version
-date - char[12]
+ Display the version of the :program:`llvm-ar` executable.
- This field provides the date of modification of the file in the form of a
- decimal encoded number that provides the number of seconds since the epoch
- (since 00:00:00 Jan 1, 1970) per Posix specifications.
+.. option:: @
-uid - char[6]
+ Read command-line options and commands from response file ````.
- This field provides the user id of the file encoded as a decimal ASCII string.
- This field might not make much sense on non-Unix systems. On Unix, it is the
- same value as the st_uid field of the stat structure returned by the stat(2)
- operating system call.
+MRI SCRIPTS
+-----------
-gid - char[6]
+:program:`llvm-ar` understands a subset of the MRI scripting interface commonly
+supported by archivers following in the ar tradition. An MRI script contains a
+sequence of commands to be executed by the archiver. The :option:`-M` option
+allows for an MRI script to be passed to :program:`llvm-ar` through the
+standard input stream.
+
+Note that :program:`llvm-ar` has known limitations regarding the use of MRI
+scripts:
+
+* Each script can only create one archive.
+* Existing archives can not be modified.
- This field provides the group id of the file encoded as a decimal ASCII string.
- This field might not make much sense on non-Unix systems. On Unix, it is the
- same value as the st_gid field of the stat structure returned by the stat(2)
- operating system call.
+MRI Script Commands
+~~~~~~~~~~~~~~~~~~~
-mode - char[8]
+Each command begins with the command's name and must appear on its own line.
+Some commands have arguments, which must be separated from the name by
+whitespace. An MRI script should begin with either a :option:`CREATE` or
+:option:`CREATETHIN` command and will typically end with a :option:`SAVE`
+command. Any text after either '*' or ';' is treated as a comment.
- This field provides the access mode of the file encoded as an octal ASCII
- string. This field might not make much sense on non-Unix systems. On Unix, it
- is the same value as the st_mode field of the stat structure returned by the
- stat(2) operating system call.
+.. option:: CREATE archive
-size - char[10]
+ Begin creation of a regular archive with the specified name. Subsequent
+ commands act upon this ``archive``.
- This field provides the size of the file, in bytes, encoded as a decimal ASCII
- string.
+.. option:: CREATETHIN archive
-fmag - char[2]
+ Begin creation of a thin archive with the specified name. Subsequent
+ commands act upon this ``archive``.
- This field is the archive file member magic number. Its content is always the
- two characters back tick (0x60) and newline (0x0A). This provides some measure
- utility in identifying archive files that have been corrupted.
+.. option:: ADDLIB archive
-offset - vbr encoded 32-bit integer
+ Append the contents of ``archive`` to the current archive.
- The offset item provides the offset into the archive file where the bitcode
- member is stored that is associated with the symbol. The offset value is 0
- based at the start of the first "normal" file member. To derive the actual
- file offset of the member, you must add the number of bytes occupied by the file
- signature (8 bytes) and the symbol tables. The value of this item is encoded
- using variable bit rate encoding to reduce the size of the symbol table.
- Variable bit rate encoding uses the high bit (0x80) of each byte to indicate
- if there are more bytes to follow. The remaining 7 bits in each byte carry bits
- from the value. The final byte does not have the high bit set.
+.. option:: ADDMOD
-length - vbr encoded 32-bit integer
+ Append ```` to the current archive.
- The length item provides the length of the symbol that follows. Like this
- *offset* item, the length is variable bit rate encoded.
+.. option:: DELETE
-symbol - character array
+ Delete the member of the current archive whose file name, excluding directory
+ components, matches ````.
- The symbol item provides the text of the symbol that is associated with the
- *offset*. The symbol is not terminated by any character. Its length is provided
- by the *length* field. Note that is allowed (but unwise) to use non-printing
- characters (even 0x00) in the symbol. This allows for multiple encodings of
- symbol names.
+.. option:: SAVE
-EXIT STATUS
------------
+ Write the current archive to the path specified in the previous
+ :option:`CREATE`/:option:`CREATETHIN` command.
-If **llvm-ar** succeeds, it will exit with 0. A usage error, results
-in an exit code of 1. A hard (file system typically) error results in an
-exit code of 2. Miscellaneous or unknown errors result in an
-exit code of 3.
+.. option:: END
-SEE ALSO
---------
+ Ends the MRI script (optional).
+
+EXIT STATUS
+-----------
-ar(1)
+If :program:`llvm-ar` succeeds, it will exit with 0. Otherwise, if an error occurs, it
+will exit with a non-zero value.
diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h
index 008188bfa2109..b22606bdb518e 100644
--- a/llvm/include/llvm/ADT/Hashing.h
+++ b/llvm/include/llvm/ADT/Hashing.h
@@ -45,7 +45,6 @@
#define LLVM_ADT_HASHING_H
#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/type_traits.h"
#include
diff --git a/llvm/include/llvm/Analysis/Loads.h b/llvm/include/llvm/Analysis/Loads.h
index b5884acf3b0cc..9604b2521e895 100644
--- a/llvm/include/llvm/Analysis/Loads.h
+++ b/llvm/include/llvm/Analysis/Loads.h
@@ -37,7 +37,8 @@ bool isDereferenceablePointer(const Value *V, Type *Ty,
/// performs context-sensitive analysis and returns true if the pointer is
/// dereferenceable at the specified instruction.
bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty,
- unsigned Align, const DataLayout &DL,
+ MaybeAlign Alignment,
+ const DataLayout &DL,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr);
@@ -45,7 +46,7 @@ bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty,
/// greater or equal than requested. If the context instruction is specified
/// performs context-sensitive analysis and returns true if the pointer is
/// dereferenceable at the specified instruction.
-bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
+bool isDereferenceableAndAlignedPointer(const Value *V, Align Alignment,
const APInt &Size, const DataLayout &DL,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr);
@@ -58,7 +59,7 @@ bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
/// If it is not obviously safe to load from the specified pointer, we do a
/// quick local scan of the basic block containing ScanFrom, to determine if
/// the address is already accessed.
-bool isSafeToLoadUnconditionally(Value *V, unsigned Align, APInt &Size,
+bool isSafeToLoadUnconditionally(Value *V, MaybeAlign Alignment, APInt &Size,
const DataLayout &DL,
Instruction *ScanFrom = nullptr,
const DominatorTree *DT = nullptr);
@@ -82,7 +83,7 @@ bool isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L,
/// If it is not obviously safe to load from the specified pointer, we do a
/// quick local scan of the basic block containing ScanFrom, to determine if
/// the address is already accessed.
-bool isSafeToLoadUnconditionally(Value *V, Type *Ty, unsigned Align,
+bool isSafeToLoadUnconditionally(Value *V, Type *Ty, MaybeAlign Alignment,
const DataLayout &DL,
Instruction *ScanFrom = nullptr,
const DominatorTree *DT = nullptr);
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index e2c94a12ad679..f550d880f68a3 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
namespace llvm {
namespace wasm {
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index f73976dbacf95..2e57b4c9d332f 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -1149,9 +1149,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase {
OpPropsBW);
// For non-rotates (X != Y) we must add shift-by-zero handling costs.
if (X != Y) {
- Type *CondTy = Type::getInt1Ty(RetTy->getContext());
- if (RetVF > 1)
- CondTy = VectorType::get(CondTy, RetVF);
+ Type *CondTy = RetTy->getWithNewBitWidth(1);
Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy,
CondTy, nullptr);
Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::Select, RetTy,
@@ -1169,7 +1167,6 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase {
unsigned getIntrinsicInstrCost(
Intrinsic::ID IID, Type *RetTy, ArrayRef Tys, FastMathFlags FMF,
unsigned ScalarizationCostPassed = std::numeric_limits::max()) {
- unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1);
auto *ConcreteTTI = static_cast(this);
SmallVector ISDs;
@@ -1326,9 +1323,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase {
/*IsUnsigned=*/false);
case Intrinsic::sadd_sat:
case Intrinsic::ssub_sat: {
- Type *CondTy = Type::getInt1Ty(RetTy->getContext());
- if (RetVF > 1)
- CondTy = VectorType::get(CondTy, RetVF);
+ Type *CondTy = RetTy->getWithNewBitWidth(1);
Type *OpTy = StructType::create({RetTy, CondTy});
Intrinsic::ID OverflowOp = IID == Intrinsic::sadd_sat
@@ -1348,9 +1343,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase {
}
case Intrinsic::uadd_sat:
case Intrinsic::usub_sat: {
- Type *CondTy = Type::getInt1Ty(RetTy->getContext());
- if (RetVF > 1)
- CondTy = VectorType::get(CondTy, RetVF);
+ Type *CondTy = RetTy->getWithNewBitWidth(1);
Type *OpTy = StructType::create({RetTy, CondTy});
Intrinsic::ID OverflowOp = IID == Intrinsic::uadd_sat
@@ -1367,9 +1360,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase {
case Intrinsic::smul_fix:
case Intrinsic::umul_fix: {
unsigned ExtSize = RetTy->getScalarSizeInBits() * 2;
- Type *ExtTy = Type::getIntNTy(RetTy->getContext(), ExtSize);
- if (RetVF > 1)
- ExtTy = VectorType::get(ExtTy, RetVF);
+ Type *ExtTy = RetTy->getWithNewBitWidth(ExtSize);
unsigned ExtOp =
IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt;
@@ -1433,9 +1424,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase {
Type *MulTy = RetTy->getContainedType(0);
Type *OverflowTy = RetTy->getContainedType(1);
unsigned ExtSize = MulTy->getScalarSizeInBits() * 2;
- Type *ExtTy = Type::getIntNTy(RetTy->getContext(), ExtSize);
- if (MulTy->isVectorTy())
- ExtTy = VectorType::get(ExtTy, MulTy->getVectorNumElements() );
+ Type *ExtTy = MulTy->getWithNewBitWidth(ExtSize);
unsigned ExtOp =
IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt;
diff --git a/llvm/include/llvm/CodeGen/DFAPacketizer.h b/llvm/include/llvm/CodeGen/DFAPacketizer.h
index 77ada7fda920b..705465b15c4c8 100644
--- a/llvm/include/llvm/CodeGen/DFAPacketizer.h
+++ b/llvm/include/llvm/CodeGen/DFAPacketizer.h
@@ -144,7 +144,7 @@ class VLIWPacketizerList {
protected:
MachineFunction &MF;
const TargetInstrInfo *TII;
- AliasAnalysis *AA;
+ AAResults *AA;
// The VLIW Scheduler.
DefaultVLIWScheduler *VLIWScheduler;
@@ -156,9 +156,9 @@ class VLIWPacketizerList {
std::map MIToSUnit;
public:
- // The AliasAnalysis parameter can be nullptr.
+ // The AAResults parameter can be nullptr.
VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI,
- AliasAnalysis *AA);
+ AAResults *AA);
virtual ~VLIWPacketizerList();
diff --git a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
index fb60191abd3a0..f812a2f6c5852 100644
--- a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Analysis/LegacyDivergenceAnalysis.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
@@ -37,6 +36,7 @@ namespace llvm {
class Argument;
class BasicBlock;
class BranchProbabilityInfo;
+class LegacyDivergenceAnalysis;
class Function;
class Instruction;
class MachineFunction;
diff --git a/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index 2a826d0b64c03..a438ecfcc25ed 100644
--- a/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -38,9 +38,6 @@ class MachineBlockFrequencyInfo : public MachineFunctionPass {
static char ID;
MachineBlockFrequencyInfo();
- explicit MachineBlockFrequencyInfo(MachineFunction &F,
- MachineBranchProbabilityInfo &MBPI,
- MachineLoopInfo &MLI);
~MachineBlockFrequencyInfo() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
diff --git a/llvm/include/llvm/CodeGen/MachineDominators.h b/llvm/include/llvm/CodeGen/MachineDominators.h
index 9d31232c9b95b..e4d7a02f8c48e 100644
--- a/llvm/include/llvm/CodeGen/MachineDominators.h
+++ b/llvm/include/llvm/CodeGen/MachineDominators.h
@@ -81,9 +81,6 @@ class MachineDominatorTree : public MachineFunctionPass {
static char ID; // Pass ID, replacement for typeid
MachineDominatorTree();
- explicit MachineDominatorTree(MachineFunction &MF) : MachineFunctionPass(ID) {
- calculate(MF);
- }
DomTreeT &getBase() {
if (!DT) DT.reset(new DomTreeT());
@@ -114,8 +111,6 @@ class MachineDominatorTree : public MachineFunctionPass {
bool runOnMachineFunction(MachineFunction &F) override;
- void calculate(MachineFunction &F);
-
bool dominates(const MachineDomTreeNode *A,
const MachineDomTreeNode *B) const {
applySplitCriticalEdges();
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 0191c779419cc..c94ad292ec964 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -20,11 +20,9 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetOpcodes.h"
-#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/MC/MCInstrDesc.h"
@@ -38,6 +36,7 @@
namespace llvm {
+class AAResults;
template class ArrayRef;
class DIExpression;
class DILocalVariable;
@@ -1043,9 +1042,7 @@ class MachineInstr
/// A DBG_VALUE is an entry value iff its debug expression contains the
/// DW_OP_LLVM_entry_value operation.
- bool isDebugEntryValue() const {
- return isDebugValue() && getDebugExpression()->isEntryValue();
- }
+ bool isDebugEntryValue() const;
/// Return true if the instruction is a debug value which describes a part of
/// a variable as unavailable.
@@ -1414,7 +1411,7 @@ class MachineInstr
/// Return true if it is safe to move this instruction. If
/// SawStore is set to true, it means that there is a store (or call) between
/// the instruction's location and its intended destination.
- bool isSafeToMove(AliasAnalysis *AA, bool &SawStore) const;
+ bool isSafeToMove(AAResults *AA, bool &SawStore) const;
/// Returns true if this instruction's memory access aliases the memory
/// access of Other.
@@ -1426,7 +1423,7 @@ class MachineInstr
/// @param AA Optional alias analysis, used to compare memory operands.
/// @param Other MachineInstr to check aliasing against.
/// @param UseTBAA Whether to pass TBAA information to alias analysis.
- bool mayAlias(AliasAnalysis *AA, const MachineInstr &Other, bool UseTBAA) const;
+ bool mayAlias(AAResults *AA, const MachineInstr &Other, bool UseTBAA) const;
/// Return true if this instruction may have an ordered
/// or volatile memory reference, or if the information describing the memory
@@ -1441,7 +1438,7 @@ class MachineInstr
/// argument area of a function (if it does not change). If the instruction
/// does multiple loads, this returns true only if all of the loads are
/// dereferenceable and invariant.
- bool isDereferenceableInvariantLoad(AliasAnalysis *AA) const;
+ bool isDereferenceableInvariantLoad(AAResults *AA) const;
/// If the specified instruction is a PHI that always merges together the
/// same virtual register, return the register, otherwise return 0.
diff --git a/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/llvm/include/llvm/CodeGen/MachineLoopInfo.h
index 1612c8b86a303..da6df59c739c2 100644
--- a/llvm/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineLoopInfo.h
@@ -37,7 +37,6 @@
namespace llvm {
-class MachineDominatorTree;
// Implementation in LoopInfoImpl.h
class MachineLoop;
extern template class LoopBase;
@@ -92,10 +91,6 @@ class MachineLoopInfo : public MachineFunctionPass {
MachineLoopInfo() : MachineFunctionPass(ID) {
initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
}
- explicit MachineLoopInfo(MachineDominatorTree &MDT)
- : MachineFunctionPass(ID) {
- calculate(MDT);
- }
MachineLoopInfo(const MachineLoopInfo &) = delete;
MachineLoopInfo &operator=(const MachineLoopInfo &) = delete;
@@ -138,7 +133,6 @@ class MachineLoopInfo : public MachineFunctionPass {
/// Calculate the natural loop information.
bool runOnMachineFunction(MachineFunction &F) override;
- void calculate(MachineDominatorTree &MDT);
void releaseMemory() override { LI.releaseMemory(); }
diff --git a/llvm/include/llvm/CodeGen/MachinePipeliner.h b/llvm/include/llvm/CodeGen/MachinePipeliner.h
index 893725c0f1d55..e9cf7e115bffe 100644
--- a/llvm/include/llvm/CodeGen/MachinePipeliner.h
+++ b/llvm/include/llvm/CodeGen/MachinePipeliner.h
@@ -40,6 +40,8 @@
#ifndef LLVM_LIB_CODEGEN_MACHINEPIPELINER_H
#define LLVM_LIB_CODEGEN_MACHINEPIPELINER_H
+#include "llvm/Analysis/AliasAnalysis.h"
+
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
diff --git a/llvm/include/llvm/CodeGen/MachineSizeOpts.h b/llvm/include/llvm/CodeGen/MachineSizeOpts.h
deleted file mode 100644
index 75e871d974757..0000000000000
--- a/llvm/include/llvm/CodeGen/MachineSizeOpts.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- MachineSizeOpts.h - machine size optimization ------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains some shared machine IR code size optimization related
-// code.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_MACHINE_SIZEOPTS_H
-#define LLVM_CODEGEN_MACHINE_SIZEOPTS_H
-
-#include "llvm/Transforms/Utils/SizeOpts.h"
-
-namespace llvm {
-
-class ProfileSummaryInfo;
-class MachineBasicBlock;
-class MachineBlockFrequencyInfo;
-class MachineFunction;
-
-/// Returns true if machine function \p MF is suggested to be size-optimized
-/// base on the profile.
-bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI,
- const MachineBlockFrequencyInfo *BFI);
-/// Returns true if machine basic block \p MBB is suggested to be size-optimized
-/// base on the profile.
-bool shouldOptimizeForSize(const MachineBasicBlock *MBB,
- ProfileSummaryInfo *PSI,
- const MachineBlockFrequencyInfo *MBFI);
-
-} // end namespace llvm
-
-#endif // LLVM_CODEGEN_MACHINE_SIZEOPTS_H
diff --git a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
index eaa55c911b812..1eb9b9f322ba2 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -34,6 +34,7 @@
namespace llvm {
+ class AAResults;
class LiveIntervals;
class MachineFrameInfo;
class MachineFunction;
@@ -173,7 +174,7 @@ namespace llvm {
/// Tracks the last instructions in this region using each virtual register.
VReg2SUnitOperIdxMultiMap CurrentVRegUses;
- AliasAnalysis *AAForDep = nullptr;
+ AAResults *AAForDep = nullptr;
/// Remember a generic side-effecting instruction as we proceed.
/// No other SU ever gets scheduled around it (except in the special
@@ -201,7 +202,7 @@ namespace llvm {
Value2SUsMap &loads, unsigned N);
/// Adds a chain edge between SUa and SUb, but only if both
- /// AliasAnalysis and Target fail to deny the dependency.
+ /// AAResults and Target fail to deny the dependency.
void addChainDependency(SUnit *SUa, SUnit *SUb,
unsigned Latency = 0);
@@ -306,7 +307,7 @@ namespace llvm {
/// If \p RPTracker is non-null, compute register pressure as a side effect.
/// The DAG builder is an efficient place to do it because it already visits
/// operands.
- void buildSchedGraph(AliasAnalysis *AA,
+ void buildSchedGraph(AAResults *AA,
RegPressureTracker *RPTracker = nullptr,
PressureDiffs *PDiffs = nullptr,
LiveIntervals *LIS = nullptr,
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index be6e2bd7d6526..6b8e2dd803ba8 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -26,8 +26,6 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/Analysis/LegacyDivergenceAnalysis.h"
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
@@ -58,6 +56,7 @@
namespace llvm {
+class AAResults;
class BlockAddress;
class Constant;
class ConstantFP;
@@ -66,6 +65,7 @@ class DataLayout;
struct fltSemantics;
class GlobalValue;
struct KnownBits;
+class LegacyDivergenceAnalysis;
class LLVMContext;
class MachineBasicBlock;
class MachineConstantPoolValue;
@@ -499,7 +499,7 @@ class SelectionDAG {
/// certain types of nodes together, or eliminating superfluous nodes. The
/// Level argument controls whether Combine is allowed to produce nodes and
/// types that are illegal on the target.
- void Combine(CombineLevel Level, AliasAnalysis *AA,
+ void Combine(CombineLevel Level, AAResults *AA,
CodeGenOpt::Level OptLevel);
/// This transforms the SelectionDAG into a SelectionDAG that
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
index a2011cc4b3959..de71a21d46718 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
@@ -22,22 +22,23 @@
#include
namespace llvm {
- class FastISel;
- class SelectionDAGBuilder;
- class SDValue;
- class MachineRegisterInfo;
- class MachineBasicBlock;
- class MachineFunction;
- class MachineInstr;
- class OptimizationRemarkEmitter;
- class TargetLowering;
- class TargetLibraryInfo;
- class FunctionLoweringInfo;
- class ScheduleHazardRecognizer;
- class SwiftErrorValueTracking;
- class GCFunctionInfo;
- class ScheduleDAGSDNodes;
- class LoadInst;
+class AAResults;
+class FastISel;
+class SelectionDAGBuilder;
+class SDValue;
+class MachineRegisterInfo;
+class MachineBasicBlock;
+class MachineFunction;
+class MachineInstr;
+class OptimizationRemarkEmitter;
+class TargetLowering;
+class TargetLibraryInfo;
+class FunctionLoweringInfo;
+class ScheduleHazardRecognizer;
+class SwiftErrorValueTracking;
+class GCFunctionInfo;
+class ScheduleDAGSDNodes;
+class LoadInst;
/// SelectionDAGISel - This is the common base class used for SelectionDAG-based
/// pattern-matching instruction selectors.
@@ -51,7 +52,7 @@ class SelectionDAGISel : public MachineFunctionPass {
MachineRegisterInfo *RegInfo;
SelectionDAG *CurDAG;
SelectionDAGBuilder *SDB;
- AliasAnalysis *AA;
+ AAResults *AA;
GCFunctionInfo *GFI;
CodeGenOpt::Level OptLevel;
const TargetInstrInfo *TII;
diff --git a/llvm/include/llvm/CodeGen/TargetCallingConv.h b/llvm/include/llvm/CodeGen/TargetCallingConv.h
index 360fc51bd0415..db3d1175afee4 100644
--- a/llvm/include/llvm/CodeGen/TargetCallingConv.h
+++ b/llvm/include/llvm/CodeGen/TargetCallingConv.h
@@ -125,18 +125,18 @@ namespace ISD {
MaybeAlign A = decodeMaybeAlign(ByValAlign);
return A ? A->value() : 0;
}
- void setByValAlign(unsigned A) {
- ByValAlign = encode(Align(A));
- assert(getByValAlign() == A && "bitfield overflow");
+ void setByValAlign(Align A) {
+ ByValAlign = encode(A);
+ assert(getByValAlign() == A.value() && "bitfield overflow");
}
unsigned getOrigAlign() const {
MaybeAlign A = decodeMaybeAlign(OrigAlign);
return A ? A->value() : 0;
}
- void setOrigAlign(unsigned A) {
- OrigAlign = encode(Align(A));
- assert(getOrigAlign() == A && "bitfield overflow");
+ void setOrigAlign(Align A) {
+ OrigAlign = encode(A);
+ assert(getOrigAlign() == A.value() && "bitfield overflow");
}
unsigned getByValSize() const { return ByValSize; }
diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index da00155ed546a..2100a64c8f549 100644
--- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -55,12 +55,12 @@ class TargetFrameLowering {
private:
StackDirection StackDir;
Align StackAlignment;
- unsigned TransientStackAlignment;
+ Align TransientStackAlignment;
int LocalAreaOffset;
bool StackRealignable;
public:
TargetFrameLowering(StackDirection D, Align StackAl, int LAO,
- unsigned TransAl = 1, bool StackReal = true)
+ Align TransAl = Align::None(), bool StackReal = true)
: StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl),
LocalAreaOffset(LAO), StackRealignable(StackReal) {}
@@ -96,7 +96,7 @@ class TargetFrameLowering {
/// calls.
///
unsigned getTransientStackAlignment() const {
- return TransientStackAlignment;
+ return TransientStackAlignment.value();
}
/// isStackRealignable - This method returns whether the stack can be
@@ -282,6 +282,11 @@ class TargetFrameLowering {
return getFrameIndexReference(MF, FI, FrameReg);
}
+ /// Returns the callee-saved registers as computed by determineCalleeSaves
+ /// in the BitVector \p SavedRegs.
+ virtual void getCalleeSaves(const MachineFunction &MF,
+ BitVector &SavedRegs) const;
+
/// This method determines which of the registers reported by
/// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved.
/// The default implementation checks populates the \p SavedRegs bitset with
@@ -289,6 +294,9 @@ class TargetFrameLowering {
/// this function to save additional registers.
/// This method also sets up the register scavenger ensuring there is a free
/// register or a frameindex available.
+ /// This method should not be called by any passes outside of PEI, because
+ /// it may change state passed in by \p MF and \p RS. The preferred
+ /// interface outside PEI is getCalleeSaves.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS = nullptr) const;
@@ -367,17 +375,7 @@ class TargetFrameLowering {
/// Check if given function is safe for not having callee saved registers.
/// This is used when interprocedural register allocation is enabled.
- static bool isSafeForNoCSROpt(const Function &F) {
- if (!F.hasLocalLinkage() || F.hasAddressTaken() ||
- !F.hasFnAttribute(Attribute::NoRecurse))
- return false;
- // Function should not be optimized as tail call.
- for (const User *U : F.users())
- if (auto CS = ImmutableCallSite(U))
- if (CS.isTailCall())
- return false;
- return true;
- }
+ static bool isSafeForNoCSROpt(const Function &F);
/// Check if the no-CSR optimisation is profitable for the given function.
virtual bool isProfitableForNoCSROpt(const Function &F) const {
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 9c3757828563e..5011cf34c0ee2 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -23,7 +23,6 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineOutliner.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
@@ -39,10 +38,12 @@
namespace llvm {
+class AAResults;
class DFAPacketizer;
class InstrItineraryData;
class LiveIntervals;
class LiveVariables;
+class MachineLoop;
class MachineMemOperand;
class MachineRegisterInfo;
class MCAsmInfo;
@@ -95,7 +96,7 @@ class TargetInstrInfo : public MCInstrInfo {
/// registers so that the instructions result is independent of the place
/// in the function.
bool isTriviallyReMaterializable(const MachineInstr &MI,
- AliasAnalysis *AA = nullptr) const {
+ AAResults *AA = nullptr) const {
return MI.getOpcode() == TargetOpcode::IMPLICIT_DEF ||
(MI.getDesc().isRematerializable() &&
(isReallyTriviallyReMaterializable(MI, AA) ||
@@ -111,7 +112,7 @@ class TargetInstrInfo : public MCInstrInfo {
/// not always available.
/// Requirements must be check as stated in isTriviallyReMaterializable() .
virtual bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
- AliasAnalysis *AA) const {
+ AAResults *AA) const {
return false;
}
@@ -154,7 +155,7 @@ class TargetInstrInfo : public MCInstrInfo {
/// this function does target-independent tests to determine if the
/// instruction is really trivially rematerializable.
bool isReallyTriviallyReMaterializableGeneric(const MachineInstr &MI,
- AliasAnalysis *AA) const;
+ AAResults *AA) const;
public:
/// These methods return the opcode of the frame setup/destroy instructions
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 4ab61edec25fa..a58fca7e73f5b 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -28,7 +28,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Analysis/LegacyDivergenceAnalysis.h"
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
@@ -76,6 +75,7 @@ class GlobalValue;
class GISelKnownBits;
class IntrinsicInst;
struct KnownBits;
+class LegacyDivergenceAnalysis;
class LLVMContext;
class MachineBasicBlock;
class MachineFunction;
@@ -1357,9 +1357,9 @@ class TargetLoweringBase {
/// Certain targets have context senstive alignment requirements, where one
/// type has the alignment requirement of another type.
- virtual unsigned getABIAlignmentForCallingConv(Type *ArgTy,
- DataLayout DL) const {
- return DL.getABITypeAlignment(ArgTy);
+ virtual Align getABIAlignmentForCallingConv(Type *ArgTy,
+ DataLayout DL) const {
+ return Align(DL.getABITypeAlignment(ArgTy));
}
/// If true, then instruction selection should seek to shrink the FP constant
@@ -2608,6 +2608,12 @@ class TargetLoweringBase {
// same blocks of its users.
virtual bool shouldConsiderGEPOffsetSplit() const { return false; }
+ // Return the shift amount threshold for profitable transforms into shifts.
+ // Transforms creating shifts above the returned value will be avoided.
+ virtual unsigned getShiftAmountThreshold(EVT VT) const {
+ return VT.getScalarSizeInBits();
+ }
+
//===--------------------------------------------------------------------===//
// Runtime Library hooks
//
diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index 41062456343a9..1aafa3ca9f1d2 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -469,61 +469,61 @@ class DefRangeSubfieldSym : public SymbolRecord {
uint32_t RecordOffset = 0;
};
+struct DefRangeRegisterHeader {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
+};
+
// S_DEFRANGE_REGISTER
class DefRangeRegisterSym : public SymbolRecord {
public:
- struct Header {
- ulittle16_t Register;
- ulittle16_t MayHaveNoName;
- };
-
explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
explicit DefRangeRegisterSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
RecordOffset(RecordOffset) {}
- uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); }
- Header Hdr;
+ DefRangeRegisterHeader Hdr;
LocalVariableAddrRange Range;
std::vector Gaps;
uint32_t RecordOffset = 0;
};
+struct DefRangeSubfieldRegisterHeader {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
+ ulittle32_t OffsetInParent;
+};
+
// S_DEFRANGE_SUBFIELD_REGISTER
class DefRangeSubfieldRegisterSym : public SymbolRecord {
public:
- struct Header {
- ulittle16_t Register;
- ulittle16_t MayHaveNoName;
- ulittle32_t OffsetInParent;
- };
-
explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
RecordOffset(RecordOffset) {}
- uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); }
- Header Hdr;
+ DefRangeSubfieldRegisterHeader Hdr;
LocalVariableAddrRange Range;
std::vector Gaps;
uint32_t RecordOffset = 0;
};
+struct DefRangeFramePointerRelHeader {
+ little32_t Offset;
+};
+
// S_DEFRANGE_FRAMEPOINTER_REL
class DefRangeFramePointerRelSym : public SymbolRecord {
static constexpr uint32_t RelocationOffset = 8;
public:
- struct Header {
- little32_t Offset;
- };
-
explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
@@ -534,22 +534,22 @@ class DefRangeFramePointerRelSym : public SymbolRecord {
return RecordOffset + RelocationOffset;
}
- Header Hdr;
+ DefRangeFramePointerRelHeader Hdr;
LocalVariableAddrRange Range;
std::vector Gaps;
uint32_t RecordOffset = 0;
};
+struct DefRangeRegisterRelHeader {
+ ulittle16_t Register;
+ ulittle16_t Flags;
+ little32_t BasePointerOffset;
+};
+
// S_DEFRANGE_REGISTER_REL
class DefRangeRegisterRelSym : public SymbolRecord {
public:
- struct Header {
- ulittle16_t Register;
- ulittle16_t Flags;
- little32_t BasePointerOffset;
- };
-
explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
@@ -567,9 +567,9 @@ class DefRangeRegisterRelSym : public SymbolRecord {
bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
- uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); }
- Header Hdr;
+ DefRangeRegisterRelHeader Hdr;
LocalVariableAddrRange Range;
std::vector Gaps;
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 08fd269807a85..85093dd218f8c 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -25,7 +25,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
-#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -504,6 +503,13 @@ class DataLayout {
/// Returns the minimum ABI-required alignment for the specified type.
unsigned getABITypeAlignment(Type *Ty) const;
+ /// Helper function to return `Alignment` if it's set or the result of
+ /// `getABITypeAlignment(Ty)`, in any case the result is a valid alignment.
+ inline Align getValueOrABITypeAlignment(MaybeAlign Alignment,
+ Type *Ty) const {
+ return Alignment ? *Alignment : Align(getABITypeAlignment(Ty));
+ }
+
/// Returns the minimum ABI-required alignment for an integer type of
/// the specified bitwidth.
Align getABIIntegerTypeAlignment(unsigned BitWidth) const;
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index ade63764ebb1f..20097ef3f31a5 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -571,6 +571,10 @@ bool Type::getVectorIsScalable() const {
return cast(this)->isScalable();
}
+ElementCount Type::getVectorElementCount() const {
+ return cast(this)->getElementCount();
+}
+
/// Class to represent pointers.
class PointerType : public Type {
explicit PointerType(Type *ElType, unsigned AddrSpace);
@@ -618,6 +622,16 @@ Type *Type::getExtendedType() const {
return cast(this)->getExtendedType();
}
+Type *Type::getWithNewBitWidth(unsigned NewBitWidth) const {
+ assert(
+ isIntOrIntVectorTy() &&
+ "Original type expected to be a vector of integers or a scalar integer.");
+ Type *NewType = getIntNTy(getContext(), NewBitWidth);
+ if (isVectorTy())
+ NewType = VectorType::get(NewType, getVectorElementCount());
+ return NewType;
+}
+
unsigned Type::getPointerAddressSpace() const {
return cast(getScalarType())->getAddressSpace();
}
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 25febbfa1e23f..d1ddb75cde9b8 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -1461,7 +1461,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
if (Value *V = foldConstant(Opc, LHS, RHS, Name)) return V;
Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS);
if (isa(BinOp))
- BinOp = setFPAttrs(BinOp, FPMathTag, FMF);
+ setFPAttrs(BinOp, FPMathTag, FMF);
return Insert(BinOp, Name);
}
@@ -1479,7 +1479,8 @@ class IRBuilder : public IRBuilderBase, public Inserter {
CallInst *C = CreateIntrinsic(ID, {L->getType()},
{L, R, RoundingV, ExceptV}, nullptr, Name);
- return cast(setFPAttrs(C, FPMathTag, UseFMF));
+ setFPAttrs(C, FPMathTag, UseFMF);
+ return C;
}
Value *CreateNeg(Value *V, const Twine &Name = "",
@@ -1532,7 +1533,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
return Insert(Folder.CreateUnOp(Opc, VC), Name);
Instruction *UnOp = UnaryOperator::Create(Opc, V);
if (isa(UnOp))
- UnOp = setFPAttrs(UnOp, FPMathTag, FMF);
+ setFPAttrs(UnOp, FPMathTag, FMF);
return Insert(UnOp, Name);
}
@@ -2084,7 +2085,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
break;
}
if (isa(C))
- C = cast(setFPAttrs(C, FPMathTag, UseFMF));
+ setFPAttrs(C, FPMathTag, UseFMF);
return C;
}
@@ -2231,7 +2232,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
const Twine &Name = "") {
PHINode *Phi = PHINode::Create(Ty, NumReservedValues);
if (isa(Phi))
- Phi = cast(setFPAttrs(Phi, nullptr /* MDNode* */, FMF));
+ setFPAttrs(Phi, nullptr /* MDNode* */, FMF);
return Insert(Phi, Name);
}
@@ -2240,7 +2241,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
MDNode *FPMathTag = nullptr) {
CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
if (isa(CI))
- CI = cast(setFPAttrs(CI, FPMathTag, FMF));
+ setFPAttrs(CI, FPMathTag, FMF);
return Insert(CI, Name);
}
@@ -2249,7 +2250,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles);
if (isa(CI))
- CI = cast(setFPAttrs(CI, FPMathTag, FMF));
+ setFPAttrs(CI, FPMathTag, FMF);
return Insert(CI, Name);
}
@@ -2297,7 +2298,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
Sel = addBranchMetadata(Sel, Prof, Unpred);
}
if (isa(Sel))
- Sel = cast(setFPAttrs(Sel, nullptr /* MDNode* */, FMF));
+ setFPAttrs(Sel, nullptr /* MDNode* */, FMF);
return Insert(Sel, Name);
}
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index eaaf506464620..1e29d2cd361d1 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -5283,12 +5283,12 @@ inline Value *getPointerOperand(Value *V) {
}
/// A helper function that returns the alignment of load or store instruction.
-inline unsigned getLoadStoreAlignment(Value *I) {
+inline MaybeAlign getLoadStoreAlignment(Value *I) {
assert((isa(I) || isa(I)) &&
"Expected Load or Store instruction");
if (auto *LI = dyn_cast(I))
- return LI->getAlignment();
- return cast(I)->getAlignment();
+ return MaybeAlign(LI->getAlignment());
+ return MaybeAlign(cast(I)->getAlignment());
}
/// A helper function that returns the address space of the pointer operand of
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index f458680cfe15d..59331142766ae 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -46,6 +46,7 @@ class FunctionType;
class GVMaterializer;
class LLVMContext;
class MemoryBuffer;
+class Pass;
class RandomNumberGenerator;
template class SmallPtrSetImpl;
class StructType;
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 965c01b167ccb..1e1f4a92f844c 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -45,6 +45,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/IR/PassManagerInternal.h"
+#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TypeName.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 63bc884f0b7d4..d0961dac833d6 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -372,6 +372,7 @@ class Type {
inline bool getVectorIsScalable() const;
inline unsigned getVectorNumElements() const;
+ inline ElementCount getVectorElementCount() const;
Type *getVectorElementType() const {
assert(getTypeID() == VectorTyID);
return ContainedTys[0];
@@ -382,6 +383,10 @@ class Type {
return ContainedTys[0];
}
+ /// Given an integer or vector type, change the lane bitwidth to NewBitwidth,
+ /// whilst keeping the old number of lanes.
+ inline Type *getWithNewBitWidth(unsigned NewBitWidth) const;
+
/// Given scalar/vector integer type, returns a type with elements twice as
/// wide as in the original type. For vectors, preserves element count.
inline Type *getExtendedType() const;
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index c703afe223a2d..6b48580ae57cf 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -18,7 +18,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCSymbol.h"
@@ -55,6 +54,13 @@ class MCSubtargetInfo;
class raw_ostream;
class Twine;
+namespace codeview {
+struct DefRangeRegisterRelHeader;
+struct DefRangeSubfieldRegisterHeader;
+struct DefRangeRegisterHeader;
+struct DefRangeFramePointerRelHeader;
+}
+
using MCSectionSubPair = std::pair;
/// Target specific streamer interface. This is used so that targets can
@@ -873,19 +879,19 @@ class MCStreamer {
virtual void EmitCVDefRangeDirective(
ArrayRef> Ranges,
- codeview::DefRangeRegisterRelSym::Header DRHdr);
+ codeview::DefRangeRegisterRelHeader DRHdr);
virtual void EmitCVDefRangeDirective(
ArrayRef> Ranges,
- codeview::DefRangeSubfieldRegisterSym::Header DRHdr);
+ codeview::DefRangeSubfieldRegisterHeader DRHdr);
virtual void EmitCVDefRangeDirective(
ArrayRef> Ranges,
- codeview::DefRangeRegisterSym::Header DRHdr);
+ codeview::DefRangeRegisterHeader DRHdr);
virtual void EmitCVDefRangeDirective(
ArrayRef> Ranges,
- codeview::DefRangeFramePointerRelSym::Header DRHdr);
+ codeview::DefRangeFramePointerRelHeader DRHdr);
/// This implements the CodeView '.cv_stringtable' assembler directive.
virtual void EmitCVStringTableDirective() {}
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 774d8c3ef3c5b..424289a9ccaa7 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -288,7 +288,8 @@ template class ELFObjectFile : public ELFObjectFileBase {
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
std::vector dynamic_relocation_sections() const override;
- section_iterator getRelocatedSection(DataRefImpl Sec) const override;
+ Expected
+ getRelocatedSection(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
uint64_t getRelocationOffset(DataRefImpl Rel) const override;
@@ -841,7 +842,7 @@ ELFObjectFile::section_rel_end(DataRefImpl Sec) const {
}
template
-section_iterator
+Expected
ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const {
if (EF.getHeader()->e_type != ELF::ET_REL)
return section_end();
@@ -851,10 +852,10 @@ ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const {
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
return section_end();
- auto R = EF.getSection(EShdr->sh_info);
- if (!R)
- report_fatal_error(errorToErrorCode(R.takeError()).message());
- return section_iterator(SectionRef(toDRI(*R), this));
+ Expected SecOrErr = EF.getSection(EShdr->sh_info);
+ if (!SecOrErr)
+ return SecOrErr.takeError();
+ return section_iterator(SectionRef(toDRI(*SecOrErr), this));
}
// Relocations
diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h
index 63c556b7f0d9a..adc9dbc189af7 100644
--- a/llvm/include/llvm/Object/ObjectFile.h
+++ b/llvm/include/llvm/Object/ObjectFile.h
@@ -130,7 +130,7 @@ class SectionRef {
iterator_range relocations() const {
return make_range(relocation_begin(), relocation_end());
}
- section_iterator getRelocatedSection() const;
+ Expected getRelocatedSection() const;
DataRefImpl getRawDataRefImpl() const;
const ObjectFile *getObject() const;
@@ -272,7 +272,7 @@ class ObjectFile : public SymbolicFile {
virtual bool isBerkeleyData(DataRefImpl Sec) const;
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
- virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
+ virtual Expected getRelocatedSection(DataRefImpl Sec) const;
// Same as above for RelocationRef.
friend class RelocationRef;
@@ -501,7 +501,7 @@ inline relocation_iterator SectionRef::relocation_end() const {
return OwningObject->section_rel_end(SectionPimpl);
}
-inline section_iterator SectionRef::getRelocatedSection() const {
+inline Expected