Skip to content

Commit c94c04e

Browse files
authored
[CIR][CIRGen][TBAA] Add support for scalar types (llvm#1220)
1 parent 8d649fb commit c94c04e

20 files changed

+505
-58
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
170170
/*alignment=*/intAttr,
171171
/*mem_order=*/
172172
cir::MemOrderAttr{},
173-
/*tbaa=*/mlir::ArrayAttr{});
173+
/*tbaa=*/cir::TBAAAttr{});
174174
}
175175

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

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

411411
cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst,

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ include "clang/CIR/Interfaces/ASTAttrInterfaces.td"
2424
// CIR Attrs
2525
//===----------------------------------------------------------------------===//
2626

27-
class CIR_Attr<string name, string attrMnemonic, list<Trait> traits = []>
28-
: AttrDef<CIR_Dialect, name, traits> {
27+
class CIR_Attr<string name, string attrMnemonic, list<Trait> traits = [],
28+
string baseCppClass = "::mlir::Attribute">
29+
: AttrDef<CIR_Dialect, name, traits, baseCppClass> {
2930
let mnemonic = attrMnemonic;
3031
}
3132

@@ -1294,8 +1295,7 @@ def GlobalAnnotationValuesAttr : CIR_Attr<"GlobalAnnotationValues",
12941295
let genVerifyDecl = 1;
12951296
}
12961297

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

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

clang/include/clang/CIR/Dialect/IR/CIROps.td

+3-3
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ def LoadOp : CIR_Op<"load", [
588588
UnitAttr:$is_volatile,
589589
OptionalAttr<I64Attr>:$alignment,
590590
OptionalAttr<MemOrder>:$mem_order,
591-
OptionalAttr<ArrayAttr>:$tbaa
591+
OptionalAttr<CIR_AnyTBAAAttr>:$tbaa
592592
);
593593
let results = (outs CIR_AnyType:$result);
594594

@@ -657,7 +657,7 @@ def StoreOp : CIR_Op<"store", [
657657
UnitAttr:$is_volatile,
658658
OptionalAttr<I64Attr>:$alignment,
659659
OptionalAttr<MemOrder>:$mem_order,
660-
OptionalAttr<ArrayAttr>:$tbaa);
660+
OptionalAttr<CIR_AnyTBAAAttr>:$tbaa);
661661

662662
let assemblyFormat = [{
663663
(`volatile` $is_volatile^)?
@@ -4068,7 +4068,7 @@ def CopyOp : CIR_Op<"copy",
40684068
let arguments = (ins Arg<CIR_PointerType, "", [MemWrite]>:$dst,
40694069
Arg<CIR_PointerType, "", [MemRead]>:$src,
40704070
UnitAttr:$is_volatile,
4071-
OptionalAttr<ArrayAttr>:$tbaa);
4071+
OptionalAttr<CIR_TBAAAttr>:$tbaa);
40724072
let summary = "Copies contents from a CIR pointer to another";
40734073
let description = [{
40744074
Given two CIR pointers, `src` and `dst`, `cir.copy` will copy the memory
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===----------------------------------------------------------------------===//
2+
// TBAAAttr
3+
//===----------------------------------------------------------------------===//
4+
5+
def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> {
6+
let summary = "CIR dialect TBAA base attribute";
7+
}
8+
9+
//===----------------------------------------------------------------------===//
10+
// TBAAScalarAttr
11+
//===----------------------------------------------------------------------===//
12+
13+
def CIR_TBAAScalarAttr : CIR_Attr<"TBAAScalar", "tbaa_scalar", [], "TBAAAttr"> {
14+
let summary = "Describes a scalar type in TBAA with an identifier.";
15+
16+
let parameters = (ins CIR_AnyScalarType : $type);
17+
18+
let description = [{
19+
Define a TBAA attribute.
20+
21+
Example:
22+
```mlir
23+
// CIR_TBAAScalarAttr
24+
#tbaa_scalar = #cir.tbaa_scalar<type = !s32i>
25+
#tbaa_scalar1 = #cir.tbaa_scalar<type = !u32i>
26+
```
27+
28+
See the following link for more details:
29+
https://llvm.org/docs/LangRef.html#tbaa-metadata
30+
}];
31+
32+
let assemblyFormat = "`<` struct(params) `>`";
33+
}
34+
35+
def CIR_AnyTBAAAttr : AnyAttrOf<[
36+
CIR_TBAAAttr,
37+
CIR_TBAAScalarAttr
38+
]>;

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

+29
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,28 @@ def CIR_IntType : CIR_Type<"Int", "int",
7474
static bool isValidPrimitiveIntBitwidth(unsigned width) {
7575
return width == 8 || width == 16 || width == 32 || width == 64;
7676
}
77+
78+
llvm::StringRef getTBAATypeName() const {
79+
switch (getWidth()) {
80+
case 1:
81+
case 8: {
82+
return "omnipotent char";
83+
}
84+
case 16: {
85+
return "short";
86+
}
87+
case 32: {
88+
return "int";
89+
}
90+
case 64: {
91+
return "long";
92+
}
93+
default: {
94+
llvm::errs() << "unknown type: " << *this << "\n";
95+
return "unknown";
96+
}
97+
}
98+
}
7799
}];
78100
let genVerifyDecl = 1;
79101
}
@@ -609,4 +631,11 @@ def CIR_AnyType : AnyTypeOf<[
609631
CIR_ComplexType
610632
]>;
611633

634+
def CIR_AnyScalarType : AnyTypeOf<[
635+
CIR_IntType, CIR_PointerType, CIR_DataMemberType, CIR_MethodType,
636+
CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_FuncType, CIR_VoidType,
637+
CIR_ExceptionType, CIR_AnyFloat, CIR_FP16, CIR_BFloat16,
638+
CIR_ComplexType
639+
]>;
640+
612641
#endif // MLIR_CIR_DIALECT_CIR_TYPES

clang/include/clang/CIR/MissingFeatures.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ struct MissingFeatures {
5858
// sanitizer related type check features
5959
static bool emitTypeCheck() { return false; }
6060
static bool tbaa() { return false; }
61-
static bool tbaa_struct() { return false; }
61+
static bool tbaaStruct() { return false; }
62+
static bool tbaaTagForStruct() { return false; }
63+
static bool tbaaVTablePtr() { return false; }
64+
static bool tbaaIncompleteType() { return false; }
65+
static bool tbaaMergeTBAAInfo() { return false; }
66+
static bool tbaaMayAlias() { return false; }
6267
static bool cleanups() { return false; }
6368
static bool emitNullabilityCheck() { return false; }
6469
static bool ptrAuth() { return false; }

clang/lib/CIR/CodeGen/CIRGenBuilder.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
839839
return create<cir::LoadOp>(
840840
loc, addr.getElementType(), addr.getPointer(), /*isDeref=*/false,
841841
/*is_volatile=*/isVolatile, /*alignment=*/mlir::IntegerAttr{},
842-
/*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{});
842+
/*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/cir::TBAAAttr{});
843843
}
844844

845845
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Type ty,

clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1716,7 +1716,7 @@ void CIRGenFunction::emitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
17161716
// Determine the metadata to describe the position of any padding in this
17171717
// memcpy, as well as the TBAA tags for the members of the struct, in case
17181718
// the optimizer wishes to expand it in to scalar memory operations.
1719-
assert(!cir::MissingFeatures::tbaa_struct() && "tbaa.struct NYI");
1719+
assert(!cir::MissingFeatures::tbaaStruct() && "tbaa.struct NYI");
17201720
if (CGM.getCodeGenOpts().NewStructPathTBAA) {
17211721
TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer(
17221722
Dest.getTBAAInfo(), Src.getTBAAInfo());

clang/lib/CIR/CodeGen/CIRGenModule.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3988,7 +3988,7 @@ cir::TBAAAttr CIRGenModule::getTBAABaseTypeInfo(QualType QTy) {
39883988
return tbaa->getBaseTypeInfo(QTy);
39893989
}
39903990

3991-
mlir::ArrayAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) {
3991+
cir::TBAAAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) {
39923992
if (!tbaa) {
39933993
return nullptr;
39943994
}

clang/lib/CIR/CodeGen/CIRGenModule.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ class CIRGenModule : public CIRGenTypeCache {
525525
/// type is not suitable for use in TBAA access tags.
526526
cir::TBAAAttr getTBAABaseTypeInfo(QualType QTy);
527527

528-
mlir::ArrayAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo);
528+
cir::TBAAAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo);
529529

530530
/// Get merged TBAA information for the purposes of type casts.
531531
TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo,

clang/lib/CIR/CodeGen/CIRGenTBAA.cpp

+122-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#include "CIRGenTBAA.h"
2-
#include "CIRGenCXXABI.h"
32
#include "CIRGenTypes.h"
43
#include "mlir/IR/BuiltinAttributes.h"
54
#include "mlir/IR/MLIRContext.h"
65
#include "mlir/Interfaces/DataLayoutInterfaces.h"
76
#include "clang/AST/ASTContext.h"
87
#include "clang/AST/RecordLayout.h"
8+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
9+
#include "clang/CIR/MissingFeatures.h"
910
#include "llvm/Support/ErrorHandling.h"
1011
namespace clang::CIRGen {
1112

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

25+
cir::TBAAAttr CIRGenTBAA::getChar() {
26+
return cir::TBAAScalarAttr::get(mlirContext,
27+
cir::IntType::get(mlirContext, 1, true));
28+
}
29+
30+
static bool typeHasMayAlias(clang::QualType qty) {
31+
// Tagged types have declarations, and therefore may have attributes.
32+
if (auto *td = qty->getAsTagDecl())
33+
if (td->hasAttr<MayAliasAttr>())
34+
return true;
35+
36+
// Also look for may_alias as a declaration attribute on a typedef.
37+
// FIXME: We should follow GCC and model may_alias as a type attribute
38+
// rather than as a declaration attribute.
39+
while (auto *tt = qty->getAs<TypedefType>()) {
40+
if (tt->getDecl()->hasAttr<MayAliasAttr>())
41+
return true;
42+
qty = tt->desugar();
43+
}
44+
return false;
45+
}
46+
47+
/// Check if the given type is a valid base type to be used in access tags.
48+
static bool isValidBaseType(clang::QualType qty) {
49+
if (const clang::RecordType *tty = qty->getAs<clang::RecordType>()) {
50+
const clang::RecordDecl *rd = tty->getDecl()->getDefinition();
51+
// Incomplete types are not valid base access types.
52+
if (!rd)
53+
return false;
54+
if (rd->hasFlexibleArrayMember())
55+
return false;
56+
// rd can be struct, union, class, interface or enum.
57+
// For now, we only handle struct and class.
58+
if (rd->isStruct() || rd->isClass())
59+
return true;
60+
}
61+
return false;
62+
}
63+
2464
cir::TBAAAttr CIRGenTBAA::getTypeInfo(clang::QualType qty) {
25-
return tbaa_NYI(mlirContext);
65+
// At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
66+
if (codeGenOpts.OptimizationLevel == 0 || codeGenOpts.RelaxedAliasing) {
67+
return nullptr;
68+
}
69+
70+
// If the type has the may_alias attribute (even on a typedef), it is
71+
// effectively in the general char alias class.
72+
if (typeHasMayAlias(qty)) {
73+
assert(!cir::MissingFeatures::tbaaMayAlias());
74+
return getChar();
75+
}
76+
// We need this function to not fall back to returning the "omnipotent char"
77+
// type node for aggregate and union types. Otherwise, any dereference of an
78+
// aggregate will result into the may-alias access descriptor, meaning all
79+
// subsequent accesses to direct and indirect members of that aggregate will
80+
// be considered may-alias too.
81+
// function.
82+
if (isValidBaseType(qty)) {
83+
// TODO(cir): support TBAA with struct
84+
return tbaa_NYI(mlirContext);
85+
}
86+
87+
const clang::Type *ty = astContext.getCanonicalType(qty).getTypePtr();
88+
if (metadataCache.contains(ty)) {
89+
return metadataCache[ty];
90+
}
91+
92+
// Note that the following helper call is allowed to add new nodes to the
93+
// cache, which invalidates all its previously obtained iterators. So we
94+
// first generate the node for the type and then add that node to the
95+
// cache.
96+
auto typeNode = cir::TBAAScalarAttr::get(mlirContext, types.ConvertType(qty));
97+
return metadataCache[ty] = typeNode;
2698
}
2799

28100
TBAAAccessInfo CIRGenTBAA::getAccessInfo(clang::QualType accessType) {
29-
return TBAAAccessInfo();
101+
// Pointee values may have incomplete types, but they shall never be
102+
// dereferenced.
103+
if (accessType->isIncompleteType()) {
104+
assert(!cir::MissingFeatures::tbaaIncompleteType());
105+
return TBAAAccessInfo::getIncompleteInfo();
106+
}
107+
108+
if (typeHasMayAlias(accessType)) {
109+
assert(!cir::MissingFeatures::tbaaMayAlias());
110+
return TBAAAccessInfo::getMayAliasInfo();
111+
}
112+
113+
uint64_t size = astContext.getTypeSizeInChars(accessType).getQuantity();
114+
return TBAAAccessInfo(getTypeInfo(accessType), size);
30115
}
31116

32117
TBAAAccessInfo CIRGenTBAA::getVTablePtrAccessInfo(mlir::Type vtablePtrType) {
118+
// TODO(cir): support vtable ptr
119+
assert(!cir::MissingFeatures::tbaaVTablePtr());
33120
return TBAAAccessInfo();
34121
}
35122

36123
mlir::ArrayAttr CIRGenTBAA::getTBAAStructInfo(clang::QualType qty) {
37-
return mlir::ArrayAttr::get(mlirContext, {});
124+
assert(!cir::MissingFeatures::tbaaStruct() && "tbaa.struct NYI");
125+
return mlir::ArrayAttr();
38126
}
39127

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

44-
mlir::ArrayAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) {
45-
return mlir::ArrayAttr::get(mlirContext, {tbaa_NYI(mlirContext)});
132+
cir::TBAAAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) {
133+
assert(!tbaaInfo.isIncomplete() &&
134+
"Access to an object of an incomplete type!");
135+
136+
if (tbaaInfo.isMayAlias()) {
137+
assert(!cir::MissingFeatures::tbaaMayAlias());
138+
tbaaInfo = TBAAAccessInfo(getChar(), tbaaInfo.size);
139+
}
140+
if (!tbaaInfo.accessType) {
141+
return nullptr;
142+
}
143+
144+
if (!codeGenOpts.StructPathTBAA)
145+
tbaaInfo = TBAAAccessInfo(tbaaInfo.accessType, tbaaInfo.size);
146+
147+
if (!tbaaInfo.baseType) {
148+
tbaaInfo.baseType = tbaaInfo.accessType;
149+
assert(!tbaaInfo.offset &&
150+
"Nonzero offset for an access with no base type!");
151+
}
152+
if (codeGenOpts.NewStructPathTBAA) {
153+
llvm_unreachable("NYI");
154+
}
155+
if (tbaaInfo.baseType == tbaaInfo.accessType) {
156+
return tbaaInfo.accessType;
157+
}
158+
return tbaa_NYI(mlirContext);
46159
}
47160

48161
TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo,
49162
TBAAAccessInfo targetInfo) {
163+
assert(!cir::MissingFeatures::tbaaMergeTBAAInfo());
50164
return TBAAAccessInfo();
51165
}
52166

53167
TBAAAccessInfo
54168
CIRGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA,
55169
TBAAAccessInfo infoB) {
170+
assert(!cir::MissingFeatures::tbaaMergeTBAAInfo());
56171
return TBAAAccessInfo();
57172
}
58173

59174
TBAAAccessInfo
60175
CIRGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo,
61176
TBAAAccessInfo srcInfo) {
177+
assert(!cir::MissingFeatures::tbaaMergeTBAAInfo());
62178
return TBAAAccessInfo();
63179
}
64180

0 commit comments

Comments
 (0)