https://github.com/HendrikHuebner created https://github.com/llvm/llvm-project/pull/169226
This PR implements the basic handling for emitting TBAA attributes during lowering. TODO: Tests From 89e04a20bebc64c967adae0eea5c7ff14497d559 Mon Sep 17 00:00:00 2001 From: hhuebner <[email protected]> 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/lib/CIR/CodeGen/CIRGenBuilder.h | 4 +- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 5 +- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 1 + clang/lib/CIR/CodeGen/CIRGenFunction.h | 9 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 70 +++++++ clang/lib/CIR/CodeGen/CIRGenModule.h | 50 +++++ 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 +- 15 files changed, 445 insertions(+), 27 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/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/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 70497258eb64a..ef7538f167b90 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" @@ -426,6 +427,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 +447,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) { 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..8d374eb723045 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, diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index e09d3de5aac9a..138ead60d68f0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -21,6 +21,7 @@ #include "clang/AST/GlobalDecl.h" #include "clang/AST/RecordLayout.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" @@ -2492,3 +2493,72 @@ DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, llvm::StringRef feature) { return errorNYI(loc.getBegin(), feature) << loc; } + +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); +} + +cir::TBAAAttr 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..9aed53e52eb08 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -15,16 +15,19 @@ #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/BuiltinOps.h" #include "mlir/IR/MLIRContext.h" @@ -85,6 +88,8 @@ class CIRGenModule : public CIRGenTypeCache { std::unique_ptr<CIRGenCXXABI> abi; + std::unique_ptr<CIRGenTBAA> tbaa; + CIRGenTypes genTypes; /// Holds information about C++ vtables. @@ -324,6 +329,51 @@ class CIRGenModule : public CIRGenTypeCache { /// with codegen. clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo); + /// 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); + + cir::TBAAAttr 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 (auto tag = getTBAAAccessTagInfo(tbaaInfo)) { + op.setTbaaAttr(tag); + } + } /// TODO: Add TBAAAccessInfo CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign, diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp new file mode 100644 index 0000000000000..9d4e89f6e7a3e --- /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); +} + +cir::TBAAAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) { + return 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..fc5fbd6c74fcb --- /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. + cir::TBAAAttr 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..3568449f873a5 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -78,6 +78,12 @@ 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; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
