MLIR  21.0.0git
PrintCallHelper.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
13 #include "mlir/IR/Builders.h"
14 #include "mlir/IR/BuiltinOps.h"
15 #include "llvm/ADT/ArrayRef.h"
16 
17 using namespace mlir;
18 using 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 is
22 /// returned. Otherwise, a unique and yet unused identifier is computed starting
23 /// from the requested one.
24 static std::string
25 ensureSymbolNameIsUnique(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 
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 = builder.create<LLVM::GlobalOp>(
70  loc, arrayTy, /*constant=*/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  builder.create<LLVM::AddressOfOp>(loc, ptrTy, globalOp.getName());
78  SmallVector<LLVM::GEPArg> indices(1, 0);
79  Value gep =
80  builder.create<LLVM::GEPOp>(loc, ptrTy, arrayTy, msgAddr, indices);
81  FailureOr<LLVM::LLVMFuncOp> printer =
82  LLVM::lookupOrCreatePrintStringFn(builder, moduleOp, runtimeFunctionName);
83  if (failed(printer))
84  return failure();
85  builder.create<LLVM::CallOp>(loc, TypeRange(),
86  SymbolRefAttr::get(printer.value()), gep);
87  return success();
88 }
static std::string ensureSymbolNameIsUnique(ModuleOp moduleOp, StringRef symbolName, SymbolTableCollection *symbolTables=nullptr)
Check if a given symbol name is already in use within the module operation.
MLIRContext * getContext() const
Definition: Builders.h:55
IntegerType getI8Type()
Definition: Builders.cpp:61
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
Conversion from types to the LLVM IR dialect.
Definition: TypeConverter.h:35
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class helps build Operations.
Definition: Builders.h:205
InsertPoint saveInsertionPoint() const
Return a saved insertion point.
Definition: Builders.h:383
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition: Builders.h:429
void restoreInsertionPoint(InsertPoint ip)
Restore the insert point to a previously saved point.
Definition: Builders.h:388
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:455
This class represents a collection of SymbolTables.
Definition: SymbolTable.h:283
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Definition: SymbolTable.h:24
static Operation * lookupSymbolIn(Operation *op, StringAttr symbol)
Returns the operation registered with the given symbol name with the regions of 'symbolTableOp'.
static SmallString< N > generateSymbolName(StringRef name, UniqueChecker uniqueChecker, unsigned &uniquingCounter)
Generate a unique symbol name.
Definition: SymbolTable.h:110
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:37
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintStringFn(OpBuilder &b, Operation *moduleOp, std::optional< StringRef > runtimeFunctionName={}, SymbolTableCollection *symbolTables=nullptr)
Declares a function to print a C-string.
LogicalResult createPrintStrCall(OpBuilder &builder, Location loc, ModuleOp moduleOp, StringRef symbolName, StringRef string, const LLVMTypeConverter &typeConverter, bool addNewline=true, std::optional< StringRef > runtimeFunctionName={}, SymbolTableCollection *symbolTables=nullptr)
Generate IR that prints the given string to stdout.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...