mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Vendor import of llvm-project branch release/16.x llvmorg-16.0.0-45-g42d1b276f779.
This commit is contained in:
parent
11ee15ea4e
commit
5bcd187b30
40 changed files with 2427 additions and 315 deletions
|
|
@ -1052,7 +1052,7 @@ def err_lambda_template_parameter_list_empty : Error<
|
|||
// C++2b static lambdas
|
||||
def err_static_lambda: ExtWarn<
|
||||
"static lambdas are a C++2b extension">, InGroup<CXX2b>;
|
||||
def warn_cxx20_compat_static_lambda: ExtWarn<
|
||||
def warn_cxx20_compat_static_lambda : Warning<
|
||||
"static lambdas are incompatible with C++ standards before C++2b">,
|
||||
InGroup<CXXPre2bCompat>, DefaultIgnore;
|
||||
def err_static_mutable_lambda : Error<
|
||||
|
|
|
|||
|
|
@ -9138,8 +9138,9 @@ def err_operator_overload_static : Error<
|
|||
def err_operator_overload_default_arg : Error<
|
||||
"parameter of overloaded %0 cannot have a default argument">;
|
||||
|
||||
def ext_subscript_overload : ExtWarn<
|
||||
"overloaded %0 with %select{no|a defaulted|more than one}1 parameter is a C++2b extension">, InGroup<CXXPre2bCompat>, DefaultIgnore;
|
||||
def ext_subscript_overload : Warning<
|
||||
"overloaded %0 with %select{no|a defaulted|more than one}1 parameter is a "
|
||||
"C++2b extension">, InGroup<CXXPre2bCompat>, DefaultIgnore;
|
||||
def error_subscript_overload : Error<
|
||||
"overloaded %0 cannot have %select{no|a defaulted|more than one}1 parameter before C++2b">;
|
||||
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
|
|||
const TargetOptions &Opts)
|
||||
: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
|
||||
HW_FP(0) {
|
||||
bool IsFreeBSD = Triple.isOSFreeBSD();
|
||||
bool IsOpenBSD = Triple.isOSOpenBSD();
|
||||
bool IsNetBSD = Triple.isOSNetBSD();
|
||||
|
||||
|
|
@ -321,7 +322,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
|
|||
default:
|
||||
if (IsNetBSD)
|
||||
setABI("apcs-gnu");
|
||||
else if (IsOpenBSD)
|
||||
else if (IsFreeBSD || IsOpenBSD)
|
||||
setABI("aapcs-linux");
|
||||
else
|
||||
setABI("aapcs");
|
||||
|
|
|
|||
|
|
@ -85,16 +85,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
else
|
||||
CmdArgs.push_back("-mfpu=softvfp");
|
||||
|
||||
switch (getToolChain().getTriple().getEnvironment()) {
|
||||
case llvm::Triple::GNUEABIHF:
|
||||
case llvm::Triple::GNUEABI:
|
||||
case llvm::Triple::EABI:
|
||||
CmdArgs.push_back("-meabi=5");
|
||||
break;
|
||||
|
||||
default:
|
||||
CmdArgs.push_back("-matpcs");
|
||||
}
|
||||
CmdArgs.push_back("-meabi=5");
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::sparc:
|
||||
|
|
@ -467,21 +458,6 @@ Tool *FreeBSD::buildAssembler() const {
|
|||
|
||||
Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
|
||||
|
||||
llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const {
|
||||
// FreeBSD uses SjLj exceptions on ARM oabi.
|
||||
switch (getTriple().getEnvironment()) {
|
||||
case llvm::Triple::GNUEABIHF:
|
||||
case llvm::Triple::GNUEABI:
|
||||
case llvm::Triple::EABI:
|
||||
return llvm::ExceptionHandling::None;
|
||||
default:
|
||||
if (getTriple().getArch() == llvm::Triple::arm ||
|
||||
getTriple().getArch() == llvm::Triple::thumb)
|
||||
return llvm::ExceptionHandling::SjLj;
|
||||
return llvm::ExceptionHandling::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool FreeBSD::HasNativeLLVMSupport() const { return true; }
|
||||
|
||||
ToolChain::UnwindTableLevel
|
||||
|
|
|
|||
|
|
@ -78,8 +78,6 @@ public:
|
|||
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
|
||||
llvm::ExceptionHandling
|
||||
GetExceptionModel(const llvm::opt::ArgList &Args) const override;
|
||||
UnwindTableLevel
|
||||
getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
|
||||
bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
|
||||
|
|
|
|||
|
|
@ -1562,7 +1562,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
|
|||
const auto *OpDeleteType =
|
||||
OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
|
||||
if (OpDeleteType->getNumParams() > DeleteArgs.size() &&
|
||||
S.getASTContext().hasSameType(
|
||||
S.getASTContext().hasSameUnqualifiedType(
|
||||
OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))
|
||||
DeleteArgs.push_back(FrameSize);
|
||||
|
||||
|
|
@ -1579,7 +1579,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
|
|||
// So we are not forced to pass alignment to the deallocation function.
|
||||
if (S.getLangOpts().CoroAlignedAllocation &&
|
||||
OpDeleteType->getNumParams() > DeleteArgs.size() &&
|
||||
S.getASTContext().hasSameType(
|
||||
S.getASTContext().hasSameUnqualifiedType(
|
||||
OpDeleteType->getParamType(DeleteArgs.size()),
|
||||
FrameAlignment->getType()))
|
||||
DeleteArgs.push_back(FrameAlignment);
|
||||
|
|
|
|||
|
|
@ -1849,8 +1849,12 @@ std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
|
|||
// Go to the nested initializer list.
|
||||
ILE = IL;
|
||||
}
|
||||
llvm_unreachable(
|
||||
"Unhandled InitListExpr sub-expressions or invalid offsets.");
|
||||
|
||||
assert(ILE);
|
||||
|
||||
// FIXME: Unhandeled InitListExpr sub-expression, possibly constructing an
|
||||
// enum?
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// Returns an SVal, if possible, for the specified position in a string
|
||||
|
|
|
|||
|
|
@ -583,6 +583,7 @@ static void GetTls(uptr *addr, uptr *size) {
|
|||
*addr = (uptr)tcb->tcb_dtv[1];
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error "Unknown OS"
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,8 +231,6 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
|
|||
// Check that tool command lines are simple and that complete escaping is
|
||||
// unnecessary.
|
||||
CHECK(!internal_strchr(arg, '"') && "quotes in args unsupported");
|
||||
CHECK(!internal_strstr(arg, "\\\\") &&
|
||||
"double backslashes in args unsupported");
|
||||
CHECK(arglen > 0 && arg[arglen - 1] != '\\' &&
|
||||
"args ending in backslash and empty args unsupported");
|
||||
command_line.append("\"%s\" ", arg);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
|
||||
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 16.0.1 == 16.00.01), _LIBCPP_VERSION is
|
||||
// defined to XXYYZZ.
|
||||
# define _LIBCPP_VERSION 160000
|
||||
# define _LIBCPP_VERSION 160001
|
||||
|
||||
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
|
||||
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
|
||||
|
|
|
|||
|
|
@ -292,7 +292,8 @@ private:
|
|||
"be reverted to the previous state in case an exception is thrown during the assignment.");
|
||||
_T2 __tmp(std::move(__oldval));
|
||||
std::destroy_at(std::addressof(__oldval));
|
||||
__exception_guard __trans([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
|
||||
auto __trans =
|
||||
std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
|
||||
std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
|
||||
__trans.__complete();
|
||||
}
|
||||
|
|
@ -451,7 +452,7 @@ public:
|
|||
if constexpr (is_nothrow_move_constructible_v<_Err>) {
|
||||
_Err __tmp(std::move(__with_err.__union_.__unex_));
|
||||
std::destroy_at(std::addressof(__with_err.__union_.__unex_));
|
||||
__exception_guard __trans([&] {
|
||||
auto __trans = std::__make_exception_guard([&] {
|
||||
std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
|
||||
});
|
||||
std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
|
||||
|
|
@ -464,7 +465,7 @@ public:
|
|||
"that it can be reverted to the previous state in case an exception is thrown during swap.");
|
||||
_Tp __tmp(std::move(__with_val.__union_.__val_));
|
||||
std::destroy_at(std::addressof(__with_val.__union_.__val_));
|
||||
__exception_guard __trans([&] {
|
||||
auto __trans = std::__make_exception_guard([&] {
|
||||
std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp));
|
||||
});
|
||||
std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* _
|
|||
_Tp& __array = *__loc;
|
||||
|
||||
// If an exception is thrown, destroy what we have constructed so far in reverse order.
|
||||
__exception_guard __guard([&]() {
|
||||
auto __guard = std::__make_exception_guard([&]() {
|
||||
std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
|
||||
});
|
||||
|
||||
|
|
@ -461,7 +461,7 @@ constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* _
|
|||
_Tp& __array = *__loc;
|
||||
|
||||
// If an exception is thrown, destroy what we have constructed so far in reverse order.
|
||||
__exception_guard __guard([&]() {
|
||||
auto __guard = std::__make_exception_guard([&]() {
|
||||
std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
|
||||
});
|
||||
for (; __i != extent_v<_Tp>; ++__i) {
|
||||
|
|
@ -488,7 +488,7 @@ __uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __
|
|||
_BidirIter __begin = __it;
|
||||
|
||||
// If an exception is thrown, destroy what we have constructed so far in reverse order.
|
||||
__exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
|
||||
auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
|
||||
for (; __n != 0; --__n, ++__it) {
|
||||
std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value);
|
||||
}
|
||||
|
|
@ -505,7 +505,7 @@ __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _B
|
|||
_BidirIter __begin = __it;
|
||||
|
||||
// If an exception is thrown, destroy what we have constructed so far in reverse order.
|
||||
__exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
|
||||
auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
|
||||
for (; __n != 0; --__n, ++__it) {
|
||||
std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ public:
|
|||
template <class _Type, class... _CtorArgs>
|
||||
[[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) {
|
||||
_Type* __ptr = allocate_object<_Type>();
|
||||
__exception_guard __guard([&] { deallocate_object(__ptr); });
|
||||
auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); });
|
||||
construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...);
|
||||
__guard.__complete();
|
||||
return __ptr;
|
||||
|
|
|
|||
|
|
@ -60,25 +60,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
template <class _Rollback>
|
||||
struct __exception_guard {
|
||||
__exception_guard() = delete;
|
||||
struct __exception_guard_exceptions {
|
||||
__exception_guard_exceptions() = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __exception_guard(_Rollback __rollback)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __exception_guard_exceptions(_Rollback __rollback)
|
||||
: __rollback_(std::move(__rollback)), __completed_(false) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __exception_guard(__exception_guard&& __other)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
__exception_guard_exceptions(__exception_guard_exceptions&& __other)
|
||||
_NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value)
|
||||
: __rollback_(std::move(__other.__rollback_)), __completed_(__other.__completed_) {
|
||||
__other.__completed_ = true;
|
||||
}
|
||||
|
||||
__exception_guard(__exception_guard const&) = delete;
|
||||
__exception_guard& operator=(__exception_guard const&) = delete;
|
||||
__exception_guard& operator=(__exception_guard&&) = delete;
|
||||
__exception_guard_exceptions(__exception_guard_exceptions const&) = delete;
|
||||
__exception_guard_exceptions& operator=(__exception_guard_exceptions const&) = delete;
|
||||
__exception_guard_exceptions& operator=(__exception_guard_exceptions&&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __complete() _NOEXCEPT { __completed_ = true; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__exception_guard() {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__exception_guard_exceptions() {
|
||||
if (!__completed_)
|
||||
__rollback_();
|
||||
}
|
||||
|
|
@ -87,36 +88,46 @@ private:
|
|||
_Rollback __rollback_;
|
||||
bool __completed_;
|
||||
};
|
||||
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard_exceptions);
|
||||
|
||||
template <class _Rollback>
|
||||
using __exception_guard = __exception_guard_exceptions<_Rollback>;
|
||||
#else // _LIBCPP_NO_EXCEPTIONS
|
||||
template <class _Rollback>
|
||||
struct __exception_guard {
|
||||
__exception_guard() = delete;
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG explicit __exception_guard(_Rollback) {}
|
||||
struct __exception_guard_noexceptions {
|
||||
__exception_guard_noexceptions() = delete;
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_NODEBUG explicit __exception_guard_noexceptions(_Rollback) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG __exception_guard(__exception_guard&& __other)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG
|
||||
__exception_guard_noexceptions(__exception_guard_noexceptions&& __other)
|
||||
_NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value)
|
||||
: __completed_(__other.__completed_) {
|
||||
__other.__completed_ = true;
|
||||
}
|
||||
|
||||
__exception_guard(__exception_guard const&) = delete;
|
||||
__exception_guard& operator=(__exception_guard const&) = delete;
|
||||
__exception_guard& operator=(__exception_guard&&) = delete;
|
||||
__exception_guard_noexceptions(__exception_guard_noexceptions const&) = delete;
|
||||
__exception_guard_noexceptions& operator=(__exception_guard_noexceptions const&) = delete;
|
||||
__exception_guard_noexceptions& operator=(__exception_guard_noexceptions&&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG void __complete() _NOEXCEPT {
|
||||
__completed_ = true;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG ~__exception_guard() {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG ~__exception_guard_noexceptions() {
|
||||
_LIBCPP_ASSERT(__completed_, "__exception_guard not completed with exceptions disabled");
|
||||
}
|
||||
|
||||
private:
|
||||
bool __completed_ = false;
|
||||
};
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard);
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard_noexceptions);
|
||||
|
||||
template <class _Rollback>
|
||||
using __exception_guard = __exception_guard_noexceptions<_Rollback>;
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
|
||||
template <class _Rollback>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exception_guard(_Rollback __rollback) {
|
||||
|
|
|
|||
|
|
@ -6,5 +6,8 @@ module libunwind [system] {
|
|||
module unwind [system] {
|
||||
header "__libunwind_config.h"
|
||||
header "unwind.h"
|
||||
private textual header "unwind_arm_ehabi.h"
|
||||
private textual header "unwind_itanium.h"
|
||||
|
||||
export *
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ typedef enum {
|
|||
typedef struct _Unwind_Context _Unwind_Context; // opaque
|
||||
|
||||
#if defined(_LIBUNWIND_ARM_EHABI)
|
||||
#include "unwind_arm_ehabi.h"
|
||||
#include <unwind_arm_ehabi.h>
|
||||
#else
|
||||
#include "unwind_itanium.h"
|
||||
#include <unwind_itanium.h>
|
||||
#endif
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
|
|||
p &= ~0xfULL;
|
||||
// CFA is the bottom of the current stack frame.
|
||||
for (; p < cfa; p += 16) {
|
||||
__asm__ __volatile__(".arch_extension memtag\n"
|
||||
__asm__ __volatile__(".arch armv8.5-a\n"
|
||||
".arch_extension memtag\n"
|
||||
"stg %[Ptr], [%[Ptr]]\n"
|
||||
:
|
||||
: [Ptr] "r"(p)
|
||||
|
|
|
|||
|
|
@ -194,9 +194,20 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
|
|||
addi 4, 3, PPC64_OFFS_FP
|
||||
|
||||
// load VS register
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
// For little-endian targets, we need a swap since lxvd2x will load the register
|
||||
// in the incorrect doubleword order.
|
||||
// FIXME: when supporting targets older than Power9 on LE is no longer required,
|
||||
// this can be changed to simply `lxv n, (16 * n)(4)`.
|
||||
#define PPC64_LVS(n) \
|
||||
lxvd2x n, 0, 4 ;\
|
||||
xxswapd n, n ;\
|
||||
addi 4, 4, 16
|
||||
#else
|
||||
#define PPC64_LVS(n) \
|
||||
lxvd2x n, 0, 4 ;\
|
||||
addi 4, 4, 16
|
||||
#endif
|
||||
|
||||
// restore the first 32 VS regs (and also all floating point regs)
|
||||
PPC64_LVS(0)
|
||||
|
|
@ -232,9 +243,16 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
|
|||
PPC64_LVS(30)
|
||||
PPC64_LVS(31)
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define PPC64_CLVS_RESTORE(n) \
|
||||
addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
|
||||
lxvd2x n, 0, 4 ;\
|
||||
xxswapd n, n
|
||||
#else
|
||||
#define PPC64_CLVS_RESTORE(n) \
|
||||
addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
|
||||
lxvd2x n, 0, 4
|
||||
#endif
|
||||
|
||||
#if !defined(_AIX)
|
||||
// use VRSAVE to conditionally restore the remaining VS regs, that are
|
||||
|
|
|
|||
|
|
@ -351,9 +351,20 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
|
|||
addi 4, 3, PPC64_OFFS_FP
|
||||
|
||||
// store VS register
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
// For little-endian targets, we need a swap since stxvd2x will store the
|
||||
// register in the incorrect doubleword order.
|
||||
// FIXME: when supporting targets older than Power9 on LE is no longer required
|
||||
// this can be changed to simply `stxv n, 16 * n(4)`.
|
||||
#define PPC64_STVS(n) \
|
||||
xxswapd n, n ;\
|
||||
stxvd2x n, 0, 4 ;\
|
||||
addi 4, 4, 16
|
||||
#else
|
||||
#define PPC64_STVS(n) \
|
||||
stxvd2x n, 0, 4 ;\
|
||||
addi 4, 4, 16
|
||||
#endif
|
||||
|
||||
PPC64_STVS(0)
|
||||
PPC64_STVS(1)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ AutoExporter::AutoExporter(
|
|||
"libclang_rt.profile-x86_64",
|
||||
"libc++",
|
||||
"libc++abi",
|
||||
"libFortran_main",
|
||||
"libFortranRuntime",
|
||||
"libFortranDecimal",
|
||||
"libunwind",
|
||||
"libmsvcrt",
|
||||
"libucrtbase",
|
||||
|
|
|
|||
|
|
@ -114,13 +114,13 @@ public:
|
|||
|
||||
static unsigned RelocSymbol64(const ELFRelocation &rel);
|
||||
|
||||
static unsigned RelocOffset32(const ELFRelocation &rel);
|
||||
static elf_addr RelocOffset32(const ELFRelocation &rel);
|
||||
|
||||
static unsigned RelocOffset64(const ELFRelocation &rel);
|
||||
static elf_addr RelocOffset64(const ELFRelocation &rel);
|
||||
|
||||
static unsigned RelocAddend32(const ELFRelocation &rel);
|
||||
static elf_sxword RelocAddend32(const ELFRelocation &rel);
|
||||
|
||||
static unsigned RelocAddend64(const ELFRelocation &rel);
|
||||
static elf_sxword RelocAddend64(const ELFRelocation &rel);
|
||||
|
||||
bool IsRela() { return (reloc.is<ELFRela *>()); }
|
||||
|
||||
|
|
@ -185,28 +185,28 @@ unsigned ELFRelocation::RelocSymbol64(const ELFRelocation &rel) {
|
|||
return ELFRela::RelocSymbol64(*rel.reloc.get<ELFRela *>());
|
||||
}
|
||||
|
||||
unsigned ELFRelocation::RelocOffset32(const ELFRelocation &rel) {
|
||||
elf_addr ELFRelocation::RelocOffset32(const ELFRelocation &rel) {
|
||||
if (rel.reloc.is<ELFRel *>())
|
||||
return rel.reloc.get<ELFRel *>()->r_offset;
|
||||
else
|
||||
return rel.reloc.get<ELFRela *>()->r_offset;
|
||||
}
|
||||
|
||||
unsigned ELFRelocation::RelocOffset64(const ELFRelocation &rel) {
|
||||
elf_addr ELFRelocation::RelocOffset64(const ELFRelocation &rel) {
|
||||
if (rel.reloc.is<ELFRel *>())
|
||||
return rel.reloc.get<ELFRel *>()->r_offset;
|
||||
else
|
||||
return rel.reloc.get<ELFRela *>()->r_offset;
|
||||
}
|
||||
|
||||
unsigned ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
|
||||
elf_sxword ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
|
||||
if (rel.reloc.is<ELFRel *>())
|
||||
return 0;
|
||||
else
|
||||
return rel.reloc.get<ELFRela *>()->r_addend;
|
||||
}
|
||||
|
||||
unsigned ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
|
||||
elf_sxword ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
|
||||
if (rel.reloc.is<ELFRel *>())
|
||||
return 0;
|
||||
else
|
||||
|
|
@ -2593,6 +2593,50 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
|
|||
rel_data, symtab_data, strtab_data);
|
||||
}
|
||||
|
||||
static void ApplyELF64ABS64Relocation(Symtab *symtab, ELFRelocation &rel,
|
||||
DataExtractor &debug_data,
|
||||
Section *rel_section) {
|
||||
Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol64(rel));
|
||||
if (symbol) {
|
||||
addr_t value = symbol->GetAddressRef().GetFileAddress();
|
||||
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
|
||||
// ObjectFileELF creates a WritableDataBuffer in CreateInstance.
|
||||
WritableDataBuffer *data_buffer =
|
||||
llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
|
||||
uint64_t *dst = reinterpret_cast<uint64_t *>(
|
||||
data_buffer->GetBytes() + rel_section->GetFileOffset() +
|
||||
ELFRelocation::RelocOffset64(rel));
|
||||
uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
|
||||
memcpy(dst, &val_offset, sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel,
|
||||
DataExtractor &debug_data,
|
||||
Section *rel_section, bool is_signed) {
|
||||
Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol64(rel));
|
||||
if (symbol) {
|
||||
addr_t value = symbol->GetAddressRef().GetFileAddress();
|
||||
value += ELFRelocation::RelocAddend32(rel);
|
||||
if ((!is_signed && (value > UINT32_MAX)) ||
|
||||
(is_signed &&
|
||||
((int64_t)value > INT32_MAX || (int64_t)value < INT32_MIN))) {
|
||||
Log *log = GetLog(LLDBLog::Modules);
|
||||
LLDB_LOGF(log, "Failed to apply debug info relocations");
|
||||
return;
|
||||
}
|
||||
uint32_t truncated_addr = (value & 0xFFFFFFFF);
|
||||
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
|
||||
// ObjectFileELF creates a WritableDataBuffer in CreateInstance.
|
||||
WritableDataBuffer *data_buffer =
|
||||
llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
|
||||
uint32_t *dst = reinterpret_cast<uint32_t *>(
|
||||
data_buffer->GetBytes() + rel_section->GetFileOffset() +
|
||||
ELFRelocation::RelocOffset32(rel));
|
||||
memcpy(dst, &truncated_addr, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ObjectFileELF::ApplyRelocations(
|
||||
Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
|
||||
const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
|
||||
|
|
@ -2656,55 +2700,50 @@ unsigned ObjectFileELF::ApplyRelocations(
|
|||
reloc_type(rel));
|
||||
}
|
||||
} else {
|
||||
switch (reloc_type(rel)) {
|
||||
case R_AARCH64_ABS64:
|
||||
case R_X86_64_64: {
|
||||
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
|
||||
if (symbol) {
|
||||
addr_t value = symbol->GetAddressRef().GetFileAddress();
|
||||
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
|
||||
// ObjectFileELF creates a WritableDataBuffer in CreateInstance.
|
||||
WritableDataBuffer *data_buffer =
|
||||
llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
|
||||
uint64_t *dst = reinterpret_cast<uint64_t *>(
|
||||
data_buffer->GetBytes() + rel_section->GetFileOffset() +
|
||||
ELFRelocation::RelocOffset64(rel));
|
||||
uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
|
||||
memcpy(dst, &val_offset, sizeof(uint64_t));
|
||||
switch (hdr->e_machine) {
|
||||
case llvm::ELF::EM_AARCH64:
|
||||
switch (reloc_type(rel)) {
|
||||
case R_AARCH64_ABS64:
|
||||
ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section);
|
||||
break;
|
||||
case R_AARCH64_ABS32:
|
||||
ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true);
|
||||
break;
|
||||
default:
|
||||
assert(false && "unexpected relocation type");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R_X86_64_32:
|
||||
case R_X86_64_32S:
|
||||
case R_AARCH64_ABS32: {
|
||||
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
|
||||
if (symbol) {
|
||||
addr_t value = symbol->GetAddressRef().GetFileAddress();
|
||||
value += ELFRelocation::RelocAddend32(rel);
|
||||
if ((reloc_type(rel) == R_X86_64_32 && (value > UINT32_MAX)) ||
|
||||
(reloc_type(rel) == R_X86_64_32S &&
|
||||
((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN)) ||
|
||||
(reloc_type(rel) == R_AARCH64_ABS32 &&
|
||||
((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) {
|
||||
Log *log = GetLog(LLDBLog::Modules);
|
||||
LLDB_LOGF(log, "Failed to apply debug info relocations");
|
||||
break;
|
||||
}
|
||||
uint32_t truncated_addr = (value & 0xFFFFFFFF);
|
||||
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
|
||||
// ObjectFileELF creates a WritableDataBuffer in CreateInstance.
|
||||
WritableDataBuffer *data_buffer =
|
||||
llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
|
||||
uint32_t *dst = reinterpret_cast<uint32_t *>(
|
||||
data_buffer->GetBytes() + rel_section->GetFileOffset() +
|
||||
ELFRelocation::RelocOffset32(rel));
|
||||
memcpy(dst, &truncated_addr, sizeof(uint32_t));
|
||||
case llvm::ELF::EM_LOONGARCH:
|
||||
switch (reloc_type(rel)) {
|
||||
case R_LARCH_64:
|
||||
ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section);
|
||||
break;
|
||||
case R_LARCH_32:
|
||||
ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true);
|
||||
break;
|
||||
default:
|
||||
assert(false && "unexpected relocation type");
|
||||
}
|
||||
break;
|
||||
case llvm::ELF::EM_X86_64:
|
||||
switch (reloc_type(rel)) {
|
||||
case R_X86_64_64:
|
||||
ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section);
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section,
|
||||
false);
|
||||
break;
|
||||
case R_X86_64_32S:
|
||||
ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true);
|
||||
break;
|
||||
case R_X86_64_PC32:
|
||||
default:
|
||||
assert(false && "unexpected relocation type");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R_X86_64_PC32:
|
||||
default:
|
||||
assert(false && "unexpected relocation type");
|
||||
assert(false && "unsupported machine");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,11 @@ public:
|
|||
uint64_t start() const { return Start; }
|
||||
uint64_t end() const { return End; }
|
||||
uint64_t size() const { return End - Start; }
|
||||
uint64_t empty() const { return size() == 0; }
|
||||
bool contains(uint64_t Addr) const { return Start <= Addr && Addr < End; }
|
||||
bool contains(const AddressRange &R) const {
|
||||
return Start <= R.Start && R.End <= End;
|
||||
}
|
||||
bool intersects(const AddressRange &R) const {
|
||||
return Start < R.End && R.Start < End;
|
||||
}
|
||||
|
|
@ -45,101 +49,163 @@ private:
|
|||
uint64_t End = 0;
|
||||
};
|
||||
|
||||
/// The AddressRanges class helps normalize address range collections.
|
||||
/// This class keeps a sorted vector of AddressRange objects and can perform
|
||||
/// insertions and searches efficiently. The address ranges are always sorted
|
||||
/// and never contain any invalid or empty address ranges.
|
||||
/// Intersecting([100,200), [150,300)) and adjacent([100,200), [200,300))
|
||||
/// address ranges are combined during insertion.
|
||||
class AddressRanges {
|
||||
/// The AddressRangesBase class presents the base functionality for the
|
||||
/// normalized address ranges collection. This class keeps a sorted vector
|
||||
/// of AddressRange-like objects and can perform searches efficiently.
|
||||
/// The address ranges are always sorted and never contain any invalid,
|
||||
/// empty or intersected address ranges.
|
||||
|
||||
template <typename T> class AddressRangesBase {
|
||||
protected:
|
||||
using Collection = SmallVector<AddressRange>;
|
||||
using Collection = SmallVector<T>;
|
||||
Collection Ranges;
|
||||
|
||||
public:
|
||||
void clear() { Ranges.clear(); }
|
||||
bool empty() const { return Ranges.empty(); }
|
||||
bool contains(uint64_t Addr) const { return find(Addr) != Ranges.end(); }
|
||||
bool contains(AddressRange Range) const {
|
||||
return find(Range) != Ranges.end();
|
||||
bool contains(uint64_t Addr) const {
|
||||
return find(Addr, Addr + 1) != Ranges.end();
|
||||
}
|
||||
std::optional<AddressRange> getRangeThatContains(uint64_t Addr) const {
|
||||
Collection::const_iterator It = find(Addr);
|
||||
bool contains(AddressRange Range) const {
|
||||
return find(Range.start(), Range.end()) != Ranges.end();
|
||||
}
|
||||
void reserve(size_t Capacity) { Ranges.reserve(Capacity); }
|
||||
size_t size() const { return Ranges.size(); }
|
||||
|
||||
std::optional<T> getRangeThatContains(uint64_t Addr) const {
|
||||
typename Collection::const_iterator It = find(Addr, Addr + 1);
|
||||
if (It == Ranges.end())
|
||||
return std::nullopt;
|
||||
|
||||
return *It;
|
||||
}
|
||||
Collection::const_iterator insert(AddressRange Range);
|
||||
void reserve(size_t Capacity) { Ranges.reserve(Capacity); }
|
||||
size_t size() const { return Ranges.size(); }
|
||||
bool operator==(const AddressRanges &RHS) const {
|
||||
return Ranges == RHS.Ranges;
|
||||
}
|
||||
const AddressRange &operator[](size_t i) const {
|
||||
|
||||
typename Collection::const_iterator begin() const { return Ranges.begin(); }
|
||||
typename Collection::const_iterator end() const { return Ranges.end(); }
|
||||
|
||||
const T &operator[](size_t i) const {
|
||||
assert(i < Ranges.size());
|
||||
return Ranges[i];
|
||||
}
|
||||
Collection::const_iterator begin() const { return Ranges.begin(); }
|
||||
Collection::const_iterator end() const { return Ranges.end(); }
|
||||
|
||||
bool operator==(const AddressRangesBase<T> &RHS) const {
|
||||
return Ranges == RHS.Ranges;
|
||||
}
|
||||
|
||||
protected:
|
||||
Collection::const_iterator find(uint64_t Addr) const;
|
||||
Collection::const_iterator find(AddressRange Range) const;
|
||||
typename Collection::const_iterator find(uint64_t Start, uint64_t End) const {
|
||||
if (Start >= End)
|
||||
return Ranges.end();
|
||||
|
||||
auto It =
|
||||
std::partition_point(Ranges.begin(), Ranges.end(), [=](const T &R) {
|
||||
return AddressRange(R).start() <= Start;
|
||||
});
|
||||
|
||||
if (It == Ranges.begin())
|
||||
return Ranges.end();
|
||||
|
||||
--It;
|
||||
if (End > AddressRange(*It).end())
|
||||
return Ranges.end();
|
||||
|
||||
return It;
|
||||
}
|
||||
};
|
||||
|
||||
/// AddressRangesMap class maps values to the address ranges.
|
||||
/// It keeps address ranges and corresponding values. If ranges
|
||||
/// are combined during insertion, then combined range keeps
|
||||
/// newly inserted value.
|
||||
template <typename T> class AddressRangesMap : protected AddressRanges {
|
||||
/// The AddressRanges class helps normalize address range collections.
|
||||
/// This class keeps a sorted vector of AddressRange objects and can perform
|
||||
/// insertions and searches efficiently. Intersecting([100,200), [150,300))
|
||||
/// and adjacent([100,200), [200,300)) address ranges are combined during
|
||||
/// insertion.
|
||||
class AddressRanges : public AddressRangesBase<AddressRange> {
|
||||
public:
|
||||
void clear() {
|
||||
Ranges.clear();
|
||||
Values.clear();
|
||||
Collection::const_iterator insert(AddressRange Range) {
|
||||
if (Range.empty())
|
||||
return Ranges.end();
|
||||
|
||||
auto It = llvm::upper_bound(Ranges, Range);
|
||||
auto It2 = It;
|
||||
while (It2 != Ranges.end() && It2->start() <= Range.end())
|
||||
++It2;
|
||||
if (It != It2) {
|
||||
Range = {Range.start(), std::max(Range.end(), std::prev(It2)->end())};
|
||||
It = Ranges.erase(It, It2);
|
||||
}
|
||||
if (It != Ranges.begin() && Range.start() <= std::prev(It)->end()) {
|
||||
--It;
|
||||
*It = {It->start(), std::max(It->end(), Range.end())};
|
||||
return It;
|
||||
}
|
||||
|
||||
return Ranges.insert(It, Range);
|
||||
}
|
||||
bool empty() const { return AddressRanges::empty(); }
|
||||
bool contains(uint64_t Addr) const { return AddressRanges::contains(Addr); }
|
||||
bool contains(AddressRange Range) const {
|
||||
return AddressRanges::contains(Range);
|
||||
}
|
||||
void insert(AddressRange Range, T Value) {
|
||||
size_t InputSize = Ranges.size();
|
||||
Collection::const_iterator RangesIt = AddressRanges::insert(Range);
|
||||
if (RangesIt == Ranges.end())
|
||||
};
|
||||
|
||||
class AddressRangeValuePair {
|
||||
public:
|
||||
operator AddressRange() const { return Range; }
|
||||
|
||||
AddressRange Range;
|
||||
int64_t Value = 0;
|
||||
};
|
||||
|
||||
inline bool operator==(const AddressRangeValuePair &LHS,
|
||||
const AddressRangeValuePair &RHS) {
|
||||
return LHS.Range == RHS.Range && LHS.Value == RHS.Value;
|
||||
}
|
||||
|
||||
/// AddressRangesMap class maps values to the address ranges.
|
||||
/// It keeps normalized address ranges and corresponding values.
|
||||
/// This class keeps a sorted vector of AddressRangeValuePair objects
|
||||
/// and can perform insertions and searches efficiently.
|
||||
/// Intersecting([100,200), [150,300)) ranges splitted into non-conflicting
|
||||
/// parts([100,200), [200,300)). Adjacent([100,200), [200,300)) address
|
||||
/// ranges are not combined during insertion.
|
||||
class AddressRangesMap : public AddressRangesBase<AddressRangeValuePair> {
|
||||
public:
|
||||
void insert(AddressRange Range, int64_t Value) {
|
||||
if (Range.empty())
|
||||
return;
|
||||
|
||||
// make Values match to Ranges.
|
||||
size_t Idx = RangesIt - Ranges.begin();
|
||||
typename ValuesCollection::iterator ValuesIt = Values.begin() + Idx;
|
||||
if (InputSize < Ranges.size())
|
||||
Values.insert(ValuesIt, T());
|
||||
else if (InputSize > Ranges.size())
|
||||
Values.erase(ValuesIt, ValuesIt + InputSize - Ranges.size());
|
||||
assert(Ranges.size() == Values.size());
|
||||
// Search for range which is less than or equal incoming Range.
|
||||
auto It = std::partition_point(Ranges.begin(), Ranges.end(),
|
||||
[=](const AddressRangeValuePair &R) {
|
||||
return R.Range.start() <= Range.start();
|
||||
});
|
||||
|
||||
// set value to the inserted or combined range.
|
||||
Values[Idx] = Value;
|
||||
}
|
||||
size_t size() const {
|
||||
assert(Ranges.size() == Values.size());
|
||||
return AddressRanges::size();
|
||||
}
|
||||
std::optional<std::pair<AddressRange, T>>
|
||||
getRangeValueThatContains(uint64_t Addr) const {
|
||||
Collection::const_iterator It = find(Addr);
|
||||
if (It == Ranges.end())
|
||||
return std::nullopt;
|
||||
if (It != Ranges.begin())
|
||||
It--;
|
||||
|
||||
return std::make_pair(*It, Values[It - Ranges.begin()]);
|
||||
}
|
||||
std::pair<AddressRange, T> operator[](size_t Idx) const {
|
||||
return std::make_pair(Ranges[Idx], Values[Idx]);
|
||||
}
|
||||
while (!Range.empty()) {
|
||||
// Inserted range does not overlap with any range.
|
||||
// Store it into the Ranges collection.
|
||||
if (It == Ranges.end() || Range.end() <= It->Range.start()) {
|
||||
Ranges.insert(It, {Range, Value});
|
||||
return;
|
||||
}
|
||||
|
||||
protected:
|
||||
using ValuesCollection = SmallVector<T>;
|
||||
ValuesCollection Values;
|
||||
// Inserted range partially overlaps with current range.
|
||||
// Store not overlapped part of inserted range.
|
||||
if (Range.start() < It->Range.start()) {
|
||||
It = Ranges.insert(It, {{Range.start(), It->Range.start()}, Value});
|
||||
It++;
|
||||
Range = {It->Range.start(), Range.end()};
|
||||
continue;
|
||||
}
|
||||
|
||||
// Inserted range fully overlaps with current range.
|
||||
if (Range.end() <= It->Range.end())
|
||||
return;
|
||||
|
||||
// Inserted range partially overlaps with current range.
|
||||
// Remove overlapped part from the inserted range.
|
||||
if (Range.start() < It->Range.end())
|
||||
Range = {It->Range.end(), Range.end()};
|
||||
|
||||
It++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class DeclContext;
|
|||
|
||||
/// Mapped value in the address map is the offset to apply to the
|
||||
/// linked address.
|
||||
using RangesTy = AddressRangesMap<int64_t>;
|
||||
using RangesTy = AddressRangesMap;
|
||||
|
||||
// FIXME: Delete this structure.
|
||||
struct PatchLocation {
|
||||
|
|
|
|||
|
|
@ -1659,7 +1659,7 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
|
|||
DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
|
||||
OrigDwarf.getDWARFObj().getRangesSection(),
|
||||
OrigDwarf.isLittleEndian(), AddressSize);
|
||||
std::optional<std::pair<AddressRange, int64_t>> CachedRange;
|
||||
std::optional<AddressRangeValuePair> CachedRange;
|
||||
DWARFUnit &OrigUnit = Unit.getOrigUnit();
|
||||
auto OrigUnitDie = OrigUnit.getUnitDIE(false);
|
||||
uint64_t UnitBaseAddress =
|
||||
|
|
@ -1687,9 +1687,9 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
|
|||
}
|
||||
|
||||
if (!CachedRange ||
|
||||
!CachedRange->first.contains(Range.StartAddress + BaseAddress))
|
||||
CachedRange = FunctionRanges.getRangeValueThatContains(
|
||||
Range.StartAddress + BaseAddress);
|
||||
!CachedRange->Range.contains(Range.StartAddress + BaseAddress))
|
||||
CachedRange = FunctionRanges.getRangeThatContains(Range.StartAddress +
|
||||
BaseAddress);
|
||||
|
||||
// All range entries should lie in the function range.
|
||||
if (!CachedRange) {
|
||||
|
|
@ -1698,8 +1698,8 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
|
|||
}
|
||||
|
||||
LinkedRanges.insert(
|
||||
{Range.StartAddress + BaseAddress + CachedRange->second,
|
||||
Range.EndAddress + BaseAddress + CachedRange->second});
|
||||
{Range.StartAddress + BaseAddress + CachedRange->Value,
|
||||
Range.EndAddress + BaseAddress + CachedRange->Value});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1802,7 +1802,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
|
|||
// in NewRows.
|
||||
std::vector<DWARFDebugLine::Row> Seq;
|
||||
const auto &FunctionRanges = Unit.getFunctionRanges();
|
||||
std::optional<std::pair<AddressRange, int64_t>> CurrRange;
|
||||
std::optional<AddressRangeValuePair> CurrRange;
|
||||
|
||||
// FIXME: This logic is meant to generate exactly the same output as
|
||||
// Darwin's classic dsymutil. There is a nicer way to implement this
|
||||
|
|
@ -1821,13 +1821,13 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
|
|||
// it is marked as end_sequence in the input (because in that
|
||||
// case, the relocation offset is accurate and that entry won't
|
||||
// serve as the start of another function).
|
||||
if (!CurrRange || !CurrRange->first.contains(Row.Address.Address) ||
|
||||
(Row.Address.Address == CurrRange->first.end() && !Row.EndSequence)) {
|
||||
if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address) ||
|
||||
(Row.Address.Address == CurrRange->Range.end() && !Row.EndSequence)) {
|
||||
// We just stepped out of a known range. Insert a end_sequence
|
||||
// corresponding to the end of the range.
|
||||
uint64_t StopAddress =
|
||||
CurrRange ? CurrRange->first.end() + CurrRange->second : -1ULL;
|
||||
CurrRange = FunctionRanges.getRangeValueThatContains(Row.Address.Address);
|
||||
CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
|
||||
CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
|
||||
if (!CurrRange) {
|
||||
if (StopAddress != -1ULL) {
|
||||
// Try harder by looking in the Address ranges map.
|
||||
|
|
@ -1836,9 +1836,9 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
|
|||
// for now do as dsymutil.
|
||||
// FIXME: Understand exactly what cases this addresses and
|
||||
// potentially remove it along with the Ranges map.
|
||||
if (std::optional<std::pair<AddressRange, int64_t>> Range =
|
||||
Ranges.getRangeValueThatContains(Row.Address.Address))
|
||||
StopAddress = Row.Address.Address + (*Range).second;
|
||||
if (std::optional<AddressRangeValuePair> Range =
|
||||
Ranges.getRangeThatContains(Row.Address.Address))
|
||||
StopAddress = Row.Address.Address + (*Range).Value;
|
||||
}
|
||||
}
|
||||
if (StopAddress != -1ULL && !Seq.empty()) {
|
||||
|
|
@ -1863,7 +1863,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
|
|||
continue;
|
||||
|
||||
// Relocate row address and add it to the current sequence.
|
||||
Row.Address.Address += CurrRange->second;
|
||||
Row.Address.Address += CurrRange->Value;
|
||||
Seq.emplace_back(Row);
|
||||
|
||||
if (Row.EndSequence)
|
||||
|
|
@ -2002,8 +2002,8 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
|
|||
// the function entry point, thus we can't just lookup the address
|
||||
// in the debug map. Use the AddressInfo's range map to see if the FDE
|
||||
// describes something that we can relocate.
|
||||
std::optional<std::pair<AddressRange, int64_t>> Range =
|
||||
Ranges.getRangeValueThatContains(Loc);
|
||||
std::optional<AddressRangeValuePair> Range =
|
||||
Ranges.getRangeThatContains(Loc);
|
||||
if (!Range) {
|
||||
// The +4 is to account for the size of the InitialLength field itself.
|
||||
InputOffset = EntryOffset + InitialLength + 4;
|
||||
|
|
@ -2032,7 +2032,7 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
|
|||
// fields that will get reconstructed by emitFDE().
|
||||
unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
|
||||
TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), AddrSize,
|
||||
Loc + Range->second,
|
||||
Loc + Range->Value,
|
||||
FrameData.substr(InputOffset, FDERemainingBytes));
|
||||
InputOffset += FDERemainingBytes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,10 +402,9 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
|
|||
// Linked addresses might end up in a different order.
|
||||
// Build linked address ranges.
|
||||
AddressRanges LinkedRanges;
|
||||
for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
|
||||
for (const AddressRangeValuePair &Range : FunctionRanges)
|
||||
LinkedRanges.insert(
|
||||
{FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
|
||||
FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});
|
||||
{Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});
|
||||
|
||||
if (!FunctionRanges.empty())
|
||||
emitDwarfDebugArangesTable(Unit, LinkedRanges);
|
||||
|
|
|
|||
|
|
@ -552,6 +552,7 @@ void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
|
|||
Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
|
||||
".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
|
||||
aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
|
||||
Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
|
||||
|
||||
// Add a mark-live pass.
|
||||
if (auto MarkLive = Ctx->getMarkLivePass(TT))
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/IntrinsicsAArch64.h"
|
||||
#include "llvm/IR/IntrinsicsARM.h"
|
||||
#include "llvm/IR/IntrinsicsWebAssembly.h"
|
||||
#include "llvm/IR/IntrinsicsX86.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
|
@ -1125,6 +1126,40 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
|
|||
break;
|
||||
}
|
||||
|
||||
case 'w':
|
||||
if (Name.startswith("wasm.fma.")) {
|
||||
rename(F);
|
||||
NewFn = Intrinsic::getDeclaration(
|
||||
F->getParent(), Intrinsic::wasm_relaxed_madd, F->getReturnType());
|
||||
return true;
|
||||
}
|
||||
if (Name.startswith("wasm.fms.")) {
|
||||
rename(F);
|
||||
NewFn = Intrinsic::getDeclaration(
|
||||
F->getParent(), Intrinsic::wasm_relaxed_nmadd, F->getReturnType());
|
||||
return true;
|
||||
}
|
||||
if (Name.startswith("wasm.laneselect.")) {
|
||||
rename(F);
|
||||
NewFn = Intrinsic::getDeclaration(
|
||||
F->getParent(), Intrinsic::wasm_relaxed_laneselect,
|
||||
F->getReturnType());
|
||||
return true;
|
||||
}
|
||||
if (Name == "wasm.dot.i8x16.i7x16.signed") {
|
||||
rename(F);
|
||||
NewFn = Intrinsic::getDeclaration(
|
||||
F->getParent(), Intrinsic::wasm_relaxed_dot_i8x16_i7x16_signed);
|
||||
return true;
|
||||
}
|
||||
if (Name == "wasm.dot.i8x16.i7x16.add.signed") {
|
||||
rename(F);
|
||||
NewFn = Intrinsic::getDeclaration(
|
||||
F->getParent(), Intrinsic::wasm_relaxed_dot_i8x16_i7x16_add_signed);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
if (UpgradeX86IntrinsicFunction(F, Name, NewFn))
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1685,6 +1685,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
|
|||
// keep one copy of each constant.
|
||||
MPM.addPass(ConstantMergePass());
|
||||
|
||||
// Remove unused arguments from functions.
|
||||
MPM.addPass(DeadArgumentEliminationPass());
|
||||
|
||||
// Reduce the code after globalopt and ipsccp. Both can open up significant
|
||||
// simplification opportunities, and both can propagate functions through
|
||||
// function pointers. When this happens, we often have to resolve varargs
|
||||
|
|
@ -1722,9 +1725,6 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
|
|||
// transform it to pass arguments by value instead of by reference.
|
||||
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(ArgumentPromotionPass()));
|
||||
|
||||
// Remove unused arguments from functions.
|
||||
MPM.addPass(DeadArgumentEliminationPass());
|
||||
|
||||
FunctionPassManager FPM;
|
||||
// The IPO Passes may leave cruft around. Clean up after them.
|
||||
FPM.addPass(InstCombinePass());
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
//===- AddressRanges.cpp ----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/AddressRanges.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
AddressRanges::Collection::const_iterator
|
||||
AddressRanges::insert(AddressRange Range) {
|
||||
if (Range.size() == 0)
|
||||
return Ranges.end();
|
||||
|
||||
auto It = llvm::upper_bound(Ranges, Range);
|
||||
auto It2 = It;
|
||||
while (It2 != Ranges.end() && It2->start() <= Range.end())
|
||||
++It2;
|
||||
if (It != It2) {
|
||||
Range = {Range.start(), std::max(Range.end(), std::prev(It2)->end())};
|
||||
It = Ranges.erase(It, It2);
|
||||
}
|
||||
if (It != Ranges.begin() && Range.start() <= std::prev(It)->end()) {
|
||||
--It;
|
||||
*It = {It->start(), std::max(It->end(), Range.end())};
|
||||
return It;
|
||||
}
|
||||
|
||||
return Ranges.insert(It, Range);
|
||||
}
|
||||
|
||||
AddressRanges::Collection::const_iterator
|
||||
AddressRanges::find(uint64_t Addr) const {
|
||||
auto It = std::partition_point(
|
||||
Ranges.begin(), Ranges.end(),
|
||||
[=](const AddressRange &R) { return R.start() <= Addr; });
|
||||
|
||||
if (It == Ranges.begin())
|
||||
return Ranges.end();
|
||||
|
||||
--It;
|
||||
if (Addr >= It->end())
|
||||
return Ranges.end();
|
||||
|
||||
return It;
|
||||
}
|
||||
|
||||
AddressRanges::Collection::const_iterator
|
||||
AddressRanges::find(AddressRange Range) const {
|
||||
if (Range.size() == 0)
|
||||
return Ranges.end();
|
||||
|
||||
auto It = std::partition_point(
|
||||
Ranges.begin(), Ranges.end(),
|
||||
[=](const AddressRange &R) { return R.start() <= Range.start(); });
|
||||
|
||||
if (It == Ranges.begin())
|
||||
return Ranges.end();
|
||||
|
||||
--It;
|
||||
if (Range.end() > It->end())
|
||||
return Ranges.end();
|
||||
|
||||
return It;
|
||||
}
|
||||
|
|
@ -782,6 +782,17 @@ void BTFDebug::visitCompositeType(const DICompositeType *CTy,
|
|||
visitEnumType(CTy, TypeId);
|
||||
}
|
||||
|
||||
bool BTFDebug::IsForwardDeclCandidate(const DIType *Base) {
|
||||
if (const auto *CTy = dyn_cast<DICompositeType>(Base)) {
|
||||
auto CTag = CTy->getTag();
|
||||
if ((CTag == dwarf::DW_TAG_structure_type ||
|
||||
CTag == dwarf::DW_TAG_union_type) &&
|
||||
!CTy->getName().empty() && !CTy->isForwardDecl())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Handle pointer, typedef, const, volatile, restrict and member types.
|
||||
void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
|
||||
bool CheckPointer, bool SeenPointer) {
|
||||
|
|
@ -796,20 +807,15 @@ void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
|
|||
if (CheckPointer && SeenPointer) {
|
||||
const DIType *Base = DTy->getBaseType();
|
||||
if (Base) {
|
||||
if (const auto *CTy = dyn_cast<DICompositeType>(Base)) {
|
||||
auto CTag = CTy->getTag();
|
||||
if ((CTag == dwarf::DW_TAG_structure_type ||
|
||||
CTag == dwarf::DW_TAG_union_type) &&
|
||||
!CTy->getName().empty() && !CTy->isForwardDecl()) {
|
||||
/// Find a candidate, generate a fixup. Later on the struct/union
|
||||
/// pointee type will be replaced with either a real type or
|
||||
/// a forward declaration.
|
||||
auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, true);
|
||||
auto &Fixup = FixupDerivedTypes[CTy];
|
||||
Fixup.push_back(std::make_pair(DTy, TypeEntry.get()));
|
||||
TypeId = addType(std::move(TypeEntry), DTy);
|
||||
return;
|
||||
}
|
||||
if (IsForwardDeclCandidate(Base)) {
|
||||
/// Find a candidate, generate a fixup. Later on the struct/union
|
||||
/// pointee type will be replaced with either a real type or
|
||||
/// a forward declaration.
|
||||
auto TypeEntry = std::make_unique<BTFTypeDerived>(DTy, Tag, true);
|
||||
auto &Fixup = FixupDerivedTypes[cast<DICompositeType>(Base)];
|
||||
Fixup.push_back(std::make_pair(DTy, TypeEntry.get()));
|
||||
TypeId = addType(std::move(TypeEntry), DTy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -844,6 +850,13 @@ void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
|
|||
visitTypeEntry(DTy->getBaseType(), TempTypeId, CheckPointer, SeenPointer);
|
||||
}
|
||||
|
||||
/// Visit a type entry. CheckPointer is true if the type has
|
||||
/// one of its predecessors as one struct/union member. SeenPointer
|
||||
/// is true if CheckPointer is true and one of its predecessors
|
||||
/// is a pointer. The goal of CheckPointer and SeenPointer is to
|
||||
/// do pruning for struct/union types so some of these types
|
||||
/// will not be emitted in BTF and rather forward declarations
|
||||
/// will be generated.
|
||||
void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId,
|
||||
bool CheckPointer, bool SeenPointer) {
|
||||
if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) {
|
||||
|
|
@ -888,6 +901,11 @@ void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId,
|
|||
if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) {
|
||||
DTy = dyn_cast<DIDerivedType>(BaseTy);
|
||||
} else {
|
||||
if (CheckPointer && DTy->getTag() == dwarf::DW_TAG_pointer_type) {
|
||||
SeenPointer = true;
|
||||
if (IsForwardDeclCandidate(BaseTy))
|
||||
break;
|
||||
}
|
||||
uint32_t TmpTypeId;
|
||||
visitTypeEntry(BaseTy, TmpTypeId, CheckPointer, SeenPointer);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -338,6 +338,9 @@ class BTFDebug : public DebugHandlerBase {
|
|||
void visitMapDefType(const DIType *Ty, uint32_t &TypeId);
|
||||
/// @}
|
||||
|
||||
/// Check whether the type is a forward declaration candidate or not.
|
||||
bool IsForwardDeclCandidate(const DIType *Base);
|
||||
|
||||
/// Get the file content for the subprogram. Certain lines of the file
|
||||
/// later may be put into string table and referenced by line info.
|
||||
std::string populateFileContent(const DISubprogram *SP);
|
||||
|
|
|
|||
|
|
@ -239,6 +239,16 @@ bool RISCVELFStreamer::requiresFixups(MCContext &C, const MCExpr *Value,
|
|||
if (B.isInSection() && B.getSection().getKind().isText())
|
||||
return true;
|
||||
|
||||
// If A is undefined and B is defined, we should emit ADD/SUB for A-B.
|
||||
// Unfortunately, A may be defined later, but this requiresFixups call has to
|
||||
// eagerly make a decision. For now, emit ADD/SUB unless A is .L*. This
|
||||
// heuristic handles many temporary label differences for .debug_* and
|
||||
// .apple_types sections.
|
||||
//
|
||||
// TODO Implement delayed relocation decision.
|
||||
if (!A.isInSection() && !A.isTemporary() && B.isInSection())
|
||||
return true;
|
||||
|
||||
// Support cross-section symbolic differences ...
|
||||
return A.isInSection() && B.isInSection() &&
|
||||
A.getSection().getName() != B.getSection().getName();
|
||||
|
|
|
|||
|
|
@ -695,6 +695,7 @@ include "X86ScheduleSLM.td"
|
|||
include "X86ScheduleZnver1.td"
|
||||
include "X86ScheduleZnver2.td"
|
||||
include "X86ScheduleZnver3.td"
|
||||
include "X86ScheduleZnver4.td"
|
||||
include "X86ScheduleBdVer2.td"
|
||||
include "X86ScheduleBtVer2.td"
|
||||
include "X86SchedSkylakeClient.td"
|
||||
|
|
@ -1627,7 +1628,7 @@ def : ProcModel<"znver2", Znver2Model, ProcessorFeatures.ZN2Features,
|
|||
ProcessorFeatures.ZN2Tuning>;
|
||||
def : ProcModel<"znver3", Znver3Model, ProcessorFeatures.ZN3Features,
|
||||
ProcessorFeatures.ZN3Tuning>;
|
||||
def : Proc<"znver4",ProcessorFeatures.ZN4Features,
|
||||
def : ProcModel<"znver4", Znver4Model, ProcessorFeatures.ZN4Features,
|
||||
ProcessorFeatures.ZN4Tuning>;
|
||||
|
||||
def : Proc<"geode", [FeatureX87, FeatureCX8, Feature3DNowA],
|
||||
|
|
|
|||
|
|
@ -896,15 +896,15 @@ multiclass ATOMIC_LOGIC_OP<Format Form, string s> {
|
|||
multiclass ATOMIC_LOGIC_OP_RM<bits<8> Opc8, string s> {
|
||||
let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
|
||||
SchedRW = [WriteBitTestSetRegRMW] in {
|
||||
def 16rm : Ii8<Opc8, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2),
|
||||
def 16rm : I<Opc8, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2),
|
||||
!strconcat(s, "{w}\t{$src2, $src1|$src1, $src2}"),
|
||||
[(set EFLAGS, (!cast<SDNode>("x86_rm_" # s) addr:$src1, GR16:$src2))]>,
|
||||
OpSize16, TB, LOCK;
|
||||
def 32rm : Ii8<Opc8, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2),
|
||||
def 32rm : I<Opc8, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2),
|
||||
!strconcat(s, "{l}\t{$src2, $src1|$src1, $src2}"),
|
||||
[(set EFLAGS, (!cast<SDNode>("x86_rm_" # s) addr:$src1, GR32:$src2))]>,
|
||||
OpSize32, TB, LOCK;
|
||||
def 64rm : RIi8<Opc8, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2),
|
||||
def 64rm : RI<Opc8, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2),
|
||||
!strconcat(s, "{q}\t{$src2, $src1|$src1, $src2}"),
|
||||
[(set EFLAGS, (!cast<SDNode>("x86_rm_" # s) addr:$src1, GR64:$src2))]>,
|
||||
TB, LOCK;
|
||||
|
|
|
|||
|
|
@ -577,20 +577,37 @@ let Predicates = [HasAVX, NoVLX] in {
|
|||
|
||||
def : Pat<(alignedloadv8f16 addr:$src),
|
||||
(VMOVAPSrm addr:$src)>;
|
||||
def : Pat<(alignedloadv8bf16 addr:$src),
|
||||
(VMOVAPSrm addr:$src)>;
|
||||
def : Pat<(loadv8f16 addr:$src),
|
||||
(VMOVUPSrm addr:$src)>;
|
||||
def : Pat<(loadv8bf16 addr:$src),
|
||||
(VMOVUPSrm addr:$src)>;
|
||||
def : Pat<(alignedstore (v8f16 VR128:$src), addr:$dst),
|
||||
(VMOVAPSmr addr:$dst, VR128:$src)>;
|
||||
def : Pat<(alignedstore (v8bf16 VR128:$src), addr:$dst),
|
||||
(VMOVAPSmr addr:$dst, VR128:$src)>;
|
||||
def : Pat<(store (v8f16 VR128:$src), addr:$dst),
|
||||
(VMOVUPSmr addr:$dst, VR128:$src)>;
|
||||
def : Pat<(store (v8bf16 VR128:$src), addr:$dst),
|
||||
(VMOVUPSmr addr:$dst, VR128:$src)>;
|
||||
|
||||
def : Pat<(alignedloadv16f16 addr:$src),
|
||||
(VMOVAPSYrm addr:$src)>;
|
||||
def : Pat<(alignedloadv16bf16 addr:$src),
|
||||
(VMOVAPSYrm addr:$src)>;
|
||||
def : Pat<(loadv16f16 addr:$src),
|
||||
(VMOVUPSYrm addr:$src)>;
|
||||
def : Pat<(loadv16bf16 addr:$src),
|
||||
(VMOVUPSYrm addr:$src)>;
|
||||
def : Pat<(alignedstore (v16f16 VR256:$src), addr:$dst),
|
||||
(VMOVAPSYmr addr:$dst, VR256:$src)>;
|
||||
def : Pat<(alignedstore (v16bf16 VR256:$src), addr:$dst),
|
||||
(VMOVAPSYmr addr:$dst, VR256:$src)>;
|
||||
def : Pat<(store (v16f16 VR256:$src), addr:$dst),
|
||||
(VMOVUPSYmr addr:$dst, VR256:$src)>;
|
||||
def : Pat<(store (v16bf16 VR256:$src), addr:$dst),
|
||||
(VMOVUPSYmr addr:$dst, VR256:$src)>;
|
||||
}
|
||||
|
||||
// Use movaps / movups for SSE integer load / store (one byte shorter).
|
||||
|
|
|
|||
|
|
@ -290,4 +290,17 @@ def ZnVer3PfmCounters : ProcPfmCounters {
|
|||
];
|
||||
}
|
||||
def : PfmCountersBinding<"znver3", ZnVer3PfmCounters>;
|
||||
def : PfmCountersBinding<"znver4", ZnVer3PfmCounters>;
|
||||
|
||||
def ZnVer4PfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = PfmCounter<"cycles_not_in_halt">;
|
||||
let UopsCounter = PfmCounter<"retired_ops">;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"Zn4Int", "ops_type_dispatched_from_decoder:int_disp_retire_mode">,
|
||||
PfmIssueCounter<"Zn4FPU", "ops_type_dispatched_from_decoder:fp_disp_retire_mode">,
|
||||
PfmIssueCounter<"Zn4Load", "ls_dispatch:ld_dispatch">,
|
||||
PfmIssueCounter<"Zn4Store", "ls_dispatch:store_dispatch">,
|
||||
PfmIssueCounter<"Zn4Divider", "div_op_count">,
|
||||
PfmIssueCounter<"Zn4AGU", "ls_dispatch:ld_st_dispatch + ls_dispatch:ld_dispatch + ls_dispatch:store_dispatch">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"znver4", ZnVer4PfmCounters>;
|
||||
|
|
|
|||
1957
llvm/lib/Target/X86/X86ScheduleZnver4.td
Normal file
1957
llvm/lib/Target/X86/X86ScheduleZnver4.td
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -523,7 +523,7 @@ StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
|
|||
default:
|
||||
if (TT.isOSNetBSD())
|
||||
return "apcs-gnu";
|
||||
if (TT.isOSOpenBSD())
|
||||
if (TT.isOSFreeBSD() || TT.isOSOpenBSD())
|
||||
return "aapcs-linux";
|
||||
return "aapcs";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3184,16 +3184,6 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant(
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::And: {
|
||||
const APInt *BOC;
|
||||
if (match(BOp1, m_APInt(BOC))) {
|
||||
// If we have ((X & C) == C), turn it into ((X & C) != 0).
|
||||
if (C == *BOC && C.isPowerOf2())
|
||||
return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE,
|
||||
BO, Constant::getNullValue(RHS->getType()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::UDiv:
|
||||
if (C.isZero()) {
|
||||
// (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A)
|
||||
|
|
@ -5653,6 +5643,12 @@ Instruction *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Op0 eq C_Pow2 -> Op0 ne 0 if Op0 is known to be C_Pow2 or zero.
|
||||
if (Op1Known.isConstant() && Op1Known.getConstant().isPowerOf2() &&
|
||||
(Op0Known & Op1Known) == Op0Known)
|
||||
return new ICmpInst(CmpInst::getInversePredicate(Pred), Op0,
|
||||
ConstantInt::getNullValue(Op1->getType()));
|
||||
break;
|
||||
}
|
||||
case ICmpInst::ICMP_ULT: {
|
||||
|
|
|
|||
|
|
@ -145,10 +145,10 @@ def reloc : Flag<["--"], "reloc">,
|
|||
def : Flag<["-"], "r">, Alias<reloc>, HelpText<"Alias for --reloc">;
|
||||
|
||||
def print_imm_hex : Flag<["--"], "print-imm-hex">,
|
||||
HelpText<"Use hex format for immediate values">;
|
||||
HelpText<"Use hex format for immediate values (default)">;
|
||||
|
||||
def no_print_imm_hex : Flag<["--"], "no-print-imm-hex">,
|
||||
HelpText<"Do not use hex format for immediate values (default)">;
|
||||
HelpText<"Do not use hex format for immediate values">;
|
||||
def : Flag<["--"], "print-imm-hex=false">, Alias<no_print_imm_hex>;
|
||||
|
||||
def private_headers : Flag<["--"], "private-headers">,
|
||||
|
|
|
|||
Loading…
Reference in a new issue