================
@@ -1473,3 +1425,255 @@ void
CIRABIRewriteContext::rewriteFunctionAddress(cir::GetGlobalOp addrOp,
cir::CastKind::bitcast, addrOp.getAddr());
addrOp.getAddr().replaceAllUsesExcept(bitcast.getResult(), bitcast);
}
+
+mlir::LogicalResult
+CIRABIRewriteContext::rewriteVAArg(mlir::Operation *vaArgOp,
+ const ArgClassification &ac,
+ mlir::OpBuilder &opBuilder) {
+ auto op = mlir::cast<cir::VAArgOp>(vaArgOp);
+ CIRBaseBuilderTy builder(opBuilder);
+ mlir::Location loc = op.getLoc();
+ mlir::Type resultTy = op.getType();
+ mlir::Value valist = op.getArgList();
+
+ auto reportNYI = [&](llvm::StringRef what) {
+ op->emitOpError() << "va_arg of " << what
+ << " not yet implemented in CallConvLowering";
+ return mlir::failure();
+ };
+
+ // An ignored type is passed in no register and no stack slot, so the fetch
+ // has nothing to read and must leave the va_list cursor where it found it,
+ // for the fetches that come after this one. The type holds no bytes, so
+ // the value the fetch produces carries no information either.
+ if (ac.kind == ArgKind::Ignore) {
+ builder.setInsertionPoint(op);
+ op.getResult().replaceAllUsesWith(builder.createDummyValue(
+ loc, resultTy,
+ clang::CharUnits::fromQuantity(dl.getTypeABIAlignment(resultTy))));
+ op->erase();
+ return mlir::success();
+ }
+
+ if (ac.kind == ArgKind::Indirect && !ac.byVal)
+ return reportNYI("a non-trivially-copyable type");
+
+ // How many eightbytes of each register class the fetched type occupies.
+ // Zero of both means the type travels in memory and is read straight from
+ // the overflow area.
+ unsigned neededInt = 0, neededSse = 0;
+ // Which coerced-pair element (0 = low eightbyte, 1 = high) is SSE rather
+ // than INTEGER class. Only meaningful when isRegPair is set.
+ std::array<bool, 2> pairIsSse = {false, false};
+ bool isRegPair = false;
+
+ if (ac.kind == ArgKind::Extend) {
+ neededInt = 1;
+ } else if (ac.kind == ArgKind::Direct) {
+ if (mlir::Type coerced = ac.coercedType) {
+ if (auto pairTy = mlir::dyn_cast<cir::RecordType>(coerced)) {
+ assert(pairTy.getNumElements() == 2 &&
+ "a register-class coercion spans at most two eightbytes");
+ for (auto [i, memberTy] : llvm::enumerate(pairTy.getMembers())) {
+ if (isSSERegisterClass(memberTy)) {
+ pairIsSse[i] = true;
+ ++neededSse;
+ } else {
+ ++neededInt;
+ }
+ }
+ isRegPair = true;
+ } else if (isSSERegisterClass(coerced)) {
+ if (fitsOneVectorSlot(coerced, dl))
+ neededSse = 1;
+ } else {
+ neededInt = isWide128BitInt(coerced) ? 2 : 1;
+ }
+ } else if (auto fp = mlir::dyn_cast<cir::FPTypeInterface>(resultTy)) {
+ // An uncoerced scalar float is SSE, unless it is x87 long double,
+ // which the SysV ABI always classifies MEMORY. That is recognized
+ // from the semantics here, because the classification spells a
+ // memory-class scalar the same way it spells a register one.
+ if (&fp.getFloatSemantics() != &llvm::APFloat::x87DoubleExtended())
+ neededSse = 1;
+ } else if (mlir::isa<cir::VectorType>(resultTy)) {
+ if (fitsOneVectorSlot(resultTy, dl))
+ neededSse = 1;
+ } else if (mlir::isa<cir::IntType, cir::PointerType, cir::BoolType>(
+ resultTy)) {
+ neededInt = isWide128BitInt(resultTy) ? 2 : 1;
+ } else {
+ return reportNYI("this type");
+ }
+ } else if (ac.kind != ArgKind::Indirect) {
+ return reportNYI("a type with an argument classification this fetch does "
----------------
adams381 wrote:
"Fetch" was my shorthand for the `va_arg` expansion, which reads badly in a
diagnostic aimed at a user. That message is gone with the arm it reported from.
https://github.com/llvm/llvm-project/pull/222420
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits