forked from OSchip/llvm-project
[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:
parent
994111238b
commit
18219caeb2
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 << "«unnamed»: ";
|
os << "«unnamed»: ";
|
||||||
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 << "«unnamed»: ";
|
os << "«unnamed»: ";
|
||||||
else
|
else
|
||||||
os << "`" << name << "`: ";
|
os << "`" << name << "`: ";
|
||||||
os << op.getResultType(i).getTableGenDefName();
|
os << op.getResultType(i).getDescription() << "\n";
|
||||||
os << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os << "\n";
|
os << "\n";
|
||||||
|
|
Loading…
Reference in New Issue