From 855b42ddd0117055477546e9cc16667a62ffdedf Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 18 May 2021 10:23:01 -0700 Subject: [PATCH] [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 --- mlir/include/mlir/IR/BuiltinAttributes.td | 10 ++++++++++ mlir/include/mlir/Support/LLVM.h | 2 ++ mlir/lib/IR/BuiltinAttributes.cpp | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td index 05dbc6b..1a5c60a 100644 --- a/mlir/include/mlir/IR/BuiltinAttributes.td +++ b/mlir/include/mlir/IR/BuiltinAttributes.td @@ -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 diff --git a/mlir/include/mlir/Support/LLVM.h b/mlir/include/mlir/Support/LLVM.h index 0683e4d..096cd9d 100644 --- a/mlir/include/mlir/Support/LLVM.h +++ b/mlir/include/mlir/Support/LLVM.h @@ -64,6 +64,7 @@ template class TypeSwitch; // Other common classes. class APInt; +class APSInt; class APFloat; template class function_ref; template class iterator_range; @@ -118,6 +119,7 @@ using TypeSwitch = llvm::TypeSwitch; // Other common classes. using llvm::APFloat; using llvm::APInt; +using llvm::APSInt; template using function_ref = llvm::function_ref; using llvm::iterator_range; using llvm::raw_ostream; diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp index 76ce6ca..b36a244 100644 --- a/mlir/lib/IR/BuiltinAttributes.cpp +++ b/mlir/lib/IR/BuiltinAttributes.cpp @@ -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 emitError, Type type, APInt value) { if (IntegerType integerType = type.dyn_cast()) { -- 2.7.4