Skip to content

Commit f83ad5d

Browse files
richmckeevercopybara-github
authored andcommitted
Fix parametric ProcDefs in bytecode interpreter.
There are several problems being fixed here, all of which are verified by the added interpreter test case: * Mapping of data by ProcDef* without the effective parametrics. * Lack of knowledge of the effective parametrics in the ProcInitializer. * The ProcInitializer being created based on evaluation of member initializers before their types were determined (wrong ordering in flatten_in_type_order). * Missing storage of TypeReference constexpr values for generics. * Incorrect comparison of TypeReference constants in interp_value.cc * An auxiliary proc map in type_info.cc using unstable pointers to objects in a vector. PiperOrigin-RevId: 930116263
1 parent 4c4a47a commit f83ad5d

11 files changed

Lines changed: 167 additions & 29 deletions

xls/dslx/bytecode/bytecode_interpreter.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ absl::Status BytecodeInterpreter::Run(bool* progress_made) {
357357
const std::vector<Bytecode>& bytecodes = frame->bf()->bytecodes();
358358
const Bytecode& bytecode = bytecodes.at(frame->pc());
359359
VLOG(2) << "Bytecode: " << bytecode.ToString(file_table());
360+
if (proc_id_.has_value()) {
361+
VLOG(2) << "Proc: " << proc_id_->ToString();
362+
}
360363
VLOG(2) << std::hex << "PC: " << frame->pc() << " : "
361364
<< bytecode.ToString(file_table());
362365
VLOG(3) << absl::StreamFormat(" - stack depth %d [%s]", stack_.size(),

xls/dslx/bytecode/proc_hierarchy_interpreter.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ absl::Status ProcHierarchyInterpreter::AddProcDefInstance(
398398
ti->GetCanonicalProcInitializer(external_initializer));
399399
XLS_RETURN_IF_ERROR(AddProcDefInstance(
400400
external_initializer.GetProcInitializerOrDie().proc_def(),
401-
external_initializer, canonical_initializer.constructor_type_info,
401+
external_initializer, canonical_initializer.next_type_info,
402402
canonical_initializer.constructor_env, import_data, options));
403403
}
404404

xls/dslx/bytecode/proc_hierarchy_interpreter_test.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,5 +1125,63 @@ impl CounterTest {
11251125
EXPECT_EQ(result.result(), TestResult::kAllPassed);
11261126
}
11271127

1128+
TEST_F(ProcHierarchyInterpreterTest, ParametricProcDef) {
1129+
constexpr std::string_view kProgram = R"(
1130+
#![feature(explicit_state_access)]
1131+
#![feature(generics)]
1132+
1133+
proc Counter<T: type> {
1134+
ch_out: chan<T> out,
1135+
i: T,
1136+
}
1137+
1138+
impl Counter {
1139+
fn new(ch_out: chan<T> out) -> Self {
1140+
Counter<T> { ch_out: ch_out, i: 0 }
1141+
}
1142+
1143+
fn next(self) {
1144+
let old_value = read(self.i);
1145+
send(token(), self.ch_out, old_value);
1146+
write(self.i, old_value + 1);
1147+
}
1148+
}
1149+
1150+
#[test]
1151+
proc CounterTest {
1152+
terminator: chan<bool> out,
1153+
ch_in0: chan<u32> in,
1154+
ch_in1: chan<s16> in,
1155+
}
1156+
1157+
impl CounterTest {
1158+
fn new(terminator: chan<bool> out) -> Self {
1159+
let (counter_out0, counter_in0) = chan<u32>("counter0");
1160+
let (counter_out1, counter_in1) = chan<s16>("counter1");
1161+
Counter<u32>::new(counter_out0).spawn();
1162+
Counter<s16>::new(counter_out1).spawn();
1163+
CounterTest {
1164+
terminator: terminator,
1165+
ch_in0: counter_in0,
1166+
ch_in1: counter_in1
1167+
}
1168+
}
1169+
1170+
fn next(self) {
1171+
let (_, value0) = recv(token(), self.ch_in0);
1172+
let (_, value1) = recv(token(), self.ch_in1);
1173+
send_if(token(), self.terminator, value0 > 2 && value1 > 2, true);
1174+
}
1175+
})";
1176+
1177+
XLS_ASSERT_OK_AND_ASSIGN(auto temp_file,
1178+
TempFile::CreateWithContent(kProgram, "_test.x"));
1179+
ParseAndTestOptions options;
1180+
XLS_ASSERT_OK_AND_ASSIGN(
1181+
TestResultData result,
1182+
ParseAndTest(kProgram, "test", std::string{temp_file.path()}, options));
1183+
EXPECT_EQ(result.result(), TestResult::kAllPassed);
1184+
}
1185+
11281186
} // namespace
11291187
} // namespace xls::dslx

xls/dslx/interp_value.cc

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ std::string InterpValue::ToStringInternal(bool humanize,
284284
case InterpValueTag::kProcInitializer:
285285
const auto& initializer =
286286
std::get<std::shared_ptr<ProcInitializer>>(payload_);
287+
std::vector<std::string> parametric_strings;
288+
parametric_strings.reserve(initializer->parametrics().size());
289+
for (const InterpValue& parametric : initializer->parametrics()) {
290+
parametric_strings.push_back(parametric.ToString());
291+
}
287292
std::vector<std::string> member_strings;
288293
for (const InterpValue& member : initializer->members()) {
289294
member_strings.push_back(member.ToString());
@@ -292,8 +297,12 @@ std::string InterpValue::ToStringInternal(bool humanize,
292297
member_strings.push_back(absl::Substitute(
293298
"fwd $0: $1", param->identifier(), value.ToString()));
294299
}
295-
return absl::Substitute("$0($1)", initializer->proc_def()->identifier(),
296-
absl::StrJoin(member_strings, ", "));
300+
return absl::Substitute(
301+
"$0$1($2)", initializer->proc_def()->identifier(),
302+
parametric_strings.empty()
303+
? ""
304+
: absl::StrCat("<", absl::StrJoin(parametric_strings, ", "), ">"),
305+
absl::StrJoin(member_strings, ", "));
297306
}
298307
return "<INVALID>";
299308
}
@@ -456,6 +465,13 @@ bool InterpValue::ProcInitializer::Eq(const ProcInitializer& other) const {
456465
if (proc_def_ != other.proc_def_) {
457466
return false;
458467
}
468+
CHECK_EQ(parametrics_.size(), other.parametrics_.size());
469+
for (int i = 0; i < parametrics_.size(); i++) {
470+
if (parametrics_[i] != other.parametrics_[i]) {
471+
return false;
472+
}
473+
}
474+
459475
if (members_.size() != other.members_.size()) {
460476
return false;
461477
}
@@ -473,6 +489,7 @@ bool InterpValue::ProcInitializer::Eq(const ProcInitializer& other) const {
473489
return false;
474490
}
475491
}
492+
476493
return true;
477494
}
478495

@@ -1223,6 +1240,14 @@ bool InterpValue::operator<(const InterpValue& rhs) const {
12231240
rhs_inst.proc_def()->owner()->name();
12241241
}
12251242

1243+
if (inst.parametrics().size() != rhs_inst.parametrics().size()) {
1244+
return inst.parametrics().size() < rhs_inst.parametrics().size();
1245+
}
1246+
for (int i = 0; i < inst.parametrics().size(); i++) {
1247+
if (!inst.parametrics()[i].Eq(rhs_inst.parametrics()[i])) {
1248+
return inst.parametrics()[i] < rhs_inst.parametrics()[i];
1249+
}
1250+
}
12261251
if (inst.members().size() != rhs_inst.members().size()) {
12271252
return inst.members().size() < rhs_inst.members().size();
12281253
}
@@ -1250,6 +1275,13 @@ bool InterpValue::operator<(const InterpValue& rhs) const {
12501275
return false;
12511276
}
12521277

1278+
if (IsTypeReference()) {
1279+
if (!rhs.IsTypeReference()) {
1280+
return false;
1281+
}
1282+
return Lt(rhs).value().IsTrue();
1283+
}
1284+
12531285
if (IsTuple()) {
12541286
if (rhs.IsArray()) {
12551287
return true;

xls/dslx/interp_value.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,28 +165,32 @@ class InterpValue {
165165
public:
166166
ProcInitializer(
167167
const ProcDef* proc_def, const AstNode* definer,
168-
std::vector<InterpValue> members,
168+
std::vector<InterpValue> parametrics, std::vector<InterpValue> members,
169169
std::vector<std::pair<const Param*, InterpValue>> forwarded_values)
170170
: proc_def_(proc_def),
171171
definer_(definer),
172+
parametrics_(std::move(parametrics)),
172173
members_(std::move(members)),
173174
forwarded_values_(std::move(forwarded_values)) {
175+
CHECK_EQ(parametrics_.size(), proc_def->parametric_bindings().size());
174176
InitMemberMap();
175177
}
176178

177179
ProcInitializer(const ProcInitializer& other)
178-
: ProcInitializer(other.proc_def_, other.definer_, other.members_,
179-
std::move(other.forwarded_values_)) {}
180+
: ProcInitializer(other.proc_def_, other.definer_, other.parametrics_,
181+
other.members_, other.forwarded_values_) {}
180182

181183
ProcInitializer(ProcInitializer&& other)
182184
: ProcInitializer(other.proc_def_, other.definer_,
183185
std::move(other.members_),
186+
std::move(other.parametrics_),
184187
std::move(other.forwarded_values_)) {
185188
other.member_map_.clear();
186189
}
187190

188191
ProcInitializer& operator=(const ProcInitializer& other) {
189192
proc_def_ = other.proc_def_;
193+
parametrics_ = other.parametrics_;
190194
members_ = other.members_;
191195
forwarded_values_ = other.forwarded_values_;
192196
definer_ = other.definer_;
@@ -200,6 +204,7 @@ class InterpValue {
200204
}
201205
proc_def_ = other.proc_def_;
202206
members_ = std::move(other.members_);
207+
parametrics_ = std::move(other.parametrics_);
203208
forwarded_values_ = std::move(other.forwarded_values_);
204209
definer_ = other.definer_;
205210
InitMemberMap();
@@ -209,6 +214,7 @@ class InterpValue {
209214

210215
const ProcDef* proc_def() const { return proc_def_; }
211216
const AstNode* definer() const { return definer_; }
217+
const std::vector<InterpValue>& parametrics() const { return parametrics_; }
212218
const std::vector<InterpValue>& members() const { return members_; }
213219
const std::vector<std::pair<const Param*, InterpValue>>& forwarded_values()
214220
const {
@@ -232,6 +238,7 @@ class InterpValue {
232238

233239
const ProcDef* proc_def_;
234240
const AstNode* definer_;
241+
std::vector<InterpValue> parametrics_;
235242
std::vector<InterpValue> members_;
236243
std::vector<std::pair<const Param*, InterpValue>> forwarded_values_;
237244

@@ -298,12 +305,12 @@ class InterpValue {
298305

299306
static InterpValue MakeProcInitializer(
300307
const ProcDef* proc_def, const AstNode* definer,
301-
std::vector<InterpValue> members,
308+
std::vector<InterpValue> parametrics, std::vector<InterpValue> members,
302309
std::vector<std::pair<const Param*, InterpValue>> forwarded_values) {
303-
return InterpValue(
304-
InterpValueTag::kProcInitializer,
305-
std::make_shared<ProcInitializer>(proc_def, definer, std::move(members),
306-
std::move(forwarded_values)));
310+
return InterpValue(InterpValueTag::kProcInitializer,
311+
std::make_shared<ProcInitializer>(
312+
proc_def, definer, std::move(parametrics),
313+
std::move(members), std::move(forwarded_values)));
307314
}
308315

309316
static absl::StatusOr<InterpValue> MakeArray(

xls/dslx/type_system/type_info.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ absl::Status TypeInfo::NoteProcConstructorInvocation(
248248
XLS_RET_CHECK(it != root->decorated_canonical_proc_initializer_.end());
249249
external_to_canonical_proc_initializer_.emplace(
250250
std::move(external_proc_initializer), std::move(canonical_initializer));
251+
251252
return absl::OkStatus();
252253
}
253254

@@ -277,9 +278,11 @@ TypeInfo::GetCanonicalProcInitializer(const InterpValue& external_initializer) {
277278
const auto it =
278279
external_to_canonical_proc_initializer_.find(external_initializer);
279280
XLS_RET_CHECK(it != external_to_canonical_proc_initializer_.end());
281+
TypeInfo* root = GetRoot();
280282
const auto decorated_it =
281-
decorated_canonical_proc_initializer_.find(it->second);
282-
XLS_RET_CHECK(decorated_it != decorated_canonical_proc_initializer_.end());
283+
root->decorated_canonical_proc_initializer_.find(it->second);
284+
XLS_RET_CHECK(decorated_it !=
285+
root->decorated_canonical_proc_initializer_.end());
283286
return *decorated_it->second;
284287
}
285288

xls/dslx/type_system/type_info.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define XLS_DSLX_TYPE_SYSTEM_TYPE_INFO_H_
1919

2020
#include <cstdint>
21+
#include <list>
2122
#include <memory>
2223
#include <optional>
2324
#include <string>
@@ -609,7 +610,7 @@ class TypeInfo {
609610
absl::flat_hash_map<const Proc*, std::vector<SpawnData>> spawns_;
610611

611612
// Initializers for each callee proc.
612-
absl::node_hash_map<const ProcDef*, std::vector<ProcInitializerWithTypeInfo>>
613+
absl::node_hash_map<const ProcDef*, std::list<ProcInitializerWithTypeInfo>>
613614
proc_def_initializers_by_callee_proc_;
614615

615616
// The same objects in `proc_def_initializers_by_callee_proc`, but with the

xls/dslx/type_system_v2/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ cc_library(
252252
"@com_google_absl//absl/functional:function_ref",
253253
"@com_google_absl//absl/log",
254254
"@com_google_absl//absl/log:check",
255+
"@com_google_absl//absl/log:vlog_is_on",
255256
"@com_google_absl//absl/memory",
256257
"@com_google_absl//absl/status",
257258
"@com_google_absl//absl/status:statusor",

xls/dslx/type_system_v2/constant_collector.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ class Visitor : public AstNodeVisitorWithDefault {
757757
invocation, table_.GetParametricEnv(parametric_context_),
758758
InterpValue::MakeProcInitializer(
759759
internal_initializer.proc_def(), internal_initializer.definer(),
760+
internal_initializer.parametrics(),
760761
std::move(external_instance_args),
761762
std::move(external_instance_forwarded_values))));
762763
return absl::OkStatus();
@@ -931,9 +932,18 @@ class Visitor : public AstNodeVisitorWithDefault {
931932
}
932933
}
933934

935+
std::vector<InterpValue> parametrics;
936+
parametrics.reserve(type.struct_def_base().parametric_bindings().size());
937+
for (const ParametricBinding* binding :
938+
type.struct_def_base().parametric_bindings()) {
939+
XLS_ASSIGN_OR_RETURN(InterpValue value,
940+
ti_->GetConstExpr(binding->name_def()));
941+
parametrics.push_back(value);
942+
}
943+
934944
auto inst = InterpValue::MakeProcInitializer(
935945
&absl::down_cast<const ProcDef&>(type.struct_def_base()), node,
936-
member_values, std::move(forwarded_values));
946+
parametrics, member_values, std::move(forwarded_values));
937947

938948
ti_->NoteCanonicalProcInitializer(
939949
node, table_.GetParametricEnv(parametric_context_), inst);

xls/dslx/type_system_v2/flatten_in_type_order.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ class Flattener : public AstNodeVisitorWithDefault {
7676
}
7777

7878
absl::Status HandleStructInstance(const StructInstance* node) override {
79-
nodes_.push_back(node);
8079
XLS_RETURN_IF_ERROR(node->struct_ref()->Accept(this));
8180
for (const auto& [_, member] : node->GetUnorderedMembers()) {
8281
XLS_RETURN_IF_ERROR(member->Accept(this));
8382
}
83+
nodes_.push_back(node);
8484
return absl::OkStatus();
8585
}
8686

0 commit comments

Comments
 (0)