Skip to content

Commit 9529507

Browse files
committed
[CIR][NFC] move data member pointer lowering to CXXABI
This patch moves the lowering code for data member pointers from the conversion patterns to the implementation of CXXABI because this part should be ABI- specific.
1 parent dbd3e03 commit 9529507

File tree

5 files changed

+159
-55
lines changed

5 files changed

+159
-55
lines changed

clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h

+26
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@
1515
#define LLVM_CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRCXXABI_H
1616

1717
#include "LowerFunctionInfo.h"
18+
#include "mlir/IR/Attributes.h"
19+
#include "mlir/IR/Types.h"
1820
#include "mlir/IR/Value.h"
21+
#include "mlir/Interfaces/DataLayoutInterfaces.h"
22+
#include "mlir/Transforms/DialectConversion.h"
1923
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
24+
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
2025
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
26+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
2127
#include "clang/CIR/Target/AArch64.h"
2228

2329
namespace cir {
@@ -59,6 +65,26 @@ class CIRCXXABI {
5965
/// Returns how an argument of the given record type should be passed.
6066
/// FIXME(cir): This expects a CXXRecordDecl! Not any record type.
6167
virtual RecordArgABI getRecordArgABI(const StructType RD) const = 0;
68+
69+
/// Lower the given data member pointer type to its ABI type. The returned
70+
/// type is also a CIR type.
71+
virtual mlir::Type
72+
lowerDataMemberType(cir::DataMemberType type,
73+
const mlir::TypeConverter &typeConverter) const = 0;
74+
75+
/// Lower the given data member pointer constant to a constant of the ABI
76+
/// type. The returned constant is represented as an attribute as well.
77+
virtual mlir::TypedAttr
78+
lowerDataMemberConstant(cir::DataMemberAttr attr,
79+
const mlir::DataLayout &layout,
80+
const mlir::TypeConverter &typeConverter) const = 0;
81+
82+
/// Lower the given cir.get_runtime_member op to a sequence of more
83+
/// "primitive" CIR operations that act on the ABI types.
84+
virtual mlir::Operation *
85+
lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
86+
mlir::Value loweredAddr, mlir::Value loweredMember,
87+
mlir::OpBuilder &builder) const = 0;
6288
};
6389

6490
/// Creates an Itanium-family ABI.

clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "../LoweringPrepareCXXABI.h"
2424
#include "CIRCXXABI.h"
2525
#include "LowerModule.h"
26+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
2627
#include "llvm/Support/ErrorHandling.h"
2728

2829
namespace cir {
@@ -51,6 +52,19 @@ class ItaniumCXXABI : public CIRCXXABI {
5152
cir_cconv_assert(!cir::MissingFeatures::recordDeclCanPassInRegisters());
5253
return RAA_Default;
5354
}
55+
56+
mlir::Type
57+
lowerDataMemberType(cir::DataMemberType type,
58+
const mlir::TypeConverter &typeConverter) const override;
59+
60+
mlir::TypedAttr lowerDataMemberConstant(
61+
cir::DataMemberAttr attr, const mlir::DataLayout &layout,
62+
const mlir::TypeConverter &typeConverter) const override;
63+
64+
mlir::Operation *
65+
lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
66+
mlir::Value loweredAddr, mlir::Value loweredMember,
67+
mlir::OpBuilder &builder) const override;
5468
};
5569

5670
} // namespace
@@ -67,6 +81,54 @@ bool ItaniumCXXABI::classifyReturnType(LowerFunctionInfo &FI) const {
6781
return false;
6882
}
6983

84+
mlir::Type ItaniumCXXABI::lowerDataMemberType(
85+
cir::DataMemberType type, const mlir::TypeConverter &typeConverter) const {
86+
// Itanium C++ ABI 2.3:
87+
// A pointer to data member is an offset from the base address of
88+
// the class object containing it, represented as a ptrdiff_t
89+
const clang::TargetInfo &target = LM.getTarget();
90+
clang::TargetInfo::IntType ptrdiffTy =
91+
target.getPtrDiffType(clang::LangAS::Default);
92+
return cir::IntType::get(type.getContext(), target.getTypeWidth(ptrdiffTy),
93+
target.isTypeSigned(ptrdiffTy));
94+
}
95+
96+
mlir::TypedAttr ItaniumCXXABI::lowerDataMemberConstant(
97+
cir::DataMemberAttr attr, const mlir::DataLayout &layout,
98+
const mlir::TypeConverter &typeConverter) const {
99+
uint64_t memberOffset;
100+
if (attr.isNullPtr()) {
101+
// Itanium C++ ABI 2.3:
102+
// A NULL pointer is represented as -1.
103+
memberOffset = -1ull;
104+
} else {
105+
// Itanium C++ ABI 2.3:
106+
// A pointer to data member is an offset from the base address of
107+
// the class object containing it, represented as a ptrdiff_t
108+
auto memberIndex = attr.getMemberIndex().value();
109+
memberOffset =
110+
attr.getType().getClsTy().getElementOffset(layout, memberIndex);
111+
}
112+
113+
mlir::Type abiTy = lowerDataMemberType(attr.getType(), typeConverter);
114+
return cir::IntAttr::get(abiTy, memberOffset);
115+
}
116+
117+
mlir::Operation *ItaniumCXXABI::lowerGetRuntimeMember(
118+
cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
119+
mlir::Value loweredAddr, mlir::Value loweredMember,
120+
mlir::OpBuilder &builder) const {
121+
auto byteTy = IntType::get(op.getContext(), 8, true);
122+
auto bytePtrTy = PointerType::get(
123+
byteTy, mlir::cast<PointerType>(op.getAddr().getType()).getAddrSpace());
124+
auto objectBytesPtr = builder.create<CastOp>(op.getLoc(), bytePtrTy,
125+
CastKind::bitcast, op.getAddr());
126+
auto memberBytesPtr = builder.create<PtrStrideOp>(
127+
op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
128+
return builder.create<CastOp>(op.getLoc(), op.getType(), CastKind::bitcast,
129+
memberBytesPtr);
130+
}
131+
70132
CIRCXXABI *CreateItaniumCXXABI(LowerModule &LM) {
71133
switch (LM.getCXXABIKind()) {
72134
// Note that AArch64 uses the generic ItaniumCXXABI class since it doesn't

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+33-41
Original file line numberDiff line numberDiff line change
@@ -1521,28 +1521,6 @@ bool hasTrailingZeros(cir::ConstArrayAttr attr) {
15211521
}));
15221522
}
15231523

1524-
static mlir::Attribute
1525-
lowerDataMemberAttr(mlir::ModuleOp moduleOp, cir::DataMemberAttr attr,
1526-
const mlir::TypeConverter &typeConverter) {
1527-
mlir::DataLayout layout{moduleOp};
1528-
1529-
uint64_t memberOffset;
1530-
if (attr.isNullPtr()) {
1531-
// TODO(cir): the numerical value of a null data member pointer is
1532-
// ABI-specific and should be queried through ABI.
1533-
assert(!MissingFeatures::targetCodeGenInfoGetNullPointer());
1534-
memberOffset = -1ull;
1535-
} else {
1536-
auto memberIndex = attr.getMemberIndex().value();
1537-
memberOffset =
1538-
attr.getType().getClsTy().getElementOffset(layout, memberIndex);
1539-
}
1540-
1541-
auto underlyingIntTy = mlir::IntegerType::get(
1542-
moduleOp->getContext(), layout.getTypeSizeInBits(attr.getType()));
1543-
return mlir::IntegerAttr::get(underlyingIntTy, memberOffset);
1544-
}
1545-
15461524
mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
15471525
cir::ConstantOp op, OpAdaptor adaptor,
15481526
mlir::ConversionPatternRewriter &rewriter) const {
@@ -1602,9 +1580,13 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
16021580
}
16031581
attr = op.getValue();
16041582
} else if (mlir::isa<cir::DataMemberType>(op.getType())) {
1583+
assert(lowerMod && "lower module is not available");
16051584
auto dataMember = mlir::cast<cir::DataMemberAttr>(op.getValue());
1606-
attr = lowerDataMemberAttr(op->getParentOfType<mlir::ModuleOp>(),
1607-
dataMember, *typeConverter);
1585+
mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1586+
mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant(
1587+
dataMember, layout, *typeConverter);
1588+
rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
1589+
return mlir::success();
16081590
}
16091591
// TODO(cir): constant arrays are currently just pushed into the stack using
16101592
// the store instruction, instead of being stored as global variables and
@@ -2208,8 +2190,15 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
22082190
return mlir::success();
22092191
} else if (auto dataMemberAttr =
22102192
mlir::dyn_cast<cir::DataMemberAttr>(init.value())) {
2211-
init = lowerDataMemberAttr(op->getParentOfType<mlir::ModuleOp>(),
2212-
dataMemberAttr, *typeConverter);
2193+
assert(lowerMod && "lower module is not available");
2194+
mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
2195+
mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant(
2196+
dataMemberAttr, layout, *typeConverter);
2197+
auto abiOp = mlir::cast<GlobalOp>(rewriter.clone(*op.getOperation()));
2198+
abiOp.setInitialValueAttr(abiValue);
2199+
abiOp.setSymType(abiValue.getType());
2200+
rewriter.replaceOp(op, abiOp);
2201+
return mlir::success();
22132202
} else if (const auto structAttr =
22142203
mlir::dyn_cast<cir::ConstStructAttr>(init.value())) {
22152204
setupRegionInitializedLLVMGlobalOp(op, rewriter);
@@ -3237,11 +3226,11 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
32373226
mlir::LogicalResult CIRToLLVMGetRuntimeMemberOpLowering::matchAndRewrite(
32383227
cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
32393228
mlir::ConversionPatternRewriter &rewriter) const {
3240-
auto llvmResTy = getTypeConverter()->convertType(op.getType());
3241-
auto llvmElementTy = mlir::IntegerType::get(op.getContext(), 8);
3242-
3243-
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3244-
op, llvmResTy, llvmElementTy, adaptor.getAddr(), adaptor.getMember());
3229+
assert(lowerMod && "lowering module is not available");
3230+
mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3231+
mlir::Operation *llvmOp = lowerMod->getCXXABI().lowerGetRuntimeMember(
3232+
op, llvmResTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
3233+
rewriter.replaceOp(op, llvmOp);
32453234
return mlir::success();
32463235
}
32473236

@@ -3850,14 +3839,17 @@ mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
38503839

38513840
void populateCIRToLLVMConversionPatterns(
38523841
mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter,
3853-
mlir::DataLayout &dataLayout,
3842+
mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule,
38543843
llvm::StringMap<mlir::LLVM::GlobalOp> &stringGlobalsMap,
38553844
llvm::StringMap<mlir::LLVM::GlobalOp> &argStringGlobalsMap,
38563845
llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsVarMap) {
38573846
patterns.add<CIRToLLVMReturnOpLowering>(patterns.getContext());
38583847
patterns.add<CIRToLLVMAllocaOpLowering>(converter, dataLayout,
38593848
stringGlobalsMap, argStringGlobalsMap,
38603849
argsVarMap, patterns.getContext());
3850+
patterns.add<CIRToLLVMConstantOpLowering, CIRToLLVMGlobalOpLowering,
3851+
CIRToLLVMGetRuntimeMemberOpLowering>(
3852+
converter, patterns.getContext(), lowerModule);
38613853
patterns.add<
38623854
// clang-format off
38633855
CIRToLLVMAbsOpLowering,
@@ -3891,7 +3883,6 @@ void populateCIRToLLVMConversionPatterns(
38913883
CIRToLLVMComplexImagPtrOpLowering,
38923884
CIRToLLVMComplexRealOpLowering,
38933885
CIRToLLVMComplexRealPtrOpLowering,
3894-
CIRToLLVMConstantOpLowering,
38953886
CIRToLLVMCopyOpLowering,
38963887
CIRToLLVMDerivedClassAddrOpLowering,
38973888
CIRToLLVMEhInflightOpLowering,
@@ -3902,8 +3893,6 @@ void populateCIRToLLVMConversionPatterns(
39023893
CIRToLLVMGetBitfieldOpLowering,
39033894
CIRToLLVMGetGlobalOpLowering,
39043895
CIRToLLVMGetMemberOpLowering,
3905-
CIRToLLVMGetRuntimeMemberOpLowering,
3906-
CIRToLLVMGlobalOpLowering,
39073896
CIRToLLVMInlineAsmOpLowering,
39083897
CIRToLLVMIsConstantOpLowering,
39093898
CIRToLLVMIsFPClassOpLowering,
@@ -3990,10 +3979,13 @@ void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
39903979

39913980
return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS);
39923981
});
3993-
converter.addConversion([&](cir::DataMemberType type) -> mlir::Type {
3994-
return mlir::IntegerType::get(type.getContext(),
3995-
dataLayout.getTypeSizeInBits(type));
3996-
});
3982+
converter.addConversion(
3983+
[&, lowerModule](cir::DataMemberType type) -> mlir::Type {
3984+
assert(lowerModule && "CXXABI is not available");
3985+
mlir::Type abiType =
3986+
lowerModule->getCXXABI().lowerDataMemberType(type, converter);
3987+
return converter.convertType(abiType);
3988+
});
39973989
converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
39983990
auto ty = converter.convertType(type.getEltType());
39993991
return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
@@ -4328,8 +4320,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
43284320
llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsVarMap;
43294321

43304322
populateCIRToLLVMConversionPatterns(patterns, converter, dataLayout,
4331-
stringGlobalsMap, argStringGlobalsMap,
4332-
argsVarMap);
4323+
lowerModule.get(), stringGlobalsMap,
4324+
argStringGlobalsMap, argsVarMap);
43334325
mlir::populateFuncToLLVMConversionPatterns(converter, patterns);
43344326

43354327
mlir::ConversionTarget target(getContext());

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

+22-3
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,15 @@ class CIRToLLVMStoreOpLowering
291291

292292
class CIRToLLVMConstantOpLowering
293293
: public mlir::OpConversionPattern<cir::ConstantOp> {
294+
cir::LowerModule *lowerMod;
295+
294296
public:
295-
using mlir::OpConversionPattern<cir::ConstantOp>::OpConversionPattern;
297+
CIRToLLVMConstantOpLowering(const mlir::TypeConverter &typeConverter,
298+
mlir::MLIRContext *context,
299+
cir::LowerModule *lowerModule)
300+
: OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {
301+
setHasBoundedRewriteRecursion();
302+
}
296303

297304
mlir::LogicalResult
298305
matchAndRewrite(cir::ConstantOp op, OpAdaptor,
@@ -490,8 +497,15 @@ class CIRToLLVMSwitchFlatOpLowering
490497

491498
class CIRToLLVMGlobalOpLowering
492499
: public mlir::OpConversionPattern<cir::GlobalOp> {
500+
cir::LowerModule *lowerMod;
501+
493502
public:
494-
using mlir::OpConversionPattern<cir::GlobalOp>::OpConversionPattern;
503+
CIRToLLVMGlobalOpLowering(const mlir::TypeConverter &typeConverter,
504+
mlir::MLIRContext *context,
505+
cir::LowerModule *lowerModule)
506+
: OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {
507+
setHasBoundedRewriteRecursion();
508+
}
495509

496510
mlir::LogicalResult
497511
matchAndRewrite(cir::GlobalOp op, OpAdaptor,
@@ -774,8 +788,13 @@ class CIRToLLVMGetMemberOpLowering
774788

775789
class CIRToLLVMGetRuntimeMemberOpLowering
776790
: public mlir::OpConversionPattern<cir::GetRuntimeMemberOp> {
791+
cir::LowerModule *lowerMod;
792+
777793
public:
778-
using mlir::OpConversionPattern<cir::GetRuntimeMemberOp>::OpConversionPattern;
794+
CIRToLLVMGetRuntimeMemberOpLowering(const mlir::TypeConverter &typeConverter,
795+
mlir::MLIRContext *context,
796+
cir::LowerModule *lowerModule)
797+
: OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {}
779798

780799
mlir::LogicalResult
781800
matchAndRewrite(cir::GetRuntimeMemberOp op, OpAdaptor,

clang/test/CIR/Lowering/data-member.cir

+16-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
!s64i = !cir.int<s, 64>
66
!structT = !cir.struct<struct "Point" {!cir.int<s, 32>, !cir.int<s, 32>, !cir.int<s, 32>}>
77

8-
module @test {
8+
module @test attributes {
9+
cir.triple = "x86_64-unknown-linux-gnu",
10+
llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
11+
} {
912
cir.global external @pt_member = #cir.data_member<1> : !cir.data_member<!s32i in !structT>
1013
// MLIR: llvm.mlir.global external @pt_member(4 : i64) {addr_space = 0 : i32} : i64
1114
// LLVM: @pt_member = global i64 4
@@ -15,8 +18,8 @@ module @test {
1518
cir.return %0 : !cir.data_member<!s32i in !structT>
1619
}
1720
// MLIR: llvm.func @constant() -> i64
18-
// MLIR-NEXT: %0 = llvm.mlir.constant(4 : i64) : i64
19-
// MLIR-NEXT: llvm.return %0 : i64
21+
// MLIR-NEXT: %[[#VAL:]] = llvm.mlir.constant(4 : i64) : i64
22+
// MLIR-NEXT: llvm.return %[[#VAL]] : i64
2023
// MLIR-NEXT: }
2124

2225
// LLVM: define i64 @constant()
@@ -28,8 +31,8 @@ module @test {
2831
cir.return %0 : !cir.data_member<!s32i in !structT>
2932
}
3033
// MLIR: llvm.func @null_constant() -> i64
31-
// MLIR-NEXT: %0 = llvm.mlir.constant(-1 : i64) : i64
32-
// MLIR-NEXT: llvm.return %0 : i64
34+
// MLIR-NEXT: %[[#VAL:]] = llvm.mlir.constant(-1 : i64) : i64
35+
// MLIR-NEXT: llvm.return %[[#VAL]] : i64
3336
// MLIR-NEXT: }
3437

3538
// LLVM: define i64 @null_constant() !dbg !7 {
@@ -40,13 +43,15 @@ module @test {
4043
%0 = cir.get_runtime_member %arg0[%arg1 : !cir.data_member<!s32i in !structT>] : !cir.ptr<!structT> -> !cir.ptr<!s32i>
4144
cir.return %0 : !cir.ptr<!s32i>
4245
}
43-
// MLIR: llvm.func @get_runtime_member(%arg0: !llvm.ptr, %arg1: i64) -> !llvm.ptr
44-
// MLIR-NEXT: %0 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, i8
45-
// MLIR-NEXT: llvm.return %0 : !llvm.ptr
46+
// MLIR: llvm.func @get_runtime_member(%[[ARG0:.+]]: !llvm.ptr, %[[ARG1:.+]]: i64) -> !llvm.ptr
47+
// MLIR-NEXT: %[[#PTR:]] = llvm.bitcast %[[ARG0]] : !llvm.ptr to !llvm.ptr
48+
// MLIR-NEXT: %[[#VAL:]] = llvm.getelementptr %[[#PTR]][%[[ARG1]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
49+
// MLIR-NEXT: %[[#RET:]] = llvm.bitcast %[[#VAL]] : !llvm.ptr to !llvm.ptr
50+
// MLIR-NEXT: llvm.return %[[#RET]] : !llvm.ptr
4651
// MLIR-NEXT: }
4752

48-
// LLVM: define ptr @get_runtime_member(ptr %0, i64 %1)
49-
// LLVM-NEXT: %3 = getelementptr i8, ptr %0, i64 %1
50-
// LLVM-NEXT: ret ptr %3
53+
// LLVM: define ptr @get_runtime_member(ptr %[[ARG0:.+]], i64 %[[ARG1:.+]])
54+
// LLVM-NEXT: %[[#VAL:]] = getelementptr i8, ptr %[[ARG0]], i64 %[[ARG1]]
55+
// LLVM-NEXT: ret ptr %[[#VAL]]
5156
// LLVM-NEXT: }
5257
}

0 commit comments

Comments
 (0)