CIRCT  20.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::VoidType &type) {
31  return moore::VoidType::get(context.getContext());
32  }
33 
34  Type visit(const slang::ast::ScalarType &type) {
35  return getSimpleBitVectorType(type);
36  }
37 
38  Type visit(const slang::ast::FloatingType &type) {
39  return moore::RealType::get(context.getContext());
40  }
41 
42  Type visit(const slang::ast::PredefinedIntegerType &type) {
43  return getSimpleBitVectorType(type);
44  }
45 
46  Type visit(const slang::ast::PackedArrayType &type) {
47  // Handle simple bit vector types of the form `bit [41:0]`.
48  if (type.elementType.as_if<slang::ast::ScalarType>())
49  return getSimpleBitVectorType(type);
50 
51  // Handle all other packed arrays.
52  auto innerType = type.elementType.visit(*this);
53  if (!innerType)
54  return {};
55  // The Slang frontend guarantees the inner type to be packed.
56  return moore::ArrayType::get(type.range.width(),
57  cast<moore::PackedType>(innerType));
58  }
59 
60  Type visit(const slang::ast::QueueType &type) {
61  auto innerType = type.elementType.visit(*this);
62  if (!innerType)
63  return {};
64  return moore::QueueType::get(cast<moore::UnpackedType>(innerType),
65  type.maxBound);
66  }
67 
68  Type visit(const slang::ast::AssociativeArrayType &type) {
69  auto innerType = type.elementType.visit(*this);
70  if (!innerType)
71  return {};
72  auto indexType = type.indexType->visit(*this);
73  if (!indexType)
74  return {};
75  return moore::AssocArrayType::get(cast<moore::UnpackedType>(innerType),
76  cast<moore::UnpackedType>(indexType));
77  }
78 
79  Type visit(const slang::ast::FixedSizeUnpackedArrayType &type) {
80  auto innerType = type.elementType.visit(*this);
81  if (!innerType)
82  return {};
83  return moore::UnpackedArrayType::get(type.range.width(),
84  cast<moore::UnpackedType>(innerType));
85  }
86 
87  Type visit(const slang::ast::DynamicArrayType &type) {
88  auto innerType = type.elementType.visit(*this);
89  if (!innerType)
90  return {};
92  cast<moore::UnpackedType>(innerType));
93  }
94 
95  // Handle type defs.
96  Type visit(const slang::ast::TypeAliasType &type) {
97  // Simply return the underlying type.
98  return type.targetType.getType().visit(*this);
99  }
100 
101  // Handle enums.
102  Type visit(const slang::ast::EnumType &type) {
103  // Simply return the underlying type.
104  return type.baseType.visit(*this);
105  }
106 
107  // Collect the members in a struct or union.
108  LogicalResult
109  collectMembers(const slang::ast::Scope &structType,
110  SmallVectorImpl<moore::StructLikeMember> &members) {
111  for (auto &field : structType.membersOfType<slang::ast::FieldSymbol>()) {
112  auto name = StringAttr::get(context.getContext(), field.name);
113  auto innerType = context.convertType(*field.getDeclaredType());
114  if (!innerType)
115  return failure();
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::StructLikeMember> members;
124  if (failed(collectMembers(type, members)))
125  return {};
126  return moore::StructType::get(context.getContext(), members);
127  }
128 
129  Type visit(const slang::ast::UnpackedStructType &type) {
130  SmallVector<moore::StructLikeMember> members;
131  if (failed(collectMembers(type, members)))
132  return {};
133  return moore::UnpackedStructType::get(context.getContext(), members);
134  }
135 
136  Type visit(const slang::ast::PackedUnionType &type) {
137  SmallVector<moore::StructLikeMember> members;
138  if (failed(collectMembers(type, members)))
139  return {};
140  return moore::UnionType::get(context.getContext(), members);
141  }
142 
143  Type visit(const slang::ast::UnpackedUnionType &type) {
144  SmallVector<moore::StructLikeMember> members;
145  if (failed(collectMembers(type, members)))
146  return {};
147  return moore::UnpackedUnionType::get(context.getContext(), members);
148  }
149 
150  Type visit(const slang::ast::StringType &type) {
151  return moore::StringType::get(context.getContext());
152  }
153 
154  /// Emit an error for all other types.
155  template <typename T>
156  Type visit(T &&node) {
157  auto d = mlir::emitError(loc, "unsupported type: ")
158  << slang::ast::toString(node.kind);
159  d.attachNote() << node.template as<slang::ast::Type>().toString();
160  return {};
161  }
162  // NOLINTEND(misc-no-recursion)
163 };
164 } // namespace
165 
166 // NOLINTBEGIN(misc-no-recursion)
167 Type Context::convertType(const slang::ast::Type &type, LocationAttr loc) {
168  if (!loc)
169  loc = convertLocation(type.location);
170  return type.visit(TypeVisitor(*this, loc));
171 }
172 
173 Type Context::convertType(const slang::ast::DeclaredType &type) {
174  LocationAttr loc;
175  if (auto *ts = type.getTypeSyntax())
176  loc = convertLocation(ts->sourceRange().start());
177  return convertType(type.getType(), loc);
178 }
179 // NOLINTEND(misc-no-recursion)
const char * toString(Flow flow)
Definition: FIRRTLOps.cpp:197
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
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:47
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:167
MLIRContext * getContext()
Return the MLIR context.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.