Merge ^/vendor/llvm-project/release-10.x up to its last change (upstream

commit llvmorg-10.0.0-rc2-0-g90c78073f73), bump versions, and update
build glue.
This commit is contained in:
Dimitry Andric 2020-02-15 14:58:40 +00:00
commit 13138422bc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang1000-import/; revision=357964
161 changed files with 2874 additions and 1379 deletions

View File

@ -29,14 +29,14 @@ class ConceptSpecializationExpr;
class ConstraintSatisfaction : public llvm::FoldingSetNode {
// The template-like entity that 'owns' the constraint checked here (can be a
// constrained entity or a concept).
NamedDecl *ConstraintOwner = nullptr;
const NamedDecl *ConstraintOwner = nullptr;
llvm::SmallVector<TemplateArgument, 4> TemplateArgs;
public:
ConstraintSatisfaction() = default;
ConstraintSatisfaction(NamedDecl *ConstraintOwner,
ConstraintSatisfaction(const NamedDecl *ConstraintOwner,
ArrayRef<TemplateArgument> TemplateArgs) :
ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(),
TemplateArgs.end()) { }
@ -57,7 +57,7 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
}
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
NamedDecl *ConstraintOwner,
const NamedDecl *ConstraintOwner,
ArrayRef<TemplateArgument> TemplateArgs);
};

View File

@ -63,6 +63,12 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction);
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
bool ContainsUnexpandedParameterPack);
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
public:
@ -75,6 +81,13 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction);
static ConceptSpecializationExpr *
Create(const ASTContext &C, ConceptDecl *NamedConcept,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
bool ContainsUnexpandedParameterPack);
static ConceptSpecializationExpr *
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);

View File

@ -11,6 +11,7 @@
namespace llvm {
class StringRef;
class Twine;
class VersionTuple;
} // namespace llvm
@ -30,7 +31,7 @@ enum class CudaVersion {
};
const char *CudaVersionToString(CudaVersion V);
// Input is "Major.Minor"
CudaVersion CudaStringToVersion(llvm::StringRef S);
CudaVersion CudaStringToVersion(const llvm::Twine &S);
enum class CudaArch {
UNKNOWN,

View File

@ -60,6 +60,9 @@ def err_drv_cuda_version_unsupported : Error<
"but installation at %3 is %4. Use --cuda-path to specify a different CUDA "
"install, pass a different GPU arch with --cuda-gpu-arch, or pass "
"--no-cuda-version-check.">;
def warn_drv_unknown_cuda_version: Warning<
"Unknown CUDA version %0. Assuming the latest supported version %1">,
InGroup<CudaUnknownVersion>;
def err_drv_cuda_host_arch : Error<"unsupported architecture '%0' for host compilation.">;
def err_drv_mix_cuda_hip : Error<"Mixed Cuda and HIP compilation is not supported.">;
def err_drv_invalid_thread_model_for_target : Error<

View File

@ -384,7 +384,10 @@ def GNULabelsAsValue : DiagGroup<"gnu-label-as-value">;
def LiteralRange : DiagGroup<"literal-range">;
def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args",
[CXX98CompatLocalTypeTemplateArgs]>;
def RangeLoopAnalysis : DiagGroup<"range-loop-analysis">;
def RangeLoopConstruct : DiagGroup<"range-loop-construct">;
def RangeLoopBindReference : DiagGroup<"range-loop-bind-reference">;
def RangeLoopAnalysis : DiagGroup<"range-loop-analysis",
[RangeLoopConstruct, RangeLoopBindReference]>;
def ForLoopAnalysis : DiagGroup<"for-loop-analysis">;
def LoopAnalysis : DiagGroup<"loop-analysis", [ForLoopAnalysis,
RangeLoopAnalysis]>;
@ -858,14 +861,15 @@ def Most : DiagGroup<"most", [
Comment,
DeleteNonVirtualDtor,
Format,
ForLoopAnalysis,
Implicit,
InfiniteRecursion,
IntInBoolContext,
LoopAnalysis,
MismatchedTags,
MissingBraces,
Move,
MultiChar,
RangeLoopConstruct,
Reorder,
ReturnType,
SelfAssignment,
@ -1113,6 +1117,9 @@ def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">;
// compiling CUDA C/C++ but which is not compatible with the CUDA spec.
def CudaCompat : DiagGroup<"cuda-compat">;
// Warning about unknown CUDA SDK version.
def CudaUnknownVersion: DiagGroup<"unknown-cuda-version">;
// A warning group for warnings about features supported by HIP but
// ignored by CUDA.
def HIPOnly : DiagGroup<"hip-only">;

View File

@ -2378,17 +2378,17 @@ def warn_for_range_const_reference_copy : Warning<
"loop variable %0 "
"%diff{has type $ but is initialized with type $"
"| is initialized with a value of a different type}1,2 resulting in a copy">,
InGroup<RangeLoopAnalysis>, DefaultIgnore;
InGroup<RangeLoopConstruct>, DefaultIgnore;
def note_use_type_or_non_reference : Note<
"use non-reference type %0 to keep the copy or type %1 to prevent copying">;
def warn_for_range_variable_always_copy : Warning<
"loop variable %0 is always a copy because the range of type %1 does not "
"return a reference">,
InGroup<RangeLoopAnalysis>, DefaultIgnore;
InGroup<RangeLoopBindReference>, DefaultIgnore;
def note_use_non_reference_type : Note<"use non-reference type %0">;
def warn_for_range_copy : Warning<
"loop variable %0 of type %1 creates a copy from type %2">,
InGroup<RangeLoopAnalysis>, DefaultIgnore;
InGroup<RangeLoopConstruct>, DefaultIgnore;
def note_use_reference_type : Note<"use reference type %0 to prevent copying">;
def err_objc_for_range_init_stmt : Error<
"initialization statement is not supported when iterating over Objective-C "
@ -4683,6 +4683,8 @@ def note_checking_constraints_for_var_spec_id_here : Note<
def note_checking_constraints_for_class_spec_id_here : Note<
"while checking constraint satisfaction for class template partial "
"specialization '%0' required here">;
def note_checking_constraints_for_function_here : Note<
"while checking constraint satisfaction for function '%0' required here">;
def note_constraint_substitution_here : Note<
"while substituting template arguments into constraint expression here">;
def note_constraint_normalization_here : Note<
@ -6746,6 +6748,10 @@ def err_bad_cxx_cast_scalar_to_vector_different_size : Error<
def err_bad_cxx_cast_vector_to_vector_different_size : Error<
"%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
"to vector %2 of different size">;
def warn_bad_cxx_cast_nested_pointer_addr_space : Warning<
"%select{reinterpret_cast|C-style cast}0 from %1 to %2 "
"changes address space of nested pointers">,
InGroup<IncompatiblePointerTypesDiscardsQualifiers>;
def err_bad_lvalue_to_rvalue_cast : Error<
"cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
"not compatible">;
@ -8390,6 +8396,12 @@ def note_defaulted_comparison_cannot_deduce : Note<
"return type of defaulted 'operator<=>' cannot be deduced because "
"return type %2 of three-way comparison for %select{|member|base class}0 %1 "
"is not a standard comparison category type">;
def err_defaulted_comparison_cannot_deduce_undeduced_auto : Error<
"return type of defaulted 'operator<=>' cannot be deduced because "
"three-way comparison for %select{|member|base class}0 %1 "
"has a deduced return type and is not yet defined">;
def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
"%select{|member|base class}0 %1 declared here">;
def note_defaulted_comparison_cannot_deduce_callee : Note<
"selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
def err_incorrect_defaulted_comparison_constexpr : Error<

View File

@ -859,6 +859,8 @@ def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">
HelpText<"include a detailed record of preprocessing actions">;
def setup_static_analyzer : Flag<["-"], "setup-static-analyzer">,
HelpText<"Set up preprocessor for static analyzer (done automatically when static analyzer is run).">;
def disable_pragma_debug_crash : Flag<["-"], "disable-pragma-debug-crash">,
HelpText<"Disable any #pragma clang __debug that can lead to crashing behavior. This is meant for testing.">;
//===----------------------------------------------------------------------===//
// OpenCL Options

View File

@ -55,9 +55,6 @@ class Command {
/// The list of program arguments which are inputs.
llvm::opt::ArgStringList InputFilenames;
/// Whether to print the input filenames when executing.
bool PrintInputFilenames = false;
/// Response file name, if this command is set to use one, or nullptr
/// otherwise
const char *ResponseFile = nullptr;
@ -86,6 +83,12 @@ class Command {
void writeResponseFile(raw_ostream &OS) const;
public:
/// Whether to print the input filenames when executing.
bool PrintInputFilenames = false;
/// Whether the command will be executed in this process or not.
bool InProcess = false;
Command(const Action &Source, const Tool &Creator, const char *Executable,
const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs);
@ -128,9 +131,6 @@ class Command {
/// Print a command argument, and optionally quote it.
static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
/// Set whether to print the input filenames when executing.
void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
protected:
/// Optionally print the filenames to be compiled
void PrintFileNames() const;
@ -139,7 +139,9 @@ class Command {
/// Use the CC1 tool callback when available, to avoid creating a new process
class CC1Command : public Command {
public:
using Command::Command;
CC1Command(const Action &Source, const Tool &Creator, const char *Executable,
const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs);
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const override;

View File

@ -189,6 +189,9 @@ class PreprocessorOptions {
/// Set up preprocessor for RunAnalysis action.
bool SetUpStaticAnalyzer = false;
/// Prevents intended crashes when using #pragma clang __debug. For testing.
bool DisablePragmaDebugCrash = false;
public:
PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}

View File

@ -6275,7 +6275,7 @@ class Sema final {
/// \returns true if an error occurred and satisfaction could not be checked,
/// false otherwise.
bool CheckConstraintSatisfaction(
NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
@ -6288,6 +6288,17 @@ class Sema final {
bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
ConstraintSatisfaction &Satisfaction);
/// Check whether the given function decl's trailing requires clause is
/// satisfied, if any. Returns false and updates Satisfaction with the
/// satisfaction verdict if successful, emits a diagnostic and returns true if
/// an error occured and satisfaction could not be determined.
///
/// \returns true if an error occurred, false otherwise.
bool CheckFunctionConstraints(const FunctionDecl *FD,
ConstraintSatisfaction &Satisfaction,
SourceLocation UsageLoc = SourceLocation());
/// \brief Ensure that the given template arguments satisfy the constraints
/// associated with the given template, emitting a diagnostic if they do not.
///
@ -6986,7 +6997,7 @@ class Sema final {
/// Get a template argument mapping the given template parameter to itself,
/// e.g. for X in \c template<int X>, this would return an expression template
/// argument referencing X.
TemplateArgumentLoc getIdentityTemplateArgumentLoc(Decl *Param,
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param,
SourceLocation Location);
void translateTemplateArguments(const ASTTemplateArgsPtr &In,

View File

@ -43,11 +43,15 @@ struct AtomicConstraint {
if (ParameterMapping->size() != Other.ParameterMapping->size())
return false;
for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I)
if (!C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
.structurallyEquals(C.getCanonicalTemplateArgument(
(*Other.ParameterMapping)[I].getArgument())))
for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I) {
llvm::FoldingSetNodeID IDA, IDB;
C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
.Profile(IDA, C);
C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
.Profile(IDB, C);
if (IDA != IDB)
return false;
}
return true;
}

View File

@ -59,8 +59,8 @@ ASTConstraintSatisfaction::Create(const ASTContext &C,
}
void ConstraintSatisfaction::Profile(
llvm::FoldingSetNodeID &ID, const ASTContext &C, NamedDecl *ConstraintOwner,
ArrayRef<TemplateArgument> TemplateArgs) {
llvm::FoldingSetNodeID &ID, const ASTContext &C,
const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
ID.AddPointer(ConstraintOwner);
ID.AddInteger(TemplateArgs.size());
for (auto &Arg : TemplateArgs)

View File

@ -756,12 +756,8 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC,
NewConverted.push_back(Arg);
}
Expr *NewIDC = ConceptSpecializationExpr::Create(
C, NestedNameSpecifierLoc(), /*TemplateKWLoc=*/SourceLocation(),
CSE->getConceptNameInfo(), /*FoundDecl=*/CSE->getNamedConcept(),
CSE->getNamedConcept(),
// Actually canonicalizing a TemplateArgumentLoc is difficult so we
// simply omit the ArgsAsWritten
/*ArgsAsWritten=*/nullptr, NewConverted, nullptr);
C, CSE->getNamedConcept(), NewConverted, nullptr,
CSE->isInstantiationDependent(), CSE->containsUnexpandedParameterPack());
if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
NewIDC = new (C) CXXFoldExpr(OrigFold->getType(), SourceLocation(), NewIDC,

View File

@ -758,6 +758,8 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
return false;
};
// FIXME: IsHidden reads from Overriding from the middle of a remove_if
// over the same sequence! Is this guaranteed to work?
Overriding.erase(
std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
Overriding.end());

View File

@ -2038,17 +2038,36 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
if (auto *MD = getCorrespondingMethodDeclaredInClass(RD, MayBeBase))
return MD;
llvm::SmallVector<CXXMethodDecl*, 4> FinalOverriders;
auto AddFinalOverrider = [&](CXXMethodDecl *D) {
// If this function is overridden by a candidate final overrider, it is not
// a final overrider.
for (CXXMethodDecl *OtherD : FinalOverriders) {
if (declaresSameEntity(D, OtherD) || recursivelyOverrides(OtherD, D))
return;
}
// Other candidate final overriders might be overridden by this function.
FinalOverriders.erase(
std::remove_if(FinalOverriders.begin(), FinalOverriders.end(),
[&](CXXMethodDecl *OtherD) {
return recursivelyOverrides(D, OtherD);
}),
FinalOverriders.end());
FinalOverriders.push_back(D);
};
for (const auto &I : RD->bases()) {
const RecordType *RT = I.getType()->getAs<RecordType>();
if (!RT)
continue;
const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base);
if (T)
return T;
if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base))
AddFinalOverrider(D);
}
return nullptr;
return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr;
}
CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
@ -2105,6 +2124,11 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
CXXMethodDecl *DevirtualizedMethod =
getCorrespondingMethodInClass(BestDynamicDecl);
// If there final overrider in the dynamic type is ambiguous, we can't
// devirtualize this call.
if (!DevirtualizedMethod)
return nullptr;
// If that method is pure virtual, we can't devirtualize. If this code is
// reached, the result would be UB, not a direct call to the derived class
// function, and we can't assume the derived class function is defined.

View File

@ -1685,6 +1685,11 @@ MemberExpr *MemberExpr::Create(
CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC))
E->setTypeDependent(T->isDependentType());
// Bitfield with value-dependent width is type-dependent.
FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl);
if (FD && FD->isBitField() && FD->getBitWidth()->isValueDependent())
E->setTypeDependent(true);
}
if (HasQualOrFound) {

View File

@ -46,24 +46,12 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C,
ASTConstraintSatisfaction::Create(C, *Satisfaction) :
nullptr) {
setTemplateArguments(ConvertedArgs);
}
ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
unsigned NumTemplateArgs)
: Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
NumTemplateArgs(NumTemplateArgs) { }
void ConceptSpecializationExpr::setTemplateArguments(
ArrayRef<TemplateArgument> Converted) {
assert(Converted.size() == NumTemplateArgs);
std::uninitialized_copy(Converted.begin(), Converted.end(),
getTrailingObjects<TemplateArgument>());
bool IsInstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
for (const TemplateArgument& Arg : Converted) {
if (Arg.isInstantiationDependent())
for (const TemplateArgumentLoc& ArgLoc : ArgsAsWritten->arguments()) {
if (ArgLoc.getArgument().isInstantiationDependent())
IsInstantiationDependent = true;
if (Arg.containsUnexpandedParameterPack())
if (ArgLoc.getArgument().containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
break;
@ -80,6 +68,18 @@ void ConceptSpecializationExpr::setTemplateArguments(
"should not be value-dependent");
}
ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
unsigned NumTemplateArgs)
: Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
NumTemplateArgs(NumTemplateArgs) { }
void ConceptSpecializationExpr::setTemplateArguments(
ArrayRef<TemplateArgument> Converted) {
assert(Converted.size() == NumTemplateArgs);
std::uninitialized_copy(Converted.begin(), Converted.end(),
getTrailingObjects<TemplateArgument>());
}
ConceptSpecializationExpr *
ConceptSpecializationExpr::Create(const ASTContext &C,
NestedNameSpecifierLoc NNS,
@ -98,6 +98,39 @@ ConceptSpecializationExpr::Create(const ASTContext &C,
ConvertedArgs, Satisfaction);
}
ConceptSpecializationExpr::ConceptSpecializationExpr(
const ASTContext &C, ConceptDecl *NamedConcept,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack)
: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
/*TypeDependent=*/false,
/*ValueDependent=*/!Satisfaction, Dependent,
ContainsUnexpandedParameterPack),
ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
DeclarationNameInfo(), NamedConcept,
NamedConcept, nullptr),
NumTemplateArgs(ConvertedArgs.size()),
Satisfaction(Satisfaction ?
ASTConstraintSatisfaction::Create(C, *Satisfaction) :
nullptr) {
setTemplateArguments(ConvertedArgs);
}
ConceptSpecializationExpr *
ConceptSpecializationExpr::Create(const ASTContext &C,
ConceptDecl *NamedConcept,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
bool ContainsUnexpandedParameterPack) {
void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
ConvertedArgs.size()));
return new (Buffer) ConceptSpecializationExpr(
C, NamedConcept, ConvertedArgs, Satisfaction, Dependent,
ContainsUnexpandedParameterPack);
}
ConceptSpecializationExpr *
ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
unsigned NumTemplateArgs) {

View File

@ -1535,8 +1535,8 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
return Stmt::BinaryOperatorClass;
case OO_Spaceship:
// FIXME: Update this once we support <=> expressions.
llvm_unreachable("<=> expressions not supported yet");
BinaryOp = BO_Cmp;
return Stmt::BinaryOperatorClass;
case OO_AmpAmp:
BinaryOp = BO_LAnd;

View File

@ -2,6 +2,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
@ -31,8 +32,8 @@ const char *CudaVersionToString(CudaVersion V) {
llvm_unreachable("invalid enum");
}
CudaVersion CudaStringToVersion(llvm::StringRef S) {
return llvm::StringSwitch<CudaVersion>(S)
CudaVersion CudaStringToVersion(const llvm::Twine &S) {
return llvm::StringSwitch<CudaVersion>(S.str())
.Case("7.0", CudaVersion::CUDA_70)
.Case("7.5", CudaVersion::CUDA_75)
.Case("8.0", CudaVersion::CUDA_80)
@ -40,7 +41,8 @@ CudaVersion CudaStringToVersion(llvm::StringRef S) {
.Case("9.1", CudaVersion::CUDA_91)
.Case("9.2", CudaVersion::CUDA_92)
.Case("10.0", CudaVersion::CUDA_100)
.Case("10.1", CudaVersion::CUDA_101);
.Case("10.1", CudaVersion::CUDA_101)
.Default(CudaVersion::UNKNOWN);
}
const char *CudaArchToString(CudaArch A) {

View File

@ -537,6 +537,13 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
}
if (Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64) {
StringRef ABIStr = Target.getABI();
llvm::LLVMContext &Ctx = TheModule.getContext();
getModule().addModuleFlag(llvm::Module::Error, "target-abi",
llvm::MDString::get(Ctx, ABIStr));
}
if (CodeGenOpts.SanitizeCfiCrossDso) {
// Indicate that we want cross-DSO control flow integrity checks.
getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1);

View File

@ -258,14 +258,23 @@ void Compilation::initCompilationForDiagnostics() {
// Remove any user specified output. Claim any unclaimed arguments, so as
// to avoid emitting warnings about unused args.
OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
options::OPT_MMD };
OptSpecifier OutputOpts[] = {
options::OPT_o, options::OPT_MD, options::OPT_MMD, options::OPT_M,
options::OPT_MM, options::OPT_MF, options::OPT_MG, options::OPT_MJ,
options::OPT_MQ, options::OPT_MT, options::OPT_MV};
for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
if (TranslatedArgs->hasArg(OutputOpts[i]))
TranslatedArgs->eraseArg(OutputOpts[i]);
}
TranslatedArgs->ClaimAllArgs();
// Force re-creation of the toolchain Args, otherwise our modifications just
// above will have no effect.
for (auto Arg : TCArgs)
if (Arg.second != TranslatedArgs)
delete Arg.second;
TCArgs.clear();
// Redirect stdout/stderr to /dev/null.
Redirects = {None, {""}, {""}};

View File

@ -3757,6 +3757,11 @@ void Driver::BuildJobs(Compilation &C) const {
/*TargetDeviceOffloadKind*/ Action::OFK_None);
}
// If we have more than one job, then disable integrated-cc1 for now.
if (C.getJobs().size() > 1)
for (auto &J : C.getJobs())
J.InProcess = false;
// If the user passed -Qunused-arguments or there were errors, don't warn
// about any unused arguments.
if (Diags.hasErrorOccurred() ||

View File

@ -371,14 +371,29 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}
CC1Command::CC1Command(const Action &Source, const Tool &Creator,
const char *Executable,
const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs)
: Command(Source, Creator, Executable, Arguments, Inputs) {
InProcess = true;
}
void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo) const {
OS << " (in-process)\n";
if (InProcess)
OS << " (in-process)\n";
Command::Print(OS, Terminator, Quote, CrashInfo);
}
int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> /*Redirects*/,
int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
std::string *ErrMsg, bool *ExecutionFailed) const {
// FIXME: Currently, if there're more than one job, we disable
// -fintegrate-cc1. If we're no longer a integrated-cc1 job, fallback to
// out-of-process execution. See discussion in https://reviews.llvm.org/D74447
if (!InProcess)
return Command::Execute(Redirects, ErrMsg, ExecutionFailed);
PrintFileNames();
SmallVector<const char *, 128> Argv;

View File

@ -4679,6 +4679,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
: "-");
}
// Give the gen diagnostics more chances to succeed, by avoiding intentional
// crashes.
if (D.CCGenDiagnostics)
CmdArgs.push_back("-disable-pragma-debug-crash");
bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
@ -6048,7 +6053,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Output.getType() == types::TY_Object &&
Args.hasFlag(options::OPT__SLASH_showFilenames,
options::OPT__SLASH_showFilenames_, false)) {
C.getJobs().getJobs().back()->setPrintInputFilenames(true);
C.getJobs().getJobs().back()->PrintInputFilenames = true;
}
if (Arg *A = Args.getLastArg(options::OPT_pg))

View File

@ -32,37 +32,24 @@ using namespace llvm::opt;
// Parses the contents of version.txt in an CUDA installation. It should
// contain one line of the from e.g. "CUDA Version 7.5.2".
static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
static CudaVersion ParseCudaVersionFile(const Driver &D, llvm::StringRef V) {
if (!V.startswith("CUDA Version "))
return CudaVersion::UNKNOWN;
V = V.substr(strlen("CUDA Version "));
int Major = -1, Minor = -1;
auto First = V.split('.');
auto Second = First.second.split('.');
if (First.first.getAsInteger(10, Major) ||
Second.first.getAsInteger(10, Minor))
SmallVector<StringRef,4> VersionParts;
V.split(VersionParts, '.');
if (VersionParts.size() < 2)
return CudaVersion::UNKNOWN;
std::string MajorMinor = join_items(".", VersionParts[0], VersionParts[1]);
CudaVersion Version = CudaStringToVersion(MajorMinor);
if (Version != CudaVersion::UNKNOWN)
return Version;
if (Major == 7 && Minor == 0) {
// This doesn't appear to ever happen -- version.txt doesn't exist in the
// CUDA 7 installs I've seen. But no harm in checking.
return CudaVersion::CUDA_70;
}
if (Major == 7 && Minor == 5)
return CudaVersion::CUDA_75;
if (Major == 8 && Minor == 0)
return CudaVersion::CUDA_80;
if (Major == 9 && Minor == 0)
return CudaVersion::CUDA_90;
if (Major == 9 && Minor == 1)
return CudaVersion::CUDA_91;
if (Major == 9 && Minor == 2)
return CudaVersion::CUDA_92;
if (Major == 10 && Minor == 0)
return CudaVersion::CUDA_100;
if (Major == 10 && Minor == 1)
return CudaVersion::CUDA_101;
return CudaVersion::UNKNOWN;
// Issue a warning and assume that the version we've found is compatible with
// the latest version we support.
D.Diag(diag::warn_drv_unknown_cuda_version)
<< MajorMinor << CudaVersionToString(CudaVersion::LATEST);
return CudaVersion::LATEST;
}
CudaInstallationDetector::CudaInstallationDetector(
@ -160,7 +147,7 @@ CudaInstallationDetector::CudaInstallationDetector(
// version.txt isn't present.
Version = CudaVersion::CUDA_70;
} else {
Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
Version = ParseCudaVersionFile(D, (*VersionFile)->getBuffer());
}
if (Version >= CudaVersion::CUDA_90) {

View File

@ -3440,6 +3440,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.LexEditorPlaceholders = false;
Opts.SetUpStaticAnalyzer = Args.hasArg(OPT_setup_static_analyzer);
Opts.DisablePragmaDebugCrash = Args.hasArg(OPT_disable_pragma_debug_crash);
}
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,

View File

@ -45,7 +45,7 @@
_Static_assert(sizeof(__val) == sizeof(__Bits)); \
_Static_assert(sizeof(__Bits) == 2 * sizeof(int)); \
__Bits __tmp; \
memcpy(&__val, &__tmp, sizeof(__val)); \
memcpy(&__tmp, &__val, sizeof(__val)); \
__tmp.__a = ::__FnName(__tmp.__a, __offset, __width); \
__tmp.__b = ::__FnName(__tmp.__b, __offset, __width); \
long long __ret; \
@ -129,7 +129,7 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f,
_Static_assert(sizeof(__val) == sizeof(__Bits)); \
_Static_assert(sizeof(__Bits) == 2 * sizeof(int)); \
__Bits __tmp; \
memcpy(&__val, &__tmp, sizeof(__val)); \
memcpy(&__tmp, &__val, sizeof(__val)); \
__tmp.__a = ::__FnName(__mask, __tmp.__a, __offset, __width); \
__tmp.__b = ::__FnName(__mask, __tmp.__b, __offset, __width); \
long long __ret; \

View File

@ -48,7 +48,7 @@
#include "cuda.h"
#if !defined(CUDA_VERSION)
#error "cuda.h did not define CUDA_VERSION"
#elif CUDA_VERSION < 7000 || CUDA_VERSION > 10010
#elif CUDA_VERSION < 7000
#error "Unsupported CUDA version!"
#endif

View File

@ -2181,7 +2181,7 @@ void _mm_sfence(void);
/// 3: Bits [63:48] are copied to the destination.
/// \returns A 16-bit integer containing the extracted 16 bits of packed data.
#define _mm_extract_pi16(a, n) \
(int)__builtin_ia32_vec_ext_v4hi((__m64)a, (int)n)
(int)__builtin_ia32_vec_ext_v4hi((__v4hi)a, (int)n)
/// Copies data from the 64-bit vector of [4 x i16] to the destination,
/// and inserts the lower 16-bits of an integer operand at the 16-bit offset
@ -2212,7 +2212,7 @@ void _mm_sfence(void);
/// \returns A 64-bit integer vector containing the copied packed data from the
/// operands.
#define _mm_insert_pi16(a, d, n) \
(__m64)__builtin_ia32_vec_set_v4hi((__m64)a, (int)d, (int)n)
(__m64)__builtin_ia32_vec_set_v4hi((__v4hi)a, (int)d, (int)n)
/// Compares each of the corresponding packed 16-bit integer values of
/// the 64-bit integer vectors, and writes the greater value to the

View File

@ -2552,8 +2552,8 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr,
'/', '/', '/', '/', '/', '/', '/', '/',
'/', '/', '/', '/', '/', '/', '/', '/'
};
while (CurPtr+16 <= BufferEnd &&
!vec_any_eq(*(const vector unsigned char*)CurPtr, Slashes))
while (CurPtr + 16 <= BufferEnd &&
!vec_any_eq(*(const __vector unsigned char *)CurPtr, Slashes))
CurPtr += 16;
#else
// Scan for '/' quickly. Many block comments are very large.

View File

@ -30,6 +30,7 @@
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorLexer.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
@ -39,7 +40,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@ -1035,15 +1035,19 @@ struct PragmaDebugHandler : public PragmaHandler {
IdentifierInfo *II = Tok.getIdentifierInfo();
if (II->isStr("assert")) {
llvm_unreachable("This is an assertion!");
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
llvm_unreachable("This is an assertion!");
} else if (II->isStr("crash")) {
LLVM_BUILTIN_TRAP;
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
LLVM_BUILTIN_TRAP;
} else if (II->isStr("parser_crash")) {
Token Crasher;
Crasher.startToken();
Crasher.setKind(tok::annot_pragma_parser_crash);
Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
PP.EnterToken(Crasher, /*IsReinject*/false);
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) {
Token Crasher;
Crasher.startToken();
Crasher.setKind(tok::annot_pragma_parser_crash);
Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
PP.EnterToken(Crasher, /*IsReinject*/ false);
}
} else if (II->isStr("dump")) {
Token Identifier;
PP.LexUnexpandedToken(Identifier);
@ -1075,9 +1079,11 @@ struct PragmaDebugHandler : public PragmaHandler {
<< II->getName();
}
} else if (II->isStr("llvm_fatal_error")) {
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
} else if (II->isStr("llvm_unreachable")) {
llvm_unreachable("#pragma clang __debug llvm_unreachable");
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
llvm_unreachable("#pragma clang __debug llvm_unreachable");
} else if (II->isStr("macro")) {
Token MacroName;
PP.LexUnexpandedToken(MacroName);
@ -1104,11 +1110,8 @@ struct PragmaDebugHandler : public PragmaHandler {
}
M->dump();
} else if (II->isStr("overflow_stack")) {
DebugOverflowStack();
} else if (II->isStr("handle_crash")) {
llvm::CrashRecoveryContext *CRC =llvm::CrashRecoveryContext::GetCurrent();
if (CRC)
CRC->HandleCrash();
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
DebugOverflowStack();
} else if (II->isStr("captured")) {
HandleCaptured(PP);
} else {

View File

@ -5060,6 +5060,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
return true;
if (TryAnnotateTypeConstraint())
return true;
if (Tok.is(tok::identifier))
return false;
@ -5192,11 +5194,14 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
// placeholder-type-specifier
case tok::annot_template_id: {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
return TemplateId->Kind == TNK_Concept_template &&
return isTypeConstraintAnnotation() &&
(NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));
}
case tok::annot_cxxscope:
if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())
return true;
return isTypeConstraintAnnotation() &&
GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);
case tok::kw___declspec:
case tok::kw___cdecl:
case tok::kw___stdcall:

View File

@ -2716,7 +2716,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
if (DeclaratorInfo.isFunctionDeclarator() &&
DefinitionKind != FDK_Definition && DS.isFriendSpecified()) {
DefinitionKind == FDK_Declaration && DS.isFriendSpecified()) {
// Diagnose attributes that appear before decl specifier:
// [[]] friend int foo();
ProhibitAttributes(FnAttrs);

View File

@ -3374,25 +3374,6 @@ ExprResult Parser::ParseRequiresExpression() {
Diag(Tok, diag::err_requires_expr_missing_arrow)
<< FixItHint::CreateInsertion(Tok.getLocation(), "->");
// Try to parse a 'type-constraint'
CXXScopeSpec SS;
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
/*EnteringContext=*/false,
/*MayBePseudoDestructor=*/nullptr,
// If this is not a type-constraint,
// then this scope-spec is part of
// the typename of a non-type
// template parameter
/*IsTypename=*/true,
/*LastII=*/nullptr,
// We won't find concepts in
// non-namespaces anyway, so might as
// well parse this correctly for
// possible type names.
/*OnlyNamespace=*/false,
/*SuppressDiagnostic=*/true)) {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
break;
}
if (TryAnnotateTypeConstraint()) {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
break;
@ -3402,8 +3383,13 @@ ExprResult Parser::ParseRequiresExpression() {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
break;
}
if (Tok.is(tok::annot_cxxscope))
CXXScopeSpec SS;
if (Tok.is(tok::annot_cxxscope)) {
Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
Tok.getAnnotationRange(),
SS);
ConsumeAnnotationToken();
}
Req = Actions.ActOnCompoundRequirement(
Expression.get(), NoexceptLoc, SS, takeTemplateIdAnnotation(Tok),
@ -3490,6 +3476,7 @@ ExprResult Parser::ParseRequiresExpression() {
// We need to consume the typename to allow 'requires { typename a; }'
SourceLocation TypenameKWLoc = ConsumeToken();
if (TryAnnotateCXXScopeToken()) {
TPA.Commit();
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
break;
}

View File

@ -2311,6 +2311,24 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return SuccessResult;
}
// Diagnose address space conversion in nested pointers.
QualType DestPtee = DestType->getPointeeType().isNull()
? DestType->getPointeeType()
: DestType->getPointeeType()->getPointeeType();
QualType SrcPtee = SrcType->getPointeeType().isNull()
? SrcType->getPointeeType()
: SrcType->getPointeeType()->getPointeeType();
while (!DestPtee.isNull() && !SrcPtee.isNull()) {
if (DestPtee.getAddressSpace() != SrcPtee.getAddressSpace()) {
Self.Diag(OpRange.getBegin(),
diag::warn_bad_cxx_cast_nested_pointer_addr_space)
<< CStyle << SrcType << DestType << SrcExpr.get()->getSourceRange();
break;
}
DestPtee = DestPtee->getPointeeType();
SrcPtee = SrcPtee->getPointeeType();
}
// C++ 5.2.10p7: A pointer to an object can be explicitly converted to
// a pointer to an object of different type.
// Void pointers are not specified, but supported by every compiler out there.

View File

@ -167,9 +167,8 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
return false;
}
template <typename TemplateDeclT>
static bool calculateConstraintSatisfaction(
Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs,
Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
return calculateConstraintSatisfaction(
@ -182,8 +181,9 @@ static bool calculateConstraintSatisfaction(
{
TemplateDeductionInfo Info(TemplateNameLoc);
Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template,
Info, AtomicExpr->getSourceRange());
Sema::InstantiatingTemplate::ConstraintSubstitution{},
const_cast<NamedDecl *>(Template), Info,
AtomicExpr->getSourceRange());
if (Inst.isInvalid())
return ExprError();
// We do not want error diagnostics escaping here.
@ -230,8 +230,7 @@ static bool calculateConstraintSatisfaction(
});
}
template<typename TemplateDeclT>
static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange,
@ -249,8 +248,8 @@ static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
}
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
TemplateIDRange);
Sema::InstantiatingTemplate::ConstraintsCheck{},
const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
if (Inst.isInvalid())
return true;
@ -273,7 +272,7 @@ static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
}
bool Sema::CheckConstraintSatisfaction(
NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
ConstraintSatisfaction &OutSatisfaction) {
if (ConstraintExprs.empty()) {
@ -284,7 +283,8 @@ bool Sema::CheckConstraintSatisfaction(
llvm::FoldingSetNodeID ID;
void *InsertPos;
ConstraintSatisfaction *Satisfaction = nullptr;
if (LangOpts.ConceptSatisfactionCaching) {
bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
if (ShouldCache) {
ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
if (Satisfaction) {
@ -295,27 +295,15 @@ bool Sema::CheckConstraintSatisfaction(
} else {
Satisfaction = &OutSatisfaction;
}
bool Failed;
if (auto *T = dyn_cast<TemplateDecl>(Template))
Failed = ::CheckConstraintSatisfaction(*this, T, ConstraintExprs,
TemplateArgs, TemplateIDRange,
*Satisfaction);
else if (auto *P =
dyn_cast<ClassTemplatePartialSpecializationDecl>(Template))
Failed = ::CheckConstraintSatisfaction(*this, P, ConstraintExprs,
TemplateArgs, TemplateIDRange,
*Satisfaction);
else
Failed = ::CheckConstraintSatisfaction(
*this, cast<VarTemplatePartialSpecializationDecl>(Template),
ConstraintExprs, TemplateArgs, TemplateIDRange, *Satisfaction);
if (Failed) {
if (LangOpts.ConceptSatisfactionCaching)
if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
TemplateArgs, TemplateIDRange,
*Satisfaction)) {
if (ShouldCache)
delete Satisfaction;
return true;
}
if (LangOpts.ConceptSatisfactionCaching) {
if (ShouldCache) {
// We cannot use InsertNode here because CheckConstraintSatisfaction might
// have invalidated it.
SatisfactionCache.InsertNode(Satisfaction);
@ -333,6 +321,30 @@ bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
});
}
bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
ConstraintSatisfaction &Satisfaction,
SourceLocation UsageLoc) {
const Expr *RC = FD->getTrailingRequiresClause();
if (RC->isInstantiationDependent()) {
Satisfaction.IsSatisfied = true;
return false;
}
Qualifiers ThisQuals;
CXXRecordDecl *Record = nullptr;
if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
ThisQuals = Method->getMethodQualifiers();
Record = const_cast<CXXRecordDecl *>(Method->getParent());
}
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
// We substitute with empty arguments in order to rebuild the atomic
// constraint in a constant-evaluated context.
// FIXME: Should this be a dedicated TreeTransform?
return CheckConstraintSatisfaction(
FD, {RC}, /*TemplateArgs=*/{},
SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
Satisfaction);
}
bool Sema::EnsureTemplateArgumentListConstraints(
TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange) {
@ -671,6 +683,10 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
return true;
Atomic.ParameterMapping.emplace(
MutableArrayRef<TemplateArgumentLoc>(
new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
SubstArgs.size()));
std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
N.getAtomicConstraint()->ParameterMapping->begin());
return false;

View File

@ -12526,6 +12526,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
var->getDeclContext()->getRedeclContext()->isFileContext() &&
var->isExternallyVisible() && var->hasLinkage() &&
!var->isInline() && !var->getDescribedVarTemplate() &&
!isa<VarTemplatePartialSpecializationDecl>(var) &&
!isTemplateInstantiation(var->getTemplateSpecializationKind()) &&
!getDiagnostics().isIgnored(diag::warn_missing_variable_declarations,
var->getLocation())) {

View File

@ -7373,7 +7373,14 @@ class DefaultedComparisonAnalyzer
/// resolution [...]
CandidateSet.exclude(FD);
S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args);
if (Args[0]->getType()->isOverloadableType())
S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args);
else {
// FIXME: We determine whether this is a valid expression by checking to
// see if there's a viable builtin operator candidate for it. That isn't
// really what the rules ask us to do, but should give the right results.
S.AddBuiltinOperatorCandidates(OO, FD->getLocation(), Args, CandidateSet);
}
Result R;
@ -7438,6 +7445,31 @@ class DefaultedComparisonAnalyzer
if (OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType()) {
if (auto *BestFD = Best->Function) {
// If any callee has an undeduced return type, deduce it now.
// FIXME: It's not clear how a failure here should be handled. For
// now, we produce an eager diagnostic, because that is forward
// compatible with most (all?) other reasonable options.
if (BestFD->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(BestFD, FD->getLocation(),
/*Diagnose=*/false)) {
// Don't produce a duplicate error when asked to explain why the
// comparison is deleted: we diagnosed that when initially checking
// the defaulted operator.
if (Diagnose == NoDiagnostics) {
S.Diag(
FD->getLocation(),
diag::err_defaulted_comparison_cannot_deduce_undeduced_auto)
<< Subobj.Kind << Subobj.Decl;
S.Diag(
Subobj.Loc,
diag::note_defaulted_comparison_cannot_deduce_undeduced_auto)
<< Subobj.Kind << Subobj.Decl;
S.Diag(BestFD->getLocation(),
diag::note_defaulted_comparison_cannot_deduce_callee)
<< Subobj.Kind << Subobj.Decl;
}
return Result::deleted();
}
if (auto *Info = S.Context.CompCategories.lookupInfoForType(
BestFD->getCallResultType())) {
R.Category = Info->Kind;
@ -7826,10 +7858,14 @@ class DefaultedComparisonSynthesizer
return StmtError();
OverloadedOperatorKind OO = FD->getOverloadedOperator();
ExprResult Op = S.CreateOverloadedBinOp(
Loc, BinaryOperator::getOverloadedOpcode(OO), Fns,
Obj.first.get(), Obj.second.get(), /*PerformADL=*/true,
/*AllowRewrittenCandidates=*/true, FD);
BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(OO);
ExprResult Op;
if (Type->isOverloadableType())
Op = S.CreateOverloadedBinOp(Loc, Opc, Fns, Obj.first.get(),
Obj.second.get(), /*PerformADL=*/true,
/*AllowRewrittenCandidates=*/true, FD);
else
Op = S.CreateBuiltinBinOp(Loc, Opc, Obj.first.get(), Obj.second.get());
if (Op.isInvalid())
return StmtError();
@ -7869,8 +7905,12 @@ class DefaultedComparisonSynthesizer
llvm::APInt ZeroVal(S.Context.getIntWidth(S.Context.IntTy), 0);
Expr *Zero =
IntegerLiteral::Create(S.Context, ZeroVal, S.Context.IntTy, Loc);
ExprResult Comp = S.CreateOverloadedBinOp(Loc, BO_NE, Fns, VDRef.get(),
Zero, true, true, FD);
ExprResult Comp;
if (VDRef.get()->getType()->isOverloadableType())
Comp = S.CreateOverloadedBinOp(Loc, BO_NE, Fns, VDRef.get(), Zero, true,
true, FD);
else
Comp = S.CreateBuiltinBinOp(Loc, BO_NE, VDRef.get(), Zero);
if (Comp.isInvalid())
return StmtError();
Sema::ConditionResult Cond = S.ActOnCondition(

View File

@ -245,8 +245,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
return true;
}
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// See if this is a deleted function.
if (FD->isDeleted()) {
auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
if (Ctor && Ctor->isInheritingConstructor())
@ -259,6 +259,29 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
return true;
}
// [expr.prim.id]p4
// A program that refers explicitly or implicitly to a function with a
// trailing requires-clause whose constraint-expression is not satisfied,
// other than to declare it, is ill-formed. [...]
//
// See if this is a function with constraints that need to be satisfied.
// Check this before deducing the return type, as it might instantiate the
// definition.
if (FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckFunctionConstraints(FD, Satisfaction, Loc))
// A diagnostic will have already been generated (non-constant
// constraint expression, for example)
return true;
if (!Satisfaction.IsSatisfied) {
Diag(Loc,
diag::err_reference_to_function_with_unsatisfied_constraints)
<< D;
DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
}
}
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
@ -326,30 +349,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
// [expr.prim.id]p4
// A program that refers explicitly or implicitly to a function with a
// trailing requires-clause whose constraint-expression is not satisfied,
// other than to declare it, is ill-formed. [...]
//
// See if this is a function with constraints that need to be satisfied.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (Expr *RC = FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
bool Failed = CheckConstraintSatisfaction(RC, Satisfaction);
if (Failed)
// A diagnostic will have already been generated (non-constant
// constraint expression, for example)
return true;
if (!Satisfaction.IsSatisfied) {
Diag(Loc,
diag::err_reference_to_function_with_unsatisfied_constraints)
<< D;
DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
}
}
}
if (isa<ParmVarDecl>(D) && isa<RequiresExprBodyDecl>(D->getDeclContext()) &&
!isUnevaluatedContext()) {
// C++ [expr.prim.req.nested] p3

View File

@ -8487,7 +8487,8 @@ concepts::NestedRequirement *
Sema::BuildNestedRequirement(Expr *Constraint) {
ConstraintSatisfaction Satisfaction;
if (!Constraint->isInstantiationDependent() &&
CheckConstraintSatisfaction(Constraint, Satisfaction))
CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
Constraint->getSourceRange(), Satisfaction))
return nullptr;
return new (Context) concepts::NestedRequirement(Context, Constraint,
Satisfaction);

View File

@ -3176,7 +3176,7 @@ static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
/// FromType and \p ToType is permissible, given knowledge about whether every
/// outer layer is const-qualified.
static bool isQualificationConversionStep(QualType FromType, QualType ToType,
bool CStyle,
bool CStyle, bool IsTopLevel,
bool &PreviousToQualsIncludeConst,
bool &ObjCLifetimeConversion) {
Qualifiers FromQuals = FromType.getQualifiers();
@ -3213,11 +3213,15 @@ static bool isQualificationConversionStep(QualType FromType, QualType ToType,
if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
return false;
// For a C-style cast, just require the address spaces to overlap.
// FIXME: Does "superset" also imply the representation of a pointer is the
// same? We're assuming that it does here and in compatiblyIncludes.
if (CStyle && !ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
!FromQuals.isAddressSpaceSupersetOf(ToQuals))
// If address spaces mismatch:
// - in top level it is only valid to convert to addr space that is a
// superset in all cases apart from C-style casts where we allow
// conversions between overlapping address spaces.
// - in non-top levels it is not a valid conversion.
if (ToQuals.getAddressSpace() != FromQuals.getAddressSpace() &&
(!IsTopLevel ||
!(ToQuals.isAddressSpaceSupersetOf(FromQuals) ||
(CStyle && FromQuals.isAddressSpaceSupersetOf(ToQuals)))))
return false;
// -- if the cv 1,j and cv 2,j are different, then const is in
@ -3258,9 +3262,9 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
while (Context.UnwrapSimilarTypes(FromType, ToType)) {
if (!isQualificationConversionStep(FromType, ToType, CStyle,
PreviousToQualsIncludeConst,
ObjCLifetimeConversion))
if (!isQualificationConversionStep(
FromType, ToType, CStyle, !UnwrappedAnyPointer,
PreviousToQualsIncludeConst, ObjCLifetimeConversion))
return false;
UnwrappedAnyPointer = true;
}
@ -4499,7 +4503,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// If we find a qualifier mismatch, the types are not reference-compatible,
// but are still be reference-related if they're similar.
bool ObjCLifetimeConversion = false;
if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false,
if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false, TopLevel,
PreviousToQualsIncludeConst,
ObjCLifetimeConversion))
return (ConvertedReferent || Context.hasSimilarType(T1, T2))
@ -6291,9 +6295,9 @@ void Sema::AddOverloadCandidate(
return;
}
if (Expr *RequiresClause = Function->getTrailingRequiresClause()) {
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
if (CheckFunctionConstraints(Function, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@ -6808,9 +6812,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
return;
}
if (Expr *RequiresClause = Method->getTrailingRequiresClause()) {
if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
if (CheckFunctionConstraints(Method, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@ -7204,10 +7208,9 @@ void Sema::AddConversionCandidate(
return;
}
Expr *RequiresClause = Conversion->getTrailingRequiresClause();
if (RequiresClause) {
if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
if (CheckFunctionConstraints(Conversion, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@ -9270,17 +9273,31 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
if (ExplicitTemplateArgs)
continue;
AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet,
/*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit*/ true,
/*AllowExplicitConversions*/ false,
ADLCallKind::UsesADL);
AddOverloadCandidate(
FD, FoundDecl, Args, CandidateSet, /*SuppressUserConversions=*/false,
PartialOverloading, /*AllowExplicit=*/true,
/*AllowExplicitConversions=*/false, ADLCallKind::UsesADL);
if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD)) {
AddOverloadCandidate(
FD, FoundDecl, {Args[1], Args[0]}, CandidateSet,
/*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit=*/true, /*AllowExplicitConversions=*/false,
ADLCallKind::UsesADL, None, OverloadCandidateParamOrder::Reversed);
}
} else {
auto *FTD = cast<FunctionTemplateDecl>(*I);
AddTemplateOverloadCandidate(
cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, Args,
CandidateSet,
FTD, FoundDecl, ExplicitTemplateArgs, Args, CandidateSet,
/*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit*/true, ADLCallKind::UsesADL);
/*AllowExplicit=*/true, ADLCallKind::UsesADL);
if (CandidateSet.getRewriteInfo().shouldAddReversed(
Context, FTD->getTemplatedDecl())) {
AddTemplateOverloadCandidate(
FTD, FoundDecl, ExplicitTemplateArgs, {Args[1], Args[0]},
CandidateSet, /*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit=*/true, ADLCallKind::UsesADL,
OverloadCandidateParamOrder::Reversed);
}
}
}
}
@ -9566,17 +9583,15 @@ bool clang::isBetterOverloadCandidate(
if (RC1 && RC2) {
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
if (S.IsAtLeastAsConstrained(Cand1.Function, {RC1}, Cand2.Function,
{RC2}, AtLeastAsConstrained1))
return false;
if (!AtLeastAsConstrained1)
return false;
if (S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function,
{RC2}, AtLeastAsConstrained1) ||
S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function,
{RC1}, AtLeastAsConstrained2))
return false;
if (!AtLeastAsConstrained2)
return true;
} else if (RC1 || RC2)
if (AtLeastAsConstrained1 != AtLeastAsConstrained2)
return AtLeastAsConstrained1;
} else if (RC1 || RC2) {
return RC1 != nullptr;
}
}
}
@ -9947,9 +9962,9 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
return false;
}
if (const Expr *RC = FD->getTrailingRequiresClause()) {
if (FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (S.CheckConstraintSatisfaction(RC, Satisfaction))
if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
return false;
if (!Satisfaction.IsSatisfied) {
if (Complain) {
@ -10974,8 +10989,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
<< FnDesc /* Ignored */;
ConstraintSatisfaction Satisfaction;
if (S.CheckConstraintSatisfaction(Fn->getTrailingRequiresClause(),
Satisfaction))
if (S.CheckFunctionConstraints(Fn, Satisfaction))
break;
S.DiagnoseUnsatisfiedConstraint(Satisfaction);
}

View File

@ -2047,12 +2047,14 @@ struct ConvertConstructorToDeductionGuideTransform {
if (const auto *TC = TTP->getTypeConstraint()) {
TemplateArgumentListInfo TransformedArgs;
const auto *ArgsAsWritten = TC->getTemplateArgsAsWritten();
if (SemaRef.Subst(ArgsAsWritten->getTemplateArgs(),
if (!ArgsAsWritten ||
SemaRef.Subst(ArgsAsWritten->getTemplateArgs(),
ArgsAsWritten->NumTemplateArgs, TransformedArgs,
Args))
SemaRef.AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
TC->getNamedConcept(), &TransformedArgs, NewTTP,
TC->getNamedConcept(), ArgsAsWritten ? &TransformedArgs : nullptr,
NewTTP,
NewTTP->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()

View File

@ -2488,7 +2488,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
NestedNameSpecifierLocBuilder Builder;
TemplateName Template = Arg.getAsTemplate();
TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
else if (QualifiedTemplateName *QTN =
@ -2514,27 +2514,10 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
}
TemplateArgumentLoc
Sema::getIdentityTemplateArgumentLoc(Decl *TemplateParm,
Sema::getIdentityTemplateArgumentLoc(NamedDecl *TemplateParm,
SourceLocation Location) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParm))
return getTrivialTemplateArgumentLoc(
TemplateArgument(
Context.getTemplateTypeParmType(TTP->getDepth(), TTP->getIndex(),
TTP->isParameterPack(), TTP)),
QualType(), Location.isValid() ? Location : TTP->getLocation());
else if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParm))
return getTrivialTemplateArgumentLoc(TemplateArgument(TemplateName(TTP)),
QualType(),
Location.isValid() ? Location :
TTP->getLocation());
auto *NTTP = cast<NonTypeTemplateParmDecl>(TemplateParm);
CXXScopeSpec SS;
DeclarationNameInfo Info(NTTP->getDeclName(),
Location.isValid() ? Location : NTTP->getLocation());
Expr *E = BuildDeclarationNameExpr(SS, Info, NTTP).get();
return getTrivialTemplateArgumentLoc(TemplateArgument(E), NTTP->getType(),
Location.isValid() ? Location :
NTTP->getLocation());
return getTrivialTemplateArgumentLoc(
Context.getInjectedTemplateArg(TemplateParm), QualType(), Location);
}
/// Convert the given deduced template argument and add it to the set of
@ -3456,13 +3439,16 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
// ([temp.constr.decl]), those constraints are checked for satisfaction
// ([temp.constr.constr]). If the constraints are not satisfied, type
// deduction fails.
if (CheckInstantiatedFunctionTemplateConstraints(Info.getLocation(),
Specialization, Builder, Info.AssociatedConstraintsSatisfaction))
return TDK_MiscellaneousDeductionFailure;
if (!PartialOverloading ||
(Builder.size() == FunctionTemplate->getTemplateParameters()->size())) {
if (CheckInstantiatedFunctionTemplateConstraints(Info.getLocation(),
Specialization, Builder, Info.AssociatedConstraintsSatisfaction))
return TDK_MiscellaneousDeductionFailure;
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
return TDK_ConstraintsNotSatisfied;
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
return TDK_ConstraintsNotSatisfied;
}
}
if (OriginalCallArgs) {

View File

@ -18,6 +18,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Stack.h"
#include "clang/Sema/DeclSpec.h"
@ -763,21 +764,30 @@ void Sema::PrintInstantiationStack() {
case CodeSynthesisContext::ConstraintsCheck: {
unsigned DiagID = 0;
if (!Active->Entity) {
Diags.Report(Active->PointOfInstantiation,
diag::note_nested_requirement_here)
<< Active->InstantiationRange;
break;
}
if (isa<ConceptDecl>(Active->Entity))
DiagID = diag::note_concept_specialization_here;
else if (isa<TemplateDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_template_id_here;
else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_var_spec_id_here;
else {
assert(isa<ClassTemplatePartialSpecializationDecl>(Active->Entity));
else if (isa<ClassTemplatePartialSpecializationDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_class_spec_id_here;
else {
assert(isa<FunctionDecl>(Active->Entity));
DiagID = diag::note_checking_constraints_for_function_here;
}
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
cast<NamedDecl>(Active->Entity)->printName(OS);
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
if (!isa<FunctionDecl>(Active->Entity))
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
<< Active->InstantiationRange;
break;
@ -1048,6 +1058,8 @@ namespace {
NonTypeTemplateParmDecl *D);
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
ExprResult TransformSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E);
/// Rebuild a DeclRefExpr for a VarDecl reference.
ExprResult RebuildVarDeclRefExpr(VarDecl *PD, SourceLocation Loc);
@ -1526,6 +1538,44 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
Arg);
}
ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
ExprResult SubstReplacement = TransformExpr(E->getReplacement());
if (SubstReplacement.isInvalid())
return true;
QualType SubstType = TransformType(E->getType());
if (SubstType.isNull())
return true;
// The type may have been previously dependent and not now, which means we
// might have to implicit cast the argument to the new type, for example:
// template<auto T, decltype(T) U>
// concept C = sizeof(U) == 4;
// void foo() requires C<2, 'a'> { }
// When normalizing foo(), we first form the normalized constraints of C:
// AtomicExpr(sizeof(U) == 4,
// U=SubstNonTypeTemplateParmExpr(Param=U,
// Expr=DeclRef(U),
// Type=decltype(T)))
// Then we substitute T = 2, U = 'a' into the parameter mapping, and need to
// produce:
// AtomicExpr(sizeof(U) == 4,
// U=SubstNonTypeTemplateParmExpr(Param=U,
// Expr=ImpCast(
// decltype(2),
// SubstNTTPE(Param=U, Expr='a',
// Type=char)),
// Type=decltype(2)))
// The call to CheckTemplateArgument here produces the ImpCast.
TemplateArgument Converted;
if (SemaRef.CheckTemplateArgument(E->getParameter(), SubstType,
SubstReplacement.get(),
Converted).isInvalid())
return true;
return transformNonTypeTemplateParmRef(E->getParameter(),
E->getExprLoc(), Converted);
}
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
SourceLocation Loc) {
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
@ -2096,6 +2146,94 @@ void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
UpdateExceptionSpec(New, ESI);
}
namespace {
struct GetContainedInventedTypeParmVisitor :
public TypeVisitor<GetContainedInventedTypeParmVisitor,
TemplateTypeParmDecl *> {
using TypeVisitor<GetContainedInventedTypeParmVisitor,
TemplateTypeParmDecl *>::Visit;
TemplateTypeParmDecl *Visit(QualType T) {
if (T.isNull())
return nullptr;
return Visit(T.getTypePtr());
}
// The deduced type itself.
TemplateTypeParmDecl *VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
if (!T->getDecl()->isImplicit())
return nullptr;
return T->getDecl();
}
// Only these types can contain 'auto' types, and subsequently be replaced
// by references to invented parameters.
TemplateTypeParmDecl *VisitElaboratedType(const ElaboratedType *T) {
return Visit(T->getNamedType());
}
TemplateTypeParmDecl *VisitPointerType(const PointerType *T) {
return Visit(T->getPointeeType());
}
TemplateTypeParmDecl *VisitBlockPointerType(const BlockPointerType *T) {
return Visit(T->getPointeeType());
}
TemplateTypeParmDecl *VisitReferenceType(const ReferenceType *T) {
return Visit(T->getPointeeTypeAsWritten());
}
TemplateTypeParmDecl *VisitMemberPointerType(const MemberPointerType *T) {
return Visit(T->getPointeeType());
}
TemplateTypeParmDecl *VisitArrayType(const ArrayType *T) {
return Visit(T->getElementType());
}
TemplateTypeParmDecl *VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
return Visit(T->getElementType());
}
TemplateTypeParmDecl *VisitVectorType(const VectorType *T) {
return Visit(T->getElementType());
}
TemplateTypeParmDecl *VisitFunctionProtoType(const FunctionProtoType *T) {
return VisitFunctionType(T);
}
TemplateTypeParmDecl *VisitFunctionType(const FunctionType *T) {
return Visit(T->getReturnType());
}
TemplateTypeParmDecl *VisitParenType(const ParenType *T) {
return Visit(T->getInnerType());
}
TemplateTypeParmDecl *VisitAttributedType(const AttributedType *T) {
return Visit(T->getModifiedType());
}
TemplateTypeParmDecl *VisitMacroQualifiedType(const MacroQualifiedType *T) {
return Visit(T->getUnderlyingType());
}
TemplateTypeParmDecl *VisitAdjustedType(const AdjustedType *T) {
return Visit(T->getOriginalType());
}
TemplateTypeParmDecl *VisitPackExpansionType(const PackExpansionType *T) {
return Visit(T->getPattern());
}
};
} // namespace
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
@ -2143,6 +2281,46 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
return nullptr;
}
// In abbreviated templates, TemplateTypeParmDecls with possible
// TypeConstraints are created when the parameter list is originally parsed.
// The TypeConstraints can therefore reference other functions parameters in
// the abbreviated function template, which is why we must instantiate them
// here, when the instantiated versions of those referenced parameters are in
// scope.
if (TemplateTypeParmDecl *TTP =
GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) {
if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
auto *Inst = cast_or_null<TemplateTypeParmDecl>(
FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs));
// We will first get here when instantiating the abbreviated function
// template's described function, but we might also get here later.
// Make sure we do not instantiate the TypeConstraint more than once.
if (Inst && !Inst->getTypeConstraint()) {
// TODO: Concepts: do not instantiate the constraint (delayed constraint
// substitution)
const ASTTemplateArgumentListInfo *TemplArgInfo
= TC->getTemplateArgsAsWritten();
TemplateArgumentListInfo InstArgs;
if (TemplArgInfo) {
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
if (Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs, InstArgs, TemplateArgs))
return nullptr;
}
if (AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
TC->getNamedConcept(), &InstArgs, Inst,
TTP->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()
: SourceLocation()))
return nullptr;
}
}
}
ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
OldParm->getInnerLocStart(),
OldParm->getLocation(),

View File

@ -1837,6 +1837,23 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
if (TemplateParams && TemplateParams->size()) {
auto *LastParam =
dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back());
if (LastParam && LastParam->isImplicit() &&
LastParam->hasTypeConstraint()) {
// In abbreviated templates, the type-constraints of invented template
// type parameters are instantiated with the function type, invalidating
// the TemplateParameterList which relied on the template type parameter
// not having a type constraint. Recreate the TemplateParameterList with
// the updated parameter list.
TemplateParams = TemplateParameterList::Create(
SemaRef.Context, TemplateParams->getTemplateLoc(),
TemplateParams->getLAngleLoc(), TemplateParams->asArray(),
TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause());
}
}
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
if (QualifierLoc) {
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
@ -2177,6 +2194,23 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
if (TemplateParams && TemplateParams->size()) {
auto *LastParam =
dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back());
if (LastParam && LastParam->isImplicit() &&
LastParam->hasTypeConstraint()) {
// In abbreviated templates, the type-constraints of invented template
// type parameters are instantiated with the function type, invalidating
// the TemplateParameterList which relied on the template type parameter
// not having a type constraint. Recreate the TemplateParameterList with
// the updated parameter list.
TemplateParams = TemplateParameterList::Create(
SemaRef.Context, TemplateParams->getTemplateLoc(),
TemplateParams->getLAngleLoc(), TemplateParams->asArray(),
TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause());
}
}
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
if (QualifierLoc) {
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
@ -2190,6 +2224,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
if (TrailingRequiresClause) {
EnterExpressionEvaluationContext ConstantEvaluated(
SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext,
D->getMethodQualifiers(), ThisContext);
ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
TemplateArgs);
if (SubstRC.isInvalid())
@ -2522,28 +2559,34 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
Inst->setAccess(AS_public);
Inst->setImplicit(D->isImplicit());
if (auto *TC = D->getTypeConstraint()) {
// TODO: Concepts: do not instantiate the constraint (delayed constraint
// substitution)
const ASTTemplateArgumentListInfo *TemplArgInfo
= TC->getTemplateArgsAsWritten();
TemplateArgumentListInfo InstArgs;
if (!D->isImplicit()) {
// Invented template parameter type constraints will be instantiated with
// the corresponding auto-typed parameter as it might reference other
// parameters.
if (TemplArgInfo) {
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs,
InstArgs, TemplateArgs))
// TODO: Concepts: do not instantiate the constraint (delayed constraint
// substitution)
const ASTTemplateArgumentListInfo *TemplArgInfo
= TC->getTemplateArgsAsWritten();
TemplateArgumentListInfo InstArgs;
if (TemplArgInfo) {
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs,
InstArgs, TemplateArgs))
return nullptr;
}
if (SemaRef.AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
TC->getNamedConcept(), &InstArgs, Inst,
D->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()
: SourceLocation()))
return nullptr;
}
if (SemaRef.AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
TC->getNamedConcept(), &InstArgs, Inst,
D->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()
: SourceLocation()))
return nullptr;
}
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
TypeSourceInfo *InstantiatedDefaultArg =
@ -4246,24 +4289,29 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
Sema::ContextRAII savedContext(*this, Decl);
LocalInstantiationScope Scope(*this);
MultiLevelTemplateArgumentList MLTAL =
getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
// If this is not an explicit specialization - we need to get the instantiated
// version of the template arguments and add them to scope for the
// substitution.
if (Decl->isTemplateInstantiation()) {
InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(),
InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(),
MLTAL.getInnermost(), SourceRange());
TemplateArgs, SourceRange());
if (Inst.isInvalid())
return true;
MultiLevelTemplateArgumentList MLTAL(
*Decl->getTemplateSpecializationArgs());
if (addInstantiatedParametersToScope(
*this, Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(),
Scope, MLTAL))
return true;
}
Qualifiers ThisQuals;
CXXRecordDecl *Record = nullptr;
if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
ThisQuals = Method->getMethodQualifiers();
Record = Method->getParent();
}
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs,
PointOfInstantiation, Satisfaction);
}

View File

@ -555,7 +555,7 @@ void ASTDeclReader::Visit(Decl *D) {
void ASTDeclReader::VisitDecl(Decl *D) {
if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
isa<ParmVarDecl>(D)) {
isa<ParmVarDecl>(D) || isa<ObjCTypeParamDecl>(D)) {
// We don't want to deserialize the DeclContext of a template
// parameter or of a parameter of a function template immediately. These
// entities might be used in the formulation of its DeclContext (for

View File

@ -607,10 +607,17 @@ window.addEventListener("keydown", function (event) {
)<<<";
}
static bool shouldDisplayPopUpRange(const SourceRange &Range) {
return !(Range.getBegin().isMacroID() || Range.getEnd().isMacroID());
}
static void
HandlePopUpPieceStartTag(Rewriter &R,
const std::vector<SourceRange> &PopUpRanges) {
for (const auto &Range : PopUpRanges) {
if (!shouldDisplayPopUpRange(Range))
continue;
html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "",
"<table class='variable_popup'><tbody>",
/*IsTokenRange=*/true);
@ -626,6 +633,8 @@ static void HandlePopUpPieceEndTag(Rewriter &R,
llvm::raw_svector_ostream Out(Buf);
SourceRange Range(Piece.getLocation().asRange());
if (!shouldDisplayPopUpRange(Range))
return;
// Write out the path indices with a right arrow and the message as a row.
Out << "<tr><td valign='top'><div class='PathIndex PathIndexPopUp'>"
@ -870,7 +879,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID,
<< (num - 1)
<< "\" title=\"Previous event ("
<< (num - 1)
<< ")\">&#x2190;</a></div></td>";
<< ")\">&#x2190;</a></div>";
}
os << "</td><td>";

View File

@ -36,6 +36,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@ -69,7 +70,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
// We cannot recover from llvm errors. When reporting a fatal error, exit
// with status 70 to generate crash diagnostics. For BSD systems this is
// defined as an internal software error. Otherwise, exit with status 1.
exit(GenCrashDiag ? 70 : 1);
llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);
}
#ifdef CLANG_HAVE_RLIMITS

View File

@ -46,6 +46,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
@ -547,7 +548,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
Diags.Report(diag::err_fe_error_backend) << Message;
// We cannot recover from llvm errors.
exit(1);
sys::Process::Exit(1);
}
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {

View File

@ -23,9 +23,12 @@
#include <errno.h>
#include <libkern/OSAtomic.h>
#include <objc/objc-sync.h>
#include <os/lock.h>
#include <sys/ucontext.h>
#if defined(__has_include) && __has_include(<os/lock.h>)
#include <os/lock.h>
#endif
#if defined(__has_include) && __has_include(<xpc/xpc.h>)
#include <xpc/xpc.h>
#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
@ -247,6 +250,8 @@ TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) {
REAL(os_lock_unlock)(lock);
}
#if defined(__has_include) && __has_include(<os/lock.h>)
TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
return REAL(os_unfair_lock_lock)(lock);
@ -286,6 +291,8 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
REAL(os_unfair_lock_unlock)(lock);
}
#endif // #if defined(__has_include) && __has_include(<os/lock.h>)
#if defined(__has_include) && __has_include(<xpc/xpc.h>)
TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,

View File

@ -342,6 +342,10 @@
# define _LIBCPP_HAS_ALIGNED_ALLOC
# define _LIBCPP_HAS_QUICK_EXIT
# define _LIBCPP_HAS_C11_FEATURES
# if __FreeBSD_version >= 1300064 || \
(__FreeBSD_version >= 1201504 && __FreeBSD_version < 1300000)
# define _LIBCPP_HAS_TIMESPEC_GET
# endif
# elif defined(__BIONIC__)
# define _LIBCPP_HAS_C11_FEATURES
# if __ANDROID_API__ >= 21

View File

@ -275,8 +275,8 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_PLT32:
case R_ARM_JUMP24:
// Source is ARM, all PLT entries are ARM so no interworking required.
// Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
if (expr == R_PC && ((s.getVA() & 1) == 1))
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 set (Thumb).
if (s.isFunc() && expr == R_PC && (s.getVA() & 1))
return true;
LLVM_FALLTHROUGH;
case R_ARM_CALL: {
@ -286,8 +286,8 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_THM_JUMP19:
case R_ARM_THM_JUMP24:
// Source is Thumb, all PLT entries are ARM so interworking is required.
// Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
if (expr == R_PLT_PC || ((s.getVA() & 1) == 0))
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM).
if (expr == R_PLT_PC || (s.isFunc() && (s.getVA() & 1) == 0))
return true;
LLVM_FALLTHROUGH;
case R_ARM_THM_CALL: {

View File

@ -67,6 +67,18 @@ static void writeFromHalf16(uint8_t *loc, uint32_t insn) {
}
void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
// Create canonical PLT entries for non-PIE code. Compilers don't generate
// non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
uint32_t glink = in.plt->getVA(); // VA of .glink
if (!config->isPic) {
for (const Symbol *sym : in.plt->entries)
if (sym->needsPltAddr) {
writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0);
buf += 16;
glink += 16;
}
}
// On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an
// absolute address from a specific .plt slot (usually called .got.plt on
// other targets) and jumps there.
@ -85,15 +97,14 @@ void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
// computes the PLT index (by computing the distance from the landing b to
// itself) and calls _dl_runtime_resolve() (in glibc).
uint32_t got = in.got->getVA();
uint32_t glink = in.plt->getVA(); // VA of .glink
const uint8_t *end = buf + 64;
if (config->isPic) {
uint32_t afterBcl = in.plt->getSize() - target->pltHeaderSize + 12;
uint32_t afterBcl = 4 * in.plt->getNumEntries() + 12;
uint32_t gotBcl = got + 4 - (glink + afterBcl);
write32(buf + 0, 0x3d6b0000 | ha(afterBcl)); // addis r11,r11,1f-glink@ha
write32(buf + 4, 0x7c0802a6); // mflr r0
write32(buf + 8, 0x429f0005); // bcl 20,30,.+4
write32(buf + 12, 0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-.glink@l
write32(buf + 12, 0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-glink@l
write32(buf + 16, 0x7d8802a6); // mflr r12
write32(buf + 20, 0x7c0803a6); // mtlr r0
write32(buf + 24, 0x7d6c5850); // sub r11,r11,r12
@ -113,16 +124,16 @@ void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
buf += 56;
} else {
write32(buf + 0, 0x3d800000 | ha(got + 4)); // lis r12,GOT+4@ha
write32(buf + 4, 0x3d6b0000 | ha(-glink)); // addis r11,r11,-Glink@ha
write32(buf + 4, 0x3d6b0000 | ha(-glink)); // addis r11,r11,-glink@ha
if (ha(got + 4) == ha(got + 8))
write32(buf + 8, 0x800c0000 | lo(got + 4)); // lwz r0,GOT+4@l(r12)
else
write32(buf + 8, 0x840c0000 | lo(got + 4)); // lwzu r0,GOT+4@l(r12)
write32(buf + 12, 0x396b0000 | lo(-glink)); // addi r11,r11,-Glink@l
write32(buf + 12, 0x396b0000 | lo(-glink)); // addi r11,r11,-glink@l
write32(buf + 16, 0x7c0903a6); // mtctr r0
write32(buf + 20, 0x7c0b5a14); // add r0,r11,r11
if (ha(got + 4) == ha(got + 8))
write32(buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8@ha(r12)
write32(buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8@l(r12)
else
write32(buf + 24, 0x818c0000 | 4); // lwz r12,4(r12)
write32(buf + 28, 0x7d605a14); // add r11,r0,r11
@ -146,7 +157,7 @@ PPC::PPC() {
gotBaseSymInGotPlt = false;
gotHeaderEntriesNum = 3;
gotPltHeaderEntriesNum = 0;
pltHeaderSize = 64; // size of PLTresolve in .glink
pltHeaderSize = 0;
pltEntrySize = 4;
ipltEntrySize = 16;
@ -178,25 +189,25 @@ void PPC::writeGotHeader(uint8_t *buf) const {
void PPC::writeGotPlt(uint8_t *buf, const Symbol &s) const {
// Address of the symbol resolver stub in .glink .
write32(buf, in.plt->getVA() + 4 * s.pltIndex);
write32(buf, in.plt->getVA() + in.plt->headerSize + 4 * s.pltIndex);
}
bool PPC::needsThunk(RelExpr expr, RelType type, const InputFile *file,
uint64_t branchAddr, const Symbol &s, int64_t /*a*/) const {
if (type != R_PPC_REL24 && type != R_PPC_PLTREL24)
uint64_t branchAddr, const Symbol &s, int64_t a) const {
if (type != R_PPC_LOCAL24PC && type != R_PPC_REL24 && type != R_PPC_PLTREL24)
return false;
if (s.isInPlt())
return true;
if (s.isUndefWeak())
return false;
return !(expr == R_PC && PPC::inBranchRange(type, branchAddr, s.getVA()));
return !PPC::inBranchRange(type, branchAddr, s.getVA(a));
}
uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; }
bool PPC::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
uint64_t offset = dst - src;
if (type == R_PPC_REL24 || type == R_PPC_PLTREL24)
if (type == R_PPC_LOCAL24PC || type == R_PPC_REL24 || type == R_PPC_PLTREL24)
return isInt<26>(offset);
llvm_unreachable("unsupported relocation type used in branch");
}
@ -219,13 +230,13 @@ RelExpr PPC::getRelExpr(RelType type, const Symbol &s,
return R_DTPREL;
case R_PPC_REL14:
case R_PPC_REL32:
case R_PPC_LOCAL24PC:
case R_PPC_REL16_LO:
case R_PPC_REL16_HI:
case R_PPC_REL16_HA:
return R_PC;
case R_PPC_GOT16:
return R_GOT_OFF;
case R_PPC_LOCAL24PC:
case R_PPC_REL24:
return R_PLT_PC;
case R_PPC_PLTREL24:

View File

@ -485,6 +485,14 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr;
else if (config->relocatable && type != target->noneRel)
sec->relocations.push_back({R_ABS, type, rel.r_offset, addend, &sym});
} else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 &&
p->r_addend >= 0x8000) {
// Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24
// indicates that r30 is relative to the input section .got2
// (r_addend>=0x8000), after linking, r30 should be relative to the output
// section .got2 . To compensate for the shift, adjust r_addend by
// ppc32Got2OutSecOff.
p->r_addend += sec->file->ppc32Got2OutSecOff;
}
}
}

View File

@ -1198,10 +1198,16 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
getLocation(sec, sym, offset));
if (!sym.isInPlt())
addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
if (!sym.isDefined())
if (!sym.isDefined()) {
replaceWithDefined(
sym, in.plt,
target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
if (config->emachine == EM_PPC) {
// PPC32 canonical PLT entries are at the beginning of .glink
cast<Defined>(sym).value = in.plt->headerSize;
in.plt->headerSize += 16;
}
}
sym.needsPltAddr = true;
sec.relocations.push_back({expr, type, offset, addend, &sym});
return;
@ -1298,10 +1304,10 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
if (expr == R_GOT_PC && !isAbsoluteValue(sym)) {
expr = target->adjustRelaxExpr(type, relocatedAddr, expr);
} else {
// Addend of R_PPC_PLTREL24 is used to choose call stub type. It should be
// ignored if optimized to R_PC.
// The 0x8000 bit of r_addend of R_PPC_PLTREL24 is used to choose call
// stub type. It should be ignored if optimized to R_PC.
if (config->emachine == EM_PPC && expr == R_PPC32_PLTREL)
addend = 0;
addend &= ~0x8000;
expr = fromPlt(expr);
}
}
@ -1752,6 +1758,37 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *os,
uint64_t off) {
auto *ts = make<ThunkSection>(os, off);
ts->partition = os->partition;
if ((config->fixCortexA53Errata843419 || config->fixCortexA8) &&
!isd->sections.empty()) {
// The errata fixes are sensitive to addresses modulo 4 KiB. When we add
// thunks we disturb the base addresses of sections placed after the thunks
// this makes patches we have generated redundant, and may cause us to
// generate more patches as different instructions are now in sensitive
// locations. When we generate more patches we may force more branches to
// go out of range, causing more thunks to be generated. In pathological
// cases this can cause the address dependent content pass not to converge.
// We fix this by rounding up the size of the ThunkSection to 4KiB, this
// limits the insertion of a ThunkSection on the addresses modulo 4 KiB,
// which means that adding Thunks to the section does not invalidate
// errata patches for following code.
// Rounding up the size to 4KiB has consequences for code-size and can
// trip up linker script defined assertions. For example the linux kernel
// has an assertion that what LLD represents as an InputSectionDescription
// does not exceed 4 KiB even if the overall OutputSection is > 128 Mib.
// We use the heuristic of rounding up the size when both of the following
// conditions are true:
// 1.) The OutputSection is larger than the ThunkSectionSpacing. This
// accounts for the case where no single InputSectionDescription is
// larger than the OutputSection size. This is conservative but simple.
// 2.) The InputSectionDescription is larger than 4 KiB. This will prevent
// any assertion failures that an InputSectionDescription is < 4 KiB
// in size.
uint64_t isdSize = isd->sections.back()->outSecOff +
isd->sections.back()->getSize() -
isd->sections.front()->outSecOff;
if (os->size > target->getThunkSectionSpacing() && isdSize > 4096)
ts->roundUpSizeForErrata = true;
}
isd->thunkSections.push_back({ts, pass});
return ts;
}
@ -1820,9 +1857,7 @@ bool ThunkCreator::normalizeExistingThunk(Relocation &rel, uint64_t src) {
rel.sym->getVA(rel.addend) + getPCBias(rel.type)))
return true;
rel.sym = &t->destination;
// TODO Restore addend on all targets.
if (config->emachine == EM_AARCH64 || config->emachine == EM_PPC64)
rel.addend = t->addend;
rel.addend = t->addend;
if (rel.sym->isInPlt())
rel.expr = toPlt(rel.expr);
}
@ -1900,16 +1935,11 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> outputSections) {
rel.sym = t->getThunkTargetSym();
rel.expr = fromPlt(rel.expr);
// On AArch64 and PPC64, a jump/call relocation may be encoded as
// On AArch64 and PPC, a jump/call relocation may be encoded as
// STT_SECTION + non-zero addend, clear the addend after
// redirection.
//
// The addend of R_PPC_PLTREL24 should be ignored after changing to
// R_PC.
if (config->emachine == EM_AARCH64 ||
config->emachine == EM_PPC64 ||
(config->emachine == EM_PPC && rel.type == R_PPC_PLTREL24))
rel.addend = 0;
if (config->emachine != EM_MIPS)
rel.addend = -getPCBias(rel.type);
}
for (auto &p : isd->thunkSections)

View File

@ -2449,6 +2449,9 @@ PltSection::PltSection()
if (config->emachine == EM_PPC || config->emachine == EM_PPC64) {
name = ".glink";
alignment = 4;
// PLTresolve is at the end.
if (config->emachine == EM_PPC)
footerSize = 64;
}
// On x86 when IBT is enabled, this section contains the second PLT (lazy
@ -2486,7 +2489,7 @@ void PltSection::addEntry(Symbol &sym) {
}
size_t PltSection::getSize() const {
return headerSize + entries.size() * target->pltEntrySize;
return headerSize + entries.size() * target->pltEntrySize + footerSize;
}
bool PltSection::isNeeded() const {
@ -3451,19 +3454,14 @@ bool ARMExidxSyntheticSection::classof(const SectionBase *d) {
}
ThunkSection::ThunkSection(OutputSection *os, uint64_t off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
config->wordsize, ".text.thunk") {
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4,
".text.thunk") {
this->parent = os;
this->outSecOff = off;
}
// When the errata patching is on, we round the size up to a 4 KiB
// boundary. This limits the effect that adding Thunks has on the addresses
// of the program modulo 4 KiB. As the errata patching is sensitive to address
// modulo 4 KiB this can prevent further patches from being needed due to
// Thunk insertion.
size_t ThunkSection::getSize() const {
if (config->fixCortexA53Errata843419 || config->fixCortexA8)
if (roundUpSizeForErrata)
return alignTo(size, 4096);
return size;
}

View File

@ -683,9 +683,9 @@ class PltSection : public SyntheticSection {
void addEntry(Symbol &sym);
size_t getNumEntries() const { return entries.size(); }
size_t headerSize = 0;
size_t headerSize;
size_t footerSize = 0;
private:
std::vector<const Symbol *> entries;
};
@ -1069,6 +1069,10 @@ class ThunkSection : public SyntheticSection {
InputSection *getTargetInputSection() const;
bool assignOffsets();
// When true, round up reported size of section to 4 KiB. See comment
// in addThunkSection() for more details.
bool roundUpSizeForErrata = false;
private:
std::vector<Thunk *> thunks;
size_t size = 0;

View File

@ -245,8 +245,7 @@ class PPC32PltCallStub final : public Thunk {
// decide the offsets in the call stub.
PPC32PltCallStub(const InputSection &isec, const Relocation &rel,
Symbol &dest)
: Thunk(dest, rel.type == R_PPC_PLTREL24 ? rel.addend : 0),
file(isec.file) {}
: Thunk(dest, rel.addend), file(isec.file) {}
uint32_t size() override { return 16; }
void writeTo(uint8_t *buf) override;
void addSymbols(ThunkSection &isec) override;
@ -257,6 +256,14 @@ class PPC32PltCallStub final : public Thunk {
const InputFile *file;
};
class PPC32LongThunk final : public Thunk {
public:
PPC32LongThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
uint32_t size() override { return config->isPic ? 32 : 16; }
void writeTo(uint8_t *buf) override;
void addSymbols(ThunkSection &isec) override;
};
// PPC64 Plt call stubs.
// Any call site that needs to call through a plt entry needs a call stub in
// the .text section. The call stub is responsible for:
@ -765,6 +772,33 @@ bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
return !config->isPic || (isec.file == file && rel.addend == addend);
}
void PPC32LongThunk::addSymbols(ThunkSection &isec) {
addSymbol(saver.save("__LongThunk_" + destination.getName()), STT_FUNC, 0,
isec);
}
void PPC32LongThunk::writeTo(uint8_t *buf) {
auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; };
auto lo = [](uint32_t v) -> uint16_t { return v; };
uint32_t d = destination.getVA(addend);
if (config->isPic) {
uint32_t off = d - (getThunkTargetSym()->getVA() + 8);
write32(buf + 0, 0x7c0802a6); // mflr r12,0
write32(buf + 4, 0x429f0005); // bcl r20,r31,.+4
write32(buf + 8, 0x7d8802a6); // mtctr r12
write32(buf + 12, 0x3d8c0000 | ha(off)); // addis r12,r12,off@ha
write32(buf + 16, 0x398c0000 | lo(off)); // addi r12,r12,off@l
write32(buf + 20, 0x7c0803a6); // mtlr r0
buf += 24;
} else {
write32(buf + 0, 0x3d800000 | ha(d)); // lis r12,d@ha
write32(buf + 4, 0x398c0000 | lo(d)); // addi r12,r12,d@l
buf += 8;
}
write32(buf + 0, 0x7d8903a6); // mtctr r12
write32(buf + 4, 0x4e800420); // bctr
}
void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset) {
uint16_t offHa = (offset + 0x8000) >> 16;
uint16_t offLo = offset & 0xffff;
@ -902,9 +936,12 @@ static Thunk *addThunkMips(RelType type, Symbol &s) {
static Thunk *addThunkPPC32(const InputSection &isec, const Relocation &rel,
Symbol &s) {
assert((rel.type == R_PPC_REL24 || rel.type == R_PPC_PLTREL24) &&
assert((rel.type == R_PPC_LOCAL24PC || rel.type == R_PPC_REL24 ||
rel.type == R_PPC_PLTREL24) &&
"unexpected relocation type for thunk");
return make<PPC32PltCallStub>(isec, rel, s);
if (s.isInPlt())
return make<PPC32PltCallStub>(isec, rel, s);
return make<PPC32LongThunk>(s, rel.addend);
}
static Thunk *addThunkPPC64(RelType type, Symbol &s, int64_t a) {

View File

@ -30,6 +30,14 @@ ELF Improvements
with GNU now. (`r375051
<https://github.com/llvm/llvm-project/commit/48993d5ab9413f0e5b94dfa292a233ce55b09e3e>`_)
* New ``elf32btsmipn32_fbsd`` and ``elf32ltsmipn32_fbsd`` emulations
are supported.
* Relax MIPS ``jalr``and ``jr`` instructions marked by the ``R_MIPS_JALR``
relocation.
* Reduced size of linked MIPS binaries.
COFF Improvements
-----------------
@ -38,7 +46,33 @@ COFF Improvements
MinGW Improvements
------------------
* ...
* Allow using custom .edata sections from input object files (for use
by Wine)
(`dadc6f248868 <https://reviews.llvm.org/rGdadc6f248868>`)
* Don't implicitly create import libraries unless requested
(`6540e55067e3 <https://reviews.llvm.org/rG6540e55067e3>`)
* Support merging multiple resource object files
(`3d3a9b3b413d <https://reviews.llvm.org/rG3d3a9b3b413d>`)
and properly handle the default manifest object files that GCC can pass
(`d581dd501381 <https://reviews.llvm.org/rGd581dd501381>`)
* Demangle itanium symbol names in warnings/error messages
(`a66fc1c99f3e <https://reviews.llvm.org/rGa66fc1c99f3e>`)
* Print source locations for undefined references and duplicate symbols,
if possible
(`1d06d48bb346 <https://reviews.llvm.org/rG1d06d48bb346>`)
and
(`b38f577c015c <https://reviews.llvm.org/rGb38f577c015c>`)
* Look for more filename patterns when resolving ``-l`` options
(`0226c35262df <https://reviews.llvm.org/rG0226c35262df>`)
* Don't error out on duplicate absolute symbols with the same value
(which can happen for the default-null symbol for weak symbols)
(`1737cc750c46 <https://reviews.llvm.org/rG1737cc750c46>`)
MachO Improvements
------------------

View File

@ -69,6 +69,8 @@ FormatCache::Entry &FormatCache::GetEntry(ConstString type) {
return m_map[type];
}
namespace lldb_private {
template<> bool FormatCache::Entry::IsCached<lldb::TypeFormatImplSP>() {
return IsFormatCached();
}
@ -79,6 +81,8 @@ template<> bool FormatCache::Entry::IsCached<lldb::SyntheticChildrenSP>() {
return IsSyntheticCached();
}
} // namespace lldb_private
template <typename ImplSP>
bool FormatCache::Get(ConstString type, ImplSP &format_impl_sp) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);

View File

@ -55,6 +55,8 @@ bool LanguageCategory::Get(FormattersMatchData &match_data,
return result;
}
namespace lldb_private {
/// Explicit instantiations for the three types.
/// \{
template bool
@ -83,6 +85,8 @@ auto &LanguageCategory::GetHardcodedFinder<lldb::SyntheticChildrenSP>() {
return m_hardcoded_synthetics;
}
} // namespace lldb_private
template <typename ImplSP>
bool LanguageCategory::GetHardcoded(FormatManager &fmt_mgr,
FormattersMatchData &match_data,

View File

@ -65,7 +65,8 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
else {
for (auto &entry : args.entries()) {
if (!entry.ref().empty())
option_arg_vector->emplace_back("<argument>", -1, entry.ref());
option_arg_vector->emplace_back(std::string("<argument>"), -1,
std::string(entry.ref()));
}
}
}

View File

@ -1061,8 +1061,8 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
}
if (!option_arg)
option_arg = "<no-argument>";
option_arg_vector->emplace_back(option_str.GetString(), has_arg,
option_arg);
option_arg_vector->emplace_back(std::string(option_str.GetString()),
has_arg, std::string(option_arg));
// Find option in the argument list; also see if it was supposed to take an
// argument and if one was supplied. Remove option (and argument, if

View File

@ -85,35 +85,6 @@ static bool DeclKindIsCXXClass(clang::Decl::Kind decl_kind) {
return false;
}
struct BitfieldInfo {
uint64_t bit_size;
uint64_t bit_offset;
BitfieldInfo()
: bit_size(LLDB_INVALID_ADDRESS), bit_offset(LLDB_INVALID_ADDRESS) {}
void Clear() {
bit_size = LLDB_INVALID_ADDRESS;
bit_offset = LLDB_INVALID_ADDRESS;
}
bool IsValid() const {
return (bit_size != LLDB_INVALID_ADDRESS) &&
(bit_offset != LLDB_INVALID_ADDRESS);
}
bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
if (IsValid()) {
// This bitfield info is valid, so any subsequent bitfields must not
// overlap and must be at a higher bit offset than any previous bitfield
// + size.
return (bit_size + bit_offset) <= next_bit_offset;
} else {
// If the this BitfieldInfo is not valid, then any offset isOK
return true;
}
}
};
ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {
if (!m_clang_ast_importer_up) {
@ -2419,7 +2390,7 @@ void DWARFASTParserClang::ParseSingleMember(
lldb::AccessType &default_accessibility,
DelayedPropertyList &delayed_properties,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
BitfieldInfo &last_field_info) {
FieldInfo &last_field_info) {
ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
const dw_tag_t tag = die.Tag();
// Get the parent byte size so we can verify any members will fit
@ -2453,6 +2424,14 @@ void DWARFASTParserClang::ParseSingleMember(
const dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
// DW_AT_data_member_location indicates the byte offset of the
// word from the base address of the structure.
//
// DW_AT_bit_offset indicates how many bits into the word
// (according to the host endianness) the low-order bit of the
// field starts. AT_bit_offset can be negative.
//
// DW_AT_bit_size indicates the size of the field in bits.
switch (attr) {
case DW_AT_name:
name = form_value.AsCString();
@ -2603,36 +2582,24 @@ void DWARFASTParserClang::ParseSingleMember(
Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
clang::FieldDecl *field_decl = nullptr;
const uint64_t character_width = 8;
const uint64_t word_width = 32;
if (tag == DW_TAG_member) {
if (member_type) {
CompilerType member_clang_type = member_type->GetLayoutCompilerType();
if (accessibility == eAccessNone)
accessibility = default_accessibility;
member_accessibilities.push_back(accessibility);
uint64_t field_bit_offset =
(member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
if (bit_size > 0) {
BitfieldInfo this_field_info;
if (bit_size > 0) {
FieldInfo this_field_info;
this_field_info.bit_offset = field_bit_offset;
this_field_info.bit_size = bit_size;
/////////////////////////////////////////////////////////////
// How to locate a field given the DWARF debug information
//
// AT_byte_size indicates the size of the word in which the bit
// offset must be interpreted.
//
// AT_data_member_location indicates the byte offset of the
// word from the base address of the structure.
//
// AT_bit_offset indicates how many bits into the word
// (according to the host endianness) the low-order bit of the
// field starts. AT_bit_offset can be negative.
//
// AT_bit_size indicates the size of the field in bits.
/////////////////////////////////////////////////////////////
if (data_bit_offset != UINT64_MAX) {
this_field_info.bit_offset = data_bit_offset;
} else {
@ -2649,8 +2616,9 @@ void DWARFASTParserClang::ParseSingleMember(
}
if ((this_field_info.bit_offset >= parent_bit_size) ||
!last_field_info.NextBitfieldOffsetIsValid(
this_field_info.bit_offset)) {
(last_field_info.IsBitfield() &&
!last_field_info.NextBitfieldOffsetIsValid(
this_field_info.bit_offset))) {
ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
objfile->GetModule()->ReportWarning(
"0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
@ -2659,40 +2627,12 @@ void DWARFASTParserClang::ParseSingleMember(
"compiler and include the preprocessed output for %s\n",
die.GetID(), DW_TAG_value_to_name(tag), name,
this_field_info.bit_offset, GetUnitName(parent_die).c_str());
this_field_info.Clear();
return;
}
// Update the field bit offset we will report for layout
field_bit_offset = this_field_info.bit_offset;
// If the member to be emitted did not start on a character
// boundary and there is empty space between the last field and
// this one, then we need to emit an anonymous member filling
// up the space up to its start. There are three cases here:
//
// 1 If the previous member ended on a character boundary, then
// we can emit an
// anonymous member starting at the most recent character
// boundary.
//
// 2 If the previous member did not end on a character boundary
// and the distance
// from the end of the previous member to the current member
// is less than a
// word width, then we can emit an anonymous member starting
// right after the
// previous member and right before this member.
//
// 3 If the previous member did not end on a character boundary
// and the distance
// from the end of the previous member to the current member
// is greater than
// or equal a word width, then we act as in Case 1.
const uint64_t character_width = 8;
const uint64_t word_width = 32;
// Objective-C has invalid DW_AT_bit_offset values in older
// versions of clang, so we have to be careful and only insert
// unnamed bitfields if we have a new enough clang.
@ -2704,53 +2644,57 @@ void DWARFASTParserClang::ParseSingleMember(
die.GetCU()->Supports_unnamed_objc_bitfields();
if (detect_unnamed_bitfields) {
BitfieldInfo anon_field_info;
clang::Optional<FieldInfo> unnamed_field_info;
uint64_t last_field_end = 0;
if ((this_field_info.bit_offset % character_width) !=
0) // not char aligned
{
uint64_t last_field_end = 0;
last_field_end =
last_field_info.bit_offset + last_field_info.bit_size;
if (last_field_info.IsValid())
last_field_end =
last_field_info.bit_offset + last_field_info.bit_size;
if (this_field_info.bit_offset != last_field_end) {
if (((last_field_end % character_width) == 0) || // case 1
(this_field_info.bit_offset - last_field_end >=
word_width)) // case 3
{
anon_field_info.bit_size =
this_field_info.bit_offset % character_width;
anon_field_info.bit_offset =
this_field_info.bit_offset - anon_field_info.bit_size;
} else // case 2
{
anon_field_info.bit_size =
this_field_info.bit_offset - last_field_end;
anon_field_info.bit_offset = last_field_end;
}
}
if (!last_field_info.IsBitfield()) {
// The last field was not a bit-field...
// but if it did take up the entire word then we need to extend
// last_field_end so the bit-field does not step into the last
// fields padding.
if (last_field_end != 0 && ((last_field_end % word_width) != 0))
last_field_end += word_width - (last_field_end % word_width);
}
if (anon_field_info.IsValid()) {
// If we have a gap between the last_field_end and the current
// field we have an unnamed bit-field
if (this_field_info.bit_offset != last_field_end &&
!(this_field_info.bit_offset < last_field_end)) {
unnamed_field_info = FieldInfo{};
unnamed_field_info->bit_size =
this_field_info.bit_offset - last_field_end;
unnamed_field_info->bit_offset = last_field_end;
}
if (unnamed_field_info) {
clang::FieldDecl *unnamed_bitfield_decl =
ClangASTContext::AddFieldToRecordType(
class_clang_type, llvm::StringRef(),
m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
word_width),
accessibility, anon_field_info.bit_size);
accessibility, unnamed_field_info->bit_size);
layout_info.field_offsets.insert(std::make_pair(
unnamed_bitfield_decl, anon_field_info.bit_offset));
unnamed_bitfield_decl, unnamed_field_info->bit_offset));
}
}
last_field_info = this_field_info;
last_field_info.SetIsBitfield(true);
} else {
last_field_info.Clear();
last_field_info.bit_offset = field_bit_offset;
if (llvm::Optional<uint64_t> clang_type_size =
member_clang_type.GetByteSize(nullptr)) {
last_field_info.bit_size = *clang_type_size * character_width;
}
last_field_info.SetIsBitfield(false);
}
CompilerType member_clang_type = member_type->GetLayoutCompilerType();
if (!member_clang_type.IsCompleteType())
member_clang_type.GetCompleteType();
@ -2885,7 +2829,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (!parent_die)
return false;
BitfieldInfo last_field_info;
FieldInfo last_field_info;
ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
ClangASTContext *ast =

View File

@ -170,33 +170,20 @@ class DWARFASTParserClang : public DWARFASTParser {
lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
private:
struct BitfieldInfo {
uint64_t bit_size;
uint64_t bit_offset;
struct FieldInfo {
uint64_t bit_size = 0;
uint64_t bit_offset = 0;
bool is_bitfield = false;
BitfieldInfo()
: bit_size(LLDB_INVALID_ADDRESS), bit_offset(LLDB_INVALID_ADDRESS) {}
FieldInfo() = default;
void Clear() {
bit_size = LLDB_INVALID_ADDRESS;
bit_offset = LLDB_INVALID_ADDRESS;
}
bool IsValid() const {
return (bit_size != LLDB_INVALID_ADDRESS) &&
(bit_offset != LLDB_INVALID_ADDRESS);
}
void SetIsBitfield(bool flag) { is_bitfield = flag; }
bool IsBitfield() { return is_bitfield; }
bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
if (IsValid()) {
// This bitfield info is valid, so any subsequent bitfields must not
// overlap and must be at a higher bit offset than any previous bitfield
// + size.
return (bit_size + bit_offset) <= next_bit_offset;
} else {
// If the this BitfieldInfo is not valid, then any offset isOK
return true;
}
// Any subsequent bitfields must not overlap and must be at a higher
// bit offset than any previous bitfield + size.
return (bit_size + bit_offset) <= next_bit_offset;
}
};
@ -208,7 +195,7 @@ class DWARFASTParserClang : public DWARFASTParser {
lldb::AccessType &default_accessibility,
DelayedPropertyList &delayed_properties,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
BitfieldInfo &last_field_info);
FieldInfo &last_field_info);
bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type,
lldb_private::CompilerType &clang_type);

View File

@ -77,7 +77,8 @@ namespace llvm {
static constexpr size_t strLen(const char *Str) {
#if __cplusplus > 201402L
return std::char_traits<char>::length(Str);
#elif __has_builtin(__builtin_strlen) || defined(__GNUC__) || defined(_MSC_VER)
#elif __has_builtin(__builtin_strlen) || defined(__GNUC__) || \
(defined(_MSC_VER) && _MSC_VER >= 1916)
return __builtin_strlen(Str);
#else
const char *Begin = Str;

View File

@ -135,7 +135,6 @@ class AsmPrinter : public MachineFunctionPass {
MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs;
private:
MCSymbol *CurrentFnBegin = nullptr;
MCSymbol *CurrentFnEnd = nullptr;
MCSymbol *CurExceptionSym = nullptr;
@ -148,6 +147,8 @@ class AsmPrinter : public MachineFunctionPass {
static char ID;
protected:
MCSymbol *CurrentFnBegin = nullptr;
/// Protected struct HandlerInfo and Handlers permit target extended
/// AsmPrinter adds their own handlers.
struct HandlerInfo {

View File

@ -13,7 +13,9 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include <memory>
namespace llvm {
@ -28,24 +30,31 @@ namespace orc {
class JITTargetMachineBuilder;
IRMaterializationUnit::ManglingOptions
irManglingOptionsFromTargetOptions(const TargetOptions &Opts);
/// Simple compile functor: Takes a single IR module and returns an ObjectFile.
/// This compiler supports a single compilation thread and LLVMContext only.
/// For multithreaded compilation, use ConcurrentIRCompiler below.
class SimpleCompiler {
class SimpleCompiler : public IRCompileLayer::IRCompiler {
public:
using CompileResult = std::unique_ptr<MemoryBuffer>;
/// Construct a simple compile functor with the given target.
SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
: TM(TM), ObjCache(ObjCache) {}
: IRCompiler(irManglingOptionsFromTargetOptions(TM.Options)), TM(TM),
ObjCache(ObjCache) {}
/// Set an ObjectCache to query before compiling.
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
/// Compile a Module to an ObjectFile.
CompileResult operator()(Module &M);
Expected<CompileResult> operator()(Module &M) override;
private:
IRMaterializationUnit::ManglingOptions
manglingOptionsForTargetMachine(const TargetMachine &TM);
CompileResult tryToLoadFromObjectCache(const Module &M);
void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer);
@ -73,14 +82,14 @@ class TMOwningSimpleCompiler : public SimpleCompiler {
///
/// This class creates a new TargetMachine and SimpleCompiler instance for each
/// compile.
class ConcurrentIRCompiler {
class ConcurrentIRCompiler : public IRCompileLayer::IRCompiler {
public:
ConcurrentIRCompiler(JITTargetMachineBuilder JTMB,
ObjectCache *ObjCache = nullptr);
void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; }
std::unique_ptr<MemoryBuffer> operator()(Module &M);
Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) override;
private:
JITTargetMachineBuilder JTMB;

View File

@ -489,13 +489,18 @@ class MaterializationResponsibility {
/// is guaranteed to return Error::success() and can be wrapped with cantFail.
Error notifyEmitted();
/// Adds new symbols to the JITDylib and this responsibility instance.
/// JITDylib entries start out in the materializing state.
/// Attempt to claim responsibility for new definitions. This method can be
/// used to claim responsibility for symbols that are added to a
/// materialization unit during the compilation process (e.g. literal pool
/// symbols). Symbol linkage rules are the same as for symbols that are
/// defined up front: duplicate strong definitions will result in errors.
/// Duplicate weak definitions will be discarded (in which case they will
/// not be added to this responsibility instance).
///
/// This method can be used by materialization units that want to add
/// additional symbols at materialization time (e.g. stubs, compile
/// callbacks, metadata).
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
Error defineMaterializing(SymbolFlagsMap SymbolFlags);
/// Notify all not-yet-emitted covered by this MaterializationResponsibility
/// instance that an error has occurred.
@ -1023,7 +1028,7 @@ class JITDylib {
const SymbolStringPtr &DependantName,
MaterializingInfo &EmittedMI);
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
void replace(std::unique_ptr<MaterializationUnit> MU);

View File

@ -29,14 +29,29 @@ namespace orc {
class IRCompileLayer : public IRLayer {
public:
using CompileFunction =
std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>;
class IRCompiler {
public:
IRCompiler(IRMaterializationUnit::ManglingOptions MO) : MO(std::move(MO)) {}
virtual ~IRCompiler();
const IRMaterializationUnit::ManglingOptions &getManglingOptions() const {
return MO;
}
virtual Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) = 0;
protected:
IRMaterializationUnit::ManglingOptions &manglingOptions() { return MO; }
private:
IRMaterializationUnit::ManglingOptions MO;
};
using NotifyCompiledFunction =
std::function<void(VModuleKey K, ThreadSafeModule TSM)>;
IRCompileLayer(ExecutionSession &ES, ObjectLayer &BaseLayer,
CompileFunction Compile);
std::unique_ptr<IRCompiler> Compile);
IRCompiler &getCompiler() { return *Compile; }
void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled);
@ -45,7 +60,8 @@ class IRCompileLayer : public IRLayer {
private:
mutable std::mutex IRLayerMutex;
ObjectLayer &BaseLayer;
CompileFunction Compile;
std::unique_ptr<IRCompiler> Compile;
const IRMaterializationUnit::ManglingOptions *ManglingOpts;
NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
};
@ -90,7 +106,10 @@ class LegacyIRCompileLayer {
/// Compile the module, and add the resulting object to the base layer
/// along with the given memory manager and symbol resolver.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
if (auto Err = BaseLayer.addObject(std::move(K), Compile(*M)))
auto Obj = Compile(*M);
if (!Obj)
return Obj.takeError();
if (auto Err = BaseLayer.addObject(std::move(K), std::move(*Obj)))
return Err;
if (NotifyCompiled)
NotifyCompiled(std::move(K), std::move(M));

View File

@ -124,7 +124,7 @@ class LLJIT {
static std::unique_ptr<ObjectLayer>
createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
static Expected<IRCompileLayer::CompileFunction>
static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB);
/// Create an LLJIT instance with a single compile thread.
@ -192,7 +192,7 @@ class LLJITBuilderState {
ExecutionSession &, const Triple &TT)>;
using CompileFunctionCreator =
std::function<Expected<IRCompileLayer::CompileFunction>(
std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(
JITTargetMachineBuilder JTMB)>;
std::unique_ptr<ExecutionSession> ES;

View File

@ -21,15 +21,62 @@
namespace llvm {
namespace orc {
/// IRMaterializationUnit is a convenient base class for MaterializationUnits
/// wrapping LLVM IR. Represents materialization responsibility for all symbols
/// in the given module. If symbols are overridden by other definitions, then
/// their linkage is changed to available-externally.
class IRMaterializationUnit : public MaterializationUnit {
public:
struct ManglingOptions {
bool EmulatedTLS = false;
};
using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
/// Create an IRMaterializationLayer. Scans the module to build the
/// SymbolFlags and SymbolToDefinition maps.
IRMaterializationUnit(ExecutionSession &ES, const ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K);
/// Create an IRMaterializationLayer from a module, and pre-existing
/// SymbolFlags and SymbolToDefinition maps. The maps must provide
/// entries for each definition in M.
/// This constructor is useful for delegating work from one
/// IRMaterializationUnit to another.
IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K,
SymbolFlagsMap SymbolFlags,
SymbolNameToDefinitionMap SymbolToDefinition);
/// Return the ModuleIdentifier as the name for this MaterializationUnit.
StringRef getName() const override;
const ThreadSafeModule &getModule() const { return TSM; }
protected:
ThreadSafeModule TSM;
SymbolNameToDefinitionMap SymbolToDefinition;
private:
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
};
/// Interface for layers that accept LLVM IR.
class IRLayer {
public:
IRLayer(ExecutionSession &ES);
IRLayer(ExecutionSession &ES,
const IRMaterializationUnit::ManglingOptions *&MO)
: ES(ES), MO(MO) {}
virtual ~IRLayer();
/// Returns the ExecutionSession for this layer.
ExecutionSession &getExecutionSession() { return ES; }
/// Get the mangling options for this layer.
const IRMaterializationUnit::ManglingOptions *&getManglingOptions() const {
return MO;
}
/// Sets the CloneToNewContextOnEmit flag (false by default).
///
/// When set, IR modules added to this layer will be cloned on to a new
@ -57,49 +104,15 @@ class IRLayer {
private:
bool CloneToNewContextOnEmit = false;
ExecutionSession &ES;
};
/// IRMaterializationUnit is a convenient base class for MaterializationUnits
/// wrapping LLVM IR. Represents materialization responsibility for all symbols
/// in the given module. If symbols are overridden by other definitions, then
/// their linkage is changed to available-externally.
class IRMaterializationUnit : public MaterializationUnit {
public:
using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
/// Create an IRMaterializationLayer. Scans the module to build the
/// SymbolFlags and SymbolToDefinition maps.
IRMaterializationUnit(ExecutionSession &ES, ThreadSafeModule TSM,
VModuleKey K);
/// Create an IRMaterializationLayer from a module, and pre-existing
/// SymbolFlags and SymbolToDefinition maps. The maps must provide
/// entries for each definition in M.
/// This constructor is useful for delegating work from one
/// IRMaterializationUnit to another.
IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K,
SymbolFlagsMap SymbolFlags,
SymbolNameToDefinitionMap SymbolToDefinition);
/// Return the ModuleIdentifier as the name for this MaterializationUnit.
StringRef getName() const override;
const ThreadSafeModule &getModule() const { return TSM; }
protected:
ThreadSafeModule TSM;
SymbolNameToDefinitionMap SymbolToDefinition;
private:
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
const IRMaterializationUnit::ManglingOptions *&MO;
};
/// MaterializationUnit that materializes modules by calling the 'emit' method
/// on the given IRLayer.
class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
public:
BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K,
ThreadSafeModule TSM);
BasicIRLayerMaterializationUnit(IRLayer &L, const ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K);
private:

View File

@ -182,8 +182,8 @@ class IRSpeculationLayer : public IRLayer {
IRSpeculationLayer(ExecutionSession &ES, IRCompileLayer &BaseLayer,
Speculator &Spec, MangleAndInterner &Mangle,
ResultEval Interpreter)
: IRLayer(ES), NextLayer(BaseLayer), S(Spec), Mangle(Mangle),
QueryAnalysis(Interpreter) {}
: IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer),
S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {}
void emit(MaterializationResponsibility R, ThreadSafeModule TSM);

View File

@ -99,7 +99,8 @@ class CrashRecoveryContext {
/// Explicitly trigger a crash recovery in the current process, and
/// return failure from RunSafely(). This function does not return.
void HandleCrash();
LLVM_ATTRIBUTE_NORETURN
void HandleExit(int RetCode);
/// In case of a crash, this is the crash identifier.
int RetCode = 0;

View File

@ -201,6 +201,12 @@ class Process {
/// Get the result of a process wide random number generator. The
/// generator will be automatically seeded in non-deterministic fashion.
static unsigned GetRandomNumber();
/// Equivalent to ::exit(), except when running inside a CrashRecoveryContext.
/// In that case, the control flow will resume after RunSafely(), like for a
/// crash, rather than exiting the current process.
LLVM_ATTRIBUTE_NORETURN
static void Exit(int RetCode);
};
}

View File

@ -62,6 +62,8 @@ class PassManagerBuilder {
typedef std::function<void(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM)>
ExtensionFn;
typedef int GlobalExtensionID;
enum ExtensionPointTy {
/// EP_EarlyAsPossible - This extension point allows adding passes before
/// any other transformations, allowing them to see the code as it is coming
@ -193,7 +195,17 @@ class PassManagerBuilder {
/// Adds an extension that will be used by all PassManagerBuilder instances.
/// This is intended to be used by plugins, to register a set of
/// optimisations to run automatically.
static void addGlobalExtension(ExtensionPointTy Ty, ExtensionFn Fn);
///
/// \returns A global extension identifier that can be used to remove the
/// extension.
static GlobalExtensionID addGlobalExtension(ExtensionPointTy Ty,
ExtensionFn Fn);
/// Removes an extension that was previously added using addGlobalExtension.
/// This is also intended to be used by plugins, to remove any extension that
/// was previously registered before being unloaded.
///
/// \param ExtensionID Identifier of the extension to be removed.
static void removeGlobalExtension(GlobalExtensionID ExtensionID);
void addExtension(ExtensionPointTy Ty, ExtensionFn Fn);
private:
@ -222,10 +234,20 @@ class PassManagerBuilder {
/// used by optimizer plugins to allow all front ends to transparently use
/// them. Create a static instance of this class in your plugin, providing a
/// private function that the PassManagerBuilder can use to add your passes.
struct RegisterStandardPasses {
class RegisterStandardPasses {
PassManagerBuilder::GlobalExtensionID ExtensionID;
public:
RegisterStandardPasses(PassManagerBuilder::ExtensionPointTy Ty,
PassManagerBuilder::ExtensionFn Fn) {
PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn));
ExtensionID = PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn));
}
~RegisterStandardPasses() {
// If the collection holding the global extensions is destroyed after the
// plugin is unloaded, the extension has to be removed here. Indeed, the
// destructor of the ExtensionFn may reference code in the plugin.
PassManagerBuilder::removeGlobalExtension(ExtensionID);
}
};

View File

@ -709,15 +709,21 @@ void AsmPrinter::EmitFunctionHeader() {
// Emit M NOPs for -fpatchable-function-entry=N,M where M>0. We arbitrarily
// place prefix data before NOPs.
unsigned PatchableFunctionPrefix = 0;
unsigned PatchableFunctionEntry = 0;
(void)F.getFnAttribute("patchable-function-prefix")
.getValueAsString()
.getAsInteger(10, PatchableFunctionPrefix);
(void)F.getFnAttribute("patchable-function-entry")
.getValueAsString()
.getAsInteger(10, PatchableFunctionEntry);
if (PatchableFunctionPrefix) {
CurrentPatchableFunctionEntrySym =
OutContext.createLinkerPrivateTempSymbol();
OutStreamer->EmitLabel(CurrentPatchableFunctionEntrySym);
emitNops(PatchableFunctionPrefix);
} else {
} else if (PatchableFunctionEntry) {
// May be reassigned when emitting the body, to reference the label after
// the initial BTI (AArch64) or endbr32/endbr64 (x86).
CurrentPatchableFunctionEntrySym = CurrentFnBegin;
}

View File

@ -968,8 +968,8 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target),
MachineLocation(CallReg));
} else {
DIE *CalleeDIE = getDIE(CalleeSP);
assert(CalleeDIE && "Could not find DIE for call site entry origin");
DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
assert(CalleeDIE && "Could not create DIE for call site entry origin");
addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin),
*CalleeDIE);
}

View File

@ -540,14 +540,6 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,
}
}
DIE &DwarfDebug::constructSubprogramDefinitionDIE(const DISubprogram *SP) {
DICompileUnit *Unit = SP->getUnit();
assert(SP->isDefinition() && "Subprogram not a definition");
assert(Unit && "Subprogram definition without parent unit");
auto &CU = getOrCreateDwarfCompileUnit(Unit);
return *CU.getOrCreateSubprogramDIE(SP);
}
/// Try to interpret values loaded into registers that forward parameters
/// for \p CallMI. Store parameters with interpreted value into \p Params.
static void collectCallSiteParameters(const MachineInstr *CallMI,
@ -758,17 +750,6 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
if (!CalleeDecl || !CalleeDecl->getSubprogram())
continue;
CalleeSP = CalleeDecl->getSubprogram();
if (CalleeSP->isDefinition()) {
// Ensure that a subprogram DIE for the callee is available in the
// appropriate CU.
constructSubprogramDefinitionDIE(CalleeSP);
} else {
// Create the declaration DIE if it is missing. This is required to
// support compilation of old bitcode with an incomplete list of
// retained metadata.
CU.getOrCreateSubprogramDIE(CalleeSP);
}
}
// TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
@ -924,6 +905,11 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
}
// Create DIEs for function declarations used for call site debug info.
for (auto Scope : DIUnit->getRetainedTypes())
if (auto *SP = dyn_cast_or_null<DISubprogram>(Scope))
NewCU.getOrCreateSubprogramDIE(SP);
CUMap.insert({DIUnit, &NewCU});
CUDieMap.insert({&NewCU.getUnitDie(), &NewCU});
return NewCU;

View File

@ -442,9 +442,6 @@ class DwarfDebug : public DebugHandlerBase {
/// Construct a DIE for this abstract scope.
void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
/// Construct a DIE for the subprogram definition \p SP and return it.
DIE &constructSubprogramDefinitionDIE(const DISubprogram *SP);
/// Construct DIEs for call site entries describing the calls in \p MF.
void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU,
DIE &ScopeDIE, const MachineFunction &MF);

View File

@ -188,9 +188,8 @@ int64_t DwarfUnit::getDefaultLowerBound() const {
/// Check whether the DIE for this MDNode can be shared across CUs.
bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const {
// When the MDNode can be part of the type system (this includes subprogram
// declarations *and* subprogram definitions, even local definitions), the
// DIE must be shared across CUs.
// When the MDNode can be part of the type system, the DIE can be shared
// across CUs.
// Combining type units and cross-CU DIE sharing is lower value (since
// cross-CU DIE sharing is used in LTO and removes type redundancy at that
// level already) but may be implementable for some value in projects
@ -198,7 +197,9 @@ bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const {
// together.
if (isDwoUnit() && !DD->shareAcrossDWOCUs())
return false;
return (isa<DIType>(D) || isa<DISubprogram>(D)) && !DD->generateTypeUnits();
return (isa<DIType>(D) ||
(isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) &&
!DD->generateTypeUnits();
}
DIE *DwarfUnit::getDIE(const DINode *D) const {

View File

@ -6857,12 +6857,20 @@ static bool splitMergedValStore(StoreInst &SI, const DataLayout &DL,
Value *Addr = Builder.CreateBitCast(
SI.getOperand(1),
SplitStoreType->getPointerTo(SI.getPointerAddressSpace()));
if ((IsLE && Upper) || (!IsLE && !Upper))
const bool IsOffsetStore = (IsLE && Upper) || (!IsLE && !Upper);
if (IsOffsetStore)
Addr = Builder.CreateGEP(
SplitStoreType, Addr,
ConstantInt::get(Type::getInt32Ty(SI.getContext()), 1));
MaybeAlign Alignment(SI.getAlignment());
if (IsOffsetStore && Alignment) {
// When splitting the store in half, naturally one half will retain the
// alignment of the original wider store, regardless of whether it was
// over-aligned or not, while the other will require adjustment.
Alignment = commonAlignment(Alignment, HalfValBitSize / 8);
}
Builder.CreateAlignedStore(
V, Addr, Upper ? SI.getAlignment() / 2 : SI.getAlignment());
V, Addr, Alignment.hasValue() ? Alignment.getValue().value() : 0);
};
CreateSplitStore(LValue, false);

View File

@ -1385,7 +1385,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
if (!V) {
// Currently the optimizer can produce this; insert an undef to
// help debugging. Probably the optimizer should not do this.
MIRBuilder.buildDirectDbgValue(0, DI.getVariable(), DI.getExpression());
MIRBuilder.buildIndirectDbgValue(0, DI.getVariable(), DI.getExpression());
} else if (const auto *CI = dyn_cast<Constant>(V)) {
MIRBuilder.buildConstDbgValue(*CI, DI.getVariable(), DI.getExpression());
} else {

View File

@ -107,13 +107,9 @@ MachineIRBuilder::buildIndirectDbgValue(Register Reg, const MDNode *Variable,
assert(
cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
"Expected inlined-at fields to agree");
// DBG_VALUE insts now carry IR-level indirection in their DIExpression
// rather than encoding it in the instruction itself.
const DIExpression *DIExpr = cast<DIExpression>(Expr);
DIExpr = DIExpression::append(DIExpr, {dwarf::DW_OP_deref});
return insertInstr(BuildMI(getMF(), getDL(),
getTII().get(TargetOpcode::DBG_VALUE),
/*IsIndirect*/ false, Reg, Variable, DIExpr));
/*IsIndirect*/ true, Reg, Variable, Expr));
}
MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
@ -124,15 +120,11 @@ MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
assert(
cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
"Expected inlined-at fields to agree");
// DBG_VALUE insts now carry IR-level indirection in their DIExpression
// rather than encoding it in the instruction itself.
const DIExpression *DIExpr = cast<DIExpression>(Expr);
DIExpr = DIExpression::append(DIExpr, {dwarf::DW_OP_deref});
return buildInstr(TargetOpcode::DBG_VALUE)
.addFrameIndex(FI)
.addReg(0)
.addImm(0)
.addMetadata(Variable)
.addMetadata(DIExpr);
.addMetadata(Expr);
}
MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
@ -156,7 +148,7 @@ MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
MIB.addReg(0U);
}
return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr);
return MIB.addImm(0).addMetadata(Variable).addMetadata(Expr);
}
MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) {

View File

@ -524,6 +524,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k), ++idx) {
GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage();
std::string Name = Globals[k]->getName();
GlobalValue::VisibilityTypes Visibility = Globals[k]->getVisibility();
GlobalValue::DLLStorageClassTypes DLLStorage =
Globals[k]->getDLLStorageClass();
@ -549,6 +550,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,
if (Linkage != GlobalValue::InternalLinkage || !IsMachO) {
GlobalAlias *GA = GlobalAlias::create(Tys[StructIdxs[idx]], AddrSpace,
Linkage, Name, GEP, &M);
GA->setVisibility(Visibility);
GA->setDLLStorageClass(DLLStorage);
}

View File

@ -100,27 +100,28 @@ enum : unsigned { UndefLocNo = ~0U };
/// usage of the location.
class DbgValueLocation {
public:
DbgValueLocation(unsigned LocNo)
: LocNo(LocNo) {
DbgValueLocation(unsigned LocNo, bool WasIndirect)
: LocNo(LocNo), WasIndirect(WasIndirect) {
static_assert(sizeof(*this) == sizeof(unsigned), "bad bitfield packing");
assert(locNo() == LocNo && "location truncation");
}
DbgValueLocation() : LocNo(0) {}
DbgValueLocation() : LocNo(0), WasIndirect(0) {}
unsigned locNo() const {
// Fix up the undef location number, which gets truncated.
return LocNo == INT_MAX ? UndefLocNo : LocNo;
}
bool wasIndirect() const { return WasIndirect; }
bool isUndef() const { return locNo() == UndefLocNo; }
DbgValueLocation changeLocNo(unsigned NewLocNo) const {
return DbgValueLocation(NewLocNo);
return DbgValueLocation(NewLocNo, WasIndirect);
}
friend inline bool operator==(const DbgValueLocation &LHS,
const DbgValueLocation &RHS) {
return LHS.LocNo == RHS.LocNo;
return LHS.LocNo == RHS.LocNo && LHS.WasIndirect == RHS.WasIndirect;
}
friend inline bool operator!=(const DbgValueLocation &LHS,
@ -129,7 +130,8 @@ class DbgValueLocation {
}
private:
unsigned LocNo;
unsigned LocNo : 31;
unsigned WasIndirect : 1;
};
/// Map of where a user value is live, and its location.
@ -166,6 +168,10 @@ class UserValue {
/// Map of slot indices where this value is live.
LocMap locInts;
/// Set of interval start indexes that have been trimmed to the
/// lexical scope.
SmallSet<SlotIndex, 2> trimmedDefs;
/// Insert a DBG_VALUE into MBB at Idx for LocNo.
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
SlotIndex StopIdx, DbgValueLocation Loc, bool Spilled,
@ -279,8 +285,8 @@ class UserValue {
void mapVirtRegs(LDVImpl *LDV);
/// Add a definition point to this value.
void addDef(SlotIndex Idx, const MachineOperand &LocMO) {
DbgValueLocation Loc(getLocationNo(LocMO));
void addDef(SlotIndex Idx, const MachineOperand &LocMO, bool IsIndirect) {
DbgValueLocation Loc(getLocationNo(LocMO), IsIndirect);
// Add a singular (Idx,Idx) -> Loc mapping.
LocMap::iterator I = locInts.find(Idx);
if (!I.valid() || I.start() != Idx)
@ -315,10 +321,11 @@ class UserValue {
///
/// \param LI Scan for copies of the value in LI->reg.
/// \param LocNo Location number of LI->reg.
/// \param WasIndirect Indicates if the original use of LI->reg was indirect
/// \param Kills Points where the range of LocNo could be extended.
/// \param [in,out] NewDefs Append (Idx, LocNo) of inserted defs here.
void addDefsFromCopies(
LiveInterval *LI, unsigned LocNo,
LiveInterval *LI, unsigned LocNo, bool WasIndirect,
const SmallVectorImpl<SlotIndex> &Kills,
SmallVectorImpl<std::pair<SlotIndex, DbgValueLocation>> &NewDefs,
MachineRegisterInfo &MRI, LiveIntervals &LIS);
@ -538,6 +545,8 @@ void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
OS << "undef";
else {
OS << I.value().locNo();
if (I.value().wasIndirect())
OS << " ind";
}
}
for (unsigned i = 0, e = locations.size(); i != e; ++i) {
@ -646,18 +655,19 @@ bool LDVImpl::handleDebugValue(MachineInstr &MI, SlotIndex Idx) {
}
// Get or create the UserValue for (variable,offset) here.
assert(!MI.getOperand(1).isImm() && "DBG_VALUE with indirect flag before "
"LiveDebugVariables");
bool IsIndirect = MI.getOperand(1).isImm();
if (IsIndirect)
assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset");
const DILocalVariable *Var = MI.getDebugVariable();
const DIExpression *Expr = MI.getDebugExpression();
UserValue *UV =
getUserValue(Var, Expr, MI.getDebugLoc());
if (!Discard)
UV->addDef(Idx, MI.getOperand(0));
UV->addDef(Idx, MI.getOperand(0), IsIndirect);
else {
MachineOperand MO = MachineOperand::CreateReg(0U, false);
MO.setIsDebug();
UV->addDef(Idx, MO);
UV->addDef(Idx, MO, false);
}
return true;
}
@ -765,7 +775,7 @@ void UserValue::extendDef(SlotIndex Idx, DbgValueLocation Loc, LiveRange *LR,
}
void UserValue::addDefsFromCopies(
LiveInterval *LI, unsigned LocNo,
LiveInterval *LI, unsigned LocNo, bool WasIndirect,
const SmallVectorImpl<SlotIndex> &Kills,
SmallVectorImpl<std::pair<SlotIndex, DbgValueLocation>> &NewDefs,
MachineRegisterInfo &MRI, LiveIntervals &LIS) {
@ -829,7 +839,7 @@ void UserValue::addDefsFromCopies(
MachineInstr *CopyMI = LIS.getInstructionFromIndex(DstVNI->def);
assert(CopyMI && CopyMI->isCopy() && "Bad copy value");
unsigned LocNo = getLocationNo(CopyMI->getOperand(0));
DbgValueLocation NewLoc(LocNo);
DbgValueLocation NewLoc(LocNo, WasIndirect);
I.insert(Idx, Idx.getNextSlot(), NewLoc);
NewDefs.push_back(std::make_pair(Idx, NewLoc));
break;
@ -877,7 +887,8 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI,
// sub-register in that regclass). For now, simply skip handling copies if
// a sub-register is involved.
if (LI && !LocMO.getSubReg())
addDefsFromCopies(LI, Loc.locNo(), Kills, Defs, MRI, LIS);
addDefsFromCopies(LI, Loc.locNo(), Loc.wasIndirect(), Kills, Defs, MRI,
LIS);
continue;
}
@ -910,6 +921,11 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI,
SlotIndex RStart = LIS.getInstructionIndex(*Range.first);
SlotIndex REnd = LIS.getInstructionIndex(*Range.second);
// Variable locations at the first instruction of a block should be
// based on the block's SlotIndex, not the first instruction's index.
if (Range.first == Range.first->getParent()->begin())
RStart = LIS.getSlotIndexes()->getIndexBefore(*Range.first);
// At the start of each iteration I has been advanced so that
// I.stop() >= PrevEnd. Check for overlap.
if (PrevEnd && I.start() < PrevEnd) {
@ -922,7 +938,8 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI,
++I;
// If the interval also overlaps the start of the "next" (i.e.
// current) range create a new interval for the remainder
// current) range create a new interval for the remainder (which
// may be further trimmed).
if (RStart < IStop)
I.insert(RStart, IStop, Loc);
}
@ -932,6 +949,13 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI,
if (!I.valid())
return;
if (I.start() < RStart) {
// Interval start overlaps range - trim to the scope range.
I.setStartUnchecked(RStart);
// Remember that this interval was trimmed.
trimmedDefs.insert(RStart);
}
// The end of a lexical scope range is the last instruction in the
// range. To convert to an interval we need the index of the
// instruction after it.
@ -1306,14 +1330,21 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
// that the original virtual register was a pointer. Also, add the stack slot
// offset for the spilled register to the expression.
const DIExpression *Expr = Expression;
if (Spilled)
Expr = DIExpression::prepend(Expr, DIExpression::ApplyOffset, SpillOffset);
uint8_t DIExprFlags = DIExpression::ApplyOffset;
bool IsIndirect = Loc.wasIndirect();
if (Spilled) {
if (IsIndirect)
DIExprFlags |= DIExpression::DerefAfter;
Expr =
DIExpression::prepend(Expr, DIExprFlags, SpillOffset);
IsIndirect = true;
}
assert((!Spilled || MO.isFI()) && "a spilled location must be a frame index");
do {
BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE),
Spilled, MO, Variable, Expr);
IsIndirect, MO, Variable, Expr);
// Continue and insert DBG_VALUES after every redefinition of register
// associated with the debug value within the range
@ -1345,6 +1376,12 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
bool Spilled = SpillIt != SpillOffsets.end();
unsigned SpillOffset = Spilled ? SpillIt->second : 0;
// If the interval start was trimmed to the lexical scope insert the
// DBG_VALUE at the previous index (otherwise it appears after the
// first instruction in the range).
if (trimmedDefs.count(Start))
Start = Start.getPrevIndex();
LLVM_DEBUG(dbgs() << "\t[" << Start << ';' << Stop << "):" << Loc.locNo());
MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start)->getIterator();
SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);

View File

@ -1393,11 +1393,9 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
"Expected inlined-at fields to agree");
// A dbg.declare describes the address of a source variable, so lower it
// into an indirect DBG_VALUE.
auto *Expr = DI->getExpression();
Expr = DIExpression::append(Expr, {dwarf::DW_OP_deref});
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ false,
*Op, DI->getVariable(), Expr);
TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true,
*Op, DI->getVariable(), DI->getExpression());
} else {
// We can't yet handle anything else here because it would require
// generating code, thus altering codegen because of debug info.
@ -1421,19 +1419,19 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
if (CI->getBitWidth() > 64)
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
.addCImm(CI)
.addReg(0U)
.addImm(0U)
.addMetadata(DI->getVariable())
.addMetadata(DI->getExpression());
else
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
.addImm(CI->getZExtValue())
.addReg(0U)
.addImm(0U)
.addMetadata(DI->getVariable())
.addMetadata(DI->getExpression());
} else if (const auto *CF = dyn_cast<ConstantFP>(V)) {
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
.addFPImm(CF)
.addReg(0U)
.addImm(0U)
.addMetadata(DI->getVariable())
.addMetadata(DI->getExpression());
} else if (unsigned Reg = lookUpRegForValue(V)) {

View File

@ -677,7 +677,7 @@ MachineInstr *
InstrEmitter::EmitDbgValue(SDDbgValue *SD,
DenseMap<SDValue, unsigned> &VRBaseMap) {
MDNode *Var = SD->getVariable();
const DIExpression *Expr = SD->getExpression();
MDNode *Expr = SD->getExpression();
DebugLoc DL = SD->getDebugLoc();
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
"Expected inlined-at fields to agree");
@ -701,11 +701,12 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
// EmitTargetCodeForFrameDebugValue is responsible for allocation.
auto FrameMI = BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE))
.addFrameIndex(SD->getFrameIx());
if (SD->isIndirect())
Expr = DIExpression::append(Expr, {dwarf::DW_OP_deref});
FrameMI.addReg(0);
// Push [fi + 0] onto the DIExpression stack.
FrameMI.addImm(0);
else
// Push fi onto the DIExpression stack.
FrameMI.addReg(0);
return FrameMI.addMetadata(Var).addMetadata(Expr);
}
// Otherwise, we're going to create an instruction here.
@ -751,9 +752,9 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
// Indirect addressing is indicated by an Imm as the second parameter.
if (SD->isIndirect())
Expr = DIExpression::append(Expr, {dwarf::DW_OP_deref});
MIB.addReg(0U, RegState::Debug);
MIB.addImm(0U);
else
MIB.addReg(0U, RegState::Debug);
MIB.addMetadata(Var);
MIB.addMetadata(Expr);

View File

@ -4716,11 +4716,11 @@ SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
break;
case ISD::VECREDUCE_FMAX:
NeutralElem = DAG.getConstantFP(
std::numeric_limits<double>::infinity(), dl, ElemVT);
-std::numeric_limits<double>::infinity(), dl, ElemVT);
break;
case ISD::VECREDUCE_FMIN:
NeutralElem = DAG.getConstantFP(
-std::numeric_limits<double>::infinity(), dl, ElemVT);
std::numeric_limits<double>::infinity(), dl, ElemVT);
break;
}

View File

@ -5622,6 +5622,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
MachineFunction &MF = DAG.getMachineFunction();
const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo();
bool IsIndirect = false;
Optional<MachineOperand> Op;
// Some arguments' frame index is recorded during argument lowering.
int FI = FuncInfo.getArgumentFrameIndex(Arg);
@ -5643,6 +5644,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
}
if (Reg) {
Op = MachineOperand::CreateReg(Reg, false);
IsIndirect = IsDbgDeclare;
}
}
@ -5691,7 +5693,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
}
assert(!IsDbgDeclare && "DbgDeclare operand is not in memory?");
FuncInfo.ArgDbgValues.push_back(
BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), false,
BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), IsDbgDeclare,
RegAndSize.first, Variable, *FragmentExpr));
}
};
@ -5709,6 +5711,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
}
Op = MachineOperand::CreateReg(VMI->second, false);
IsIndirect = IsDbgDeclare;
} else if (ArgRegsAndSizes.size() > 1) {
// This was split due to the calling convention, and no virtual register
// mapping exists for the value.
@ -5722,28 +5725,9 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
assert(Variable->isValidLocationForIntrinsic(DL) &&
"Expected inlined-at fields to agree");
// If the argument arrives in a stack slot, then what the IR thought was a
// normal Value is actually in memory, and we must add a deref to load it.
if (Op->isFI()) {
int FI = Op->getIndex();
unsigned Size = DAG.getMachineFunction().getFrameInfo().getObjectSize(FI);
if (Expr->isImplicit()) {
SmallVector<uint64_t, 2> Ops = {dwarf::DW_OP_deref_size, Size};
Expr = DIExpression::prependOpcodes(Expr, Ops);
} else {
Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
}
}
// If this location was specified with a dbg.declare, then it and its
// expression calculate the address of the variable. Append a deref to
// force it to be a memory location.
if (IsDbgDeclare)
Expr = DIExpression::append(Expr, {dwarf::DW_OP_deref});
IsIndirect = (Op->isReg()) ? IsIndirect : true;
FuncInfo.ArgDbgValues.push_back(
BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), false,
BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), IsIndirect,
*Op, Variable, Expr));
return true;

View File

@ -960,7 +960,8 @@ void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) {
}
// Remap all instructions to the new stack slots.
std::vector<std::vector<MachineMemOperand *>> SSRefs(MFI->getObjectIndexEnd());
std::vector<std::vector<MachineMemOperand *>> SSRefs(
MFI->getObjectIndexEnd());
for (MachineBasicBlock &BB : *MF)
for (MachineInstr &I : BB) {
// Skip lifetime markers. We'll remove them soon.
@ -1074,12 +1075,13 @@ void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) {
}
// Rewrite MachineMemOperands that reference old frame indices.
for (auto E : enumerate(SSRefs)) {
const PseudoSourceValue *NewSV =
MF->getPSVManager().getFixedStack(SlotRemap[E.index()]);
for (MachineMemOperand *Ref : E.value())
Ref->setValue(NewSV);
}
for (auto E : enumerate(SSRefs))
if (!E.value().empty()) {
const PseudoSourceValue *NewSV =
MF->getPSVManager().getFixedStack(SlotRemap.find(E.index())->second);
for (MachineMemOperand *Ref : E.value())
Ref->setValue(NewSV);
}
// Update the location of C++ catch objects for the MSVC personality routine.
if (WinEHFuncInfo *EHInfo = MF->getWinEHFuncInfo())

View File

@ -847,8 +847,7 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) {
// Iterate through, and add to, a tree of operands and users in the use-def.
while (!WorkList.empty()) {
Value *V = WorkList.back();
WorkList.pop_back();
Value *V = WorkList.pop_back_val();
if (CurrentVisited.count(V))
continue;
@ -917,7 +916,7 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) {
++ToPromote;
}
// DAG optimisations should be able to handle these cases better, especially
// DAG optimizations should be able to handle these cases better, especially
// for function arguments.
if (ToPromote < 2 || (Blocks.size() == 1 && (NonFreeArgs > SafeWrap.size())))
return false;
@ -941,6 +940,9 @@ bool TypePromotion::runOnFunction(Function &F) {
if (!TPC)
return false;
AllVisited.clear();
SafeToPromote.clear();
SafeWrap.clear();
bool MadeChange = false;
const DataLayout &DL = F.getParent()->getDataLayout();
const TargetMachine &TM = TPC->getTM<TargetMachine>();
@ -998,6 +1000,10 @@ bool TypePromotion::runOnFunction(Function &F) {
if (MadeChange)
LLVM_DEBUG(dbgs() << "After TypePromotion: " << F << "\n");
AllVisited.clear();
SafeToPromote.clear();
SafeWrap.clear();
return MadeChange;
}

View File

@ -67,9 +67,11 @@ namespace orc {
class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
public:
PartitioningIRMaterializationUnit(ExecutionSession &ES, ThreadSafeModule TSM,
VModuleKey K, CompileOnDemandLayer &Parent)
: IRMaterializationUnit(ES, std::move(TSM), std::move(K)),
PartitioningIRMaterializationUnit(ExecutionSession &ES,
const ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K,
CompileOnDemandLayer &Parent)
: IRMaterializationUnit(ES, MO, std::move(TSM), std::move(K)),
Parent(Parent) {}
PartitioningIRMaterializationUnit(
@ -111,7 +113,8 @@ CompileOnDemandLayer::compileWholeModule(GlobalValueSet Requested) {
CompileOnDemandLayer::CompileOnDemandLayer(
ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr,
IndirectStubsManagerBuilder BuildIndirectStubsManager)
: IRLayer(ES), BaseLayer(BaseLayer), LCTMgr(LCTMgr),
: IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
LCTMgr(LCTMgr),
BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {}
void CompileOnDemandLayer::setPartitionFunction(PartitionFunction Partition) {
@ -136,27 +139,23 @@ void CompileOnDemandLayer::emit(MaterializationResponsibility R,
TSM.withModuleDo([&](Module &M) {
// First, do some cleanup on the module:
cleanUpModule(M);
MangleAndInterner Mangle(ES, M.getDataLayout());
for (auto &GV : M.global_values()) {
if (GV.isDeclaration() || GV.hasLocalLinkage() ||
GV.hasAppendingLinkage())
continue;
auto Name = Mangle(GV.getName());
auto Flags = JITSymbolFlags::fromGlobalValue(GV);
if (Flags.isCallable())
Callables[Name] = SymbolAliasMapEntry(Name, Flags);
else
NonCallables[Name] = SymbolAliasMapEntry(Name, Flags);
}
});
for (auto &KV : R.getSymbols()) {
auto &Name = KV.first;
auto &Flags = KV.second;
if (Flags.isCallable())
Callables[Name] = SymbolAliasMapEntry(Name, Flags);
else
NonCallables[Name] = SymbolAliasMapEntry(Name, Flags);
}
// Create a partitioning materialization unit and lodge it with the
// implementation dylib.
if (auto Err = PDR.getImplDylib().define(
std::make_unique<PartitioningIRMaterializationUnit>(
ES, std::move(TSM), R.getVModuleKey(), *this))) {
ES, *getManglingOptions(), std::move(TSM), R.getVModuleKey(),
*this))) {
ES.reportError(std::move(Err));
R.failMaterialization();
return;
@ -316,7 +315,7 @@ void CompileOnDemandLayer::emitPartition(
}
R.replace(std::make_unique<PartitioningIRMaterializationUnit>(
ES, std::move(TSM), R.getVModuleKey(), *this));
ES, *getManglingOptions(), std::move(TSM), R.getVModuleKey(), *this));
BaseLayer.emit(std::move(R), std::move(*ExtractedTSM));
}

View File

@ -24,11 +24,20 @@
namespace llvm {
namespace orc {
IRMaterializationUnit::ManglingOptions
irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
IRMaterializationUnit::ManglingOptions MO;
MO.EmulatedTLS = Opts.EmulatedTLS;
return MO;
}
/// Compile a Module to an ObjectFile.
SimpleCompiler::CompileResult SimpleCompiler::operator()(Module &M) {
Expected<SimpleCompiler::CompileResult> SimpleCompiler::operator()(Module &M) {
CompileResult CachedObject = tryToLoadFromObjectCache(M);
if (CachedObject)
return CachedObject;
return std::move(CachedObject);
SmallVector<char, 0> ObjBufferSV;
@ -38,7 +47,8 @@ SimpleCompiler::CompileResult SimpleCompiler::operator()(Module &M) {
legacy::PassManager PM;
MCContext *Ctx;
if (TM.addPassesToEmitMC(PM, Ctx, ObjStream))
llvm_unreachable("Target does not support MC emission.");
return make_error<StringError>("Target does not support MC emission",
inconvertibleErrorCode());
PM.run(M);
}
@ -47,14 +57,11 @@ SimpleCompiler::CompileResult SimpleCompiler::operator()(Module &M) {
auto Obj = object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
if (Obj) {
notifyObjectCompiled(M, *ObjBuffer);
return std::move(ObjBuffer);
}
if (!Obj)
return Obj.takeError();
// TODO: Actually report errors helpfully.
consumeError(Obj.takeError());
return nullptr;
notifyObjectCompiled(M, *ObjBuffer);
return std::move(ObjBuffer);
}
SimpleCompiler::CompileResult
@ -73,9 +80,11 @@ void SimpleCompiler::notifyObjectCompiled(const Module &M,
ConcurrentIRCompiler::ConcurrentIRCompiler(JITTargetMachineBuilder JTMB,
ObjectCache *ObjCache)
: JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
: IRCompiler(irManglingOptionsFromTargetOptions(JTMB.getOptions())),
JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
std::unique_ptr<MemoryBuffer> ConcurrentIRCompiler::operator()(Module &M) {
Expected<std::unique_ptr<MemoryBuffer>>
ConcurrentIRCompiler::operator()(Module &M) {
auto TM = cantFail(JTMB.createTargetMachine());
SimpleCompiler C(*TM, ObjCache);
return C(M);

View File

@ -468,15 +468,19 @@ Error MaterializationResponsibility::notifyEmitted() {
}
Error MaterializationResponsibility::defineMaterializing(
const SymbolFlagsMap &NewSymbolFlags) {
// Add the given symbols to this responsibility object.
// It's ok if we hit a duplicate here: In that case the new version will be
// discarded, and the JITDylib::defineMaterializing method will return a
// duplicate symbol error.
for (auto &KV : NewSymbolFlags)
SymbolFlags.insert(KV);
SymbolFlagsMap NewSymbolFlags) {
return JD.defineMaterializing(NewSymbolFlags);
LLVM_DEBUG({
dbgs() << "In " << JD.getName() << " defining materializing symbols "
<< NewSymbolFlags << "\n";
});
if (auto AcceptedDefs = JD.defineMaterializing(std::move(NewSymbolFlags))) {
// Add all newly accepted symbols to this responsibility object.
for (auto &KV : *AcceptedDefs)
SymbolFlags.insert(KV);
return Error::success();
} else
return AcceptedDefs.takeError();
}
void MaterializationResponsibility::failMaterialization() {
@ -809,31 +813,52 @@ void JITDylib::removeGenerator(DefinitionGenerator &G) {
});
}
Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
return ES.runSessionLocked([&]() -> Error {
Expected<SymbolFlagsMap>
JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
std::vector<SymbolTable::iterator> AddedSyms;
std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs;
for (auto &KV : SymbolFlags) {
SymbolTable::iterator EntryItr;
bool Added;
for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
SFItr != SFEnd; ++SFItr) {
std::tie(EntryItr, Added) =
Symbols.insert(std::make_pair(KV.first, SymbolTableEntry(KV.second)));
auto &Name = SFItr->first;
auto &Flags = SFItr->second;
if (Added) {
AddedSyms.push_back(EntryItr);
EntryItr->second.setState(SymbolState::Materializing);
} else {
// Remove any symbols already added.
for (auto &SI : AddedSyms)
Symbols.erase(SI);
auto EntryItr = Symbols.find(Name);
// FIXME: Return all duplicates.
return make_error<DuplicateDefinition>(*KV.first);
}
// If the entry already exists...
if (EntryItr != Symbols.end()) {
// If this is a strong definition then error out.
if (!Flags.isWeak()) {
// Remove any symbols already added.
for (auto &SI : AddedSyms)
Symbols.erase(SI);
// FIXME: Return all duplicates.
return make_error<DuplicateDefinition>(*Name);
}
// Otherwise just make a note to discard this symbol after the loop.
RejectedWeakDefs.push_back(SFItr);
continue;
} else
EntryItr =
Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
AddedSyms.push_back(EntryItr);
EntryItr->second.setState(SymbolState::Materializing);
}
return Error::success();
// Remove any rejected weak definitions from the SymbolFlags map.
while (!RejectedWeakDefs.empty()) {
SymbolFlags.erase(RejectedWeakDefs.back());
RejectedWeakDefs.pop_back();
}
return SymbolFlags;
});
}

View File

@ -11,9 +11,14 @@
namespace llvm {
namespace orc {
IRCompileLayer::IRCompiler::~IRCompiler() {}
IRCompileLayer::IRCompileLayer(ExecutionSession &ES, ObjectLayer &BaseLayer,
CompileFunction Compile)
: IRLayer(ES), BaseLayer(BaseLayer), Compile(std::move(Compile)) {}
std::unique_ptr<IRCompiler> Compile)
: IRLayer(ES, ManglingOpts), BaseLayer(BaseLayer),
Compile(std::move(Compile)) {
ManglingOpts = &this->Compile->getManglingOptions();
}
void IRCompileLayer::setNotifyCompiled(NotifyCompiledFunction NotifyCompiled) {
std::lock_guard<std::mutex> Lock(IRLayerMutex);
@ -24,7 +29,7 @@ void IRCompileLayer::emit(MaterializationResponsibility R,
ThreadSafeModule TSM) {
assert(TSM && "Module must not be null");
if (auto Obj = TSM.withModuleDo(Compile)) {
if (auto Obj = TSM.withModuleDo(*Compile)) {
{
std::lock_guard<std::mutex> Lock(IRLayerMutex);
if (NotifyCompiled)

View File

@ -12,10 +12,10 @@
namespace llvm {
namespace orc {
IRTransformLayer::IRTransformLayer(ExecutionSession &ES,
IRLayer &BaseLayer,
TransformFunction Transform)
: IRLayer(ES), BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
IRTransformLayer::IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer,
TransformFunction Transform)
: IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
Transform(std::move(Transform)) {}
void IRTransformLayer::emit(MaterializationResponsibility R,
ThreadSafeModule TSM) {

View File

@ -96,8 +96,10 @@ LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
auto ObjLinkingLayer =
std::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr));
if (S.JTMB->getTargetTriple().isOSBinFormatCOFF())
if (S.JTMB->getTargetTriple().isOSBinFormatCOFF()) {
ObjLinkingLayer->setOverrideObjectFlagsWithResponsibilityFlags(true);
ObjLinkingLayer->setAutoClaimResponsibilityForObjectSymbols(true);
}
// FIXME: Explicit conversion to std::unique_ptr<ObjectLayer> added to silence
// errors from some GCC / libstdc++ bots. Remove this conversion (i.e.
@ -105,7 +107,7 @@ LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
return std::unique_ptr<ObjectLayer>(std::move(ObjLinkingLayer));
}
Expected<IRCompileLayer::CompileFunction>
Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
LLJIT::createCompileFunction(LLJITBuilderState &S,
JITTargetMachineBuilder JTMB) {
@ -116,13 +118,13 @@ LLJIT::createCompileFunction(LLJITBuilderState &S,
// Otherwise default to creating a SimpleCompiler, or ConcurrentIRCompiler,
// depending on the number of threads requested.
if (S.NumCompileThreads > 0)
return ConcurrentIRCompiler(std::move(JTMB));
return std::make_unique<ConcurrentIRCompiler>(std::move(JTMB));
auto TM = JTMB.createTargetMachine();
if (!TM)
return TM.takeError();
return TMOwningSimpleCompiler(std::move(*TM));
return std::make_unique<TMOwningSimpleCompiler>(std::move(*TM));
}
LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/IR/Constants.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h"
@ -15,15 +16,15 @@
namespace llvm {
namespace orc {
IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {}
IRLayer::~IRLayer() {}
Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) {
return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
*this, std::move(K), std::move(TSM)));
*this, *getManglingOptions(), std::move(TSM), std::move(K)));
}
IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,
const ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K)
: MaterializationUnit(SymbolFlagsMap(), std::move(K)), TSM(std::move(TSM)) {
@ -32,12 +33,44 @@ IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,
MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
this->TSM.withModuleDo([&](Module &M) {
for (auto &G : M.global_values()) {
if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() &&
!G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) {
auto MangledName = Mangle(G.getName());
SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
SymbolToDefinition[MangledName] = &G;
// Skip globals that don't generate symbols.
if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
continue;
// thread locals generate different symbols depending on whether or not
// emulated TLS is enabled.
if (G.isThreadLocal() && MO.EmulatedTLS) {
auto &GV = cast<GlobalVariable>(G);
auto Flags = JITSymbolFlags::fromGlobalValue(GV);
auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
SymbolFlags[EmuTLSV] = Flags;
SymbolToDefinition[EmuTLSV] = &GV;
// If this GV has a non-zero initializer we'll need to emit an
// __emutls.t symbol too.
if (GV.hasInitializer()) {
const auto *InitVal = GV.getInitializer();
// Skip zero-initializers.
if (isa<ConstantAggregateZero>(InitVal))
continue;
const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
if (InitIntValue && InitIntValue->isZero())
continue;
auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
SymbolFlags[EmuTLST] = Flags;
}
continue;
}
// Otherwise we just need a normal linker mangling.
auto MangledName = Mangle(G.getName());
SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
SymbolToDefinition[MangledName] = &G;
}
});
}
@ -72,8 +105,8 @@ void IRMaterializationUnit::discard(const JITDylib &JD,
}
BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
IRLayer &L, VModuleKey K, ThreadSafeModule TSM)
: IRMaterializationUnit(L.getExecutionSession(), std::move(TSM),
IRLayer &L, const ManglingOptions &MO, ThreadSafeModule TSM, VModuleKey K)
: IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM),
std::move(K)),
L(L), K(std::move(K)) {}

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/Object/COFF.h"
namespace {
@ -160,6 +161,39 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
std::set<StringRef> &InternalSymbols) {
SymbolFlagsMap ExtraSymbolsToClaim;
SymbolMap Symbols;
// Hack to support COFF constant pool comdats introduced during compilation:
// (See http://llvm.org/PR40074)
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) {
auto &ES = getExecutionSession();
// For all resolved symbols that are not already in the responsibilty set:
// check whether the symbol is in a comdat section and if so mark it as
// weak.
for (auto &Sym : COFFObj->symbols()) {
if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)
continue;
auto Name = Sym.getName();
if (!Name)
return Name.takeError();
auto I = Resolved.find(*Name);
// Skip unresolved symbols, internal symbols, and symbols that are
// already in the responsibility set.
if (I == Resolved.end() || InternalSymbols.count(*Name) ||
R.getSymbols().count(ES.intern(*Name)))
continue;
auto Sec = Sym.getSection();
if (!Sec)
return Sec.takeError();
if (*Sec == COFFObj->section_end())
continue;
auto &COFFSec = *COFFObj->getCOFFSection(**Sec);
if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);
}
}
for (auto &KV : Resolved) {
// Scan the symbols and add them to the Symbols map for resolution.
@ -184,10 +218,17 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
}
if (!ExtraSymbolsToClaim.empty())
if (!ExtraSymbolsToClaim.empty()) {
if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
return Err;
// If we claimed responsibility for any weak symbols but were rejected then
// we need to remove them from the resolved set.
for (auto &KV : ExtraSymbolsToClaim)
if (KV.second.isWeak() && !R.getSymbols().count(KV.first))
Symbols.erase(KV.first);
}
if (auto Err = R.notifyResolved(Symbols)) {
R.failMaterialization();
return Err;

Some files were not shown because too many files have changed in this diff Show More