[IntegerAttr] Add helpers for working with LLVM's APSInt type.

The FIRRTL dialect in CIRCT uses inherently signful types, and APSInt
is the best way to model that.  Add a couple of helpers that make it
easier to work with an IntegerAttr that carries a sign.

This follows the example of getZExt() and getSExt() which assert when
the underlying type of the attribute is unexpected.  In this case
we assert fail when the underlying type of the attribute is signless.

This is strictly additive, so it is NFC.  It is tested in the CIRCT
repo.

Differential Revision: https://reviews.llvm.org/D102701
This commit is contained in:
Chris Lattner 2021-05-18 10:23:01 -07:00
parent 5781f9a743
commit 855b42ddd0
3 changed files with 20 additions and 0 deletions

View File

@ -466,6 +466,12 @@ def Builtin_IntegerAttr : Builtin_Attr<"Integer"> {
return BoolAttr::get(type.getContext(), value.getBoolValue());
return $_get(type.getContext(), type, value);
}]>,
AttrBuilder<(ins "const APSInt &":$value), [{
auto signedness = value.isSigned() ?
IntegerType::Signed : IntegerType::Unsigned;
auto type = IntegerType::get($_ctxt, value.getBitWidth(), signedness);
return $_get(type.getContext(), type, value);
}]>,
AttrBuilderWithInferredContext<(ins "Type":$type, "int64_t":$value), [{
// `index` has a defined internal storage width.
if (type.isIndex()) {
@ -492,6 +498,10 @@ def Builtin_IntegerAttr : Builtin_Attr<"Integer"> {
/// an unsigned integer.
uint64_t getUInt() const;
/// Return the value as an APSInt which carries the signed from the type of
/// the attribute. This traps on signless integers types!
APSInt getAPSInt() const;
private:
/// Return a boolean attribute. This is a special variant of the `get`
/// method that is used by the MLIRContext to cache the boolean IntegerAttr

View File

@ -64,6 +64,7 @@ template <typename T, typename ResultT> class TypeSwitch;
// Other common classes.
class APInt;
class APSInt;
class APFloat;
template <typename Fn> class function_ref;
template <typename IteratorT> class iterator_range;
@ -118,6 +119,7 @@ using TypeSwitch = llvm::TypeSwitch<T, ResultT>;
// Other common classes.
using llvm::APFloat;
using llvm::APInt;
using llvm::APSInt;
template <typename Fn> using function_ref = llvm::function_ref<Fn>;
using llvm::iterator_range;
using llvm::raw_ostream;

View File

@ -259,6 +259,14 @@ uint64_t IntegerAttr::getUInt() const {
return getValue().getZExtValue();
}
/// Return the value as an APSInt which carries the signed from the type of
/// the attribute. This traps on signless integers types!
APSInt IntegerAttr::getAPSInt() const {
assert(!getType().isSignlessInteger() &&
"Signless integers don't carry a sign for APSInt");
return APSInt(getValue(), getType().isUnsignedInteger());
}
LogicalResult IntegerAttr::verify(function_ref<InFlightDiagnostic()> emitError,
Type type, APInt value) {
if (IntegerType integerType = type.dyn_cast<IntegerType>()) {