================
@@ -1008,3 +1009,105 @@ CIRGenFunction::emitNVPTXBuiltinExpr(unsigned 
builtinId, const CallExpr *expr) {
     return std::nullopt;
   }
 }
+
+// vprintf takes two args: A format string, and a pointer to a buffer 
containing
+// the varargs.
+//
+// For example, the call
+//
+//   printf("format string", arg1, arg2, arg3);
+//
+// is converted into something resembling
+//
+//   struct Tmp {
+//     Arg1 a1;
+//     Arg2 a2;
+//     Arg3 a3;
+//   };
+//   char* buf = alloca(sizeof(Tmp));
+//   *(Tmp*)buf = {a1, a2, a3};
+//   vprintf("format string", buf);
+//
+// `buf` is aligned to the max of {alignof(Arg1), ...}. Furthermore, each of
+// the args is itself aligned to its preferred alignment.
+//
+// Note that by the time this function runs, the arguments have already
+// undergone the standard C vararg promotion (short -> int, float -> double
+// etc). In this function we pack the arguments into the buffer described 
above.
+static mlir::Value packArgsIntoNVPTXFormatBuffer(CIRGenFunction &cgf,
+                                                 const CallArgList &args,
+                                                 mlir::Location loc) {
+  const cir::CIRDataLayout dataLayout = cgf.cgm.getDataLayout();
+  CIRGenBuilderTy &builder = cgf.getBuilder();
+
+  if (args.size() <= 1)
+    // If there are no arguments other than the format string,
+    // pass a nullptr to vprintf.
+    return builder.getNullPtr(builder.getVoidPtrTy(), loc);
+
+  llvm::SmallVector<mlir::Type> argTypes;
+  for (const auto &arg : llvm::drop_begin(args))
+    argTypes.push_back(arg.getKnownRValue(cgf, loc).getValue().getType());
+
+  // We can directly store the arguments into a struct, and the alignment
+  // would automatically be correct. That's because vprintf does not
+  // accept aggregates.
+  mlir::Type allocaTy = builder.getAnonRecordTy(argTypes);
+  auto allocaAlign = clang::CharUnits::fromQuantity(
+      dataLayout.getABITypeAlign(allocaTy).value());
+  Address allocaAddr =
+      cgf.createTempAlloca(allocaTy, allocaAlign, loc, "printf_args");
+  mlir::Value alloca = allocaAddr.getPointer();
+
+  for (auto [i, arg] : llvm::enumerate(llvm::drop_begin(args))) {
+    mlir::Value member = builder.createGetMember(
+        loc, cir::PointerType::get(argTypes[i]), alloca, /*name=*/"",
+        /*index=*/i);
+    auto abiAlign = clang::CharUnits::fromQuantity(
+        dataLayout.getABITypeAlign(argTypes[i]).value());
+    cir::StoreOp::create(builder, loc, arg.getRValue(cgf, loc).getValue(),
+                         member, /*is_volatile=*/false,
+                         builder.getAlignmentAttr(abiAlign),
+                         /*sync_scope=*/cir::SyncScopeKindAttr{},
+                         /*mem_order=*/cir::MemOrderAttr{});
+  }
+
+  return builder.createBitcast(alloca, builder.getVoidPtrTy());
+}
+
+mlir::Value
+CIRGenFunction::emitNVPTXDevicePrintfCallExpr(const CallExpr *expr) {
+  assert(cgm.getTriple().isNVPTX());
+  assert(expr->getBuiltinCallee() == Builtin::BIprintf ||
+         expr->getBuiltinCallee() == Builtin::BI__builtin_printf);
+  assert(expr->getNumArgs() >= 1); // printf always has at least one arg.
+  CallArgList args;
+  emitCallArgs(args,
+               expr->getDirectCallee()->getType()->getAs<FunctionProtoType>(),
+               expr->arguments(), expr->getDirectCallee());
+
+  mlir::Location loc = getLoc(expr->getBeginLoc());
+
+  // We don't know how to emit non-scalar varargs.
+  bool hasNonScalar =
+      llvm::any_of(llvm::drop_begin(args), [&](const CallArg &a) {
+        return !a.getRValue(*this, loc).isScalar();
----------------
andykaylor wrote:

```suggestion
        return a.hasLValue || !a.getKnownRValue.isScalar();
```
This was actually quite problematic since it's checking to see if this is a 
scalar value. If it isn't this will generate a copy. I guess that's not 
terrible since we're about to emit an error anyway, but it's bad form.


https://github.com/llvm/llvm-project/pull/196573
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to