16struct InstanceTypeTree {
17 explicit InstanceTypeTree(
const ClassType* type)
24 const ClassType* type;
25 std::vector<std::unique_ptr<InstanceTypeTree>>
children;
35std::unique_ptr<InstanceTypeTree> BuildInstanceTypeTree() {
38 std::unordered_map<const ClassType*, InstanceTypeTree*> map_by_type;
39 std::vector<std::unique_ptr<InstanceTypeTree>> unparented_types;
41 if (
const TypeAlias* alias = TypeAlias::DynamicCast(p.get())) {
42 const Type* type = alias->type();
43 const ClassType* class_type = ClassType::DynamicCast(type);
44 if (class_type ==
nullptr) {
47 auto& map_slot = map_by_type[class_type];
48 if (map_slot !=
nullptr) {
51 std::unique_ptr<InstanceTypeTree> type_tree =
52 std::make_unique<InstanceTypeTree>(class_type);
53 map_slot = type_tree.get();
54 unparented_types.push_back(std::move(type_tree));
59 std::unique_ptr<InstanceTypeTree> root;
60 for (
auto& type_tree : unparented_types) {
61 const ClassType* parent = type_tree->type->GetSuperClass();
62 if (parent ==
nullptr) {
64 Error(
"Expected only one root class type. Found: ", root->type->name(),
65 " and ", type_tree->type->name())
66 .
Position(type_tree->type->GetPosition());
67 root = std::move(type_tree);
69 map_by_type[parent]->children.push_back(std::move(type_tree));
76void PropagateInstanceTypeConstraints(InstanceTypeTree* root) {
77 for (
auto& child : root->children) {
78 PropagateInstanceTypeConstraints(child.get());
79 if (child->start < root->start) root->start = child->start;
80 if (child->end > root->end) root->end = child->end;
81 root->num_values += child->num_values;
83 const InstanceTypeConstraints& constraints =
84 root->type->GetInstanceTypeConstraints();
85 if (!root->type->IsAbstract() && !root->type->HasSameInstanceTypeAsParent()) {
86 root->num_own_values = 1;
88 root->num_values += root->num_own_values;
89 if (constraints.num_flags_bits != -1) {
91 root->children.clear();
92 root->num_values = 1 << constraints.num_flags_bits;
93 root->num_own_values = root->num_values;
95 root->end = root->num_values - 1;
97 if (constraints.value != -1) {
98 if (root->num_own_values != 1) {
99 Error(
"Instance type value requested for abstract class ",
101 .
Position(root->type->GetPosition());
103 root->value = constraints.value;
104 if (constraints.value < root->start) root->start = constraints.value;
105 if (constraints.value > root->end) root->end = constraints.value;
111int SelectOwnValues(InstanceTypeTree* root,
int start_value) {
112 if (root->value == -1) {
113 root->value = start_value;
114 }
else if (root->value < start_value) {
115 Error(
"Failed to assign instance type ", root->value,
" to ",
117 .
Position(root->type->GetPosition());
119 return root->value + root->num_own_values;
125struct CompareUnconstrainedTypes {
126 constexpr bool operator()(
const InstanceTypeTree* a,
127 const InstanceTypeTree* b)
const {
128 return (a->num_values > b->num_values)
130 : (a->num_values < b->num_values)
141int SolveInstanceTypeConstraints(
142 std::unique_ptr<InstanceTypeTree> root,
int start_value,
143 std::vector<std::unique_ptr<InstanceTypeTree>>*
destination) {
144 if (root->start < start_value) {
145 Error(
"Failed to assign instance type ", root->start,
" to ",
147 .
Position(root->type->GetPosition());
155 std::unique_ptr<InstanceTypeTree> lowest_child;
156 std::unique_ptr<InstanceTypeTree> highest_child;
157 std::multimap<int, std::unique_ptr<InstanceTypeTree>>
158 constrained_children_by_start;
160 std::map<InstanceTypeTree*, std::unique_ptr<InstanceTypeTree>,
161 CompareUnconstrainedTypes>
162 unconstrained_children_by_size;
163 for (
auto& child : root->children) {
164 if (child->type->IsHighestInstanceTypeWithinParent()) {
166 Error(
"Two classes requested to be the highest instance type: ",
167 highest_child->type->name(),
" and ", child->type->name(),
168 " within range for parent class ", root->type->name())
169 .
Position(child->type->GetPosition());
171 if (child->type->IsLowestInstanceTypeWithinParent()) {
173 "Class requested to be both highest and lowest instance type "
174 "within its parent range: ",
176 .
Position(child->type->GetPosition());
178 highest_child = std::move(child);
179 }
else if (child->type->IsLowestInstanceTypeWithinParent()) {
181 Error(
"Two classes requested to be the lowest instance type: ",
182 lowest_child->type->name(),
" and ", child->type->name(),
183 " within range for parent class ", root->type->name())
184 .
Position(child->type->GetPosition());
186 lowest_child = std::move(child);
187 }
else if (child->start > child->end) {
188 unconstrained_children_by_size.insert(
189 std::make_pair(child.get(), std::move(child)));
191 constrained_children_by_start.insert(
192 std::make_pair(child->start, std::move(child)));
195 root->children.clear();
197 bool own_type_pending = root->num_own_values > 0;
200 if (lowest_child !=
nullptr) {
201 start_value = SolveInstanceTypeConstraints(std::move(lowest_child),
202 start_value, &root->children);
204 for (
auto& constrained_child_pair : constrained_children_by_start) {
206 std::unique_ptr<InstanceTypeTree> constrained_child =
207 std::move(constrained_child_pair.second);
210 if (own_type_pending) {
211 if ((root->value != -1 && root->value < constrained_child->start) ||
212 (root->value == -1 &&
213 start_value + root->num_own_values <= constrained_child->start)) {
214 start_value = SelectOwnValues(root.get(), start_value);
215 own_type_pending =
false;
223 for (
auto it = unconstrained_children_by_size.begin();
224 it != unconstrained_children_by_size.end();) {
225 if (it->second->num_values + start_value <= constrained_child->
start) {
226 start_value = SolveInstanceTypeConstraints(
227 std::move(it->second), start_value, &root->children);
228 it = unconstrained_children_by_size.erase(it);
235 start_value = SolveInstanceTypeConstraints(std::move(constrained_child),
236 start_value, &root->children);
238 if (own_type_pending) {
239 start_value = SelectOwnValues(root.get(), start_value);
240 own_type_pending =
false;
242 for (
auto& child_pair : unconstrained_children_by_size) {
243 start_value = SolveInstanceTypeConstraints(std::move(child_pair.second),
244 start_value, &root->children);
246 if (highest_child !=
nullptr) {
247 start_value = SolveInstanceTypeConstraints(std::move(highest_child),
248 start_value, &root->children);
252 root->end = start_value - 1;
254 root->children.empty() ? start_value : root->children.front()->start;
255 if (root->value != -1 && root->value < root->start) {
256 root->start = root->value;
258 root->num_values = root->end - root->start + 1;
259 root->type->InitializeInstanceTypes(
260 root->value == -1 ? std::optional<int>{} : root->value,
261 std::make_pair(root->start, root->end));
263 if (root->num_values > 0) {
269std::unique_ptr<InstanceTypeTree> SolveInstanceTypeConstraints(
270 std::unique_ptr<InstanceTypeTree> root) {
271 std::vector<std::unique_ptr<InstanceTypeTree>>
destination;
272 SolveInstanceTypeConstraints(std::move(root), 0, &
destination);
276std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
277 std::unique_ptr<InstanceTypeTree> root = BuildInstanceTypeTree();
278 if (root !=
nullptr) {
279 PropagateInstanceTypeConstraints(root.get());
280 root = SolveInstanceTypeConstraints(std::move(root));
310void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
311 std::ostream& values,
312 std::ostream& fully_defined_single_instance_types,
313 std::ostream& fully_defined_multiple_instance_types,
314 std::ostream& only_declared_single_instance_types,
315 std::ostream& only_declared_multiple_instance_types,
316 std::ostream& fully_defined_range_instance_types,
317 std::ostream& only_declared_range_instance_types,
318 const std::string& indent) {
319 std::string type_name =
321 std::string inner_indent = indent;
323 if (root->num_values > 1) {
324 definitions << indent <<
"V(FIRST_" << type_name <<
", " << root->start
328 if (root->num_own_values == 1) {
329 definitions << inner_indent <<
"V(" << type_name <<
", " << root->value
330 <<
") /* " << root->type->GetPosition() <<
" */\\\n";
331 values <<
" V(" << type_name <<
") /* " << root->type->GetPosition()
333 std::ostream& type_checker_list =
334 root->type->HasUndefinedLayout()
335 ? (root->num_values == 1 ? only_declared_single_instance_types
336 : only_declared_multiple_instance_types)
337 : (root->
num_values == 1 ? fully_defined_single_instance_types
338 : fully_defined_multiple_instance_types);
339 type_checker_list <<
" V(" << root->type->name() <<
", " << type_name
340 <<
") /* " << root->type->GetPosition() <<
" */ \\\n";
342 for (
auto& child : root->children) {
343 PrintInstanceTypes(child.get(), definitions, values,
344 fully_defined_single_instance_types,
345 fully_defined_multiple_instance_types,
346 only_declared_single_instance_types,
347 only_declared_multiple_instance_types,
348 fully_defined_range_instance_types,
349 only_declared_range_instance_types, inner_indent);
351 if (root->num_values > 1) {
356 if (root->num_own_values <= 1) {
357 definitions << indent <<
"V(LAST_" << type_name <<
", " << root->end
362 if (root->type->GetSuperClass() !=
nullptr) {
363 std::ostream& range_instance_types =
364 root->type->HasUndefinedLayout() ? only_declared_range_instance_types
365 : fully_defined_range_instance_types;
366 range_instance_types <<
" V(" << root->type->name() <<
", FIRST_"
367 << type_name <<
", LAST_" << type_name <<
") \\\n";
375 const std::string& output_directory) {
376 std::stringstream header;
377 std::string file_name =
"instance-types.h";
381 header <<
"// Instance types for all classes except for those that use "
382 "InstanceType as flags.\n";
383 header <<
"#define TORQUE_ASSIGNED_INSTANCE_TYPES(V) \\\n";
384 std::unique_ptr<InstanceTypeTree> instance_types = AssignInstanceTypes();
385 std::stringstream values_list;
386 std::stringstream fully_defined_single_instance_types;
387 std::stringstream fully_defined_multiple_instance_types;
388 std::stringstream only_declared_single_instance_types;
389 std::stringstream only_declared_multiple_instance_types;
390 std::stringstream fully_defined_range_instance_types;
391 std::stringstream only_declared_range_instance_types;
392 if (instance_types !=
nullptr) {
393 PrintInstanceTypes(instance_types.get(), header, values_list,
394 fully_defined_single_instance_types,
395 fully_defined_multiple_instance_types,
396 only_declared_single_instance_types,
397 only_declared_multiple_instance_types,
398 fully_defined_range_instance_types,
399 only_declared_range_instance_types,
" ");
403 header <<
"// Instance types for all classes except for those that use\n";
404 header <<
"// InstanceType as flags.\n";
405 header <<
"#define TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(V) \\\n";
406 header << values_list.str();
409 header <<
"// Pairs of (ClassName, INSTANCE_TYPE) for classes that have\n";
410 header <<
"// full Torque definitions.\n";
411 header <<
"#define TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(V) \\\n";
412 header << fully_defined_single_instance_types.str();
415 header <<
"// Pairs of (ClassName, INSTANCE_TYPE) for classes that have\n";
416 header <<
"// full Torque definitions and subclasses.\n";
417 header <<
"#define TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(V) \\\n";
418 header << fully_defined_multiple_instance_types.str();
421 header <<
"// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n";
422 header <<
"// declared but not defined in Torque. These classes may\n";
423 header <<
"// correspond with actual C++ classes, but they are not\n";
424 header <<
"// guaranteed to.\n";
425 header <<
"#define TORQUE_INSTANCE_CHECKERS_SINGLE_ONLY_DECLARED(V) \\\n";
426 header << only_declared_single_instance_types.str();
429 header <<
"// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n";
430 header <<
"// declared but not defined in Torque, and have subclasses.\n";
431 header <<
"// These classes may correspond with actual C++ classes, but\n";
432 header <<
"// they are not guaranteed to.\n";
433 header <<
"#define TORQUE_INSTANCE_CHECKERS_MULTIPLE_ONLY_DECLARED(V) \\\n";
434 header << only_declared_multiple_instance_types.str();
437 header <<
"// Triples of (ClassName, FIRST_TYPE, LAST_TYPE) for classes\n";
438 header <<
"// that have full Torque definitions.\n";
439 header <<
"#define TORQUE_INSTANCE_CHECKERS_RANGE_FULLY_DEFINED(V) \\\n";
440 header << fully_defined_range_instance_types.str();
443 header <<
"// Triples of (ClassName, FIRST_TYPE, LAST_TYPE) for classes\n";
444 header <<
"// that are declared but not defined in Torque. These classes\n";
445 header <<
"// may correspond with actual C++ classes, but they are not\n";
446 header <<
"// guaranteed to.\n";
447 header <<
"#define TORQUE_INSTANCE_CHECKERS_RANGE_ONLY_DECLARED(V) \\\n";
448 header << only_declared_range_instance_types.str();
451 std::stringstream torque_defined_class_list;
452 std::stringstream torque_defined_varsize_instance_type_list;
453 std::stringstream torque_defined_fixed_instance_type_list;
454 std::stringstream torque_defined_map_csa_list;
455 std::stringstream torque_defined_map_root_list;
458 std::string upper_case_name = type->name();
460 std::string instance_type_name =
463 if (!type->IsExtern()) {
464 torque_defined_class_list <<
" V(" << upper_case_name <<
") \\\n";
467 if (type->ShouldGenerateUniqueMap()) {
468 torque_defined_map_csa_list <<
" V(_, " << upper_case_name <<
"Map, "
469 << lower_case_name <<
"_map, "
470 << upper_case_name <<
") \\\n";
471 torque_defined_map_root_list <<
" V(Map, " << lower_case_name
472 <<
"_map, " << upper_case_name
474 std::stringstream& list =
475 type->HasStaticSize() ? torque_defined_fixed_instance_type_list
476 : torque_defined_varsize_instance_type_list;
477 list <<
" V(" << instance_type_name <<
", " << upper_case_name <<
", "
478 << lower_case_name <<
") \\\n";
482 header <<
"// Fully Torque-defined classes (both internal and exported).\n";
483 header <<
"#define TORQUE_DEFINED_CLASS_LIST(V) \\\n";
484 header << torque_defined_class_list.str();
486 header <<
"#define TORQUE_DEFINED_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n";
487 header << torque_defined_varsize_instance_type_list.str();
489 header <<
"#define TORQUE_DEFINED_FIXED_INSTANCE_TYPE_LIST(V) \\\n";
490 header << torque_defined_fixed_instance_type_list.str();
492 header <<
"#define TORQUE_DEFINED_INSTANCE_TYPE_LIST(V) \\\n";
493 header <<
" TORQUE_DEFINED_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n";
494 header <<
" TORQUE_DEFINED_FIXED_INSTANCE_TYPE_LIST(V) \\\n";
496 header <<
"#define TORQUE_DEFINED_MAP_CSA_LIST_GENERATOR(V, _) \\\n";
497 header << torque_defined_map_csa_list.str();
499 header <<
"#define TORQUE_DEFINED_MAP_ROOT_LIST(V) \\\n";
500 header << torque_defined_map_root_list.str();
503 std::string output_header_path = output_directory +
"/" + file_name;
504 WriteFile(output_header_path, header.str());
static const std::vector< std::unique_ptr< Declarable > > & AllDeclarables()
static void SetInstanceTypesInitialized()
void GenerateInstanceTypes(const std::string &output_directory)
void WriteFile(const std::string &file, const std::string &content)
MessageBuilder & Position(SourcePosition position)
static std::vector< const ClassType * > GetClasses()
std::vector< std::unique_ptr< InstanceTypeTree > > children
InstructionOperand destination
std::string CapifyStringWithUnderscores(const std::string &camellified_string)
std::string SnakeifyString(const std::string &camel_string)
MessageBuilder Error(Args &&... args)
Disallow flags or implications overriding each other abort_on_contradictory_flags true
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation nullptr