Skip to content

Commit c302703

Browse files
Lancernlanza
authored andcommitted
[CIR][NFC] move data member pointer lowering to CXXABI (#1130)
This PR 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 c450b99 commit c302703

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)