================ @@ -0,0 +1,146 @@ +//===- LowerToLLVMOffloadPrintf.cpp - Lower cir.offload.printf ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file lowers cir.offload.printf to the printf runtime interface of each +// device target. The expansions follow the lowerings of the GPU dialect's +// gpu.printf in mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp. +// +//===----------------------------------------------------------------------===// + +#include "LowerToLLVM.h" + +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/IR/BuiltinOps.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "llvm/TargetParser/Triple.h" + +namespace cir { +namespace direct { + +namespace { + +// 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 ABI 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. +mlir::Value +packArgsIntoNVPTXFormatBuffer(cir::OffloadPrintfOp op, mlir::ValueRange args, + mlir::ConversionPatternRewriter &rewriter, + const mlir::DataLayout &dataLayout) { + mlir::Location loc = op.getLoc(); + auto ptrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); + + if (args.empty()) + // If there are no arguments other than the format string, + // pass a nullptr to vprintf. + return mlir::LLVM::ZeroOp::create(rewriter, loc, ptrTy); + + // We can directly store the arguments into a struct, and the alignment + // would automatically be correct. That's because vprintf does not + // accept aggregates. + auto allocaTy = mlir::LLVM::LLVMStructType::getLiteral( + rewriter.getContext(), llvm::to_vector(args.getTypes())); + + // Allocate the buffer in the entry block, so that a printf in a loop does + // not grow the stack on every iteration. + mlir::Value alloca; + { + mlir::OpBuilder::InsertionGuard guard(rewriter); + auto fn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>(); ---------------- steffenlarsen wrote:
Ah, fair point. I wouldn't expect it to move earlier, but for safeties sake I have added the assert. That should catch the case if it ever happens and we can adjust accordingly. https://github.com/llvm/llvm-project/pull/230517 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
