@@ -119,12 +119,6 @@ class ConversionOrderVisitor : public AstNodeVisitorWithDefault {
119
119
return DefaultHandler(node);
120
120
}
121
121
122
- absl::Status HandleSlice(const Slice* slice) override {
123
- // Slices get replaced with `StartAndWith` objects in `TypeInfo`, so there
124
- // is no point in trying to compute the type info of the slice itself.
125
- return absl::OkStatus();
126
- }
127
-
128
122
absl::Status HandleInvocation(const Invocation* node) override {
129
123
// Exclude the arguments of invocations, but otherwise do the equivalent of
130
124
// DefaultHandler. We exclude the arguments, because when an argument should
@@ -1264,9 +1258,20 @@ class InferenceTableConverterImpl : public InferenceTableConverter,
1264
1258
// A `Slice` actually has its bounds stored in `TypeInfo` out-of-band from
1265
1259
// the real type info, mirroring the `StartAndWidthExprs` that we store in
1266
1260
// the `InferenceTable`.
1267
- if (std::holds_alternative<Slice*>(index->rhs()) ||
1268
- std::holds_alternative<WidthSlice*>(index->rhs())) {
1269
- XLS_RETURN_IF_ERROR(ConcretizeSlice(parametric_context, index, ti));
1261
+ if (std::holds_alternative<Slice*>(index->rhs())) {
1262
+ std::optional<StartAndWidthExprs> start_and_width_exprs =
1263
+ table_.GetSliceStartAndWidthExprs(ToAstNode(index->rhs()));
1264
+ CHECK(start_and_width_exprs.has_value());
1265
+ StartAndWidth start_and_width;
1266
+ XLS_ASSIGN_OR_RETURN(start_and_width.start,
1267
+ EvaluateU32OrExpr(parametric_context,
1268
+ start_and_width_exprs->start));
1269
+ XLS_ASSIGN_OR_RETURN(start_and_width.width,
1270
+ EvaluateU32OrExpr(parametric_context,
1271
+ start_and_width_exprs->width));
1272
+ ti->AddSliceStartAndWidth(std::get<Slice*>(index->rhs()),
1273
+ GetParametricEnv(parametric_context),
1274
+ start_and_width);
1270
1275
}
1271
1276
}
1272
1277
if (const auto* const_assert = dynamic_cast<const ConstAssert*>(node)) {
@@ -1295,53 +1300,6 @@ class InferenceTableConverterImpl : public InferenceTableConverter,
1295
1300
return absl::OkStatus();
1296
1301
}
1297
1302
1298
- // Adds the concrete start and width value of the slice requested by the given
1299
- // `index` node to the given `TypeInfo`.
1300
- absl::Status ConcretizeSlice(
1301
- std::optional<const ParametricContext*> parametric_context,
1302
- const Index* index, TypeInfo* ti) {
1303
- std::optional<StartAndWidthExprs> start_and_width_exprs =
1304
- table_.GetSliceStartAndWidthExprs(index);
1305
- CHECK(start_and_width_exprs.has_value());
1306
- absl::StatusOr<int32_t> start =
1307
- EvaluateU32OrExpr(parametric_context, start_and_width_exprs->start);
1308
- XLS_ASSIGN_OR_RETURN(
1309
- uint32_t width,
1310
- EvaluateU32OrExpr(parametric_context, start_and_width_exprs->width));
1311
- const Type& array_type = **ti->GetItem(index->lhs());
1312
- int64_t array_size;
1313
- if (array_type.IsArray()) {
1314
- XLS_ASSIGN_OR_RETURN(array_size,
1315
- array_type.AsArray().size().GetAsInt64());
1316
- } else {
1317
- std::optional<BitsLikeProperties> bits_like = GetBitsLike(array_type);
1318
- CHECK(bits_like.has_value());
1319
- XLS_ASSIGN_OR_RETURN(array_size, bits_like->size.GetAsInt64());
1320
- }
1321
-
1322
- // A generic `Slice` must have a constexpr start value. A `WidthSlice` can
1323
- // have a constexpr or dynamic start value. If it's constexpr, we validate
1324
- // it.
1325
- const bool is_generic_slice = std::holds_alternative<Slice*>(index->rhs());
1326
- if (is_generic_slice && !start.ok()) {
1327
- return start.status();
1328
- }
1329
- if (start.ok() && (*start < 0 || *start + width > array_size)) {
1330
- return TypeInferenceErrorStatus(
1331
- index->span(), nullptr,
1332
- absl::StrCat("Slice range out of bounds for array of size ",
1333
- array_size),
1334
- file_table_);
1335
- }
1336
-
1337
- if (is_generic_slice) {
1338
- ti->AddSliceStartAndWidth(std::get<Slice*>(index->rhs()),
1339
- GetParametricEnv(parametric_context),
1340
- StartAndWidth{*start, width});
1341
- }
1342
- return absl::OkStatus();
1343
- }
1344
-
1345
1303
// Used when a `ConstAssert` is concretized, to actually check if the asserted
1346
1304
// expression holds.
1347
1305
absl::Status CheckConstAssert(
@@ -2259,6 +2217,20 @@ class InferenceTableConverterImpl : public InferenceTableConverter,
2259
2217
absl::StatusOr<int64_t> EvaluateU32OrExpr(
2260
2218
std::optional<const ParametricContext*> parametric_context,
2261
2219
std::variant<int64_t, const Expr*> value_or_expr) override {
2220
+ return Evaluate32BitIntOrExpr(parametric_context, value_or_expr,
2221
+ /*is_signed=*/false);
2222
+ }
2223
+
2224
+ absl::StatusOr<int64_t> EvaluateS32OrExpr(
2225
+ std::optional<const ParametricContext*> parametric_context,
2226
+ std::variant<int64_t, const Expr*> value_or_expr) override {
2227
+ return Evaluate32BitIntOrExpr(parametric_context, value_or_expr,
2228
+ /*is_signed=*/true);
2229
+ }
2230
+
2231
+ absl::StatusOr<int64_t> Evaluate32BitIntOrExpr(
2232
+ std::optional<const ParametricContext*> parametric_context,
2233
+ std::variant<int64_t, const Expr*> value_or_expr, bool is_signed) {
2262
2234
if (std::holds_alternative<int64_t>(value_or_expr)) {
2263
2235
return std::get<int64_t>(value_or_expr);
2264
2236
}
@@ -2270,7 +2242,9 @@ class InferenceTableConverterImpl : public InferenceTableConverter,
2270
2242
std::optional<const TypeAnnotation*> type_annotation =
2271
2243
table_.GetTypeAnnotation(expr);
2272
2244
if (!type_annotation.has_value()) {
2273
- type_annotation = CreateU32Annotation(*expr->owner(), expr->span());
2245
+ type_annotation = is_signed
2246
+ ? CreateS32Annotation(*expr->owner(), expr->span())
2247
+ : CreateU32Annotation(*expr->owner(), expr->span());
2274
2248
}
2275
2249
XLS_ASSIGN_OR_RETURN(InterpValue value,
2276
2250
Evaluate(ParametricContextScopedExpr(
0 commit comments