xref: /llvm-project/mlir/lib/Dialect/LLVMIR/IR/FunctionCallUtils.cpp (revision e84f6b6a88c1222d512edf0644c8f869dd12b8ef)
1e332c22cSNicolas Vasilache //===- FunctionCallUtils.cpp - Utilities for C function calls -------------===//
2e332c22cSNicolas Vasilache //
3e332c22cSNicolas Vasilache // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e332c22cSNicolas Vasilache // See https://llvm.org/LICENSE.txt for license information.
5e332c22cSNicolas Vasilache // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e332c22cSNicolas Vasilache //
7e332c22cSNicolas Vasilache //===----------------------------------------------------------------------===//
8e332c22cSNicolas Vasilache //
9e332c22cSNicolas Vasilache // This file implements helper functions to call common simple C functions in
10e332c22cSNicolas Vasilache // LLVMIR (e.g. amon others to support printing and debugging).
11e332c22cSNicolas Vasilache //
12e332c22cSNicolas Vasilache //===----------------------------------------------------------------------===//
13e332c22cSNicolas Vasilache 
14e332c22cSNicolas Vasilache #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
15e332c22cSNicolas Vasilache #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
16e332c22cSNicolas Vasilache #include "mlir/IR/Builders.h"
17e332c22cSNicolas Vasilache #include "mlir/IR/OpDefinition.h"
18e332c22cSNicolas Vasilache #include "mlir/Support/LLVM.h"
19e332c22cSNicolas Vasilache 
20e332c22cSNicolas Vasilache using namespace mlir;
21e332c22cSNicolas Vasilache using namespace mlir::LLVM;
22e332c22cSNicolas Vasilache 
23e332c22cSNicolas Vasilache /// Helper functions to lookup or create the declaration for commonly used
24e332c22cSNicolas Vasilache /// external C function calls. The list of functions provided here must be
25e332c22cSNicolas Vasilache /// implemented separately (e.g. as  part of a support runtime library or as
26e332c22cSNicolas Vasilache /// part of the libc).
27e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintI64 = "printI64";
28e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintU64 = "printU64";
29657f60a0SAart Bik static constexpr llvm::StringRef kPrintF16 = "printF16";
30657f60a0SAart Bik static constexpr llvm::StringRef kPrintBF16 = "printBF16";
31e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintF32 = "printF32";
32e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintF64 = "printF64";
333be3883eSBenjamin Maxwell static constexpr llvm::StringRef kPrintString = "printString";
34e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintOpen = "printOpen";
35e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintClose = "printClose";
36e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintComma = "printComma";
37e332c22cSNicolas Vasilache static constexpr llvm::StringRef kPrintNewline = "printNewline";
38d04c2b2fSMehdi Amini static constexpr llvm::StringRef kMalloc = "malloc";
39d04c2b2fSMehdi Amini static constexpr llvm::StringRef kAlignedAlloc = "aligned_alloc";
40d04c2b2fSMehdi Amini static constexpr llvm::StringRef kFree = "free";
4129fbe600SMichele Scuttari static constexpr llvm::StringRef kGenericAlloc = "_mlir_memref_to_llvm_alloc";
4229fbe600SMichele Scuttari static constexpr llvm::StringRef kGenericAlignedAlloc =
4329fbe600SMichele Scuttari     "_mlir_memref_to_llvm_aligned_alloc";
4429fbe600SMichele Scuttari static constexpr llvm::StringRef kGenericFree = "_mlir_memref_to_llvm_free";
45db2de8d7SStephan Herhut static constexpr llvm::StringRef kMemRefCopy = "memrefCopy";
46e332c22cSNicolas Vasilache 
47e332c22cSNicolas Vasilache /// Generic print function lookupOrCreate helper.
48*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
49*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateFn(Operation *moduleOp, StringRef name,
50*e84f6b6aSLuohao Wang                              ArrayRef<Type> paramTypes, Type resultType,
51*e84f6b6aSLuohao Wang                              bool isVarArg, bool isReserved) {
52f543dfd1SChristopher Bate   assert(moduleOp->hasTrait<OpTrait::SymbolTable>() &&
53f543dfd1SChristopher Bate          "expected SymbolTable operation");
54f543dfd1SChristopher Bate   auto func = llvm::dyn_cast_or_null<LLVM::LLVMFuncOp>(
55f543dfd1SChristopher Bate       SymbolTable::lookupSymbolIn(moduleOp, name));
56*e84f6b6aSLuohao Wang   auto funcT = LLVMFunctionType::get(resultType, paramTypes, isVarArg);
57*e84f6b6aSLuohao Wang   // Assert the signature of the found function is same as expected
58*e84f6b6aSLuohao Wang   if (func) {
59*e84f6b6aSLuohao Wang     if (funcT != func.getFunctionType()) {
60*e84f6b6aSLuohao Wang       if (isReserved) {
61*e84f6b6aSLuohao Wang         func.emitError("redefinition of reserved function '")
62*e84f6b6aSLuohao Wang             << name << "' of different type " << func.getFunctionType()
63*e84f6b6aSLuohao Wang             << " is prohibited";
64*e84f6b6aSLuohao Wang       } else {
65*e84f6b6aSLuohao Wang         func.emitError("redefinition of function '")
66*e84f6b6aSLuohao Wang             << name << "' of different type " << funcT << " is prohibited";
67*e84f6b6aSLuohao Wang       }
68*e84f6b6aSLuohao Wang       return failure();
69*e84f6b6aSLuohao Wang     }
70e332c22cSNicolas Vasilache     return func;
71*e84f6b6aSLuohao Wang   }
72f543dfd1SChristopher Bate   OpBuilder b(moduleOp->getRegion(0));
73e332c22cSNicolas Vasilache   return b.create<LLVM::LLVMFuncOp>(
74e332c22cSNicolas Vasilache       moduleOp->getLoc(), name,
75fd85a64fSIngo Müller       LLVM::LLVMFunctionType::get(resultType, paramTypes, isVarArg));
76e332c22cSNicolas Vasilache }
77e332c22cSNicolas Vasilache 
78*e84f6b6aSLuohao Wang static FailureOr<LLVM::LLVMFuncOp>
79*e84f6b6aSLuohao Wang lookupOrCreateReservedFn(Operation *moduleOp, StringRef name,
80*e84f6b6aSLuohao Wang                          ArrayRef<Type> paramTypes, Type resultType) {
81*e84f6b6aSLuohao Wang   return lookupOrCreateFn(moduleOp, name, paramTypes, resultType,
82*e84f6b6aSLuohao Wang                           /*isVarArg=*/false, /*isReserved=*/true);
83*e84f6b6aSLuohao Wang }
84*e84f6b6aSLuohao Wang 
85*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
86*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintI64Fn(Operation *moduleOp) {
87*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
88*e84f6b6aSLuohao Wang       moduleOp, kPrintI64, IntegerType::get(moduleOp->getContext(), 64),
89e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
90e332c22cSNicolas Vasilache }
91e332c22cSNicolas Vasilache 
92*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
93*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintU64Fn(Operation *moduleOp) {
94*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
95*e84f6b6aSLuohao Wang       moduleOp, kPrintU64, IntegerType::get(moduleOp->getContext(), 64),
96e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
97e332c22cSNicolas Vasilache }
98e332c22cSNicolas Vasilache 
99*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
100*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintF16Fn(Operation *moduleOp) {
101*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
102*e84f6b6aSLuohao Wang       moduleOp, kPrintF16,
103657f60a0SAart Bik       IntegerType::get(moduleOp->getContext(), 16), // bits!
104657f60a0SAart Bik       LLVM::LLVMVoidType::get(moduleOp->getContext()));
105657f60a0SAart Bik }
106657f60a0SAart Bik 
107*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
108*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintBF16Fn(Operation *moduleOp) {
109*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
110*e84f6b6aSLuohao Wang       moduleOp, kPrintBF16,
111657f60a0SAart Bik       IntegerType::get(moduleOp->getContext(), 16), // bits!
112657f60a0SAart Bik       LLVM::LLVMVoidType::get(moduleOp->getContext()));
113657f60a0SAart Bik }
114657f60a0SAart Bik 
115*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
116*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintF32Fn(Operation *moduleOp) {
117*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
118*e84f6b6aSLuohao Wang       moduleOp, kPrintF32, Float32Type::get(moduleOp->getContext()),
119e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
120e332c22cSNicolas Vasilache }
121e332c22cSNicolas Vasilache 
122*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
123*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintF64Fn(Operation *moduleOp) {
124*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
125*e84f6b6aSLuohao Wang       moduleOp, kPrintF64, Float64Type::get(moduleOp->getContext()),
126e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
127e332c22cSNicolas Vasilache }
128e332c22cSNicolas Vasilache 
12997a238e8SChristian Ulmann static LLVM::LLVMPointerType getCharPtr(MLIRContext *context) {
13050ea17b8SMarkus Böck   return LLVM::LLVMPointerType::get(context);
13150ea17b8SMarkus Böck }
13250ea17b8SMarkus Böck 
13397a238e8SChristian Ulmann static LLVM::LLVMPointerType getVoidPtr(MLIRContext *context) {
13450ea17b8SMarkus Böck   // A char pointer and void ptr are the same in LLVM IR.
13597a238e8SChristian Ulmann   return getCharPtr(context);
13650ea17b8SMarkus Böck }
13750ea17b8SMarkus Böck 
138*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp> mlir::LLVM::lookupOrCreatePrintStringFn(
139f543dfd1SChristopher Bate     Operation *moduleOp, std::optional<StringRef> runtimeFunctionName) {
140*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
141*e84f6b6aSLuohao Wang       moduleOp, runtimeFunctionName.value_or(kPrintString),
14297a238e8SChristian Ulmann       getCharPtr(moduleOp->getContext()),
143325b58d5SMatthias Springer       LLVM::LLVMVoidType::get(moduleOp->getContext()));
144325b58d5SMatthias Springer }
145325b58d5SMatthias Springer 
146*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
147*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintOpenFn(Operation *moduleOp) {
148*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
149*e84f6b6aSLuohao Wang       moduleOp, kPrintOpen, {},
150e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
151e332c22cSNicolas Vasilache }
152e332c22cSNicolas Vasilache 
153*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
154*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintCloseFn(Operation *moduleOp) {
155*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
156*e84f6b6aSLuohao Wang       moduleOp, kPrintClose, {},
157e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
158e332c22cSNicolas Vasilache }
159e332c22cSNicolas Vasilache 
160*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
161*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintCommaFn(Operation *moduleOp) {
162*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
163*e84f6b6aSLuohao Wang       moduleOp, kPrintComma, {},
164e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
165e332c22cSNicolas Vasilache }
166e332c22cSNicolas Vasilache 
167*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
168*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreatePrintNewlineFn(Operation *moduleOp) {
169*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
170*e84f6b6aSLuohao Wang       moduleOp, kPrintNewline, {},
171e332c22cSNicolas Vasilache       LLVM::LLVMVoidType::get(moduleOp->getContext()));
172e332c22cSNicolas Vasilache }
173e332c22cSNicolas Vasilache 
174*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
175*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateMallocFn(Operation *moduleOp, Type indexType) {
176*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(moduleOp, kMalloc, indexType,
17797a238e8SChristian Ulmann                                   getVoidPtr(moduleOp->getContext()));
178e332c22cSNicolas Vasilache }
179e332c22cSNicolas Vasilache 
180*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
181*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateAlignedAllocFn(Operation *moduleOp, Type indexType) {
182*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(moduleOp, kAlignedAlloc,
18397a238e8SChristian Ulmann                                   {indexType, indexType},
18497a238e8SChristian Ulmann                                   getVoidPtr(moduleOp->getContext()));
185a8601f11SMichele Scuttari }
186a8601f11SMichele Scuttari 
187*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
188*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateFreeFn(Operation *moduleOp) {
189*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
190*e84f6b6aSLuohao Wang       moduleOp, kFree, getVoidPtr(moduleOp->getContext()),
191*e84f6b6aSLuohao Wang       LLVM::LLVMVoidType::get(moduleOp->getContext()));
192*e84f6b6aSLuohao Wang }
193*e84f6b6aSLuohao Wang 
194*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
195*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateGenericAllocFn(Operation *moduleOp, Type indexType) {
196*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(moduleOp, kGenericAlloc, indexType,
197*e84f6b6aSLuohao Wang                                   getVoidPtr(moduleOp->getContext()));
198*e84f6b6aSLuohao Wang }
199*e84f6b6aSLuohao Wang 
200*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
201*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateGenericAlignedAllocFn(Operation *moduleOp,
202*e84f6b6aSLuohao Wang                                                 Type indexType) {
203*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(moduleOp, kGenericAlignedAlloc,
204*e84f6b6aSLuohao Wang                                   {indexType, indexType},
205*e84f6b6aSLuohao Wang                                   getVoidPtr(moduleOp->getContext()));
206*e84f6b6aSLuohao Wang }
207*e84f6b6aSLuohao Wang 
208*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
209*e84f6b6aSLuohao Wang mlir::LLVM::lookupOrCreateGenericFreeFn(Operation *moduleOp) {
210*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
21197a238e8SChristian Ulmann       moduleOp, kGenericFree, getVoidPtr(moduleOp->getContext()),
212a8601f11SMichele Scuttari       LLVM::LLVMVoidType::get(moduleOp->getContext()));
213a8601f11SMichele Scuttari }
214a8601f11SMichele Scuttari 
215*e84f6b6aSLuohao Wang FailureOr<LLVM::LLVMFuncOp>
216f543dfd1SChristopher Bate mlir::LLVM::lookupOrCreateMemRefCopyFn(Operation *moduleOp, Type indexType,
21788d5eba1SStephan Herhut                                        Type unrankedDescriptorType) {
218*e84f6b6aSLuohao Wang   return lookupOrCreateReservedFn(
21988d5eba1SStephan Herhut       moduleOp, kMemRefCopy,
22088d5eba1SStephan Herhut       ArrayRef<Type>{indexType, unrankedDescriptorType, unrankedDescriptorType},
22188d5eba1SStephan Herhut       LLVM::LLVMVoidType::get(moduleOp->getContext()));
22288d5eba1SStephan Herhut }
223