Files
llvm/mlir/lib/TableGen/OpClass.cpp
Tres Popp 2d2d696137 [MLIR] Propagate input side effect information
Summary:
Previously operations like std.load created methods for obtaining their
effects but did not inherit from the SideEffect interfaces when their
parameters were decorated with the information. The resulting situation
was that passes had no information on the SideEffects of std.load/store
and had to treat them more cautiously. This adds the inheritance
information when creating the methods.

As a side effect, many tests are modified, as they were using std.load
for testing and this oepration would be folded away as part of pattern
rewriting. Tests are modified to use store or to reutn the result of the
std.load.

Reviewers: mravishankar, antiagainst, nicolasvasilache, herhut, aartbik, ftynse!

Subscribers: mehdi_amini, rriddle, jpienaar, shauheen, antiagainst, nicolasvasilache, csigg, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, bader, grosul1, frgossen, Kayjukh, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D78802
2020-04-27 11:35:52 +02:00

239 lines
7.6 KiB
C++

//===- OpClass.cpp - Helper classes for Op C++ code emission --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "mlir/TableGen/OpClass.h"
#include "mlir/TableGen/Format.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
using namespace mlir;
//===----------------------------------------------------------------------===//
// OpMethodSignature definitions
//===----------------------------------------------------------------------===//
tblgen::OpMethodSignature::OpMethodSignature(StringRef retType, StringRef name,
StringRef params)
: returnType(retType), methodName(name), parameters(params) {}
void tblgen::OpMethodSignature::writeDeclTo(raw_ostream &os) const {
os << returnType << (elideSpaceAfterType(returnType) ? "" : " ") << methodName
<< "(" << parameters << ")";
}
void tblgen::OpMethodSignature::writeDefTo(raw_ostream &os,
StringRef namePrefix) const {
// We need to remove the default values for parameters in method definition.
// TODO(antiagainst): We are using '=' and ',' as delimiters for parameter
// initializers. This is incorrect for initializer list with more than one
// element. Change to a more robust approach.
auto removeParamDefaultValue = [](StringRef params) {
std::string result;
std::pair<StringRef, StringRef> parts;
while (!params.empty()) {
parts = params.split("=");
result.append(result.empty() ? "" : ", ");
result += parts.first;
params = parts.second.split(",").second;
}
return result;
};
os << returnType << (elideSpaceAfterType(returnType) ? "" : " ") << namePrefix
<< (namePrefix.empty() ? "" : "::") << methodName << "("
<< removeParamDefaultValue(parameters) << ")";
}
bool tblgen::OpMethodSignature::elideSpaceAfterType(StringRef type) {
return type.empty() || type.endswith("&") || type.endswith("*");
}
//===----------------------------------------------------------------------===//
// OpMethodBody definitions
//===----------------------------------------------------------------------===//
tblgen::OpMethodBody::OpMethodBody(bool declOnly) : isEffective(!declOnly) {}
tblgen::OpMethodBody &tblgen::OpMethodBody::operator<<(Twine content) {
if (isEffective)
body.append(content.str());
return *this;
}
tblgen::OpMethodBody &tblgen::OpMethodBody::operator<<(int content) {
if (isEffective)
body.append(std::to_string(content));
return *this;
}
tblgen::OpMethodBody &
tblgen::OpMethodBody::operator<<(const FmtObjectBase &content) {
if (isEffective)
body.append(content.str());
return *this;
}
void tblgen::OpMethodBody::writeTo(raw_ostream &os) const {
auto bodyRef = StringRef(body).drop_while([](char c) { return c == '\n'; });
os << bodyRef;
if (bodyRef.empty() || bodyRef.back() != '\n')
os << "\n";
}
//===----------------------------------------------------------------------===//
// OpMethod definitions
//===----------------------------------------------------------------------===//
tblgen::OpMethod::OpMethod(StringRef retType, StringRef name, StringRef params,
OpMethod::Property property, bool declOnly)
: properties(property), isDeclOnly(declOnly),
methodSignature(retType, name, params), methodBody(declOnly) {}
tblgen::OpMethodBody &tblgen::OpMethod::body() { return methodBody; }
bool tblgen::OpMethod::isStatic() const { return properties & MP_Static; }
bool tblgen::OpMethod::isPrivate() const { return properties & MP_Private; }
void tblgen::OpMethod::writeDeclTo(raw_ostream &os) const {
os.indent(2);
if (isStatic())
os << "static ";
methodSignature.writeDeclTo(os);
os << ";";
}
void tblgen::OpMethod::writeDefTo(raw_ostream &os, StringRef namePrefix) const {
if (isDeclOnly)
return;
methodSignature.writeDefTo(os, namePrefix);
os << " {\n";
methodBody.writeTo(os);
os << "}";
}
//===----------------------------------------------------------------------===//
// Class definitions
//===----------------------------------------------------------------------===//
tblgen::Class::Class(StringRef name) : className(name) {}
tblgen::OpMethod &tblgen::Class::newMethod(StringRef retType, StringRef name,
StringRef params,
OpMethod::Property property,
bool declOnly) {
methods.emplace_back(retType, name, params, property, declOnly);
return methods.back();
}
tblgen::OpMethod &tblgen::Class::newConstructor(StringRef params,
bool declOnly) {
return newMethod("", getClassName(), params, OpMethod::MP_Constructor,
declOnly);
}
void tblgen::Class::newField(StringRef type, StringRef name,
StringRef defaultValue) {
std::string varName = formatv("{0} {1}", type, name).str();
std::string field = defaultValue.empty()
? varName
: formatv("{0} = {1}", varName, defaultValue).str();
fields.push_back(std::move(field));
}
void tblgen::Class::writeDeclTo(raw_ostream &os) const {
bool hasPrivateMethod = false;
os << "class " << className << " {\n";
os << "public:\n";
for (const auto &method : methods) {
if (!method.isPrivate()) {
method.writeDeclTo(os);
os << '\n';
} else {
hasPrivateMethod = true;
}
}
os << '\n';
os << "private:\n";
if (hasPrivateMethod) {
for (const auto &method : methods) {
if (method.isPrivate()) {
method.writeDeclTo(os);
os << '\n';
}
}
os << '\n';
}
for (const auto &field : fields)
os.indent(2) << field << ";\n";
os << "};\n";
}
void tblgen::Class::writeDefTo(raw_ostream &os) const {
for (const auto &method : methods) {
method.writeDefTo(os, className);
os << "\n\n";
}
}
//===----------------------------------------------------------------------===//
// OpClass definitions
//===----------------------------------------------------------------------===//
tblgen::OpClass::OpClass(StringRef name, StringRef extraClassDeclaration)
: Class(name), extraClassDeclaration(extraClassDeclaration),
hasOperandAdaptor(true) {}
void tblgen::OpClass::setHasOperandAdaptorClass(bool has) {
hasOperandAdaptor = has;
}
void tblgen::OpClass::addTrait(Twine trait) {
auto traitStr = trait.str();
if (traitsSet.insert(traitStr).second)
traitsVec.push_back(std::move(traitStr));
}
void tblgen::OpClass::writeDeclTo(raw_ostream &os) const {
os << "class " << className << " : public Op<" << className;
for (const auto &trait : traitsVec)
os << ", " << trait;
os << "> {\npublic:\n";
os << " using Op::Op;\n";
if (hasOperandAdaptor)
os << " using OperandAdaptor = " << className << "OperandAdaptor;\n";
bool hasPrivateMethod = false;
for (const auto &method : methods) {
if (!method.isPrivate()) {
method.writeDeclTo(os);
os << "\n";
} else {
hasPrivateMethod = true;
}
}
// TODO: Add line control markers to make errors easier to debug.
if (!extraClassDeclaration.empty())
os << extraClassDeclaration << "\n";
if (hasPrivateMethod) {
os << "\nprivate:\n";
for (const auto &method : methods) {
if (method.isPrivate()) {
method.writeDeclTo(os);
os << "\n";
}
}
}
os << "};\n";
}