Skip to content

Commit 5214ce7

Browse files
committed
add more skeleton code and missing features
1 parent 298b519 commit 5214ce7

File tree

2 files changed

+100
-13
lines changed

2 files changed

+100
-13
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ struct MissingFeatures {
2828
static bool supportTySizeQueryForAArch64() { return false; }
2929
static bool supportTyAlignQueryForAArch64() { return false; }
3030
static bool supportisHomogeneousAggregateQueryForAArch64() { return false; }
31+
static bool supportisEndianQueryForAArch64() { return false; }
32+
static bool supportisAggregateTypeForABIAArch64() { return false; }
3133

3234
// Address space related
3335
static bool addressSpace() { return false; }

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

+98-13
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "../IR/MissingFeatures.h"
1616
#include "LoweringPrepareItaniumCXXABI.h"
17+
#include "clang/AST/CharUnits.h"
1718
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1819

1920
#include <assert.h>
@@ -67,6 +68,8 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
6768
assert(!cir::MissingFeatures::classifyArgumentTypeForAArch64());
6869
// indirect arg passing would expect one more level of pointer dereference.
6970
assert(!cir::MissingFeatures::handleAArch64Indirect());
71+
// false as a place holder for now, as we don't have a way to query
72+
bool isIndirect = false;
7073
assert(!cir::MissingFeatures::supportgetCoerceToTypeForAArch64());
7174
// we don't convert to LLVM Type here as we are lowering to CIR here.
7275
// so baseTy is the just type of the result of va_arg.
@@ -82,7 +85,7 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
8285
if (Kind == AArch64ABIKind::AAPCSSoft) {
8386
llvm_unreachable("AAPCSSoft cir.var_arg lowering NYI");
8487
}
85-
bool IsFPR = mlir::cir::isAnyFloatingPointType(opResTy);
88+
bool IsFPR = mlir::cir::isAnyFloatingPointType(baseTy);
8689

8790
// The AArch64 va_list type and handling is specified in the Procedure Call
8891
// Standard, section B.4:
@@ -111,13 +114,19 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
111114
// though anyone passing 2GB of arguments, each at most 16 bytes, deserves
112115
// whatever they get).
113116

114-
assert(!cir::MissingFeatures::handleAArch64Indirect());
115117
assert(!cir::MissingFeatures::supportTySizeQueryForAArch64());
116118
assert(!cir::MissingFeatures::supportTyAlignQueryForAArch64());
119+
// One is just place holder for now, as we don't have a way to query
120+
// type size and alignment.
121+
clang::CharUnits tySize = clang::CharUnits::One();
122+
clang::CharUnits tyAlign = clang::CharUnits::One();
123+
;
124+
117125
// indirectness, type size and type alignment all
118126
// decide regSize, but they are all ABI defined
119127
// thus need ABI lowering query system.
120-
int regSize = 8;
128+
assert(!cir::MissingFeatures::handleAArch64Indirect());
129+
int regSize = isIndirect ? 8 : tySize.getQuantity();
121130
int regTopIndex;
122131
mlir::Value regOffsP;
123132
mlir::cir::LoadOp regOffs;
@@ -160,9 +169,10 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
160169
// Integer arguments may need to correct register alignment (for example a
161170
// "struct { __int128 a; };" gets passed in x_2N, x_{2N+1}). In this case we
162171
// align __gr_offs to calculate the potential address.
163-
if (!IsFPR) {
172+
if (!IsFPR && !isIndirect && tyAlign.getQuantity() > 8) {
164173
assert(!cir::MissingFeatures::handleAArch64Indirect());
165174
assert(!cir::MissingFeatures::supportTyAlignQueryForAArch64());
175+
llvm_unreachable("register alignment correction NYI");
166176
}
167177

168178
// Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list.
@@ -193,6 +203,49 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
193203
auto i8Ty = mlir::IntegerType::get(builder.getContext(), 8);
194204
auto i8PtrTy = mlir::cir::PointerType::get(builder.getContext(), i8Ty);
195205
auto castRegTop = builder.createBitcast(regTop, i8PtrTy);
206+
auto resAsInt8P = builder.create<mlir::cir::PtrStrideOp>(
207+
loc, castRegTop.getType(), castRegTop, regOffs);
208+
209+
if (isIndirect) {
210+
assert(!cir::MissingFeatures::handleAArch64Indirect());
211+
llvm_unreachable("indirect arg passing NYI");
212+
}
213+
214+
// TODO: isHFA, numMembers and base should be query result from query
215+
uint64_t numMembers = 0;
216+
assert(!cir::MissingFeatures::supportisHomogeneousAggregateQueryForAArch64());
217+
bool isHFA = false;
218+
assert(!cir::MissingFeatures::supportisEndianQueryForAArch64());
219+
// TODO: endianess should be query result from ABI info
220+
bool isBigEndian = false;
221+
assert(!cir::MissingFeatures::supportisAggregateTypeForABIAArch64());
222+
// TODO: isAggregateTypeForABI should be query result from ABI info
223+
bool isAggregateTypeForABI = false;
224+
if (isHFA && numMembers > 1) {
225+
// Homogeneous aggregates passed in registers will have their elements split
226+
// and stored 16-bytes apart regardless of size (they're notionally in qN,
227+
// qN+1, ...). We reload and store into a temporary local variable
228+
// contiguously.
229+
assert(!isIndirect && "Homogeneous aggregates should be passed directly");
230+
llvm_unreachable("Homogeneous aggregates NYI");
231+
} else {
232+
assert(!cir::MissingFeatures::supportTyAlignQueryForAArch64());
233+
// TODO: slotSize should be query result about alignment.
234+
clang::CharUnits slotSize = clang::CharUnits::fromQuantity(8);
235+
if (isBigEndian && !isIndirect && (isHFA || isAggregateTypeForABI) &&
236+
tySize < slotSize) {
237+
clang::CharUnits offset = slotSize - tySize;
238+
auto offsetConst = builder.create<mlir::cir::ConstantOp>(
239+
loc, regOffs.getType(),
240+
mlir::cir::IntAttr::get(regOffs.getType(), offset.getQuantity()));
241+
242+
resAsInt8P = builder.create<mlir::cir::PtrStrideOp>(
243+
loc, castRegTop.getType(), resAsInt8P, offsetConst);
244+
}
245+
}
246+
247+
auto resAsVoidP = builder.createBitcast(resAsInt8P, regTop.getType());
248+
196249
// On big-endian platforms, the value will be right-aligned in its stack slot.
197250
// and we also need to think about other ABI lowering concerns listed below.
198251
assert(!cir::MissingFeatures::handleBigEndian());
@@ -201,9 +254,6 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
201254
assert(!cir::MissingFeatures::supportTySizeQueryForAArch64());
202255
assert(!cir::MissingFeatures::supportTyAlignQueryForAArch64());
203256

204-
auto resAsInt8P = builder.create<mlir::cir::PtrStrideOp>(
205-
loc, castRegTop.getType(), castRegTop, regOffs);
206-
auto resAsVoidP = builder.createBitcast(resAsInt8P, regTop.getType());
207257
builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{resAsVoidP}, contBlock);
208258

209259
//=======================================
@@ -216,25 +266,57 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
216266
auto ptrDiffTy =
217267
mlir::cir::IntType::get(builder.getContext(), 64, /*signed=*/false);
218268

269+
assert(!cir::MissingFeatures::handleAArch64Indirect());
270+
assert(!cir::MissingFeatures::supportTyAlignQueryForAArch64());
271+
// Again, stack arguments may need realignment. In this case both integer and
272+
// floating-point ones might be affected.
273+
if (!isIndirect && tyAlign.getQuantity() > 8) {
274+
// TODO: this algorithm requres casting from ptr type to int type, then
275+
// back to ptr type thus needs careful handling. NYI now.
276+
llvm_unreachable("alignment greater than 8 NYI");
277+
}
278+
279+
// All stack slots are multiples of 8 bytes.
280+
clang::CharUnits stackSlotSize = clang::CharUnits::fromQuantity(8);
281+
clang::CharUnits stackSize;
282+
if (isIndirect)
283+
stackSize = stackSlotSize;
284+
else
285+
stackSize = tySize.alignTo(stackSlotSize);
286+
219287
// On big-endian platforms, the value will be right-aligned in its stack slot
220288
// Also, the consideration involves type size and alignment, arg indirectness
221289
// which are all ABI defined thus need ABI lowering query system.
222290
// The implementation we have now supports most common cases which assumes
223291
// no indirectness, no alignment greater than 8, and little endian.
224292
assert(!cir::MissingFeatures::handleBigEndian());
225-
assert(!cir::MissingFeatures::handleAArch64Indirect());
226-
assert(!cir::MissingFeatures::supportTyAlignQueryForAArch64());
227293
assert(!cir::MissingFeatures::supportTySizeQueryForAArch64());
228294

229-
auto eight = builder.create<mlir::cir::ConstantOp>(
230-
loc, ptrDiffTy, mlir::cir::IntAttr::get(ptrDiffTy, 8));
295+
auto stackSizeC = builder.create<mlir::cir::ConstantOp>(
296+
loc, ptrDiffTy,
297+
mlir::cir::IntAttr::get(ptrDiffTy, stackSize.getQuantity()));
231298
auto castStack = builder.createBitcast(onStackPtr, i8PtrTy);
232299
// Write the new value of __stack for the next call to va_arg
233300
auto newStackAsi8Ptr = builder.create<mlir::cir::PtrStrideOp>(
234-
loc, castStack.getType(), castStack, eight);
301+
loc, castStack.getType(), castStack, stackSizeC);
235302
auto newStack = builder.createBitcast(newStackAsi8Ptr, onStackPtr.getType());
236303
builder.createStore(loc, newStack, stackP);
237-
builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{onStackPtr}, contBlock);
304+
305+
if (isBigEndian && !isAggregateTypeForABI && tySize < stackSlotSize) {
306+
clang::CharUnits offset = stackSlotSize - tySize;
307+
auto offsetConst = builder.create<mlir::cir::ConstantOp>(
308+
loc, ptrDiffTy,
309+
mlir::cir::IntAttr::get(ptrDiffTy, offset.getQuantity()));
310+
auto offsetStackAsi8Ptr = builder.create<mlir::cir::PtrStrideOp>(
311+
loc, castStack.getType(), castStack, offsetConst);
312+
auto onStackPtrBE =
313+
builder.createBitcast(offsetStackAsi8Ptr, onStackPtr.getType());
314+
builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{onStackPtrBE},
315+
contBlock);
316+
} else {
317+
builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{onStackPtr},
318+
contBlock);
319+
}
238320

239321
// generate additional instructions for end block
240322
builder.setInsertionPoint(op);
@@ -246,6 +328,9 @@ LoweringPrepareAArch64CXXABI::lowerAAPCSVAArg(cir::CIRBaseBuilderTy &builder,
246328
auto res = builder.create<mlir::cir::LoadOp>(loc, castResP);
247329
// there would be another level of ptr dereference if indirect arg passing
248330
assert(!cir::MissingFeatures::handleAArch64Indirect());
331+
if (isIndirect) {
332+
res = builder.create<mlir::cir::LoadOp>(loc, res.getResult());
333+
}
249334
return res.getResult();
250335
}
251336

0 commit comments

Comments
 (0)