brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · e8ed4b3 Raw
205 lines · cpp
1//===- CallInterfaces.cpp - ControlFlow Interfaces ------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Interfaces/CallInterfaces.h"10#include "mlir/IR/Builders.h"11 12using namespace mlir;13 14//===----------------------------------------------------------------------===//15// Argument and result attributes utilities16//===----------------------------------------------------------------------===//17 18static ParseResult19parseTypeAndAttrList(OpAsmParser &parser, SmallVectorImpl<Type> &types,20                     SmallVectorImpl<DictionaryAttr> &attrs) {21  // Parse individual function results.22  return parser.parseCommaSeparatedList([&]() -> ParseResult {23    types.emplace_back();24    attrs.emplace_back();25    NamedAttrList attrList;26    if (parser.parseType(types.back()) ||27        parser.parseOptionalAttrDict(attrList))28      return failure();29    attrs.back() = attrList.getDictionary(parser.getContext());30    return success();31  });32}33 34ParseResult call_interface_impl::parseFunctionResultList(35    OpAsmParser &parser, SmallVectorImpl<Type> &resultTypes,36    SmallVectorImpl<DictionaryAttr> &resultAttrs) {37  if (failed(parser.parseOptionalLParen())) {38    // We already know that there is no `(`, so parse a type.39    // Because there is no `(`, it cannot be a function type.40    Type ty;41    if (parser.parseType(ty))42      return failure();43    resultTypes.push_back(ty);44    resultAttrs.emplace_back();45    return success();46  }47 48  // Special case for an empty set of parens.49  if (succeeded(parser.parseOptionalRParen()))50    return success();51  if (parseTypeAndAttrList(parser, resultTypes, resultAttrs))52    return failure();53  return parser.parseRParen();54}55 56ParseResult call_interface_impl::parseFunctionSignature(57    OpAsmParser &parser, SmallVectorImpl<Type> &argTypes,58    SmallVectorImpl<DictionaryAttr> &argAttrs,59    SmallVectorImpl<Type> &resultTypes,60    SmallVectorImpl<DictionaryAttr> &resultAttrs, bool mustParseEmptyResult) {61  // Parse arguments.62  if (parser.parseLParen())63    return failure();64  if (failed(parser.parseOptionalRParen())) {65    if (parseTypeAndAttrList(parser, argTypes, argAttrs))66      return failure();67    if (parser.parseRParen())68      return failure();69  }70  // Parse results.71  if (succeeded(parser.parseOptionalArrow()))72    return call_interface_impl::parseFunctionResultList(parser, resultTypes,73                                                        resultAttrs);74  if (mustParseEmptyResult)75    return failure();76  return success();77}78 79/// Print a function result list. The provided `attrs` must either be null, or80/// contain a set of DictionaryAttrs of the same arity as `types`.81static void printFunctionResultList(OpAsmPrinter &p, TypeRange types,82                                    ArrayAttr attrs) {83  assert(!types.empty() && "Should not be called for empty result list.");84  assert((!attrs || attrs.size() == types.size()) &&85         "Invalid number of attributes.");86 87  auto &os = p.getStream();88  bool needsParens = types.size() > 1 || llvm::isa<FunctionType>(types[0]) ||89                     (attrs && !llvm::cast<DictionaryAttr>(attrs[0]).empty());90  if (needsParens)91    os << '(';92  llvm::interleaveComma(llvm::seq<size_t>(0, types.size()), os, [&](size_t i) {93    p.printType(types[i]);94    if (attrs)95      p.printOptionalAttrDict(llvm::cast<DictionaryAttr>(attrs[i]).getValue());96  });97  if (needsParens)98    os << ')';99}100 101void call_interface_impl::printFunctionSignature(102    OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic,103    TypeRange resultTypes, ArrayAttr resultAttrs, Region *body,104    bool printEmptyResult) {105  bool isExternal = !body || body->empty();106  if (!isExternal && !isVariadic && !argAttrs && !resultAttrs &&107      printEmptyResult) {108    p.printFunctionalType(argTypes, resultTypes);109    return;110  }111 112  p << '(';113  for (unsigned i = 0, e = argTypes.size(); i < e; ++i) {114    if (i > 0)115      p << ", ";116 117    if (!isExternal) {118      ArrayRef<NamedAttribute> attrs;119      if (argAttrs)120        attrs = llvm::cast<DictionaryAttr>(argAttrs[i]).getValue();121      p.printRegionArgument(body->getArgument(i), attrs);122    } else {123      p.printType(argTypes[i]);124      if (argAttrs)125        p.printOptionalAttrDict(126            llvm::cast<DictionaryAttr>(argAttrs[i]).getValue());127    }128  }129 130  if (isVariadic) {131    if (!argTypes.empty())132      p << ", ";133    p << "...";134  }135 136  p << ')';137 138  if (!resultTypes.empty()) {139    p << " -> ";140    printFunctionResultList(p, resultTypes, resultAttrs);141  } else if (printEmptyResult) {142    p << " -> ()";143  }144}145 146void call_interface_impl::addArgAndResultAttrs(147    Builder &builder, OperationState &result, ArrayRef<DictionaryAttr> argAttrs,148    ArrayRef<DictionaryAttr> resultAttrs, StringAttr argAttrsName,149    StringAttr resAttrsName) {150  auto nonEmptyAttrsFn = [](DictionaryAttr attrs) {151    return attrs && !attrs.empty();152  };153  // Convert the specified array of dictionary attrs (which may have null154  // entries) to an ArrayAttr of dictionaries.155  auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {156    SmallVector<Attribute> attrs;157    for (auto &dict : dictAttrs)158      attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));159    return builder.getArrayAttr(attrs);160  };161 162  // Add the attributes to the operation arguments.163  if (llvm::any_of(argAttrs, nonEmptyAttrsFn))164    result.addAttribute(argAttrsName, getArrayAttr(argAttrs));165 166  // Add the attributes to the operation results.167  if (llvm::any_of(resultAttrs, nonEmptyAttrsFn))168    result.addAttribute(resAttrsName, getArrayAttr(resultAttrs));169}170 171void call_interface_impl::addArgAndResultAttrs(172    Builder &builder, OperationState &result,173    ArrayRef<OpAsmParser::Argument> args, ArrayRef<DictionaryAttr> resultAttrs,174    StringAttr argAttrsName, StringAttr resAttrsName) {175  SmallVector<DictionaryAttr> argAttrs;176  for (const auto &arg : args)177    argAttrs.push_back(arg.attrs);178  addArgAndResultAttrs(builder, result, argAttrs, resultAttrs, argAttrsName,179                       resAttrsName);180}181 182//===----------------------------------------------------------------------===//183// CallOpInterface184//===----------------------------------------------------------------------===//185 186Operation *187call_interface_impl::resolveCallable(CallOpInterface call,188                                     SymbolTableCollection *symbolTable) {189  CallInterfaceCallable callable = call.getCallableForCallee();190  if (auto symbolVal = dyn_cast<Value>(callable))191    return symbolVal.getDefiningOp();192 193  // If the callable isn't a value, lookup the symbol reference.194  auto symbolRef = cast<SymbolRefAttr>(callable);195  if (symbolTable)196    return symbolTable->lookupNearestSymbolFrom(call.getOperation(), symbolRef);197  return SymbolTable::lookupNearestSymbolFrom(call.getOperation(), symbolRef);198}199 200//===----------------------------------------------------------------------===//201// CallInterfaces202//===----------------------------------------------------------------------===//203 204#include "mlir/Interfaces/CallInterfaces.cpp.inc"205