Compare commits

...

3 Commits

Author SHA1 Message Date
Tom Stellard
d359f20968 Merging r333213:
------------------------------------------------------------------------
r333213 | ctopper | 2018-05-24 10:59:47 -0700 (Thu, 24 May 2018) | 16 lines

sanitizer: Use pre-computed size of struct ustat for Linux

<sys/ustat.h> has been removed from glibc 2.28 by:

commit cf2478d53ad7071e84c724a986b56fe17f4f4ca7
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Sun Mar 18 11:28:59 2018 +0800

Deprecate ustat syscall interface
This patch uses pre-computed size of struct ustat for Linux to fix

https://bugs.llvm.org/show_bug.cgi?id=37418

Patch by H.J. Lu.

Differential Revision: https://reviews.llvm.org/D47281
------------------------------------------------------------------------

llvm-svn: 334776
2018-06-14 22:33:33 +00:00
Tom Stellard
7daf52428c Merging r323390:
------------------------------------------------------------------------
r323390 | ericwf | 2018-01-24 16:02:48 -0800 (Wed, 24 Jan 2018) | 9 lines

Fix PR35564 - std::list splice/erase incorrectly throw in debug mode.

There was a bug in the implementation of splice where the container
sizes were updated before decrementing one of the iterators. Afterwards,
the result of decrementing the iterator was flagged as UB by the debug
implementation because the container was reported to be empty.

This patch fixes that bug by delaying the updating of the container
sizes until after the iterators have been correctly constructed.
------------------------------------------------------------------------

llvm-svn: 334621
2018-06-13 16:57:18 +00:00
Tom Stellard
4f031296e9 Merging r326394:
------------------------------------------------------------------------
r326394 | rnk | 2018-02-28 16:09:35 -0800 (Wed, 28 Feb 2018) | 10 lines

[DAE] don't remove args of musttail target/caller

`musttail` requires identical signatures of caller and callee. Removing
arguments breaks `musttail` semantics.

PR36441

Patch by Fedor Indutny

Differential Revision: https://reviews.llvm.org/D43708
------------------------------------------------------------------------

llvm-svn: 334464
2018-06-12 01:39:23 +00:00
5 changed files with 129 additions and 11 deletions

View File

@@ -159,7 +159,6 @@ typedef struct user_fpregs elf_fpregset_t;
# include <sys/procfs.h>
#endif
#include <sys/user.h>
#include <sys/ustat.h>
#include <linux/cyclades.h>
#include <linux/if_eql.h>
#include <linux/if_plip.h>
@@ -253,7 +252,19 @@ namespace __sanitizer {
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
#if SANITIZER_LINUX && !SANITIZER_ANDROID
unsigned struct_ustat_sz = sizeof(struct ustat);
// Use pre-computed size of struct ustat to avoid <sys/ustat.h> which
// has been removed from glibc 2.28.
#if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \
|| defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \
|| defined(__x86_64__)
#define SIZEOF_STRUCT_USTAT 32
#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
|| defined(__powerpc__) || defined(__s390__)
#define SIZEOF_STRUCT_USTAT 20
#else
#error Unknown size of struct ustat
#endif
unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID

View File

@@ -2058,15 +2058,15 @@ list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f, con
#endif
if (__f != __l)
{
if (this != &__c)
{
size_type __s = _VSTD::distance(__f, __l);
__c.__sz() -= __s;
base::__sz() += __s;
}
__link_pointer __first = __f.__ptr_;
--__l;
__link_pointer __last = __l.__ptr_;
if (this != &__c)
{
size_type __s = _VSTD::distance(__f, __l) + 1;
__c.__sz() -= __s;
base::__sz() += __s;
}
base::__unlink_nodes(__first, __last);
__link_nodes(__p.__ptr_, __first, __last);
#if _LIBCPP_DEBUG_LEVEL >= 2

View File

@@ -42,6 +42,7 @@ public:
Base::run();
try {
FrontOnEmptyContainer();
if constexpr (CT != CT_ForwardList) {
AssignInvalidates();
BackOnEmptyContainer();
@@ -50,6 +51,8 @@ public:
InsertIterIterIter();
EmplaceIterValue();
EraseIterIter();
} else {
SpliceFirstElemAfter();
}
if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) {
PopBack();
@@ -57,12 +60,66 @@ public:
if constexpr (CT == CT_List || CT == CT_Deque) {
PopFront(); // FIXME: Run with forward list as well
}
if constexpr (CT == CT_List || CT == CT_ForwardList) {
RemoveFirstElem();
}
if constexpr (CT == CT_List) {
SpliceFirstElem();
}
} catch (...) {
assert(false && "uncaught debug exception");
}
}
private:
static void RemoveFirstElem() {
// See llvm.org/PR35564
CHECKPOINT("remove(<first-elem>)");
{
Container C = makeContainer(1);
auto FirstVal = *(C.begin());
C.remove(FirstVal);
assert(C.empty());
}
{
Container C = {1, 1, 1, 1};
auto FirstVal = *(C.begin());
C.remove(FirstVal);
assert(C.empty());
}
}
static void SpliceFirstElem() {
// See llvm.org/PR35564
CHECKPOINT("splice(<first-elem>)");
{
Container C = makeContainer(1);
Container C2;
C2.splice(C2.end(), C, C.begin(), ++C.begin());
}
{
Container C = makeContainer(1);
Container C2;
C2.splice(C2.end(), C, C.begin());
}
}
static void SpliceFirstElemAfter() {
// See llvm.org/PR35564
CHECKPOINT("splice(<first-elem>)");
{
Container C = makeContainer(1);
Container C2;
C2.splice_after(C2.begin(), C, C.begin(), ++C.begin());
}
{
Container C = makeContainer(1);
Container C2;
C2.splice_after(C2.begin(), C, C.begin());
}
}
static void AssignInvalidates() {
CHECKPOINT("assign(Size, Value)");
Container C(allocator_type{});

View File

@@ -507,14 +507,28 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
// MaybeLive. Initialized to a list of RetCount empty lists.
RetUses MaybeLiveRetUses(RetCount);
for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
if (const ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()))
bool HasMustTailCalls = false;
for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
if (const ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType()
!= F.getFunctionType()->getReturnType()) {
// We don't support old style multiple return values.
MarkLive(F);
return;
}
}
// If we have any returns of `musttail` results - the signature can't
// change
if (BB->getTerminatingMustTailCall() != nullptr)
HasMustTailCalls = true;
}
if (HasMustTailCalls) {
DEBUG(dbgs() << "DeadArgumentEliminationPass - " << F.getName()
<< " has musttail calls\n");
}
if (!F.hasLocalLinkage() && (!ShouldHackArguments || F.isIntrinsic())) {
MarkLive(F);
@@ -526,6 +540,9 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
// Keep track of the number of live retvals, so we can skip checks once all
// of them turn out to be live.
unsigned NumLiveRetVals = 0;
bool HasMustTailCallers = false;
// Loop all uses of the function.
for (const Use &U : F.uses()) {
// If the function is PASSED IN as an argument, its address has been
@@ -536,6 +553,11 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
return;
}
// The number of arguments for `musttail` call must match the number of
// arguments of the caller
if (CS.isMustTailCall())
HasMustTailCallers = true;
// If this use is anything other than a call site, the function is alive.
const Instruction *TheCall = CS.getInstruction();
if (!TheCall) { // Not a direct call site?
@@ -580,6 +602,11 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
}
}
if (HasMustTailCallers) {
DEBUG(dbgs() << "DeadArgumentEliminationPass - " << F.getName()
<< " has musttail callers\n");
}
// Now we've inspected all callers, record the liveness of our return values.
for (unsigned i = 0; i != RetCount; ++i)
MarkValue(CreateRet(&F, i), RetValLiveness[i], MaybeLiveRetUses[i]);
@@ -593,12 +620,19 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
for (Function::const_arg_iterator AI = F.arg_begin(),
E = F.arg_end(); AI != E; ++AI, ++i) {
Liveness Result;
if (F.getFunctionType()->isVarArg()) {
if (F.getFunctionType()->isVarArg() || HasMustTailCallers ||
HasMustTailCalls) {
// Variadic functions will already have a va_arg function expanded inside
// them, making them potentially very sensitive to ABI changes resulting
// from removing arguments entirely, so don't. For example AArch64 handles
// register and stack HFAs very differently, and this is reflected in the
// IR which has already been generated.
//
// `musttail` calls to this function restrict argument removal attempts.
// The signature of the caller must match the signature of the function.
//
// `musttail` calls in this function prevents us from changing its
// signature
Result = Live;
} else {
// See what the effect of this use is (recording any uses that cause

View File

@@ -0,0 +1,16 @@
; RUN: opt -deadargelim -S < %s | FileCheck %s
; PR36441
; Dead arguments should not be removed in presence of `musttail` calls.
; CHECK-LABEL: define internal void @test(i32 %a, i32 %b)
; CHECK: musttail call void @foo(i32 %a, i32 0)
; FIXME: we should replace those with `undef`s
define internal void @test(i32 %a, i32 %b) {
musttail call void @foo(i32 %a, i32 0)
ret void
}
; CHECK-LABEL: define internal void @foo(i32 %a, i32 %b)
define internal void @foo(i32 %a, i32 %b) {
ret void
}