Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion xls/dslx/ir_convert/extract_conversion_order.cc
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,10 @@ class InvocationVisitor : public ExprVisitor {
std::optional<ProcId> proc_id;
auto maybe_proc = callee_info->callee->proc();
if (maybe_proc.has_value()) {
XLS_RET_CHECK(proc_id_.has_value()) << "Functions cannot spawn procs.";
if (!proc_id_.has_value()) {
return absl::UnimplementedError(
absl::StrFormat("Functions cannot spawn procs."));
}

// Only count `next` as a new instance, so that `config` and `next` have
// the same ID. This assumes that we call a proc's `config` and `next` in
Expand Down
15 changes: 9 additions & 6 deletions xls/dslx/ir_convert/function_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3333,13 +3333,16 @@ absl::Status FunctionConverter::HandleSpawn(const Spawn* node) {
}
ProcBuilder* builder_ptr =
dynamic_cast<ProcBuilder*>(function_builder_.get());
XLS_RET_CHECK_NE(builder_ptr, nullptr)
<< "Spawn nodes should only be encountered during proc conversion; "
"we seem to be in function conversion.";
if (builder_ptr == nullptr) {
return absl::UnimplementedError(
absl::StrFormat("IrConversionError: %s Functions cannot spawn procs.",
node->span().ToString(file_table())));
}
if (current_fn_tag_ != FunctionTag::kProcConfig) {
return IrConversionErrorStatus(
node->span(), "Procs can only be spawned in a proc `config` method.",
file_table());
return absl::UnimplementedError(absl::StrFormat(
"IrConversionError: %s Procs can only be spawned in a proc `config` "
"method.",
node->span().ToString(file_table())));
}

const Invocation* invocation = node->config();
Expand Down
48 changes: 46 additions & 2 deletions xls/dslx/ir_convert/ir_converter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3420,8 +3420,52 @@ fn main() {
auto import_data = CreateImportDataForTest();
EXPECT_THAT(
ConvertOneFunctionForTest(program, "main", import_data, kNoPosOptions),
StatusIs(absl::StatusCode::kInternal,
HasSubstr("Functions cannot spawn procs")));
StatusIs(absl::StatusCode::kUnimplemented,
HasSubstr("Functions cannot spawn procs.")));
}

TEST_P(IrConverterWithBothTypecheckVersionsTest,
InvalidSpawnProcScopedChannel) {
constexpr std::string_view program = R"(
proc p {
init { () }
config() { () }
next(state: ()) { state }
}

fn main() {
spawn p();
}
)";
auto import_data = CreateImportDataForTest();
EXPECT_THAT(ConvertOneFunctionForTest(program, "main", import_data,
kProcScopedChannelOptions),
StatusIs(absl::StatusCode::kUnimplemented,
HasSubstr("Functions cannot spawn procs.")));
}

TEST_P(IrConverterWithBothTypecheckVersionsTest, InvalidSpawnInNextProcScoped) {
constexpr std::string_view program = R"(
proc p {
init { () }
config() { () }
next(state: ()) { state }
}

proc main {
init { () }
config() { () }
next(state: ()) {
spawn p();
}
}
)";
auto import_data = CreateImportDataForTest();
EXPECT_THAT(ConvertOneFunctionForTest(program, "main", import_data,
kProcScopedChannelOptions),
StatusIs(absl::StatusCode::kUnimplemented,
HasSubstr("Procs can only be spawned in a proc `config` "
"method.")));
}

TEST_P(IrConverterWithBothTypecheckVersionsTest,
Expand Down