Skip to content

Commit b5f3862

Browse files
authored
[CIR][LowerToLLVM][CXXABI] Lower cir.va.arg (#573)
lowering var_arg op for ARM64 architecture. This is CIR lowering. This PR modified LoweringPrepare CXXABI code to make LoweringPrepareArm64CXXABI class inherit more generic LoweringPrepareItaniumCXXABI, this way lowering var_arg would be only meaningful for arm64 targets and for other arch its no op for now. The ABI doc and detailed algorithm description can be found in this official doc. [](https://github.com/ARM-software/abi-aa/blob/617079d8a0d45bec83d351974849483cf0cc66d5/aapcs64/aapcs64.rst#appendix-variable-argument-lists)
1 parent 492242b commit b5f3862

11 files changed

+705
-32
lines changed

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

+13
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,19 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
269269
return createCast(mlir::cir::CastKind::int_to_ptr, src, newTy);
270270
}
271271

272+
mlir::Value createGetMemberOp(mlir::Location &loc, mlir::Value structPtr,
273+
const char *fldName, unsigned idx) {
274+
275+
assert(structPtr.getType().isa<mlir::cir::PointerType>());
276+
auto structBaseTy =
277+
structPtr.getType().cast<mlir::cir::PointerType>().getPointee();
278+
assert(structBaseTy.isa<mlir::cir::StructType>());
279+
auto fldTy = structBaseTy.cast<mlir::cir::StructType>().getMembers()[idx];
280+
auto fldPtrTy = ::mlir::cir::PointerType::get(getContext(), fldTy);
281+
return create<mlir::cir::GetMemberOp>(loc, fldPtrTy, structPtr, fldName,
282+
idx);
283+
}
284+
272285
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
273286
return createCast(mlir::cir::CastKind::ptr_to_int, src, newTy);
274287
}

clang/lib/CIR/Dialect/IR/MissingFeatures.h

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ struct MissingFeatures {
2121
// C++ ABI support
2222
static bool cxxABI() { return false; }
2323
static bool setCallingConv() { return false; }
24+
static bool handleBigEndian() { return false; }
25+
static bool handleAArch64Indirect() { return false; }
26+
static bool classifyArgumentTypeForAArch64() { return false; }
27+
static bool supportgetCoerceToTypeForAArch64() { return false; }
28+
static bool supportTySizeQueryForAArch64() { return false; }
29+
static bool supportTyAlignQueryForAArch64() { return false; }
30+
static bool supportisHomogeneousAggregateQueryForAArch64() { return false; }
31+
static bool supportisEndianQueryForAArch64() { return false; }
32+
static bool supportisAggregateTypeForABIAArch64() { return false; }
2433

2534
// Address space related
2635
static bool addressSpace() { return false; }

clang/lib/CIR/Dialect/Transforms/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_clang_library(MLIRCIRTransforms
22
LifetimeCheck.cpp
33
LoweringPrepare.cpp
44
LoweringPrepareItaniumCXXABI.cpp
5+
LoweringPrepareAArch64CXXABI.cpp
56
MergeCleanups.cpp
67
DropAST.cpp
78
IdiomRecognizer.cpp

clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp

+34-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include "clang/AST/CharUnits.h"
1616
#include "clang/AST/Mangle.h"
1717
#include "clang/Basic/Module.h"
18+
#include "clang/Basic/TargetInfo.h"
1819
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
20+
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
1921
#include "clang/CIR/Dialect/IR/CIRDialect.h"
2022
#include "clang/CIR/Dialect/Passes.h"
2123
#include "clang/CIR/Interfaces/ASTAttrInterfaces.h"
@@ -70,6 +72,7 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
7072

7173
void runOnOp(Operation *op);
7274
void lowerThreeWayCmpOp(CmpThreeWayOp op);
75+
void lowerVAArgOp(VAArgOp op);
7376
void lowerGlobalOp(GlobalOp op);
7477
void lowerDynamicCastOp(DynamicCastOp op);
7578
void lowerStdFindOp(StdFindOp op);
@@ -108,15 +111,24 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
108111

109112
void setASTContext(clang::ASTContext *c) {
110113
astCtx = c;
114+
auto abiStr = c->getTargetInfo().getABI();
111115
switch (c->getCXXABIKind()) {
112116
case clang::TargetCXXABI::GenericItanium:
117+
cxxABI.reset(::cir::LoweringPrepareCXXABI::createItaniumABI());
118+
break;
113119
case clang::TargetCXXABI::GenericAArch64:
114120
case clang::TargetCXXABI::AppleARM64:
115-
// TODO: this isn't quite right, clang uses AppleARM64CXXABI which
116-
// inherits from ARMCXXABI. We'll have to follow suit.
117-
cxxABI.reset(::cir::LoweringPrepareCXXABI::createItaniumABI());
121+
// TODO: This is temporary solution. ABIKind info should be
122+
// propagated from the targetInfo managed by ABI lowering
123+
// query system.
124+
assert(abiStr == "aapcs" || abiStr == "darwinpcs" ||
125+
abiStr == "aapcs-soft");
126+
cxxABI.reset(::cir::LoweringPrepareCXXABI::createAArch64ABI(
127+
abiStr == "aapcs"
128+
? ::cir::AArch64ABIKind::AAPCS
129+
: (abiStr == "darwinpccs" ? ::cir::AArch64ABIKind::DarwinPCS
130+
: ::cir::AArch64ABIKind::AAPCSSoft)));
118131
break;
119-
120132
default:
121133
llvm_unreachable("NYI");
122134
}
@@ -320,6 +332,19 @@ static void canonicalizeIntrinsicThreeWayCmp(CIRBaseBuilderTy &builder,
320332
op.erase();
321333
}
322334

335+
void LoweringPreparePass::lowerVAArgOp(VAArgOp op) {
336+
CIRBaseBuilderTy builder(getContext());
337+
builder.setInsertionPoint(op);
338+
::cir::CIRDataLayout datalayout(theModule);
339+
340+
auto res = cxxABI->lowerVAArg(builder, op, datalayout);
341+
if (res) {
342+
op.replaceAllUsesWith(res);
343+
op.erase();
344+
}
345+
return;
346+
}
347+
323348
void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
324349
CIRBaseBuilderTy builder(getContext());
325350
builder.setInsertionPointAfter(op);
@@ -603,6 +628,8 @@ void LoweringPreparePass::lowerIterEndOp(IterEndOp op) {
603628
void LoweringPreparePass::runOnOp(Operation *op) {
604629
if (auto threeWayCmp = dyn_cast<CmpThreeWayOp>(op)) {
605630
lowerThreeWayCmpOp(threeWayCmp);
631+
} else if (auto vaArgOp = dyn_cast<VAArgOp>(op)) {
632+
lowerVAArgOp(vaArgOp);
606633
} else if (auto getGlobal = dyn_cast<GlobalOp>(op)) {
607634
lowerGlobalOp(getGlobal);
608635
} else if (auto dynamicCast = dyn_cast<DynamicCastOp>(op)) {
@@ -635,8 +662,9 @@ void LoweringPreparePass::runOnOperation() {
635662

636663
SmallVector<Operation *> opsToTransform;
637664
op->walk([&](Operation *op) {
638-
if (isa<CmpThreeWayOp, GlobalOp, DynamicCastOp, StdFindOp, IterEndOp,
639-
IterBeginOp, ArrayCtor, ArrayDtor, mlir::cir::FuncOp>(op))
665+
if (isa<CmpThreeWayOp, VAArgOp, GlobalOp, DynamicCastOp, StdFindOp,
666+
IterEndOp, IterBeginOp, ArrayCtor, ArrayDtor, mlir::cir::FuncOp>(
667+
op))
640668
opsToTransform.push_back(op);
641669
});
642670

0 commit comments

Comments
 (0)