CIRCT  19.0.0git
Types.cpp
Go to the documentation of this file.
1 //===- Types.cpp - Slang type conversion ----------------------------------===//
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 
10 #include "slang/syntax/AllSyntax.h"
11 
12 using namespace circt;
13 using namespace ImportVerilog;
14 using moore::Domain;
15 
16 namespace {
17 struct TypeVisitor {
18  Context &context;
19  Location loc;
20  TypeVisitor(Context &context, Location loc) : context(context), loc(loc) {}
21 
22  // Handle simple bit vector types such as `bit`, `int`, or `bit [41:0]`.
23  Type getSimpleBitVectorType(const slang::ast::IntegralType &type) {
24  return moore::IntType::get(context.getContext(), type.bitWidth,
25  type.isFourState ? Domain::FourValued
26  : Domain::TwoValued);
27  }
28 
29  // NOLINTBEGIN(misc-no-recursion)
30  Type visit(const slang::ast::ScalarType &type) {
31  return getSimpleBitVectorType(type);
32  }
33 
34  Type visit(const slang::ast::FloatingType &type) {
35  return moore::RealType::get(context.getContext());
36  }
37 
38  Type visit(const slang::ast::PredefinedIntegerType &type) {
39  return getSimpleBitVectorType(type);
40  }
41 
42  Type visit(const slang::ast::PackedArrayType &type) {
43  // Handle simple bit vector types of the form `bit [41:0]`.
44  if (type.elementType.as_if<slang::ast::ScalarType>())
45  return getSimpleBitVectorType(type);
46 
47  // Handle all other packed arrays.
48  auto innerType = type.elementType.visit(*this);
49  if (!innerType)
50  return {};
51  // The Slang frontend guarantees the inner type to be packed.
52  auto packedInnerType = cast<moore::PackedType>(innerType);
54  packedInnerType, moore::Range(type.range.left, type.range.right));
55  }
56 
57  Type visit(const slang::ast::QueueType &type) {
58  auto innerType = type.elementType.visit(*this);
59  if (!innerType)
60  return {};
61  return moore::UnpackedQueueDim::get(cast<moore::UnpackedType>(innerType),
62  type.maxBound);
63  }
64 
65  Type visit(const slang::ast::AssociativeArrayType &type) {
66  auto innerType = type.elementType.visit(*this);
67  if (!innerType)
68  return {};
69  auto indexType = type.indexType->visit(*this);
70  if (!indexType)
71  return {};
72  return moore::UnpackedAssocDim::get(cast<moore::UnpackedType>(innerType),
73  cast<moore::UnpackedType>(indexType));
74  }
75 
76  Type visit(const slang::ast::FixedSizeUnpackedArrayType &type) {
77  auto innerType = type.elementType.visit(*this);
78  if (!innerType)
79  return {};
81  cast<moore::UnpackedType>(innerType),
82  moore::Range(type.range.left, type.range.right));
83  }
84 
85  Type visit(const slang::ast::DynamicArrayType &type) {
86  auto innerType = type.elementType.visit(*this);
87  if (!innerType)
88  return {};
89  return moore::UnpackedUnsizedDim::get(cast<moore::UnpackedType>(innerType));
90  }
91 
92  // Handle type defs.
93  Type visit(const slang::ast::TypeAliasType &type) {
94  // Simply return the underlying type.
95  return type.targetType.getType().visit(*this);
96  }
97 
98  // Handle enums.
99  Type visit(const slang::ast::EnumType &type) {
100  // Simply return the underlying type.
101  return type.baseType.visit(*this);
102  }
103 
104  // Collect the members in a struct or union.
105  LogicalResult collectMembers(const slang::ast::Scope &structType,
106  SmallVectorImpl<moore::StructMember> &members,
107  bool enforcePacked) {
108  for (auto &field : structType.membersOfType<slang::ast::FieldSymbol>()) {
109  auto name = StringAttr::get(context.getContext(), field.name);
110  auto innerType = context.convertType(*field.getDeclaredType());
111  if (!innerType)
112  return failure();
113  // The Slang frontend guarantees the inner type to be packed if the struct
114  // is packed.
115  assert(!enforcePacked || isa<moore::PackedType>(innerType));
116  members.push_back({name, cast<moore::UnpackedType>(innerType)});
117  }
118  return success();
119  }
120 
121  // Handle packed and unpacked structs.
122  Type visit(const slang::ast::PackedStructType &type) {
123  SmallVector<moore::StructMember> members;
124  if (failed(collectMembers(type, members, true)))
125  return {};
126  return moore::PackedStructType::get(context.getContext(),
127  moore::StructKind::Struct, members);
128  }
129 
130  Type visit(const slang::ast::UnpackedStructType &type) {
131  SmallVector<moore::StructMember> members;
132  if (failed(collectMembers(type, members, false)))
133  return {};
135  moore::StructKind::Struct, members);
136  }
137 
138  /// Emit an error for all other types.
139  template <typename T>
140  Type visit(T &&node) {
141  auto d = mlir::emitError(loc, "unsupported type: ")
142  << slang::ast::toString(node.kind);
143  d.attachNote() << node.template as<slang::ast::Type>().toString();
144  return {};
145  }
146  // NOLINTEND(misc-no-recursion)
147 };
148 } // namespace
149 
150 // NOLINTBEGIN(misc-no-recursion)
151 Type Context::convertType(const slang::ast::Type &type, LocationAttr loc) {
152  if (!loc)
153  loc = convertLocation(type.location);
154  return type.visit(TypeVisitor(*this, loc));
155 }
156 
157 Type Context::convertType(const slang::ast::DeclaredType &type) {
158  LocationAttr loc;
159  if (auto *ts = type.getTypeSyntax())
160  loc = convertLocation(ts->sourceRange().start());
161  return convertType(type.getType(), loc);
162 }
163 // NOLINTEND(misc-no-recursion)
assert(baseType &&"element must be base type")
constexpr const char * toString(Flow flow)
Definition: FIRRTLOps.cpp:169
static PackedRangeDim get(PackedType inner, Range range)
Definition: MooreTypes.cpp:191
static PackedStructType get(MLIRContext *context, StructKind kind, ArrayRef< StructMember > members)
Definition: MooreTypes.cpp:355
static UnpackedAssocDim get(UnpackedType inner, UnpackedType indexType={})
Definition: MooreTypes.cpp:261
static UnpackedQueueDim get(UnpackedType inner, std::optional< unsigned > bound={})
Definition: MooreTypes.cpp:270
static UnpackedRangeDim get(UnpackedType inner, Range range)
Definition: MooreTypes.cpp:255
static UnpackedStructType get(MLIRContext *context, StructKind kind, ArrayRef< StructMember > members)
Definition: MooreTypes.cpp:367
static UnpackedUnsizedDim get(UnpackedType inner)
Definition: MooreTypes.cpp:245
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
mlir::Type innerType(mlir::Type type)
Definition: ESITypes.cpp:184
Domain
The number of values each bit of a type can assume.
Definition: MooreTypes.h:27
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
Definition: Types.cpp:151
MLIRContext * getContext()
Return the MLIR context.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.
The [a:b] part in a vector/array type such as logic [a:b].
Definition: MooreTypes.h:62