[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:
Ivan A. Kosarev 2017-11-27 09:39:29 +00:00
parent b833bf6ae1
commit 4e50e707bf
5 changed files with 99 additions and 55 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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)

View File

@ -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,