github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/IR/Function.cpp (about) 1 //===- 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 // ============================================================================= 17 18 #include "mlir/IR/Function.h" 19 #include "mlir/IR/BlockAndValueMapping.h" 20 #include "mlir/IR/Builders.h" 21 #include "mlir/IR/Diagnostics.h" 22 #include "mlir/IR/Dialect.h" 23 #include "mlir/IR/MLIRContext.h" 24 #include "mlir/IR/Module.h" 25 #include "mlir/IR/OpImplementation.h" 26 #include "llvm/ADT/MapVector.h" 27 #include "llvm/ADT/SmallString.h" 28 #include "llvm/ADT/Twine.h" 29 30 using namespace mlir; 31 32 //===----------------------------------------------------------------------===// 33 // Function Operation. 34 //===----------------------------------------------------------------------===// 35 36 FuncOp FuncOp::create(Location location, StringRef name, FunctionType type, 37 ArrayRef<NamedAttribute> attrs) { 38 OperationState state(location, "func"); 39 Builder builder(location->getContext()); 40 FuncOp::build(&builder, &state, name, type, attrs); 41 return llvm::cast<FuncOp>(Operation::create(state)); 42 } 43 FuncOp FuncOp::create(Location location, StringRef name, FunctionType type, 44 llvm::iterator_range<dialect_attr_iterator> attrs) { 45 SmallVector<NamedAttribute, 8> attrRef(attrs); 46 return create(location, name, type, llvm::makeArrayRef(attrRef)); 47 } 48 FuncOp FuncOp::create(Location location, StringRef name, FunctionType type, 49 ArrayRef<NamedAttribute> attrs, 50 ArrayRef<NamedAttributeList> argAttrs) { 51 FuncOp func = create(location, name, type, attrs); 52 func.setAllArgAttrs(argAttrs); 53 return func; 54 } 55 56 void FuncOp::build(Builder *builder, OperationState *result, StringRef name, 57 FunctionType type, ArrayRef<NamedAttribute> attrs) { 58 result->addAttribute(SymbolTable::getSymbolAttrName(), 59 builder->getStringAttr(name)); 60 result->addAttribute(getTypeAttrName(), builder->getTypeAttr(type)); 61 result->attributes.append(attrs.begin(), attrs.end()); 62 result->addRegion(); 63 } 64 65 void FuncOp::build(Builder *builder, OperationState *result, StringRef name, 66 FunctionType type, ArrayRef<NamedAttribute> attrs, 67 ArrayRef<NamedAttributeList> argAttrs) { 68 build(builder, result, name, type, attrs); 69 assert(type.getNumInputs() == argAttrs.size()); 70 SmallString<8> argAttrName; 71 for (unsigned i = 0, e = type.getNumInputs(); i != e; ++i) 72 if (auto argDict = argAttrs[i].getDictionary()) 73 result->addAttribute(getArgAttrName(i, argAttrName), argDict); 74 } 75 76 /// Parsing/Printing methods. 77 78 ParseResult FuncOp::parse(OpAsmParser *parser, OperationState *result) { 79 auto buildFuncType = [](Builder &builder, ArrayRef<Type> argTypes, 80 ArrayRef<Type> results, impl::VariadicFlag, 81 std::string &) { 82 return builder.getFunctionType(argTypes, results); 83 }; 84 85 return impl::parseFunctionLikeOp(parser, result, /*allowVariadic=*/false, 86 buildFuncType); 87 } 88 89 void FuncOp::print(OpAsmPrinter *p) { 90 FunctionType fnType = getType(); 91 impl::printFunctionLikeOp(p, *this, fnType.getInputs(), /*isVariadic=*/false, 92 fnType.getResults()); 93 } 94 95 LogicalResult FuncOp::verify() { 96 // If this function is external there is nothing to do. 97 if (isExternal()) 98 return success(); 99 100 // Verify that the argument list of the function and the arg list of the entry 101 // block line up. The trait already verified that the number of arguments is 102 // the same between the signature and the block. 103 auto fnInputTypes = getType().getInputs(); 104 Block &entryBlock = front(); 105 for (unsigned i = 0, e = entryBlock.getNumArguments(); i != e; ++i) 106 if (fnInputTypes[i] != entryBlock.getArgument(i)->getType()) 107 return emitOpError("type of entry block argument #") 108 << i << '(' << entryBlock.getArgument(i)->getType() 109 << ") must match the type of the corresponding argument in " 110 << "function signature(" << fnInputTypes[i] << ')'; 111 112 return success(); 113 } 114 115 /// Add an entry block to an empty function, and set up the block arguments 116 /// to match the signature of the function. 117 Block *FuncOp::addEntryBlock() { 118 assert(empty() && "function already has an entry block"); 119 auto *entry = new Block(); 120 push_back(entry); 121 entry->addArguments(getType().getInputs()); 122 return entry; 123 } 124 125 /// Clone the internal blocks from this function into dest and all attributes 126 /// from this function to dest. 127 void FuncOp::cloneInto(FuncOp dest, BlockAndValueMapping &mapper) { 128 // Add the attributes of this function to dest. 129 llvm::MapVector<Identifier, Attribute> newAttrs; 130 for (auto &attr : dest.getAttrs()) 131 newAttrs.insert(attr); 132 for (auto &attr : getAttrs()) 133 newAttrs.insert(attr); 134 dest.getOperation()->setAttrs( 135 DictionaryAttr::get(newAttrs.takeVector(), getContext())); 136 137 // Clone the body. 138 getBody().cloneInto(&dest.getBody(), mapper); 139 } 140 141 /// Create a deep copy of this function and all of its blocks, remapping 142 /// any operands that use values outside of the function using the map that is 143 /// provided (leaving them alone if no entry is present). Replaces references 144 /// to cloned sub-values with the corresponding value that is copied, and adds 145 /// those mappings to the mapper. 146 FuncOp FuncOp::clone(BlockAndValueMapping &mapper) { 147 FunctionType newType = getType(); 148 149 // If the function has a body, then the user might be deleting arguments to 150 // the function by specifying them in the mapper. If so, we don't add the 151 // argument to the input type vector. 152 bool isExternalFn = isExternal(); 153 if (!isExternalFn) { 154 SmallVector<Type, 4> inputTypes; 155 inputTypes.reserve(newType.getNumInputs()); 156 for (unsigned i = 0, e = getNumArguments(); i != e; ++i) 157 if (!mapper.contains(getArgument(i))) 158 inputTypes.push_back(newType.getInput(i)); 159 newType = FunctionType::get(inputTypes, newType.getResults(), getContext()); 160 } 161 162 // Create the new function. 163 FuncOp newFunc = llvm::cast<FuncOp>(getOperation()->cloneWithoutRegions()); 164 newFunc.setType(newType); 165 166 /// Set the argument attributes for arguments that aren't being replaced. 167 for (unsigned i = 0, e = getNumArguments(), destI = 0; i != e; ++i) 168 if (isExternalFn || !mapper.contains(getArgument(i))) 169 newFunc.setArgAttrs(destI++, getArgAttrs(i)); 170 171 /// Clone the current function into the new one and return it. 172 cloneInto(newFunc, mapper); 173 return newFunc; 174 } 175 FuncOp FuncOp::clone() { 176 BlockAndValueMapping mapper; 177 return clone(mapper); 178 }