Vendor import of llvm-project branch release/16.x llvmorg-16.0.0-45-g42d1b276f779.

This commit is contained in:
Dimitry Andric 2023-03-31 22:55:52 +02:00
parent 11ee15ea4e
commit 5bcd187b30
40 changed files with 2427 additions and 315 deletions

View file

@ -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<

View file

@ -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">;

View file

@ -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");

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -583,6 +583,7 @@ static void GetTls(uptr *addr, uptr *size) {
*addr = (uptr)tcb->tcb_dtv[1];
}
}
#else
#error "Unknown OS"
#endif
}

View file

@ -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);

View file

@ -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)

View file

@ -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_));

View file

@ -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));
}

View file

@ -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;

View file

@ -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) {

View file

@ -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 *
}

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -49,6 +49,9 @@ AutoExporter::AutoExporter(
"libclang_rt.profile-x86_64",
"libc++",
"libc++abi",
"libFortran_main",
"libFortranRuntime",
"libFortranDecimal",
"libunwind",
"libmsvcrt",
"libucrtbase",

View file

@ -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");
}
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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;
}

View file

@ -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);

View file

@ -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))

View file

@ -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;

View file

@ -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());

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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();

View file

@ -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],

View file

@ -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;

View file

@ -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).

View file

@ -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>;

File diff suppressed because it is too large Load diff

View file

@ -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";
}

View file

@ -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: {

View file

@ -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">,