forked from OSchip/llvm-project
[TableGen] Support using Variadic<Type> in results
This CL extended TableGen Operator class to provide accessors for information on op results. In OpDefinitionGen, added checks to make sure only the last result can be variadic, and adjusted traits and builders generation to consider variadic results. PiperOrigin-RevId: 234596124
This commit is contained in:
parent
0a4c940c1b
commit
e0fc503896
|
@ -72,6 +72,9 @@ public:
|
|||
// Returns the `index`-th result's name.
|
||||
StringRef getResultName(int index) const;
|
||||
|
||||
// Returns true if this operation has a variadic result.
|
||||
bool hasVariadicResult() const;
|
||||
|
||||
// Op attribute interators.
|
||||
using attribute_iterator = const NamedAttribute *;
|
||||
attribute_iterator attribute_begin() const;
|
||||
|
@ -123,8 +126,8 @@ public:
|
|||
StringRef getSummary() const;
|
||||
|
||||
private:
|
||||
// Populates the operands and attributes.
|
||||
void populateOperandsAndAttributes();
|
||||
// Populates the vectors containing operands, attributes, and results.
|
||||
void populateOpStructure();
|
||||
|
||||
// The name of the op split around '_'.
|
||||
SmallVector<StringRef, 2> splittedDefName;
|
||||
|
@ -135,6 +138,9 @@ private:
|
|||
// The attributes of the op.
|
||||
SmallVector<NamedAttribute, 4> attributes;
|
||||
|
||||
// The results of the op.
|
||||
SmallVector<Value, 4> results;
|
||||
|
||||
// The start of native attributes, which are specified when creating the op
|
||||
// as a part of the op's definition.
|
||||
int nativeAttrStart;
|
||||
|
|
|
@ -35,7 +35,7 @@ using llvm::Record;
|
|||
|
||||
tblgen::Operator::Operator(const llvm::Record &def) : def(def) {
|
||||
SplitString(def.getName(), splittedDefName, "_");
|
||||
populateOperandsAndAttributes();
|
||||
populateOpStructure();
|
||||
}
|
||||
|
||||
const SmallVectorImpl<StringRef> &tblgen::Operator::getSplitDefName() const {
|
||||
|
@ -63,13 +63,15 @@ int tblgen::Operator::getNumResults() const {
|
|||
}
|
||||
|
||||
tblgen::Type tblgen::Operator::getResultType(int index) const {
|
||||
DagInit *results = def.getValueAsDag("results");
|
||||
return Type(cast<DefInit>(results->getArg(index)));
|
||||
return results[index].type;
|
||||
}
|
||||
|
||||
StringRef tblgen::Operator::getResultName(int index) const {
|
||||
DagInit *results = def.getValueAsDag("results");
|
||||
return results->getArgNameStr(index);
|
||||
return results[index].name;
|
||||
}
|
||||
|
||||
bool tblgen::Operator::hasVariadicResult() const {
|
||||
return !results.empty() && results.back().type.isVariadic();
|
||||
}
|
||||
|
||||
int tblgen::Operator::getNumNativeAttributes() const {
|
||||
|
@ -127,7 +129,7 @@ auto tblgen::Operator::getArg(int index) -> Argument {
|
|||
return {&attributes[index - nativeAttrStart]};
|
||||
}
|
||||
|
||||
void tblgen::Operator::populateOperandsAndAttributes() {
|
||||
void tblgen::Operator::populateOpStructure() {
|
||||
auto &recordKeeper = def.getRecords();
|
||||
auto attrClass = recordKeeper.getClass("Attr");
|
||||
auto derivedAttrClass = recordKeeper.getClass("DerivedAttr");
|
||||
|
@ -144,7 +146,7 @@ void tblgen::Operator::populateOperandsAndAttributes() {
|
|||
auto argDefInit = dyn_cast<DefInit>(arg);
|
||||
if (!argDefInit)
|
||||
PrintFatalError(def.getLoc(),
|
||||
Twine("undefined type for argument ") + Twine(i));
|
||||
Twine("undefined type for argument #") + Twine(i));
|
||||
Record *argDef = argDefInit->getDef();
|
||||
if (argDef->isSubClassOf(attrClass))
|
||||
break;
|
||||
|
@ -191,11 +193,36 @@ void tblgen::Operator::populateOperandsAndAttributes() {
|
|||
}
|
||||
}
|
||||
|
||||
// Verify that only the last operand can be variadic.
|
||||
for (int i = 0, e = operands.size() - 1; i < e; ++i) {
|
||||
if (operands[i].type.isVariadic())
|
||||
PrintFatalError(def.getLoc(),
|
||||
"only the last operand allowed to be variadic");
|
||||
}
|
||||
|
||||
auto *resultsDag = def.getValueAsDag("results");
|
||||
auto *outsOp = dyn_cast<DefInit>(resultsDag->getOperator());
|
||||
if (!outsOp || outsOp->getDef()->getName() != "outs") {
|
||||
PrintFatalError(def.getLoc(), "'results' must have 'outs' directive");
|
||||
}
|
||||
|
||||
// Handle results.
|
||||
for (unsigned i = 0, e = resultsDag->getNumArgs(); i < e; ++i) {
|
||||
auto name = resultsDag->getArgNameStr(i);
|
||||
auto *resultDef = dyn_cast<DefInit>(resultsDag->getArg(i));
|
||||
if (!resultDef) {
|
||||
PrintFatalError(def.getLoc(),
|
||||
Twine("undefined type for result #") + Twine(i));
|
||||
}
|
||||
results.push_back({name, Type(resultDef)});
|
||||
}
|
||||
|
||||
// Verify that only the last result can be variadic.
|
||||
for (int i = 0, e = results.size() - 1; i < e; ++i) {
|
||||
if (results[i].type.isVariadic())
|
||||
PrintFatalError(def.getLoc(),
|
||||
"only the last result allowed to be variadic");
|
||||
}
|
||||
}
|
||||
|
||||
ArrayRef<llvm::SMLoc> tblgen::Operator::getLoc() const { return def.getLoc(); }
|
||||
|
|
|
@ -247,7 +247,8 @@ void OpEmitter::emitStandaloneParamBuilder(bool isAllSameType) {
|
|||
// Emit parameters for all return types
|
||||
if (!isAllSameType) {
|
||||
for (unsigned i = 0; i != numResults; ++i)
|
||||
os << ", Type returnType" << i;
|
||||
os << (op.getResultType(i).isVariadic() ? ", ArrayRef<Type> " : ", Type ")
|
||||
<< "returnType" << i;
|
||||
}
|
||||
|
||||
// Emit parameters for all operands
|
||||
|
@ -270,23 +271,36 @@ void OpEmitter::emitStandaloneParamBuilder(bool isAllSameType) {
|
|||
|
||||
// Push all result types to the result
|
||||
if (numResults > 0) {
|
||||
OUT(4) << "result->addTypes({";
|
||||
if (!isAllSameType) {
|
||||
os << "returnType0";
|
||||
for (unsigned i = 1; i != numResults; ++i)
|
||||
os << ", returnType" << i;
|
||||
bool hasVariadicResult = op.hasVariadicResult();
|
||||
int numNonVariadicResults =
|
||||
numResults - static_cast<int>(hasVariadicResult);
|
||||
|
||||
if (numNonVariadicResults > 0) {
|
||||
OUT(4) << "result->addTypes({returnType0";
|
||||
for (int i = 1; i < numNonVariadicResults; ++i) {
|
||||
os << ", resultType" << i;
|
||||
}
|
||||
os << "});\n";
|
||||
}
|
||||
|
||||
if (hasVariadicResult) {
|
||||
OUT(4) << formatv("result->addTypes(returnType{0});\n", numResults - 1);
|
||||
}
|
||||
} else {
|
||||
OUT(4) << "result->addTypes({";
|
||||
auto resultType = formatv("{0}->getType()", getArgumentName(op, 0)).str();
|
||||
os << resultType;
|
||||
for (unsigned i = 1; i != numResults; ++i)
|
||||
os << resultType;
|
||||
os << "});\n\n";
|
||||
}
|
||||
os << "});\n\n";
|
||||
}
|
||||
|
||||
// Push all operands to the result
|
||||
bool hasVariadicOperand = op.hasVariadicOperand();
|
||||
int numNonVariadicOperands = numOperands - int(hasVariadicOperand);
|
||||
int numNonVariadicOperands =
|
||||
numOperands - static_cast<int>(hasVariadicOperand);
|
||||
if (numNonVariadicOperands > 0) {
|
||||
OUT(4) << "result->addOperands({" << getArgumentName(op, 0);
|
||||
for (int i = 1; i < numNonVariadicOperands; ++i) {
|
||||
|
@ -316,6 +330,8 @@ void OpEmitter::emitBuilder() {
|
|||
}
|
||||
|
||||
auto numResults = op.getNumResults();
|
||||
bool hasVariadicResult = op.hasVariadicResult();
|
||||
int numNonVariadicResults = numResults - int(hasVariadicResult);
|
||||
|
||||
auto numOperands = op.getNumOperands();
|
||||
bool hasVariadicOperand = op.hasVariadicOperand();
|
||||
|
@ -345,7 +361,8 @@ void OpEmitter::emitBuilder() {
|
|||
"ArrayRef<NamedAttribute> attributes) {\n";
|
||||
|
||||
// Result types
|
||||
OUT(4) << "assert(resultTypes.size() == " << numResults
|
||||
OUT(4) << "assert(resultTypes.size()" << (hasVariadicResult ? " >= " : " == ")
|
||||
<< numNonVariadicResults
|
||||
<< "u && \"mismatched number of return types\");\n"
|
||||
<< " result->addTypes(resultTypes);\n";
|
||||
|
||||
|
@ -369,7 +386,7 @@ void OpEmitter::emitBuilder() {
|
|||
|
||||
// 3. Deduced result types
|
||||
|
||||
if (op.hasTrait("SameOperandsAndResultType"))
|
||||
if (!op.hasVariadicResult() && op.hasTrait("SameOperandsAndResultType"))
|
||||
emitStandaloneParamBuilder(/*isAllSameType=*/true);
|
||||
}
|
||||
|
||||
|
@ -501,18 +518,27 @@ void OpEmitter::emitVerifier() {
|
|||
|
||||
void OpEmitter::emitTraits() {
|
||||
auto numResults = op.getNumResults();
|
||||
bool hasVariadicResult = op.hasVariadicResult();
|
||||
|
||||
// Add return size trait.
|
||||
switch (numResults) {
|
||||
case 0:
|
||||
os << ", OpTrait::ZeroResult";
|
||||
break;
|
||||
case 1:
|
||||
os << ", OpTrait::OneResult";
|
||||
break;
|
||||
default:
|
||||
os << ", OpTrait::NResults<" << numResults << ">::Impl";
|
||||
break;
|
||||
os << ", OpTrait::";
|
||||
if (hasVariadicResult) {
|
||||
if (numResults == 1)
|
||||
os << "VariadicResults";
|
||||
else
|
||||
os << "AtLeastNResults<" << (numResults - 1) << ">::Impl";
|
||||
} else {
|
||||
switch (numResults) {
|
||||
case 0:
|
||||
os << "ZeroResult";
|
||||
break;
|
||||
case 1:
|
||||
os << "OneResult";
|
||||
break;
|
||||
default:
|
||||
os << "NResults<" << numResults << ">::Impl";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add variadic size trait and normal op traits.
|
||||
|
|
Loading…
Reference in New Issue