summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenTBAA.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CodeGenTBAA.cpp')
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp265
1 files changed, 157 insertions, 108 deletions
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index 8a75a552d9faa..f394ea288d469 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -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;
}
@@ -88,21 +90,27 @@ static bool TypeHasMayAlias(QualType QTy) {
return false;
}
-llvm::MDNode *
-CodeGenTBAA::getTBAAInfo(QualType QTy) {
- // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
- if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
- return nullptr;
-
- // If the type has the may_alias attribute (even on a typedef), it is
- // effectively in the general char alias class.
- if (TypeHasMayAlias(QTy))
- return getChar();
-
- const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+/// Check if the given type is a valid base type to be used in access tags.
+static bool isValidBaseType(QualType QTy) {
+ if (QTy->isReferenceType())
+ return false;
+ if (const RecordType *TTy = QTy->getAs<RecordType>()) {
+ const RecordDecl *RD = TTy->getDecl()->getDefinition();
+ // Incomplete types are not valid base access types.
+ if (!RD)
+ return false;
+ if (RD->hasFlexibleArrayMember())
+ return false;
+ // RD can be struct, union, class, interface or enum.
+ // For now, we only handle struct and class.
+ if (RD->isStruct() || RD->isClass())
+ return true;
+ }
+ return false;
+}
- if (llvm::MDNode *N = MetadataCache[Ty])
- return N;
+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)) {
@@ -120,22 +128,21 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// Unsigned types can alias their corresponding signed types.
case BuiltinType::UShort:
- return getTBAAInfo(Context.ShortTy);
+ return getTypeInfo(Context.ShortTy);
case BuiltinType::UInt:
- return getTBAAInfo(Context.IntTy);
+ return getTypeInfo(Context.IntTy);
case BuiltinType::ULong:
- return getTBAAInfo(Context.LongTy);
+ return getTypeInfo(Context.LongTy);
case BuiltinType::ULongLong:
- return getTBAAInfo(Context.LongLongTy);
+ return getTypeInfo(Context.LongLongTy);
case BuiltinType::UInt128:
- return getTBAAInfo(Context.Int128Ty);
+ return getTypeInfo(Context.Int128Ty);
// Treat all other builtin types as distinct types. This includes
// treating wchar_t, char16_t, and char32_t as distinct from their
// "underlying types".
default:
- return MetadataCache[Ty] =
- createTBAAScalarType(BTy->getName(Features), getChar());
+ return createScalarTypeNode(BTy->getName(Features), getChar(), Size);
}
}
@@ -143,14 +150,13 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// an object through a glvalue of other than one of the following types the
// behavior is undefined: [...] a char, unsigned char, or std::byte type."
if (Ty->isStdByteType())
- return MetadataCache[Ty] = getChar();
+ return getChar();
- // Handle pointers.
+ // Handle pointers and references.
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
// pointers distinct.
- if (Ty->isPointerType())
- return MetadataCache[Ty] = createTBAAScalarType("any pointer",
- getChar());
+ if (Ty->isPointerType() || Ty->isReferenceType())
+ return createScalarTypeNode("any pointer", getChar(), Size);
// Enum types are distinct types. In C++ they have "underlying types",
// however they aren't related for TBAA.
@@ -160,20 +166,53 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// TODO: Is there a way to get a program-wide unique name for a
// decl with local linkage or no linkage?
if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible())
- return MetadataCache[Ty] = getChar();
+ return getChar();
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
MContext.mangleTypeName(QualType(ETy, 0), Out);
- return MetadataCache[Ty] = createTBAAScalarType(OutName, getChar());
+ return createScalarTypeNode(OutName, getChar(), Size);
}
// For now, handle any other kind of type conservatively.
- return MetadataCache[Ty] = getChar();
+ return getChar();
+}
+
+llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
+ // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
+ if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
+ return nullptr;
+
+ // If the type has the may_alias attribute (even on a typedef), it is
+ // effectively in the general char alias class.
+ if (TypeHasMayAlias(QTy))
+ return getChar();
+
+ // We need this function to not fall back to returning the "omnipotent char"
+ // type node for aggregate and union types. Otherwise, any dereference of an
+ // aggregate will result into the may-alias access descriptor, meaning all
+ // subsequent accesses to direct and indirect members of that aggregate will
+ // be considered may-alias too.
+ // TODO: Combine getTypeInfo() and getBaseTypeInfo() into a single function.
+ if (isValidBaseType(QTy))
+ return getBaseTypeInfo(QTy);
+
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+ if (llvm::MDNode *N = MetadataCache[Ty])
+ return N;
+
+ // Note that the following helper call is allowed to add new nodes to the
+ // cache, which invalidates all its previously obtained iterators. So we
+ // first generate the node for the type and then add that node to the cache.
+ llvm::MDNode *TypeNode = getTypeInfoHelper(Ty);
+ return MetadataCache[Ty] = TypeNode;
}
-llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
- return 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
@@ -212,8 +251,8 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
/* 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);
- llvm::MDNode *TBAATag = getTBAAScalarTagInfo(TBAAInfo);
+ llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy);
+ llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
return true;
}
@@ -233,46 +272,23 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
return StructMetadataCache[Ty] = nullptr;
}
-/// Check if the given type can be handled by path-aware TBAA.
-static bool isTBAAPathStruct(QualType QTy) {
- if (const RecordType *TTy = QTy->getAs<RecordType>()) {
- const RecordDecl *RD = TTy->getDecl()->getDefinition();
- if (RD->hasFlexibleArrayMember())
- return false;
- // RD can be struct, union, class, interface or enum.
- // For now, we only handle struct and class.
- if (RD->isStruct() || RD->isClass())
- return true;
- }
- return false;
-}
-
-llvm::MDNode *
-CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
- const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
- assert(isTBAAPathStruct(QTy));
-
- if (llvm::MDNode *N = StructTypeMetadataCache[Ty])
- return N;
-
- if (const RecordType *TTy = QTy->getAs<RecordType>()) {
+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;
- if (isTBAAPathStruct(FieldQTy))
- FieldNode = getTBAAStructTypeInfo(FieldQTy);
- else
- FieldNode = getTBAAInfo(FieldQTy);
- if (!FieldNode)
- return StructTypeMetadataCache[Ty] = nullptr;
- Fields.push_back(std::make_pair(
- FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
+ 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 (!TypeNode)
+ return BaseTypeMetadataCache[Ty] = nullptr;
+
+ 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;
@@ -283,47 +299,80 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
} 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 StructTypeMetadataCache[Ty] =
- 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.Type, Field.Offset));
+ return MDHelper.createTBAAStructTypeNode(OutName, OffsetsAndTypes);
}
- return StructMetadataCache[Ty] = nullptr;
+ return nullptr;
}
-/// Return a TBAA tag node for both scalar TBAA and struct-path aware TBAA.
-llvm::MDNode *
-CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
- uint64_t Offset) {
- if (!AccessNode)
+llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
+ if (!isValidBaseType(QTy))
+ return nullptr;
+
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+ if (llvm::MDNode *N = BaseTypeMetadataCache[Ty])
+ return N;
+
+ // Note that the following helper call is allowed to add new nodes to the
+ // cache, which invalidates all its previously obtained iterators. So we
+ // first generate the node for the type and then add that node to the cache.
+ llvm::MDNode *TypeNode = getBaseTypeInfoHelper(Ty);
+ return BaseTypeMetadataCache[Ty] = TypeNode;
+}
+
+llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
+ assert(!Info.isIncomplete() && "Access to an object of an incomplete type!");
+
+ if (Info.isMayAlias())
+ Info = TBAAAccessInfo(getChar(), Info.Size);
+
+ if (!Info.AccessType)
return nullptr;
if (!CodeGenOpts.StructPathTBAA)
- return getTBAAScalarTagInfo(AccessNode);
+ Info = TBAAAccessInfo(Info.AccessType, Info.Size);
- const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();
- TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);
- if (llvm::MDNode *N = StructTagMetadataCache[PathTag])
+ llvm::MDNode *&N = AccessTagMetadataCache[Info];
+ if (N)
return N;
- llvm::MDNode *BNode = nullptr;
- if (isTBAAPathStruct(BaseQTy))
- BNode = getTBAAStructTypeInfo(BaseQTy);
- if (!BNode)
- return StructTagMetadataCache[PathTag] =
- MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0);
+ if (!Info.BaseType) {
+ Info.BaseType = Info.AccessType;
+ assert(!Info.Offset && "Nonzero offset for an access with no base type!");
+ }
+ return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType,
+ Info.Offset);
+}
- return StructTagMetadataCache[PathTag] =
- MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset);
+TBAAAccessInfo CodeGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
+ TBAAAccessInfo TargetInfo) {
+ if (SourceInfo.isMayAlias() || TargetInfo.isMayAlias())
+ return TBAAAccessInfo::getMayAliasInfo();
+ return TargetInfo;
}
-llvm::MDNode *
-CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) {
- if (!AccessNode)
- return nullptr;
- if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode])
- return N;
+TBAAAccessInfo
+CodeGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA,
+ TBAAAccessInfo InfoB) {
+ if (InfoA == InfoB)
+ return InfoA;
+
+ if (!InfoA || !InfoB)
+ return TBAAAccessInfo();
+
+ if (InfoA.isMayAlias() || InfoB.isMayAlias())
+ return TBAAAccessInfo::getMayAliasInfo();
- return ScalarTagMetadataCache[AccessNode] =
- MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0);
+ // TODO: Implement the rest of the logic here. For example, two accesses
+ // with same final access types result in an access to an object of that final
+ // access type regardless of their base types.
+ return TBAAAccessInfo::getMayAliasInfo();
}