blob: df3d7c8629e7ab5d074a90f452a0de4abd1cd7f5 [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 Lattner4c95a502018-06-23 16:03:42 -070018#include "mlir/IR/CFGFunction.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070019#include "mlir/IR/MLFunction.h"
Chris Lattnera8e47672018-07-25 14:08:16 -070020#include "mlir/IR/Module.h"
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070021#include "mlir/IR/StmtVisitor.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070022#include "mlir/IR/Types.h"
Chris Lattner974a8762018-08-17 16:49:42 -070023#include "llvm/ADT/SmallString.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070024#include "llvm/ADT/StringRef.h"
Chris Lattnerc0c5e0f2018-06-21 09:49:33 -070025using namespace mlir;
26
Chris Lattner4c95a502018-06-23 16:03:42 -070027Function::Function(StringRef name, FunctionType *type, Kind kind)
Chris Lattner974a8762018-08-17 16:49:42 -070028 : kind(kind), name(Identifier::get(name, type->getContext())), type(type) {}
Chris Lattnerc0c5e0f2018-06-21 09:49:33 -070029
Chris Lattnerff0d5902018-07-05 09:12:11 -070030MLIRContext *Function::getContext() const { return getType()->getContext(); }
31
Chris Lattnera8e47672018-07-25 14:08:16 -070032/// Delete this object.
33void Function::destroy() {
34 switch (getKind()) {
35 case Kind::ExtFunc:
36 delete cast<ExtFunction>(this);
37 break;
38 case Kind::MLFunc:
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -070039 cast<MLFunction>(this)->destroy();
Chris Lattnera8e47672018-07-25 14:08:16 -070040 break;
41 case Kind::CFGFunc:
42 delete cast<CFGFunction>(this);
43 break;
44 }
45}
46
47Module *llvm::ilist_traits<Function>::getContainingModule() {
48 size_t Offset(
49 size_t(&((Module *)nullptr->*Module::getSublistAccess(nullptr))));
50 iplist<Function> *Anchor(static_cast<iplist<Function> *>(this));
51 return reinterpret_cast<Module *>(reinterpret_cast<char *>(Anchor) - Offset);
52}
53
54/// This is a trait method invoked when a Function is added to a Module. We
Chris Lattner974a8762018-08-17 16:49:42 -070055/// keep the module pointer and module symbol table up to date.
Chris Lattnera8e47672018-07-25 14:08:16 -070056void llvm::ilist_traits<Function>::addNodeToList(Function *function) {
57 assert(!function->getModule() && "already in a module!");
Chris Lattner974a8762018-08-17 16:49:42 -070058 auto *module = getContainingModule();
59 function->module = module;
60
61 // Add this function to the symbol table of the module, uniquing the name if
62 // a conflict is detected.
63 if (!module->symbolTable.insert({function->name, function}).second) {
64 // If a conflict was detected, then the function will not have been added to
65 // the symbol table. Try suffixes until we get to a unique name that works.
66 SmallString<128> nameBuffer(function->getName().begin(),
67 function->getName().end());
68 unsigned originalLength = nameBuffer.size();
69
70 // Iteratively try suffixes until we find one that isn't used. We use a
71 // module level uniquing counter to avoid N^2 behavior.
72 do {
73 nameBuffer.resize(originalLength);
74 nameBuffer += '_';
75 nameBuffer += std::to_string(module->uniquingCounter++);
76 function->name = Identifier::get(nameBuffer, module->getContext());
77 } while (!module->symbolTable.insert({function->name, function}).second);
78 }
Chris Lattnera8e47672018-07-25 14:08:16 -070079}
80
81/// This is a trait method invoked when a Function is removed from a Module.
82/// We keep the module pointer up to date.
83void llvm::ilist_traits<Function>::removeNodeFromList(Function *function) {
84 assert(function->module && "not already in a module!");
Chris Lattner974a8762018-08-17 16:49:42 -070085
86 // Remove the symbol table entry.
87 function->module->symbolTable.erase(function->getName());
Chris Lattnera8e47672018-07-25 14:08:16 -070088 function->module = nullptr;
89}
90
91/// This is a trait method invoked when an instruction is moved from one block
92/// to another. We keep the block pointer up to date.
93void llvm::ilist_traits<Function>::transferNodesFromList(
94 ilist_traits<Function> &otherList, function_iterator first,
95 function_iterator last) {
96 // If we are transferring functions within the same module, the Module
97 // pointer doesn't need to be updated.
98 Module *curParent = getContainingModule();
99 if (curParent == otherList.getContainingModule())
100 return;
101
Chris Lattner974a8762018-08-17 16:49:42 -0700102 // Update the 'module' member and symbol table records for each function.
103 for (; first != last; ++first) {
104 removeNodeFromList(&*first);
105 addNodeToList(&*first);
106 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700107}
108
109/// Unlink this function from its Module and delete it.
110void Function::eraseFromModule() {
111 assert(getModule() && "Function has no parent");
112 getModule()->getFunctions().erase(this);
113}
114
Chris Lattner4c95a502018-06-23 16:03:42 -0700115//===----------------------------------------------------------------------===//
116// ExtFunction implementation.
117//===----------------------------------------------------------------------===//
Chris Lattnerf7e22732018-06-22 22:03:48 -0700118
Chris Lattner4c95a502018-06-23 16:03:42 -0700119ExtFunction::ExtFunction(StringRef name, FunctionType *type)
120 : Function(name, type, Kind::ExtFunc) {
Chris Lattnere2259872018-06-21 15:22:42 -0700121}
122
Chris Lattner4c95a502018-06-23 16:03:42 -0700123//===----------------------------------------------------------------------===//
124// CFGFunction implementation.
125//===----------------------------------------------------------------------===//
126
127CFGFunction::CFGFunction(StringRef name, FunctionType *type)
128 : Function(name, type, Kind::CFGFunc) {
Chris Lattnere2259872018-06-21 15:22:42 -0700129}
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700130
Chris Lattnera8e47672018-07-25 14:08:16 -0700131CFGFunction::~CFGFunction() {
132 // Instructions may have cyclic references, which need to be dropped before we
133 // can start deleting them.
134 for (auto &bb : *this) {
135 for (auto &inst : bb)
136 inst.dropAllReferences();
James Molloyf8bbadb2018-08-01 11:53:50 -0700137 if (bb.getTerminator())
138 bb.getTerminator()->dropAllReferences();
Chris Lattnera8e47672018-07-25 14:08:16 -0700139 }
140}
141
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700142//===----------------------------------------------------------------------===//
143// MLFunction implementation.
144//===----------------------------------------------------------------------===//
145
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700146/// Create a new MLFunction with the specific fields.
147MLFunction *MLFunction::create(StringRef name, FunctionType *type) {
148 const auto &argTypes = type->getInputs();
149 auto byteSize = totalSizeToAlloc<MLFuncArgument>(argTypes.size());
150 void *rawMem = malloc(byteSize);
151
152 // Initialize the MLFunction part of the function object.
153 auto function = ::new (rawMem) MLFunction(name, type);
154
155 // Initialize the arguments.
156 auto arguments = function->getArgumentsInternal();
157 for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
158 new (&arguments[i]) MLFuncArgument(argTypes[i], function);
159 return function;
160}
161
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700162MLFunction::MLFunction(StringRef name, FunctionType *type)
Tatiana Shpeismanc2d88e92018-07-14 16:44:22 -0700163 : Function(name, type, Kind::MLFunc), StmtBlock(StmtBlockKind::MLFunc) {}
Chris Lattnera8e47672018-07-25 14:08:16 -0700164
165MLFunction::~MLFunction() {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700166 // Explicitly erase statements instead of relying of 'StmtBlock' destructor
167 // since child statements need to be destroyed before function arguments
168 // are destroyed.
169 clear();
170
171 // Explicitly run the destructors for the function arguments.
172 for (auto &arg : getArgumentsInternal())
173 arg.~MLFuncArgument();
174}
175
176void MLFunction::destroy() {
177 this->~MLFunction();
178 free(this);
Chris Lattnera8e47672018-07-25 14:08:16 -0700179}
Uday Bondhugula2ce3b572018-08-13 11:30:36 -0700180
181const OperationStmt *MLFunction::getReturnStmt() const {
182 return cast<OperationStmt>(&back());
183}
184
185OperationStmt *MLFunction::getReturnStmt() {
186 return cast<OperationStmt>(&back());
187}