[doc] Generate more readable description for operands

This CL mandated TypeConstraint and Type to provide descriptions and fixed
various subclasses and definitions to provide so. The purpose is to enforce
good documentation; using empty string as the default just invites oversight.

PiperOrigin-RevId: 231579629
This commit is contained in:
Lei Zhang 2019-01-30 05:57:39 -08:00 committed by jpienaar
parent 994111238b
commit 18219caeb2
7 changed files with 34 additions and 28 deletions

View File

@ -91,17 +91,17 @@ def IsStaticShapeTensorTypePred :
// A constraint on types. This can be used to check the validity of // A constraint on types. This can be used to check the validity of
// instruction arguments. // instruction arguments.
class TypeConstraint<Pred condition, string descr = ""> { class TypeConstraint<Pred condition, string descr> {
// The predicates that this type satisfies. // The predicates that this type satisfies.
// Format: {0} will be expanded to the type. // Format: {0} will be expanded to the type.
Pred predicate = condition; Pred predicate = condition;
// User-readable description used, e.g., for error reporting. If empty, a // User-readable description used, e.g., for error reporting. If empty,
// generic message will be used instead. // a generic message will be used instead.
string description = descr; string description = descr;
} }
// A type, carries type constraints, but accepts any type by default. // A type, carries type constraints, but accepts any type by default.
class Type<Pred condition = CPred<"true">, string descr = ""> class Type<Pred condition, string descr = "">
: TypeConstraint<condition, descr>; : TypeConstraint<condition, descr>;
// A type that can be constructed using MLIR::Builder. // A type that can be constructed using MLIR::Builder.
@ -117,7 +117,7 @@ class BuildableType<code builder> {
} }
// Integer types. // Integer types.
class IntegerBase<CPred pred, string descr = ?> : Type<pred, descr>; class IntegerBase<CPred pred, string descr> : Type<pred, descr>;
// Any integer type irrespective of its width. // Any integer type irrespective of its width.
def Integer : IntegerBase<CPred<"{0}.isa<IntegerType>()">, "integer">; def Integer : IntegerBase<CPred<"{0}.isa<IntegerType>()">, "integer">;
@ -127,7 +127,8 @@ def Index : IntegerBase<CPred<"{0}.isa<IndexType>()">, "index">;
// Integer type of a specific width. // Integer type of a specific width.
class I<int width> class I<int width>
: IntegerBase<CPred<"{0}.isInteger(" # width # ")">, "i" # width>, : IntegerBase<CPred<"{0}.isInteger(" # width # ")">,
width # "-bit integer">,
BuildableType<"getIntegerType(" # width # ")"> { BuildableType<"getIntegerType(" # width # ")"> {
int bitwidth = width; int bitwidth = width;
} }
@ -135,14 +136,15 @@ def I1 : I<1>;
def I32 : I<32>; def I32 : I<32>;
// Floating point types. // Floating point types.
class FloatBase<CPred pred, string descr = ?> : Type<pred, descr>; class FloatBase<CPred pred, string descr> : Type<pred, descr>;
// Any float type irrespective of its width. // Any float type irrespective of its width.
def Float : FloatBase<CPred<"{0}.isa<FloatType>()">, "floating point">; def Float : FloatBase<CPred<"{0}.isa<FloatType>()">, "floating-point">;
// Float type of a specific width. // Float type of a specific width.
class F<int width> class F<int width>
: FloatBase<CPred<"{0}.isF" # width # "()">, "f" # width>, : FloatBase<CPred<"{0}.isF" # width # "()">,
width # "-bit float">,
BuildableType<"getF" # width # "Type()"> { BuildableType<"getF" # width # "Type()"> {
int bitwidth = width; int bitwidth = width;
} }
@ -156,8 +158,8 @@ class ContainerType<Type etype, Pred containerPred, code elementTypeCall,
// element into the element type checker. // element into the element type checker.
Type<AllOf<[containerPred, Type<AllOf<[containerPred,
SubstLeaves<"{0}", !cast<string>(elementTypeCall), SubstLeaves<"{0}", !cast<string>(elementTypeCall),
etype.predicate>]>, etype.predicate>]>,
descr # "<" # etype.description # ">" > { descr # " of " # etype.description # " values"> {
// The type of elements in the container. // The type of elements in the container.
Type elementType = etype; Type elementType = etype;
@ -199,7 +201,7 @@ def StaticShapeTensor
class TypedTensor<Type t> class TypedTensor<Type t>
: ContainerType<t, Tensor.predicate, : ContainerType<t, Tensor.predicate,
"{0}.cast<TensorType>().getElementType()", "{0}.cast<TensorType>().getElementType()",
"tensor">; "tensor">;
def F32Tensor : TypedTensor<F32>; def F32Tensor : TypedTensor<F32>;
@ -212,7 +214,7 @@ def IntegerLike : TypeConstraint<AnyOf<[Integer.predicate, Index.predicate,
// Type constraint for float-like types: floats, vectors or tensors thereof. // Type constraint for float-like types: floats, vectors or tensors thereof.
def FloatLike : TypeConstraint<AnyOf<[Float.predicate, def FloatLike : TypeConstraint<AnyOf<[Float.predicate,
TypedVector<Float>.predicate, TypedTensor<Float>.predicate]>, TypedVector<Float>.predicate, TypedTensor<Float>.predicate]>,
"float-like">; "floating-point-like">;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Attributes // Attributes

View File

@ -28,7 +28,7 @@
include "mlir/IR/op_base.td" include "mlir/IR/op_base.td"
#endif // OP_BASE #endif // OP_BASE
def AnyType : Type; def AnyType : Type<CPred<"true">, "any type">;
// Base class for standard arithmetic operations. Requires operands and // Base class for standard arithmetic operations. Requires operands and
// results to be of the same type, but does not constrain them to specific // results to be of the same type, but does not constrain them to specific

View File

@ -50,8 +50,8 @@ public:
// be substituted with an expression returning an mlir::Type. // be substituted with an expression returning an mlir::Type.
std::string getConditionTemplate() const; std::string getConditionTemplate() const;
// Returns the user-readable description of the constraint. If the // Returns the user-readable description of the constraint. If the description
// description is not provided, returns an empty string. // is not provided, returns the TableGen def name.
StringRef getDescription() const; StringRef getDescription() const;
protected: protected:

View File

@ -44,12 +44,10 @@ std::string tblgen::TypeConstraint::getConditionTemplate() const {
} }
llvm::StringRef tblgen::TypeConstraint::getDescription() const { llvm::StringRef tblgen::TypeConstraint::getDescription() const {
const static auto fieldName = "description"; auto doc = def.getValueAsString("description");
auto *val = def.getValue(fieldName); if (doc.empty())
if (!val) return def.getName();
return ""; return doc;
return def.getValueAsString(fieldName);
} }
tblgen::TypeConstraint::TypeConstraint(const llvm::DefInit &init) tblgen::TypeConstraint::TypeConstraint(const llvm::DefInit &init)

View File

@ -173,12 +173,19 @@ func @func_with_ops(f32) {
%sf = addf{%a, %a} : f32 // expected-error {{invalid operand}} %sf = addf{%a, %a} : f32 // expected-error {{invalid operand}}
} }
// -----
func @func_with_ops(f32) {
^bb0(%a : f32):
// expected-error@+1 {{'addi' op operand #0 must be integer-like}}
%sf = addi %a, %a : f32
}
// ----- // -----
func @func_with_ops(i32) { func @func_with_ops(i32) {
^bb0(%a : i32): ^bb0(%a : i32):
%sf = addf %a, %a : i32 // expected-error {{'addf' op operand #0 must be float-like}} %sf = addf %a, %a : i32 // expected-error {{'addf' op operand #0 must be floating-point-like}}
} }
// ----- // -----

View File

@ -11,7 +11,7 @@ def Y_Const_Attr {
} }
// Define ops to rewrite. // Define ops to rewrite.
def T1: Type; def T1: Type<CPred<"true">, "T1">;
def X_AddOp : Op<"x.add"> { def X_AddOp : Op<"x.add"> {
let arguments = (ins T1, T1); let arguments = (ins T1, T1);
} }

View File

@ -33,6 +33,7 @@ using namespace llvm;
using namespace mlir; using namespace mlir;
using mlir::tblgen::Operator; using mlir::tblgen::Operator;
using mlir::tblgen::Type;
// Emit the description by aligning the text to the left per line (e.g., // Emit the description by aligning the text to the left per line (e.g.,
// removing the minimum indentation across the block). // removing the minimum indentation across the block).
@ -105,8 +106,7 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
os << "`" << operand.name->getAsUnquotedString() << "`: "; os << "`" << operand.name->getAsUnquotedString() << "`: ";
else else
os << "&laquo;unnamed&raquo;: "; os << "&laquo;unnamed&raquo;: ";
os << operand.defInit->getAsUnquotedString(); os << Type(operand.defInit).getDescription() << "\n";
os << "\n";
} }
// Emit attributes. // Emit attributes.
@ -131,8 +131,7 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
os << "&laquo;unnamed&raquo;: "; os << "&laquo;unnamed&raquo;: ";
else else
os << "`" << name << "`: "; os << "`" << name << "`: ";
os << op.getResultType(i).getTableGenDefName(); os << op.getResultType(i).getDescription() << "\n";
os << "\n";
} }
os << "\n"; os << "\n";