89 lines · cpp
1//===- PrintCallHelper.cpp - Helper to emit runtime print calls -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Conversion/LLVMCommon/PrintCallHelper.h"10#include "mlir/Conversion/LLVMCommon/TypeConverter.h"11#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"12#include "mlir/Dialect/LLVMIR/LLVMDialect.h"13#include "mlir/IR/Builders.h"14#include "mlir/IR/BuiltinOps.h"15#include "llvm/ADT/ArrayRef.h"16 17using namespace mlir;18using namespace llvm;19 20/// Check if a given symbol name is already in use within the module operation.21/// If no symbol with such name is present, then the same identifier is22/// returned. Otherwise, a unique and yet unused identifier is computed starting23/// from the requested one.24static std::string25ensureSymbolNameIsUnique(ModuleOp moduleOp, StringRef symbolName,26 SymbolTableCollection *symbolTables = nullptr) {27 if (symbolTables) {28 SymbolTable &symbolTable = symbolTables->getSymbolTable(moduleOp);29 unsigned counter = 0;30 SmallString<128> uniqueName = symbolTable.generateSymbolName<128>(31 symbolName,32 [&](const SmallString<128> &tentativeName) {33 return symbolTable.lookupSymbolIn(moduleOp, tentativeName) != nullptr;34 },35 counter);36 37 return static_cast<std::string>(uniqueName);38 }39 40 static int counter = 0;41 std::string uniqueName = std::string(symbolName);42 while (moduleOp.lookupSymbol(uniqueName)) {43 uniqueName = std::string(symbolName) + "_" + std::to_string(counter++);44 }45 return uniqueName;46}47 48LogicalResult mlir::LLVM::createPrintStrCall(49 OpBuilder &builder, Location loc, ModuleOp moduleOp, StringRef symbolName,50 StringRef string, const LLVMTypeConverter &typeConverter, bool addNewline,51 std::optional<StringRef> runtimeFunctionName,52 SymbolTableCollection *symbolTables) {53 auto ip = builder.saveInsertionPoint();54 builder.setInsertionPointToStart(moduleOp.getBody());55 MLIRContext *ctx = builder.getContext();56 57 // Create a zero-terminated byte representation and allocate global symbol.58 SmallVector<uint8_t> elementVals;59 elementVals.append(string.begin(), string.end());60 if (addNewline)61 elementVals.push_back('\n');62 elementVals.push_back('\0');63 auto dataAttrType = RankedTensorType::get(64 {static_cast<int64_t>(elementVals.size())}, builder.getI8Type());65 auto dataAttr =66 DenseElementsAttr::get(dataAttrType, llvm::ArrayRef(elementVals));67 auto arrayTy =68 LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), elementVals.size());69 auto globalOp = LLVM::GlobalOp::create(70 builder, loc, arrayTy, /*isConstant=*/true, LLVM::Linkage::Private,71 ensureSymbolNameIsUnique(moduleOp, symbolName, symbolTables), dataAttr);72 73 auto ptrTy = LLVM::LLVMPointerType::get(builder.getContext());74 // Emit call to `printStr` in runtime library.75 builder.restoreInsertionPoint(ip);76 auto msgAddr =77 LLVM::AddressOfOp::create(builder, loc, ptrTy, globalOp.getName());78 SmallVector<LLVM::GEPArg> indices(1, 0);79 Value gep =80 LLVM::GEPOp::create(builder, loc, ptrTy, arrayTy, msgAddr, indices);81 FailureOr<LLVM::LLVMFuncOp> printer =82 LLVM::lookupOrCreatePrintStringFn(builder, moduleOp, runtimeFunctionName);83 if (failed(printer))84 return failure();85 LLVM::CallOp::create(builder, loc, TypeRange(),86 SymbolRefAttr::get(printer.value()), gep);87 return success();88}89