[clang] [CIR] Upstream initial TBAA implementation (PR #169226)
Hendrik Hübner via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 24 09:09:31 PST 2025
https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/169226
>From cdfac7fffb460c4ddacc19f333ba5bb2ca1c819e Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Fri, 21 Nov 2025 02:39:40 +0100
Subject: [PATCH] [CIR] Upstream initial TBAA implementation
---
.../CIR/Dialect/Builder/CIRBaseBuilder.h | 8 +-
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 8 +
clang/include/clang/CIR/Dialect/IR/CIROps.td | 23 ++-
clang/include/clang/CIR/MissingFeatures.h | 1 +
clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 4 +-
clang/lib/CIR/CodeGen/CIRGenClass.cpp | 10 +-
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 67 ++++---
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 8 +-
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 1 +
clang/lib/CIR/CodeGen/CIRGenFunction.h | 18 +-
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 81 +++++++-
clang/lib/CIR/CodeGen/CIRGenModule.h | 52 +++++
clang/lib/CIR/CodeGen/CIRGenTBAA.cpp | 65 ++++++
clang/lib/CIR/CodeGen/CIRGenTBAA.h | 188 ++++++++++++++++++
clang/lib/CIR/CodeGen/CIRGenValue.h | 32 ++-
clang/lib/CIR/CodeGen/CMakeLists.txt | 1 +
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +-
clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp | 2 +-
19 files changed, 516 insertions(+), 61 deletions(-)
create mode 100644 clang/lib/CIR/CodeGen/CIRGenTBAA.cpp
create mode 100644 clang/lib/CIR/CodeGen/CIRGenTBAA.h
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index be9965ae3101f..371f046c25ba0 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -205,7 +205,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
bool isVolatile = false, uint64_t alignment = 0) {
mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
- alignmentAttr, cir::MemOrderAttr{});
+ alignmentAttr, cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{});
}
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
@@ -321,14 +321,14 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
/// Create a copy with inferred length.
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
bool isVolatile = false) {
- return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile);
+ return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile, /*tbaa=*/mlir::ArrayAttr{});
}
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
bool isVolatile = false,
mlir::IntegerAttr align = {},
cir::MemOrderAttr order = {}) {
- return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order);
+ return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order, /*tbaa=*/mlir::ArrayAttr{});
}
[[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule,
@@ -353,7 +353,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr);
return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
/*isVolatile=*/false, alignmentAttr,
- /*mem_order=*/{});
+ /*mem_order=*/{}, /*tbaa=*/mlir::ArrayAttr{});
}
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 12bc9cf7b5b04..5dbfe9334c867 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -447,6 +447,14 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
}];
}
+//===----------------------------------------------------------------------===//
+// TBAAAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> {
+ let summary = "CIR dialect TBAA base attribute";
+}
+
//===----------------------------------------------------------------------===//
// GlobalViewAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index a19c4f951fff9..40710783c97c0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -586,7 +586,10 @@ def CIR_LoadOp : CIR_Op<"load", [
UnitAttr:$isDeref,
UnitAttr:$is_volatile,
OptionalAttr<I64Attr>:$alignment,
- OptionalAttr<CIR_MemOrder>:$mem_order);
+ OptionalAttr<CIR_MemOrder>:$mem_order,
+ OptionalAttr<ArrayAttr>:$tbaa
+ );
+
let results = (outs CIR_AnyType:$result);
let assemblyFormat = [{
@@ -595,6 +598,7 @@ def CIR_LoadOp : CIR_Op<"load", [
(`align` `(` $alignment^ `)`)?
(`atomic` `(` $mem_order^ `)`)?
$addr `:` qualified(type($addr)) `,` type($result) attr-dict
+ (`tbaa` `(` $tbaa^ `)`)?
}];
// FIXME: add verifier.
@@ -638,13 +642,16 @@ def CIR_StoreOp : CIR_Op<"store", [
[MemWrite]>:$addr,
UnitAttr:$is_volatile,
OptionalAttr<I64Attr>:$alignment,
- OptionalAttr<CIR_MemOrder>:$mem_order);
+ OptionalAttr<CIR_MemOrder>:$mem_order,
+ OptionalAttr<ArrayAttr>:$tbaa
+ );
let assemblyFormat = [{
(`volatile` $is_volatile^)?
(`align` `(` $alignment^ `)`)?
(`atomic` `(` $mem_order^ `)`)?
$value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr))
+ (`tbaa` `(` $tbaa^ `)`)?
}];
// FIXME: add verifier.
@@ -2979,12 +2986,16 @@ def CIR_CopyOp : CIR_Op<"copy",[
let arguments = (ins
Arg<CIR_PointerType, "", [MemWrite]>:$dst,
Arg<CIR_PointerType, "", [MemRead]>:$src,
- UnitAttr:$is_volatile
+ UnitAttr:$is_volatile,
+ OptionalAttr<ArrayAttr>:$tbaa
);
- let assemblyFormat = [{$src `to` $dst (`volatile` $is_volatile^)?
- attr-dict `:` qualified(type($dst))
+ let assemblyFormat = [{
+ $src `to` $dst (`volatile` $is_volatile^)?
+ attr-dict `:` qualified(type($dst))
+ (`tbaa` `(` $tbaa^ `)`)?
}];
+
let hasVerifier = 1;
let extraClassDeclaration = [{
@@ -2994,7 +3005,7 @@ def CIR_CopyOp : CIR_Op<"copy",[
/// Returns the number of bytes to be copied.
unsigned getLength(const mlir::DataLayout &dt) {
return dt.getTypeSize(getType().getPointee());
- }
+ }
}];
}
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index c99fd6f0bfcc4..defcb5dd600d1 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -302,6 +302,7 @@ struct MissingFeatures {
static bool openCL() { return false; }
static bool openMP() { return false; }
static bool opTBAA() { return false; }
+ static bool opTBAAStruct() { return false; }
static bool peepholeProtection() { return false; }
static bool pgoUse() { return false; }
static bool pointerAuthentication() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 48c082d89de18..aea832051b355 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -1011,7 +1011,7 @@ void CIRGenFunction::emitAtomicStore(RValue rvalue, LValue dest,
if (isVolatile)
store.setIsVolatile(true);
- assert(!cir::MissingFeatures::opLoadStoreTbaa());
+ cgm.decorateOperationWithTBAA(store, dest.getTBAAInfo());
return;
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 85b38120169fd..98cabf899bfa7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -462,7 +462,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
mlir::IntegerAttr align = getAlignmentAttr(addr.getAlignment());
return cir::LoadOp::create(*this, loc, addr.getPointer(), /*isDeref=*/false,
isVolatile, /*alignment=*/align,
- /*mem_order=*/cir::MemOrderAttr{});
+ /*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{});
}
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty,
@@ -473,7 +473,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
mlir::IntegerAttr alignAttr = getAlignmentAttr(alignment);
return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false,
/*isVolatile=*/false, alignAttr,
- /*mem_order=*/cir::MemOrderAttr{});
+ /*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{});
}
cir::LoadOp
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 0f10347944fae..b775317a6a0c0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -429,7 +429,15 @@ void CIRGenFunction::initializeVTablePointer(mlir::Location loc,
builder, loc, builder.getPtrToVPtrType(), classAddr.getPointer());
Address vtableField = Address(vtablePtr, classAddr.getAlignment());
builder.createStore(loc, vtableAddressPoint, vtableField);
- assert(!cir::MissingFeatures::opTBAA());
+
+ cir::StoreOp 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());
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 70497258eb64a..dd1143c9301b1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -14,6 +14,7 @@
#include "CIRGenConstantEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
+#include "CIRGenTBAA.h"
#include "CIRGenValue.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Value.h"
@@ -69,7 +70,8 @@ Address CIRGenFunction::emitAddrOfFieldStorage(Address base,
/// Given an expression of pointer type, try to
/// derive a more accurate bound on the alignment of the pointer.
Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,
- LValueBaseInfo *baseInfo) {
+ LValueBaseInfo *baseInfo,
+ TBAAAccessInfo *tbaaInfo) {
// We allow this with ObjC object pointers because of fragile ABIs.
assert(expr->getType()->isPointerType() ||
expr->getType()->isObjCObjectPointerType());
@@ -98,12 +100,18 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,
*baseInfo = innerBaseInfo;
if (isa<ExplicitCastExpr>(ce)) {
- LValueBaseInfo targetTypeBaseInfo;
-
const QualType pointeeType = expr->getType()->getPointeeType();
+
+ LValueBaseInfo targetTypeBaseInfo;
const CharUnits align =
cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
+ if (tbaaInfo) {
+ TBAAAccessInfo targetTypeTbaaInfo = cgm.getTBAAAccessInfo(pointeeType);
+ *tbaaInfo =
+ cgm.mergeTBAAInfoForCast(*tbaaInfo, targetTypeTbaaInfo);
+ }
+
// If the source l-value is opaque, honor the alignment of the
// casted-to type.
if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
@@ -315,7 +323,8 @@ static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,
void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
bool isVolatile, QualType ty,
- LValueBaseInfo baseInfo, bool isInit,
+ LValueBaseInfo baseInfo, TBAAAccessInfo tbaaInfo,
+ bool isInit,
bool isNontemporal) {
assert(!cir::MissingFeatures::opLoadStoreThreadLocal());
@@ -338,8 +347,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
value = emitToMemory(value, ty);
- assert(!cir::MissingFeatures::opLoadStoreTbaa());
- LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);
+ LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo, tbaaInfo);
if (ty->isAtomicType() ||
(!isInit && isLValueSuitableForInlineAtomic(atomicLValue))) {
emitAtomicStore(RValue::get(value), atomicLValue, isInit);
@@ -357,14 +365,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
}
assert(currSrcLoc && "must pass in source location");
- builder.createStore(*currSrcLoc, value, addr, isVolatile);
+ cir::StoreOp store = builder.createStore(*currSrcLoc, value, addr, isVolatile);
+ cgm.decorateOperationWithTBAA(store, tbaaInfo);
if (isNontemporal) {
cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal");
return;
}
-
- assert(!cir::MissingFeatures::opTBAA());
}
// TODO: Replace this with a proper TargetInfo function call.
@@ -426,6 +433,8 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base,
LValue CIRGenFunction::emitLValueForBitField(LValue base,
const FieldDecl *field) {
LValueBaseInfo baseInfo = base.getBaseInfo();
+ TBAAAccessInfo tbaaInfo{};
+
const CIRGenRecordLayout &layout =
cgm.getTypes().getCIRGenRecordLayout(field->getParent());
const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);
@@ -444,7 +453,7 @@ LValue CIRGenFunction::emitLValueForBitField(LValue base,
// TODO(cir): Support TBAA for bit fields.
assert(!cir::MissingFeatures::opTBAA());
LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());
- return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);
+ return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo, tbaaInfo);
}
LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
@@ -457,7 +466,10 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
const RecordDecl *rec = field->getParent();
AlignmentSource baseAlignSource = baseInfo.getAlignmentSource();
LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource));
- assert(!cir::MissingFeatures::opTBAA());
+ TBAAAccessInfo fieldTbaaInfo{};
+
+ // TODO(cir): Initialize tbaa info
+ assert(!MissingFeatures::opTBAA());
Address addr = base.getAddress();
if (auto *classDecl = dyn_cast<CXXRecordDecl>(rec)) {
@@ -489,11 +501,11 @@ 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::opTBAA());
- 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;
@@ -561,13 +573,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue,
}
emitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
- lvalue.getType(), lvalue.getBaseInfo(), isInit,
+ lvalue.getType(), lvalue.getBaseInfo(), lvalue.getTBAAInfo(), isInit,
/*isNontemporal=*/false);
}
mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile,
QualType ty, SourceLocation loc,
- LValueBaseInfo baseInfo) {
+ LValueBaseInfo baseInfo, TBAAAccessInfo tbaaInfo) {
assert(!cir::MissingFeatures::opLoadStoreThreadLocal());
mlir::Type eltTy = addr.getElementType();
@@ -586,8 +598,7 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile,
"emitLoadOfScalar Vec3 & PreserveVec3Type disabled");
}
- assert(!cir::MissingFeatures::opLoadStoreTbaa());
- LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);
+ LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo, tbaaInfo);
if (ty->isAtomicType() || isLValueSuitableForInlineAtomic(atomicLValue))
cgm.errorNYI("emitLoadOfScalar: load atomic");
@@ -596,19 +607,21 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile,
assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck());
- mlir::Value loadOp = builder.createLoad(getLoc(loc), addr, isVolatile);
+ cir::LoadOp loadOp = builder.createLoad(getLoc(loc), addr, isVolatile);
+ cgm.decorateOperationWithTBAA(loadOp, tbaaInfo);
+
if (!ty->isBooleanType() && ty->hasBooleanRepresentation())
cgm.errorNYI("emitLoadOfScalar: boolean type with boolean representation");
+
return loadOp;
}
mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,
SourceLocation loc) {
assert(!cir::MissingFeatures::opLoadStoreNontemporal());
- assert(!cir::MissingFeatures::opLoadStoreTbaa());
return emitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
- lvalue.getType(), loc, lvalue.getBaseInfo());
+ lvalue.getType(), loc, lvalue.getBaseInfo(), lvalue.getTBAAInfo());
}
/// Given an expression that represents a value lvalue, this
@@ -2285,17 +2298,19 @@ RValue CIRGenFunction::emitReferenceBindingToExpr(const Expr *e) {
}
Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc,
- LValueBaseInfo *pointeeBaseInfo) {
+ LValueBaseInfo *pointeeBaseInfo, TBAAAccessInfo *pointeeTbaaInfo) {
if (refLVal.isVolatile())
cgm.errorNYI(loc, "load of volatile reference");
+ QualType pointeeType = refLVal.getType()->getPointeeType();
cir::LoadOp load =
cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(),
refLVal.getAddress().getPointer());
- assert(!cir::MissingFeatures::opTBAA());
+ cgm.decorateOperationWithTBAA(load, refLVal.getTBAAInfo());
+ if (pointeeTbaaInfo)
+ *pointeeTbaaInfo = cgm.getTBAAAccessInfo(pointeeType);
- QualType pointeeType = refLVal.getType()->getPointeeType();
CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
return Address(load, convertTypeForMem(pointeeType), align);
}
@@ -2306,10 +2321,10 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,
AlignmentSource source) {
LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
LValueBaseInfo pointeeBaseInfo;
- assert(!cir::MissingFeatures::opTBAA());
- Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
+ TBAAAccessInfo tbaaAccessInfo;
+ Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo, &tbaaAccessInfo);
return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
- pointeeBaseInfo);
+ pointeeBaseInfo, tbaaAccessInfo);
}
void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 872fc8d14ad95..b466b68b8f0ae 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -983,7 +983,13 @@ void CIRGenFunction::emitAggregateCopy(LValue dest, LValue src, QualType ty,
[[maybe_unused]] cir::CopyOp copyOp =
builder.createCopy(destPtr.getPointer(), srcPtr.getPointer(), isVolatile);
- assert(!cir::MissingFeatures::opTBAA());
+ assert(!cir::MissingFeatures::opTBAAStruct());
+
+ if (cgm.getCodeGenOpts().NewStructPathTBAA) {
+ TBAAAccessInfo tbaaInfo = cgm.mergeTBAAInfoForMemoryTransfer(
+ dest.getTBAAInfo(), src.getTBAAInfo());
+ cgm.decorateOperationWithTBAA(copyOp, tbaaInfo);
+ }
}
// TODO(cir): This could be shared with classic codegen.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 33bdfa315a9ea..c38bf6d90c915 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -14,6 +14,7 @@
#include "CIRGenCXXABI.h"
#include "CIRGenCall.h"
+#include "CIRGenTBAA.h"
#include "CIRGenValue.h"
#include "mlir/IR/Location.h"
#include "clang/AST/ExprCXX.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index a3a7b4a207a81..53512163596cd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -16,6 +16,7 @@
#include "CIRGenBuilder.h"
#include "CIRGenCall.h"
#include "CIRGenModule.h"
+#include "CIRGenTBAA.h"
#include "CIRGenTypeCache.h"
#include "CIRGenValue.h"
#include "EHScopeStack.h"
@@ -838,11 +839,13 @@ class CIRGenFunction : public CIRGenTypeCache {
LValue makeAddrLValue(Address addr, QualType ty,
AlignmentSource source = AlignmentSource::Type) {
- return makeAddrLValue(addr, ty, LValueBaseInfo(source));
+ return makeAddrLValue(addr, ty, LValueBaseInfo(source),
+ cgm.getTBAAAccessInfo(ty));
}
- LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo) {
- return LValue::makeAddr(addr, ty, baseInfo);
+ LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo,
+ TBAAAccessInfo tbaaInfo = {}) {
+ return LValue::makeAddr(addr, ty, baseInfo, tbaaInfo);
}
void initializeVTablePointers(mlir::Location loc,
@@ -1670,7 +1673,7 @@ class CIRGenFunction : public CIRGenTypeCache {
RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
- LValueBaseInfo *pointeeBaseInfo);
+ LValueBaseInfo *pointeeBaseInfo, TBAAAccessInfo *pointeeTbaaInfo);
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
QualType refTy, AlignmentSource source);
@@ -1680,7 +1683,7 @@ class CIRGenFunction : public CIRGenTypeCache {
/// l-value.
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
- SourceLocation loc, LValueBaseInfo baseInfo);
+ SourceLocation loc, LValueBaseInfo baseInfo, TBAAAccessInfo tbaaInfo);
/// Emit code to compute a designator that specifies the location
/// of the expression.
@@ -1719,7 +1722,8 @@ class CIRGenFunction : public CIRGenTypeCache {
/// reasonable to just ignore the returned alignment when it isn't from an
/// explicit source.
Address emitPointerWithAlignment(const clang::Expr *expr,
- LValueBaseInfo *baseInfo = nullptr);
+ LValueBaseInfo *baseInfo = nullptr,
+ TBAAAccessInfo *tbaaInfo = nullptr);
/// Emits a reference binding to the passed in expression.
RValue emitReferenceBindingToExpr(const Expr *e);
@@ -1748,7 +1752,7 @@ class CIRGenFunction : public CIRGenTypeCache {
bool isInit);
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
- clang::QualType ty, LValueBaseInfo baseInfo,
+ clang::QualType ty, LValueBaseInfo baseInfo, TBAAAccessInfo tbaaInfo,
bool isInit = false, bool isNontemporal = false);
void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index e09d3de5aac9a..d36973f2a1e3c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -20,12 +20,15 @@
#include "clang/AST/DeclOpenACC.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/TypeBase.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
#include "clang/CIR/MissingFeatures.h"
#include "CIRGenFunctionInfo.h"
+#include "CIRGenTBAA.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
@@ -96,6 +99,13 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
astContext.getTargetInfo().getPointerAlign(LangAS::Default))
.getQuantity();
+
+ // Enable TBAA unless it's suppressed. TSan and TySan need TBAA even at O0.
+ if (langOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) ||
+ (!codeGenOpts.RelaxedAliasing && codeGenOpts.OptimizationLevel > 0))
+ tbaa = std::make_unique<CIRGenTBAA>(&mlirContext, astContext, getTypes(), theModule, codeGenOpts,
+ getLangOpts());
+
const unsigned charSize = astContext.getTargetInfo().getCharWidth();
uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
@@ -160,7 +170,6 @@ CharUnits CIRGenModule::getClassPointerAlignment(const CXXRecordDecl *rd) {
CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
LValueBaseInfo *baseInfo) {
- assert(!cir::MissingFeatures::opTBAA());
// FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
// that doesn't return the information we need to compute baseInfo.
@@ -2492,3 +2501,73 @@ DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature) {
return errorNYI(loc.getBegin(), feature) << loc;
}
+
+cir::TBAAAttr CIRGenModule::getTBAATypeInfo(QualType type) {
+ if (!tbaa) {
+ return nullptr;
+ }
+ return tbaa->getTypeInfo(type);
+}
+
+TBAAAccessInfo CIRGenModule::getTBAAAccessInfo(QualType accessType) {
+ if (!tbaa) {
+ return TBAAAccessInfo{};
+ }
+ if (getLangOpts().CUDAIsDevice) {
+ llvm_unreachable("TBAA access NYI");
+ }
+ return tbaa->getAccessInfo(accessType);
+}
+
+TBAAAccessInfo
+CIRGenModule::getTBAAVTablePtrAccessInfo(mlir::Type vTablePtrType) {
+ if (!tbaa)
+ return TBAAAccessInfo{};
+
+ llvm_unreachable("TBAA vtable pointer access NYI");
+ return tbaa->getVTablePtrAccessInfo(vTablePtrType);
+}
+
+mlir::ArrayAttr CIRGenModule::getTBAAStructInfo(QualType type) {
+ if (!tbaa)
+ return nullptr;
+ return tbaa->getTBAAStructInfo(type);
+}
+
+cir::TBAAAttr CIRGenModule::getTBAABaseTypeInfo(QualType type) {
+ if (!tbaa) {
+ return nullptr;
+ }
+ return tbaa->getBaseTypeInfo(type);
+}
+
+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 2c45bb238f95a..d83575226231e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -15,17 +15,21 @@
#include "CIRGenBuilder.h"
#include "CIRGenCall.h"
+#include "CIRGenTBAA.h"
#include "CIRGenTypeCache.h"
#include "CIRGenTypes.h"
#include "CIRGenVTables.h"
#include "CIRGenValue.h"
#include "clang/AST/CharUnits.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "TargetInfo.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "clang/AST/Decl.h"
@@ -85,6 +89,8 @@ class CIRGenModule : public CIRGenTypeCache {
std::unique_ptr<CIRGenCXXABI> abi;
+ std::unique_ptr<CIRGenTBAA> tbaa;
+
CIRGenTypes genTypes;
/// Holds information about C++ vtables.
@@ -325,6 +331,52 @@ class CIRGenModule : public CIRGenTypeCache {
clang::CharUnits getNaturalTypeAlignment(clang::QualType t,
LValueBaseInfo *baseInfo);
+ /// Get attribute used to describe accesses to objects of
+ /// the given type.
+ cir::TBAAAttr getTBAATypeInfo(QualType type);
+
+ /// 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 type);
+
+ /// 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 type);
+
+ 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 <typename Op>
+ void decorateOperationWithTBAA(Op op, TBAAAccessInfo tbaaInfo) {
+ if (mlir::ArrayAttr tag = getTBAAAccessTagInfo(tbaaInfo)) {
+ op.setTbaaAttr(tag);
+ }
+ }
+
/// TODO: Add TBAAAccessInfo
CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign,
const CXXRecordDecl *baseDecl,
diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp
new file mode 100644
index 0000000000000..a6e1667875695
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp
@@ -0,0 +1,65 @@
+#include "CIRGenTBAA.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"
+
+namespace clang::CIRGen {
+
+static cir::TBAAAttr tbaaNYI(mlir::MLIRContext *ctx) {
+ return cir::TBAAAttr::get(ctx);
+}
+
+CIRGenTBAA::CIRGenTBAA(mlir::MLIRContext *mlirContext,
+ clang::ASTContext &astContext, CIRGenTypes &types,
+ mlir::ModuleOp moduleOp,
+ const clang::CodeGenOptions &codeGenOpts,
+ const clang::LangOptions &features)
+ : mlirContext(mlirContext), astContext(astContext), types(types),
+ moduleOp(moduleOp), codeGenOpts(codeGenOpts), features(features) {}
+
+cir::TBAAAttr CIRGenTBAA::getTypeInfo(clang::QualType qty) {
+ return tbaaNYI(mlirContext);
+}
+
+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(mlirContext, {});
+}
+
+cir::TBAAAttr CIRGenTBAA::getBaseTypeInfo(clang::QualType qty) {
+ return tbaaNYI(mlirContext);
+}
+
+mlir::ArrayAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) {
+ return mlir::ArrayAttr::get(mlirContext, {tbaaNYI(mlirContext)});
+}
+
+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
new file mode 100644
index 0000000000000..c05e8f4e6f964
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.h
@@ -0,0 +1,188 @@
+//===--- CIRGenTBAA.h - TBAA information for LLVM CIRGen --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the code that manages TBAA information and defines the TBAA policy
+// for the optimizer to use.
+//
+//===----------------------------------------------------------------------===//
+
+#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),
+ size(size) {}
+
+ TBAAAccessInfo(cir::TBAAAttr baseType, cir::TBAAAttr accessType,
+ uint64_t offset, uint64_t size)
+ : TBAAAccessInfo(TBAAAccessKind::Ordinary, baseType, accessType, offset,
+ size) {}
+
+ explicit TBAAAccessInfo(cir::TBAAAttr accessType, uint64_t size)
+ : TBAAAccessInfo(TBAAAccessKind::Ordinary, /* baseType= */ {}, accessType,
+ /* offset= */ 0, size) {}
+
+ TBAAAccessInfo()
+ : TBAAAccessInfo(/* accessType= */ nullptr, /* size= */ 0) {};
+
+ static TBAAAccessInfo getMayAliasInfo() {
+ return TBAAAccessInfo(TBAAAccessKind::MayAlias, /* baseType= */ {},
+ /* accessType= */ nullptr,
+ /* offset= */ 0, /* size= */ 0);
+ }
+
+ static TBAAAccessInfo getIncompleteInfo() {
+ return TBAAAccessInfo(TBAAAccessKind::Incomplete, /* baseType= */ {},
+ /* accessType= */ {},
+ /* offset= */ 0, /* size= */ 0);
+ }
+
+ bool isMayAlias() const { return kind == TBAAAccessKind::MayAlias; }
+
+ 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 *mlirContext;
+ [[maybe_unused]] clang::ASTContext &astContext;
+ [[maybe_unused]] CIRGenTypes &types;
+ mlir::ModuleOp moduleOp;
+ [[maybe_unused]] const clang::CodeGenOptions &codeGenOpts;
+ [[maybe_unused]] const clang::LangOptions &features;
+
+public:
+ CIRGenTBAA(mlir::MLIRContext *mlirContext, clang::ASTContext &astContext,
+ 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<clang::CIRGen::TBAAAccessInfo> {
+ static clang::CIRGen::TBAAAccessInfo getEmptyKey() {
+ unsigned unsignedKey = DenseMapInfo<unsigned>::getEmptyKey();
+ return clang::CIRGen::TBAAAccessInfo(
+ static_cast<clang::CIRGen::TBAAAccessKind>(unsignedKey),
+ DenseMapInfo<cir::TBAAAttr>::getEmptyKey(),
+ DenseMapInfo<cir::TBAAAttr>::getEmptyKey(),
+ DenseMapInfo<uint64_t>::getEmptyKey(),
+ DenseMapInfo<uint64_t>::getEmptyKey());
+ }
+ static clang::CIRGen::TBAAAccessInfo getTombstoneKey() {
+ unsigned unsignedKey = DenseMapInfo<unsigned>::getTombstoneKey();
+ return clang::CIRGen::TBAAAccessInfo(
+ static_cast<clang::CIRGen::TBAAAccessKind>(unsignedKey),
+ DenseMapInfo<cir::TBAAAttr>::getTombstoneKey(),
+ DenseMapInfo<cir::TBAAAttr>::getTombstoneKey(),
+ DenseMapInfo<uint64_t>::getTombstoneKey(),
+ DenseMapInfo<uint64_t>::getTombstoneKey());
+ }
+ static unsigned getHashValue(const clang::CIRGen::TBAAAccessInfo &val) {
+ auto kindValue = static_cast<unsigned>(val.kind);
+ return DenseMapInfo<unsigned>::getHashValue(kindValue) ^
+ DenseMapInfo<cir::TBAAAttr>::getHashValue(val.baseType) ^
+ DenseMapInfo<cir::TBAAAttr>::getHashValue(val.accessType) ^
+ DenseMapInfo<uint64_t>::getHashValue(val.offset) ^
+ DenseMapInfo<uint64_t>::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 2002bd7e7c488..6324292ee4770 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -20,6 +20,7 @@
#include "clang/AST/Type.h"
#include "CIRGenRecordLayout.h"
+#include "CIRGenTBAA.h"
#include "mlir/IR/Value.h"
#include "clang/CIR/MissingFeatures.h"
@@ -172,9 +173,11 @@ class LValue {
mlir::Type elementType;
LValueBaseInfo baseInfo;
const CIRGenBitFieldInfo *bitFieldInfo{nullptr};
+ TBAAAccessInfo tbaaInfo;
void initialize(clang::QualType type, clang::Qualifiers quals,
- clang::CharUnits alignment, LValueBaseInfo baseInfo) {
+ clang::CharUnits alignment, LValueBaseInfo baseInfo,
+ TBAAAccessInfo tbaaInfo) {
assert((!alignment.isZero() || type->isIncompleteType()) &&
"initializing l-value with zero alignment!");
this->type = type;
@@ -223,6 +226,9 @@ class LValue {
assert(!cir::MissingFeatures::addressIsKnownNonNull());
}
+ TBAAAccessInfo getTBAAInfo() const { return tbaaInfo; }
+ void setTBAAInfo(TBAAAccessInfo info) { tbaaInfo = info; }
+
const clang::Qualifiers &getQuals() const { return quals; }
clang::Qualifiers &getQuals() { return quals; }
@@ -230,7 +236,8 @@ class LValue {
void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }
static LValue makeAddr(Address address, clang::QualType t,
- LValueBaseInfo baseInfo) {
+ LValueBaseInfo baseInfo,
+ TBAAAccessInfo tbaaInfo = {}) {
// Classic codegen sets the objc gc qualifier here. That requires an
// ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.
assert(!cir::MissingFeatures::objCGC());
@@ -239,7 +246,8 @@ class LValue {
r.lvType = Simple;
r.v = address.getPointer();
r.elementType = address.getElementType();
- r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);
+ r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo,
+ tbaaInfo);
return r;
}
@@ -274,26 +282,28 @@ class LValue {
}
static LValue makeVectorElt(Address vecAddress, mlir::Value index,
- clang::QualType t, LValueBaseInfo baseInfo) {
+ clang::QualType t, LValueBaseInfo baseInfo,
+ TBAAAccessInfo tbaaInfo = {}) {
LValue r;
r.lvType = VectorElt;
r.v = vecAddress.getPointer();
r.elementType = vecAddress.getElementType();
r.vectorIdx = index;
- r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);
+ r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo,
+ tbaaInfo);
return r;
}
static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts,
- clang::QualType type,
- LValueBaseInfo baseInfo) {
+ clang::QualType type, LValueBaseInfo baseInfo,
+ TBAAAccessInfo tbaaInfo = {}) {
LValue r;
r.lvType = ExtVectorElt;
r.v = vecAddress.getPointer();
r.elementType = vecAddress.getElementType();
r.vectorElts = elts;
r.initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
- baseInfo);
+ baseInfo, tbaaInfo);
return r;
}
@@ -319,13 +329,15 @@ class LValue {
/// \param Info - The information describing how to perform the bit-field
/// access.
static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info,
- clang::QualType type, LValueBaseInfo baseInfo) {
+ clang::QualType type, LValueBaseInfo baseInfo,
+ TBAAAccessInfo tbaaInfo) {
LValue r;
r.lvType = BitField;
r.v = addr.getPointer();
r.elementType = addr.getElementType();
r.bitFieldInfo = &info;
- r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
+ r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo,
+ tbaaInfo);
return r;
}
};
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index d3e2290ceea0b..81f844404096f 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -40,6 +40,7 @@ add_clang_library(clangCIR
CIRGenStmt.cpp
CIRGenStmtOpenACC.cpp
CIRGenStmtOpenACCLoop.cpp
+ CIRGenTBAA.cpp
CIRGenTypes.cpp
CIRGenVTables.cpp
TargetInfo.cpp
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 6bf543cf794b7..daa8b6cf4b7ea 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -61,7 +61,6 @@ struct CIROpAsmDialectInterface : public OpAsmDialectInterface {
os << voidType.getAlias();
return AliasResult::OverridableAlias;
}
-
return AliasResult::NoAlias;
}
@@ -78,6 +77,11 @@ struct CIROpAsmDialectInterface : public OpAsmDialectInterface {
os << dynCastInfoAttr.getAlias();
return AliasResult::FinalAlias;
}
+ if (auto tbaaAttr = mlir::dyn_cast<cir::TBAAAttr>(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 66469e208d7b0..1e6b88afca233 100644
--- a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp
@@ -143,7 +143,7 @@ DeletionKind cir::CopyOp::removeBlockingUses(
cir::StoreOp::create(builder, getLoc(), reachingDefinition, getDst(),
/*isVolatile=*/false,
/*alignment=*/mlir::IntegerAttr{},
- /*mem-order=*/cir::MemOrderAttr());
+ /*mem-order=*/cir::MemOrderAttr(), /*tbaa=*/mlir::ArrayAttr{});
return DeletionKind::Delete;
}
More information about the cfe-commits
mailing list