addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits());
return LValue::MakeAddr(addr, getValueType(), CGF.getContext(),
- LVal.getBaseInfo(), LVal.getTBAAAccessType());
+ LVal.getBaseInfo(), LVal.getTBAAInfo());
}
/// \brief Emits atomic load.
// Other decoration.
if (IsVolatile)
Load->setVolatile(true);
- TBAAAccessInfo TBAAInfo(LVal.getTBAAAccessType());
- CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
+ CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());
return Load;
}
// Other decoration.
if (IsVolatile)
store->setVolatile(true);
- TBAAAccessInfo TBAAInfo(dest.getTBAAAccessType());
- CGM.DecorateInstructionWithTBAA(store, TBAAInfo);
+ CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());
return;
}
llvm::Value *V = LV.getPointer();
Scope.ForceCleanup({&V});
return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(),
- getContext(), LV.getBaseInfo(),
- LV.getTBAAAccessType());
+ getContext(), LV.getBaseInfo(), LV.getTBAAInfo());
}
// FIXME: Is it possible to create an ExprWithCleanups that produces a
// bitfield lvalue or some other non-simple lvalue?
// Atomic operations have to be done on integral types.
LValue AtomicLValue =
- LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo.AccessType);
+ LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo);
if (Ty->isAtomicType() || LValueIsSuitableForInlineAtomic(AtomicLValue)) {
return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal();
}
Load->getContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
}
- if (TBAAInfo.AccessType) {
- if (BaseInfo.getMayAlias())
- TBAAInfo = CGM.getTBAAMayAliasAccessInfo();
- CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
- }
+
+ if (BaseInfo.getMayAlias())
+ TBAAInfo = CGM.getTBAAMayAliasAccessInfo();
+ CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
if (EmitScalarRangeCheck(Load, Ty, Loc)) {
// In order to prevent the optimizer from throwing away the check, don't
Value = EmitToMemory(Value, Ty);
LValue AtomicLValue =
- LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo.AccessType);
+ LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo);
if (Ty->isAtomicType() ||
(!isInit && LValueIsSuitableForInlineAtomic(AtomicLValue))) {
EmitAtomicStore(RValue::get(Value), AtomicLValue, isInit);
llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
}
- if (TBAAInfo.AccessType) {
- if (BaseInfo.getMayAlias())
- TBAAInfo = CGM.getTBAAMayAliasAccessInfo();
- CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
- }
+
+ if (BaseInfo.getMayAlias())
+ TBAAInfo = CGM.getTBAAMayAliasAccessInfo();
+ CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
}
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
LValue LV = MakeAddrLValue(addr, type, FieldBaseInfo);
LV.getQuals().addCVRQualifiers(cvr);
- if (TBAAPath) {
+
+ // Fields of may_alias structs act like 'char' for TBAA purposes.
+ // FIXME: this should get propagated down through anonymous structs
+ // and unions.
+ if (mayAlias) {
+ LV.setTBAAInfo(CGM.getTBAAMayAliasAccessInfo());
+ } else if (TBAAPath) {
+ // If no base type been assigned for the base access, then try to generate
+ // one for this base lvalue.
+ TBAAAccessInfo TBAAInfo = base.getTBAAInfo();
+ if (!TBAAInfo.BaseType) {
+ TBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType());
+ assert(!TBAAInfo.Offset &&
+ "Nonzero offset for an access with no base type!");
+ }
+
+ // Adjust offset to be relative to the base type.
const ASTRecordLayout &Layout =
getContext().getASTRecordLayout(field->getParent());
- // Set the base type to be the base type of the base LValue and
- // update offset to be relative to the base type.
unsigned CharWidth = getContext().getCharWidth();
- TBAAAccessInfo TBAAInfo = mayAlias ?
- CGM.getTBAAMayAliasAccessInfo() :
- TBAAAccessInfo(base.getTBAAInfo().BaseType, CGM.getTBAATypeInfo(type),
- base.getTBAAInfo().Offset + Layout.getFieldOffset(
- field->getFieldIndex()) / CharWidth);
+ if (TBAAInfo.BaseType)
+ TBAAInfo.Offset +=
+ Layout.getFieldOffset(field->getFieldIndex()) / CharWidth;
+
+ // Update the final access type.
+ TBAAInfo.AccessType = LV.getTBAAInfo().AccessType;
+
LV.setTBAAInfo(TBAAInfo);
}
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
LV.getQuals().removeObjCGCAttr();
- // Fields of may_alias structs act like 'char' for TBAA purposes.
- // FIXME: this should get propagated down through anonymous structs
- // and unions.
- if (mayAlias && LV.getTBAAAccessType())
- LV.setTBAAInfo(CGM.getTBAAMayAliasAccessInfo());
-
return LV;
}
private:
void Initialize(QualType Type, Qualifiers Quals,
CharUnits Alignment, LValueBaseInfo BaseInfo,
- llvm::MDNode *TBAAAccessType = nullptr) {
+ TBAAAccessInfo TBAAInfo = TBAAAccessInfo()) {
assert((!Alignment.isZero() || Type->isIncompleteType()) &&
"initializing l-value with zero alignment!");
this->Type = Type;
assert(this->Alignment == Alignment.getQuantity() &&
"Alignment exceeds allowed max!");
this->BaseInfo = BaseInfo;
- this->TBAAInfo = TBAAAccessInfo(Type, TBAAAccessType, /* Offset= */ 0);
+ this->TBAAInfo = TBAAInfo;
// Initialize Objective-C flags.
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
TBAAAccessInfo getTBAAInfo() const { return TBAAInfo; }
void setTBAAInfo(TBAAAccessInfo Info) { TBAAInfo = Info; }
- llvm::MDNode *getTBAAAccessType() const { return TBAAInfo.AccessType; }
- void setTBAAAccessType(llvm::MDNode *N) { TBAAInfo.AccessType = N; }
-
const Qualifiers &getQuals() const { return Quals; }
Qualifiers &getQuals() { return Quals; }
// global register lvalue
llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; }
- static LValue MakeAddr(Address address, QualType type,
- ASTContext &Context,
- LValueBaseInfo BaseInfo,
- llvm::MDNode *TBAAAccessType = nullptr) {
+ static LValue MakeAddr(Address address, QualType type, ASTContext &Context,
+ LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) {
Qualifiers qs = type.getQualifiers();
qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
R.LVType = Simple;
assert(address.getPointer()->getType()->isPointerTy());
R.V = address.getPointer();
- R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAAccessType);
+ R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo);
return R;
}
LValueBaseInfo BaseInfo;
CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo);
return LValue::MakeAddr(Address(V, Alignment), T, getContext(), BaseInfo,
- CGM.getTBAATypeInfo(T));
+ CGM.getTBAAAccessInfo(T));
}
/// Given a value of type T* that may not be to a complete object,
LValueBaseInfo BaseInfo =
LValueBaseInfo(AlignmentSource::Type)) {
return LValue::MakeAddr(Addr, T, getContext(), BaseInfo,
- CGM.getTBAATypeInfo(T));
+ CGM.getTBAAAccessInfo(T));
}
LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment,
LValueBaseInfo BaseInfo =
LValueBaseInfo(AlignmentSource::Type)) {
return LValue::MakeAddr(Address(V, Alignment), T, getContext(),
- BaseInfo, CGM.getTBAATypeInfo(T));
+ BaseInfo, CGM.getTBAAAccessInfo(T));
}
LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T);
SourceLocation Loc,
LValueBaseInfo BaseInfo =
LValueBaseInfo(AlignmentSource::Type),
- TBAAAccessInfo TBAAInfo = TBAAAccessInfo(),
+ bool isNontemporal = false) {
+ return EmitLoadOfScalar(Addr, Volatile, Ty, Loc, BaseInfo,
+ CGM.getTBAAAccessInfo(Ty), isNontemporal);
+ }
+
+ llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty,
+ SourceLocation Loc, LValueBaseInfo BaseInfo,
+ TBAAAccessInfo TBAAInfo,
bool isNontemporal = false);
/// EmitLoadOfScalar - Load a scalar value from an address, taking
bool Volatile, QualType Ty,
LValueBaseInfo BaseInfo =
LValueBaseInfo(AlignmentSource::Type),
- TBAAAccessInfo TBAAInfo = TBAAAccessInfo(),
+ bool isInit = false, bool isNontemporal = false) {
+ EmitStoreOfScalar(Value, Addr, Volatile, Ty, BaseInfo,
+ CGM.getTBAAAccessInfo(Ty), isInit, isNontemporal);
+ }
+
+ void EmitStoreOfScalar(llvm::Value *Value, Address Addr,
+ bool Volatile, QualType Ty,
+ LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo,
bool isInit = false, bool isNontemporal = false);
/// EmitStoreOfScalar - Store a scalar value to an address, taking
return TBAA->getTBAAStructInfo(QTy);
}
+llvm::MDNode *CodeGenModule::getTBAABaseTypeInfo(QualType QTy) {
+ if (!TBAA)
+ return nullptr;
+ return TBAA->getBaseTypeInfo(QTy);
+}
+
llvm::MDNode *CodeGenModule::getTBAAAccessTagInfo(TBAAAccessInfo Info) {
if (!TBAA)
return nullptr;
llvm::MDNode *getTBAAStructInfo(QualType QTy);
+ /// getTBAABaseTypeInfo - Get metadata that describes the given base access
+ /// type. Return null if the type is not suitable for use in TBAA access tags.
+ llvm::MDNode *getTBAABaseTypeInfo(QualType QTy);
+
/// getTBAAAccessTagInfo - Get TBAA tag for a given memory access.
llvm::MDNode *getTBAAAccessTagInfo(TBAAAccessInfo Info);
/// Check if the given type is a valid base type to be used in access tags.
static bool isValidBaseType(QualType QTy) {
- if (QTy == QualType())
- return false;
if (const RecordType *TTy = QTy->getAs<RecordType>()) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
if (RD->hasFlexibleArrayMember())
}
llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
- const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
- assert(isValidBaseType(QTy));
+ if (!isValidBaseType(QTy))
+ return nullptr;
- if (llvm::MDNode *N = StructTypeMetadataCache[Ty])
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+ if (llvm::MDNode *N = BaseTypeMetadataCache[Ty])
return N;
if (const RecordType *TTy = QTy->getAs<RecordType>()) {
llvm::MDNode *FieldNode = isValidBaseType(FieldQTy) ?
getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
if (!FieldNode)
- return StructTypeMetadataCache[Ty] = nullptr;
+ return BaseTypeMetadataCache[Ty] = nullptr;
Fields.push_back(std::make_pair(
FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
}
OutName = RD->getName();
}
// Create the struct type node with a vector of pairs (offset, type).
- return StructTypeMetadataCache[Ty] =
+ return BaseTypeMetadataCache[Ty] =
MDHelper.createTBAAStructTypeNode(OutName, Fields);
}
- return StructMetadataCache[Ty] = nullptr;
+ return BaseTypeMetadataCache[Ty] = nullptr;
}
llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
if (!CodeGenOpts.StructPathTBAA)
Info = TBAAAccessInfo(Info.AccessType);
- const Type *BTy = nullptr;
- if (Info.BaseType != QualType())
- BTy = Context.getCanonicalType(Info.BaseType).getTypePtr();
- TBAAPathTag PathTag = TBAAPathTag(BTy, Info.AccessType, Info.Offset);
- if (llvm::MDNode *N = StructTagMetadataCache[PathTag])
+ llvm::MDNode *&N = AccessTagMetadataCache[Info];
+ if (N)
return N;
- llvm::MDNode *BNode = nullptr;
- if (isValidBaseType(Info.BaseType))
- BNode = getBaseTypeInfo(Info.BaseType);
- if (!BNode)
- return StructTagMetadataCache[PathTag] =
- MDHelper.createTBAAStructTagNode(Info.AccessType, Info.AccessType,
- /* Offset= */ 0);
-
- return StructTagMetadataCache[PathTag] =
- MDHelper.createTBAAStructTagNode(BNode, Info.AccessType, Info.Offset);
+ 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);
}
TBAAAccessInfo CodeGenTBAA::getMayAliasAccessInfo() {
namespace CodeGen {
class CGRecordLayout;
-struct TBAAPathTag {
- TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O)
- : BaseT(B), AccessN(A), Offset(O) {}
- const Type *BaseT;
- const llvm::MDNode *AccessN;
- uint64_t Offset;
-};
-
// TBAAAccessInfo - Describes a memory access in terms of TBAA.
struct TBAAAccessInfo {
- TBAAAccessInfo(QualType BaseType, llvm::MDNode *AccessType, uint64_t Offset)
+ TBAAAccessInfo(llvm::MDNode *BaseType, llvm::MDNode *AccessType,
+ uint64_t Offset)
: BaseType(BaseType), AccessType(AccessType), Offset(Offset)
{}
explicit TBAAAccessInfo(llvm::MDNode *AccessType)
- : TBAAAccessInfo(/* BaseType= */ QualType(), AccessType, /* Offset= */ 0)
+ : TBAAAccessInfo(/* BaseType= */ nullptr, AccessType, /* Offset= */ 0)
{}
TBAAAccessInfo()
/// BaseType - The base/leading access type. May be null if this access
/// descriptor represents an access that is not considered to be an access
/// to an aggregate or union member.
- QualType BaseType;
+ llvm::MDNode *BaseType;
/// AccessType - The final access type. May be null if there is no TBAA
/// information available about this access.
/// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing
/// them.
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
- /// This maps clang::Types to a struct node in the type DAG.
- llvm::DenseMap<const Type *, llvm::MDNode *> StructTypeMetadataCache;
- /// This maps TBAAPathTags to a tag node.
- llvm::DenseMap<TBAAPathTag, llvm::MDNode *> StructTagMetadataCache;
+ /// This maps clang::Types to a base access type in the type DAG.
+ llvm::DenseMap<const Type *, llvm::MDNode *> BaseTypeMetadataCache;
+ /// This maps TBAA access descriptors to tag nodes.
+ llvm::DenseMap<TBAAAccessInfo, llvm::MDNode *> AccessTagMetadataCache;
/// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing
/// them for struct assignments.
/// the given type.
llvm::MDNode *getTBAAStructInfo(QualType QTy);
- /// getBaseTypeInfo - Get metadata node for a given base access type.
- llvm::MDNode *getBaseTypeInfo(QualType QType);
+ /// getBaseTypeInfo - Get metadata that describes the given base access type.
+ /// Return null if the type is not suitable for use in TBAA access tags.
+ llvm::MDNode *getBaseTypeInfo(QualType QTy);
/// getAccessTagInfo - Get TBAA tag for a given memory access.
llvm::MDNode *getAccessTagInfo(TBAAAccessInfo Info);
namespace llvm {
-template<> struct DenseMapInfo<clang::CodeGen::TBAAPathTag> {
- static clang::CodeGen::TBAAPathTag getEmptyKey() {
- return clang::CodeGen::TBAAPathTag(
- DenseMapInfo<const clang::Type *>::getEmptyKey(),
- DenseMapInfo<const MDNode *>::getEmptyKey(),
+template<> struct DenseMapInfo<clang::CodeGen::TBAAAccessInfo> {
+ static clang::CodeGen::TBAAAccessInfo getEmptyKey() {
+ return clang::CodeGen::TBAAAccessInfo(
+ DenseMapInfo<MDNode *>::getEmptyKey(),
+ DenseMapInfo<MDNode *>::getEmptyKey(),
DenseMapInfo<uint64_t>::getEmptyKey());
}
- static clang::CodeGen::TBAAPathTag getTombstoneKey() {
- return clang::CodeGen::TBAAPathTag(
- DenseMapInfo<const clang::Type *>::getTombstoneKey(),
- DenseMapInfo<const MDNode *>::getTombstoneKey(),
+ static clang::CodeGen::TBAAAccessInfo getTombstoneKey() {
+ return clang::CodeGen::TBAAAccessInfo(
+ DenseMapInfo<MDNode *>::getTombstoneKey(),
+ DenseMapInfo<MDNode *>::getTombstoneKey(),
DenseMapInfo<uint64_t>::getTombstoneKey());
}
- static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) {
- return DenseMapInfo<const clang::Type *>::getHashValue(Val.BaseT) ^
- DenseMapInfo<const MDNode *>::getHashValue(Val.AccessN) ^
+ static unsigned getHashValue(const clang::CodeGen::TBAAAccessInfo &Val) {
+ return DenseMapInfo<MDNode *>::getHashValue(Val.BaseType) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.AccessType) ^
DenseMapInfo<uint64_t>::getHashValue(Val.Offset);
}
- static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS,
- const clang::CodeGen::TBAAPathTag &RHS) {
- return LHS.BaseT == RHS.BaseT &&
- LHS.AccessN == RHS.AccessN &&
+ static bool isEqual(const clang::CodeGen::TBAAAccessInfo &LHS,
+ const clang::CodeGen::TBAAAccessInfo &RHS) {
+ return LHS.BaseType == RHS.BaseType &&
+ LHS.AccessType == RHS.AccessType &&
LHS.Offset == RHS.Offset;
}
};
}
// CHECK-LABEL: @_Z7CallFoo
-// CHECK: %{{.*}} = load {{.*}} !tbaa ![[NUM:[0-9]+]]
+// CHECK: %{{.*}} = load i32 (%struct.A*)**, {{.*}} !tbaa ![[NUM:[0-9]+]]
// CHECK: br i1
-// CHECK: load {{.*}}, !tbaa ![[NUM]]
+// CHECK: load i8*, {{.*}}, !tbaa ![[NUM]]
//
// CHECK-LABEL: @_ZN1AC2Ev
-// CHECK: store {{.*}} !tbaa ![[NUM]]
+// CHECK: store i32 (...)** {{.*}}, !tbaa ![[NUM]]
//
// CHECK: [[NUM]] = !{[[TYPE:!.*]], [[TYPE]], i64 0}
// CHECK: [[TYPE]] = !{!"vtable pointer", !{{.*}}