Skip to content

Commit

Permalink
[CodeGen] Collect information about sizes of accesses and access type…
Browse files Browse the repository at this point in the history
…s 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
  • Loading branch information
Ivan A. Kosarev committed Nov 27, 2017
1 parent b833bf6 commit 4e50e70
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 55 deletions.
6 changes: 4 additions & 2 deletions clang/lib/CodeGen/CGClass.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
15 changes: 11 additions & 4 deletions clang/lib/CodeGen/CodeGenModule.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.h
Expand Up @@ -664,7 +664,7 @@ class CodeGenModule : public CodeGenTypeCache {

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

Expand Down
73 changes: 45 additions & 28 deletions clang/lib/CodeGen/CodeGenTBAA.cpp
Expand Up @@ -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() {
}
Expand All @@ -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);
}

Expand All @@ -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;
}
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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)
Expand Down
58 changes: 38 additions & 20 deletions clang/lib/CodeGen/CodeGenTBAA.h
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -164,7 +179,7 @@ class CodeGenTBAA {

/// 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.
Expand Down Expand Up @@ -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());
}

Expand All @@ -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());
}

Expand All @@ -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,
Expand Down

0 comments on commit 4e50e70

Please sign in to comment.