Loading [MathJax]/extensions/tex2jax.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RTGAttributes.cpp
Go to the documentation of this file.
1//===- RTGAttributes.cpp --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "mlir/IR/Builders.h"
12#include "mlir/IR/DialectImplementation.h"
13#include "llvm/ADT/TypeSwitch.h"
14
15using namespace circt;
16using namespace rtg;
17
18//===----------------------------------------------------------------------===//
19// ImmediateAttr
20//===----------------------------------------------------------------------===//
21
22namespace circt {
23namespace rtg {
24namespace detail {
25struct ImmediateAttrStorage : public mlir::AttributeStorage {
26 using KeyTy = APInt;
27 ImmediateAttrStorage(APInt value) : value(std::move(value)) {}
28
29 KeyTy getAsKey() const { return value; }
30
31 // NOTE: the implementation of this operator is the reason we need to define
32 // the storage manually. The auto-generated version would just do the direct
33 // equality check of the APInt, but that asserts the bitwidth of both to be
34 // the same, leading to a crash. This implementation, therefore, checks for
35 // matching bit-width beforehand.
36 bool operator==(const KeyTy &key) const {
37 return (value.getBitWidth() == key.getBitWidth() && value == key);
38 }
39
40 static llvm::hash_code hashKey(const KeyTy &key) {
41 return llvm::hash_value(key);
42 }
43
45 construct(mlir::AttributeStorageAllocator &allocator, KeyTy &&key) {
46 return new (allocator.allocate<ImmediateAttrStorage>())
47 ImmediateAttrStorage(std::move(key));
48 }
49
50 APInt value;
51};
52} // namespace detail
53} // namespace rtg
54} // namespace circt
55
56Type ImmediateAttr::getType() const {
57 return ImmediateType::get(getContext(), getValue().getBitWidth());
58}
59
60APInt ImmediateAttr::getValue() const { return getImpl()->value; }
61
62Attribute ImmediateAttr::parse(AsmParser &odsParser, Type odsType) {
63 llvm::SMLoc loc = odsParser.getCurrentLocation();
64
65 APInt val;
66 uint32_t width; // NOTE: this integer type should match the 'width' parameter
67 // type in immediate type.
68 if (odsParser.parseLess() || odsParser.parseInteger(width) ||
69 odsParser.parseComma() || odsParser.parseInteger(val) ||
70 odsParser.parseGreater())
71 return {};
72
73 // If the attribute type is explicitly given, check that the bit-widths match.
74 if (auto immTy = llvm::dyn_cast_or_null<ImmediateType>(odsType)) {
75 if (immTy.getWidth() != width) {
76 odsParser.emitError(loc) << "explicit immediate type bit-width does not "
77 "match attribute bit-width, "
78 << immTy.getWidth() << " vs " << width;
79 return {};
80 }
81 }
82
83 if (width > val.getBitWidth()) {
84 // sext is always safe here, even for unsigned values, because the
85 // parseOptionalInteger method will return something with a zero in the
86 // top bits if it is a positive number.
87 val = val.sext(width);
88 } else if (width < val.getBitWidth()) {
89 // The parser can return an unnecessarily wide result.
90 // This isn't a problem, but truncating off bits is bad.
91 unsigned neededBits =
92 val.isNegative() ? val.getSignificantBits() : val.getActiveBits();
93 if (width < neededBits) {
94 odsParser.emitError(loc)
95 << "integer value out-of-range for bit-width " << width;
96 return {};
97 }
98 val = val.trunc(width);
99 }
100
101 return ImmediateAttr::get(odsParser.getContext(), val);
102}
103
104void ImmediateAttr::print(AsmPrinter &odsPrinter) const {
105 odsPrinter << "<" << getValue().getBitWidth() << ", " << getValue() << ">";
106}
107
108//===----------------------------------------------------------------------===//
109// TableGen generated logic.
110//===----------------------------------------------------------------------===//
111
112void RTGDialect::registerAttributes() {
113 addAttributes<
114#define GET_ATTRDEF_LIST
115#include "circt/Dialect/RTG/IR/RTGAttributes.cpp.inc"
116 >();
117}
118
119#define GET_ATTRDEF_CLASSES
120#include "circt/Dialect/RTG/IR/RTGAttributes.cpp.inc"
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
Definition HWTypes.cpp:110
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition rtg.py:1
static llvm::hash_code hashKey(const KeyTy &key)
bool operator==(const KeyTy &key) const
static ImmediateAttrStorage * construct(mlir::AttributeStorageAllocator &allocator, KeyTy &&key)