forked from OSchip/llvm-project
[CodeGen] Collect information about sizes of accesses and access types for TBAA
The information about access and type sizes is necessary for producing TBAA metadata in the new size-aware format. With this patch, D39955 and D39956 in place we should be able to change CodeGenTBAA::createScalarTypeNode() and CodeGenTBAA::getBaseTypeInfo() to generate metadata in the new format under the -new-struct-path-tbaa command-line option. For now, this new information remains unused. Differential Revision: https://reviews.llvm.org/D40176 llvm-svn: 319012
This commit is contained in:
parent
b833bf6ae1
commit
4e50e707bf
|
@ -2423,7 +2423,8 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
|
|||
VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy);
|
||||
|
||||
llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
|
||||
CGM.DecorateInstructionWithTBAA(Store, CGM.getTBAAVTablePtrAccessInfo());
|
||||
TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTablePtrTy);
|
||||
CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
|
||||
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
|
||||
CGM.getCodeGenOpts().StrictVTablePointers)
|
||||
CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass);
|
||||
|
@ -2517,7 +2518,8 @@ llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
|
|||
const CXXRecordDecl *RD) {
|
||||
Address VTablePtrSrc = Builder.CreateElementBitCast(This, VTableTy);
|
||||
llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");
|
||||
CGM.DecorateInstructionWithTBAA(VTable, CGM.getTBAAVTablePtrAccessInfo());
|
||||
TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy);
|
||||
CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);
|
||||
|
||||
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
|
||||
CGM.getCodeGenOpts().StrictVTablePointers)
|
||||
|
|
|
@ -136,7 +136,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
|
|||
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
|
||||
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
|
||||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
|
||||
TBAA.reset(new CodeGenTBAA(Context, VMContext, CodeGenOpts, getLangOpts(),
|
||||
TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(),
|
||||
getCXXABI().getMangleContext()));
|
||||
|
||||
// If debug info or coverage generation is enabled, create the CGDebugInfo
|
||||
|
@ -579,13 +579,20 @@ llvm::MDNode *CodeGenModule::getTBAATypeInfo(QualType QTy) {
|
|||
}
|
||||
|
||||
TBAAAccessInfo CodeGenModule::getTBAAAccessInfo(QualType AccessType) {
|
||||
return TBAAAccessInfo(getTBAATypeInfo(AccessType));
|
||||
// Pointee values may have incomplete types, but they shall never be
|
||||
// dereferenced.
|
||||
if (AccessType->isIncompleteType())
|
||||
return TBAAAccessInfo::getIncompleteInfo();
|
||||
|
||||
uint64_t Size = Context.getTypeSizeInChars(AccessType).getQuantity();
|
||||
return TBAAAccessInfo(getTBAATypeInfo(AccessType), Size);
|
||||
}
|
||||
|
||||
TBAAAccessInfo CodeGenModule::getTBAAVTablePtrAccessInfo() {
|
||||
TBAAAccessInfo
|
||||
CodeGenModule::getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType) {
|
||||
if (!TBAA)
|
||||
return TBAAAccessInfo();
|
||||
return TBAA->getVTablePtrAccessInfo();
|
||||
return TBAA->getVTablePtrAccessInfo(VTablePtrType);
|
||||
}
|
||||
|
||||
llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
|
||||
|
|
|
@ -664,7 +664,7 @@ public:
|
|||
|
||||
/// getTBAAVTablePtrAccessInfo - Get the TBAA information that describes an
|
||||
/// access to a virtual table pointer.
|
||||
TBAAAccessInfo getTBAAVTablePtrAccessInfo();
|
||||
TBAAAccessInfo getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType);
|
||||
|
||||
llvm::MDNode *getTBAAStructInfo(QualType QTy);
|
||||
|
||||
|
|
|
@ -25,16 +25,18 @@
|
|||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext& VMContext,
|
||||
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M,
|
||||
const CodeGenOptions &CGO,
|
||||
const LangOptions &Features, MangleContext &MContext)
|
||||
: Context(Ctx), CodeGenOpts(CGO), Features(Features), MContext(MContext),
|
||||
MDHelper(VMContext), Root(nullptr), Char(nullptr) {
|
||||
}
|
||||
: Context(Ctx), Module(M), CodeGenOpts(CGO),
|
||||
Features(Features), MContext(MContext), MDHelper(M.getContext()),
|
||||
Root(nullptr), Char(nullptr)
|
||||
{}
|
||||
|
||||
CodeGenTBAA::~CodeGenTBAA() {
|
||||
}
|
||||
|
@ -54,10 +56,10 @@ llvm::MDNode *CodeGenTBAA::getRoot() {
|
|||
return Root;
|
||||
}
|
||||
|
||||
// For both scalar TBAA and struct-path aware TBAA, the scalar type has the
|
||||
// same format: name, parent node, and offset.
|
||||
llvm::MDNode *CodeGenTBAA::createTBAAScalarType(StringRef Name,
|
||||
llvm::MDNode *Parent) {
|
||||
llvm::MDNode *CodeGenTBAA::createScalarTypeNode(StringRef Name,
|
||||
llvm::MDNode *Parent,
|
||||
uint64_t Size) {
|
||||
(void)Size; // TODO: Support generation of size-aware type nodes.
|
||||
return MDHelper.createTBAAScalarTypeNode(Name, Parent);
|
||||
}
|
||||
|
||||
|
@ -67,7 +69,7 @@ llvm::MDNode *CodeGenTBAA::getChar() {
|
|||
// these special powers only cover user-accessible memory, and doesn't
|
||||
// include things like vtables.
|
||||
if (!Char)
|
||||
Char = createTBAAScalarType("omnipotent char", getRoot());
|
||||
Char = createScalarTypeNode("omnipotent char", getRoot(), /* Size= */ 1);
|
||||
|
||||
return Char;
|
||||
}
|
||||
|
@ -108,6 +110,8 @@ static bool isValidBaseType(QualType QTy) {
|
|||
}
|
||||
|
||||
llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
|
||||
uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity();
|
||||
|
||||
// Handle builtin types.
|
||||
if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) {
|
||||
switch (BTy->getKind()) {
|
||||
|
@ -138,7 +142,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
|
|||
// treating wchar_t, char16_t, and char32_t as distinct from their
|
||||
// "underlying types".
|
||||
default:
|
||||
return createTBAAScalarType(BTy->getName(Features), getChar());
|
||||
return createScalarTypeNode(BTy->getName(Features), getChar(), Size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +156,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
|
|||
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
|
||||
// pointers distinct.
|
||||
if (Ty->isPointerType() || Ty->isReferenceType())
|
||||
return createTBAAScalarType("any pointer", getChar());
|
||||
return createScalarTypeNode("any pointer", getChar(), Size);
|
||||
|
||||
// Enum types are distinct types. In C++ they have "underlying types",
|
||||
// however they aren't related for TBAA.
|
||||
|
@ -167,7 +171,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
|
|||
SmallString<256> OutName;
|
||||
llvm::raw_svector_ostream Out(OutName);
|
||||
MContext.mangleTypeName(QualType(ETy, 0), Out);
|
||||
return createTBAAScalarType(OutName, getChar());
|
||||
return createScalarTypeNode(OutName, getChar(), Size);
|
||||
}
|
||||
|
||||
// For now, handle any other kind of type conservatively.
|
||||
|
@ -204,8 +208,11 @@ llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
|
|||
return MetadataCache[Ty] = TypeNode;
|
||||
}
|
||||
|
||||
TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo() {
|
||||
return TBAAAccessInfo(createTBAAScalarType("vtable pointer", getRoot()));
|
||||
TBAAAccessInfo CodeGenTBAA::getVTablePtrAccessInfo(llvm::Type *VTablePtrType) {
|
||||
llvm::DataLayout DL(&Module);
|
||||
unsigned Size = DL.getPointerTypeSize(VTablePtrType);
|
||||
return TBAAAccessInfo(createScalarTypeNode("vtable pointer", getRoot(), Size),
|
||||
Size);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -245,7 +252,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
|
|||
uint64_t Offset = BaseOffset;
|
||||
uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
|
||||
llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy);
|
||||
llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType));
|
||||
llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
|
||||
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
|
||||
return true;
|
||||
}
|
||||
|
@ -268,19 +275,20 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
|
|||
llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
|
||||
if (auto *TTy = dyn_cast<RecordType>(Ty)) {
|
||||
const RecordDecl *RD = TTy->getDecl()->getDefinition();
|
||||
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
SmallVector <std::pair<llvm::MDNode*, uint64_t>, 4> Fields;
|
||||
unsigned idx = 0;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(),
|
||||
e = RD->field_end(); i != e; ++i, ++idx) {
|
||||
QualType FieldQTy = i->getType();
|
||||
llvm::MDNode *FieldNode = isValidBaseType(FieldQTy) ?
|
||||
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
|
||||
for (FieldDecl *Field : RD->fields()) {
|
||||
QualType FieldQTy = Field->getType();
|
||||
llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
|
||||
getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
|
||||
if (!FieldNode)
|
||||
if (!TypeNode)
|
||||
return BaseTypeMetadataCache[Ty] = nullptr;
|
||||
Fields.push_back(std::make_pair(
|
||||
FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
|
||||
|
||||
uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
|
||||
uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
|
||||
uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
|
||||
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
|
||||
TypeNode));
|
||||
}
|
||||
|
||||
SmallString<256> OutName;
|
||||
|
@ -291,8 +299,15 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
|
|||
} else {
|
||||
OutName = RD->getName();
|
||||
}
|
||||
|
||||
// TODO: Support size-aware type nodes and create one here for the
|
||||
// given aggregate type.
|
||||
|
||||
// Create the struct type node with a vector of pairs (offset, type).
|
||||
return MDHelper.createTBAAStructTypeNode(OutName, Fields);
|
||||
SmallVector<std::pair<llvm::MDNode*, uint64_t>, 4> OffsetsAndTypes;
|
||||
for (const auto &Field : Fields)
|
||||
OffsetsAndTypes.push_back(std::make_pair(Field.TBAA, Field.Offset));
|
||||
return MDHelper.createTBAAStructTypeNode(OutName, OffsetsAndTypes);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -314,14 +329,16 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
|
|||
}
|
||||
|
||||
llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
|
||||
assert(!Info.isIncomplete() && "Access to an object of an incomplete type!");
|
||||
|
||||
if (Info.isMayAlias())
|
||||
Info = TBAAAccessInfo(getChar());
|
||||
Info = TBAAAccessInfo(getChar(), Info.Size);
|
||||
|
||||
if (!Info.AccessType)
|
||||
return nullptr;
|
||||
|
||||
if (!CodeGenOpts.StructPathTBAA)
|
||||
Info = TBAAAccessInfo(Info.AccessType);
|
||||
Info = TBAAAccessInfo(Info.AccessType, Info.Size);
|
||||
|
||||
llvm::MDNode *&N = AccessTagMetadataCache[Info];
|
||||
if (N)
|
||||
|
|
|
@ -36,40 +36,53 @@ class CGRecordLayout;
|
|||
enum class TBAAAccessKind : unsigned {
|
||||
Ordinary,
|
||||
MayAlias,
|
||||
Incomplete,
|
||||
};
|
||||
|
||||
// TBAAAccessInfo - Describes a memory access in terms of TBAA.
|
||||
struct TBAAAccessInfo {
|
||||
TBAAAccessInfo(TBAAAccessKind Kind, llvm::MDNode *BaseType,
|
||||
llvm::MDNode *AccessType, uint64_t Offset)
|
||||
: Kind(Kind), BaseType(BaseType), AccessType(AccessType), Offset(Offset)
|
||||
llvm::MDNode *AccessType, uint64_t Offset, uint64_t Size)
|
||||
: Kind(Kind), BaseType(BaseType), AccessType(AccessType),
|
||||
Offset(Offset), Size(Size)
|
||||
{}
|
||||
|
||||
TBAAAccessInfo(llvm::MDNode *BaseType, llvm::MDNode *AccessType,
|
||||
uint64_t Offset)
|
||||
: TBAAAccessInfo(TBAAAccessKind::Ordinary, BaseType, AccessType, Offset)
|
||||
uint64_t Offset, uint64_t Size)
|
||||
: TBAAAccessInfo(TBAAAccessKind::Ordinary, BaseType, AccessType,
|
||||
Offset, Size)
|
||||
{}
|
||||
|
||||
explicit TBAAAccessInfo(llvm::MDNode *AccessType)
|
||||
: TBAAAccessInfo(/* BaseType= */ nullptr, AccessType, /* Offset= */ 0)
|
||||
explicit TBAAAccessInfo(llvm::MDNode *AccessType, uint64_t Size)
|
||||
: TBAAAccessInfo(/* BaseType= */ nullptr, AccessType, /* Offset= */ 0, Size)
|
||||
{}
|
||||
|
||||
TBAAAccessInfo()
|
||||
: TBAAAccessInfo(/* AccessType= */ nullptr)
|
||||
: TBAAAccessInfo(/* AccessType= */ nullptr, /* Size= */ 0)
|
||||
{}
|
||||
|
||||
static TBAAAccessInfo getMayAliasInfo() {
|
||||
return TBAAAccessInfo(TBAAAccessKind::MayAlias, /* BaseType= */ nullptr,
|
||||
/* AccessType= */ nullptr, /* Offset= */ 0);
|
||||
return TBAAAccessInfo(TBAAAccessKind::MayAlias,
|
||||
/* BaseType= */ nullptr, /* AccessType= */ nullptr,
|
||||
/* Offset= */ 0, /* Size= */ 0);
|
||||
}
|
||||
|
||||
bool isMayAlias() const { return Kind == TBAAAccessKind::MayAlias; }
|
||||
|
||||
static TBAAAccessInfo getIncompleteInfo() {
|
||||
return TBAAAccessInfo(TBAAAccessKind::Incomplete,
|
||||
/* BaseType= */ nullptr, /* AccessType= */ nullptr,
|
||||
/* Offset= */ 0, /* Size= */ 0);
|
||||
}
|
||||
|
||||
bool isIncomplete() const { return Kind == TBAAAccessKind::Incomplete; }
|
||||
|
||||
bool operator==(const TBAAAccessInfo &Other) const {
|
||||
return Kind == Other.Kind &&
|
||||
BaseType == Other.BaseType &&
|
||||
AccessType == Other.AccessType &&
|
||||
Offset == Other.Offset;
|
||||
Offset == Other.Offset &&
|
||||
Size == Other.Size;
|
||||
}
|
||||
|
||||
bool operator!=(const TBAAAccessInfo &Other) const {
|
||||
|
@ -95,12 +108,16 @@ struct TBAAAccessInfo {
|
|||
/// Offset - The byte offset of the final access within the base one. Must be
|
||||
/// zero if the base access type is not specified.
|
||||
uint64_t Offset;
|
||||
|
||||
/// Size - The size of access, in bytes.
|
||||
uint64_t Size;
|
||||
};
|
||||
|
||||
/// CodeGenTBAA - This class organizes the cross-module state that is used
|
||||
/// while lowering AST types to LLVM types.
|
||||
class CodeGenTBAA {
|
||||
ASTContext &Context;
|
||||
llvm::Module &Module;
|
||||
const CodeGenOptions &CodeGenOpts;
|
||||
const LangOptions &Features;
|
||||
MangleContext &MContext;
|
||||
|
@ -138,10 +155,10 @@ class CodeGenTBAA {
|
|||
SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields,
|
||||
bool MayAlias);
|
||||
|
||||
/// A wrapper function to create a scalar type. For struct-path aware TBAA,
|
||||
/// the scalar type has the same format as the struct type: name, offset,
|
||||
/// pointer to another node in the type DAG.
|
||||
llvm::MDNode *createTBAAScalarType(StringRef Name, llvm::MDNode *Parent);
|
||||
/// createScalarTypeNode - A wrapper function to create a metadata node
|
||||
/// describing a scalar type.
|
||||
llvm::MDNode *createScalarTypeNode(StringRef Name, llvm::MDNode *Parent,
|
||||
uint64_t Size);
|
||||
|
||||
/// getTypeInfoHelper - An internal helper function to generate metadata used
|
||||
/// to describe accesses to objects of the given type.
|
||||
|
@ -152,10 +169,8 @@ class CodeGenTBAA {
|
|||
llvm::MDNode *getBaseTypeInfoHelper(const Type *Ty);
|
||||
|
||||
public:
|
||||
CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
|
||||
const CodeGenOptions &CGO,
|
||||
const LangOptions &Features,
|
||||
MangleContext &MContext);
|
||||
CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, const CodeGenOptions &CGO,
|
||||
const LangOptions &Features, MangleContext &MContext);
|
||||
~CodeGenTBAA();
|
||||
|
||||
/// getTypeInfo - Get metadata used to describe accesses to objects of the
|
||||
|
@ -164,7 +179,7 @@ public:
|
|||
|
||||
/// getVTablePtrAccessInfo - Get the TBAA information that describes an
|
||||
/// access to a virtual table pointer.
|
||||
TBAAAccessInfo getVTablePtrAccessInfo();
|
||||
TBAAAccessInfo getVTablePtrAccessInfo(llvm::Type *VTablePtrType);
|
||||
|
||||
/// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of
|
||||
/// the given type.
|
||||
|
@ -200,6 +215,7 @@ template<> struct DenseMapInfo<clang::CodeGen::TBAAAccessInfo> {
|
|||
static_cast<clang::CodeGen::TBAAAccessKind>(UnsignedKey),
|
||||
DenseMapInfo<MDNode *>::getEmptyKey(),
|
||||
DenseMapInfo<MDNode *>::getEmptyKey(),
|
||||
DenseMapInfo<uint64_t>::getEmptyKey(),
|
||||
DenseMapInfo<uint64_t>::getEmptyKey());
|
||||
}
|
||||
|
||||
|
@ -209,6 +225,7 @@ template<> struct DenseMapInfo<clang::CodeGen::TBAAAccessInfo> {
|
|||
static_cast<clang::CodeGen::TBAAAccessKind>(UnsignedKey),
|
||||
DenseMapInfo<MDNode *>::getTombstoneKey(),
|
||||
DenseMapInfo<MDNode *>::getTombstoneKey(),
|
||||
DenseMapInfo<uint64_t>::getTombstoneKey(),
|
||||
DenseMapInfo<uint64_t>::getTombstoneKey());
|
||||
}
|
||||
|
||||
|
@ -217,7 +234,8 @@ template<> struct DenseMapInfo<clang::CodeGen::TBAAAccessInfo> {
|
|||
return DenseMapInfo<unsigned>::getHashValue(KindValue) ^
|
||||
DenseMapInfo<MDNode *>::getHashValue(Val.BaseType) ^
|
||||
DenseMapInfo<MDNode *>::getHashValue(Val.AccessType) ^
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Offset);
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Offset) ^
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Size);
|
||||
}
|
||||
|
||||
static bool isEqual(const clang::CodeGen::TBAAAccessInfo &LHS,
|
||||
|
|
Loading…
Reference in New Issue