#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
#define LLVM_ANALYSIS_MEMORYBUILTINS_H
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/ValueHandle.h"
#include <cstdint>
#include <utility>
namespace llvm {
class AllocaInst;
class AAResults;
class Argument;
class ConstantPointerNull;
class DataLayout;
class ExtractElementInst;
class ExtractValueInst;
class GEPOperator;
class GlobalAlias;
class GlobalVariable;
class Instruction;
class IntegerType;
class IntrinsicInst;
class IntToPtrInst;
class LLVMContext;
class LoadInst;
class PHINode;
class SelectInst;
class Type;
class UndefValue;
class Value;
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI);
bool isAllocationFn(const Value *V,
function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI);
bool isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI);
Value *getReallocatedOperand(const CallBase *CB, const TargetLibraryInfo *TLI);
bool isLibFreeFunction(const Function *F, const LibFunc TLIFn);
Value *getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI);
bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI);
Value *getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI);
Optional<APInt> getAllocSize(
const CallBase *CB, const TargetLibraryInfo *TLI,
function_ref<const Value *(const Value *)> Mapper = [](const Value *V) {
return V;
});
Constant *getInitialValueOfAllocation(const Value *V,
const TargetLibraryInfo *TLI,
Type *Ty);
Optional<StringRef> getAllocationFamily(const Value *I,
const TargetLibraryInfo *TLI);
struct ObjectSizeOpts {
enum class Mode : uint8_t {
Exact,
Min,
Max
};
Mode EvalMode = Mode::Exact;
bool RoundToAlign = false;
bool NullIsUnknownSize = false;
AAResults *AA = nullptr;
};
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
Value *lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL,
const TargetLibraryInfo *TLI, bool MustSucceed);
Value *lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL,
const TargetLibraryInfo *TLI, AAResults *AA,
bool MustSucceed);
using SizeOffsetType = std::pair<APInt, APInt>;
class ObjectSizeOffsetVisitor
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
const DataLayout &DL;
const TargetLibraryInfo *TLI;
ObjectSizeOpts Options;
unsigned IntTyBits;
APInt Zero;
SmallPtrSet<Instruction *, 8> SeenInsts;
APInt align(APInt Size, MaybeAlign Align);
SizeOffsetType unknown() {
return std::make_pair(APInt(), APInt());
}
public:
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, ObjectSizeOpts Options = {});
SizeOffsetType compute(Value *V);
static bool knownSize(const SizeOffsetType &SizeOffset) {
return SizeOffset.first.getBitWidth() > 1;
}
static bool knownOffset(const SizeOffsetType &SizeOffset) {
return SizeOffset.second.getBitWidth() > 1;
}
static bool bothKnown(const SizeOffsetType &SizeOffset) {
return knownSize(SizeOffset) && knownOffset(SizeOffset);
}
SizeOffsetType visitAllocaInst(AllocaInst &I);
SizeOffsetType visitArgument(Argument &A);
SizeOffsetType visitCallBase(CallBase &CB);
SizeOffsetType visitConstantPointerNull(ConstantPointerNull&);
SizeOffsetType visitExtractElementInst(ExtractElementInst &I);
SizeOffsetType visitExtractValueInst(ExtractValueInst &I);
SizeOffsetType visitGlobalAlias(GlobalAlias &GA);
SizeOffsetType visitGlobalVariable(GlobalVariable &GV);
SizeOffsetType visitIntToPtrInst(IntToPtrInst&);
SizeOffsetType visitLoadInst(LoadInst &I);
SizeOffsetType visitPHINode(PHINode&);
SizeOffsetType visitSelectInst(SelectInst &I);
SizeOffsetType visitUndefValue(UndefValue&);
SizeOffsetType visitInstruction(Instruction &I);
private:
SizeOffsetType findLoadSizeOffset(
LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From,
SmallDenseMap<BasicBlock *, SizeOffsetType, 8> &VisitedBlocks,
unsigned &ScannedInstCount);
SizeOffsetType combineSizeOffset(SizeOffsetType LHS, SizeOffsetType RHS);
SizeOffsetType computeImpl(Value *V);
bool CheckedZextOrTrunc(APInt &I);
};
using SizeOffsetEvalType = std::pair<Value *, Value *>;
class ObjectSizeOffsetEvaluator
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>;
using WeakEvalType = std::pair<WeakTrackingVH, WeakTrackingVH>;
using CacheMapTy = DenseMap<const Value *, WeakEvalType>;
using PtrSetTy = SmallPtrSet<const Value *, 8>;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
LLVMContext &Context;
BuilderTy Builder;
IntegerType *IntTy;
Value *Zero;
CacheMapTy CacheMap;
PtrSetTy SeenVals;
ObjectSizeOpts EvalOpts;
SmallPtrSet<Instruction *, 8> InsertedInstructions;
SizeOffsetEvalType compute_(Value *V);
public:
static SizeOffsetEvalType unknown() {
return std::make_pair(nullptr, nullptr);
}
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, ObjectSizeOpts EvalOpts = {});
SizeOffsetEvalType compute(Value *V);
bool knownSize(SizeOffsetEvalType SizeOffset) {
return SizeOffset.first;
}
bool knownOffset(SizeOffsetEvalType SizeOffset) {
return SizeOffset.second;
}
bool anyKnown(SizeOffsetEvalType SizeOffset) {
return knownSize(SizeOffset) || knownOffset(SizeOffset);
}
bool bothKnown(SizeOffsetEvalType SizeOffset) {
return knownSize(SizeOffset) && knownOffset(SizeOffset);
}
SizeOffsetEvalType visitAllocaInst(AllocaInst &I);
SizeOffsetEvalType visitCallBase(CallBase &CB);
SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I);
SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I);
SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP);
SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&);
SizeOffsetEvalType visitLoadInst(LoadInst &I);
SizeOffsetEvalType visitPHINode(PHINode &PHI);
SizeOffsetEvalType visitSelectInst(SelectInst &I);
SizeOffsetEvalType visitInstruction(Instruction &I);
};
}
#endif