diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index a8589baa5ae0..b19fe5884e86 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -158,7 +158,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { llvm_unreachable("Zero initializer for given type is NYI"); } - mlir::Value createLoad(mlir::Location loc, mlir::Value ptr, + cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, bool isVolatile = false, uint64_t alignment = 0) { mlir::IntegerAttr intAttr; if (alignment) @@ -167,7 +167,9 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return create(loc, ptr, /*isDeref=*/false, isVolatile, /*alignment=*/intAttr, - /*mem_order=*/cir::MemOrderAttr{}); + /*mem_order=*/ + cir::MemOrderAttr{}, + /*tbaa=*/mlir::ArrayAttr{}); } mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, @@ -353,7 +355,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { if (mlir::cast(dst.getType()).getPointee() != val.getType()) dst = createPtrBitcast(dst, val.getType()); - return create(loc, val, dst, _volatile, align, order); + return create(loc, val, dst, _volatile, align, order, + /*tbaa=*/mlir::ArrayAttr{}); } mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, @@ -400,7 +403,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { /// Create a copy with inferred length. cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile = false) { - return create(dst.getLoc(), dst, src, isVolatile); + return create(dst.getLoc(), dst, src, isVolatile, + /*tbaa=*/mlir::ArrayAttr{}); } cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst, diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 463bdd5cec7a..d0ac1d00c4b5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -1216,6 +1216,9 @@ def GlobalAnnotationValuesAttr : CIR_Attr<"GlobalAnnotationValues", let genVerifyDecl = 1; } +def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> { +} + include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td" #endif // MLIR_CIR_DIALECT_CIR_ATTRS diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index fc485c38f453..bd2f34dbfaaf 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -587,7 +587,8 @@ def LoadOp : CIR_Op<"load", [ [MemRead]>:$addr, UnitAttr:$isDeref, UnitAttr:$is_volatile, OptionalAttr:$alignment, - OptionalAttr:$mem_order + OptionalAttr:$mem_order, + OptionalAttr:$tbaa ); let results = (outs CIR_AnyType:$result); @@ -597,6 +598,7 @@ def LoadOp : CIR_Op<"load", [ (`align` `(` $alignment^ `)`)? (`atomic` `(` $mem_order^ `)`)? $addr `:` qualified(type($addr)) `,` type($result) attr-dict + (`tbaa` `(` $tbaa^ `)`)? }]; let extraClassDeclaration = [{ @@ -654,13 +656,15 @@ def StoreOp : CIR_Op<"store", [ [MemWrite]>:$addr, UnitAttr:$is_volatile, OptionalAttr:$alignment, - OptionalAttr:$mem_order); + OptionalAttr:$mem_order, + OptionalAttr:$tbaa); let assemblyFormat = [{ (`volatile` $is_volatile^)? (`align` `(` $alignment^ `)`)? (`atomic` `(` $mem_order^ `)`)? $value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr)) + (`tbaa` `(` $tbaa^ `)`)? }]; let extraClassDeclaration = [{ @@ -3980,7 +3984,8 @@ def CopyOp : CIR_Op<"copy", DeclareOpInterfaceMethods]> { let arguments = (ins Arg:$dst, Arg:$src, - UnitAttr:$is_volatile); + UnitAttr:$is_volatile, + OptionalAttr:$tbaa); let summary = "Copies contents from a CIR pointer to another"; let description = [{ Given two CIR pointers, `src` and `dst`, `cir.copy` will copy the memory @@ -3999,7 +4004,9 @@ def CopyOp : CIR_Op<"copy", }]; let assemblyFormat = [{$src `to` $dst (`volatile` $is_volatile^)? - attr-dict `:` qualified(type($dst)) }]; + attr-dict `:` qualified(type($dst)) + (`tbaa` `(` $tbaa^ `)`)? + }]; let hasVerifier = 1; let extraClassDeclaration = [{ diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 7d59e10809eb..f6e7b34ad197 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -58,6 +58,7 @@ struct MissingFeatures { // sanitizer related type check features static bool emitTypeCheck() { return false; } static bool tbaa() { return false; } + static bool tbaa_struct() { return false; } static bool cleanups() { return false; } static bool emitNullabilityCheck() { return false; } static bool ptrAuth() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index 41fcd60179d0..607f62cea8ca 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -585,7 +585,7 @@ static void emitAtomicOp(CIRGenFunction &CGF, AtomicExpr *E, Address Dest, case AtomicExpr::AO__atomic_load: case AtomicExpr::AO__scoped_atomic_load_n: case AtomicExpr::AO__scoped_atomic_load: { - auto *load = builder.createLoad(loc, Ptr).getDefiningOp(); + auto load = builder.createLoad(loc, Ptr); // FIXME(cir): add scope information. assert(!cir::MissingFeatures::syncScopeID()); load->setAttr("mem_order", orderAttr); @@ -1462,8 +1462,7 @@ void CIRGenFunction::emitAtomicStore(RValue rvalue, LValue dest, if (IsVolatile) store.setIsVolatile(true); - // DecorateInstructionWithTBAA - assert(!cir::MissingFeatures::tbaa()); + CGM.decorateOperationWithTBAA(store, dest.getTBAAInfo()); return; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index e66b40700875..ef098ceaabe2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -832,7 +832,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { addr.getAlignment()); } - mlir::Value createLoad(mlir::Location loc, Address addr, + cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile = false) { auto ptrTy = mlir::dyn_cast(addr.getPointer().getType()); if (addr.getElementType() != ptrTy.getPointee()) @@ -842,7 +842,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return create( loc, addr.getElementType(), addr.getPointer(), /*isDeref=*/false, /*is_volatile=*/isVolatile, /*alignment=*/mlir::IntegerAttr{}, - /*mem_order=*/cir::MemOrderAttr{}); + /*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{}); } mlir::Value createAlignedLoad(mlir::Location loc, mlir::Type ty, diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp index 8a20664fd2a8..c54d06c1f9d1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp @@ -751,8 +751,14 @@ void CIRGenFunction::initializeVTablePointer(mlir::Location loc, assert(!cir::MissingFeatures::addressSpace()); VTableField = builder.createElementBitCast(loc, VTableField, VTableAddressPoint.getType()); - builder.createStore(loc, VTableAddressPoint, VTableField); - assert(!cir::MissingFeatures::tbaa()); + auto storeOp = builder.createStore(loc, VTableAddressPoint, VTableField); + TBAAAccessInfo TBAAInfo = + CGM.getTBAAVTablePtrAccessInfo(VTableAddressPoint.getType()); + CGM.decorateOperationWithTBAA(storeOp, TBAAInfo); + if (CGM.getCodeGenOpts().OptimizationLevel > 0 && + CGM.getCodeGenOpts().StrictVTablePointers) { + assert(!cir::MissingFeatures::createInvariantGroup()); + } } void CIRGenFunction::initializeVTablePointers(mlir::Location loc, @@ -1659,14 +1665,16 @@ mlir::Value CIRGenFunction::getVTablePtr(mlir::Location Loc, Address This, Address CIRGenFunction::emitCXXMemberDataPointerAddress( const Expr *E, Address base, mlir::Value memberPtr, - const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo) { + const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo, + TBAAAccessInfo *tbaaInfo) { assert(!cir::MissingFeatures::cxxABI()); auto op = builder.createGetIndirectMember(getLoc(E->getSourceRange()), base.getPointer(), memberPtr); QualType memberType = memberPtrType->getPointeeType(); - CharUnits memberAlign = CGM.getNaturalTypeAlignment(memberType, baseInfo); + CharUnits memberAlign = + CGM.getNaturalTypeAlignment(memberType, baseInfo, tbaaInfo); memberAlign = CGM.getDynamicOffsetAlignment( base.getAlignment(), memberPtrType->getClass()->getAsCXXRecordDecl(), memberAlign); diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index 6fa387483492..c4d53a8477ec 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -327,7 +327,7 @@ void CIRGenFunction::emitAutoVarInit(const AutoVarEmission &emission) { // its removal/optimization to the CIR lowering. if (!constant || isa(Init)) { initializeWhatIsTechnicallyUninitialized(Loc); - LValue lv = LValue::makeAddr(Loc, type, AlignmentSource::Decl); + LValue lv = makeAddrLValue(Loc, type, AlignmentSource::Decl); emitExprAsInit(Init, &D, lv); // In case lv has uses it means we indeed initialized something // out of it while trying to build the expression, mark it as such. diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 22ab92a3f57b..6090e7411a47 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -136,20 +136,26 @@ static Address emitPointerWithAlignment(const Expr *expr, CE->getSubExpr()->getType()->getAs()) { if (PtrTy->getPointeeType()->isVoidType()) break; - assert(!cir::MissingFeatures::tbaa()); LValueBaseInfo innerBaseInfo; + TBAAAccessInfo innerTBAAInfo; Address addr = cgf.emitPointerWithAlignment( - CE->getSubExpr(), &innerBaseInfo, tbaaInfo, isKnownNonNull); + CE->getSubExpr(), &innerBaseInfo, &innerTBAAInfo, isKnownNonNull); if (baseInfo) *baseInfo = innerBaseInfo; + if (tbaaInfo) { + *tbaaInfo = innerTBAAInfo; + } if (isa(CE)) { - assert(!cir::MissingFeatures::tbaa()); LValueBaseInfo TargetTypeBaseInfo; + TBAAAccessInfo TargetTypeTBAAInfo; CharUnits Align = cgf.CGM.getNaturalPointeeTypeAlignment( - expr->getType(), &TargetTypeBaseInfo); + expr->getType(), &TargetTypeBaseInfo, &TargetTypeTBAAInfo); + if (tbaaInfo) + *tbaaInfo = + cgf.CGM.mergeTBAAInfoForCast(*tbaaInfo, TargetTypeTBAAInfo); // If the source l-value is opaque, honor the alignment of the // casted-to type. @@ -188,9 +194,15 @@ static Address emitPointerWithAlignment(const Expr *expr, // TODO: Support accesses to members of base classes in TBAA. For now, we // conservatively pretend that the complete object is of the base class // type. - assert(!cir::MissingFeatures::tbaa()); - Address Addr = cgf.emitPointerWithAlignment(CE->getSubExpr(), baseInfo); - auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl(); + if (tbaaInfo) { + *tbaaInfo = cgf.CGM.getTBAAAccessInfo(expr->getType()); + } + Address Addr = cgf.emitPointerWithAlignment( + CE->getSubExpr(), baseInfo, nullptr, + (KnownNonNull_t)(isKnownNonNull || + CE->getCastKind() == CK_UncheckedDerivedToBase)); + const auto *Derived = + CE->getSubExpr()->getType()->getPointeeCXXRecordDecl(); return cgf.getAddressOfBaseClass( Addr, Derived, CE->path_begin(), CE->path_end(), cgf.shouldNullCheckClassCastValue(CE), CE->getExprLoc()); @@ -210,7 +222,8 @@ static Address emitPointerWithAlignment(const Expr *expr, LValue LV = cgf.emitLValue(UO->getSubExpr()); if (baseInfo) *baseInfo = LV.getBaseInfo(); - assert(!cir::MissingFeatures::tbaa()); + if (tbaaInfo) + *tbaaInfo = LV.getTBAAInfo(); return LV.getAddress(); } } @@ -288,7 +301,7 @@ LValue CIRGenFunction::emitLValueForBitField(LValue base, QualType fieldType = field->getType().withCVRQualifiers(base.getVRQualifiers()); - assert(!cir::MissingFeatures::tbaa() && "NYI TBAA for bit fields"); + // TODO(cir): Support TBAA for bit fields. LValueBaseInfo fieldBaseInfo(BaseInfo.getAlignmentSource()); return LValue::MakeBitfield(Addr, info, fieldType, fieldBaseInfo, TBAAAccessInfo()); @@ -306,15 +319,34 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { const RecordDecl *rec = field->getParent(); AlignmentSource BaseAlignSource = BaseInfo.getAlignmentSource(); LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(BaseAlignSource)); - if (cir::MissingFeatures::tbaa() || rec->hasAttr() || + TBAAAccessInfo FieldTBAAInfo; + if (base.getTBAAInfo().isMayAlias() || rec->hasAttr() || FieldType->isVectorType()) { - assert(!cir::MissingFeatures::tbaa() && "NYI"); + FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo(); } else if (rec->isUnion()) { - assert(!cir::MissingFeatures::tbaa() && "NYI"); + FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo(); } else { // If no base type been assigned for the base access, then try to generate // one for this base lvalue. - assert(!cir::MissingFeatures::tbaa() && "NYI"); + FieldTBAAInfo = base.getTBAAInfo(); + if (!FieldTBAAInfo.baseType) { + FieldTBAAInfo.baseType = CGM.getTBAABaseTypeInfo(base.getType()); + assert(!FieldTBAAInfo.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()); + unsigned CharWidth = getContext().getCharWidth(); + if (FieldTBAAInfo.baseType) + FieldTBAAInfo.offset += + Layout.getFieldOffset(field->getFieldIndex()) / CharWidth; + + // Update the final access type and size. + FieldTBAAInfo.accessType = CGM.getTBAAAccessInfo(FieldType).accessType; + FieldTBAAInfo.size = + getContext().getTypeSizeInChars(FieldType).getQuantity(); } Address addr = base.getAddress(); @@ -365,12 +397,12 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { // If this is a reference field, load the reference right now. if (FieldType->isReferenceType()) { - assert(!cir::MissingFeatures::tbaa()); - LValue RefLVal = makeAddrLValue(addr, FieldType, FieldBaseInfo); + LValue RefLVal = + makeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo); if (RecordCVR & Qualifiers::Volatile) RefLVal.getQuals().addVolatile(); addr = emitLoadOfReference(RefLVal, getLoc(field->getSourceRange()), - &FieldBaseInfo); + &FieldBaseInfo, &FieldTBAAInfo); // Qualifiers on the struct don't apply to the referencee. RecordCVR = 0; @@ -387,10 +419,7 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { if (field->hasAttr()) llvm_unreachable("NYI"); - if (cir::MissingFeatures::tbaa()) - // Next line should take a TBAA object - llvm_unreachable("NYI"); - LValue LV = makeAddrLValue(addr, FieldType, FieldBaseInfo); + LValue LV = makeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo); LV.getQuals().addCVRQualifiers(RecordCVR); // __weak attribute on a field is ignored. @@ -423,8 +452,8 @@ LValue CIRGenFunction::emitLValueForFieldInitialization( LValueBaseInfo BaseInfo = Base.getBaseInfo(); AlignmentSource FieldAlignSource = BaseInfo.getAlignmentSource(); LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(FieldAlignSource)); - assert(!cir::MissingFeatures::tbaa() && "NYI"); - return makeAddrLValue(V, FieldType, FieldBaseInfo); + return makeAddrLValue(V, FieldType, FieldBaseInfo, + CGM.getTBAAInfoForSubobject(Base, FieldType)); } LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *E) { @@ -628,14 +657,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, } assert(currSrcLoc && "must pass in source location"); - builder.createStore(*currSrcLoc, value, addr, isVolatile); + auto storeOp = builder.createStore(*currSrcLoc, value, addr, isVolatile); if (isNontemporal) { llvm_unreachable("NYI"); } - if (cir::MissingFeatures::tbaa()) - llvm_unreachable("NYI"); + CGM.decorateOperationWithTBAA(storeOp, tbaaInfo); } void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue, @@ -1111,12 +1139,12 @@ CIRGenFunction::emitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { auto memberPtr = emitScalarExpr(E->getRHS()); LValueBaseInfo baseInfo; - // TODO(cir): add TBAA - assert(!cir::MissingFeatures::tbaa()); - auto memberAddr = emitCXXMemberDataPointerAddress(E, baseAddr, memberPtr, - memberPtrTy, &baseInfo); + TBAAAccessInfo tbaaInfo; + auto memberAddr = emitCXXMemberDataPointerAddress( + E, baseAddr, memberPtr, memberPtrTy, &baseInfo, &tbaaInfo); - return makeAddrLValue(memberAddr, memberPtrTy->getPointeeType(), baseInfo); + return makeAddrLValue(memberAddr, memberPtrTy->getPointeeType(), baseInfo, + tbaaInfo); } LValue CIRGenFunction::emitExtVectorElementExpr(const ExtVectorElementExpr *E) { @@ -1128,11 +1156,10 @@ LValue CIRGenFunction::emitExtVectorElementExpr(const ExtVectorElementExpr *E) { // If it is a pointer to a vector, emit the address and form an lvalue with // it. LValueBaseInfo BaseInfo; - // TODO(cir): Support TBAA - assert(!cir::MissingFeatures::tbaa()); - Address Ptr = emitPointerWithAlignment(E->getBase(), &BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Ptr = emitPointerWithAlignment(E->getBase(), &BaseInfo, &TBAAInfo); const auto *PT = E->getBase()->getType()->castAs(); - base = makeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo); + base = makeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo, TBAAInfo); base.getQuals().removeObjCGCAttr(); } else if (E->getBase()->isGLValue()) { // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), @@ -1271,8 +1298,9 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *E) { assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type"); LValueBaseInfo BaseInfo; - // TODO: add TBAAInfo - Address Addr = emitPointerWithAlignment(E->getSubExpr(), &BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Addr = + emitPointerWithAlignment(E->getSubExpr(), &BaseInfo, &TBAAInfo); // Tag 'load' with deref attribute. if (auto loadOp = @@ -1280,7 +1308,7 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *E) { loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext())); } - LValue LV = LValue::makeAddr(Addr, T, BaseInfo); + LValue LV = LValue::makeAddr(Addr, T, BaseInfo, TBAAInfo); // TODO: set addr space // TODO: ObjC/GC/__weak write barrier stuff. return LV; @@ -1305,9 +1333,8 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *E) { (E->getOpcode() == UO_Real ? emitAddrOfRealComponent(Loc, LV.getAddress(), LV.getType()) : emitAddrOfImagComponent(Loc, LV.getAddress(), LV.getType())); - // TODO(cir): TBAA info. - assert(!cir::MissingFeatures::tbaa()); - LValue ElemLV = makeAddrLValue(Component, T, LV.getBaseInfo()); + LValue ElemLV = makeAddrLValue(Component, T, LV.getBaseInfo(), + CGM.getTBAAInfoForSubobject(LV, T)); ElemLV.getQuals().addQualifiers(LV.getQuals()); return ElemLV; } @@ -1527,7 +1554,8 @@ void CIRGenFunction::emitIgnoredExpr(const Expr *E) { } Address CIRGenFunction::emitArrayToPointerDecay(const Expr *E, - LValueBaseInfo *BaseInfo) { + LValueBaseInfo *BaseInfo, + TBAAAccessInfo *TBAAInfo) { assert(E->getType()->isArrayType() && "Array to pointer decay must have array source type!"); @@ -1559,7 +1587,8 @@ Address CIRGenFunction::emitArrayToPointerDecay(const Expr *E, QualType EltType = E->getType()->castAsArrayTypeUnsafe()->getElementType(); if (BaseInfo) *BaseInfo = LV.getBaseInfo(); - assert(!cir::MissingFeatures::tbaa() && "NYI"); + if (TBAAInfo) + *TBAAInfo = CGM.getTBAAAccessInfo(EltType); mlir::Value ptr = CGM.getBuilder().maybeBuildArrayDecay( CGM.getLoc(E->getSourceRange()), Addr.getPointer(), @@ -1755,15 +1784,16 @@ LValue CIRGenFunction::emitArraySubscriptExpr(const ArraySubscriptExpr *E, llvm_unreachable("extvector subscript is NYI"); } - assert(!cir::MissingFeatures::tbaa() && "TBAA is NYI"); LValueBaseInfo EltBaseInfo; + TBAAAccessInfo EltTBAAInfo; + Address Addr = Address::invalid(); if (const VariableArrayType *vla = getContext().getAsVariableArrayType(E->getType())) { // The base must be a pointer, which is not an aggregate. Emit // it. It needs to be emitted first in case it's what captures // the VLA bounds. - Addr = emitPointerWithAlignment(E->getBase(), &EltBaseInfo); + Addr = emitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); auto Idx = EmitIdxAfterBase(/*Promote*/ true); // The element count here is the total number of non-VLA elements. @@ -1806,13 +1836,10 @@ LValue CIRGenFunction::emitArraySubscriptExpr(const ArraySubscriptExpr *E, CGM.getLoc(E->getExprLoc()), /*shouldDecay=*/true, &arrayType, E->getBase()); EltBaseInfo = ArrayLV.getBaseInfo(); - // TODO(cir): EltTBAAInfo - assert(!cir::MissingFeatures::tbaa() && "TBAA is NYI"); + EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType()); } else { // The base must be a pointer; emit it with an estimate of its alignment. - // TODO(cir): EltTBAAInfo - assert(!cir::MissingFeatures::tbaa() && "TBAA is NYI"); - Addr = emitPointerWithAlignment(E->getBase(), &EltBaseInfo); + Addr = emitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); auto Idx = EmitIdxAfterBase(/*Promote*/ true); QualType ptrType = E->getBase()->getType(); Addr = emitArraySubscriptPtr( @@ -1822,7 +1849,7 @@ LValue CIRGenFunction::emitArraySubscriptExpr(const ArraySubscriptExpr *E, &ptrType, E->getBase()); } - LValue LV = LValue::makeAddr(Addr, E->getType(), EltBaseInfo); + LValue LV = LValue::makeAddr(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) { llvm_unreachable("ObjC is NYI"); @@ -1967,8 +1994,8 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *E) { // TODO: Support accesses to members of base classes in TBAA. For now, we // conservatively pretend that the complete object is of the base class // type. - assert(!cir::MissingFeatures::tbaa()); - return makeAddrLValue(Base, E->getType(), LV.getBaseInfo()); + return makeAddrLValue(Base, E->getType(), LV.getBaseInfo(), + CGM.getTBAAInfoForSubobject(LV, E->getType())); } case CK_ToUnion: assert(0 && "NYI"); @@ -1986,10 +2013,9 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *E) { auto DestAS = builder.getAddrSpaceAttr(E->getType().getAddressSpace()); mlir::Value V = getTargetHooks().performAddrSpaceCast( *this, LV.getPointer(), SrcAS, DestAS, ConvertType(DestTy)); - assert(!cir::MissingFeatures::tbaa()); return makeAddrLValue(Address(V, getTypes().convertTypeForMem(E->getType()), LV.getAddress().getAlignment()), - E->getType(), LV.getBaseInfo()); + E->getType(), LV.getBaseInfo(), LV.getTBAAInfo()); } case CK_ObjCObjectLValueCast: { assert(0 && "NYI"); @@ -2070,7 +2096,8 @@ LValue CIRGenFunction::emitMemberExpr(const MemberExpr *E) { LValue BaseLV; if (E->isArrow()) { LValueBaseInfo BaseInfo; - Address Addr = emitPointerWithAlignment(BaseExpr, &BaseInfo); + TBAAAccessInfo TBAAInfo; + Address Addr = emitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); QualType PtrTy = BaseExpr->getType()->getPointeeType(); SanitizerSet SkippedChecks; bool IsBaseCXXThis = isWrappedCXXThis(BaseExpr); @@ -2080,7 +2107,7 @@ LValue CIRGenFunction::emitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Null, true); emitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); - BaseLV = makeAddrLValue(Addr, PtrTy, BaseInfo); + BaseLV = makeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else BaseLV = emitCheckedLValue(BaseExpr, TCK_MemberAccess); @@ -2434,56 +2461,55 @@ CIRGenFunction::emitConditionalBlocks(const AbstractConditionalOperator *E, } }; - Info.Result = builder - .create( - loc, condV, /*trueBuilder=*/ - [&](mlir::OpBuilder &b, mlir::Location loc) { - CIRGenFunction::LexicalScope lexScope{ - *this, loc, b.getInsertionBlock()}; - CGF.currLexScope->setAsTernary(); - - assert( - !cir::MissingFeatures::incrementProfileCounter()); - eval.begin(CGF); - Info.LHS = BranchGenFunc(CGF, trueExpr); - auto lhs = Info.LHS->getPointer(); - eval.end(CGF); - - if (lhs) { - yieldTy = lhs.getType(); - b.create(loc, lhs); - return; - } - // If LHS or RHS is a throw or void expression we need - // to patch arms as to properly match yield types. - insertPoints.push_back(b.saveInsertionPoint()); - }, - /*falseBuilder=*/ - [&](mlir::OpBuilder &b, mlir::Location loc) { - CIRGenFunction::LexicalScope lexScope{ - *this, loc, b.getInsertionBlock()}; - CGF.currLexScope->setAsTernary(); - - assert( - !cir::MissingFeatures::incrementProfileCounter()); - eval.begin(CGF); - Info.RHS = BranchGenFunc(CGF, falseExpr); - auto rhs = Info.RHS->getPointer(); - eval.end(CGF); - - if (rhs) { - yieldTy = rhs.getType(); - b.create(loc, rhs); - } else { - // If LHS or RHS is a throw or void expression we - // need to patch arms as to properly match yield - // types. - insertPoints.push_back(b.saveInsertionPoint()); - } - - patchVoidOrThrowSites(); - }) - .getResult(); + Info.Result = + builder + .create( + loc, condV, /*trueBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + CIRGenFunction::LexicalScope lexScope{*this, loc, + b.getInsertionBlock()}; + CGF.currLexScope->setAsTernary(); + + assert(!cir::MissingFeatures::incrementProfileCounter()); + eval.begin(CGF); + Info.LHS = BranchGenFunc(CGF, trueExpr); + auto lhs = Info.LHS->getPointer(); + eval.end(CGF); + + if (lhs) { + yieldTy = lhs.getType(); + b.create(loc, lhs); + return; + } + // If LHS or RHS is a throw or void expression we need + // to patch arms as to properly match yield types. + insertPoints.push_back(b.saveInsertionPoint()); + }, + /*falseBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + CIRGenFunction::LexicalScope lexScope{*this, loc, + b.getInsertionBlock()}; + CGF.currLexScope->setAsTernary(); + + assert(!cir::MissingFeatures::incrementProfileCounter()); + eval.begin(CGF); + Info.RHS = BranchGenFunc(CGF, falseExpr); + auto rhs = Info.RHS->getPointer(); + eval.end(CGF); + + if (rhs) { + yieldTy = rhs.getType(); + b.create(loc, rhs); + } else { + // If LHS or RHS is a throw or void expression we + // need to patch arms as to properly match yield + // types. + insertPoints.push_back(b.saveInsertionPoint()); + } + + patchVoidOrThrowSites(); + }) + .getResult(); return Info; } @@ -2518,8 +2544,10 @@ LValue CIRGenFunction::emitConditionalOperatorLValue( AlignmentSource alignSource = std::max(Info.LHS->getBaseInfo().getAlignmentSource(), Info.RHS->getBaseInfo().getAlignmentSource()); - assert(!cir::MissingFeatures::tbaa()); - return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource)); + TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForConditionalOperator( + Info.LHS->getTBAAInfo(), Info.RHS->getTBAAInfo()); + return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource), + TBAAInfo); } else { llvm_unreachable("NYI"); } @@ -2623,7 +2651,7 @@ LValue CIRGenFunction::emitLValue(const Expr *E) { return emitStmtExprLValue(cast(E)); } - return LValue::makeAddr(Address::invalid(), E->getType()); + llvm_unreachable("NYI"); } /// Given the address of a temporary variable, produce an r-value of its type. @@ -2894,17 +2922,16 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile, Ptr = builder.create(loc, ElemPtrTy, cir::CastKind::bitcast, Ptr); } - - mlir::Value Load = builder.CIRBaseBuilderTy::createLoad(loc, Ptr, isVolatile); + auto loadOp = builder.CIRBaseBuilderTy::createLoad(loc, Ptr, isVolatile); if (isNontemporal) { llvm_unreachable("NYI"); } + CGM.decorateOperationWithTBAA(loadOp, tbaaInfo); - assert(!cir::MissingFeatures::tbaa() && "NYI"); assert(!cir::MissingFeatures::emitScalarRangeCheck() && "NYI"); - return emitFromMemory(Load, ty); + return emitFromMemory(loadOp, ty); } // Note: this function also emit constructor calls to support a MSVC extensions @@ -2954,8 +2981,7 @@ Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc, builder.create(loc, refLVal.getAddress().getElementType(), refLVal.getAddress().getPointer()); - // TODO(cir): DecorateInstructionWithTBAA relevant for us? - assert(!cir::MissingFeatures::tbaa()); + CGM.decorateOperationWithTBAA(load, refLVal.getTBAAInfo()); QualType pointeeType = refLVal.getType()->getPointeeType(); CharUnits align = @@ -2967,9 +2993,11 @@ Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc, LValue CIRGenFunction::emitLoadOfReferenceLValue(LValue RefLVal, mlir::Location Loc) { LValueBaseInfo PointeeBaseInfo; - Address PointeeAddr = emitLoadOfReference(RefLVal, Loc, &PointeeBaseInfo); + TBAAAccessInfo PointeeTBAAInfo; + Address PointeeAddr = + emitLoadOfReference(RefLVal, Loc, &PointeeBaseInfo, &PointeeTBAAInfo); return makeAddrLValue(PointeeAddr, RefLVal.getType()->getPointeeType(), - PointeeBaseInfo); + PointeeBaseInfo, PointeeTBAAInfo); } void CIRGenFunction::emitUnreachable(SourceLocation Loc) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index f13cb8600f9a..32f343ffd605 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -1708,13 +1708,18 @@ void CIRGenFunction::emitAggregateCopy(LValue Dest, LValue Src, QualType Ty, } } - builder.createCopy(DestPtr.getPointer(), SrcPtr.getPointer(), isVolatile); + auto copyOp = + builder.createCopy(DestPtr.getPointer(), SrcPtr.getPointer(), isVolatile); // 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. - if (CGM.getCodeGenOpts().NewStructPathTBAA || cir::MissingFeatures::tbaa()) - llvm_unreachable("TBAA is NYI"); + assert(!cir::MissingFeatures::tbaa_struct() && "tbaa.struct NYI"); + if (CGM.getCodeGenOpts().NewStructPathTBAA) { + TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer( + Dest.getTBAAInfo(), Src.getTBAAInfo()); + CGM.decorateOperationWithTBAA(copyOp, TBAAInfo); + } } AggValueSlot::Overlap_t diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index be3ec6071def..e336594388ae 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -218,9 +218,9 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr( LValue This; if (IsArrow) { LValueBaseInfo BaseInfo; - assert(!cir::MissingFeatures::tbaa()); - Address ThisValue = emitPointerWithAlignment(Base, &BaseInfo); - This = makeAddrLValue(ThisValue, Base->getType(), BaseInfo); + TBAAAccessInfo TBAAInfo; + Address ThisValue = emitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); + This = makeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); } else { This = emitLValue(Base); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index ee2a0c32cbff..7d51dc05e7c1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1604,10 +1604,7 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { Address DestAddr = SourceAddr.withPointer(DestPtr).withElementType(DestElemTy); LValue DestLVal = CGF.makeAddrLValue(DestAddr, DestTy); - - if (Kind == CK_LValueToRValueBitCast) - assert(!cir::MissingFeatures::tbaa()); - + DestLVal.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo()); return emitLoadOfLValue(DestLVal, CE->getExprLoc()); } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index b31a4ba325ae..1c84cb3ca71b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -824,14 +824,13 @@ LValue CIRGenFunction::MakeNaturalAlignPointeeAddrLValue(mlir::Value val, TBAAAccessInfo tbaaInfo; CharUnits align = CGM.getNaturalTypeAlignment(ty, &baseInfo, &tbaaInfo, /* for PointeeType= */ true); - return makeAddrLValue(Address(val, align), ty, baseInfo); + return makeAddrLValue(Address(val, align), ty, baseInfo, tbaaInfo); } LValue CIRGenFunction::MakeNaturalAlignAddrLValue(mlir::Value val, QualType ty) { LValueBaseInfo baseInfo; TBAAAccessInfo tbaaInfo; - assert(!cir::MissingFeatures::tbaa()); CharUnits alignment = CGM.getNaturalTypeAlignment(ty, &baseInfo, &tbaaInfo); Address addr(val, getTypes().convertTypeForMem(ty), alignment); return LValue::makeAddr(addr, ty, getContext(), baseInfo, tbaaInfo); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 8d4fabeff642..e5db0a01e429 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -886,7 +886,8 @@ class CIRGenFunction : public CIRGenTypeCache { LValue emitLoadOfReferenceLValue(Address RefAddr, mlir::Location Loc, QualType RefTy, AlignmentSource Source = AlignmentSource::Type) { - LValue RefLVal = makeAddrLValue(RefAddr, RefTy, LValueBaseInfo(Source)); + LValue RefLVal = makeAddrLValue(RefAddr, RefTy, LValueBaseInfo(Source), + CGM.getTBAAAccessInfo(RefTy)); return emitLoadOfReferenceLValue(RefLVal, Loc); } void emitImplicitAssignmentOperatorBody(FunctionArgList &Args); @@ -909,7 +910,8 @@ class CIRGenFunction : public CIRGenTypeCache { /// TODO: Add TBAAAccessInfo Address emitCXXMemberDataPointerAddress( const Expr *E, Address base, mlir::Value memberPtr, - const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo); + const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo, + TBAAAccessInfo *tbaaInfo); /// Generate a call of the given function, expecting the given /// result type, and using the given argument list which specifies both the @@ -1649,9 +1651,8 @@ class CIRGenFunction : public CIRGenTypeCache { QualType DstTy, SourceLocation Loc); LValue makeAddrLValue(Address addr, clang::QualType ty, - LValueBaseInfo baseInfo) { - return LValue::makeAddr(addr, ty, getContext(), baseInfo, - CGM.getTBAAAccessInfo(ty)); + LValueBaseInfo baseInfo, TBAAAccessInfo tbaaInfo) { + return LValue::makeAddr(addr, ty, getContext(), baseInfo, tbaaInfo); } LValue makeAddrLValue(Address addr, clang::QualType ty, @@ -1744,7 +1745,8 @@ class CIRGenFunction : public CIRGenTypeCache { /// TODO(cir): add TBAAAccessInfo Address emitArrayToPointerDecay(const Expr *Array, - LValueBaseInfo *BaseInfo = nullptr); + LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr); /// Emits the code necessary to evaluate an arbitrary expression into the /// given memory location. diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 97678fa2ad8a..b9e332d4b27a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -205,6 +205,11 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, /*line=*/0, /*col=*/0)); } + if (langOpts.Sanitize.has(SanitizerKind::Thread) || + (!codeGenOpts.RelaxedAliasing && codeGenOpts.OptimizationLevel > 0)) { + tbaa.reset(new CIRGenTBAA(&context, astctx, genTypes, theModule, + codeGenOpts, langOpts)); + } } CIRGenModule::~CIRGenModule() {} @@ -258,6 +263,9 @@ CharUnits CIRGenModule::getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo, TBAAAccessInfo *tbaaInfo, bool forPointeeType) { + if (tbaaInfo) { + *tbaaInfo = getTBAAAccessInfo(T); + } // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown. But // that doesn't return the information we need to compute BaseInfo. @@ -3513,8 +3521,69 @@ void CIRGenModule::emitGlobalAnnotations() { deferredAnnotations.clear(); } +cir::TBAAAttr CIRGenModule::getTBAATypeInfo(QualType QTy) { + if (!tbaa) { + return nullptr; + } + return tbaa->getTypeInfo(QTy); +} + TBAAAccessInfo CIRGenModule::getTBAAAccessInfo(QualType accessType) { + if (!tbaa) { + return TBAAAccessInfo(); + } + if (getLangOpts().CUDAIsDevice) { + llvm_unreachable("NYI"); + } + return tbaa->getAccessInfo(accessType); +} + +TBAAAccessInfo +CIRGenModule::getTBAAVTablePtrAccessInfo(mlir::Type VTablePtrType) { if (!tbaa) return TBAAAccessInfo(); - llvm_unreachable("NYI"); + return tbaa->getVTablePtrAccessInfo(VTablePtrType); +} + +mlir::ArrayAttr CIRGenModule::getTBAAStructInfo(QualType QTy) { + if (!tbaa) + return nullptr; + return tbaa->getTBAAStructInfo(QTy); +} + +cir::TBAAAttr CIRGenModule::getTBAABaseTypeInfo(QualType QTy) { + if (!tbaa) { + return nullptr; + } + return tbaa->getBaseTypeInfo(QTy); +} + +mlir::ArrayAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) { + if (!tbaa) { + return nullptr; + } + return tbaa->getAccessTagInfo(tbaaInfo); +} + +TBAAAccessInfo CIRGenModule::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, + TBAAAccessInfo TargetInfo) { + if (!tbaa) + return TBAAAccessInfo(); + return tbaa->mergeTBAAInfoForCast(SourceInfo, TargetInfo); +} + +TBAAAccessInfo +CIRGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, + TBAAAccessInfo InfoB) { + if (!tbaa) + return TBAAAccessInfo(); + return tbaa->mergeTBAAInfoForConditionalOperator(InfoA, InfoB); +} + +TBAAAccessInfo +CIRGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo) { + if (!tbaa) + return TBAAAccessInfo(); + return tbaa->mergeTBAAInfoForConditionalOperator(DestInfo, SrcInfo); } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 961a999990b6..61d975491f33 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -39,6 +39,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/MLIRContext.h" @@ -506,10 +507,52 @@ class CIRGenModule : public CIRGenTypeCache { return VTables.getItaniumVTableContext(); } - /// getTBAAAccessInfo - Gte TBAA information that describes an access to an - /// object of the given type. + /// Get attribute used to describe accesses to objects of + /// the given type. + cir::TBAAAttr getTBAATypeInfo(QualType QTy); + + /// Get TBAA information that describes an access to an object of the given + /// type. TBAAAccessInfo getTBAAAccessInfo(QualType accessType); + /// Get the TBAA information that describes an access to a virtual table + /// pointer. + TBAAAccessInfo getTBAAVTablePtrAccessInfo(mlir::Type VTablePtrType); + + mlir::ArrayAttr getTBAAStructInfo(QualType QTy); + + /// Get metadata that describes the given base access type. Return null if the + /// type is not suitable for use in TBAA access tags. + cir::TBAAAttr getTBAABaseTypeInfo(QualType QTy); + + mlir::ArrayAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo); + + /// Get merged TBAA information for the purposes of type casts. + TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, + TBAAAccessInfo TargetInfo); + + /// Get merged TBAA information for the purposes of conditional operator. + TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, + TBAAAccessInfo InfoB); + + /// Get merged TBAA information for the purposes of memory transfer calls. + TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo); + + /// Get TBAA information for an access with a given base lvalue. + TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType) { + if (Base.getTBAAInfo().isMayAlias()) + return TBAAAccessInfo::getMayAliasInfo(); + return getTBAAAccessInfo(AccessType); + } + + template + void decorateOperationWithTBAA(Op op, TBAAAccessInfo tbaaInfo) { + if (auto tag = getTBAAAccessTagInfo(tbaaInfo)) { + op.setTbaaAttr(tag); + } + } + /// This contains all the decls which have definitions but which are deferred /// for emission and therefore should only be output if they are actually /// used. If a decl is in this, then it is known to have not been referenced diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp index e69de29bb2d1..c3083e93eeb1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp @@ -0,0 +1,64 @@ +#include "CIRGenTBAA.h" +#include "CIRGenCXXABI.h" +#include "CIRGenTypes.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/Interfaces/DataLayoutInterfaces.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "llvm/Support/ErrorHandling.h" +namespace clang::CIRGen { + +cir::TBAAAttr tbaa_NYI(mlir::MLIRContext *ctx) { + return cir::TBAAAttr::get(ctx); +} + +CIRGenTBAA::CIRGenTBAA(mlir::MLIRContext *ctx, clang::ASTContext &context, + CIRGenTypes &types, mlir::ModuleOp moduleOp, + const clang::CodeGenOptions &codeGenOpts, + const clang::LangOptions &features) + : ctx(ctx), context(context), types(types), moduleOp(moduleOp), + codeGenOpts(codeGenOpts), features(features) {} + +cir::TBAAAttr CIRGenTBAA::getTypeInfo(clang::QualType qty) { + return tbaa_NYI(ctx); +} + +TBAAAccessInfo CIRGenTBAA::getAccessInfo(clang::QualType accessType) { + return TBAAAccessInfo(); +} + +TBAAAccessInfo CIRGenTBAA::getVTablePtrAccessInfo(mlir::Type vtablePtrType) { + return TBAAAccessInfo(); +} + +mlir::ArrayAttr CIRGenTBAA::getTBAAStructInfo(clang::QualType qty) { + return mlir::ArrayAttr::get(ctx, {}); +} + +cir::TBAAAttr CIRGenTBAA::getBaseTypeInfo(clang::QualType qty) { + return tbaa_NYI(ctx); +} + +mlir::ArrayAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) { + return mlir::ArrayAttr::get(ctx, {tbaa_NYI(ctx)}); +} + +TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, + TBAAAccessInfo targetInfo) { + return TBAAAccessInfo(); +} + +TBAAAccessInfo +CIRGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, + TBAAAccessInfo infoB) { + return TBAAAccessInfo(); +} + +TBAAAccessInfo +CIRGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, + TBAAAccessInfo srcInfo) { + return TBAAAccessInfo(); +} + +} // namespace clang::CIRGen diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.h b/clang/lib/CIR/CodeGen/CIRGenTBAA.h index 2b33f0da16d4..b6a392bd164c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTBAA.h +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.h @@ -13,16 +13,169 @@ #ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTBAA_H #define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTBAA_H - +#include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "clang/AST/Type.h" +#include "clang/Basic/CodeGenOptions.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" namespace clang::CIRGen { +class CIRGenTypes; +enum class TBAAAccessKind : unsigned { + Ordinary, + MayAlias, + Incomplete, +}; +// Describes a memory access in terms of TBAA. +struct TBAAAccessInfo { + TBAAAccessInfo(TBAAAccessKind kind, cir::TBAAAttr baseType, + cir::TBAAAttr accessType, uint64_t offset, uint64_t size) + : kind(kind), baseType(baseType), accessType(accessType), offset(offset) { + } -// TBAAAccessInfo - Describes a memory access in terms of TBAA. -struct TBAAAccessInfo {}; + TBAAAccessInfo(cir::TBAAAttr baseType, cir::TBAAAttr accessType, + uint64_t offset, uint64_t size) + : kind(TBAAAccessKind::Ordinary), baseType(baseType), + accessType(accessType), offset(offset) {} -/// CIRGenTBAA - This class organizes the cross-module state that is used while -/// lowering AST types to LLVM types. -class CIRGenTBAA {}; + explicit TBAAAccessInfo(cir::TBAAAttr accessType, uint64_t size) + : TBAAAccessInfo(TBAAAccessKind::Ordinary, /* baseType= */ {}, accessType, + /* offset= */ 0, size) {} -} // namespace clang::CIRGen + TBAAAccessInfo() + : TBAAAccessInfo(/* accessType= */ nullptr, /* size= */ 0) {}; + + static TBAAAccessInfo getMayAliasInfo() { + return TBAAAccessInfo(TBAAAccessKind::MayAlias, /* baseType= */ {}, + /* accessType= */ nullptr, + /* offset= */ 0, /* size= */ 0); + } + + bool isMayAlias() const { return kind == TBAAAccessKind::MayAlias; } + + static TBAAAccessInfo getIncompleteInfo() { + return TBAAAccessInfo(TBAAAccessKind::Incomplete, /* baseType= */ {}, + /* accessType= */ {}, + /* 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 && + size == other.size; + } + + bool operator!=(const TBAAAccessInfo &other) const { + return !(*this == other); + } + + explicit operator bool() const { return *this != TBAAAccessInfo(); } + + /// The kind of the access descriptor. + TBAAAccessKind kind; + + /// 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. + cir::TBAAAttr baseType; + + /// The final access type. May be null if there is no TBAA + /// information available about this access. + cir::TBAAAttr accessType; + + /// 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; + /// The size of access, in bytes. + uint64_t size; +}; + +/// This class organizes the cross-module state that is used while lowering AST +/// types to LLVM types. +class CIRGenTBAA { + mlir::MLIRContext *ctx; + clang::ASTContext &context; + CIRGenTypes &types; + mlir::ModuleOp moduleOp; + const clang::CodeGenOptions &codeGenOpts; + const clang::LangOptions &features; + +public: + CIRGenTBAA(mlir::MLIRContext *ctx, clang::ASTContext &context, + CIRGenTypes &types, mlir::ModuleOp moduleOp, + const clang::CodeGenOptions &codeGenOpts, + const clang::LangOptions &features); + + /// Get attribute used to describe accesses to objects of the given type. + cir::TBAAAttr getTypeInfo(clang::QualType qty); + + /// Get TBAA information that describes an access to an object of the given + /// type. + TBAAAccessInfo getAccessInfo(clang::QualType accessType); + + /// Get the TBAA information that describes an access to a virtual table + /// pointer. + TBAAAccessInfo getVTablePtrAccessInfo(mlir::Type vtablePtrType); + + /// Get the TBAAStruct attributes to be used for a memcpy of the given type. + mlir::ArrayAttr getTBAAStructInfo(clang::QualType qty); + + /// Get attribute that describes the given base access type. Return null if + /// the type is not suitable for use in TBAA access tags. + cir::TBAAAttr getBaseTypeInfo(clang::QualType qty); + + /// Get TBAA tag for a given memory access. + mlir::ArrayAttr getAccessTagInfo(TBAAAccessInfo tbaaInfo); + + /// Get merged TBAA information for the purpose of type casts. + TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, + TBAAAccessInfo targetInfo); + + /// Get merged TBAA information for the purpose of conditional operator. + TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, + TBAAAccessInfo infoB); + + /// Get merged TBAA information for the purpose of memory transfer calls. + TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, + TBAAAccessInfo srcInfo); +}; +} // namespace clang::CIRGen +namespace llvm { +template <> struct DenseMapInfo { + static clang::CIRGen::TBAAAccessInfo getEmptyKey() { + unsigned unsignedKey = DenseMapInfo::getEmptyKey(); + return clang::CIRGen::TBAAAccessInfo( + static_cast(unsignedKey), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey()); + } + static clang::CIRGen::TBAAAccessInfo getTombstoneKey() { + unsigned unsignedKey = DenseMapInfo::getTombstoneKey(); + return clang::CIRGen::TBAAAccessInfo( + static_cast(unsignedKey), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey()); + } + static unsigned getHashValue(const clang::CIRGen::TBAAAccessInfo &val) { + auto kindValue = static_cast(val.kind); + return DenseMapInfo::getHashValue(kindValue) ^ + DenseMapInfo::getHashValue(val.baseType) ^ + DenseMapInfo::getHashValue(val.accessType) ^ + DenseMapInfo::getHashValue(val.offset) ^ + DenseMapInfo::getHashValue(val.size); + } + static bool isEqual(const clang::CIRGen::TBAAAccessInfo &lhs, + const clang::CIRGen::TBAAAccessInfo &rhs) { + return lhs == rhs; + } +}; +} // namespace llvm #endif diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h index fc2f650eaed6..8dd16f6ce9e1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenValue.h +++ b/clang/lib/CIR/CodeGen/CIRGenValue.h @@ -268,26 +268,14 @@ class LValue { LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } - static LValue makeAddr(Address address, clang::QualType T, - AlignmentSource Source = AlignmentSource::Type) { - LValue R; - R.LVType = Simple; - R.V = address.getPointer(); - R.ElementType = address.getElementType(); - R.Initialize(T, T.getQualifiers(), address.getAlignment(), - LValueBaseInfo(Source), TBAAAccessInfo()); - return R; - } - // FIXME: only have one of these static methods. - static LValue makeAddr(Address address, clang::QualType T, - LValueBaseInfo LBI) { + static LValue makeAddr(Address address, clang::QualType T, LValueBaseInfo LBI, + TBAAAccessInfo tbaaInfo) { LValue R; R.LVType = Simple; R.V = address.getPointer(); R.ElementType = address.getElementType(); - R.Initialize(T, T.getQualifiers(), address.getAlignment(), LBI, - TBAAAccessInfo()); + R.Initialize(T, T.getQualifiers(), address.getAlignment(), LBI, tbaaInfo); return R; } @@ -307,6 +295,7 @@ class LValue { } TBAAAccessInfo getTBAAInfo() const { return tbaaInfo; } + void setTBAAInfo(TBAAAccessInfo info) { tbaaInfo = info; } const clang::Qualifiers &getQuals() const { return Quals; } clang::Qualifiers &getQuals() { return Quals; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 214553b66e83..ab49ffbdcb98 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -106,6 +106,10 @@ struct CIROpAsmDialectInterface : public OpAsmDialectInterface { os << dynCastInfoAttr.getAlias(); return AliasResult::FinalAlias; } + if (auto tbaaAttr = mlir::dyn_cast(attr)) { + os << tbaaAttr.getMnemonic(); + return AliasResult::OverridableAlias; + } return AliasResult::NoAlias; } diff --git a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp index e75b30b1c1c3..80963353a304 100644 --- a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/DataLayoutInterfaces.h" @@ -52,8 +53,7 @@ void cir::AllocaOp::handleBlockArgument(const MemorySlot &slot, std::optional cir::AllocaOp::handlePromotionComplete(const MemorySlot &slot, - Value defaultValue, - OpBuilder &builder) { + Value defaultValue, OpBuilder &builder) { if (defaultValue && defaultValue.use_empty()) defaultValue.getDefiningOp()->erase(); this->erase(); @@ -150,7 +150,8 @@ DeletionKind cir::CopyOp::removeBlockingUses( const DataLayout &dataLayout) { if (loadsFrom(slot)) builder.create(getLoc(), reachingDefinition, getDst(), false, - mlir::IntegerAttr{}, cir::MemOrderAttr()); + mlir::IntegerAttr{}, cir::MemOrderAttr(), + mlir::ArrayAttr{}); return DeletionKind::Delete; } diff --git a/clang/test/CIR/CodeGen/tbaa.c b/clang/test/CIR/CodeGen/tbaa.c new file mode 100644 index 000000000000..43cdde47ecb7 --- /dev/null +++ b/clang/test/CIR/CodeGen/tbaa.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s + +// CIR: #tbaa[[TBAA_NO:.*]] = #cir.tbaa +void f(int *a, float *b) { + // CIR: cir.scope + // CIR: %[[TMP1:.*]] = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) + // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i tbaa([#tbaa[[TBAA_NO]]]) + // CIR: cir.if + // CIR: %[[C2:.*]] = cir.const #cir.fp<2 + // CIR: %[[TMP3:.*]] = cir.load deref %[[ARG_b:.*]] : !cir.ptr>, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) + // CIR: cir.store %[[C2]], %[[TMP3]] : !cir.float, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) + // CIR: else + // CIR: %[[C3:.*]] = cir.const #cir.fp<3 + // CIR: %[[TMP4:.*]] = cir.load deref %[[ARG_b]] : !cir.ptr>, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) + // CIR: cir.store %[[C3]], %[[TMP4]] : !cir.float, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) + if (*a == 1) { + *b = 2.0f; + } else { + *b = 3.0f; + } +}