summaryrefslogtreecommitdiff
path: root/include/llvm
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-09 21:23:09 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-09 21:23:09 +0000
commit909545a822eef491158f831688066f0ec2866938 (patch)
tree5b0bf0e81294007a9b462b21031b3df272c655c3 /include/llvm
parent7e7b6700743285c0af506ac6299ddf82ebd434b9 (diff)
Diffstat (limited to 'include/llvm')
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h2
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h10
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h3
-rw-r--r--include/llvm/DebugInfo/MSF/StreamArray.h111
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h4
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCUtils.h246
-rw-r--r--include/llvm/ExecutionEngine/Orc/RawByteChannel.h4
-rw-r--r--include/llvm/IR/ModuleSummaryIndexYAML.h12
-rw-r--r--include/llvm/IR/PassManager.h127
-rw-r--r--include/llvm/IR/User.h20
-rw-r--r--include/llvm/Support/Path.h8
-rw-r--r--include/llvm/Transforms/IPO.h13
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h1
14 files changed, 373 insertions, 192 deletions
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index 9dcffe1ac5fb3..1a93f9aa5fd27 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -1491,6 +1491,8 @@ public:
void print(raw_ostream &OS) const;
void verify() const;
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &Inv);
/// Collect parametric terms occurring in step expressions (first step of
/// delinearization).
diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
index 196fbc7faa8d9..8675882431d56 100644
--- a/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
@@ -290,7 +290,7 @@ public:
}
/// Returns extension attribute kind to be used for i32 parameters
- /// correpsonding to C-level int or unsigned int. May be zeroext, signext,
+ /// corresponding to C-level int or unsigned int. May be zeroext, signext,
/// or none.
Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const {
if (Impl->ShouldExtI32Param)
@@ -301,7 +301,7 @@ public:
}
/// Returns extension attribute kind to be used for i32 return values
- /// correpsonding to C-level int or unsigned int. May be zeroext, signext,
+ /// corresponding to C-level int or unsigned int. May be zeroext, signext,
/// or none.
Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const {
if (Impl->ShouldExtI32Return)
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 92a9896d7a180..f3f5e324d76af 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -308,6 +308,16 @@ public:
// Iteration support for live in sets. These sets are kept in sorted
// order by their register number.
typedef LiveInVector::const_iterator livein_iterator;
+#ifndef NDEBUG
+ /// Unlike livein_begin, this method does not check that the liveness
+ /// information is accurate. Still for debug purposes it may be useful
+ /// to have iterators that won't assert if the liveness information
+ /// is not current.
+ livein_iterator livein_begin_dbg() const { return LiveIns.begin(); }
+ iterator_range<livein_iterator> liveins_dbg() const {
+ return make_range(livein_begin_dbg(), livein_end());
+ }
+#endif
livein_iterator livein_begin() const;
livein_iterator livein_end() const { return LiveIns.end(); }
bool livein_empty() const { return LiveIns.empty(); }
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index 2fab8137564ea..4600c2c0f10cb 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -148,8 +148,7 @@ class MachineFrameInfo {
/// grouping overaligned allocas into a "secondary stack frame" and
/// then only use a single alloca to allocate this frame and only a
/// single virtual register to access it. Currently, without such an
- /// optimization, each such alloca gets it's own dynamic
- /// realignment.
+ /// optimization, each such alloca gets its own dynamic realignment.
bool StackRealignable;
/// Whether the function has the \c alignstack attribute.
diff --git a/include/llvm/DebugInfo/MSF/StreamArray.h b/include/llvm/DebugInfo/MSF/StreamArray.h
index d8b74bc75c947..3bba80d807f3f 100644
--- a/include/llvm/DebugInfo/MSF/StreamArray.h
+++ b/include/llvm/DebugInfo/MSF/StreamArray.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_MSF_STREAMARRAY_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/DebugInfo/MSF/StreamRef.h"
#include "llvm/Support/Error.h"
#include <cassert>
@@ -107,7 +108,10 @@ private:
Extractor E;
};
-template <typename ValueType, typename Extractor> class VarStreamArrayIterator {
+template <typename ValueType, typename Extractor>
+class VarStreamArrayIterator
+ : public iterator_facade_base<VarStreamArrayIterator<ValueType, Extractor>,
+ std::forward_iterator_tag, ValueType> {
typedef VarStreamArrayIterator<ValueType, Extractor> IterType;
typedef VarStreamArray<ValueType, Extractor> ArrayType;
@@ -144,41 +148,39 @@ public:
return false;
}
- bool operator!=(const IterType &R) { return !(*this == R); }
-
const ValueType &operator*() const {
assert(Array && !HasError);
return ThisValue;
}
- IterType &operator++() {
- // We are done with the current record, discard it so that we are
- // positioned at the next record.
- IterRef = IterRef.drop_front(ThisLen);
- if (IterRef.getLength() == 0) {
- // There is nothing after the current record, we must make this an end
- // iterator.
- moveToEnd();
- } else {
- // There is some data after the current record.
- auto EC = Extract(IterRef, ThisLen, ThisValue);
- if (EC) {
- consumeError(std::move(EC));
- markError();
- } else if (ThisLen == 0) {
- // An empty record? Make this an end iterator.
+ IterType &operator+=(std::ptrdiff_t N) {
+ while (N > 0) {
+ // We are done with the current record, discard it so that we are
+ // positioned at the next record.
+ IterRef = IterRef.drop_front(ThisLen);
+ if (IterRef.getLength() == 0) {
+ // There is nothing after the current record, we must make this an end
+ // iterator.
moveToEnd();
+ return *this;
+ } else {
+ // There is some data after the current record.
+ auto EC = Extract(IterRef, ThisLen, ThisValue);
+ if (EC) {
+ consumeError(std::move(EC));
+ markError();
+ return *this;
+ } else if (ThisLen == 0) {
+ // An empty record? Make this an end iterator.
+ moveToEnd();
+ return *this;
+ }
}
+ --N;
}
return *this;
}
- IterType operator++(int) {
- IterType Original = *this;
- ++*this;
- return Original;
- }
-
private:
void moveToEnd() {
Array = nullptr;
@@ -211,6 +213,16 @@ public:
assert(Stream.getLength() % sizeof(T) == 0);
}
+ bool operator==(const FixedStreamArray<T> &Other) const {
+ return Stream == Other.Stream;
+ }
+
+ bool operator!=(const FixedStreamArray<T> &Other) const {
+ return !(*this == Other);
+ }
+
+ FixedStreamArray &operator=(const FixedStreamArray &) = default;
+
const T &operator[](uint32_t Index) const {
assert(Index < size());
uint32_t Off = Index * sizeof(T);
@@ -226,6 +238,8 @@ public:
uint32_t size() const { return Stream.getLength() / sizeof(T); }
+ bool empty() const { return size() == 0; }
+
FixedStreamArrayIterator<T> begin() const {
return FixedStreamArrayIterator<T>(*this, 0);
}
@@ -240,36 +254,53 @@ private:
ReadableStreamRef Stream;
};
-template <typename T> class FixedStreamArrayIterator {
+template <typename T>
+class FixedStreamArrayIterator
+ : public iterator_facade_base<FixedStreamArrayIterator<T>,
+ std::random_access_iterator_tag, T> {
+
public:
FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index)
: Array(Array), Index(Index) {}
- bool operator==(const FixedStreamArrayIterator<T> &R) {
- assert(&Array == &R.Array);
- return Index == R.Index;
+ FixedStreamArrayIterator<T> &
+ operator=(const FixedStreamArrayIterator<T> &Other) {
+ Array = Other.Array;
+ Index = Other.Index;
+ return *this;
}
- bool operator!=(const FixedStreamArrayIterator<T> &R) {
- return !(*this == R);
+ const T &operator*() const { return Array[Index]; }
+
+ bool operator==(const FixedStreamArrayIterator<T> &R) const {
+ assert(Array == R.Array);
+ return (Index == R.Index) && (Array == R.Array);
}
- const T &operator*() const { return Array[Index]; }
+ FixedStreamArrayIterator<T> &operator+=(std::ptrdiff_t N) {
+ Index += N;
+ return *this;
+ }
- FixedStreamArrayIterator<T> &operator++() {
- assert(Index < Array.size());
- ++Index;
+ FixedStreamArrayIterator<T> &operator-=(std::ptrdiff_t N) {
+ assert(Index >= N);
+ Index -= N;
return *this;
}
- FixedStreamArrayIterator<T> operator++(int) {
- FixedStreamArrayIterator<T> Original = *this;
- ++*this;
- return Original;
+ std::ptrdiff_t operator-(const FixedStreamArrayIterator<T> &R) const {
+ assert(Array == R.Array);
+ assert(Index >= R.Index);
+ return Index - R.Index;
+ }
+
+ bool operator<(const FixedStreamArrayIterator<T> &RHS) const {
+ assert(Array == RHS.Array);
+ return Index < RHS.Index;
}
private:
- const FixedStreamArray<T> &Array;
+ FixedStreamArray<T> Array;
uint32_t Index;
};
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
index ab2b0fad89fd6..3086ef0cdf803 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
@@ -83,7 +83,7 @@ public:
namespace remote {
class OrcRemoteTargetRPCAPI
- : public rpc::SingleThreadedRPC<rpc::RawByteChannel> {
+ : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
protected:
class ResourceIdMgr {
public:
@@ -108,7 +108,7 @@ protected:
public:
// FIXME: Remove constructors once MSVC supports synthesizing move-ops.
OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
- : rpc::SingleThreadedRPC<rpc::RawByteChannel>(C, true) {}
+ : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {}
class CallIntVoid
: public rpc::Function<CallIntVoid, int32_t(JITTargetAddress Addr)> {
diff --git a/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index f51fbe153a41c..37e2e66e5af48 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -702,7 +702,7 @@ public:
/// sync.
template <typename ImplT, typename ChannelT, typename FunctionIdT,
typename SequenceNumberT>
-class RPCBase {
+class RPCEndpointBase {
protected:
class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> {
public:
@@ -747,7 +747,7 @@ protected:
public:
/// Construct an RPC instance on a channel.
- RPCBase(ChannelT &C, bool LazyAutoNegotiation)
+ RPCEndpointBase(ChannelT &C, bool LazyAutoNegotiation)
: C(C), LazyAutoNegotiation(LazyAutoNegotiation) {
// Hold ResponseId in a special variable, since we expect Response to be
// called relatively frequently, and want to avoid the map lookup.
@@ -788,15 +788,21 @@ public:
return FnIdOrErr.takeError();
}
- // Allocate a sequence number.
- auto SeqNo = SequenceNumberMgr.getSequenceNumber();
- assert(!PendingResponses.count(SeqNo) &&
- "Sequence number already allocated");
+ SequenceNumberT SeqNo; // initialized in locked scope below.
+ {
+ // Lock the pending responses map and sequence number manager.
+ std::lock_guard<std::mutex> Lock(ResponsesMutex);
+
+ // Allocate a sequence number.
+ SeqNo = SequenceNumberMgr.getSequenceNumber();
+ assert(!PendingResponses.count(SeqNo) &&
+ "Sequence number already allocated");
- // Install the user handler.
- PendingResponses[SeqNo] =
+ // Install the user handler.
+ PendingResponses[SeqNo] =
detail::createResponseHandler<ChannelT, typename Func::ReturnType>(
std::move(Handler));
+ }
// Open the function call message.
if (auto Err = C.startSendMessage(FnId, SeqNo)) {
@@ -863,11 +869,33 @@ public:
return detail::ReadArgs<ArgTs...>(Args...);
}
+ /// Abandon all outstanding result handlers.
+ ///
+ /// This will call all currently registered result handlers to receive an
+ /// "abandoned" error as their argument. This is used internally by the RPC
+ /// in error situations, but can also be called directly by clients who are
+ /// disconnecting from the remote and don't or can't expect responses to their
+ /// outstanding calls. (Especially for outstanding blocking calls, calling
+ /// this function may be necessary to avoid dead threads).
+ void abandonPendingResponses() {
+ // Lock the pending responses map and sequence number manager.
+ std::lock_guard<std::mutex> Lock(ResponsesMutex);
+
+ for (auto &KV : PendingResponses)
+ KV.second->abandon();
+ PendingResponses.clear();
+ SequenceNumberMgr.reset();
+ }
+
protected:
// The LaunchPolicy type allows a launch policy to be specified when adding
// a function handler. See addHandlerImpl.
using LaunchPolicy = std::function<Error(std::function<Error()>)>;
+ FunctionIdT getInvalidFunctionId() const {
+ return FnIdAllocator.getInvalidId();
+ }
+
/// Add the given handler to the handler map and make it available for
/// autonegotiation and execution.
template <typename Func, typename HandlerT>
@@ -884,28 +912,32 @@ protected:
wrapHandler<Func>(std::move(Handler), std::move(Launch));
}
- // Abandon all outstanding results.
- void abandonPendingResponses() {
- for (auto &KV : PendingResponses)
- KV.second->abandon();
- PendingResponses.clear();
- SequenceNumberMgr.reset();
- }
-
Error handleResponse(SequenceNumberT SeqNo) {
- auto I = PendingResponses.find(SeqNo);
- if (I == PendingResponses.end()) {
- abandonPendingResponses();
- return orcError(OrcErrorCode::UnexpectedRPCResponse);
+ using Handler = typename decltype(PendingResponses)::mapped_type;
+ Handler PRHandler;
+
+ {
+ // Lock the pending responses map and sequence number manager.
+ std::unique_lock<std::mutex> Lock(ResponsesMutex);
+ auto I = PendingResponses.find(SeqNo);
+
+ if (I != PendingResponses.end()) {
+ PRHandler = std::move(I->second);
+ PendingResponses.erase(I);
+ SequenceNumberMgr.releaseSequenceNumber(SeqNo);
+ } else {
+ // Unlock the pending results map to prevent recursive lock.
+ Lock.unlock();
+ abandonPendingResponses();
+ return orcError(OrcErrorCode::UnexpectedRPCResponse);
+ }
}
- auto PRHandler = std::move(I->second);
- PendingResponses.erase(I);
- SequenceNumberMgr.releaseSequenceNumber(SeqNo);
+ assert(PRHandler &&
+ "If we didn't find a response handler we should have bailed out");
if (auto Err = PRHandler->handleResponse(C)) {
abandonPendingResponses();
- SequenceNumberMgr.reset();
return Err;
}
@@ -915,7 +947,7 @@ protected:
FunctionIdT handleNegotiate(const std::string &Name) {
auto I = LocalFunctionIds.find(Name);
if (I == LocalFunctionIds.end())
- return FnIdAllocator.getInvalidId();
+ return getInvalidFunctionId();
return I->second;
}
@@ -938,7 +970,7 @@ protected:
// If autonegotiation indicates that the remote end doesn't support this
// function, return an unknown function error.
- if (RemoteId == FnIdAllocator.getInvalidId())
+ if (RemoteId == getInvalidFunctionId())
return orcError(OrcErrorCode::UnknownRPCFunction);
// Autonegotiation succeeded and returned a valid id. Update the map and
@@ -1012,6 +1044,7 @@ protected:
std::map<FunctionIdT, WrappedHandlerFn> Handlers;
+ std::mutex ResponsesMutex;
detail::SequenceNumberManager<SequenceNumberT> SequenceNumberMgr;
std::map<SequenceNumberT, std::unique_ptr<detail::ResponseHandler<ChannelT>>>
PendingResponses;
@@ -1021,17 +1054,18 @@ protected:
template <typename ChannelT, typename FunctionIdT = uint32_t,
typename SequenceNumberT = uint32_t>
-class MultiThreadedRPC
- : public detail::RPCBase<
- MultiThreadedRPC<ChannelT, FunctionIdT, SequenceNumberT>, ChannelT,
- FunctionIdT, SequenceNumberT> {
+class MultiThreadedRPCEndpoint
+ : public detail::RPCEndpointBase<
+ MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
+ ChannelT, FunctionIdT, SequenceNumberT> {
private:
using BaseClass =
- detail::RPCBase<MultiThreadedRPC<ChannelT, FunctionIdT, SequenceNumberT>,
- ChannelT, FunctionIdT, SequenceNumberT>;
+ detail::RPCEndpointBase<
+ MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
+ ChannelT, FunctionIdT, SequenceNumberT>;
public:
- MultiThreadedRPC(ChannelT &C, bool LazyAutoNegotiation)
+ MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
: BaseClass(C, LazyAutoNegotiation) {}
/// The LaunchPolicy type allows a launch policy to be specified when adding
@@ -1061,30 +1095,41 @@ public:
std::move(Launch));
}
+ /// Add a class-method as a handler.
+ template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
+ void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...),
+ LaunchPolicy Launch = LaunchPolicy()) {
+ addHandler<Func>(
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method),
+ Launch);
+ }
+
/// Negotiate a function id for Func with the other end of the channel.
- template <typename Func> Error negotiateFunction() {
+ template <typename Func> Error negotiateFunction(bool Retry = false) {
using OrcRPCNegotiate = typename BaseClass::OrcRPCNegotiate;
+ // Check if we already have a function id...
+ auto I = this->RemoteFunctionIds.find(Func::getPrototype());
+ if (I != this->RemoteFunctionIds.end()) {
+ // If it's valid there's nothing left to do.
+ if (I->second != this->getInvalidFunctionId())
+ return Error::success();
+ // If it's invalid and we can't re-attempt negotiation, throw an error.
+ if (!Retry)
+ return orcError(OrcErrorCode::UnknownRPCFunction);
+ }
+
+ // We don't have a function id for Func yet, call the remote to try to
+ // negotiate one.
if (auto RemoteIdOrErr = callB<OrcRPCNegotiate>(Func::getPrototype())) {
this->RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
+ if (*RemoteIdOrErr == this->getInvalidFunctionId())
+ return orcError(OrcErrorCode::UnknownRPCFunction);
return Error::success();
} else
return RemoteIdOrErr.takeError();
}
- /// Convenience method for negotiating multiple functions at once.
- template <typename Func> Error negotiateFunctions() {
- return negotiateFunction<Func>();
- }
-
- /// Convenience method for negotiating multiple functions at once.
- template <typename Func1, typename Func2, typename... Funcs>
- Error negotiateFunctions() {
- if (auto Err = negotiateFunction<Func1>())
- return Err;
- return negotiateFunctions<Func2, Funcs...>();
- }
-
/// Return type for non-blocking call primitives.
template <typename Func>
using NonBlockingCallResult = typename detail::ResultTraits<
@@ -1169,19 +1214,20 @@ public:
template <typename ChannelT, typename FunctionIdT = uint32_t,
typename SequenceNumberT = uint32_t>
-class SingleThreadedRPC
- : public detail::RPCBase<
- SingleThreadedRPC<ChannelT, FunctionIdT, SequenceNumberT>, ChannelT,
- FunctionIdT, SequenceNumberT> {
+class SingleThreadedRPCEndpoint
+ : public detail::RPCEndpointBase<
+ SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
+ ChannelT, FunctionIdT, SequenceNumberT> {
private:
using BaseClass =
- detail::RPCBase<SingleThreadedRPC<ChannelT, FunctionIdT, SequenceNumberT>,
- ChannelT, FunctionIdT, SequenceNumberT>;
+ detail::RPCEndpointBase<
+ SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
+ ChannelT, FunctionIdT, SequenceNumberT>;
using LaunchPolicy = typename BaseClass::LaunchPolicy;
public:
- SingleThreadedRPC(ChannelT &C, bool LazyAutoNegotiation)
+ SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
: BaseClass(C, LazyAutoNegotiation) {}
template <typename Func, typename HandlerT>
@@ -1197,29 +1243,31 @@ public:
}
/// Negotiate a function id for Func with the other end of the channel.
- template <typename Func> Error negotiateFunction() {
+ template <typename Func> Error negotiateFunction(bool Retry = false) {
using OrcRPCNegotiate = typename BaseClass::OrcRPCNegotiate;
+ // Check if we already have a function id...
+ auto I = this->RemoteFunctionIds.find(Func::getPrototype());
+ if (I != this->RemoteFunctionIds.end()) {
+ // If it's valid there's nothing left to do.
+ if (I->second != this->getInvalidFunctionId())
+ return Error::success();
+ // If it's invalid and we can't re-attempt negotiation, throw an error.
+ if (!Retry)
+ return orcError(OrcErrorCode::UnknownRPCFunction);
+ }
+
+ // We don't have a function id for Func yet, call the remote to try to
+ // negotiate one.
if (auto RemoteIdOrErr = callB<OrcRPCNegotiate>(Func::getPrototype())) {
this->RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
+ if (*RemoteIdOrErr == this->getInvalidFunctionId())
+ return orcError(OrcErrorCode::UnknownRPCFunction);
return Error::success();
} else
return RemoteIdOrErr.takeError();
}
- /// Convenience method for negotiating multiple functions at once.
- template <typename Func> Error negotiateFunctions() {
- return negotiateFunction<Func>();
- }
-
- /// Convenience method for negotiating multiple functions at once.
- template <typename Func1, typename Func2, typename... Funcs>
- Error negotiateFunctions() {
- if (auto Err = negotiateFunction<Func1>())
- return Err;
- return negotiateFunctions<Func2, Funcs...>();
- }
-
template <typename Func, typename... ArgTs,
typename AltRetT = typename Func::ReturnType>
typename detail::ResultTraits<AltRetT>::ErrorReturnType
@@ -1332,6 +1380,68 @@ private:
uint32_t NumOutstandingCalls;
};
+/// @brief Convenience class for grouping RPC Functions into APIs that can be
+/// negotiated as a block.
+///
+template <typename... Funcs>
+class APICalls {
+public:
+
+ /// @brief Test whether this API contains Function F.
+ template <typename F>
+ class Contains {
+ public:
+ static const bool value = false;
+ };
+
+ /// @brief Negotiate all functions in this API.
+ template <typename RPCEndpoint>
+ static Error negotiate(RPCEndpoint &R) {
+ return Error::success();
+ }
+};
+
+template <typename Func, typename... Funcs>
+class APICalls<Func, Funcs...> {
+public:
+
+ template <typename F>
+ class Contains {
+ public:
+ static const bool value = std::is_same<F, Func>::value |
+ APICalls<Funcs...>::template Contains<F>::value;
+ };
+
+ template <typename RPCEndpoint>
+ static Error negotiate(RPCEndpoint &R) {
+ if (auto Err = R.template negotiateFunction<Func>())
+ return Err;
+ return APICalls<Funcs...>::negotiate(R);
+ }
+
+};
+
+template <typename... InnerFuncs, typename... Funcs>
+class APICalls<APICalls<InnerFuncs...>, Funcs...> {
+public:
+
+ template <typename F>
+ class Contains {
+ public:
+ static const bool value =
+ APICalls<InnerFuncs...>::template Contains<F>::value |
+ APICalls<Funcs...>::template Contains<F>::value;
+ };
+
+ template <typename RPCEndpoint>
+ static Error negotiate(RPCEndpoint &R) {
+ if (auto Err = APICalls<InnerFuncs...>::negotiate(R))
+ return Err;
+ return APICalls<Funcs...>::negotiate(R);
+ }
+
+};
+
} // end namespace rpc
} // end namespace orc
} // end namespace llvm
diff --git a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
index 83a7b9a844f2a..3b6c84eb19650 100644
--- a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
+++ b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
@@ -48,9 +48,7 @@ public:
template <typename FunctionIdT, typename SequenceIdT>
Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) {
writeLock.lock();
- if (auto Err = serializeSeq(*this, FnId, SeqNo))
- return Err;
- return Error::success();
+ return serializeSeq(*this, FnId, SeqNo);
}
/// Notify the channel that we're ending a message send.
diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h
index a8c8ff9ef2ebb..aeb66633f2c85 100644
--- a/include/llvm/IR/ModuleSummaryIndexYAML.h
+++ b/include/llvm/IR/ModuleSummaryIndexYAML.h
@@ -28,14 +28,14 @@ template <> struct ScalarEnumerationTraits<TypeTestResolution::Kind> {
template <> struct MappingTraits<TypeTestResolution> {
static void mapping(IO &io, TypeTestResolution &res) {
- io.mapRequired("Kind", res.TheKind);
- io.mapRequired("SizeBitWidth", res.SizeBitWidth);
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("SizeBitWidth", res.SizeBitWidth);
}
};
template <> struct MappingTraits<TypeIdSummary> {
static void mapping(IO &io, TypeIdSummary& summary) {
- io.mapRequired("TTRes", summary.TTRes);
+ io.mapOptional("TTRes", summary.TTRes);
}
};
@@ -53,7 +53,7 @@ namespace yaml {
template <> struct MappingTraits<FunctionSummaryYaml> {
static void mapping(IO &io, FunctionSummaryYaml& summary) {
- io.mapRequired("TypeTests", summary.TypeTests);
+ io.mapOptional("TypeTests", summary.TypeTests);
}
};
@@ -100,8 +100,8 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
template <> struct MappingTraits<ModuleSummaryIndex> {
static void mapping(IO &io, ModuleSummaryIndex& index) {
- io.mapRequired("GlobalValueMap", index.GlobalValueMap);
- io.mapRequired("TypeIdMap", index.TypeIdMap);
+ io.mapOptional("GlobalValueMap", index.GlobalValueMap);
+ io.mapOptional("TypeIdMap", index.TypeIdMap);
}
};
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index 7a63956f1cdbc..2e95f67a14a94 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -879,18 +879,22 @@ extern template class AnalysisManager<Function>;
/// \brief Convenience typedef for the Function analysis manager.
typedef AnalysisManager<Function> FunctionAnalysisManager;
-/// \brief A module analysis which acts as a proxy for a function analysis
-/// manager.
+/// \brief An analysis over an "outer" IR unit that provides access to an
+/// analysis manager over an "inner" IR unit. The inner unit must be contained
+/// in the outer unit.
///
-/// This primarily proxies invalidation information from the module analysis
-/// manager and module pass manager to a function analysis manager. You should
-/// never use a function analysis manager from within (transitively) a module
-/// pass manager unless your parent module pass has received a proxy result
-/// object for it.
+/// Fore example, InnerAnalysisManagerProxy<FunctionAnalysisManager, Module> is
+/// an analysis over Modules (the "outer" unit) that provides access to a
+/// Function analysis manager. The FunctionAnalysisManager is the "inner"
+/// manager being proxied, and Functions are the "inner" unit. The inner/outer
+/// relationship is valid because each Function is contained in one Module.
///
-/// Note that the proxy's result is a move-only object and represents ownership
-/// of the validity of the analyses in the \c FunctionAnalysisManager it
-/// provides.
+/// If you're (transitively) within a pass manager for an IR unit U that
+/// contains IR unit V, you should never use an analysis manager over V, except
+/// via one of these proxies.
+///
+/// Note that the proxy's result is a move-only RAII object. The validity of
+/// the analyses in the inner analysis manager is tied to its lifetime.
template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
class InnerAnalysisManagerProxy
: public AnalysisInfoMixin<
@@ -926,23 +930,16 @@ public:
/// \brief Accessor for the analysis manager.
AnalysisManagerT &getManager() { return *InnerAM; }
- /// \brief Handler for invalidation of the outer IR unit.
- ///
- /// If this analysis itself is preserved, then we assume that the set of \c
- /// IR units that the inner analysis manager controls hasn't changed and
- /// thus we don't need to invalidate *all* cached data associated with any
- /// \c IRUnitT* in the \c AnalysisManagerT.
+ /// \brief Handler for invalidation of the outer IR unit, \c IRUnitT.
///
- /// Regardless of whether this analysis is marked as preserved, all of the
- /// analyses in the \c AnalysisManagerT are potentially invalidated (for
- /// the relevant inner set of their IR units) based on the set of preserved
- /// analyses.
+ /// If the proxy analysis itself is not preserved, we assume that the set of
+ /// inner IR objects contained in IRUnit may have changed. In this case,
+ /// we have to call \c clear() on the inner analysis manager, as it may now
+ /// have stale pointers to its inner IR objects.
///
- /// Because this needs to understand the mapping from one IR unit to an
- /// inner IR unit, this method isn't defined in the primary template.
- /// Instead, each specialization of this template will need to provide an
- /// explicit specialization of this method to handle that particular pair
- /// of IR unit and inner AnalysisManagerT.
+ /// Regardless of whether the proxy analysis is marked as preserved, all of
+ /// the analyses in the inner analysis manager are potentially invalidated
+ /// based on the set of preserved analyses.
bool invalidate(
IRUnitT &IR, const PreservedAnalyses &PA,
typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &Inv);
@@ -956,13 +953,9 @@ public:
/// \brief Run the analysis pass and create our proxy result object.
///
- /// This doesn't do any interesting work, it is primarily used to insert our
- /// proxy result object into the module analysis cache so that we can proxy
- /// invalidation to the function analysis manager.
- ///
- /// In debug builds, it will also assert that the analysis manager is empty
- /// as no queries should arrive at the function analysis manager prior to
- /// this analysis being requested.
+ /// This doesn't do any interesting work; it is primarily used to insert our
+ /// proxy result object into the outer analysis cache so that we can proxy
+ /// invalidation to the inner analysis manager.
Result run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
ExtraArgTs...) {
return Result(*InnerAM);
@@ -996,22 +989,24 @@ bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
Module>;
-/// \brief A function analysis which acts as a proxy for a module analysis
-/// manager.
+/// \brief An analysis over an "inner" IR unit that provides access to an
+/// analysis manager over a "outer" IR unit. The inner unit must be contained
+/// in the outer unit.
///
-/// This primarily provides an accessor to a parent module analysis manager to
-/// function passes. Only the const interface of the module analysis manager is
-/// provided to indicate that once inside of a function analysis pass you
-/// cannot request a module analysis to actually run. Instead, the user must
-/// rely on the \c getCachedResult API.
+/// For example OuterAnalysisManagerProxy<ModuleAnalysisManager, Function> is an
+/// analysis over Functions (the "inner" unit) which provides access to a Module
+/// analysis manager. The ModuleAnalysisManager is the "outer" manager being
+/// proxied, and Modules are the "outer" IR unit. The inner/outer relationship
+/// is valid because each Function is contained in one Module.
///
-/// The invalidation provided by this proxy involves tracking when an
-/// invalidation event in the outer analysis manager needs to trigger an
-/// invalidation of a particular analysis on this IR unit.
+/// This proxy only exposes the const interface of the outer analysis manager,
+/// to indicate that you cannot cause an outer analysis to run from within an
+/// inner pass. Instead, you must rely on the \c getCachedResult API.
///
-/// Because outer analyses aren't invalidated while these IR units are being
-/// precessed, we have to register and handle these as deferred invalidation
-/// events.
+/// This proxy doesn't manage invalidation in any way -- that is handled by the
+/// recursive return path of each layer of the pass manager. A consequence of
+/// this is the outer analyses may be stale. We invalidate the outer analyses
+/// only when we're done running passes over the inner IR units.
template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
class OuterAnalysisManagerProxy
: public AnalysisInfoMixin<
@@ -1024,7 +1019,7 @@ public:
const AnalysisManagerT &getManager() const { return *AM; }
- /// \brief Handle invalidation by ignoring it, this pass is immutable.
+ /// \brief Handle invalidation by ignoring it; this pass is immutable.
bool invalidate(
IRUnitT &, const PreservedAnalyses &,
typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &) {
@@ -1089,18 +1084,15 @@ AnalysisKey
extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
Function>;
-/// Provide the \c ModuleAnalysisManager to \c Fucntion proxy.
+/// Provide the \c ModuleAnalysisManager to \c Function proxy.
typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
ModuleAnalysisManagerFunctionProxy;
/// \brief Trivial adaptor that maps from a module to its functions.
///
/// Designed to allow composition of a FunctionPass(Manager) and
-/// a ModulePassManager. Note that if this pass is constructed with a pointer
-/// to a \c ModuleAnalysisManager it will run the
-/// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function
-/// pass over the module to enable a \c FunctionAnalysisManager to be used
-/// within this run safely.
+/// a ModulePassManager, by running the FunctionPass(Manager) over every
+/// function in the module.
///
/// Function passes run within this adaptor can rely on having exclusive access
/// to the function they are run over. They should not read or modify any other
@@ -1115,6 +1107,10 @@ typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
/// module.
/// FIXME: Make the above true for all of LLVM's actual passes, some still
/// violate this principle.
+///
+/// Note that although function passes can access module analyses, module
+/// analyses are not invalidated while the function passes are running, so they
+/// may be stale. Function analyses will not be stale.
template <typename FunctionPassT>
class ModuleToFunctionPassAdaptor
: public PassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> {
@@ -1124,7 +1120,6 @@ public:
/// \brief Runs the function pass across every function in the module.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
- // Setup the function analysis manager from its proxy.
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
@@ -1145,10 +1140,11 @@ public:
PA.intersect(std::move(PassPA));
}
- // By definition we preserve the proxy. We also preserve all analyses on
- // Function units. This precludes *any* invalidation of function analyses
- // by the proxy, but that's OK because we've taken care to invalidate
- // analyses in the function analysis manager incrementally above.
+ // The FunctionAnalysisManagerModuleProxy is preserved because (we assume)
+ // the function passes we ran didn't add or remove any functions.
+ //
+ // We also preserve all analyses on Functions, because we did all the
+ // invalidation we needed to do above.
PA.preserveSet<AllAnalysesOn<Function>>();
PA.preserve<FunctionAnalysisManagerModuleProxy>();
return PA;
@@ -1166,7 +1162,7 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
}
-/// \brief A template utility pass to force an analysis result to be available.
+/// \brief A utility pass template to force an analysis result to be available.
///
/// If there are extra arguments at the pass's run level there may also be
/// extra arguments to the analysis manager's \c getResult routine. We can't
@@ -1196,17 +1192,14 @@ struct RequireAnalysisPass
}
};
-/// \brief A template utility pass to force an analysis result to be
-/// invalidated.
-///
-/// This is a no-op pass which simply forces a specific analysis result to be
-/// invalidated when it is run.
+/// \brief A no-op pass template which simply forces a specific analysis result
+/// to be invalidated.
template <typename AnalysisT>
struct InvalidateAnalysisPass
: PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> {
/// \brief Run this pass over some unit of IR.
///
- /// This pass can be run over any unit of IR and use any analysis manager
+ /// This pass can be run over any unit of IR and use any analysis manager,
/// provided they satisfy the basic API requirements. When this pass is
/// created, these methods can be instantiated to satisfy whatever the
/// context requires.
@@ -1218,10 +1211,10 @@ struct InvalidateAnalysisPass
}
};
-/// \brief A utility pass that does nothing but preserves no analyses.
+/// \brief A utility pass that does nothing, but preserves no analyses.
///
-/// As a consequence fo not preserving any analyses, this pass will force all
-/// analysis passes to be re-run to produce fresh results if any are needed.
+/// Because this preserves no analyses, any analysis passes queried after this
+/// pass runs will recompute fresh results.
struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> {
/// \brief Run this pass over some unit of IR.
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index e6fe97484580e..c907d6b670b55 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -238,6 +238,26 @@ public:
return make_range(value_op_begin(), value_op_end());
}
+ struct const_value_op_iterator
+ : iterator_adaptor_base<const_value_op_iterator, const_op_iterator,
+ std::random_access_iterator_tag, const Value *,
+ ptrdiff_t, const Value *, const Value *> {
+ explicit const_value_op_iterator(const Use *U = nullptr) :
+ iterator_adaptor_base(U) {}
+ const Value *operator*() const { return *I; }
+ const Value *operator->() const { return operator*(); }
+ };
+
+ const_value_op_iterator value_op_begin() const {
+ return const_value_op_iterator(op_begin());
+ }
+ const_value_op_iterator value_op_end() const {
+ return const_value_op_iterator(op_end());
+ }
+ iterator_range<const_value_op_iterator> operand_values() const {
+ return make_range(value_op_begin(), value_op_end());
+ }
+
/// \brief Drop all references to operands.
///
/// This function is in charge of "letting go" of all objects that this User
diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h
index 0513350d446bc..2bbcef0c293f6 100644
--- a/include/llvm/Support/Path.h
+++ b/include/llvm/Support/Path.h
@@ -207,6 +207,14 @@ void native(const Twine &path, SmallVectorImpl<char> &result);
/// @param path A path that is transformed to native format.
void native(SmallVectorImpl<char> &path);
+/// @brief Replaces backslashes with slashes if Windows.
+///
+/// @param path processed path
+/// @result The result of replacing backslashes with forward slashes if Windows.
+/// On Unix, this function is a no-op because backslashes are valid path
+/// chracters.
+std::string convert_to_slash(StringRef path);
+
/// @}
/// @name Lexical Observers
/// @{
diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h
index 4bebc863b4a9f..dd55062e56f1a 100644
--- a/include/llvm/Transforms/IPO.h
+++ b/include/llvm/Transforms/IPO.h
@@ -215,9 +215,20 @@ ModulePass *createMetaRenamerPass();
/// manager.
ModulePass *createBarrierNoopPass();
+/// What to do with the summary when running the LowerTypeTests pass.
+enum class LowerTypeTestsSummaryAction {
+ None, ///< Do nothing.
+ Import, ///< Import typeid resolutions from summary and globals.
+ Export, ///< Export typeid resolutions to summary and globals.
+};
+
/// \brief This pass lowers type metadata and the llvm.type.test intrinsic to
/// bitsets.
-ModulePass *createLowerTypeTestsPass();
+/// \param Action What to do with the summary passed as Index.
+/// \param Index The summary to use for importing or exporting, this can be null
+/// when Action is None.
+ModulePass *createLowerTypeTestsPass(LowerTypeTestsSummaryAction Action,
+ ModuleSummaryIndex *Index);
/// \brief This pass export CFI checks for use by external modules.
ModulePass *createCrossDSOCFIPass();
diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
index 9f9ce467337e7..abfb24f0fe509 100644
--- a/include/llvm/Transforms/IPO/PassManagerBuilder.h
+++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h
@@ -21,7 +21,6 @@
#include <vector>
namespace llvm {
-class ModuleSummaryIndex;
class Pass;
class TargetLibraryInfoImpl;
class TargetMachine;