Skip to content

Commit d951763

Browse files
committed
clean(uvtd): get rid of old/no longer necessary bitfield getter path
1 parent 2172883 commit d951763

File tree

1 file changed

+5
-225
lines changed

1 file changed

+5
-225
lines changed

UVTD/src/MemberVarsWrapperGenerator.cpp

Lines changed: 5 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -158,180 +158,6 @@ namespace RC::UVTD
158158
}
159159

160160

161-
// Information about a versioned bitfield for adaptive getter generation
162-
struct VersionedBitfieldInfo
163-
{
164-
File::StringType storage_type;
165-
uint8_t bit_position;
166-
uint8_t bit_length;
167-
int32_t major_version;
168-
int32_t minor_version;
169-
};
170-
171-
// Helper to format mask as hex string
172-
static auto format_hex_mask(uint64_t mask) -> File::StringType
173-
{
174-
return std::format(STR("0x{:X}"), mask);
175-
}
176-
177-
// Helper to generate a version-adaptive bitfield getter body
178-
// This handles cases where bit position or storage type changes between versions
179-
static auto generate_versioned_bitfield_getter_body(
180-
Output::Targets<Output::NewFileDevice>& dumper,
181-
const File::StringType& class_name,
182-
const File::StringType& variable_name,
183-
const std::vector<VersionedBitfieldInfo>& versions) -> void
184-
{
185-
dumper.send(STR("{{\n"));
186-
dumper.send(STR(" static const int32_t offset = []() -> int32_t {{\n"));
187-
dumper.send(STR(" auto offset_it = MemberOffsets.find(STR(\"{}\"));\n"), variable_name);
188-
dumper.send(STR(
189-
" if (offset_it == MemberOffsets.end()) {{ throw std::runtime_error{{\"Tried getting member variable '{}::{}' "
190-
"that doesn't exist in this engine version.\"}}; }}\n"),
191-
class_name,
192-
variable_name);
193-
dumper.send(STR(" return offset_it->second;\n"));
194-
dumper.send(STR(" }}();\n\n"));
195-
196-
// Generate version checks from newest to oldest
197-
bool first = true;
198-
for (auto it = versions.rbegin(); it != versions.rend(); ++it)
199-
{
200-
const auto& ver = *it;
201-
uint64_t mask = (1ULL << ver.bit_length) - 1;
202-
File::StringType mask_hex = format_hex_mask(mask);
203-
204-
if (first)
205-
{
206-
// For the newest version (checked first at runtime)
207-
auto next_it = it;
208-
++next_it;
209-
if (next_it != versions.rend())
210-
{
211-
dumper.send(STR(" if (Version::IsAtLeast({}, {})) {{\n"), ver.major_version, ver.minor_version);
212-
dumper.send(STR(" {} storage = *Helper::Casting::ptr_cast<{}*>(this, offset);\n"), ver.storage_type, ver.storage_type);
213-
if (ver.bit_length == 1)
214-
{
215-
dumper.send(STR(" return (storage >> {}) & 1;\n"), ver.bit_position);
216-
}
217-
else
218-
{
219-
dumper.send(STR(" return (storage >> {}) & {};\n"), ver.bit_position, mask_hex);
220-
}
221-
dumper.send(STR(" }}\n"));
222-
}
223-
else
224-
{
225-
// Only one version - no need for version check
226-
dumper.send(STR(" {} storage = *Helper::Casting::ptr_cast<{}*>(this, offset);\n"), ver.storage_type, ver.storage_type);
227-
if (ver.bit_length == 1)
228-
{
229-
dumper.send(STR(" return (storage >> {}) & 1;\n"), ver.bit_position);
230-
}
231-
else
232-
{
233-
dumper.send(STR(" return (storage >> {}) & {};\n"), ver.bit_position, mask_hex);
234-
}
235-
}
236-
first = false;
237-
}
238-
else
239-
{
240-
// Check if this is the last (oldest) version
241-
auto next_it = it;
242-
++next_it;
243-
if (next_it == versions.rend())
244-
{
245-
// Last version - use else
246-
dumper.send(STR(" else {{\n"));
247-
}
248-
else
249-
{
250-
dumper.send(STR(" else if (Version::IsAtLeast({}, {})) {{\n"), ver.major_version, ver.minor_version);
251-
}
252-
dumper.send(STR(" {} storage = *Helper::Casting::ptr_cast<{}*>(this, offset);\n"), ver.storage_type, ver.storage_type);
253-
if (ver.bit_length == 1)
254-
{
255-
dumper.send(STR(" return (storage >> {}) & 1;\n"), ver.bit_position);
256-
}
257-
else
258-
{
259-
dumper.send(STR(" return (storage >> {}) & {};\n"), ver.bit_position, mask_hex);
260-
}
261-
dumper.send(STR(" }}\n"));
262-
}
263-
}
264-
dumper.send(STR("}}\n"));
265-
}
266-
267-
// Helper to generate a version-adaptive bitfield setter body
268-
static auto generate_versioned_bitfield_setter_body(
269-
Output::Targets<Output::NewFileDevice>& dumper,
270-
const File::StringType& class_name,
271-
const File::StringType& variable_name,
272-
const std::vector<VersionedBitfieldInfo>& versions) -> void
273-
{
274-
dumper.send(STR("{{\n"));
275-
dumper.send(STR(" static const int32_t offset = []() -> int32_t {{\n"));
276-
dumper.send(STR(" auto offset_it = MemberOffsets.find(STR(\"{}\"));\n"), variable_name);
277-
dumper.send(STR(
278-
" if (offset_it == MemberOffsets.end()) {{ throw std::runtime_error{{\"Tried setting member variable '{}::{}' "
279-
"that doesn't exist in this engine version.\"}}; }}\n"),
280-
class_name,
281-
variable_name);
282-
dumper.send(STR(" return offset_it->second;\n"));
283-
dumper.send(STR(" }}();\n\n"));
284-
285-
// Generate version checks from newest to oldest
286-
bool first = true;
287-
for (auto it = versions.rbegin(); it != versions.rend(); ++it)
288-
{
289-
const auto& ver = *it;
290-
uint64_t mask = (1ULL << ver.bit_length) - 1;
291-
File::StringType mask_hex = format_hex_mask(mask);
292-
293-
if (first)
294-
{
295-
auto next_it = it;
296-
++next_it;
297-
if (next_it != versions.rend())
298-
{
299-
dumper.send(STR(" if (Version::IsAtLeast({}, {})) {{\n"), ver.major_version, ver.minor_version);
300-
dumper.send(STR(" {}& storage = *Helper::Casting::ptr_cast<{}*>(this, offset);\n"), ver.storage_type, ver.storage_type);
301-
dumper.send(STR(" storage = (storage & ~(static_cast<{}>({}) << {})) | ((static_cast<{}>(value) & {}) << {});\n"),
302-
ver.storage_type, mask_hex, ver.bit_position, ver.storage_type, mask_hex, ver.bit_position);
303-
dumper.send(STR(" }}\n"));
304-
}
305-
else
306-
{
307-
// Only one version
308-
dumper.send(STR(" {}& storage = *Helper::Casting::ptr_cast<{}*>(this, offset);\n"), ver.storage_type, ver.storage_type);
309-
dumper.send(STR(" storage = (storage & ~(static_cast<{}>({}) << {})) | ((static_cast<{}>(value) & {}) << {});\n"),
310-
ver.storage_type, mask_hex, ver.bit_position, ver.storage_type, mask_hex, ver.bit_position);
311-
}
312-
first = false;
313-
}
314-
else
315-
{
316-
auto next_it = it;
317-
++next_it;
318-
if (next_it == versions.rend())
319-
{
320-
dumper.send(STR(" else {{\n"));
321-
}
322-
else
323-
{
324-
dumper.send(STR(" else if (Version::IsAtLeast({}, {})) {{\n"), ver.major_version, ver.minor_version);
325-
}
326-
dumper.send(STR(" {}& storage = *Helper::Casting::ptr_cast<{}*>(this, offset);\n"), ver.storage_type, ver.storage_type);
327-
dumper.send(STR(" storage = (storage & ~(static_cast<{}>({}) << {})) | ((static_cast<{}>(value) & {}) << {});\n"),
328-
ver.storage_type, mask_hex, ver.bit_position, ver.storage_type, mask_hex, ver.bit_position);
329-
dumper.send(STR(" }}\n"));
330-
}
331-
}
332-
dumper.send(STR("}}\n\n"));
333-
}
334-
335161
// Information about a versioned getter that needs a public wrapper
336162
struct VersionedGetterInfo
337163
{
@@ -501,7 +327,9 @@ namespace RC::UVTD
501327
// Check if this variable has version-specific type changes
502328
// If so, we generate versioned getters instead of a single getter
503329
// Versioned getters are always private - public wrappers will be added later
504-
bool has_versioned_getters = variable.has_type_changes() && !inheritance_info.has_value();
330+
// Versioned bitfields are handled by BitfieldProxy at runtime (storage_size, bit_pos, bit_len from INI),
331+
// so they don't need versioned getters
332+
bool has_versioned_getters = variable.has_type_changes() && !inheritance_info.has_value() && !variable.is_bitfield;
505333

506334
// Count how many unique getters we'll actually generate after normalization
507335
// Types that normalize to the same thing (e.g., FDefaultAllocator vs TSizedDefaultAllocator<32>,
@@ -510,30 +338,8 @@ namespace RC::UVTD
510338
std::set<File::StringType> seen_normalized_types;
511339
File::StringType best_type_for_single_getter; // The "best" type to use if we only need one getter
512340

513-
// Check if all versioned types are bitfields - if so, we can generate an adaptive getter
514-
bool all_versions_are_bitfields = false;
515-
std::vector<VersionedBitfieldInfo> versioned_bitfield_infos;
516-
517341
if (has_versioned_getters)
518342
{
519-
all_versions_are_bitfields = true;
520-
for (const auto& [version_key, versioned_type] : variable.types_by_version)
521-
{
522-
if (!versioned_type.is_bitfield)
523-
{
524-
all_versions_are_bitfields = false;
525-
break;
526-
}
527-
528-
VersionedBitfieldInfo bf_info;
529-
bf_info.storage_type = versioned_type.type;
530-
bf_info.bit_position = versioned_type.bit_position;
531-
bf_info.bit_length = versioned_type.bit_length;
532-
bf_info.major_version = versioned_type.major_version;
533-
bf_info.minor_version = versioned_type.minor_version;
534-
versioned_bitfield_infos.push_back(bf_info);
535-
}
536-
537343
for (const auto& [version_key, versioned_type] : variable.types_by_version)
538344
{
539345
File::StringType version_type_name = versioned_type.type;
@@ -564,8 +370,7 @@ namespace RC::UVTD
564370

565371
// Only treat as versioned if we have multiple unique types after normalization
566372
// If only one unique type remains, treat as a normal getter with the best type
567-
// EXCEPT: if all versions are bitfields, we can generate a single adaptive getter
568-
bool effectively_has_versioned_getters = has_versioned_getters && valid_getter_count > 1 && !all_versions_are_bitfields;
373+
bool effectively_has_versioned_getters = has_versioned_getters && valid_getter_count > 1;
569374

570375
if (is_private || effectively_has_versioned_getters)
571376
{
@@ -578,34 +383,9 @@ namespace RC::UVTD
578383

579384
if (has_versioned_getters)
580385
{
581-
// If all versions are bitfields, generate a single adaptive getter that handles
582-
// the different storage types and bit positions at runtime
583-
if (all_versions_are_bitfields && versioned_bitfield_infos.size() > 1)
584-
{
585-
Output::send(STR(" Generating adaptive bitfield getter for {}::{} ({} versions)\n"),
586-
final_class_name, final_variable_name, versioned_bitfield_infos.size());
587-
588-
// For bitfields, return bool for single-bit fields, otherwise use the largest storage type
589-
// to ensure we can hold any version's value
590-
bool all_single_bit = std::all_of(versioned_bitfield_infos.begin(), versioned_bitfield_infos.end(),
591-
[](const VersionedBitfieldInfo& info) { return info.bit_length == 1; });
592-
593-
File::StringType return_type = all_single_bit ? STR("bool") : STR("uint32_t");
594-
595-
// For versioned bitfields, we can't provide a reference getter since storage type may change
596-
// So we only provide the Value getter/setter methods
597-
header_wrapper_dumper.send(STR(" {} Get{}Value() const;\n"), return_type, final_variable_name);
598-
header_wrapper_dumper.send(STR(" void Set{}Value({} value);\n\n"), final_variable_name, return_type);
599-
600-
wrapper_src_dumper.send(STR("{} {}::Get{}Value() const\n"), return_type, final_class_name, final_variable_name);
601-
generate_versioned_bitfield_getter_body(wrapper_src_dumper, final_class_name, final_variable_name, versioned_bitfield_infos);
602-
603-
wrapper_src_dumper.send(STR("void {}::Set{}Value({} value)\n"), final_class_name, final_variable_name, return_type);
604-
generate_versioned_bitfield_setter_body(wrapper_src_dumper, final_class_name, final_variable_name, versioned_bitfield_infos);
605-
}
606386
// If after normalization we only have one unique type, generate a single getter
607387
// using the "best" type (the most recent version, which has TObjectPtr/TSizedDefaultAllocator)
608-
else if (valid_getter_count == 1)
388+
if (valid_getter_count == 1)
609389
{
610390
Output::send(STR(" Unified versioned getters for {}::{} to single type: {}\n"),
611391
final_class_name, final_variable_name, best_type_for_single_getter);

0 commit comments

Comments
 (0)