Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR][CIRGen][TBAA] Add support for scalar types #1220

Merged
merged 1 commit into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
/*alignment=*/intAttr,
/*mem_order=*/
cir::MemOrderAttr{},
/*tbaa=*/mlir::ArrayAttr{});
/*tbaa=*/cir::TBAAAttr{});
}

mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
Expand Down Expand Up @@ -357,7 +357,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
val.getType())
dst = createPtrBitcast(dst, val.getType());
return create<cir::StoreOp>(loc, val, dst, _volatile, align, order,
/*tbaa=*/mlir::ArrayAttr{});
/*tbaa=*/cir::TBAAAttr{});
}

mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
Expand Down Expand Up @@ -405,7 +405,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
bool isVolatile = false) {
return create<cir::CopyOp>(dst.getLoc(), dst, src, isVolatile,
/*tbaa=*/mlir::ArrayAttr{});
/*tbaa=*/cir::TBAAAttr{});
}

cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst,
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ include "clang/CIR/Interfaces/ASTAttrInterfaces.td"
// CIR Attrs
//===----------------------------------------------------------------------===//

class CIR_Attr<string name, string attrMnemonic, list<Trait> traits = []>
: AttrDef<CIR_Dialect, name, traits> {
class CIR_Attr<string name, string attrMnemonic, list<Trait> traits = [],
string baseCppClass = "::mlir::Attribute">
: AttrDef<CIR_Dialect, name, traits, baseCppClass> {
let mnemonic = attrMnemonic;
}

Expand Down Expand Up @@ -1294,8 +1295,7 @@ def GlobalAnnotationValuesAttr : CIR_Attr<"GlobalAnnotationValues",
let genVerifyDecl = 1;
}

def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> {
}
include "clang/CIR/Dialect/IR/CIRTBAAAttrs.td"

include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td"

Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ def LoadOp : CIR_Op<"load", [
UnitAttr:$is_volatile,
OptionalAttr<I64Attr>:$alignment,
OptionalAttr<MemOrder>:$mem_order,
OptionalAttr<ArrayAttr>:$tbaa
OptionalAttr<CIR_AnyTBAAAttr>:$tbaa
);
let results = (outs CIR_AnyType:$result);

Expand Down Expand Up @@ -657,7 +657,7 @@ def StoreOp : CIR_Op<"store", [
UnitAttr:$is_volatile,
OptionalAttr<I64Attr>:$alignment,
OptionalAttr<MemOrder>:$mem_order,
OptionalAttr<ArrayAttr>:$tbaa);
OptionalAttr<CIR_AnyTBAAAttr>:$tbaa);

let assemblyFormat = [{
(`volatile` $is_volatile^)?
Expand Down Expand Up @@ -4068,7 +4068,7 @@ def CopyOp : CIR_Op<"copy",
let arguments = (ins Arg<CIR_PointerType, "", [MemWrite]>:$dst,
Arg<CIR_PointerType, "", [MemRead]>:$src,
UnitAttr:$is_volatile,
OptionalAttr<ArrayAttr>:$tbaa);
OptionalAttr<CIR_TBAAAttr>:$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
Expand Down
38 changes: 38 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
// TBAAAttr
//===----------------------------------------------------------------------===//

def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> {
let summary = "CIR dialect TBAA base attribute";
}

//===----------------------------------------------------------------------===//
// TBAAScalarAttr
//===----------------------------------------------------------------------===//

def CIR_TBAAScalarAttr : CIR_Attr<"TBAAScalar", "tbaa_scalar", [], "TBAAAttr"> {
let summary = "Describes a scalar type in TBAA with an identifier.";

let parameters = (ins CIR_AnyScalarType : $type);

let description = [{
Define a TBAA attribute.

Example:
```mlir
// CIR_TBAAScalarAttr
#tbaa_scalar = #cir.tbaa_scalar<type = !s32i>
#tbaa_scalar1 = #cir.tbaa_scalar<type = !u32i>
```

See the following link for more details:
https://llvm.org/docs/LangRef.html#tbaa-metadata
}];

let assemblyFormat = "`<` struct(params) `>`";
}

def CIR_AnyTBAAAttr : AnyAttrOf<[
CIR_TBAAAttr,
CIR_TBAAScalarAttr
]>;
29 changes: 29 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ def CIR_IntType : CIR_Type<"Int", "int",
static bool isValidPrimitiveIntBitwidth(unsigned width) {
return width == 8 || width == 16 || width == 32 || width == 64;
}

llvm::StringRef getTBAATypeName() const {
switch (getWidth()) {
case 1:
case 8: {
return "omnipotent char";
}
case 16: {
return "short";
}
case 32: {
return "int";
}
case 64: {
return "long";
}
default: {
llvm::errs() << "unknown type: " << *this << "\n";
return "unknown";
}
}
}
}];
let genVerifyDecl = 1;
}
Expand Down Expand Up @@ -609,4 +631,11 @@ def CIR_AnyType : AnyTypeOf<[
CIR_ComplexType
]>;

def CIR_AnyScalarType : AnyTypeOf<[
CIR_IntType, CIR_PointerType, CIR_DataMemberType, CIR_MethodType,
CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_FuncType, CIR_VoidType,
CIR_ExceptionType, CIR_AnyFloat, CIR_FP16, CIR_BFloat16,
CIR_ComplexType
]>;

#endif // MLIR_CIR_DIALECT_CIR_TYPES
7 changes: 6 additions & 1 deletion clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ 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 tbaaStruct() { return false; }
static bool tbaaTagForStruct() { return false; }
static bool tbaaVTablePtr() { return false; }
static bool tbaaIncompleteType() { return false; }
static bool tbaaMergeTBAAInfo() { return false; }
static bool tbaaMayAlias() { return false; }
static bool cleanups() { return false; }
static bool emitNullabilityCheck() { return false; }
static bool ptrAuth() { return false; }
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return create<cir::LoadOp>(
loc, addr.getElementType(), addr.getPointer(), /*isDeref=*/false,
/*is_volatile=*/isVolatile, /*alignment=*/mlir::IntegerAttr{},
/*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{});
/*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/cir::TBAAAttr{});
}

mlir::Value createAlignedLoad(mlir::Location loc, mlir::Type ty,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1716,7 +1716,7 @@ void CIRGenFunction::emitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
// 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.
assert(!cir::MissingFeatures::tbaa_struct() && "tbaa.struct NYI");
assert(!cir::MissingFeatures::tbaaStruct() && "tbaa.struct NYI");
if (CGM.getCodeGenOpts().NewStructPathTBAA) {
TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer(
Dest.getTBAAInfo(), Src.getTBAAInfo());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3988,7 +3988,7 @@ cir::TBAAAttr CIRGenModule::getTBAABaseTypeInfo(QualType QTy) {
return tbaa->getBaseTypeInfo(QTy);
}

mlir::ArrayAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) {
cir::TBAAAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) {
if (!tbaa) {
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ class CIRGenModule : public CIRGenTypeCache {
/// type is not suitable for use in TBAA access tags.
cir::TBAAAttr getTBAABaseTypeInfo(QualType QTy);

mlir::ArrayAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo);
cir::TBAAAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo);

/// Get merged TBAA information for the purposes of type casts.
TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,
Expand Down
128 changes: 122 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenTBAA.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#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 "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang::CIRGen {

Expand All @@ -21,44 +22,159 @@ CIRGenTBAA::CIRGenTBAA(mlir::MLIRContext *mlirContext,
: mlirContext(mlirContext), astContext(astContext), types(types),
moduleOp(moduleOp), codeGenOpts(codeGenOpts), features(features) {}

cir::TBAAAttr CIRGenTBAA::getChar() {
return cir::TBAAScalarAttr::get(mlirContext,
cir::IntType::get(mlirContext, 1, true));
}

static bool typeHasMayAlias(clang::QualType qty) {
// Tagged types have declarations, and therefore may have attributes.
if (auto *td = qty->getAsTagDecl())
if (td->hasAttr<MayAliasAttr>())
return true;

// Also look for may_alias as a declaration attribute on a typedef.
// FIXME: We should follow GCC and model may_alias as a type attribute
// rather than as a declaration attribute.
while (auto *tt = qty->getAs<TypedefType>()) {
if (tt->getDecl()->hasAttr<MayAliasAttr>())
return true;
qty = tt->desugar();
}
return false;
}

/// Check if the given type is a valid base type to be used in access tags.
static bool isValidBaseType(clang::QualType qty) {
if (const clang::RecordType *tty = qty->getAs<clang::RecordType>()) {
const clang::RecordDecl *rd = tty->getDecl()->getDefinition();
// Incomplete types are not valid base access types.
if (!rd)
return false;
if (rd->hasFlexibleArrayMember())
return false;
// rd can be struct, union, class, interface or enum.
// For now, we only handle struct and class.
if (rd->isStruct() || rd->isClass())
return true;
}
return false;
}

cir::TBAAAttr CIRGenTBAA::getTypeInfo(clang::QualType qty) {
return tbaa_NYI(mlirContext);
// At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
if (codeGenOpts.OptimizationLevel == 0 || codeGenOpts.RelaxedAliasing) {
return nullptr;
}

// If the type has the may_alias attribute (even on a typedef), it is
// effectively in the general char alias class.
if (typeHasMayAlias(qty)) {
assert(!cir::MissingFeatures::tbaaMayAlias());
return getChar();
PikachuHyA marked this conversation as resolved.
Show resolved Hide resolved
}
// We need this function to not fall back to returning the "omnipotent char"
// type node for aggregate and union types. Otherwise, any dereference of an
// aggregate will result into the may-alias access descriptor, meaning all
// subsequent accesses to direct and indirect members of that aggregate will
// be considered may-alias too.
// function.
if (isValidBaseType(qty)) {
// TODO(cir): support TBAA with struct
return tbaa_NYI(mlirContext);
PikachuHyA marked this conversation as resolved.
Show resolved Hide resolved
}

const clang::Type *ty = astContext.getCanonicalType(qty).getTypePtr();
if (metadataCache.contains(ty)) {
return metadataCache[ty];
}

// Note that the following helper call is allowed to add new nodes to the
// cache, which invalidates all its previously obtained iterators. So we
// first generate the node for the type and then add that node to the
// cache.
auto typeNode = cir::TBAAScalarAttr::get(mlirContext, types.ConvertType(qty));
return metadataCache[ty] = typeNode;
}

TBAAAccessInfo CIRGenTBAA::getAccessInfo(clang::QualType accessType) {
return TBAAAccessInfo();
// Pointee values may have incomplete types, but they shall never be
// dereferenced.
if (accessType->isIncompleteType()) {
assert(!cir::MissingFeatures::tbaaIncompleteType());
return TBAAAccessInfo::getIncompleteInfo();
PikachuHyA marked this conversation as resolved.
Show resolved Hide resolved
}

if (typeHasMayAlias(accessType)) {
assert(!cir::MissingFeatures::tbaaMayAlias());
return TBAAAccessInfo::getMayAliasInfo();
PikachuHyA marked this conversation as resolved.
Show resolved Hide resolved
}

uint64_t size = astContext.getTypeSizeInChars(accessType).getQuantity();
return TBAAAccessInfo(getTypeInfo(accessType), size);
}

TBAAAccessInfo CIRGenTBAA::getVTablePtrAccessInfo(mlir::Type vtablePtrType) {
// TODO(cir): support vtable ptr
bcardosolopes marked this conversation as resolved.
Show resolved Hide resolved
assert(!cir::MissingFeatures::tbaaVTablePtr());
return TBAAAccessInfo();
}

mlir::ArrayAttr CIRGenTBAA::getTBAAStructInfo(clang::QualType qty) {
return mlir::ArrayAttr::get(mlirContext, {});
assert(!cir::MissingFeatures::tbaaStruct() && "tbaa.struct NYI");
return mlir::ArrayAttr();
}

cir::TBAAAttr CIRGenTBAA::getBaseTypeInfo(clang::QualType qty) {
return tbaa_NYI(mlirContext);
}

mlir::ArrayAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) {
return mlir::ArrayAttr::get(mlirContext, {tbaa_NYI(mlirContext)});
cir::TBAAAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) {
assert(!tbaaInfo.isIncomplete() &&
"Access to an object of an incomplete type!");
bcardosolopes marked this conversation as resolved.
Show resolved Hide resolved

if (tbaaInfo.isMayAlias()) {
assert(!cir::MissingFeatures::tbaaMayAlias());
tbaaInfo = TBAAAccessInfo(getChar(), tbaaInfo.size);
}
if (!tbaaInfo.accessType) {
return nullptr;
}

if (!codeGenOpts.StructPathTBAA)
tbaaInfo = TBAAAccessInfo(tbaaInfo.accessType, tbaaInfo.size);

if (!tbaaInfo.baseType) {
tbaaInfo.baseType = tbaaInfo.accessType;
assert(!tbaaInfo.offset &&
"Nonzero offset for an access with no base type!");
}
if (codeGenOpts.NewStructPathTBAA) {
llvm_unreachable("NYI");
}
if (tbaaInfo.baseType == tbaaInfo.accessType) {
return tbaaInfo.accessType;
}
return tbaa_NYI(mlirContext);
}

TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo,
TBAAAccessInfo targetInfo) {
assert(!cir::MissingFeatures::tbaaMergeTBAAInfo());
return TBAAAccessInfo();
}

TBAAAccessInfo
CIRGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA,
TBAAAccessInfo infoB) {
assert(!cir::MissingFeatures::tbaaMergeTBAAInfo());
return TBAAAccessInfo();
}

TBAAAccessInfo
CIRGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo,
TBAAAccessInfo srcInfo) {
assert(!cir::MissingFeatures::tbaaMergeTBAAInfo());
return TBAAAccessInfo();
}

Expand Down
Loading
Loading