Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/Analysis/MemoryLocation.h b/linux-x64/clang/include/llvm/Analysis/MemoryLocation.h
index 7c26353..3b188d7 100644
--- a/linux-x64/clang/include/llvm/Analysis/MemoryLocation.h
+++ b/linux-x64/clang/include/llvm/Analysis/MemoryLocation.h
@@ -17,20 +17,25 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/Support/TypeSize.h"
namespace llvm {
+class CallBase;
+class Instruction;
class LoadInst;
class StoreInst;
class MemTransferInst;
class MemIntrinsic;
+class AtomicCmpXchgInst;
class AtomicMemTransferInst;
class AtomicMemIntrinsic;
+class AtomicRMWInst;
class AnyMemTransferInst;
class AnyMemIntrinsic;
class TargetLibraryInfo;
+class VAArgInst;
// Represents the size of a MemoryLocation. Logically, it's an
// Optional<uint63_t> that also carries a bit to represent whether the integer
@@ -59,10 +64,11 @@
// None.
class LocationSize {
enum : uint64_t {
- Unknown = ~uint64_t(0),
+ BeforeOrAfterPointer = ~uint64_t(0),
+ AfterPointer = BeforeOrAfterPointer - 1,
+ MapEmpty = BeforeOrAfterPointer - 2,
+ MapTombstone = BeforeOrAfterPointer - 3,
ImpreciseBit = uint64_t(1) << 63,
- MapEmpty = Unknown - 1,
- MapTombstone = Unknown - 2,
// The maximum value we can represent without falling back to 'unknown'.
MaxValue = (MapTombstone - 1) & ~ImpreciseBit,
@@ -76,7 +82,11 @@
constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {}
- static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition.");
+ static_assert(AfterPointer & ImpreciseBit,
+ "AfterPointer is imprecise by definition.");
+ static_assert(BeforeOrAfterPointer & ImpreciseBit,
+ "BeforeOrAfterPointer is imprecise by definition.");
+
public:
// FIXME: Migrate all users to construct via either `precise` or `upperBound`,
// to make it more obvious at the callsite the kind of size that they're
@@ -85,21 +95,39 @@
// Since the overwhelming majority of users of this provide precise values,
// this assumes the provided value is precise.
constexpr LocationSize(uint64_t Raw)
- : Value(Raw > MaxValue ? Unknown : Raw) {}
+ : Value(Raw > MaxValue ? AfterPointer : Raw) {}
static LocationSize precise(uint64_t Value) { return LocationSize(Value); }
+ static LocationSize precise(TypeSize Value) {
+ if (Value.isScalable())
+ return afterPointer();
+ return precise(Value.getFixedSize());
+ }
static LocationSize upperBound(uint64_t Value) {
// You can't go lower than 0, so give a precise result.
if (LLVM_UNLIKELY(Value == 0))
return precise(0);
if (LLVM_UNLIKELY(Value > MaxValue))
- return unknown();
+ return afterPointer();
return LocationSize(Value | ImpreciseBit, Direct);
}
+ static LocationSize upperBound(TypeSize Value) {
+ if (Value.isScalable())
+ return afterPointer();
+ return upperBound(Value.getFixedSize());
+ }
- constexpr static LocationSize unknown() {
- return LocationSize(Unknown, Direct);
+ /// Any location after the base pointer (but still within the underlying
+ /// object).
+ constexpr static LocationSize afterPointer() {
+ return LocationSize(AfterPointer, Direct);
+ }
+
+ /// Any location before or after the base pointer (but still within the
+ /// underlying object).
+ constexpr static LocationSize beforeOrAfterPointer() {
+ return LocationSize(BeforeOrAfterPointer, Direct);
}
// Sentinel values, generally used for maps.
@@ -116,20 +144,24 @@
if (Other == *this)
return *this;
- if (!hasValue() || !Other.hasValue())
- return unknown();
+ if (Value == BeforeOrAfterPointer || Other.Value == BeforeOrAfterPointer)
+ return beforeOrAfterPointer();
+ if (Value == AfterPointer || Other.Value == AfterPointer)
+ return afterPointer();
return upperBound(std::max(getValue(), Other.getValue()));
}
- bool hasValue() const { return Value != Unknown; }
+ bool hasValue() const {
+ return Value != AfterPointer && Value != BeforeOrAfterPointer;
+ }
uint64_t getValue() const {
assert(hasValue() && "Getting value from an unknown LocationSize!");
return Value & ~ImpreciseBit;
}
// Returns whether or not this value is precise. Note that if a value is
- // precise, it's guaranteed to not be `unknown()`.
+ // precise, it's guaranteed to not be unknown.
bool isPrecise() const {
return (Value & ImpreciseBit) == 0;
}
@@ -137,6 +169,9 @@
// Convenience method to check if this LocationSize's value is 0.
bool isZero() const { return hasValue() && getValue() == 0; }
+ /// Whether accesses before the base pointer are possible.
+ bool mayBeBeforePointer() const { return Value == BeforeOrAfterPointer; }
+
bool operator==(const LocationSize &Other) const {
return Value == Other.Value;
}
@@ -194,6 +229,8 @@
/// member is null if that kind of information is unavailable).
AAMDNodes AATags;
+ void print(raw_ostream &OS) const { OS << *Ptr << " " << Size << "\n"; }
+
/// Return a location with information about the memory reference by the given
/// instruction.
static MemoryLocation get(const LoadInst *LI);
@@ -204,22 +241,7 @@
static MemoryLocation get(const Instruction *Inst) {
return *MemoryLocation::getOrNone(Inst);
}
- static Optional<MemoryLocation> getOrNone(const Instruction *Inst) {
- switch (Inst->getOpcode()) {
- case Instruction::Load:
- return get(cast<LoadInst>(Inst));
- case Instruction::Store:
- return get(cast<StoreInst>(Inst));
- case Instruction::VAArg:
- return get(cast<VAArgInst>(Inst));
- case Instruction::AtomicCmpXchg:
- return get(cast<AtomicCmpXchgInst>(Inst));
- case Instruction::AtomicRMW:
- return get(cast<AtomicRMWInst>(Inst));
- default:
- return None;
- }
- }
+ static Optional<MemoryLocation> getOrNone(const Instruction *Inst);
/// Return a location representing the source of a memory transfer.
static MemoryLocation getForSource(const MemTransferInst *MTI);
@@ -240,8 +262,30 @@
return getForArgument(Call, ArgIdx, &TLI);
}
- explicit MemoryLocation(const Value *Ptr = nullptr,
- LocationSize Size = LocationSize::unknown(),
+ /// Return a location that may access any location after Ptr, while remaining
+ /// within the underlying object.
+ static MemoryLocation getAfter(const Value *Ptr,
+ const AAMDNodes &AATags = AAMDNodes()) {
+ return MemoryLocation(Ptr, LocationSize::afterPointer(), AATags);
+ }
+
+ /// Return a location that may access any location before or after Ptr, while
+ /// remaining within the underlying object.
+ static MemoryLocation
+ getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags = AAMDNodes()) {
+ return MemoryLocation(Ptr, LocationSize::beforeOrAfterPointer(), AATags);
+ }
+
+ // Return the exact size if the exact size is known at compiletime,
+ // otherwise return MemoryLocation::UnknownSize.
+ static uint64_t getSizeOrUnknown(const TypeSize &T) {
+ return T.isScalable() ? UnknownSize : T.getFixedSize();
+ }
+
+ MemoryLocation()
+ : Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()), AATags() {}
+
+ explicit MemoryLocation(const Value *Ptr, LocationSize Size,
const AAMDNodes &AATags = AAMDNodes())
: Ptr(Ptr), Size(Size), AATags(AATags) {}