1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-28 08:02:54 +00:00

Merge llvm-project release/13.x llvmorg-13.0.0-rc1-97-g23ba3732246a

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-13.0.0-rc1-97-g23ba3732246a.

PR:		258209
MFC after:	2 weeks
This commit is contained in:
Dimitry Andric 2021-08-25 20:31:14 +02:00
commit 6e75b2fbf9
157 changed files with 4419 additions and 1490 deletions

View File

@ -331,6 +331,152 @@ OLD_DIRS+=usr/lib/clang/12.0.1/lib/freebsd
OLD_DIRS+=usr/lib/clang/12.0.1/lib
OLD_DIRS+=usr/lib/clang/12.0.1
# 20211113: new libc++ import which bumps version from 12.0.1 to 13.0.0.
OLD_FILES+=usr/include/c++/v1/__functional_03
OLD_FILES+=usr/include/c++/v1/__functional_base_03
OLD_FILES+=usr/include/c++/v1/__memory/base.h
OLD_FILES+=usr/include/c++/v1/__memory/utilities.h
OLD_FILES+=usr/include/c++/v1/__sso_allocator
OLD_FILES+=usr/include/c++/v1/tr1/__availability
OLD_FILES+=usr/include/c++/v1/tr1/__bit_reference
OLD_FILES+=usr/include/c++/v1/tr1/__bits
OLD_FILES+=usr/include/c++/v1/tr1/__bsd_locale_defaults.h
OLD_FILES+=usr/include/c++/v1/tr1/__bsd_locale_fallbacks.h
OLD_FILES+=usr/include/c++/v1/tr1/__config
OLD_FILES+=usr/include/c++/v1/tr1/__debug
OLD_FILES+=usr/include/c++/v1/tr1/__errc
OLD_FILES+=usr/include/c++/v1/tr1/__functional_03
OLD_FILES+=usr/include/c++/v1/tr1/__functional_base
OLD_FILES+=usr/include/c++/v1/tr1/__functional_base_03
OLD_FILES+=usr/include/c++/v1/tr1/__hash_table
OLD_FILES+=usr/include/c++/v1/tr1/__libcpp_version
OLD_FILES+=usr/include/c++/v1/tr1/__locale
OLD_FILES+=usr/include/c++/v1/tr1/__mutex_base
OLD_FILES+=usr/include/c++/v1/tr1/__node_handle
OLD_FILES+=usr/include/c++/v1/tr1/__nullptr
OLD_FILES+=usr/include/c++/v1/tr1/__split_buffer
OLD_FILES+=usr/include/c++/v1/tr1/__sso_allocator
OLD_FILES+=usr/include/c++/v1/tr1/__std_stream
OLD_FILES+=usr/include/c++/v1/tr1/__string
OLD_FILES+=usr/include/c++/v1/tr1/__threading_support
OLD_FILES+=usr/include/c++/v1/tr1/__tree
OLD_FILES+=usr/include/c++/v1/tr1/__tuple
OLD_FILES+=usr/include/c++/v1/tr1/__undef_macros
OLD_FILES+=usr/include/c++/v1/tr1/algorithm
OLD_FILES+=usr/include/c++/v1/tr1/any
OLD_FILES+=usr/include/c++/v1/tr1/array
OLD_FILES+=usr/include/c++/v1/tr1/atomic
OLD_FILES+=usr/include/c++/v1/tr1/barrier
OLD_FILES+=usr/include/c++/v1/tr1/bit
OLD_FILES+=usr/include/c++/v1/tr1/bitset
OLD_FILES+=usr/include/c++/v1/tr1/cassert
OLD_FILES+=usr/include/c++/v1/tr1/ccomplex
OLD_FILES+=usr/include/c++/v1/tr1/cctype
OLD_FILES+=usr/include/c++/v1/tr1/cerrno
OLD_FILES+=usr/include/c++/v1/tr1/cfenv
OLD_FILES+=usr/include/c++/v1/tr1/cfloat
OLD_FILES+=usr/include/c++/v1/tr1/charconv
OLD_FILES+=usr/include/c++/v1/tr1/chrono
OLD_FILES+=usr/include/c++/v1/tr1/cinttypes
OLD_FILES+=usr/include/c++/v1/tr1/ciso646
OLD_FILES+=usr/include/c++/v1/tr1/climits
OLD_FILES+=usr/include/c++/v1/tr1/clocale
OLD_FILES+=usr/include/c++/v1/tr1/cmath
OLD_FILES+=usr/include/c++/v1/tr1/codecvt
OLD_FILES+=usr/include/c++/v1/tr1/compare
OLD_FILES+=usr/include/c++/v1/tr1/complex
OLD_FILES+=usr/include/c++/v1/tr1/complex.h
OLD_FILES+=usr/include/c++/v1/tr1/concepts
OLD_FILES+=usr/include/c++/v1/tr1/condition_variable
OLD_FILES+=usr/include/c++/v1/tr1/csetjmp
OLD_FILES+=usr/include/c++/v1/tr1/csignal
OLD_FILES+=usr/include/c++/v1/tr1/cstdarg
OLD_FILES+=usr/include/c++/v1/tr1/cstdbool
OLD_FILES+=usr/include/c++/v1/tr1/cstddef
OLD_FILES+=usr/include/c++/v1/tr1/cstdint
OLD_FILES+=usr/include/c++/v1/tr1/cstdio
OLD_FILES+=usr/include/c++/v1/tr1/cstdlib
OLD_FILES+=usr/include/c++/v1/tr1/cstring
OLD_FILES+=usr/include/c++/v1/tr1/ctgmath
OLD_FILES+=usr/include/c++/v1/tr1/ctime
OLD_FILES+=usr/include/c++/v1/tr1/ctype.h
OLD_FILES+=usr/include/c++/v1/tr1/cwchar
OLD_FILES+=usr/include/c++/v1/tr1/cwctype
OLD_FILES+=usr/include/c++/v1/tr1/deque
OLD_FILES+=usr/include/c++/v1/tr1/errno.h
OLD_FILES+=usr/include/c++/v1/tr1/exception
OLD_FILES+=usr/include/c++/v1/tr1/execution
OLD_FILES+=usr/include/c++/v1/tr1/fenv.h
OLD_FILES+=usr/include/c++/v1/tr1/filesystem
OLD_FILES+=usr/include/c++/v1/tr1/float.h
OLD_FILES+=usr/include/c++/v1/tr1/forward_list
OLD_FILES+=usr/include/c++/v1/tr1/fstream
OLD_FILES+=usr/include/c++/v1/tr1/functional
OLD_FILES+=usr/include/c++/v1/tr1/future
OLD_FILES+=usr/include/c++/v1/tr1/initializer_list
OLD_FILES+=usr/include/c++/v1/tr1/inttypes.h
OLD_FILES+=usr/include/c++/v1/tr1/iomanip
OLD_FILES+=usr/include/c++/v1/tr1/ios
OLD_FILES+=usr/include/c++/v1/tr1/iosfwd
OLD_FILES+=usr/include/c++/v1/tr1/iostream
OLD_FILES+=usr/include/c++/v1/tr1/istream
OLD_FILES+=usr/include/c++/v1/tr1/iterator
OLD_FILES+=usr/include/c++/v1/tr1/latch
OLD_FILES+=usr/include/c++/v1/tr1/limits
OLD_FILES+=usr/include/c++/v1/tr1/limits.h
OLD_FILES+=usr/include/c++/v1/tr1/list
OLD_FILES+=usr/include/c++/v1/tr1/locale
OLD_FILES+=usr/include/c++/v1/tr1/locale.h
OLD_FILES+=usr/include/c++/v1/tr1/map
OLD_FILES+=usr/include/c++/v1/tr1/math.h
OLD_FILES+=usr/include/c++/v1/tr1/memory
OLD_FILES+=usr/include/c++/v1/tr1/mutex
OLD_FILES+=usr/include/c++/v1/tr1/new
OLD_FILES+=usr/include/c++/v1/tr1/numbers
OLD_FILES+=usr/include/c++/v1/tr1/numeric
OLD_FILES+=usr/include/c++/v1/tr1/optional
OLD_FILES+=usr/include/c++/v1/tr1/ostream
OLD_FILES+=usr/include/c++/v1/tr1/queue
OLD_FILES+=usr/include/c++/v1/tr1/random
OLD_FILES+=usr/include/c++/v1/tr1/ratio
OLD_FILES+=usr/include/c++/v1/tr1/regex
OLD_FILES+=usr/include/c++/v1/tr1/scoped_allocator
OLD_FILES+=usr/include/c++/v1/tr1/semaphore
OLD_FILES+=usr/include/c++/v1/tr1/set
OLD_FILES+=usr/include/c++/v1/tr1/setjmp.h
OLD_FILES+=usr/include/c++/v1/tr1/shared_mutex
OLD_FILES+=usr/include/c++/v1/tr1/span
OLD_FILES+=usr/include/c++/v1/tr1/sstream
OLD_FILES+=usr/include/c++/v1/tr1/stack
OLD_FILES+=usr/include/c++/v1/tr1/stdbool.h
OLD_FILES+=usr/include/c++/v1/tr1/stddef.h
OLD_FILES+=usr/include/c++/v1/tr1/stdexcept
OLD_FILES+=usr/include/c++/v1/tr1/stdint.h
OLD_FILES+=usr/include/c++/v1/tr1/stdio.h
OLD_FILES+=usr/include/c++/v1/tr1/stdlib.h
OLD_FILES+=usr/include/c++/v1/tr1/streambuf
OLD_FILES+=usr/include/c++/v1/tr1/string
OLD_FILES+=usr/include/c++/v1/tr1/string.h
OLD_FILES+=usr/include/c++/v1/tr1/string_view
OLD_FILES+=usr/include/c++/v1/tr1/strstream
OLD_FILES+=usr/include/c++/v1/tr1/system_error
OLD_FILES+=usr/include/c++/v1/tr1/tgmath.h
OLD_FILES+=usr/include/c++/v1/tr1/thread
OLD_FILES+=usr/include/c++/v1/tr1/tuple
OLD_FILES+=usr/include/c++/v1/tr1/type_traits
OLD_FILES+=usr/include/c++/v1/tr1/typeindex
OLD_FILES+=usr/include/c++/v1/tr1/typeinfo
OLD_FILES+=usr/include/c++/v1/tr1/unordered_map
OLD_FILES+=usr/include/c++/v1/tr1/unordered_set
OLD_FILES+=usr/include/c++/v1/tr1/utility
OLD_FILES+=usr/include/c++/v1/tr1/valarray
OLD_FILES+=usr/include/c++/v1/tr1/variant
OLD_FILES+=usr/include/c++/v1/tr1/vector
OLD_FILES+=usr/include/c++/v1/tr1/version
OLD_FILES+=usr/include/c++/v1/tr1/wchar.h
OLD_FILES+=usr/include/c++/v1/tr1/wctype.h
OLD_DIRS+=usr/include/c++/v1/tr1
# 20211027: libdialog shlib bumped to version 10 for dialog 1.3
OLD_LIBS+=usr/lib/libdialog.so.9
OLD_LIBS+=usr/lib/libdpv.so.2

View File

@ -243,6 +243,9 @@ TARGET_HEADER_BUILTIN(_ReadStatusReg, "LLii", "nh", "intrin.h", ALL_MS_LANGUAG
TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__mulh, "SLLiSLLiSLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
#undef BUILTIN
#undef LANGBUILTIN
#undef TARGET_HEADER_BUILTIN

View File

@ -129,8 +129,6 @@ def err_drv_invalid_Xopenmp_target_with_args : Error<
"invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">;
def err_drv_argument_only_allowed_with : Error<
"invalid argument '%0' only allowed with '%1'">;
def err_drv_minws_unsupported_input_type : Error<
"'-fminimize-whitespace' invalid for input of type %0">;
def err_drv_amdgpu_ieee_without_no_honor_nans : Error<
"invalid argument '-mno-amdgpu-ieee' only allowed with relaxed NaN handling">;
def err_drv_argument_not_allowed_with : Error<

View File

@ -300,6 +300,13 @@ def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">,
def pp_pragma_sysheader_in_main_file : Warning<
"#pragma system_header ignored in main file">,
InGroup<DiagGroup<"pragma-system-header-outside-header">>;
def err_pragma_include_instead_not_sysheader : Error<
"'#pragma clang include_instead' cannot be used outside of system headers">;
def err_pragma_include_instead_system_reserved : Error<
"header '%0' is an implementation detail; #include %select{'%2'|either '%2' "
"or '%3'|one of %2}1 instead">;
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
def pp_out_of_date_dependency : Warning<
"current file is older than dependency %0">;

View File

@ -10100,8 +10100,6 @@ def err_opencl_requires_extension : Error<
def ext_opencl_double_without_pragma : Extension<
"Clang permits use of type 'double' regardless pragma if 'cl_khr_fp64' is"
" supported">;
def err_opencl_double_requires_extension : Error<
"use of type 'double' requires %select{cl_khr_fp64|cl_khr_fp64 and __opencl_c_fp64}0 support">;
def warn_opencl_generic_address_space_arg : Warning<
"passing non-generic address space pointer to %0"
" may cause dynamic conversion affecting performance">,

View File

@ -224,7 +224,7 @@ LANGOPT(OpenCLVersion , 32, 0, "OpenCL C version")
LANGOPT(OpenCLCPlusPlus , 1, 0, "C++ for OpenCL")
LANGOPT(OpenCLCPlusPlusVersion , 32, 0, "C++ for OpenCL version")
LANGOPT(OpenCLGenericAddressSpace, 1, 0, "OpenCL generic keyword")
LANGOPT(OpenCLPipe , 1, 0, "OpenCL pipe keyword")
LANGOPT(OpenCLPipes , 1, 0, "OpenCL pipes language constructs and built-ins")
LANGOPT(NativeHalfType , 1, 0, "Native half type support")
LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns")
LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")

View File

@ -354,6 +354,9 @@ class LangOptions : public LangOptionsBase {
/// A list of all -fno-builtin-* function names (e.g., memset).
std::vector<std::string> NoBuiltinFuncs;
/// A prefix map for __FILE__, __BASE_FILE__ and __builtin_FILE().
std::map<std::string, std::string, std::greater<std::string>> MacroPrefixMap;
/// Triples of the OpenMP targets that the host code codegen should
/// take into account in order to generate accurate offloading descriptors.
std::vector<llvm::Triple> OMPTargetTriples;
@ -460,6 +463,9 @@ class LangOptions : public LangOptionsBase {
}
bool isSYCL() const { return SYCLIsDevice || SYCLIsHost; }
/// Remap path prefix according to -fmacro-prefix-path option.
void remapPathPrefix(SmallString<256> &Path) const;
};
/// Floating point control options

View File

@ -1799,9 +1799,6 @@ def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">,
defm use_line_directives : BoolFOption<"use-line-directives",
PreprocessorOutputOpts<"UseLineDirectives">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Use #line in preprocessed output">, NegFlag<SetFalse>>;
defm minimize_whitespace : BoolFOption<"minimize-whitespace",
PreprocessorOutputOpts<"MinimizeWhitespace">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Minimize whitespace when emitting preprocessor output">, NegFlag<SetFalse>>;
def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Assert that the compilation takes place in a freestanding environment">,
@ -2828,10 +2825,10 @@ def fcoverage_prefix_map_EQ
HelpText<"remap file source paths in coverage mapping">;
def ffile_prefix_map_EQ
: Joined<["-"], "ffile-prefix-map=">, Group<f_Group>,
HelpText<"remap file source paths in debug info and predefined preprocessor macros">;
HelpText<"remap file source paths in debug info, predefined preprocessor macros and __builtin_FILE()">;
def fmacro_prefix_map_EQ
: Joined<["-"], "fmacro-prefix-map=">, Group<Preprocessor_Group>, Flags<[CC1Option]>,
HelpText<"remap file source paths in predefined preprocessor macros">;
: Joined<["-"], "fmacro-prefix-map=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"remap file source paths in predefined preprocessor macros and __builtin_FILE()">;
defm force_dwarf_frame : BoolFOption<"force-dwarf-frame",
CodeGenOpts<"ForceDwarfFrameSection">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Always emit a debug frame section">, NegFlag<SetFalse>>;

View File

@ -66,14 +66,6 @@ namespace types {
/// isAcceptedByClang - Can clang handle this input type.
bool isAcceptedByClang(ID Id);
/// isDerivedFromC - Is the input derived from C.
///
/// That is, does the lexer follow the rules of
/// TokenConcatenation::AvoidConcat. If this is the case, the preprocessor may
/// add and remove whitespace between tokens. Used to determine whether the
/// input can be processed by -fminimize-whitespace.
bool isDerivedFromC(ID Id);
/// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
bool isCXX(ID Id);

View File

@ -24,7 +24,6 @@ class PreprocessorOutputOptions {
unsigned ShowIncludeDirectives : 1; ///< Print includes, imports etc. within preprocessed output.
unsigned RewriteIncludes : 1; ///< Preprocess include directives only.
unsigned RewriteImports : 1; ///< Include contents of transitively-imported modules.
unsigned MinimizeWhitespace : 1; ///< Ignore whitespace from input.
public:
PreprocessorOutputOptions() {
@ -37,7 +36,6 @@ class PreprocessorOutputOptions {
ShowIncludeDirectives = 0;
RewriteIncludes = 0;
RewriteImports = 0;
MinimizeWhitespace = 0;
}
};

View File

@ -20,9 +20,12 @@
#include "clang/Lex/ModuleMap.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Allocator.h"
#include <cassert>
#include <cstddef>
@ -110,6 +113,14 @@ struct HeaderFileInfo {
/// of the framework.
StringRef Framework;
/// List of aliases that this header is known as.
/// Most headers should only have at most one alias, but a handful
/// have two.
llvm::SetVector<llvm::SmallString<32>,
llvm::SmallVector<llvm::SmallString<32>, 2>,
llvm::SmallSet<llvm::SmallString<32>, 2>>
Aliases;
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
@ -453,6 +464,10 @@ class HeaderSearch {
getFileInfo(File).DirInfo = SrcMgr::C_System;
}
void AddFileAlias(const FileEntry *File, StringRef Alias) {
getFileInfo(File).Aliases.insert(Alias);
}
/// Mark the specified file as part of a module.
void MarkFileModuleHeader(const FileEntry *FE,
ModuleMap::ModuleHeaderRole Role,

View File

@ -1953,7 +1953,8 @@ class Preprocessor {
/// This either returns the EOF token and returns true, or
/// pops a level off the include stack and returns false, at which point the
/// client should call lex again.
bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
bool HandleEndOfFile(Token &Result, SourceLocation Loc,
bool isEndOfMacro = false);
/// Callback invoked when the current TokenLexer hits the end of its
/// token stream.
@ -2363,12 +2364,14 @@ class Preprocessor {
// Pragmas.
void HandlePragmaDirective(PragmaIntroducer Introducer);
void ResolvePragmaIncludeInstead(SourceLocation Location) const;
public:
void HandlePragmaOnce(Token &OnceTok);
void HandlePragmaMark(Token &MarkTok);
void HandlePragmaPoison();
void HandlePragmaSystemHeader(Token &SysHeaderTok);
void HandlePragmaIncludeInstead(Token &Tok);
void HandlePragmaDependency(Token &DependencyTok);
void HandlePragmaPushMacro(Token &Tok);
void HandlePragmaPopMacro(Token &Tok);

View File

@ -14,11 +14,13 @@
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MultipleIncludeOpt.h"
#include "clang/Lex/Token.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include <cassert>
namespace clang {
@ -74,6 +76,13 @@ class PreprocessorLexer {
/// we are currently in.
SmallVector<PPConditionalInfo, 4> ConditionalStack;
struct IncludeInfo {
const FileEntry *File;
SourceLocation Location;
};
// A complete history of all the files included by the current file.
llvm::StringMap<IncludeInfo> IncludeHistory;
PreprocessorLexer() : FID() {}
PreprocessorLexer(Preprocessor *pp, FileID fid);
virtual ~PreprocessorLexer() = default;
@ -175,6 +184,15 @@ class PreprocessorLexer {
ConditionalStack.clear();
ConditionalStack.append(CL.begin(), CL.end());
}
void addInclude(StringRef Filename, const FileEntry &File,
SourceLocation Location) {
IncludeHistory.insert({Filename, {&File, Location}});
}
const llvm::StringMap<IncludeInfo> &getIncludeHistory() const {
return IncludeHistory;
}
};
} // namespace clang

View File

@ -199,9 +199,6 @@ class PreprocessorOptions {
/// build it again.
std::shared_ptr<FailedModulesSet> FailedModules;
/// A prefix map for __FILE__ and __BASE_FILE__.
std::map<std::string, std::string, std::greater<std::string>> MacroPrefixMap;
/// Contains the currently active skipped range mappings for skipping excluded
/// conditional directives.
///

View File

@ -7828,8 +7828,7 @@ class Sema final {
TemplateArgumentLoc &Arg,
SmallVectorImpl<TemplateArgument> &Converted);
bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
TypeSourceInfo *Arg);
bool CheckTemplateArgument(TypeSourceInfo *Arg);
ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *Arg,
TemplateArgument &Converted,

View File

@ -6066,9 +6066,11 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
NNS->getAsNamespaceAlias()->getNamespace()
->getOriginalNamespace());
// The difference between TypeSpec and TypeSpecWithTemplate is that the
// latter will have the 'template' keyword when printed.
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
QualType T = getCanonicalType(QualType(NNS->getAsType(), 0));
const Type *T = getCanonicalType(NNS->getAsType());
// If we have some kind of dependent-named type (e.g., "typename T::type"),
// break it apart into its prefix and identifier, then reconsititute those
@ -6078,14 +6080,16 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
// typedef typename T::type T1;
// typedef typename T1::type T2;
if (const auto *DNT = T->getAs<DependentNameType>())
return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
return NestedNameSpecifier::Create(
*this, DNT->getQualifier(),
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>())
return NestedNameSpecifier::Create(*this, DTST->getQualifier(), true,
const_cast<Type *>(T));
// Otherwise, just canonicalize the type, and force it to be a TypeSpec.
// FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the
// first place?
// TODO: Set 'Template' parameter to true for other template types.
return NestedNameSpecifier::Create(*this, nullptr, false,
const_cast<Type *>(T.getTypePtr()));
const_cast<Type *>(T));
}
case NestedNameSpecifier::Global:

View File

@ -2233,8 +2233,11 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
};
switch (getIdentKind()) {
case SourceLocExpr::File:
return MakeStringLiteral(PLoc.getFilename());
case SourceLocExpr::File: {
SmallString<256> Path(PLoc.getFilename());
Ctx.getLangOpts().remapPathPrefix(Path);
return MakeStringLiteral(Path);
}
case SourceLocExpr::Function: {
const Decl *CurDecl = dyn_cast_or_null<Decl>(Context);
return MakeStringLiteral(

View File

@ -11,6 +11,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
using namespace clang;
@ -48,6 +50,12 @@ VersionTuple LangOptions::getOpenCLVersionTuple() const {
return VersionTuple(Ver / 100, (Ver % 100) / 10);
}
void LangOptions::remapPathPrefix(SmallString<256> &Path) const {
for (const auto &Entry : MacroPrefixMap)
if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
break;
}
FPOptions FPOptions::defaultWithoutTrailingStorage(const LangOptions &LO) {
FPOptions result(LO);
return result;

View File

@ -111,7 +111,9 @@ bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
// Feature pairs. First feature in a pair requires the second one to be
// supported.
static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = {
{"__opencl_c_read_write_images", "__opencl_c_images"}};
{"__opencl_c_read_write_images", "__opencl_c_images"},
{"__opencl_c_3d_image_writes", "__opencl_c_images"},
{"__opencl_c_pipes", "__opencl_c_generic_address_space"}};
auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
@ -130,7 +132,8 @@ bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
const TargetInfo &TI, DiagnosticsEngine &Diags) {
// Extensions and equivalent feature pairs.
static const llvm::StringMap<llvm::StringRef> FeatureExtensionMap = {
{"cl_khr_fp64", "__opencl_c_fp64"}};
{"cl_khr_fp64", "__opencl_c_fp64"},
{"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();

View File

@ -400,14 +400,18 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
// OpenCL C v3.0 s6.7.5 - The generic address space requires support for
// OpenCL C 2.0 or OpenCL C 3.0 with the __opencl_c_generic_address_space
// feature
// FIXME: OpenCLGenericAddressSpace is also defined in setLangDefaults()
// OpenCL C v3.0 s6.2.1 - OpenCL pipes require support of OpenCL C 2.0
// or later and __opencl_c_pipes feature
// FIXME: These language options are also defined in setLangDefaults()
// for OpenCL C 2.0 but with no access to target capabilities. Target
// should be immutable once created and thus this language option needs
// should be immutable once created and thus these language options need
// to be defined only once.
if (Opts.OpenCLVersion >= 300) {
if (Opts.OpenCLVersion == 300) {
const auto &OpenCLFeaturesMap = getSupportedOpenCLOpts();
Opts.OpenCLGenericAddressSpace = hasFeatureEnabled(
OpenCLFeaturesMap, "__opencl_c_generic_address_space");
Opts.OpenCLPipes =
hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_pipes");
}
}

View File

@ -431,7 +431,8 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
Feature == "sve2-aes" || Feature == "sve2-sha3" ||
Feature == "sve2-sm4" || Feature == "f64mm" || Feature == "f32mm" ||
Feature == "i8mm" || Feature == "bf16") &&
(FPU & SveMode));
(FPU & SveMode)) ||
(Feature == "ls64" && HasLS64);
}
bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
@ -752,6 +753,9 @@ bool AArch64TargetInfo::validateConstraintModifier(
if (Size == 64)
return true;
if (Size == 512)
return HasLS64;
SuggestedModifier = "w";
return false;
}

View File

@ -310,9 +310,12 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
Opts["cl_khr_mipmap_image"] = true;
Opts["cl_khr_mipmap_image_writes"] = true;
Opts["cl_khr_subgroups"] = true;
Opts["cl_khr_3d_image_writes"] = true;
Opts["cl_amd_media_ops"] = true;
Opts["cl_amd_media_ops2"] = true;
Opts["__opencl_c_images"] = true;
Opts["__opencl_c_3d_image_writes"] = true;
Opts["cl_khr_3d_image_writes"] = true;
}
}

View File

@ -9732,6 +9732,29 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F);
}
if (BuiltinID == AArch64::BI__mulh || BuiltinID == AArch64::BI__umulh) {
llvm::Type *ResType = ConvertType(E->getType());
llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
bool IsSigned = BuiltinID == AArch64::BI__mulh;
Value *LHS =
Builder.CreateIntCast(EmitScalarExpr(E->getArg(0)), Int128Ty, IsSigned);
Value *RHS =
Builder.CreateIntCast(EmitScalarExpr(E->getArg(1)), Int128Ty, IsSigned);
Value *MulResult, *HigherBits;
if (IsSigned) {
MulResult = Builder.CreateNSWMul(LHS, RHS);
HigherBits = Builder.CreateAShr(MulResult, 64);
} else {
MulResult = Builder.CreateNUWMul(LHS, RHS);
HigherBits = Builder.CreateLShr(MulResult, 64);
}
HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned);
return HigherBits;
}
// Handle MSVC intrinsics before argument evaluation to prevent double
// evaluation.
if (Optional<MSVCIntrin> MsvcIntId = translateAarch64ToMsvcIntrin(BuiltinID))

View File

@ -555,7 +555,8 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
} else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) {
getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR ||
D->hasAttr<SelectAnyAttr>()) {
// C++ [basic.start.init]p2:
// Definitions of explicitly specialized class template static data
// members have ordered initialization. Other class template static data
@ -568,17 +569,18 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
// group with the global being initialized. On most platforms, this is a
// minor startup time optimization. In the MS C++ ABI, there are no guard
// variables, so this COMDAT key is required for correctness.
AddGlobalCtor(Fn, 65535, COMDATKey);
if (getTarget().getCXXABI().isMicrosoft() && COMDATKey) {
// In The MS C++, MS add template static data member in the linker
// drective.
addUsedGlobal(COMDATKey);
}
} else if (D->hasAttr<SelectAnyAttr>()) {
//
// SelectAny globals will be comdat-folded. Put the initializer into a
// COMDAT group associated with the global, so the initializers get folded
// too.
AddGlobalCtor(Fn, 65535, COMDATKey);
if (COMDATKey && (getTriple().isOSBinFormatELF() ||
getTarget().getCXXABI().isMicrosoft())) {
// When COMDAT is used on ELF or in the MS C++ ABI, the key must be in
// llvm.used to prevent linker GC.
addUsedGlobal(COMDATKey);
}
} else {
I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
if (I == DelayedCXXInitPosition.end()) {

View File

@ -2097,7 +2097,8 @@ CodeGenFunction::EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info,
} else {
llvm::Type *Ty = ConvertType(InputType);
uint64_t Size = CGM.getDataLayout().getTypeSizeInBits(Ty);
if (Size <= 64 && llvm::isPowerOf2_64(Size)) {
if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
getTargetHooks().isScalarizableAsmOperand(*this, Ty)) {
Ty = llvm::IntegerType::get(getLLVMContext(), Size);
Ty = llvm::PointerType::getUnqual(Ty);
@ -2320,23 +2321,28 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
// If this is a register output, then make the inline asm return it
// by-value. If this is a memory result, return the value by-reference.
bool isScalarizableAggregate =
hasAggregateEvaluationKind(OutExpr->getType());
if (!Info.allowsMemory() && (hasScalarEvaluationKind(OutExpr->getType()) ||
isScalarizableAggregate)) {
QualType QTy = OutExpr->getType();
const bool IsScalarOrAggregate = hasScalarEvaluationKind(QTy) ||
hasAggregateEvaluationKind(QTy);
if (!Info.allowsMemory() && IsScalarOrAggregate) {
Constraints += "=" + OutputConstraint;
ResultRegQualTys.push_back(OutExpr->getType());
ResultRegQualTys.push_back(QTy);
ResultRegDests.push_back(Dest);
ResultTruncRegTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
if (Info.allowsRegister() && isScalarizableAggregate) {
ResultTypeRequiresCast.push_back(true);
unsigned Size = getContext().getTypeSize(OutExpr->getType());
llvm::Type *ConvTy = llvm::IntegerType::get(getLLVMContext(), Size);
ResultRegTypes.push_back(ConvTy);
} else {
ResultTypeRequiresCast.push_back(false);
ResultRegTypes.push_back(ResultTruncRegTypes.back());
llvm::Type *Ty = ConvertTypeForMem(QTy);
const bool RequiresCast = Info.allowsRegister() &&
(getTargetHooks().isScalarizableAsmOperand(*this, Ty) ||
Ty->isAggregateType());
ResultTruncRegTypes.push_back(Ty);
ResultTypeRequiresCast.push_back(RequiresCast);
if (RequiresCast) {
unsigned Size = getContext().getTypeSize(QTy);
Ty = llvm::IntegerType::get(getLLVMContext(), Size);
}
ResultRegTypes.push_back(Ty);
// If this output is tied to an input, and if the input is larger, then
// we need to set the actual result type of the inline asm node to be the
// same as the input type.
@ -2638,11 +2644,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
llvm::Value *Tmp = RegResults[i];
llvm::Type *TruncTy = ResultTruncRegTypes[i];
// If the result type of the LLVM IR asm doesn't match the result type of
// the expression, do the conversion.
if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
llvm::Type *TruncTy = ResultTruncRegTypes[i];
// Truncate the integer result to the right size, note that TruncTy can be
// a pointer.
@ -2672,6 +2678,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
unsigned Size = getContext().getTypeSize(ResultRegQualTys[i]);
Address A = Builder.CreateBitCast(Dest.getAddress(*this),
ResultRegTypes[i]->getPointerTo());
if (getTargetHooks().isScalarizableAsmOperand(*this, TruncTy)) {
Builder.CreateStore(Tmp, A);
continue;
}
QualType Ty = getContext().getIntTypeForBitwidth(Size, /*Signed*/ false);
if (Ty.isNull()) {
const Expr *OutExpr = S.getOutputExpr(i);

View File

@ -186,7 +186,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
!getModule().getSourceFileName().empty()) {
std::string Path = getModule().getSourceFileName();
// Check if a path substitution is needed from the MacroPrefixMap.
for (const auto &Entry : PPO.MacroPrefixMap)
for (const auto &Entry : LangOpts.MacroPrefixMap)
if (Path.rfind(Entry.first, 0) != std::string::npos) {
Path = Entry.second + Path.substr(Entry.first.size());
break;

View File

@ -5526,6 +5526,20 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
Fn->addFnAttr("branch-target-enforcement",
BPI.BranchTargetEnforcement ? "true" : "false");
}
bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
llvm::Type *Ty) const override {
if (CGF.getTarget().hasFeature("ls64")) {
auto *ST = dyn_cast<llvm::StructType>(Ty);
if (ST && ST->getNumElements() == 1) {
auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
if (AT && AT->getNumElements() == 8 &&
AT->getElementType()->isIntegerTy(64))
return true;
}
}
return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty);
}
};
class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {

View File

@ -148,6 +148,13 @@ class TargetCodeGenInfo {
return Ty;
}
/// Target hook to decide whether an inline asm operand can be passed
/// by value.
virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
llvm::Type *Ty) const {
return false;
}
/// Adds constraints and types for result registers.
virtual void addReturnRegisterOutputs(
CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue,

View File

@ -52,9 +52,8 @@ using namespace clang;
using namespace llvm::opt;
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC,
options::OPT_fminimize_whitespace,
options::OPT_fno_minimize_whitespace)) {
if (Arg *A =
Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC)) {
if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
!Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
@ -2638,7 +2637,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath;
llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math;
StringRef FPContract = "on";
StringRef FPContract = "";
bool StrictFPModel = false;
@ -2663,7 +2662,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = false;
SignedZeros = true;
// -fno_fast_math restores default denormal and fpcontract handling
FPContract = "on";
FPContract = "";
DenormalFPMath = llvm::DenormalMode::getIEEE();
// FIXME: The target may have picked a non-IEEE default mode here based on
@ -2683,18 +2682,20 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// ffp-model= is a Driver option, it is entirely rewritten into more
// granular options before being passed into cc1.
// Use the gcc option in the switch below.
if (!FPModel.empty() && !FPModel.equals(Val))
if (!FPModel.empty() && !FPModel.equals(Val)) {
D.Diag(clang::diag::warn_drv_overriding_flag_option)
<< Args.MakeArgString("-ffp-model=" + FPModel)
<< Args.MakeArgString("-ffp-model=" + Val);
FPContract = "";
}
if (Val.equals("fast")) {
optID = options::OPT_ffast_math;
FPModel = Val;
FPContract = Val;
FPContract = "fast";
} else if (Val.equals("precise")) {
optID = options::OPT_ffp_contract;
FPModel = Val;
FPContract = "on";
FPContract = "fast";
PreciseFPModel = true;
} else if (Val.equals("strict")) {
StrictFPModel = true;
@ -2780,11 +2781,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
if (PreciseFPModel) {
// When -ffp-model=precise is seen on the command line,
// the boolean PreciseFPModel is set to true which indicates
// "the current option is actually PreciseFPModel". The optID
// is changed to OPT_ffp_contract and FPContract is set to "on".
// the argument Val string is "precise": it shouldn't be checked.
// -ffp-model=precise enables ffp-contract=fast as a side effect
// the FPContract value has already been set to a string literal
// and the Val string isn't a pertinent value.
;
} else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
FPContract = Val;
@ -2882,17 +2881,18 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = DefaultDenormalFPMath;
DenormalFP32Math = llvm::DenormalMode::getIEEE();
FPContract = "on";
FPContract = "";
break;
}
if (StrictFPModel) {
// If -ffp-model=strict has been specified on command line but
// subsequent options conflict then emit warning diagnostic.
if (HonorINFs && HonorNaNs && !AssociativeMath && !ReciprocalMath &&
SignedZeros && TrappingMath && RoundingFPMath &&
DenormalFPMath == llvm::DenormalMode::getIEEE() &&
DenormalFP32Math == llvm::DenormalMode::getIEEE() &&
FPContract.equals("off"))
if (HonorINFs && HonorNaNs &&
!AssociativeMath && !ReciprocalMath &&
SignedZeros && TrappingMath && RoundingFPMath &&
(FPContract.equals("off") || FPContract.empty()) &&
DenormalFPMath == llvm::DenormalMode::getIEEE() &&
DenormalFP32Math == llvm::DenormalMode::getIEEE())
// OK: Current Arg doesn't conflict with -ffp-model=strict
;
else {
@ -6068,16 +6068,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_use_line_directives, false))
CmdArgs.push_back("-fuse-line-directives");
// -fno-minimize-whitespace is default.
if (Args.hasFlag(options::OPT_fminimize_whitespace,
options::OPT_fno_minimize_whitespace, false)) {
types::ID InputType = Inputs[0].getType();
if (!isDerivedFromC(InputType))
D.Diag(diag::err_drv_minws_unsupported_input_type)
<< types::getTypeName(InputType);
CmdArgs.push_back("-fminimize-whitespace");
}
// -fms-extensions=0 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC))
@ -7701,8 +7691,11 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
assert(CurTC == nullptr && "Expected one dependence!");
CurTC = TC;
});
UB += C.addTempFile(
C.getArgs().MakeArgString(CurTC->getInputFilename(Inputs[I])));
} else {
UB += CurTC->getInputFilename(Inputs[I]);
}
UB += CurTC->getInputFilename(Inputs[I]);
}
CmdArgs.push_back(TCArgs.MakeArgString(UB));

View File

@ -588,21 +588,43 @@ void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();
const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();
const Driver &D = getDriver();
if (!D.SysRoot.empty()) {
SmallString<128> ResourceDirInclude(D.ResourceDir);
if (!IsELF) {
llvm::sys::path::append(ResourceDirInclude, "include");
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&
(!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
const bool HasSysRoot = !D.SysRoot.empty();
if (HasSysRoot) {
SmallString<128> P(D.SysRoot);
if (getTriple().isMusl())
if (IsLinuxMusl)
llvm::sys::path::append(P, "usr/include");
else
llvm::sys::path::append(P, "include");
addExternCSystemInclude(DriverArgs, CC1Args, P.str());
return;
// LOCAL_INCLUDE_DIR
addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");
// TOOL_INCLUDE_DIR
AddMultilibIncludeArgs(DriverArgs, CC1Args);
}
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
if (HasSysRoot)
return;
std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");

View File

@ -136,10 +136,13 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
llvm_unreachable("Unsupported target architecture.");
}
if (Args.hasArg(options::OPT_mwindows)) {
Arg *SubsysArg =
Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
CmdArgs.push_back("--subsystem");
CmdArgs.push_back("windows");
} else if (Args.hasArg(options::OPT_mconsole)) {
} else if (SubsysArg &&
SubsysArg->getOption().matches(options::OPT_mconsole)) {
CmdArgs.push_back("--subsystem");
CmdArgs.push_back("console");
}

View File

@ -147,45 +147,6 @@ bool types::isAcceptedByClang(ID Id) {
}
}
bool types::isDerivedFromC(ID Id) {
switch (Id) {
default:
return false;
case TY_PP_C:
case TY_C:
case TY_CL:
case TY_CLCXX:
case TY_PP_CUDA:
case TY_CUDA:
case TY_CUDA_DEVICE:
case TY_PP_HIP:
case TY_HIP:
case TY_HIP_DEVICE:
case TY_PP_ObjC:
case TY_PP_ObjC_Alias:
case TY_ObjC:
case TY_PP_CXX:
case TY_CXX:
case TY_PP_ObjCXX:
case TY_PP_ObjCXX_Alias:
case TY_ObjCXX:
case TY_RenderScript:
case TY_PP_CHeader:
case TY_CHeader:
case TY_CLHeader:
case TY_PP_ObjCHeader:
case TY_ObjCHeader:
case TY_PP_CXXHeader:
case TY_CXXHeader:
case TY_PP_ObjCXXHeader:
case TY_ObjCXXHeader:
case TY_CXXModule:
case TY_PP_CXXModule:
return true;
}
}
bool types::isObjC(ID Id) {
switch (Id) {
default:

View File

@ -347,7 +347,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
if (ScopeStart > Start + 1 &&
Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
Changes[ScopeStart - 1].Tok->is(tok::l_paren))
return true;
return Style.BinPackArguments;
// Ternary operator
if (Changes[i].Tok->is(TT_ConditionalExpr))

View File

@ -3173,7 +3173,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.ZVector = 0;
Opts.setDefaultFPContractMode(LangOptions::FPM_On);
Opts.OpenCLCPlusPlus = Opts.CPlusPlus;
Opts.OpenCLPipe = Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
Opts.OpenCLPipes = Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
Opts.OpenCLGenericAddressSpace =
Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
@ -3528,6 +3528,9 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
GenerateArg(Args, OPT_fexperimental_relative_cxx_abi_vtables, SA);
else
GenerateArg(Args, OPT_fno_experimental_relative_cxx_abi_vtables, SA);
for (const auto &MP : Opts.MacroPrefixMap)
GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA);
}
bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
@ -4037,6 +4040,12 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
options::OPT_fno_experimental_relative_cxx_abi_vtables,
TargetCXXABI::usesRelativeVTables(T));
for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
auto Split = StringRef(A).split('=');
Opts.MacroPrefixMap.insert(
{std::string(Split.first), std::string(Split.second)});
}
return Diags.getNumErrors() == NumErrorsBefore;
}
@ -4109,9 +4118,6 @@ static void GeneratePreprocessorArgs(PreprocessorOptions &Opts,
for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
GenerateArg(Args, OPT_error_on_deserialized_pch_decl, D, SA);
for (const auto &MP : Opts.MacroPrefixMap)
GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA);
if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
GenerateArg(Args, OPT_preamble_bytes_EQ,
Twine(Opts.PrecompiledPreambleBytes.first) + "," +
@ -4180,12 +4186,6 @@ static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
auto Split = StringRef(A).split('=');
Opts.MacroPrefixMap.insert(
{std::string(Split.first), std::string(Split.second)});
}
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
StringRef Value(A->getValue());
size_t Comma = Value.find(',');

View File

@ -95,20 +95,14 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
bool DumpIncludeDirectives;
bool UseLineDirectives;
bool IsFirstFileEntered;
bool MinimizeWhitespace;
Token PrevTok;
Token PrevPrevTok;
public:
PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
bool defines, bool DumpIncludeDirectives,
bool UseLineDirectives, bool MinimizeWhitespace)
bool UseLineDirectives)
: PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
DisableLineMarkers(lineMarkers), DumpDefines(defines),
DumpIncludeDirectives(DumpIncludeDirectives),
UseLineDirectives(UseLineDirectives),
MinimizeWhitespace(MinimizeWhitespace) {
UseLineDirectives(UseLineDirectives) {
CurLine = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
@ -116,13 +110,8 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
FileType = SrcMgr::C_User;
Initialized = false;
IsFirstFileEntered = false;
PrevTok.startToken();
PrevPrevTok.startToken();
}
bool isMinimizeWhitespace() const { return MinimizeWhitespace; }
void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
@ -131,12 +120,7 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
return EmittedDirectiveOnThisLine;
}
/// Ensure that the output stream position is at the beginning of a new line
/// and inserts one if it does not. It is intended to ensure that directives
/// inserted by the directives not from the input source (such as #line) are
/// in the first column. To insert newlines that represent the input, use
/// MoveToLine(/*...*/, /*RequireStartOfLine=*/true).
void startNewLineIfNeeded();
bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true);
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@ -164,45 +148,18 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
/// Insert whitespace before emitting the next token.
///
/// @param Tok Next token to be emitted.
/// @param RequireSpace Ensure at least one whitespace is emitted. Useful
/// if non-tokens have been emitted to the stream.
/// @param RequireSameLine Never emit newlines. Useful when semantics depend
/// on being on the same line, such as directives.
void HandleWhitespaceBeforeTok(const Token &Tok, bool RequireSpace,
bool RequireSameLine);
bool HandleFirstTokOnLine(Token &Tok);
/// Move to the line of the provided source location. This will
/// return true if a newline was inserted or if
/// the requested location is the first token on the first line.
/// In these cases the next output will be the first column on the line and
/// make it possible to insert indention. The newline was inserted
/// implicitly when at the beginning of the file.
///
/// @param Tok Token where to move to.
/// @param RequiresStartOfLine Whether the next line depends on being in the
/// first column, such as a directive.
///
/// @return Whether column adjustments are necessary.
bool MoveToLine(const Token &Tok, bool RequireStartOfLine) {
PresumedLoc PLoc = SM.getPresumedLoc(Tok.getLocation());
if (PLoc.isInvalid())
return false;
bool IsFirstInFile = Tok.isAtStartOfLine() && PLoc.getLine() == 1;
return MoveToLine(PLoc.getLine(), RequireStartOfLine) || IsFirstInFile;
}
/// Move to the line of the provided source location. Returns true if a new
/// line was inserted.
bool MoveToLine(SourceLocation Loc, bool RequireStartOfLine) {
/// return true if the output stream required adjustment or if
/// the requested location is on the first line.
bool MoveToLine(SourceLocation Loc) {
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid())
return false;
return MoveToLine(PLoc.getLine(), RequireStartOfLine);
return MoveToLine(PLoc.getLine()) || (PLoc.getLine() == 1);
}
bool MoveToLine(unsigned LineNo, bool RequireStartOfLine);
bool MoveToLine(unsigned LineNo);
bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok,
const Token &Tok) {
@ -230,7 +187,7 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
const char *Extra,
unsigned ExtraLen) {
startNewLineIfNeeded();
startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
// Emit #line directives or GNU line markers depending on what mode we're in.
if (UseLineDirectives) {
@ -257,57 +214,43 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
/// object. We can do this by emitting some number of \n's, or be emitting a
/// #line directive. This returns false if already at the specified line, true
/// if some newlines were emitted.
bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo,
bool RequireStartOfLine) {
// If it is required to start a new line or finish the current, insert
// vertical whitespace now and take it into account when moving to the
// expected line.
bool StartedNewLine = false;
if ((RequireStartOfLine && EmittedTokensOnThisLine) ||
EmittedDirectiveOnThisLine) {
OS << '\n';
StartedNewLine = true;
CurLine += 1;
EmittedTokensOnThisLine = false;
EmittedDirectiveOnThisLine = false;
}
bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) {
// If this line is "close enough" to the original line, just print newlines,
// otherwise print a #line directive.
if (CurLine == LineNo) {
// Nothing to do if we are already on the correct line.
} else if (!StartedNewLine && (!MinimizeWhitespace || !DisableLineMarkers) &&
LineNo - CurLine == 1) {
// Printing a single line has priority over printing a #line directive, even
// when minimizing whitespace which otherwise would print #line directives
// for every single line.
OS << '\n';
StartedNewLine = true;
} else if (!MinimizeWhitespace && LineNo - CurLine <= 8) {
const char *NewLines = "\n\n\n\n\n\n\n\n";
OS.write(NewLines, LineNo - CurLine);
StartedNewLine = true;
if (LineNo-CurLine <= 8) {
if (LineNo-CurLine == 1)
OS << '\n';
else if (LineNo == CurLine)
return false; // Spelling line moved, but expansion line didn't.
else {
const char *NewLines = "\n\n\n\n\n\n\n\n";
OS.write(NewLines, LineNo-CurLine);
}
} else if (!DisableLineMarkers) {
// Emit a #line or line marker.
WriteLineInfo(LineNo, nullptr, 0);
StartedNewLine = true;
}
if (StartedNewLine) {
EmittedTokensOnThisLine = false;
EmittedDirectiveOnThisLine = false;
} else {
// Okay, we're in -P mode, which turns off line markers. However, we still
// need to emit a newline between tokens on different lines.
startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
}
CurLine = LineNo;
return StartedNewLine;
return true;
}
void PrintPPOutputPPCallbacks::startNewLineIfNeeded() {
bool
PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) {
if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) {
OS << '\n';
EmittedTokensOnThisLine = false;
EmittedDirectiveOnThisLine = false;
if (ShouldUpdateCurrentLine)
++CurLine;
return true;
}
return false;
}
/// FileChanged - Whenever the preprocessor enters or exits a #include file
@ -330,7 +273,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
if (Reason == PPCallbacks::EnterFile) {
SourceLocation IncludeLoc = UserLoc.getIncludeLoc();
if (IncludeLoc.isValid())
MoveToLine(IncludeLoc, /*RequireStartOfLine=*/false);
MoveToLine(IncludeLoc);
} else if (Reason == PPCallbacks::SystemHeaderPragma) {
// GCC emits the # directive for this directive on the line AFTER the
// directive and emits a bunch of spaces that aren't needed. This is because
@ -347,8 +290,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
FileType = NewFileType;
if (DisableLineMarkers) {
if (!MinimizeWhitespace)
startNewLineIfNeeded();
startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
return;
}
@ -394,13 +336,15 @@ void PrintPPOutputPPCallbacks::InclusionDirective(
// In -dI mode, dump #include directives prior to dumping their content or
// interpretation.
if (DumpIncludeDirectives) {
MoveToLine(HashLoc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(HashLoc);
const std::string TokenText = PP.getSpelling(IncludeTok);
assert(!TokenText.empty());
OS << "#" << TokenText << " "
<< (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
<< " /* clang -E -dI */";
setEmittedDirectiveOnThisLine();
startNewLineIfNeeded();
}
// When preprocessing, turn implicit imports into module import pragmas.
@ -409,13 +353,17 @@ void PrintPPOutputPPCallbacks::InclusionDirective(
case tok::pp_include:
case tok::pp_import:
case tok::pp_include_next:
MoveToLine(HashLoc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(HashLoc);
OS << "#pragma clang module import " << Imported->getFullModuleName(true)
<< " /* clang -E: implicit import for "
<< "#" << PP.getSpelling(IncludeTok) << " "
<< (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
<< " */";
setEmittedDirectiveOnThisLine();
// Since we want a newline after the pragma, but not a #<line>, start a
// new line immediately.
EmittedTokensOnThisLine = true;
startNewLineIfNeeded();
break;
case tok::pp___include_macros:
@ -450,11 +398,11 @@ void PrintPPOutputPPCallbacks::EndModule(const Module *M) {
/// Ident - Handle #ident directives when read by the preprocessor.
///
void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
MoveToLine(Loc);
OS.write("#ident ", strlen("#ident "));
OS.write(S.begin(), S.size());
setEmittedTokensOnThisLine();
EmittedTokensOnThisLine = true;
}
/// MacroDefined - This hook is called whenever a macro definition is seen.
@ -466,7 +414,7 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
// Ignore __FILE__ etc.
MI->isBuiltinMacro()) return;
MoveToLine(MI->getDefinitionLoc(), /*RequireStartOfLine=*/true);
MoveToLine(MI->getDefinitionLoc());
PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS);
setEmittedDirectiveOnThisLine();
}
@ -477,7 +425,7 @@ void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
// Only print out macro definitions in -dD mode.
if (!DumpDefines) return;
MoveToLine(MacroNameTok.getLocation(), /*RequireStartOfLine=*/true);
MoveToLine(MacroNameTok.getLocation());
OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName();
setEmittedDirectiveOnThisLine();
}
@ -498,7 +446,8 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
StringRef Namespace,
PragmaMessageKind Kind,
StringRef Str) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma ";
if (!Namespace.empty())
OS << Namespace << ' ';
@ -523,7 +472,8 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc,
StringRef DebugType) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma clang __debug ";
OS << DebugType;
@ -533,14 +483,16 @@ void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc,
void PrintPPOutputPPCallbacks::
PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic push";
setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::
PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic pop";
setEmittedDirectiveOnThisLine();
}
@ -549,7 +501,8 @@ void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
StringRef Namespace,
diag::Severity Map,
StringRef Str) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic ";
switch (Map) {
case diag::Severity::Remark:
@ -575,7 +528,8 @@ void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc,
StringRef WarningSpec,
ArrayRef<int> Ids) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma warning(" << WarningSpec << ':';
for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I)
OS << ' ' << *I;
@ -585,7 +539,8 @@ void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc,
void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc,
int Level) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma warning(push";
if (Level >= 0)
OS << ", " << Level;
@ -594,14 +549,16 @@ void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc,
}
void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma warning(pop)";
setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc,
StringRef Str) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma character_execution_set(push";
if (!Str.empty())
OS << ", " << Str;
@ -610,80 +567,64 @@ void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc,
}
void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma character_execution_set(pop)";
setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::
PragmaAssumeNonNullBegin(SourceLocation Loc) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma clang assume_nonnull begin";
setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::
PragmaAssumeNonNullEnd(SourceLocation Loc) {
MoveToLine(Loc, /*RequireStartOfLine=*/true);
startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma clang assume_nonnull end";
setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::HandleWhitespaceBeforeTok(const Token &Tok,
bool RequireSpace,
bool RequireSameLine) {
// These tokens are not expanded to anything and don't need whitespace before
// them.
if (Tok.is(tok::eof) ||
(Tok.isAnnotation() && !Tok.is(tok::annot_header_unit) &&
!Tok.is(tok::annot_module_begin) && !Tok.is(tok::annot_module_end)))
return;
/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
/// is called for the first token on each new line. If this really is the start
/// of a new logical line, handle it and return true, otherwise return false.
/// This may not be the start of a logical line because the "start of line"
/// marker is set for spelling lines, not expansion ones.
bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
// Figure out what line we went to and insert the appropriate number of
// newline characters.
if (!MoveToLine(Tok.getLocation()))
return false;
if (!RequireSameLine && MoveToLine(Tok, /*RequireStartOfLine=*/false)) {
if (MinimizeWhitespace) {
// Avoid interpreting hash as a directive under -fpreprocessed.
if (Tok.is(tok::hash))
OS << ' ';
} else {
// Print out space characters so that the first token on a line is
// indented for easy reading.
unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation());
// Print out space characters so that the first token on a line is
// indented for easy reading.
unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation());
// The first token on a line can have a column number of 1, yet still
// expect leading white space, if a macro expansion in column 1 starts
// with an empty macro argument, or an empty nested macro expansion. In
// this case, move the token to column 2.
if (ColNo == 1 && Tok.hasLeadingSpace())
ColNo = 2;
// The first token on a line can have a column number of 1, yet still expect
// leading white space, if a macro expansion in column 1 starts with an empty
// macro argument, or an empty nested macro expansion. In this case, move the
// token to column 2.
if (ColNo == 1 && Tok.hasLeadingSpace())
ColNo = 2;
// This hack prevents stuff like:
// #define HASH #
// HASH define foo bar
// From having the # character end up at column 1, which makes it so it
// is not handled as a #define next time through the preprocessor if in
// -fpreprocessed mode.
if (ColNo <= 1 && Tok.is(tok::hash))
OS << ' ';
// This hack prevents stuff like:
// #define HASH #
// HASH define foo bar
// From having the # character end up at column 1, which makes it so it
// is not handled as a #define next time through the preprocessor if in
// -fpreprocessed mode.
if (ColNo <= 1 && Tok.is(tok::hash))
OS << ' ';
// Otherwise, indent the appropriate number of spaces.
for (; ColNo > 1; --ColNo)
OS << ' ';
}
} else {
// Insert whitespace between the previous and next token if either
// - The caller requires it
// - The input had whitespace between them and we are not in
// whitespace-minimization mode
// - The whitespace is necessary to keep the tokens apart and there is not
// already a newline between them
if (RequireSpace || (!MinimizeWhitespace && Tok.hasLeadingSpace()) ||
((EmittedTokensOnThisLine || EmittedTokensOnThisLine) &&
AvoidConcat(PrevPrevTok, PrevTok, Tok)))
OS << ' ';
}
// Otherwise, indent the appropriate number of spaces.
for (; ColNo > 1; --ColNo)
OS << ' ';
PrevPrevTok = PrevTok;
PrevTok = Tok;
return true;
}
void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
@ -727,9 +668,9 @@ struct UnknownPragmaHandler : public PragmaHandler {
Token &PragmaTok) override {
// Figure out what line we went to and insert the appropriate number of
// newline characters.
Callbacks->MoveToLine(PragmaTok.getLocation(), /*RequireStartOfLine=*/true);
Callbacks->startNewLineIfNeeded();
Callbacks->MoveToLine(PragmaTok.getLocation());
Callbacks->OS.write(Prefix, strlen(Prefix));
Callbacks->setEmittedTokensOnThisLine();
if (ShouldExpandTokens) {
// The first token does not have expanded macros. Expand them, if
@ -741,16 +682,21 @@ struct UnknownPragmaHandler : public PragmaHandler {
/*IsReinject=*/false);
PP.Lex(PragmaTok);
}
Token PrevToken;
Token PrevPrevToken;
PrevToken.startToken();
PrevPrevToken.startToken();
// Read and print all of the pragma tokens.
bool IsFirst = true;
while (PragmaTok.isNot(tok::eod)) {
Callbacks->HandleWhitespaceBeforeTok(PragmaTok, /*RequireSpace=*/IsFirst,
/*RequireSameLine=*/true);
IsFirst = false;
if (PragmaTok.hasLeadingSpace() ||
Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok))
Callbacks->OS << ' ';
std::string TokSpell = PP.getSpelling(PragmaTok);
Callbacks->OS.write(&TokSpell[0], TokSpell.size());
Callbacks->setEmittedTokensOnThisLine();
PrevPrevToken = PrevToken;
PrevToken = PragmaTok;
if (ShouldExpandTokens)
PP.Lex(PragmaTok);
@ -769,41 +715,44 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
bool DropComments = PP.getLangOpts().TraditionalCPP &&
!PP.getCommentRetentionState();
bool IsStartOfLine = false;
char Buffer[256];
Token PrevPrevTok, PrevTok;
PrevPrevTok.startToken();
PrevTok.startToken();
while (1) {
// Two lines joined with line continuation ('\' as last character on the
// line) must be emitted as one line even though Tok.getLine() returns two
// different values. In this situation Tok.isAtStartOfLine() is false even
// though it may be the first token on the lexical line. When
// dropping/skipping a token that is at the start of a line, propagate the
// start-of-line-ness to the next token to not append it to the previous
// line.
IsStartOfLine = IsStartOfLine || Tok.isAtStartOfLine();
if (Callbacks->hasEmittedDirectiveOnThisLine()) {
Callbacks->startNewLineIfNeeded();
Callbacks->MoveToLine(Tok.getLocation());
}
Callbacks->HandleWhitespaceBeforeTok(Tok, /*RequireSpace=*/false,
/*RequireSameLine=*/!IsStartOfLine);
// If this token is at the start of a line, emit newlines if needed.
if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
// done.
} else if (Tok.hasLeadingSpace() ||
// If we haven't emitted a token on this line yet, PrevTok isn't
// useful to look at and no concatenation could happen anyway.
(Callbacks->hasEmittedTokensOnThisLine() &&
// Don't print "-" next to "-", it would form "--".
Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) {
OS << ' ';
}
if (DropComments && Tok.is(tok::comment)) {
// Skip comments. Normally the preprocessor does not generate
// tok::comment nodes at all when not keeping comments, but under
// -traditional-cpp the lexer keeps /all/ whitespace, including comments.
PP.Lex(Tok);
continue;
SourceLocation StartLoc = Tok.getLocation();
Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength()));
} else if (Tok.is(tok::eod)) {
// Don't print end of directive tokens, since they are typically newlines
// that mess up our line tracking. These come from unknown pre-processor
// directives or hash-prefixed comments in standalone assembly files.
PP.Lex(Tok);
// FIXME: The token on the next line after #include should have
// Tok.isAtStartOfLine() set.
IsStartOfLine = true;
continue;
} else if (Tok.is(tok::annot_module_include)) {
// PrintPPOutputPPCallbacks::InclusionDirective handles producing
// appropriate output here. Ignore this token entirely.
PP.Lex(Tok);
IsStartOfLine = true;
continue;
} else if (Tok.is(tok::annot_module_begin)) {
// FIXME: We retrieve this token after the FileChanged callback, and
@ -815,13 +764,11 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
Callbacks->BeginModule(
reinterpret_cast<Module *>(Tok.getAnnotationValue()));
PP.Lex(Tok);
IsStartOfLine = true;
continue;
} else if (Tok.is(tok::annot_module_end)) {
Callbacks->EndModule(
reinterpret_cast<Module *>(Tok.getAnnotationValue()));
PP.Lex(Tok);
IsStartOfLine = true;
continue;
} else if (Tok.is(tok::annot_header_unit)) {
// This is a header-name that has been (effectively) converted into a
@ -849,17 +796,8 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
// Tokens that can contain embedded newlines need to adjust our current
// line number.
// FIXME: The token may end with a newline in which case
// setEmittedDirectiveOnThisLine/setEmittedTokensOnThisLine afterwards is
// wrong.
if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown)
Callbacks->HandleNewlinesInToken(TokPtr, Len);
if (Tok.is(tok::comment) && Len >= 2 && TokPtr[0] == '/' &&
TokPtr[1] == '/') {
// It's a line comment;
// Ensure that we don't concatenate anything behind it.
Callbacks->setEmittedDirectiveOnThisLine();
}
} else {
std::string S = PP.getSpelling(Tok);
OS.write(S.data(), S.size());
@ -868,17 +806,13 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
// line number.
if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown)
Callbacks->HandleNewlinesInToken(S.data(), S.size());
if (Tok.is(tok::comment) && S.size() >= 2 && S[0] == '/' && S[1] == '/') {
// It's a line comment;
// Ensure that we don't concatenate anything behind it.
Callbacks->setEmittedDirectiveOnThisLine();
}
}
Callbacks->setEmittedTokensOnThisLine();
IsStartOfLine = false;
if (Tok.is(tok::eof)) break;
PrevPrevTok = PrevTok;
PrevTok = Tok;
PP.Lex(Tok);
}
}
@ -936,8 +870,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(
PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros,
Opts.ShowIncludeDirectives, Opts.UseLineDirectives,
Opts.MinimizeWhitespace);
Opts.ShowIncludeDirectives, Opts.UseLineDirectives);
// Expand macros in pragmas with -fms-extensions. The assumption is that
// the majority of pragmas in such a file will be Microsoft pragmas.

View File

@ -574,6 +574,9 @@ void _WriteStatusReg(int, __int64);
unsigned short __cdecl _byteswap_ushort(unsigned short val);
unsigned long __cdecl _byteswap_ulong (unsigned long val);
unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64 val);
__int64 __mulh(__int64 __a, __int64 __b);
unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b);
#endif
/*----------------------------------------------------------------------------*\

View File

@ -2811,11 +2811,11 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
ConditionalStack.pop_back();
}
SourceLocation EndLoc = getSourceLocation(BufferEnd);
// C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
// a pedwarn.
if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
DiagnosticsEngine &Diags = PP->getDiagnostics();
SourceLocation EndLoc = getSourceLocation(BufferEnd);
unsigned DiagID;
if (LangOpts.CPlusPlus11) {
@ -2838,7 +2838,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
BufferPtr = CurPtr;
// Finally, let the preprocessor handle this.
return PP->HandleEndOfFile(Result, isPragmaLexer());
return PP->HandleEndOfFile(Result, EndLoc, isPragmaLexer());
}
/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from

View File

@ -2022,6 +2022,10 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
// Record the header's filename for later use.
if (File)
CurLexer->addInclude(OriginalFilename, File->getFileEntry(), FilenameLoc);
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
if (File && isPCHThroughHeader(&File->getFileEntry()))
SkippingUntilPCHThroughHeader = false;

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
@ -22,6 +23,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/Path.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@ -299,10 +301,46 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
}
}
void Preprocessor::ResolvePragmaIncludeInstead(
const SourceLocation Location) const {
assert(Location.isValid());
if (CurLexer == nullptr)
return;
if (SourceMgr.isInSystemHeader(Location))
return;
for (const auto &Include : CurLexer->getIncludeHistory()) {
StringRef Filename = Include.getKey();
const PreprocessorLexer::IncludeInfo &Info = Include.getValue();
ArrayRef<SmallString<32>> Aliases =
HeaderInfo.getFileInfo(Info.File).Aliases.getArrayRef();
if (Aliases.empty())
continue;
switch (Aliases.size()) {
case 1:
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
<< Filename << 0 << Aliases[0];
continue;
case 2:
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
<< Filename << 1 << Aliases[0] << Aliases[1];
continue;
default: {
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
<< Filename << 2 << ("{'" + llvm::join(Aliases, "', '") + "'}");
}
}
}
}
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
/// the current file. This either returns the EOF token or pops a level off
/// the include stack and keeps going.
bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc,
bool isEndOfMacro) {
assert(!CurTokenLexer &&
"Ending a file when currently in a macro!");
@ -372,6 +410,9 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}
}
if (EndLoc.isValid())
ResolvePragmaIncludeInstead(EndLoc);
// Complain about reaching a true EOF within arc_cf_code_audited.
// We don't want to complain about reaching the end of a macro
// instantiation or a _Pragma.
@ -560,7 +601,7 @@ bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);
// Handle this like a #include file being popped off the stack.
return HandleEndOfFile(Result, true);
return HandleEndOfFile(Result, {}, true);
}
/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the

View File

@ -1453,15 +1453,6 @@ static bool isTargetEnvironment(const TargetInfo &TI,
return TI.getTriple().getEnvironment() == Env.getEnvironment();
}
static void remapMacroPath(
SmallString<256> &Path,
const std::map<std::string, std::string, std::greater<std::string>>
&MacroPrefixMap) {
for (const auto &Entry : MacroPrefixMap)
if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
break;
}
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
@ -1543,7 +1534,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
} else {
FN += PLoc.getFilename();
}
remapMacroPath(FN, PPOpts->MacroPrefixMap);
getLangOpts().remapPathPrefix(FN);
Lexer::Stringify(FN);
OS << '"' << FN << '"';
}

View File

@ -13,6 +13,7 @@
#include "clang/Lex/Pragma.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticLex.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
@ -35,11 +36,12 @@
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Timer.h"
@ -495,43 +497,88 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
SrcMgr::C_System);
}
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
static llvm::Optional<Token> LexHeader(Preprocessor &PP,
Optional<FileEntryRef> &File,
bool SuppressIncludeNotFoundError) {
Token FilenameTok;
if (LexHeaderName(FilenameTok, /*AllowConcatenation*/false))
return;
if (PP.LexHeaderName(FilenameTok, /*AllowConcatenation*/ false))
return llvm::None;
// If the next token wasn't a header-name, diagnose the error.
if (FilenameTok.isNot(tok::header_name)) {
Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
return;
PP.Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
return llvm::None;
}
// Reserve a buffer to get the spelling.
SmallString<128> FilenameBuffer;
bool Invalid = false;
StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
StringRef Filename = PP.getSpelling(FilenameTok, FilenameBuffer, &Invalid);
if (Invalid)
return;
return llvm::None;
bool isAngled =
GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
PP.GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
// error.
if (Filename.empty())
return;
return llvm::None;
// Search include directories for this file.
const DirectoryLookup *CurDir;
Optional<FileEntryRef> File =
LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
nullptr, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr);
File = PP.LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
nullptr, CurDir, nullptr, nullptr, nullptr, nullptr,
nullptr);
if (!File) {
if (!SuppressIncludeNotFoundError)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
PP.Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return llvm::None;
}
return FilenameTok;
}
/// HandlePragmaIncludeInstead - Handle \#pragma clang include_instead(header).
void Preprocessor::HandlePragmaIncludeInstead(Token &Tok) {
// Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
PreprocessorLexer *TheLexer = getCurrentFileLexer();
if (!SourceMgr.isInSystemHeader(Tok.getLocation())) {
Diag(Tok, diag::err_pragma_include_instead_not_sysheader);
return;
}
Lex(Tok);
if (Tok.isNot(tok::l_paren)) {
Diag(Tok, diag::err_expected) << "(";
return;
}
Optional<FileEntryRef> File;
llvm::Optional<Token> FilenameTok =
LexHeader(*this, File, SuppressIncludeNotFoundError);
if (!FilenameTok)
return;
Lex(Tok);
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected) << ")";
return;
}
SmallString<128> FilenameBuffer;
StringRef Filename = getSpelling(*FilenameTok, FilenameBuffer);
HeaderInfo.AddFileAlias(TheLexer->getFileEntry(), Filename);
}
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
Optional<FileEntryRef> File;
llvm::Optional<Token> FilenameTok =
LexHeader(*this, File, SuppressIncludeNotFoundError);
if (!FilenameTok)
return;
const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
// If this file is older than the file it depends on, emit a diagnostic.
@ -547,7 +594,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
// Remove the trailing ' ' if present.
if (!Message.empty())
Message.erase(Message.end()-1);
Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
Diag(*FilenameTok, diag::pp_out_of_date_dependency) << Message;
}
}
@ -1022,6 +1069,18 @@ struct PragmaSystemHeaderHandler : public PragmaHandler {
}
};
/// PragmaIncludeInsteadHandler - "\#pragma clang include_instead(header)" marks
/// the current file as non-includable if the including header is not a system
/// header.
struct PragmaIncludeInsteadHandler : public PragmaHandler {
PragmaIncludeInsteadHandler() : PragmaHandler("include_instead") {}
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Token &IIToken) override {
PP.HandlePragmaIncludeInstead(IIToken);
}
};
struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler() : PragmaHandler("dependency") {}
@ -1934,6 +1993,7 @@ void Preprocessor::RegisterBuiltinPragmas() {
// #pragma clang ...
AddPragmaHandler("clang", new PragmaPoisonHandler());
AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
AddPragmaHandler("clang", new PragmaIncludeInsteadHandler());
AddPragmaHandler("clang", new PragmaDebugHandler());
AddPragmaHandler("clang", new PragmaDependencyHandler());
AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));

View File

@ -716,12 +716,6 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
}
// Update the token info (identifier info and appropriate token kind).
// FIXME: the raw_identifier may contain leading whitespace which is removed
// from the cleaned identifier token. The SourceLocation should be updated to
// refer to the non-whitespace character. For instance, the text "\\\nB" (a
// line continuation before 'B') is parsed as a single tok::raw_identifier and
// is cleaned to tok::identifier "B". After cleaning the token's length is
// still 3 and the SourceLocation refers to the location of the backslash.
Identifier.setIdentifierInfo(II);
if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() &&
getSourceManager().isInSystemHeader(Identifier.getLocation()))

View File

@ -3952,8 +3952,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
Tok.setKind(tok::identifier);
goto DoneWithDeclSpec;
}
isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
} else if (!getLangOpts().OpenCLPipes) {
DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
isInvalid = true;
} else
isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
break;
// We only need to enumerate each image type once.
#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
@ -5126,8 +5130,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
switch (Tok.getKind()) {
default: return false;
// OpenCL 2.0 and later define this keyword.
case tok::kw_pipe:
return getLangOpts().OpenCLPipe;
return (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) ||
getLangOpts().OpenCLCPlusPlus;
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
@ -5656,7 +5662,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
if (Kind == tok::star || Kind == tok::caret)
return true;
if (Kind == tok::kw_pipe && Lang.OpenCLPipe)
// OpenCL 2.0 and later define this keyword.
if (Kind == tok::kw_pipe &&
((Lang.OpenCL && Lang.OpenCLVersion >= 200) || Lang.OpenCLCPlusPlus))
return true;
if (!Lang.CPlusPlus)

View File

@ -327,7 +327,8 @@ void Sema::Initialize() {
if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) {
addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
addImplicitTypedef("queue_t", Context.OCLQueueTy);
addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
if (getLangOpts().OpenCLPipes)
addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));

View File

@ -742,22 +742,15 @@ Optional<NormalizedConstraint>
NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
ArrayRef<const Expr *> E) {
assert(E.size() != 0);
auto First = fromConstraintExpr(S, D, E[0]);
if (E.size() == 1)
return First;
auto Second = fromConstraintExpr(S, D, E[1]);
if (!Second)
auto Conjunction = fromConstraintExpr(S, D, E[0]);
if (!Conjunction)
return None;
llvm::Optional<NormalizedConstraint> Conjunction;
Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
CCK_Conjunction);
for (unsigned I = 2; I < E.size(); ++I) {
for (unsigned I = 1; I < E.size(); ++I) {
auto Next = fromConstraintExpr(S, D, E[I]);
if (!Next)
return llvm::Optional<NormalizedConstraint>{};
NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
return None;
*Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
std::move(*Next), CCK_Conjunction);
*Conjunction = std::move(NewConjunction);
}
return Conjunction;
}

View File

@ -12472,6 +12472,8 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
return false;
}
const NestedNameSpecifier *CNNS =
Context.getCanonicalNestedNameSpecifier(Qual);
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
@ -12497,8 +12499,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
// didn't before instantiation).
if (Context.getCanonicalNestedNameSpecifier(Qual) !=
Context.getCanonicalNestedNameSpecifier(DQual))
if (CNNS != Context.getCanonicalNestedNameSpecifier(DQual))
continue;
Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();

View File

@ -1079,7 +1079,7 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
return Param;
// Check the template argument itself.
if (CheckTemplateArgument(Param, DefaultTInfo)) {
if (CheckTemplateArgument(DefaultTInfo)) {
Param->setInvalidDecl();
return Param;
}
@ -5042,7 +5042,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
}
}
if (CheckTemplateArgument(Param, TSI))
if (CheckTemplateArgument(TSI))
return true;
// Add the converted template type argument.
@ -5661,7 +5661,7 @@ bool Sema::CheckTemplateArgumentList(
TemplateArgumentListInfo NewArgs = TemplateArgs;
// Make sure we get the template parameter list from the most
// recentdeclaration, since that is the only one that has is guaranteed to
// recent declaration, since that is the only one that is guaranteed to
// have all the default template argument information.
TemplateParameterList *Params =
cast<TemplateDecl>(Template->getMostRecentDecl())
@ -6208,8 +6208,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
///
/// This routine implements the semantics of C++ [temp.arg.type]. It
/// returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
TypeSourceInfo *ArgInfo) {
bool Sema::CheckTemplateArgument(TypeSourceInfo *ArgInfo) {
assert(ArgInfo && "invalid TypeSourceInfo");
QualType Arg = ArgInfo->getType();
SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();

View File

@ -1934,25 +1934,23 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
return Req;
Sema::SFINAETrap Trap(SemaRef);
TemplateDeductionInfo Info(Req->getExpr()->getBeginLoc());
llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *>
TransExpr;
if (Req->isExprSubstitutionFailure())
TransExpr = Req->getExprSubstitutionDiagnostic();
else {
Sema::InstantiatingTemplate ExprInst(SemaRef, Req->getExpr()->getBeginLoc(),
Req, Info,
Req->getExpr()->getSourceRange());
Expr *E = Req->getExpr();
TemplateDeductionInfo Info(E->getBeginLoc());
Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req, Info,
E->getSourceRange());
if (ExprInst.isInvalid())
return nullptr;
ExprResult TransExprRes = TransformExpr(Req->getExpr());
ExprResult TransExprRes = TransformExpr(E);
if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
TransExpr = createSubstDiag(SemaRef, Info,
[&] (llvm::raw_ostream& OS) {
Req->getExpr()->printPretty(OS, nullptr,
SemaRef.getPrintingPolicy());
});
TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream &OS) {
E->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
});
else
TransExpr = TransExprRes.get();
}
@ -1966,6 +1964,7 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
else if (RetReq.isTypeConstraint()) {
TemplateParameterList *OrigTPL =
RetReq.getTypeConstraintTemplateParameterList();
TemplateDeductionInfo Info(OrigTPL->getTemplateLoc());
Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(),
Req, Info, OrigTPL->getSourceRange());
if (TPLInst.isInvalid())

View File

@ -1525,18 +1525,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().isSupported("cl_khr_fp64", S.getLangOpts()))
S.Diag(DS.getTypeSpecTypeLoc(),
diag::err_opencl_double_requires_extension)
<< (S.getLangOpts().OpenCLVersion >= 300);
else if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp64", S.getLangOpts()))
S.Diag(DS.getTypeSpecTypeLoc(), diag::ext_opencl_double_without_pragma);
}
if (DS.getTypeSpecWidth() == TypeSpecifierWidth::Long)
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().isSupported("cl_khr_fp64", S.getLangOpts()))
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
<< 0 << Result
<< (S.getLangOpts().OpenCLVersion == 300
? "cl_khr_fp64 and __opencl_c_fp64"
: "cl_khr_fp64");
else if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp64", S.getLangOpts()))
S.Diag(DS.getTypeSpecTypeLoc(), diag::ext_opencl_double_without_pragma);
}
break;
case DeclSpec::TST_float128:
if (!S.Context.getTargetInfo().hasFloat128Type() &&
@ -1724,21 +1726,28 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (S.getLangOpts().OpenCL) {
const auto &OpenCLOptions = S.getOpenCLOptions();
StringRef OptName;
bool IsOpenCLC30 = (S.getLangOpts().OpenCLVersion == 300);
// OpenCL C v3.0 s6.3.3 - OpenCL image types require __opencl_c_images
// support
// support.
// OpenCL C v3.0 s6.2.1 - OpenCL 3d image write types requires support
// for OpenCL C 2.0, or OpenCL C 3.0 or newer and the
// __opencl_c_3d_image_writes feature. OpenCL C v3.0 API s4.2 - For devices
// that support OpenCL 3.0, cl_khr_3d_image_writes must be returned when and
// only when the optional feature is supported
if ((Result->isImageType() || Result->isSamplerT()) &&
(S.getLangOpts().OpenCLVersion >= 300 &&
!OpenCLOptions.isSupported("__opencl_c_images", S.getLangOpts())))
OptName = "__opencl_c_images";
else if (Result->isOCLImage3dWOType() &&
!OpenCLOptions.isSupported("cl_khr_3d_image_writes",
S.getLangOpts()))
OptName = "cl_khr_3d_image_writes";
if (!OptName.empty()) {
(IsOpenCLC30 &&
!OpenCLOptions.isSupported("__opencl_c_images", S.getLangOpts()))) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
<< 0 << Result << OptName;
<< 0 << Result << "__opencl_c_images";
declarator.setInvalidType();
} else if (Result->isOCLImage3dWOType() &&
!OpenCLOptions.isSupported("cl_khr_3d_image_writes",
S.getLangOpts())) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
<< 0 << Result
<< (IsOpenCLC30
? "cl_khr_3d_image_writes and __opencl_c_3d_image_writes"
: "cl_khr_3d_image_writes");
declarator.setInvalidType();
}
}

View File

@ -129,6 +129,7 @@ INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
#endif
INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic())
INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version())
INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
@ -137,7 +138,6 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
#undef INSTR_PROF_RAW_HEADER
/* INSTR_PROF_RAW_HEADER end */
@ -646,7 +646,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
/* Raw profile format version (start from 1). */
#define INSTR_PROF_RAW_VERSION 6
#define INSTR_PROF_RAW_VERSION 7
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 7
/* Coverage mapping format version (start from 0). */

View File

@ -116,7 +116,7 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);
return sizeof(__llvm_profile_header) +
return sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
(DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters +
(CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters +
NamesSize + PaddingBytesAfterNames;

View File

@ -22,6 +22,7 @@ void (*VPMergeHook)(ValueProfData *, __llvm_profile_data *);
COMPILER_RT_VISIBILITY
uint64_t lprofGetLoadModuleSignature() {
/* A very fast way to compute a module signature. */
uint64_t Version = __llvm_profile_get_version();
uint64_t CounterSize = (uint64_t)(__llvm_profile_end_counters() -
__llvm_profile_begin_counters());
uint64_t DataSize = __llvm_profile_get_data_size(__llvm_profile_begin_data(),
@ -33,7 +34,7 @@ uint64_t lprofGetLoadModuleSignature() {
const __llvm_profile_data *FirstD = __llvm_profile_begin_data();
return (NamesSize << 40) + (CounterSize << 30) + (DataSize << 20) +
(NumVnodes << 10) + (DataSize > 0 ? FirstD->NameRef : 0);
(NumVnodes << 10) + (DataSize > 0 ? FirstD->NameRef : 0) + Version;
}
/* Returns 1 if profile is not structurally compatible. */
@ -44,7 +45,8 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
__llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
__llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
SrcDataStart =
(__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header));
(__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header) +
Header->BinaryIdsSize);
SrcDataEnd = SrcDataStart + Header->DataSize;
if (ProfileSize < sizeof(__llvm_profile_header))
@ -63,7 +65,7 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
Header->ValueKindLast != IPVK_Last)
return 1;
if (ProfileSize < sizeof(__llvm_profile_header) +
if (ProfileSize < sizeof(__llvm_profile_header) + Header->BinaryIdsSize +
Header->DataSize * sizeof(__llvm_profile_data) +
Header->NamesSize + Header->CountersSize)
return 1;
@ -91,7 +93,8 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
const char *SrcValueProfDataStart, *SrcValueProfData;
SrcDataStart =
(__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header));
(__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header) +
Header->BinaryIdsSize);
SrcDataEnd = SrcDataStart + Header->DataSize;
SrcCountersStart = (uint64_t *)SrcDataEnd;
SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize);

View File

@ -17,6 +17,15 @@
#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
#if defined(__FreeBSD__) && !defined(ElfW)
/*
* FreeBSD's elf.h and link.h headers do not define the ElfW(type) macro yet.
* If this is added to all supported FreeBSD versions in the future, this
* compatibility macro can be removed.
*/
#define ElfW(type) __ElfN(type)
#endif
#define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_COMMON)
#define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_COMMON)
#define PROF_NAME_START INSTR_PROF_SECT_START(INSTR_PROF_NAME_COMMON)
@ -76,6 +85,7 @@ COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_end_vnodes(void) {
COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START;
COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP;
#ifdef NT_GNU_BUILD_ID
static size_t RoundUp(size_t size, size_t align) {
return (size + align - 1) & ~(align - 1);
}
@ -179,5 +189,14 @@ COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
return 0;
}
#else /* !NT_GNU_BUILD_ID */
/*
* Fallback implementation for targets that don't support the GNU
* extensions NT_GNU_BUILD_ID and __ehdr_start.
*/
COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
return 0;
}
#endif
#endif

View File

@ -354,6 +354,16 @@
# define _LIBCPP_NO_CFI
#endif
// If the compiler supports using_if_exists, pretend we have those functions and they'll
// be picked up if the C library provides them.
//
// TODO: Once we drop support for Clang 12, we can assume the compiler supports using_if_exists
// for platforms that don't have a conforming C11 library, so we can drop this whole thing.
#if __has_attribute(using_if_exists)
# define _LIBCPP_HAS_TIMESPEC_GET
# define _LIBCPP_HAS_QUICK_EXIT
# define _LIBCPP_HAS_ALIGNED_ALLOC
#else
#if (defined(__ISO_C_VISIBLE) && (__ISO_C_VISIBLE >= 2011)) || __cplusplus >= 201103L
# if defined(__FreeBSD__)
# define _LIBCPP_HAS_ALIGNED_ALLOC
@ -408,6 +418,7 @@
# endif
# endif // __APPLE__
#endif
#endif // __has_attribute(using_if_exists)
#ifndef _LIBCPP_CXX03_LANG
# define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp)

View File

@ -59,7 +59,7 @@ int timespec_get( struct timespec *ts, int base); // C++17
// we're detecting this here instead of in <__config> because we can't include
// system headers from <__config>, since it leads to circular module dependencies.
// This is also meant to be a very temporary workaround until the SDKs are fixed.
#if defined(__APPLE__)
#if defined(__APPLE__) && !__has_attribute(using_if_exists)
# include <sys/cdefs.h>
# if defined(_LIBCPP_HAS_TIMESPEC_GET) && (__DARWIN_C_LEVEL < __DARWIN_C_FULL)
# define _LIBCPP_HAS_TIMESPEC_GET_NOT_ACTUALLY_PROVIDED

View File

@ -55,14 +55,14 @@ namespace std {
*/
// Make sure all feature tests macros are always available.
#include <version>
// Only enable the contents of the header when libc++ was build with LIBCXX_ENABLE_INCOMPLETE_FEATURES enabled
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
#include <__config>
#include <__format/format_error.h>
#include <__format/format_parse_context.h>
#include <version>
#if defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
# error "The Format library is not supported since libc++ has been configured with LIBCXX_ENABLE_INCOMPLETE_FEATURES disabled"
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@ -81,4 +81,6 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
#endif // _LIBCPP_FORMAT

View File

@ -607,8 +607,15 @@ public:
static_assert((is_same<_CharT, typename traits_type::char_type>::value),
"traits_type::char_type must be the same type as CharT");
#ifdef _LIBCPP_CXX03_LANG
// Preserve the ability to compare with literal 0,
// and implicitly convert to bool, but not implicitly convert to int.
_LIBCPP_INLINE_VISIBILITY
operator void*() const {return fail() ? nullptr : (void*)this;}
#else
_LIBCPP_INLINE_VISIBILITY
explicit operator bool() const {return !fail();}
#endif
_LIBCPP_INLINE_VISIBILITY bool operator!() const {return fail();}
_LIBCPP_INLINE_VISIBILITY iostate rdstate() const {return ios_base::rdstate();}

View File

@ -160,6 +160,11 @@ namespace std::ranges {
*/
// Make sure all feature tests macros are always available.
#include <version>
// Only enable the contents of the header when libc++ was build with LIBCXX_ENABLE_INCOMPLETE_FEATURES enabled
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
#include <__config>
#include <__ranges/access.h>
#include <__ranges/all.h>
@ -181,11 +186,6 @@ namespace std::ranges {
#include <initializer_list> // Required by the standard.
#include <iterator> // Required by the standard.
#include <type_traits>
#include <version>
#if defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
# error "The Ranges library is not supported since libc++ has been configured with LIBCXX_ENABLE_INCOMPLETE_FEATURES disabled"
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
@ -204,4 +204,6 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
#endif // _LIBCPP_RANGES

View File

@ -38,6 +38,10 @@ enum ELFKind {
ELF64BEKind
};
// For -Bno-symbolic, -Bsymbolic-non-weak-functions, -Bsymbolic-functions,
// -Bsymbolic.
enum class BsymbolicKind { None, NonWeakFunctions, Functions, All };
// For --build-id.
enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid };
@ -82,7 +86,8 @@ struct SymbolVersion {
struct VersionDefinition {
llvm::StringRef name;
uint16_t id;
std::vector<SymbolVersion> patterns;
std::vector<SymbolVersion> nonLocalPatterns;
std::vector<SymbolVersion> localPatterns;
};
// This struct contains the global configuration for the linker.
@ -144,8 +149,7 @@ struct Configuration {
bool armHasMovtMovw = false;
bool armJ1J2BranchEncoding = false;
bool asNeeded = false;
bool bsymbolic = false;
bool bsymbolicFunctions = false;
BsymbolicKind bsymbolic = BsymbolicKind::None;
bool callGraphProfileSort;
bool checkSections;
bool checkDynamicRelocs;

View File

@ -1006,12 +1006,15 @@ static void readConfigs(opt::InputArgList &args) {
OPT_no_allow_multiple_definition, false) ||
hasZOption(args, "muldefs");
config->auxiliaryList = args::getStrings(args, OPT_auxiliary);
if (opt::Arg *arg = args.getLastArg(OPT_Bno_symbolic, OPT_Bsymbolic_functions,
OPT_Bsymbolic)) {
if (arg->getOption().matches(OPT_Bsymbolic_functions))
config->bsymbolicFunctions = true;
if (opt::Arg *arg =
args.getLastArg(OPT_Bno_symbolic, OPT_Bsymbolic_non_weak_functions,
OPT_Bsymbolic_functions, OPT_Bsymbolic)) {
if (arg->getOption().matches(OPT_Bsymbolic_non_weak_functions))
config->bsymbolic = BsymbolicKind::NonWeakFunctions;
else if (arg->getOption().matches(OPT_Bsymbolic_functions))
config->bsymbolic = BsymbolicKind::Functions;
else if (arg->getOption().matches(OPT_Bsymbolic))
config->bsymbolic = true;
config->bsymbolic = BsymbolicKind::All;
}
config->checkSections =
args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
@ -1348,18 +1351,19 @@ static void readConfigs(opt::InputArgList &args) {
}
assert(config->versionDefinitions.empty());
config->versionDefinitions.push_back({"local", (uint16_t)VER_NDX_LOCAL, {}});
config->versionDefinitions.push_back(
{"global", (uint16_t)VER_NDX_GLOBAL, {}});
{"local", (uint16_t)VER_NDX_LOCAL, {}, {}});
config->versionDefinitions.push_back(
{"global", (uint16_t)VER_NDX_GLOBAL, {}, {}});
// If --retain-symbol-file is used, we'll keep only the symbols listed in
// the file and discard all others.
if (auto *arg = args.getLastArg(OPT_retain_symbols_file)) {
config->versionDefinitions[VER_NDX_LOCAL].patterns.push_back(
config->versionDefinitions[VER_NDX_LOCAL].nonLocalPatterns.push_back(
{"*", /*isExternCpp=*/false, /*hasWildcard=*/true});
if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
for (StringRef s : args::getLines(*buffer))
config->versionDefinitions[VER_NDX_GLOBAL].patterns.push_back(
config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(
{s, /*isExternCpp=*/false, /*hasWildcard=*/false});
}
@ -1374,7 +1378,8 @@ static void readConfigs(opt::InputArgList &args) {
// When producing an executable, --dynamic-list specifies non-local defined
// symbols which are required to be exported. When producing a shared object,
// symbols not specified by --dynamic-list are non-preemptible.
config->symbolic = config->bsymbolic || args.hasArg(OPT_dynamic_list);
config->symbolic =
config->bsymbolic == BsymbolicKind::All || args.hasArg(OPT_dynamic_list);
for (auto *arg : args.filtered(OPT_dynamic_list))
if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
readDynamicList(*buffer);
@ -2065,23 +2070,37 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
if (suffix1[0] != '@' || suffix1[1] == '@')
continue;
// Check whether the default version foo@@v1 exists. If it exists, the
// symbol can be found by the name "foo" in the symbol table.
Symbol *maybeDefault = symtab->find(name);
if (!maybeDefault)
// Check the existing symbol foo. We have two special cases to handle:
//
// * There is a definition of foo@v1 and foo@@v1.
// * There is a definition of foo@v1 and foo.
Defined *sym2 = dyn_cast_or_null<Defined>(symtab->find(name));
if (!sym2)
continue;
const char *suffix2 = maybeDefault->getVersionSuffix();
if (suffix2[0] != '@' || suffix2[1] != '@' ||
strcmp(suffix1 + 1, suffix2 + 2) != 0)
continue;
// foo@v1 and foo@@v1 should be merged, so redirect foo@v1 to foo@@v1.
map.try_emplace(sym, maybeDefault);
// If both foo@v1 and foo@@v1 are defined and non-weak, report a duplicate
// definition error.
maybeDefault->resolve(*sym);
// Eliminate foo@v1 from the symbol table.
sym->symbolKind = Symbol::PlaceholderKind;
const char *suffix2 = sym2->getVersionSuffix();
if (suffix2[0] == '@' && suffix2[1] == '@' &&
strcmp(suffix1 + 1, suffix2 + 2) == 0) {
// foo@v1 and foo@@v1 should be merged, so redirect foo@v1 to foo@@v1.
map.try_emplace(sym, sym2);
// If both foo@v1 and foo@@v1 are defined and non-weak, report a duplicate
// definition error.
sym2->resolve(*sym);
// Eliminate foo@v1 from the symbol table.
sym->symbolKind = Symbol::PlaceholderKind;
} else if (auto *sym1 = dyn_cast<Defined>(sym)) {
if (sym2->versionId > VER_NDX_GLOBAL
? config->versionDefinitions[sym2->versionId].name == suffix1 + 1
: sym1->section == sym2->section && sym1->value == sym2->value) {
// Due to an assembler design flaw, if foo is defined, .symver foo,
// foo@v1 defines both foo and foo@v1. Unless foo is bound to a
// different version, GNU ld makes foo@v1 canonical and elimiates foo.
// Emulate its behavior, otherwise we would have foo or foo@@v1 beside
// foo@v1. foo@v1 and foo combining does not apply if they are not
// defined in the same place.
map.try_emplace(sym2, sym);
sym2->symbolKind = Symbol::PlaceholderKind;
}
}
}
if (map.empty())

View File

@ -849,17 +849,8 @@ void LinkerScript::diagnoseOrphanHandling() const {
}
uint64_t LinkerScript::advance(uint64_t size, unsigned alignment) {
bool isTbss =
(ctx->outSec->flags & SHF_TLS) && ctx->outSec->type == SHT_NOBITS;
uint64_t start = isTbss ? dot + ctx->threadBssOffset : dot;
start = alignTo(start, alignment);
uint64_t end = start + size;
if (isTbss)
ctx->threadBssOffset = end - dot;
else
dot = end;
return end;
dot = alignTo(dot, alignment) + size;
return dot;
}
void LinkerScript::output(InputSection *s) {
@ -931,13 +922,24 @@ static OutputSection *findFirstSection(PhdrEntry *load) {
// This function assigns offsets to input sections and an output section
// for a single sections command (e.g. ".text { *(.text); }").
void LinkerScript::assignOffsets(OutputSection *sec) {
const bool isTbss = (sec->flags & SHF_TLS) && sec->type == SHT_NOBITS;
const bool sameMemRegion = ctx->memRegion == sec->memRegion;
const bool prevLMARegionIsDefault = ctx->lmaRegion == nullptr;
const uint64_t savedDot = dot;
ctx->memRegion = sec->memRegion;
ctx->lmaRegion = sec->lmaRegion;
if (sec->flags & SHF_ALLOC) {
if (!(sec->flags & SHF_ALLOC)) {
// Non-SHF_ALLOC sections have zero addresses.
dot = 0;
} else if (isTbss) {
// Allow consecutive SHF_TLS SHT_NOBITS output sections. The address range
// starts from the end address of the previous tbss section.
if (ctx->tbssAddr == 0)
ctx->tbssAddr = dot;
else
dot = ctx->tbssAddr;
} else {
if (ctx->memRegion)
dot = ctx->memRegion->curPos;
if (sec->addrExpr)
@ -950,9 +952,6 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
if (ctx->memRegion && ctx->memRegion->curPos < dot)
expandMemoryRegion(ctx->memRegion, dot - ctx->memRegion->curPos,
ctx->memRegion->name, sec->name);
} else {
// Non-SHF_ALLOC sections have zero addresses.
dot = 0;
}
switchTo(sec);
@ -1008,8 +1007,13 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
// Non-SHF_ALLOC sections do not affect the addresses of other OutputSections
// as they are not part of the process image.
if (!(sec->flags & SHF_ALLOC))
if (!(sec->flags & SHF_ALLOC)) {
dot = savedDot;
} else if (isTbss) {
// NOBITS TLS sections are similar. Additionally save the end address.
ctx->tbssAddr = dot;
dot = savedDot;
}
}
static bool isDiscardable(OutputSection &sec) {

View File

@ -247,11 +247,11 @@ class LinkerScript final {
// not be used outside of the scope of a call to the above functions.
struct AddressState {
AddressState();
uint64_t threadBssOffset = 0;
OutputSection *outSec = nullptr;
MemoryRegion *memRegion = nullptr;
MemoryRegion *lmaRegion = nullptr;
uint64_t lmaOffset = 0;
uint64_t tbssAddr = 0;
};
llvm::DenseMap<StringRef, OutputSection *> nameToOutputSection;

View File

@ -43,6 +43,9 @@ def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind default visibility defined symbols
def Bsymbolic_functions: F<"Bsymbolic-functions">,
HelpText<"Bind default visibility defined function symbols locally for -shared">;
def Bsymbolic_non_weak_functions: F<"Bsymbolic-non-weak-functions">,
HelpText<"Bind default visibility defined STB_GLOBAL function symbols locally for -shared">;
def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries (default)">;
def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;

View File

@ -527,6 +527,13 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &ss) {
if (auto *alias = dyn_cast_or_null<SharedSymbol>(sym))
ret.insert(alias);
}
// The loop does not check SHT_GNU_verneed, so ret does not contain
// non-default version symbols. If ss has a non-default version, ret won't
// contain ss. Just add ss unconditionally. If a non-default version alias is
// separately copy relocated, it and ss will have different addresses.
// Fortunately this case is impractical and fails with GNU ld as well.
ret.insert(&ss);
return ret;
}

View File

@ -1496,9 +1496,9 @@ void ScriptParser::readAnonymousDeclaration() {
std::vector<SymbolVersion> globals;
std::tie(locals, globals) = readSymbols();
for (const SymbolVersion &pat : locals)
config->versionDefinitions[VER_NDX_LOCAL].patterns.push_back(pat);
config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat);
for (const SymbolVersion &pat : globals)
config->versionDefinitions[VER_NDX_GLOBAL].patterns.push_back(pat);
config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat);
expect(";");
}
@ -1510,13 +1510,12 @@ void ScriptParser::readVersionDeclaration(StringRef verStr) {
std::vector<SymbolVersion> locals;
std::vector<SymbolVersion> globals;
std::tie(locals, globals) = readSymbols();
for (const SymbolVersion &pat : locals)
config->versionDefinitions[VER_NDX_LOCAL].patterns.push_back(pat);
// Create a new version definition and add that to the global symbols.
VersionDefinition ver;
ver.name = verStr;
ver.patterns = globals;
ver.nonLocalPatterns = std::move(globals);
ver.localPatterns = std::move(locals);
ver.id = config->versionDefinitions.size();
config->versionDefinitions.push_back(ver);

View File

@ -134,9 +134,20 @@ static bool canBeVersioned(const Symbol &sym) {
StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
if (!demangledSyms) {
demangledSyms.emplace();
std::string demangled;
for (Symbol *sym : symVector)
if (canBeVersioned(*sym))
(*demangledSyms)[demangleItanium(sym->getName())].push_back(sym);
if (canBeVersioned(*sym)) {
StringRef name = sym->getName();
size_t pos = name.find('@');
if (pos == std::string::npos)
demangled = demangleItanium(name);
else if (pos + 1 == name.size() || name[pos + 1] == '@')
demangled = demangleItanium(name.substr(0, pos));
else
demangled =
(demangleItanium(name.substr(0, pos)) + name.substr(pos)).str();
(*demangledSyms)[demangled].push_back(sym);
}
}
return *demangledSyms;
}
@ -150,19 +161,29 @@ std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
return {};
}
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) {
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver,
bool includeNonDefault) {
std::vector<Symbol *> res;
SingleStringMatcher m(ver.name);
auto check = [&](StringRef name) {
size_t pos = name.find('@');
if (!includeNonDefault)
return pos == StringRef::npos;
return !(pos + 1 < name.size() && name[pos + 1] == '@');
};
if (ver.isExternCpp) {
for (auto &p : getDemangledSyms())
if (m.match(p.first()))
res.insert(res.end(), p.second.begin(), p.second.end());
for (Symbol *sym : p.second)
if (check(sym->getName()))
res.push_back(sym);
return res;
}
for (Symbol *sym : symVector)
if (canBeVersioned(*sym) && m.match(sym->getName()))
if (canBeVersioned(*sym) && check(sym->getName()) &&
m.match(sym->getName()))
res.push_back(sym);
return res;
}
@ -172,7 +193,7 @@ void SymbolTable::handleDynamicList() {
for (SymbolVersion &ver : config->dynamicList) {
std::vector<Symbol *> syms;
if (ver.hasWildcard)
syms = findAllByVersion(ver);
syms = findAllByVersion(ver, /*includeNonDefault=*/true);
else
syms = findByVersion(ver);
@ -181,21 +202,13 @@ void SymbolTable::handleDynamicList() {
}
}
// Set symbol versions to symbols. This function handles patterns
// containing no wildcard characters.
void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
StringRef versionName) {
if (ver.hasWildcard)
return;
// Set symbol versions to symbols. This function handles patterns containing no
// wildcard characters. Return false if no symbol definition matches ver.
bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
StringRef versionName,
bool includeNonDefault) {
// Get a list of symbols which we need to assign the version to.
std::vector<Symbol *> syms = findByVersion(ver);
if (syms.empty()) {
if (!config->undefinedVersion)
error("version script assignment of '" + versionName + "' to symbol '" +
ver.name + "' failed: symbol not defined");
return;
}
auto getName = [](uint16_t ver) -> std::string {
if (ver == VER_NDX_LOCAL)
@ -207,10 +220,11 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
// Assign the version.
for (Symbol *sym : syms) {
// Skip symbols containing version info because symbol versions
// specified by symbol names take precedence over version scripts.
// See parseSymbolVersion().
if (sym->getName().contains('@'))
// For a non-local versionId, skip symbols containing version info because
// symbol versions specified by symbol names take precedence over version
// scripts. See parseSymbolVersion().
if (!includeNonDefault && versionId != VER_NDX_LOCAL &&
sym->getName().contains('@'))
continue;
// If the version has not been assigned, verdefIndex is -1. Use an arbitrary
@ -225,13 +239,15 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
warn("attempt to reassign symbol '" + ver.name + "' of " +
getName(sym->versionId) + " to " + getName(versionId));
}
return !syms.empty();
}
void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId,
bool includeNonDefault) {
// Exact matching takes precedence over fuzzy matching,
// so we set a version to a symbol only if no version has been assigned
// to the symbol. This behavior is compatible with GNU.
for (Symbol *sym : findAllByVersion(ver))
for (Symbol *sym : findAllByVersion(ver, includeNonDefault))
if (sym->verdefIndex == UINT32_C(-1)) {
sym->verdefIndex = 0;
sym->versionId = versionId;
@ -244,26 +260,60 @@ void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
// script file, the script does not actually define any symbol version,
// but just specifies symbols visibilities.
void SymbolTable::scanVersionScript() {
SmallString<128> buf;
// First, we assign versions to exact matching symbols,
// i.e. version definitions not containing any glob meta-characters.
for (VersionDefinition &v : config->versionDefinitions)
for (SymbolVersion &pat : v.patterns)
assignExactVersion(pat, v.id, v.name);
std::vector<Symbol *> syms;
for (VersionDefinition &v : config->versionDefinitions) {
auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
bool found =
assignExactVersion(pat, id, ver, /*includeNonDefault=*/false);
buf.clear();
found |= assignExactVersion({(pat.name + "@" + v.name).toStringRef(buf),
pat.isExternCpp, /*hasWildCard=*/false},
id, ver, /*includeNonDefault=*/true);
if (!found && !config->undefinedVersion)
errorOrWarn("version script assignment of '" + ver + "' to symbol '" +
pat.name + "' failed: symbol not defined");
};
for (SymbolVersion &pat : v.nonLocalPatterns)
if (!pat.hasWildcard)
assignExact(pat, v.id, v.name);
for (SymbolVersion pat : v.localPatterns)
if (!pat.hasWildcard)
assignExact(pat, VER_NDX_LOCAL, "local");
}
// Next, assign versions to wildcards that are not "*". Note that because the
// last match takes precedence over previous matches, we iterate over the
// definitions in the reverse order.
for (VersionDefinition &v : llvm::reverse(config->versionDefinitions))
for (SymbolVersion &pat : v.patterns)
auto assignWildcard = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
assignWildcardVersion(pat, id, /*includeNonDefault=*/false);
buf.clear();
assignWildcardVersion({(pat.name + "@" + ver).toStringRef(buf),
pat.isExternCpp, /*hasWildCard=*/true},
id,
/*includeNonDefault=*/true);
};
for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
for (SymbolVersion &pat : v.nonLocalPatterns)
if (pat.hasWildcard && pat.name != "*")
assignWildcardVersion(pat, v.id);
assignWildcard(pat, v.id, v.name);
for (SymbolVersion &pat : v.localPatterns)
if (pat.hasWildcard && pat.name != "*")
assignWildcard(pat, VER_NDX_LOCAL, v.name);
}
// Then, assign versions to "*". In GNU linkers they have lower priority than
// other wildcards.
for (VersionDefinition &v : config->versionDefinitions)
for (SymbolVersion &pat : v.patterns)
for (VersionDefinition &v : config->versionDefinitions) {
for (SymbolVersion &pat : v.nonLocalPatterns)
if (pat.hasWildcard && pat.name == "*")
assignWildcardVersion(pat, v.id);
assignWildcard(pat, v.id, v.name);
for (SymbolVersion &pat : v.localPatterns)
if (pat.hasWildcard && pat.name == "*")
assignWildcard(pat, VER_NDX_LOCAL, v.name);
}
// Symbol themselves might know their versions because symbols
// can contain versions in the form of <name>@<version>.

View File

@ -65,12 +65,14 @@ class SymbolTable {
private:
std::vector<Symbol *> findByVersion(SymbolVersion ver);
std::vector<Symbol *> findAllByVersion(SymbolVersion ver);
std::vector<Symbol *> findAllByVersion(SymbolVersion ver,
bool includeNonDefault);
llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms();
void assignExactVersion(SymbolVersion ver, uint16_t versionId,
StringRef versionName);
void assignWildcardVersion(SymbolVersion ver, uint16_t versionId);
bool assignExactVersion(SymbolVersion ver, uint16_t versionId,
StringRef versionName, bool includeNonDefault);
void assignWildcardVersion(SymbolVersion ver, uint16_t versionId,
bool includeNonDefault);
// The order the global symbols are in is not defined. We can use an arbitrary
// order, but it has to be reproducible. That is true even when cross linking.

View File

@ -208,6 +208,9 @@ OutputSection *Symbol::getOutputSection() const {
// If a symbol name contains '@', the characters after that is
// a symbol version name. This function parses that.
void Symbol::parseSymbolVersion() {
// Return if localized by a local: pattern in a version script.
if (versionId == VER_NDX_LOCAL)
return;
StringRef s = getName();
size_t pos = s.find('@');
if (pos == 0 || pos == StringRef::npos)
@ -368,8 +371,12 @@ bool elf::computeIsPreemptible(const Symbol &sym) {
// If -Bsymbolic or --dynamic-list is specified, or -Bsymbolic-functions is
// specified and the symbol is STT_FUNC, the symbol is preemptible iff it is
// in the dynamic list.
if (config->symbolic || (config->bsymbolicFunctions && sym.isFunc()))
// in the dynamic list. -Bsymbolic-non-weak-functions is a non-weak subset of
// -Bsymbolic-functions.
if (config->symbolic ||
(config->bsymbolic == BsymbolicKind::Functions && sym.isFunc()) ||
(config->bsymbolic == BsymbolicKind::NonWeakFunctions && sym.isFunc() &&
sym.binding != STB_WEAK))
return sym.inDynamicList;
return true;
}

View File

@ -1356,7 +1356,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
// Set DT_FLAGS and DT_FLAGS_1.
uint32_t dtFlags = 0;
uint32_t dtFlags1 = 0;
if (config->bsymbolic)
if (config->bsymbolic == BsymbolicKind::All)
dtFlags |= DF_SYMBOLIC;
if (config->zGlobal)
dtFlags1 |= DF_1_GLOBAL;

View File

@ -24,12 +24,90 @@ Non-comprehensive list of changes in this release
ELF Improvements
----------------
* ``-z start-stop-gc`` is now supported and becomes the default.
(`D96914 <https://reviews.llvm.org/D96914>`_)
(`rG6d2d3bd0 <https://reviews.llvm.org/rG6d2d3bd0a61f5fc7fd9f61f48bc30e9ca77cc619>`_)
* ``--shuffle-sections=<seed>`` has been changed to ``--shuffle-sections=<section-glob>=<seed>``.
If seed is -1, the matched input sections are reversed.
(`D98445 <https://reviews.llvm.org/D98445>`_)
(`D98679 <https://reviews.llvm.org/D98679>`_)
* ``-Bsymbolic -Bsymbolic-functions`` has been changed to behave the same as ``-Bsymbolic-functions``. This matches GNU ld.
(`D102461 <https://reviews.llvm.org/D102461>`_)
* ``-Bno-symbolic`` has been added.
(`D102461 <https://reviews.llvm.org/D102461>`_)
* A new linker script command ``OVERWRITE_SECTIONS`` has been added.
(`D103303 <https://reviews.llvm.org/D103303>`_)
* ``-Bsymbolic-non-weak-functions`` has been added as a ``STB_GLOBAL`` subset of ``-Bsymbolic-functions``.
(`D102570 <https://reviews.llvm.org/D102570>`_)
* ``--no-allow-shlib-undefined`` has been improved to catch more cases.
(`D101996 <https://reviews.llvm.org/D101996>`_)
* ``__rela_iplt_start`` is no longer defined for -pie/-shared.
This makes GCC/Clang ``-static-pie`` built executables work.
(`rG8cb78e99 <https://reviews.llvm.org/rf8cb78e99aae9aa3f89f7bfe667db2c5b767f21f>`_)
* IRELATIVE/TLSDESC relocations now support ``-z rel``.
(`D100544 <https://reviews.llvm.org/D100544>`_)
* Section groups with a zero flag are now supported.
This is used by ``comdat nodeduplicate`` in LLVM IR.
(`D96636 <https://reviews.llvm.org/D96636>`_)
(`D106228 <https://reviews.llvm.org/D106228>`_)
* Defined symbols are now resolved before undefined symbols to stabilize the bheavior of archive member extraction.
(`D95985 <https://reviews.llvm.org/D95985>`_)
* ``STB_WEAK`` symbols are now preferred over COMMON symbols as a fix to a ``--fortran-common`` regression.
(`D105945 <https://reviews.llvm.org/D105945>`_)
* Absolute relocations referencing undef weak now produce dynamic relocations for -pie, matching GOT-generating relocations.
(`D105164 <https://reviews.llvm.org/D105164>`_)
* Exported symbols are now communicated to the LTO library so as to make LTO
based whole program devirtualization (``-flto=thin -fwhole-program-vtables``)
work with shared objects.
(`D91583 <https://reviews.llvm.org/D91583>`_)
* Whole program devirtualization now respects ``local:`` version nodes in a version script.
(`D98220 <https://reviews.llvm.org/D98220>`_)
(`D98686 <https://reviews.llvm.org/D98686>`_)
* ``local:`` version nodes in a version script now apply to non-default version symbols.
(`D107234 <https://reviews.llvm.org/D107234>`_)
* If an object file defines both ``foo`` and ``foo@v1``, now only ``foo@v1`` will be in the output.
(`D107235 <https://reviews.llvm.org/D107235>`_)
* Copy relocations on non-default version symbols are now supported.
(`D107535 <https://reviews.llvm.org/D107535>`_)
Linker script changes:
* ``.``, ``$``, and double quotes can now be used in symbol names in expressions.
(`D98306 <https://reviews.llvm.org/D98306>`_)
(`rGe7a7ad13 <https://reviews.llvm.org/rGe7a7ad134fe182aad190cb3ebc441164470e92f5>`_)
* Fixed value of ``.`` in the output section description of ``.tbss``.
(`D107288 <https://reviews.llvm.org/D107288>`_)
* ``NOLOAD`` sections can now be placed in a ``PT_LOAD`` program header.
(`D103815 <https://reviews.llvm.org/D103815>`_)
* ``OUTPUT_FORMAT(default, big, little)`` now consults ``-EL`` and ``-EB``.
(`D96214 <https://reviews.llvm.org/D96214>`_)
* The ``OVERWRITE_SECTIONS`` command has been added.
(`D103303 <https://reviews.llvm.org/D103303>`_)
* The section order within an ``INSERT AFTER`` command is now preserved.
(`D105158 <https://reviews.llvm.org/D105158>`_)
Architecture specific changes:
* aarch64_be is now supported.
(`D96188 <https://reviews.llvm.org/D96188>`_)
* The AMDGPU port now supports ``--amdhsa-code-object-version=4`` object files;
(`D95811 <https://reviews.llvm.org/D95811>`_)
* The ARM port now accounts for PC biases in range extension thunk creation.
(`D97550 <https://reviews.llvm.org/D97550>`_)
* The AVR port now computes ``e_flags``.
(`D99754 <https://reviews.llvm.org/D99754>`_)
* The Mips port now omits unneeded dynamic relocations for PIE non-preemptible TLS.
(`D101382 <https://reviews.llvm.org/D101382>`_)
* The PowerPC port now supports ``--power10-stubs=no`` to omit Power10 instructions from call stubs.
(`D94625 <https://reviews.llvm.org/D94625>`_)
* Fixed a thunk creation bug in the PowerPC port when TOC/NOTOC calls are mixed.
(`D101837 <https://reviews.llvm.org/D101837>`_)
* The RISC-V port now resolves undefined weak relocations to the current location if not using PLT.
(`D103001 <https://reviews.llvm.org/D103001>`_)
* ``R_386_GOTOFF`` relocations from .debug_info are now allowed to be compatible with GCC.
(`D95994 <https://reviews.llvm.org/D95994>`_)
* ``gotEntrySize`` has been added to improve support for the ILP32 ABI of x86-64.
(`D102569 <https://reviews.llvm.org/D102569>`_)
Breaking changes
----------------
@ -40,17 +118,75 @@ Breaking changes
COFF Improvements
-----------------
* ...
* Avoid thread exhaustion when running on 32 bit Windows.
(`D105506 <https://reviews.llvm.org/D105506>`_)
* Improve terminating the process on Windows while a thread pool might be
running. (`D102944 <https://reviews.llvm.org/D102944>`_)
MinGW Improvements
------------------
* ...
* Support for linking directly against a DLL without using an import library
has been added. (`D104530 <https://reviews.llvm.org/D104530>`_ and
`D104531 <https://reviews.llvm.org/D104531>`_)
MachO Improvements
------------------
* Fix linking with ``--export-all-symbols`` in combination with
``-function-sections``. (`D101522 <https://reviews.llvm.org/D101522>`_ and
`D101615 <https://reviews.llvm.org/D101615>`_)
* Item 1.
* Fix automatic export of symbols from LTO objects.
(`D101569 <https://reviews.llvm.org/D101569>`_)
* Accept more spellings of some options.
(`D107237 <https://reviews.llvm.org/D107237>`_ and
`D107253 <https://reviews.llvm.org/D107253>`_)
Mach-O Improvements
-------------------
The Mach-O backend is now able to link several large, real-world programs,
though we are still working out the kinks.
* arm64 is now supported as a target. (`D88629 <https://reviews.llvm.org/D88629>`_)
* arm64_32 is now supported as a target. (`D99822 <https://reviews.llvm.org/D99822>`_)
* Branch-range-extension thunks are now supported. (`D100818 <https://reviews.llvm.org/D100818>`_)
* ``-dead_strip`` is now supported. (`D103324 <https://reviews.llvm.org/D103324>`_)
* Support for identical code folding (``--icf=all``) has been added.
(`D103292 <https://reviews.llvm.org/D103292>`_)
* Support for special ``$start`` and ``$end`` symbols for segment & sections has been
added. (`D106767 <https://reviews.llvm.org/D106767>`_, `D106629 <https://reviews.llvm.org/D106629>`_)
* ``$ld$previous`` symbols are now supported. (`D103505 <https://reviews.llvm.org/D103505 >`_)
* ``$ld$install_name`` symbols are now supported. (`D103746 <https://reviews.llvm.org/D103746>`_)
* ``__mh_*_header`` symbols are now supported. (`D97007 <https://reviews.llvm.org/D97007>`_)
* LC_CODE_SIGNATURE is now supported. (`D96164 <https://reviews.llvm.org/D96164>`_)
* LC_FUNCTION_STARTS is now supported. (`D97260 <https://reviews.llvm.org/D97260>`_)
* LC_DATA_IN_CODE is now supported. (`D103006 <https://reviews.llvm.org/D103006>`_)
* Bind opcodes are more compactly encoded. (`D106128 <https://reviews.llvm.org/D106128>`_,
`D105075 <https://reviews.llvm.org/D105075>`_)
* LTO cache support has been added. (`D105922 <https://reviews.llvm.org/D105922>`_)
* ``-application_extension`` is now supported. (`D105818 <https://reviews.llvm.org/D105818>`_)
* ``-export_dynamic`` is now partially supported. (`D105482 <https://reviews.llvm.org/D105482>`_)
* ``-arch_multiple`` is now supported. (`D105450 <https://reviews.llvm.org/D105450>`_)
* ``-final_output`` is now supported. (`D105449 <https://reviews.llvm.org/D105449>`_)
* ``-umbrella`` is now supported. (`D105448 <https://reviews.llvm.org/D105448>`_)
* ``--print-dylib-search`` is now supported. (`D103985 <https://reviews.llvm.org/D103985>`_)
* ``-force_load_swift_libs`` is now supported. (`D103709 <https://reviews.llvm.org/D103709>`_)
* ``-reexport_framework``, ``-reexport_library``, ``-reexport-l`` are now supported.
(`D103497 <https://reviews.llvm.org/D103497>`_)
* ``.weak_def_can_be_hidden`` is now supported. (`D101080 <https://reviews.llvm.org/D101080>`_)
* ``-add_ast_path`` is now supported. (`D100076 <https://reviews.llvm.org/D100076>`_)
* ``-segprot`` is now supported. (`D99389 <https://reviews.llvm.org/D99389>`_)
* ``-dependency_info`` is now partially supported. (`D98559 <https://reviews.llvm.org/D98559>`_)
* ``--time-trace`` is now supported. (`D98419 <https://reviews.llvm.org/D98419>`_)
* ``-mark_dead_strippable_dylib`` is now supported. (`D98262 <https://reviews.llvm.org/D98262>`_)
* ``-[un]exported_symbol[s_list]`` is now supported. (`D98223 <https://reviews.llvm.org/D98223>`_)
* ``-flat_namespace`` is now supported. (`D97641 <https://reviews.llvm.org/D97641>`_)
* ``-rename_section`` and ``-rename_segment`` are now supported. (`D97600 <https://reviews.llvm.org/D97600>`_)
* ``-bundle_loader`` is now supported. (`D95913 <https://reviews.llvm.org/D95913>`_)
* ``-map`` is now partially supported. (`D98323 <https://reviews.llvm.org/D98323>`_)
There were numerous other bug-fixes as well.
WebAssembly Improvements
------------------------

View File

@ -85,6 +85,9 @@ flag.
.It Fl Bsymbolic-functions
Bind default visibility defined function symbols locally for
.Fl shared.
.It Fl Bsymbolic-non-weak-functions
Bind default visibility defined STB_GLOBAL function symbols locally for
.Fl shared.
.It Fl -build-id Ns = Ns Ar value
Generate a build ID note.
.Ar value

View File

@ -7,8 +7,11 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectMemoryTag.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Target/Process.h"
using namespace lldb;
@ -21,7 +24,8 @@ class CommandObjectMemoryTagRead : public CommandObjectParsed {
public:
CommandObjectMemoryTagRead(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "tag",
"Read memory tags for the given range of memory.",
"Read memory tags for the given range of memory."
" Mismatched tags will be marked.",
nullptr,
eCommandRequiresTarget | eCommandRequiresProcess |
eCommandProcessMustBePaused) {
@ -97,16 +101,17 @@ class CommandObjectMemoryTagRead : public CommandObjectParsed {
return false;
}
result.AppendMessageWithFormatv("Logical tag: {0:x}",
tag_manager->GetLogicalTag(start_addr));
lldb::addr_t logical_tag = tag_manager->GetLogicalTag(start_addr);
result.AppendMessageWithFormatv("Logical tag: {0:x}", logical_tag);
result.AppendMessage("Allocation tags:");
addr_t addr = tagged_range->GetRangeBase();
for (auto tag : *tags) {
addr_t next_addr = addr + tag_manager->GetGranuleSize();
// Showing tagged adresses here until we have non address bit handling
result.AppendMessageWithFormatv("[{0:x}, {1:x}): {2:x}", addr, next_addr,
tag);
result.AppendMessageWithFormatv("[{0:x}, {1:x}): {2:x}{3}", addr,
next_addr, tag,
logical_tag == tag ? "" : " (mismatch)");
addr = next_addr;
}
@ -115,6 +120,168 @@ class CommandObjectMemoryTagRead : public CommandObjectParsed {
}
};
#define LLDB_OPTIONS_memory_tag_write
#include "CommandOptions.inc"
class CommandObjectMemoryTagWrite : public CommandObjectParsed {
public:
class OptionGroupTagWrite : public OptionGroup {
public:
OptionGroupTagWrite() : OptionGroup(), m_end_addr(LLDB_INVALID_ADDRESS) {}
~OptionGroupTagWrite() override = default;
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::makeArrayRef(g_memory_tag_write_options);
}
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
ExecutionContext *execution_context) override {
Status status;
const int short_option =
g_memory_tag_write_options[option_idx].short_option;
switch (short_option) {
case 'e':
m_end_addr = OptionArgParser::ToAddress(execution_context, option_value,
LLDB_INVALID_ADDRESS, &status);
break;
default:
llvm_unreachable("Unimplemented option");
}
return status;
}
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_end_addr = LLDB_INVALID_ADDRESS;
}
lldb::addr_t m_end_addr;
};
CommandObjectMemoryTagWrite(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "tag",
"Write memory tags starting from the granule that "
"contains the given address.",
nullptr,
eCommandRequiresTarget | eCommandRequiresProcess |
eCommandProcessMustBePaused),
m_option_group(), m_tag_write_options() {
// Address
m_arguments.push_back(
CommandArgumentEntry{CommandArgumentData(eArgTypeAddressOrExpression)});
// One or more tag values
m_arguments.push_back(CommandArgumentEntry{
CommandArgumentData(eArgTypeValue, eArgRepeatPlus)});
m_option_group.Append(&m_tag_write_options);
m_option_group.Finalize();
}
~CommandObjectMemoryTagWrite() override = default;
Options *GetOptions() override { return &m_option_group; }
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if (command.GetArgumentCount() < 2) {
result.AppendError("wrong number of arguments; expected "
"<address-expression> <tag> [<tag> [...]]");
return false;
}
Status error;
addr_t start_addr = OptionArgParser::ToAddress(
&m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
if (start_addr == LLDB_INVALID_ADDRESS) {
result.AppendErrorWithFormatv("Invalid address expression, {0}",
error.AsCString());
return false;
}
command.Shift(); // shift off start address
std::vector<lldb::addr_t> tags;
for (auto &entry : command) {
lldb::addr_t tag_value;
// getAsInteger returns true on failure
if (entry.ref().getAsInteger(0, tag_value)) {
result.AppendErrorWithFormat(
"'%s' is not a valid unsigned decimal string value.\n",
entry.c_str());
return false;
}
tags.push_back(tag_value);
}
Process *process = m_exe_ctx.GetProcessPtr();
llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
process->GetMemoryTagManager();
if (!tag_manager_or_err) {
result.SetError(Status(tag_manager_or_err.takeError()));
return false;
}
const MemoryTagManager *tag_manager = *tag_manager_or_err;
MemoryRegionInfos memory_regions;
// If this fails the list of regions is cleared, so we don't need to read
// the return status here.
process->GetMemoryRegions(memory_regions);
// We have to assume start_addr is not granule aligned.
// So if we simply made a range:
// (start_addr, start_addr + (N * granule_size))
// We would end up with a range that isn't N granules but N+1
// granules. To avoid this we'll align the start first using the method that
// doesn't check memory attributes. (if the final range is untagged we'll
// handle that error later)
lldb::addr_t aligned_start_addr =
tag_manager->ExpandToGranule(MemoryTagManager::TagRange(start_addr, 1))
.GetRangeBase();
lldb::addr_t end_addr = 0;
// When you have an end address you want to align the range like tag read
// does. Meaning, align the start down (which we've done) and align the end
// up.
if (m_tag_write_options.m_end_addr != LLDB_INVALID_ADDRESS)
end_addr = m_tag_write_options.m_end_addr;
else
// Without an end address assume number of tags matches number of granules
// to write to
end_addr =
aligned_start_addr + (tags.size() * tag_manager->GetGranuleSize());
// Now we've aligned the start address so if we ask for another range
// using the number of tags N, we'll get back a range that is also N
// granules in size.
llvm::Expected<MemoryTagManager::TagRange> tagged_range =
tag_manager->MakeTaggedRange(aligned_start_addr, end_addr,
memory_regions);
if (!tagged_range) {
result.SetError(Status(tagged_range.takeError()));
return false;
}
Status status = process->WriteMemoryTags(tagged_range->GetRangeBase(),
tagged_range->GetByteSize(), tags);
if (status.Fail()) {
result.SetError(status);
return false;
}
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
OptionGroupOptions m_option_group;
OptionGroupTagWrite m_tag_write_options;
};
CommandObjectMemoryTag::CommandObjectMemoryTag(CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "tag", "Commands for manipulating memory tags",
@ -123,6 +290,11 @@ CommandObjectMemoryTag::CommandObjectMemoryTag(CommandInterpreter &interpreter)
new CommandObjectMemoryTagRead(interpreter));
read_command_object->SetCommandName("memory tag read");
LoadSubCommand("read", read_command_object);
CommandObjectSP write_command_object(
new CommandObjectMemoryTagWrite(interpreter));
write_command_object->SetCommandName("memory tag write");
LoadSubCommand("write", write_command_object);
}
CommandObjectMemoryTag::~CommandObjectMemoryTag() = default;

View File

@ -504,6 +504,14 @@ let Command = "memory write" in {
Desc<"Start writing bytes from an offset within the input file.">;
}
let Command = "memory tag write" in {
def memory_write_end_addr : Option<"end-addr", "e">, Group<1>,
Arg<"AddressOrExpression">, Desc<
"Set tags for start address to end-addr, repeating tags as needed"
" to cover the range. (instead of calculating the range from the"
" number of tags given)">;
}
let Command = "register read" in {
def register_read_alternate : Option<"alternate", "A">,
Desc<"Display register names using the alternate register name if there "

View File

@ -3474,15 +3474,31 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
return SendIllFormedResponse(packet, invalid_type_err);
int32_t type =
packet.GetS32(std::numeric_limits<int32_t>::max(), /*base=*/16);
if (type == std::numeric_limits<int32_t>::max() ||
// Type is a signed integer but packed into the packet as its raw bytes.
// However, our GetU64 uses strtoull which allows +/-. We do not want this.
const char *first_type_char = packet.Peek();
if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
return SendIllFormedResponse(packet, invalid_type_err);
// Extract type as unsigned then cast to signed.
// Using a uint64_t here so that we have some value outside of the 32 bit
// range to use as the invalid return value.
uint64_t raw_type =
packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
if ( // Make sure the cast below would be valid
raw_type > std::numeric_limits<uint32_t>::max() ||
// To catch inputs like "123aardvark" that will parse but clearly aren't
// valid in this case.
packet.GetBytesLeft()) {
return SendIllFormedResponse(packet, invalid_type_err);
}
// First narrow to 32 bits otherwise the copy into type would take
// the wrong 4 bytes on big endian.
uint32_t raw_type_32 = raw_type;
int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
StreamGDBRemote response;
std::vector<uint8_t> tags;
Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
@ -3552,7 +3568,11 @@ GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
if (raw_type > std::numeric_limits<uint32_t>::max())
return SendIllFormedResponse(packet, invalid_type_err);
int32_t type = static_cast<int32_t>(raw_type);
// First narrow to 32 bits. Otherwise the copy below would get the wrong
// 4 bytes on big endian.
uint32_t raw_type_32 = raw_type;
int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
// Tag data
if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')

View File

@ -744,6 +744,10 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
/// minimum/maximum flavor.
CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF);
/// Return the minimum or maximum constant value for the specified integer
/// min/max flavor and type.
APInt getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth);
/// Check if the values in \p VL are select instructions that can be converted
/// to a min or max (vector) intrinsic. Returns the intrinsic ID, if such a
/// conversion is possible, together with a bool indicating whether all select

View File

@ -1396,6 +1396,11 @@ class TargetLoweringBase {
return NVT;
}
virtual EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty,
bool AllowUnknown = false) const {
return getValueType(DL, Ty, AllowUnknown);
}
/// Return the EVT corresponding to this LLVM type. This is fixed by the LLVM
/// operations except for the pointer size. If AllowUnknown is true, this
/// will return MVT::Other for types with no EVT counterpart (e.g. structs),

View File

@ -216,6 +216,7 @@ def untyped : ValueType<8, 174>; // Produces an untyped value
def funcref : ValueType<0, 175>; // WebAssembly's funcref type
def externref : ValueType<0, 176>; // WebAssembly's externref type
def x86amx : ValueType<8192, 177>; // X86 AMX value
def i64x8 : ValueType<512, 178>; // 8 Consecutive GPRs (AArch64)
def token : ValueType<0, 248>; // TokenTy

View File

@ -324,6 +324,9 @@ class Module {
/// name is not found.
GlobalValue *getNamedValue(StringRef Name) const;
/// Return the number of global values in the module.
unsigned getNumNamedValues() const;
/// Return a unique non-zero ID for the specified metadata kind. This ID is
/// uniqued across modules in the current LLVMContext.
unsigned getMDKindID(StringRef Name) const;

View File

@ -1104,6 +1104,7 @@ namespace RawInstrProf {
// Version 5: Bit 60 of FuncHash is reserved for the flag for the context
// sensitive records.
// Version 6: Added binary id.
// Version 7: Reorder binary id and include version in signature.
const uint64_t Version = INSTR_PROF_RAW_VERSION;
template <class IntPtrT> inline uint64_t getMagic();

View File

@ -129,6 +129,7 @@ INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
#endif
INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic())
INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version())
INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
@ -137,7 +138,6 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
#undef INSTR_PROF_RAW_HEADER
/* INSTR_PROF_RAW_HEADER end */
@ -646,7 +646,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
/* Raw profile format version (start from 1). */
#define INSTR_PROF_RAW_VERSION 6
#define INSTR_PROF_RAW_VERSION 7
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 7
/* Coverage mapping format version (start from 0). */

View File

@ -270,9 +270,10 @@ namespace llvm {
funcref = 175, // WebAssembly's funcref type
externref = 176, // WebAssembly's externref type
x86amx = 177, // This is an X86 AMX value
i64x8 = 178, // 8 Consecutive GPRs (AArch64)
FIRST_VALUETYPE = 1, // This is always the beginning of the list.
LAST_VALUETYPE = x86amx, // This always remains at the end of the list.
LAST_VALUETYPE = i64x8, // This always remains at the end of the list.
VALUETYPE_SIZE = LAST_VALUETYPE + 1,
// This is the current maximum for LAST_VALUETYPE.
@ -987,6 +988,7 @@ namespace llvm {
case nxv16f16:
case nxv8f32:
case nxv4f64: return TypeSize::Scalable(256);
case i64x8:
case v512i1:
case v64i8:
case v32i16:

View File

@ -1855,6 +1855,10 @@ struct Attributor {
///
static void createShallowWrapper(Function &F);
/// Returns true if the function \p F can be internalized. i.e. it has a
/// compatible linkage.
static bool isInternalizable(Function &F);
/// Make another copy of the function \p F such that the copied version has
/// internal linkage afterwards and can be analysed. Then we replace all uses
/// of the original function to the copied one
@ -1870,6 +1874,22 @@ struct Attributor {
/// null pointer.
static Function *internalizeFunction(Function &F, bool Force = false);
/// Make copies of each function in the set \p FnSet such that the copied
/// version has internal linkage afterwards and can be analysed. Then we
/// replace all uses of the original function to the copied one. The map
/// \p FnMap contains a mapping of functions to their internalized versions.
///
/// Only non-locally linked functions that have `linkonce_odr` or `weak_odr`
/// linkage can be internalized because these linkages guarantee that other
/// definitions with the same name have the same semantics as this one.
///
/// This version will internalize all the functions in the set \p FnSet at
/// once and then replace the uses. This prevents internalized functions being
/// called by external functions when there is an internalized version in the
/// module.
static bool internalizeFunctions(SmallPtrSetImpl<Function *> &FnSet,
DenseMap<Function *, Function *> &FnMap);
/// Return the data layout associated with the anchor scope.
const DataLayout &getDataLayout() const { return InfoCache.DL; }

View File

@ -51,11 +51,13 @@
#define LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
namespace llvm {
@ -176,7 +178,7 @@ class PredicateSwitch : public PredicateWithEdge {
class PredicateInfo {
public:
PredicateInfo(Function &, DominatorTree &, AssumptionCache &);
~PredicateInfo() = default;
~PredicateInfo();
void verifyPredicateInfo() const;
@ -203,6 +205,8 @@ class PredicateInfo {
// the Predicate Info, they belong to the ValueInfo structs in the ValueInfos
// vector.
DenseMap<const Value *, const PredicateBase *> PredicateMap;
// The set of ssa_copy declarations we created with our custom mangling.
SmallSet<AssertingVH<Function>, 20> CreatedDeclarations;
};
// This pass does eager building and then printing of PredicateInfo. It is used

View File

@ -4080,6 +4080,22 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
std::swap(TrueVal, FalseVal);
}
// Check for integer min/max with a limit constant:
// X > MIN_INT ? X : MIN_INT --> X
// X < MAX_INT ? X : MAX_INT --> X
if (TrueVal->getType()->isIntOrIntVectorTy()) {
Value *X, *Y;
SelectPatternFlavor SPF =
matchDecomposedSelectPattern(cast<ICmpInst>(CondVal), TrueVal, FalseVal,
X, Y).Flavor;
if (SelectPatternResult::isMinOrMax(SPF) && Pred == getMinMaxPred(SPF)) {
APInt LimitC = getMinMaxLimit(getInverseMinMaxFlavor(SPF),
X->getType()->getScalarSizeInBits());
if (match(Y, m_SpecificInt(LimitC)))
return X;
}
}
if (Pred == ICmpInst::ICMP_EQ && match(CmpRHS, m_Zero())) {
Value *X;
const APInt *Y;

View File

@ -893,9 +893,10 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
FTy.getReturnType()->isIntegerTy(32);
case LibFunc_snprintf:
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(2)->isPointerTy() &&
FTy.getReturnType()->isIntegerTy(32));
return NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
IsSizeTTy(FTy.getParamType(1)) &&
FTy.getParamType(2)->isPointerTy() &&
FTy.getReturnType()->isIntegerTy(32);
case LibFunc_snprintf_chk:
return NumParams == 5 && FTy.getParamType(0)->isPointerTy() &&

View File

@ -6253,6 +6253,16 @@ CmpInst::Predicate llvm::getInverseMinMaxPred(SelectPatternFlavor SPF) {
return getMinMaxPred(getInverseMinMaxFlavor(SPF));
}
APInt llvm::getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth) {
switch (SPF) {
case SPF_SMAX: return APInt::getSignedMaxValue(BitWidth);
case SPF_SMIN: return APInt::getSignedMinValue(BitWidth);
case SPF_UMAX: return APInt::getMaxValue(BitWidth);
case SPF_UMIN: return APInt::getMinValue(BitWidth);
default: llvm_unreachable("Unexpected flavor");
}
}
std::pair<Intrinsic::ID, bool>
llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
// Check if VL contains select instructions that can be folded into a min/max

View File

@ -325,7 +325,8 @@ bool InlineAsmLowering::lowerInlineAsm(
return false;
}
OpInfo.ConstraintVT = TLI->getValueType(DL, OpTy, true).getSimpleVT();
OpInfo.ConstraintVT =
TLI->getAsmOperandValueType(DL, OpTy, true).getSimpleVT();
} else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) {
assert(!Call.getType()->isVoidTy() && "Bad inline asm!");
@ -334,13 +335,17 @@ bool InlineAsmLowering::lowerInlineAsm(
TLI->getSimpleValueType(DL, STy->getElementType(ResNo));
} else {
assert(ResNo == 0 && "Asm only has one result!");
OpInfo.ConstraintVT = TLI->getSimpleValueType(DL, Call.getType());
OpInfo.ConstraintVT =
TLI->getAsmOperandValueType(DL, Call.getType()).getSimpleVT();
}
++ResNo;
} else {
OpInfo.ConstraintVT = MVT::Other;
}
if (OpInfo.ConstraintVT == MVT::i64x8)
return false;
// Compute the constraint code and ConstraintType to use.
computeConstraintToUse(TLI, OpInfo);

View File

@ -2439,9 +2439,7 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) {
N0.getOperand(0));
// fold (add (add (xor a, -1), b), 1) -> (sub b, a)
if (N0.getOpcode() == ISD::ADD ||
N0.getOpcode() == ISD::UADDO ||
N0.getOpcode() == ISD::SADDO) {
if (N0.getOpcode() == ISD::ADD) {
SDValue A, Xor;
if (isBitwiseNot(N0.getOperand(0))) {
@ -20562,8 +20560,12 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *N) {
// otherwise => (extract_subvec V1, ExtIdx)
uint64_t InsIdx = V.getConstantOperandVal(2);
if (InsIdx * SmallVT.getScalarSizeInBits() ==
ExtIdx * NVT.getScalarSizeInBits())
ExtIdx * NVT.getScalarSizeInBits()) {
if (LegalOperations && !TLI.isOperationLegal(ISD::BITCAST, NVT))
return SDValue();
return DAG.getBitcast(NVT, V.getOperand(1));
}
return DAG.getNode(
ISD::EXTRACT_SUBVECTOR, SDLoc(N), NVT,
DAG.getBitcast(N->getOperand(0).getValueType(), V.getOperand(0)),

View File

@ -8176,7 +8176,7 @@ class SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo {
}
}
return TLI.getValueType(DL, OpTy, true);
return TLI.getAsmOperandValueType(DL, OpTy, true);
}
};
@ -8479,8 +8479,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
DAG.getDataLayout(), STy->getElementType(ResNo));
} else {
assert(ResNo == 0 && "Asm only has one result!");
OpInfo.ConstraintVT =
TLI.getSimpleValueType(DAG.getDataLayout(), Call.getType());
OpInfo.ConstraintVT = TLI.getAsmOperandValueType(
DAG.getDataLayout(), Call.getType()).getSimpleVT();
}
++ResNo;
} else {

View File

@ -1660,7 +1660,7 @@ static bool MIIsInTerminatorSequence(const MachineInstr &MI) {
// physical registers if there is debug info associated with the terminator
// of our mbb. We want to include said debug info in our terminator
// sequence, so we return true in that case.
return MI.isDebugValue();
return MI.isDebugInstr();
// We have left the terminator sequence if we are not doing one of the
// following:

View File

@ -4687,7 +4687,8 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
getSimpleValueType(DL, STy->getElementType(ResNo));
} else {
assert(ResNo == 0 && "Asm only has one result!");
OpInfo.ConstraintVT = getSimpleValueType(DL, Call.getType());
OpInfo.ConstraintVT =
getAsmOperandValueType(DL, Call.getType()).getSimpleVT();
}
++ResNo;
break;

View File

@ -677,8 +677,9 @@ calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
}
if (Retain) {
if (Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36))
if ((Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)) &&
!TM.getTargetTriple().isOSSolaris())
Flags |= ELF::SHF_GNU_RETAIN;
return NextUniqueID++;
}
@ -855,8 +856,10 @@ static MCSection *selectELFSectionForGlobal(
EmitUniqueSection = true;
Flags |= ELF::SHF_LINK_ORDER;
}
if (Retain && (Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36))) {
if (Retain &&
(Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)) &&
!TM.getTargetTriple().isOSSolaris()) {
EmitUniqueSection = true;
Flags |= ELF::SHF_GNU_RETAIN;
}

View File

@ -167,6 +167,7 @@ std::string EVT::getEVTString() const {
case MVT::Glue: return "glue";
case MVT::x86mmx: return "x86mmx";
case MVT::x86amx: return "x86amx";
case MVT::i64x8: return "i64x8";
case MVT::Metadata: return "Metadata";
case MVT::Untyped: return "Untyped";
case MVT::funcref: return "funcref";
@ -198,6 +199,7 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
case MVT::ppcf128: return Type::getPPC_FP128Ty(Context);
case MVT::x86mmx: return Type::getX86_MMXTy(Context);
case MVT::x86amx: return Type::getX86_AMXTy(Context);
case MVT::i64x8: return IntegerType::get(Context, 512);
case MVT::externref:
return PointerType::get(StructType::create(Context), 10);
case MVT::funcref:

View File

@ -349,200 +349,6 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,
}
}
/// Wrapper around getFoldedSizeOfImpl() that adds caching.
static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded,
DenseMap<Type *, Constant *> &Cache);
/// Return a ConstantExpr with type DestTy for sizeof on Ty, with any known
/// factors factored out. If Folded is false, return null if no factoring was
/// possible, to avoid endlessly bouncing an unfoldable expression back into the
/// top-level folder.
static Constant *getFoldedSizeOfImpl(Type *Ty, Type *DestTy, bool Folded,
DenseMap<Type *, Constant *> &Cache) {
// This is the actual implementation of getFoldedSizeOf(). To get the caching
// behavior, we need to call getFoldedSizeOf() when we recurse.
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *N = ConstantInt::get(DestTy, ATy->getNumElements());
Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true, Cache);
return ConstantExpr::getNUWMul(E, N);
}
if (StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isPacked()) {
unsigned NumElems = STy->getNumElements();
// An empty struct has size zero.
if (NumElems == 0)
return ConstantExpr::getNullValue(DestTy);
// Check for a struct with all members having the same size.
Constant *MemberSize =
getFoldedSizeOf(STy->getElementType(0), DestTy, true, Cache);
bool AllSame = true;
for (unsigned i = 1; i != NumElems; ++i)
if (MemberSize !=
getFoldedSizeOf(STy->getElementType(i), DestTy, true, Cache)) {
AllSame = false;
break;
}
if (AllSame) {
Constant *N = ConstantInt::get(DestTy, NumElems);
return ConstantExpr::getNUWMul(MemberSize, N);
}
}
// Pointer size doesn't depend on the pointee type, so canonicalize them
// to an arbitrary pointee.
if (PointerType *PTy = dyn_cast<PointerType>(Ty))
if (!PTy->getElementType()->isIntegerTy(1))
return getFoldedSizeOf(
PointerType::get(IntegerType::get(PTy->getContext(), 1),
PTy->getAddressSpace()),
DestTy, true, Cache);
// If there's no interesting folding happening, bail so that we don't create
// a constant that looks like it needs folding but really doesn't.
if (!Folded)
return nullptr;
// Base case: Get a regular sizeof expression.
Constant *C = ConstantExpr::getSizeOf(Ty);
C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false,
DestTy, false),
C, DestTy);
return C;
}
static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded,
DenseMap<Type *, Constant *> &Cache) {
// Check for previously generated folded size constant.
auto It = Cache.find(Ty);
if (It != Cache.end())
return It->second;
return Cache[Ty] = getFoldedSizeOfImpl(Ty, DestTy, Folded, Cache);
}
static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
DenseMap<Type *, Constant *> Cache;
return getFoldedSizeOf(Ty, DestTy, Folded, Cache);
}
/// Return a ConstantExpr with type DestTy for alignof on Ty, with any known
/// factors factored out. If Folded is false, return null if no factoring was
/// possible, to avoid endlessly bouncing an unfoldable expression back into the
/// top-level folder.
static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy, bool Folded) {
// The alignment of an array is equal to the alignment of the
// array element. Note that this is not always true for vectors.
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *C = ConstantExpr::getAlignOf(ATy->getElementType());
C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false,
DestTy,
false),
C, DestTy);
return C;
}
if (StructType *STy = dyn_cast<StructType>(Ty)) {
// Packed structs always have an alignment of 1.
if (STy->isPacked())
return ConstantInt::get(DestTy, 1);
// Otherwise, struct alignment is the maximum alignment of any member.
// Without target data, we can't compare much, but we can check to see
// if all the members have the same alignment.
unsigned NumElems = STy->getNumElements();
// An empty struct has minimal alignment.
if (NumElems == 0)
return ConstantInt::get(DestTy, 1);
// Check for a struct with all members having the same alignment.
Constant *MemberAlign =
getFoldedAlignOf(STy->getElementType(0), DestTy, true);
bool AllSame = true;
for (unsigned i = 1; i != NumElems; ++i)
if (MemberAlign != getFoldedAlignOf(STy->getElementType(i), DestTy, true)) {
AllSame = false;
break;
}
if (AllSame)
return MemberAlign;
}
// Pointer alignment doesn't depend on the pointee type, so canonicalize them
// to an arbitrary pointee.
if (PointerType *PTy = dyn_cast<PointerType>(Ty))
if (!PTy->getElementType()->isIntegerTy(1))
return
getFoldedAlignOf(PointerType::get(IntegerType::get(PTy->getContext(),
1),
PTy->getAddressSpace()),
DestTy, true);
// If there's no interesting folding happening, bail so that we don't create
// a constant that looks like it needs folding but really doesn't.
if (!Folded)
return nullptr;
// Base case: Get a regular alignof expression.
Constant *C = ConstantExpr::getAlignOf(Ty);
C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false,
DestTy, false),
C, DestTy);
return C;
}
/// Return a ConstantExpr with type DestTy for offsetof on Ty and FieldNo, with
/// any known factors factored out. If Folded is false, return null if no
/// factoring was possible, to avoid endlessly bouncing an unfoldable expression
/// back into the top-level folder.
static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo, Type *DestTy,
bool Folded) {
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, false,
DestTy, false),
FieldNo, DestTy);
Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true);
return ConstantExpr::getNUWMul(E, N);
}
if (StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isPacked()) {
unsigned NumElems = STy->getNumElements();
// An empty struct has no members.
if (NumElems == 0)
return nullptr;
// Check for a struct with all members having the same size.
Constant *MemberSize =
getFoldedSizeOf(STy->getElementType(0), DestTy, true);
bool AllSame = true;
for (unsigned i = 1; i != NumElems; ++i)
if (MemberSize !=
getFoldedSizeOf(STy->getElementType(i), DestTy, true)) {
AllSame = false;
break;
}
if (AllSame) {
Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo,
false,
DestTy,
false),
FieldNo, DestTy);
return ConstantExpr::getNUWMul(MemberSize, N);
}
}
// If there's no interesting folding happening, bail so that we don't create
// a constant that looks like it needs folding but really doesn't.
if (!Folded)
return nullptr;
// Base case: Get a regular offsetof expression.
Constant *C = ConstantExpr::getOffsetOf(Ty, FieldNo);
C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false,
DestTy, false),
C, DestTy);
return C;
}
Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
Type *DestTy) {
if (isa<PoisonValue>(V))
@ -666,53 +472,6 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
// Is it a null pointer value?
if (V->isNullValue())
return ConstantInt::get(DestTy, 0);
// If this is a sizeof-like expression, pull out multiplications by
// known factors to expose them to subsequent folding. If it's an
// alignof-like expression, factor out known factors.
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
if (CE->getOpcode() == Instruction::GetElementPtr &&
CE->getOperand(0)->isNullValue()) {
// FIXME: Looks like getFoldedSizeOf(), getFoldedOffsetOf() and
// getFoldedAlignOf() don't handle the case when DestTy is a vector of
// pointers yet. We end up in asserts in CastInst::getCastOpcode (see
// test/Analysis/ConstantFolding/cast-vector.ll). I've only seen this
// happen in one "real" C-code test case, so it does not seem to be an
// important optimization to handle vectors here. For now, simply bail
// out.
if (DestTy->isVectorTy())
return nullptr;
GEPOperator *GEPO = cast<GEPOperator>(CE);
Type *Ty = GEPO->getSourceElementType();
if (CE->getNumOperands() == 2) {
// Handle a sizeof-like expression.
Constant *Idx = CE->getOperand(1);
bool isOne = isa<ConstantInt>(Idx) && cast<ConstantInt>(Idx)->isOne();
if (Constant *C = getFoldedSizeOf(Ty, DestTy, !isOne)) {
Idx = ConstantExpr::getCast(CastInst::getCastOpcode(Idx, true,
DestTy, false),
Idx, DestTy);
return ConstantExpr::getMul(C, Idx);
}
} else if (CE->getNumOperands() == 3 &&
CE->getOperand(1)->isNullValue()) {
// Handle an alignof-like expression.
if (StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isPacked()) {
ConstantInt *CI = cast<ConstantInt>(CE->getOperand(2));
if (CI->isOne() &&
STy->getNumElements() == 2 &&
STy->getElementType(0)->isIntegerTy(1)) {
return getFoldedAlignOf(STy->getElementType(1), DestTy, false);
}
}
// Handle an offsetof-like expression.
if (Ty->isStructTy() || Ty->isArrayTy()) {
if (Constant *C = getFoldedOffsetOf(Ty, CE->getOperand(2),
DestTy, false))
return C;
}
}
}
// Other pointer types cannot be casted
return nullptr;
case Instruction::UIToFP:

View File

@ -114,6 +114,10 @@ GlobalValue *Module::getNamedValue(StringRef Name) const {
return cast_or_null<GlobalValue>(getValueSymbolTable().lookup(Name));
}
unsigned Module::getNumNamedValues() const {
return getValueSymbolTable().size();
}
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
/// This ID is uniqued across modules in the current LLVMContext.
unsigned Module::getMDKindID(StringRef Name) const {

View File

@ -366,6 +366,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
if (GET_VERSION(Version) != RawInstrProf::Version)
return error(instrprof_error::unsupported_version);
BinaryIdsSize = swap(Header.BinaryIdsSize);
CountersDelta = swap(Header.CountersDelta);
NamesDelta = swap(Header.NamesDelta);
auto DataSize = swap(Header.DataSize);
@ -374,7 +375,6 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
NamesSize = swap(Header.NamesSize);
ValueKindLast = swap(Header.ValueKindLast);
BinaryIdsSize = swap(Header.BinaryIdsSize);
auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
auto PaddingSize = getNumPaddingBytes(NamesSize);

View File

@ -653,6 +653,9 @@ bool AArch64AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode,
case 'x':
Reg = getXRegFromWReg(Reg);
break;
case 't':
Reg = getXRegFromXRegTuple(Reg);
break;
}
O << AArch64InstPrinter::getRegisterName(Reg);
@ -749,6 +752,10 @@ bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
AArch64::GPR64allRegClass.contains(Reg))
return printAsmMRegister(MO, 'x', O);
// If this is an x register tuple, print an x register.
if (AArch64::GPR64x8ClassRegClass.contains(Reg))
return printAsmMRegister(MO, 't', O);
unsigned AltName = AArch64::NoRegAltName;
const TargetRegisterClass *RegClass;
if (AArch64::ZPRRegClass.contains(Reg)) {

View File

@ -246,6 +246,12 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
addRegisterClass(MVT::i32, &AArch64::GPR32allRegClass);
addRegisterClass(MVT::i64, &AArch64::GPR64allRegClass);
if (Subtarget->hasLS64()) {
addRegisterClass(MVT::i64x8, &AArch64::GPR64x8ClassRegClass);
setOperationAction(ISD::LOAD, MVT::i64x8, Custom);
setOperationAction(ISD::STORE, MVT::i64x8, Custom);
}
if (Subtarget->hasFPARMv8()) {
addRegisterClass(MVT::f16, &AArch64::FPR16RegClass);
addRegisterClass(MVT::bf16, &AArch64::FPR16RegClass);
@ -2023,6 +2029,8 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
MAKE_CASE(AArch64ISD::LASTA)
MAKE_CASE(AArch64ISD::LASTB)
MAKE_CASE(AArch64ISD::REINTERPRET_CAST)
MAKE_CASE(AArch64ISD::LS64_BUILD)
MAKE_CASE(AArch64ISD::LS64_EXTRACT)
MAKE_CASE(AArch64ISD::TBL)
MAKE_CASE(AArch64ISD::FADD_PRED)
MAKE_CASE(AArch64ISD::FADDA_PRED)
@ -4345,9 +4353,17 @@ SDValue AArch64TargetLowering::LowerMGATHER(SDValue Op,
if (IsFixedLength) {
assert(Subtarget->useSVEForFixedLengthVectors() &&
"Cannot lower when not using SVE for fixed vectors");
IndexVT = getContainerForFixedLengthVector(DAG, IndexVT);
MemVT = IndexVT.changeVectorElementType(MemVT.getVectorElementType());
if (MemVT.getScalarSizeInBits() <= IndexVT.getScalarSizeInBits()) {
IndexVT = getContainerForFixedLengthVector(DAG, IndexVT);
MemVT = IndexVT.changeVectorElementType(MemVT.getVectorElementType());
} else {
MemVT = getContainerForFixedLengthVector(DAG, MemVT);
IndexVT = MemVT.changeTypeToInteger();
}
InputVT = DAG.getValueType(MemVT.changeTypeToInteger());
Mask = DAG.getNode(
ISD::ZERO_EXTEND, DL,
VT.changeVectorElementType(IndexVT.getVectorElementType()), Mask);
}
if (PassThru->isUndef() || isZerosVector(PassThru.getNode()))
@ -4442,8 +4458,13 @@ SDValue AArch64TargetLowering::LowerMSCATTER(SDValue Op,
if (IsFixedLength) {
assert(Subtarget->useSVEForFixedLengthVectors() &&
"Cannot lower when not using SVE for fixed vectors");
IndexVT = getContainerForFixedLengthVector(DAG, IndexVT);
MemVT = IndexVT.changeVectorElementType(MemVT.getVectorElementType());
if (MemVT.getScalarSizeInBits() <= IndexVT.getScalarSizeInBits()) {
IndexVT = getContainerForFixedLengthVector(DAG, IndexVT);
MemVT = IndexVT.changeVectorElementType(MemVT.getVectorElementType());
} else {
MemVT = getContainerForFixedLengthVector(DAG, MemVT);
IndexVT = MemVT.changeTypeToInteger();
}
InputVT = DAG.getValueType(MemVT.changeTypeToInteger());
StoreVal =
@ -4452,6 +4473,9 @@ SDValue AArch64TargetLowering::LowerMSCATTER(SDValue Op,
ISD::ANY_EXTEND, DL,
VT.changeVectorElementType(IndexVT.getVectorElementType()), StoreVal);
StoreVal = convertToScalableVector(DAG, IndexVT, StoreVal);
Mask = DAG.getNode(
ISD::ZERO_EXTEND, DL,
VT.changeVectorElementType(IndexVT.getVectorElementType()), Mask);
} else if (VT.isFloatingPoint()) {
// Handle FP data by casting the data so an integer scatter can be used.
EVT StoreValVT = getPackedSVEVectorVT(VT.getVectorElementCount());
@ -4605,17 +4629,51 @@ SDValue AArch64TargetLowering::LowerSTORE(SDValue Op,
{StoreNode->getChain(), Lo, Hi, StoreNode->getBasePtr()},
StoreNode->getMemoryVT(), StoreNode->getMemOperand());
return Result;
} else if (MemVT == MVT::i64x8) {
SDValue Value = StoreNode->getValue();
assert(Value->getValueType(0) == MVT::i64x8);
SDValue Chain = StoreNode->getChain();
SDValue Base = StoreNode->getBasePtr();
EVT PtrVT = Base.getValueType();
for (unsigned i = 0; i < 8; i++) {
SDValue Part = DAG.getNode(AArch64ISD::LS64_EXTRACT, Dl, MVT::i64,
Value, DAG.getConstant(i, Dl, MVT::i32));
SDValue Ptr = DAG.getNode(ISD::ADD, Dl, PtrVT, Base,
DAG.getConstant(i * 8, Dl, PtrVT));
Chain = DAG.getStore(Chain, Dl, Part, Ptr, StoreNode->getPointerInfo(),
StoreNode->getOriginalAlign());
}
return Chain;
}
return SDValue();
}
// Custom lowering for extending v4i8 vector loads.
SDValue AArch64TargetLowering::LowerLOAD(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
LoadSDNode *LoadNode = cast<LoadSDNode>(Op);
assert(LoadNode && "Expected custom lowering of a load node");
if (LoadNode->getMemoryVT() == MVT::i64x8) {
SmallVector<SDValue, 8> Ops;
SDValue Base = LoadNode->getBasePtr();
SDValue Chain = LoadNode->getChain();
EVT PtrVT = Base.getValueType();
for (unsigned i = 0; i < 8; i++) {
SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base,
DAG.getConstant(i * 8, DL, PtrVT));
SDValue Part = DAG.getLoad(MVT::i64, DL, Chain, Ptr,
LoadNode->getPointerInfo(),
LoadNode->getOriginalAlign());
Ops.push_back(Part);
Chain = SDValue(Part.getNode(), 1);
}
SDValue Loaded = DAG.getNode(AArch64ISD::LS64_BUILD, DL, MVT::i64x8, Ops);
return DAG.getMergeValues({Loaded, Chain}, DL);
}
// Custom lowering for extending v4i8 vector loads.
EVT VT = Op->getValueType(0);
assert((VT == MVT::v4i16 || VT == MVT::v4i32) && "Expected v4i16 or v4i32");
@ -8173,6 +8231,8 @@ AArch64TargetLowering::getRegForInlineAsmConstraint(
case 'r':
if (VT.isScalableVector())
return std::make_pair(0U, nullptr);
if (Subtarget->hasLS64() && VT.getSizeInBits() == 512)
return std::make_pair(0U, &AArch64::GPR64x8ClassRegClass);
if (VT.getFixedSizeInBits() == 64)
return std::make_pair(0U, &AArch64::GPR64commonRegClass);
return std::make_pair(0U, &AArch64::GPR32commonRegClass);
@ -8260,6 +8320,15 @@ AArch64TargetLowering::getRegForInlineAsmConstraint(
return Res;
}
EVT AArch64TargetLowering::getAsmOperandValueType(const DataLayout &DL,
llvm::Type *Ty,
bool AllowUnknown) const {
if (Subtarget->hasLS64() && Ty->isIntegerTy(512))
return EVT(MVT::i64x8);
return TargetLowering::getAsmOperandValueType(DL, Ty, AllowUnknown);
}
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops.
void AArch64TargetLowering::LowerAsmOperandForConstraint(

View File

@ -330,6 +330,10 @@ enum NodeType : unsigned {
// Cast between vectors of the same element type but differ in length.
REINTERPRET_CAST,
// Nodes to build an LD64B / ST64B 64-bit quantity out of i64, and vice versa
LS64_BUILD,
LS64_EXTRACT,
LD1_MERGE_ZERO,
LD1S_MERGE_ZERO,
LDNF1_MERGE_ZERO,
@ -824,6 +828,9 @@ class AArch64TargetLowering : public TargetLowering {
bool isAllActivePredicate(SDValue N) const;
EVT getPromotedVTForPredicate(EVT VT) const;
EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty,
bool AllowUnknown = false) const override;
private:
/// Keep a pointer to the AArch64Subtarget around so that we can
/// make the right decision when generating code for different targets.

View File

@ -1120,6 +1120,16 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
if (!MI.getOperand(1).isReg())
return false;
auto NormalizeCmpValue = [](int64_t Value) -> int {
// Comparison immediates may be 64-bit, but CmpValue is only an int.
// Normalize to 0/1/2 return value, where 2 indicates any value apart from
// 0 or 1.
// TODO: Switch CmpValue to int64_t in the API to avoid this.
if (Value == 0 || Value == 1)
return Value;
return 2;
};
switch (MI.getOpcode()) {
default:
break;
@ -1155,8 +1165,7 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
SrcReg = MI.getOperand(1).getReg();
SrcReg2 = 0;
CmpMask = ~0;
// FIXME: In order to convert CmpValue to 0 or 1
CmpValue = MI.getOperand(2).getImm() != 0;
CmpValue = NormalizeCmpValue(MI.getOperand(2).getImm());
return true;
case AArch64::ANDSWri:
case AArch64::ANDSXri:
@ -1165,14 +1174,9 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
SrcReg = MI.getOperand(1).getReg();
SrcReg2 = 0;
CmpMask = ~0;
// FIXME:The return val type of decodeLogicalImmediate is uint64_t,
// while the type of CmpValue is int. When converting uint64_t to int,
// the high 32 bits of uint64_t will be lost.
// In fact it causes a bug in spec2006-483.xalancbmk
// CmpValue is only used to compare with zero in OptimizeCompareInstr
CmpValue = AArch64_AM::decodeLogicalImmediate(
CmpValue = NormalizeCmpValue(AArch64_AM::decodeLogicalImmediate(
MI.getOperand(2).getImm(),
MI.getOpcode() == AArch64::ANDSWri ? 32 : 64) != 0;
MI.getOpcode() == AArch64::ANDSWri ? 32 : 64));
return true;
}
@ -1462,10 +1466,9 @@ bool AArch64InstrInfo::optimizeCompareInstr(
if (CmpInstr.getOpcode() == AArch64::PTEST_PP)
return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
// Continue only if we have a "ri" where immediate is zero.
// FIXME:CmpValue has already been converted to 0 or 1 in analyzeCompare
// function.
assert((CmpValue == 0 || CmpValue == 1) && "CmpValue must be 0 or 1!");
// Warning: CmpValue == 2 indicates *any* value apart from 0 or 1.
assert((CmpValue == 0 || CmpValue == 1 || CmpValue == 2) &&
"CmpValue must be 0, 1, or 2!");
if (SrcReg2 != 0)
return false;
@ -1473,9 +1476,10 @@ bool AArch64InstrInfo::optimizeCompareInstr(
if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
return false;
if (!CmpValue && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
return true;
return removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
return (CmpValue == 0 || CmpValue == 1) &&
removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
}
/// Get opcode of S version of Instr.

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