blob: bfcfd6f6dd3e2a63810af0705df490b90b296e58 [file] [log] [blame]
Chris Lattnerc0c5e0f2018-06-21 09:49:33 -07001//===- Function.cpp - MLIR Function Classes -------------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
Chris Lattnerc0c5e0f2018-06-21 09:49:33 -070017
Chris Lattner4613d9e2018-08-19 21:17:22 -070018#include "mlir/IR/Attributes.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070019#include "mlir/IR/CFGFunction.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070020#include "mlir/IR/MLFunction.h"
Chris Lattnera8e47672018-07-25 14:08:16 -070021#include "mlir/IR/Module.h"
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070022#include "mlir/IR/StmtVisitor.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070023#include "mlir/IR/Types.h"
Chris Lattner974a8762018-08-17 16:49:42 -070024#include "llvm/ADT/SmallString.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070025#include "llvm/ADT/StringRef.h"
Chris Lattnerc0c5e0f2018-06-21 09:49:33 -070026using namespace mlir;
27
Chris Lattner4c95a502018-06-23 16:03:42 -070028Function::Function(StringRef name, FunctionType *type, Kind kind)
Chris Lattner974a8762018-08-17 16:49:42 -070029 : kind(kind), name(Identifier::get(name, type->getContext())), type(type) {}
Chris Lattnerc0c5e0f2018-06-21 09:49:33 -070030
Chris Lattner4613d9e2018-08-19 21:17:22 -070031Function::~Function() {
32 // Clean up function attributes referring to this function.
33 FunctionAttr::dropFunctionReference(this);
34}
35
Chris Lattnerff0d5902018-07-05 09:12:11 -070036MLIRContext *Function::getContext() const { return getType()->getContext(); }
37
Chris Lattnera8e47672018-07-25 14:08:16 -070038/// Delete this object.
39void Function::destroy() {
40 switch (getKind()) {
41 case Kind::ExtFunc:
42 delete cast<ExtFunction>(this);
43 break;
44 case Kind::MLFunc:
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -070045 cast<MLFunction>(this)->destroy();
Chris Lattnera8e47672018-07-25 14:08:16 -070046 break;
47 case Kind::CFGFunc:
48 delete cast<CFGFunction>(this);
49 break;
50 }
51}
52
53Module *llvm::ilist_traits<Function>::getContainingModule() {
54 size_t Offset(
55 size_t(&((Module *)nullptr->*Module::getSublistAccess(nullptr))));
56 iplist<Function> *Anchor(static_cast<iplist<Function> *>(this));
57 return reinterpret_cast<Module *>(reinterpret_cast<char *>(Anchor) - Offset);
58}
59
60/// This is a trait method invoked when a Function is added to a Module. We
Chris Lattner974a8762018-08-17 16:49:42 -070061/// keep the module pointer and module symbol table up to date.
Chris Lattnera8e47672018-07-25 14:08:16 -070062void llvm::ilist_traits<Function>::addNodeToList(Function *function) {
63 assert(!function->getModule() && "already in a module!");
Chris Lattner974a8762018-08-17 16:49:42 -070064 auto *module = getContainingModule();
65 function->module = module;
66
67 // Add this function to the symbol table of the module, uniquing the name if
68 // a conflict is detected.
69 if (!module->symbolTable.insert({function->name, function}).second) {
70 // If a conflict was detected, then the function will not have been added to
71 // the symbol table. Try suffixes until we get to a unique name that works.
72 SmallString<128> nameBuffer(function->getName().begin(),
73 function->getName().end());
74 unsigned originalLength = nameBuffer.size();
75
76 // Iteratively try suffixes until we find one that isn't used. We use a
77 // module level uniquing counter to avoid N^2 behavior.
78 do {
79 nameBuffer.resize(originalLength);
80 nameBuffer += '_';
81 nameBuffer += std::to_string(module->uniquingCounter++);
82 function->name = Identifier::get(nameBuffer, module->getContext());
83 } while (!module->symbolTable.insert({function->name, function}).second);
84 }
Chris Lattnera8e47672018-07-25 14:08:16 -070085}
86
87/// This is a trait method invoked when a Function is removed from a Module.
88/// We keep the module pointer up to date.
89void llvm::ilist_traits<Function>::removeNodeFromList(Function *function) {
90 assert(function->module && "not already in a module!");
Chris Lattner974a8762018-08-17 16:49:42 -070091
92 // Remove the symbol table entry.
93 function->module->symbolTable.erase(function->getName());
Chris Lattnera8e47672018-07-25 14:08:16 -070094 function->module = nullptr;
95}
96
97/// This is a trait method invoked when an instruction is moved from one block
98/// to another. We keep the block pointer up to date.
99void llvm::ilist_traits<Function>::transferNodesFromList(
100 ilist_traits<Function> &otherList, function_iterator first,
101 function_iterator last) {
102 // If we are transferring functions within the same module, the Module
103 // pointer doesn't need to be updated.
104 Module *curParent = getContainingModule();
105 if (curParent == otherList.getContainingModule())
106 return;
107
Chris Lattner974a8762018-08-17 16:49:42 -0700108 // Update the 'module' member and symbol table records for each function.
109 for (; first != last; ++first) {
110 removeNodeFromList(&*first);
111 addNodeToList(&*first);
112 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700113}
114
115/// Unlink this function from its Module and delete it.
116void Function::eraseFromModule() {
117 assert(getModule() && "Function has no parent");
118 getModule()->getFunctions().erase(this);
119}
120
Chris Lattner4c95a502018-06-23 16:03:42 -0700121//===----------------------------------------------------------------------===//
122// ExtFunction implementation.
123//===----------------------------------------------------------------------===//
Chris Lattnerf7e22732018-06-22 22:03:48 -0700124
Chris Lattner4c95a502018-06-23 16:03:42 -0700125ExtFunction::ExtFunction(StringRef name, FunctionType *type)
126 : Function(name, type, Kind::ExtFunc) {
Chris Lattnere2259872018-06-21 15:22:42 -0700127}
128
Chris Lattner4c95a502018-06-23 16:03:42 -0700129//===----------------------------------------------------------------------===//
130// CFGFunction implementation.
131//===----------------------------------------------------------------------===//
132
133CFGFunction::CFGFunction(StringRef name, FunctionType *type)
134 : Function(name, type, Kind::CFGFunc) {
Chris Lattnere2259872018-06-21 15:22:42 -0700135}
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700136
Chris Lattnera8e47672018-07-25 14:08:16 -0700137CFGFunction::~CFGFunction() {
138 // Instructions may have cyclic references, which need to be dropped before we
139 // can start deleting them.
140 for (auto &bb : *this) {
141 for (auto &inst : bb)
142 inst.dropAllReferences();
James Molloyf8bbadb2018-08-01 11:53:50 -0700143 if (bb.getTerminator())
144 bb.getTerminator()->dropAllReferences();
Chris Lattnera8e47672018-07-25 14:08:16 -0700145 }
146}
147
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700148//===----------------------------------------------------------------------===//
149// MLFunction implementation.
150//===----------------------------------------------------------------------===//
151
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700152/// Create a new MLFunction with the specific fields.
153MLFunction *MLFunction::create(StringRef name, FunctionType *type) {
154 const auto &argTypes = type->getInputs();
155 auto byteSize = totalSizeToAlloc<MLFuncArgument>(argTypes.size());
156 void *rawMem = malloc(byteSize);
157
158 // Initialize the MLFunction part of the function object.
159 auto function = ::new (rawMem) MLFunction(name, type);
160
161 // Initialize the arguments.
162 auto arguments = function->getArgumentsInternal();
163 for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
164 new (&arguments[i]) MLFuncArgument(argTypes[i], function);
165 return function;
166}
167
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700168MLFunction::MLFunction(StringRef name, FunctionType *type)
Tatiana Shpeismanc2d88e92018-07-14 16:44:22 -0700169 : Function(name, type, Kind::MLFunc), StmtBlock(StmtBlockKind::MLFunc) {}
Chris Lattnera8e47672018-07-25 14:08:16 -0700170
171MLFunction::~MLFunction() {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700172 // Explicitly erase statements instead of relying of 'StmtBlock' destructor
173 // since child statements need to be destroyed before function arguments
174 // are destroyed.
175 clear();
176
177 // Explicitly run the destructors for the function arguments.
178 for (auto &arg : getArgumentsInternal())
179 arg.~MLFuncArgument();
180}
181
182void MLFunction::destroy() {
183 this->~MLFunction();
184 free(this);
Chris Lattnera8e47672018-07-25 14:08:16 -0700185}
Uday Bondhugula2ce3b572018-08-13 11:30:36 -0700186
187const OperationStmt *MLFunction::getReturnStmt() const {
188 return cast<OperationStmt>(&back());
189}
190
191OperationStmt *MLFunction::getReturnStmt() {
192 return cast<OperationStmt>(&back());
193}