forked from OSchip/llvm-project
Add basic support for adding !tbaa.struct metadata on llvm.memcpy calls for
struct assignment. llvm-svn: 164853
This commit is contained in:
parent
3852b3e189
commit
22695fcec3
|
@ -1362,11 +1362,17 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the metadata to describe the position of any padding in this
|
||||
// memcpy, as well as the TBAA tags for the members of the struct, in case
|
||||
// the optimizer wishes to expand it in to scalar memory operations.
|
||||
llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty);
|
||||
|
||||
Builder.CreateMemCpy(DestPtr, SrcPtr,
|
||||
llvm::ConstantInt::get(IntPtrTy,
|
||||
TypeInfo.first.getQuantity()),
|
||||
alignment.getQuantity(), isVolatile);
|
||||
alignment.getQuantity(), isVolatile,
|
||||
/*TBAATag=*/0, TBAAStructTag);
|
||||
}
|
||||
|
||||
void CodeGenFunction::MaybeEmitStdInitializerListCleanup(llvm::Value *loc,
|
||||
|
|
|
@ -202,6 +202,12 @@ llvm::MDNode *CodeGenModule::getTBAAInfoForVTablePtr() {
|
|||
return TBAA->getTBAAInfoForVTablePtr();
|
||||
}
|
||||
|
||||
llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
|
||||
if (!TBAA)
|
||||
return 0;
|
||||
return TBAA->getTBAAStructInfo(QTy);
|
||||
}
|
||||
|
||||
void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
|
||||
llvm::MDNode *TBAAInfo) {
|
||||
Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);
|
||||
|
|
|
@ -461,6 +461,7 @@ public:
|
|||
|
||||
llvm::MDNode *getTBAAInfo(QualType QTy);
|
||||
llvm::MDNode *getTBAAInfoForVTablePtr();
|
||||
llvm::MDNode *getTBAAStructInfo(QualType QTy);
|
||||
|
||||
bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "CodeGenTBAA.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
#include "clang/AST/Mangle.h"
|
||||
#include "clang/Frontend/CodeGenOptions.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
|
@ -167,3 +168,59 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
|
|||
llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
|
||||
return MDHelper.createTBAANode("vtable pointer", getRoot());
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenTBAA::CollectFields(uint64_t BaseOffset,
|
||||
QualType QTy,
|
||||
SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &
|
||||
Fields,
|
||||
bool MayAlias) {
|
||||
/* Things not handled yet include: C++ base classes, bitfields, */
|
||||
|
||||
if (const RecordType *TTy = QTy->getAs<RecordType>()) {
|
||||
const RecordDecl *RD = TTy->getDecl()->getDefinition();
|
||||
if (RD->hasFlexibleArrayMember())
|
||||
return false;
|
||||
|
||||
// TODO: Handle C++ base classes.
|
||||
if (const CXXRecordDecl *Decl = dyn_cast<CXXRecordDecl>(RD))
|
||||
if (Decl->bases_begin() != Decl->bases_end())
|
||||
return false;
|
||||
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
|
||||
unsigned idx = 0;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(),
|
||||
e = RD->field_end(); i != e; ++i, ++idx) {
|
||||
uint64_t Offset = BaseOffset +
|
||||
Layout.getFieldOffset(idx) / Context.getCharWidth();
|
||||
QualType FieldQTy = i->getType();
|
||||
if (!CollectFields(Offset, FieldQTy, Fields,
|
||||
MayAlias || TypeHasMayAlias(FieldQTy)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Otherwise, treat whatever it is as a field. */
|
||||
uint64_t Offset = BaseOffset;
|
||||
uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
|
||||
llvm::MDNode *TBAAInfo = MayAlias ? getChar() : getTBAAInfo(QTy);
|
||||
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAAInfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
llvm::MDNode *
|
||||
CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
|
||||
const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
|
||||
|
||||
if (llvm::MDNode *N = StructMetadataCache[Ty])
|
||||
return N;
|
||||
|
||||
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
|
||||
if (CollectFields(0, QTy, Fields, TypeHasMayAlias(QTy)))
|
||||
return MDHelper.createTBAAStructNode(Fields);
|
||||
|
||||
// For now, handle any other kind of type conservatively.
|
||||
return StructMetadataCache[Ty] = NULL;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ class CodeGenTBAA {
|
|||
/// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.
|
||||
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
|
||||
|
||||
/// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing
|
||||
/// them for struct assignments.
|
||||
llvm::DenseMap<const Type *, llvm::MDNode *> StructMetadataCache;
|
||||
|
||||
llvm::MDNode *Root;
|
||||
llvm::MDNode *Char;
|
||||
|
||||
|
@ -60,6 +64,13 @@ class CodeGenTBAA {
|
|||
/// considered to be equivalent to it.
|
||||
llvm::MDNode *getChar();
|
||||
|
||||
/// CollectFields - Collect information about the fields of a type for
|
||||
/// !tbaa.struct metadata formation. Return false for an unsupported type.
|
||||
bool CollectFields(uint64_t BaseOffset,
|
||||
QualType Ty,
|
||||
SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields,
|
||||
bool MayAlias);
|
||||
|
||||
public:
|
||||
CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
|
||||
const CodeGenOptions &CGO,
|
||||
|
@ -74,6 +85,10 @@ public:
|
|||
/// getTBAAInfoForVTablePtr - Get the TBAA MDNode to be used for a
|
||||
/// dereference of a vtable pointer.
|
||||
llvm::MDNode *getTBAAInfoForVTablePtr();
|
||||
|
||||
/// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of
|
||||
/// the given type.
|
||||
llvm::MDNode *getTBAAStructInfo(QualType QTy);
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -o - -O1 %s | FileCheck %s
|
||||
//
|
||||
// Check that we generate !tbaa.struct metadata for struct copies.
|
||||
struct A {
|
||||
short s;
|
||||
int i;
|
||||
char c;
|
||||
int j;
|
||||
};
|
||||
|
||||
void copy(struct A *a, struct A *b) {
|
||||
*a = *b;
|
||||
}
|
||||
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 16, i32 4, i1 false), !tbaa.struct [[TS:!.*]]
|
||||
// CHECK: [[TS]] = metadata !{i64 0, i64 2, metadata !{{.*}}, i64 4, i64 4, metadata !{{.*}}, i64 8, i64 1, metadata !{{.*}}, i64 12, i64 4, metadata !{{.*}}}
|
Loading…
Reference in New Issue