avoid too much field copy

This commit is contained in:
water
2024-03-09 13:02:53 -05:00
parent 390a511055
commit ec190a145c
13 changed files with 123 additions and 128 deletions
+6 -13
View File
@@ -901,18 +901,14 @@ int StructureType::get_inline_array_start_alignment() const {
}
}
bool StructureType::lookup_field(const std::string& name, Field* out) {
const Field* StructureType::lookup_field(const std::string& name) const {
for (auto& x : m_fields) {
if (x.name() == name) {
if (out) {
*out = x;
}
return true;
return &x;
}
}
return false;
return nullptr;
}
void StructureType::override_field_type(const std::string& field_name, const TypeSpec& new_type) {
@@ -1045,16 +1041,13 @@ std::string BitField::diff(const BitField& other) const {
BitFieldType::BitFieldType(std::string parent, std::string name, int size, bool sign_extend)
: ValueType(std::move(parent), std::move(name), false, size, sign_extend, RegClass::GPR_64) {}
bool BitFieldType::lookup_field(const std::string& name, BitField* out) const {
const BitField* BitFieldType::lookup_field(const std::string& name) const {
for (auto& field : m_fields) {
if (field.name() == name) {
if (out) {
*out = field;
}
return true;
return &field;
}
}
return false;
return nullptr;
}
std::string BitField::print() const {
+2 -2
View File
@@ -305,7 +305,7 @@ class StructureType : public ReferenceType {
int get_in_memory_alignment() const override;
int get_inline_array_stride_alignment() const override;
int get_inline_array_start_alignment() const override;
bool lookup_field(const std::string& name, Field* out);
const Field* lookup_field(const std::string& name) const;
bool is_dynamic() const { return m_dynamic; }
~StructureType() = default;
void set_pack(bool pack) { m_pack = pack; }
@@ -384,7 +384,7 @@ class BitField {
class BitFieldType : public ValueType {
public:
BitFieldType(std::string parent, std::string name, int size, bool sign_extend);
bool lookup_field(const std::string& name, BitField* out) const;
const BitField* lookup_field(const std::string& name) const;
std::string print() const override;
bool operator==(const Type& other) const override;
const std::vector<BitField>& fields() const { return m_fields; }
+26 -25
View File
@@ -952,42 +952,42 @@ void TypeSystem::assert_method_id(const std::string& type_name,
FieldLookupInfo TypeSystem::lookup_field_info(const std::string& type_name,
const std::string& field_name) const {
FieldLookupInfo info;
info.field = lookup_field(type_name, field_name);
info.field = &lookup_field(type_name, field_name);
// get array size, for bounds checking (when possible)
if (info.field.is_array() && !info.field.is_dynamic()) {
info.array_size = info.field.array_size();
if (info.field->is_array() && !info.field->is_dynamic()) {
info.array_size = info.field->array_size();
}
auto base_type = lookup_type_allow_partial_def(info.field.type());
auto base_type = lookup_type_allow_partial_def(info.field->type());
if (base_type->is_reference()) {
if (info.field.is_inline()) {
if (info.field.is_array()) {
if (info.field->is_inline()) {
if (info.field->is_array()) {
// inline array of reference types
info.needs_deref = false;
info.type = make_inline_array_typespec(info.field.type());
info.type = make_inline_array_typespec(info.field->type());
} else {
// inline object
info.needs_deref = false;
info.type = info.field.type();
info.type = info.field->type();
}
} else {
if (info.field.is_array()) {
if (info.field->is_array()) {
info.needs_deref = false;
info.type = make_pointer_typespec(info.field.type());
info.type = make_pointer_typespec(info.field->type());
} else {
info.needs_deref = true;
info.type = info.field.type();
info.type = info.field->type();
}
}
} else {
if (info.field.is_array()) {
if (info.field->is_array()) {
info.needs_deref = false;
info.type = make_pointer_typespec(info.field.type());
info.type = make_pointer_typespec(info.field->type());
} else {
// not array
info.needs_deref = true;
info.type = info.field.type();
info.type = info.field->type();
}
}
return info;
@@ -999,7 +999,7 @@ FieldLookupInfo TypeSystem::lookup_field_info(const std::string& type_name,
void TypeSystem::assert_field_offset(const std::string& type_name,
const std::string& field_name,
int offset) {
Field field = lookup_field(type_name, field_name);
const Field& field = lookup_field(type_name, field_name);
if (field.offset() != offset) {
throw_typesystem_error("assert_field_offset({}, {}, {}) failed - got {}\n", type_name,
field_name, offset);
@@ -1020,7 +1020,7 @@ int TypeSystem::add_field_to_type(StructureType* type,
bool skip_in_static_decomp,
double score,
const std::optional<TypeSpec> decomp_as_ts) {
if (type->lookup_field(field_name, nullptr)) {
if (type->lookup_field(field_name)) {
throw_typesystem_error("Type {} already has a field named {}\n", type->get_name(), field_name);
}
@@ -1304,13 +1304,14 @@ int TypeSystem::get_next_method_id(const Type* type) const {
/*!
* Lookup a field of a type by name
*/
Field TypeSystem::lookup_field(const std::string& type_name, const std::string& field_name) const {
const Field& TypeSystem::lookup_field(const std::string& type_name,
const std::string& field_name) const {
auto type = get_type_of_type<StructureType>(type_name);
Field field;
if (!type->lookup_field(field_name, &field)) {
auto field = type->lookup_field(field_name);
if (!field) {
throw_typesystem_error("Type {} has no field named {}\n", type_name, field_name);
}
return field;
return *field;
}
/*!
@@ -1876,16 +1877,16 @@ bool TypeSystem::is_bitfield_type(const std::string& type_name) const {
BitfieldLookupInfo TypeSystem::lookup_bitfield_info(const std::string& type_name,
const std::string& field_name) const {
auto type = get_type_of_type<BitFieldType>(type_name);
BitField f;
if (!type->lookup_field(field_name, &f)) {
const BitField* f = type->lookup_field(field_name);
if (!f) {
throw_typesystem_error("Type {} has no bitfield named {}\n", type_name, field_name);
}
BitfieldLookupInfo result;
result.result_type = f.type();
result.offset = f.offset();
result.result_type = f->type();
result.offset = f->offset();
result.sign_extend = lookup_type(result.result_type)->get_load_signed();
result.size = f.size();
result.size = f->size();
return result;
}
+3 -2
View File
@@ -17,6 +17,7 @@
#include "Type.h"
#include "TypeSpec.h"
#include "common/util/StringHashTable.h"
struct TypeFlags {
union {
@@ -31,7 +32,7 @@ struct TypeFlags {
};
struct FieldLookupInfo {
Field field;
const Field* field = nullptr;
TypeSpec type;
bool needs_deref = true;
int array_size = -1;
@@ -303,7 +304,7 @@ class TypeSystem {
const std::string& actual,
bool allow_alias) const;
int get_alignment_in_type(const Field& field);
Field lookup_field(const std::string& type_name, const std::string& field_name) const;
const Field& lookup_field(const std::string& type_name, const std::string& field_name) const;
StructureType* add_builtin_structure(const std::string& parent,
const std::string& type_name,
bool boxed = false);
+25 -24
View File
@@ -106,8 +106,7 @@ void add_field(
double score = 0;
bool skip_in_decomp = false;
std::optional<TypeSpec> decomp_as_ts = std::nullopt;
Field override_field;
bool override = false;
const Field* override_field = nullptr;
if (!rest->is_empty_list()) {
if (car(rest).is_int()) {
@@ -131,21 +130,22 @@ void add_field(
offset_override = get_int(car(rest));
rest = cdr(rest);
} else if (opt_name == ":override") {
override = true;
if (!structure->lookup_field(name, &override_field)) {
override_field = structure->lookup_field(name);
if (!override_field) {
throw std::runtime_error(fmt::format("Field {} not found to override", name));
}
} else if (opt_name == ":overlay-at") {
const auto& param = car(rest);
rest = cdr(rest);
Field overlay_field;
const Field* overlay_field = nullptr;
if (param.is_symbol()) {
auto field_name = symbol_string(param);
if (!structure->lookup_field(field_name, &overlay_field)) {
overlay_field = structure->lookup_field(field_name);
if (!overlay_field) {
throw std::runtime_error(
fmt::format("Field {} not found to overlay for {}", field_name, name));
fmt::format("Field {} not found to overlay for {} (1)", field_name, name));
}
offset_override = overlay_field.offset();
offset_override = overlay_field->offset();
} else if (param.is_pair() && car(&param).is_symbol("->")) {
auto name_it = cdr(&param);
if (name_it->is_empty_list()) {
@@ -157,17 +157,17 @@ void add_field(
while (!name_it->is_empty_list()) {
const auto& deref_field = car(name_it);
if (deref_field.is_int()) {
auto ref_array_field = !type_to_use && !overlay_field.is_inline()
? ts->lookup_type_allow_partial_def(overlay_field.type())
auto ref_array_field = !type_to_use && !overlay_field->is_inline()
? ts->lookup_type_allow_partial_def(overlay_field->type())
: nullptr;
if (ref_array_field) {
// we can have an array of references (non-inline) to a forward-declared type
offset_override += ref_array_field->get_load_size() * deref_field.as_int();
} else {
auto type_to_deref = type_to_use && overlay_field.is_inline()
auto type_to_deref = type_to_use && overlay_field->is_inline()
? TypeSpec("inline-array")
: TypeSpec("pointer");
type_to_deref.add_arg(overlay_field.type());
type_to_deref.add_arg(overlay_field->type());
auto deref_info = ts->get_deref_info(type_to_deref);
if (!deref_info.can_deref) {
throw std::runtime_error(
@@ -180,16 +180,17 @@ void add_field(
if (!type_to_use) {
throw std::runtime_error(
fmt::format("Field {} not inside a structure for overlay-at in {}",
overlay_field.name(), name));
overlay_field->name(), name));
}
auto field_name = symbol_string(car(name_it));
if (!type_to_use->lookup_field(field_name, &overlay_field)) {
overlay_field = type_to_use->lookup_field(field_name);
if (!overlay_field) {
throw std::runtime_error(
fmt::format("Field {} not found to overlay for {}", field_name, name));
fmt::format("Field {} not found to overlay for {} (2)", field_name, name));
}
type_to_use =
dynamic_cast<StructureType*>(ts->lookup_type_no_throw(overlay_field.type()));
offset_override += overlay_field.offset();
dynamic_cast<StructureType*>(ts->lookup_type_no_throw(overlay_field->type()));
offset_override += overlay_field->offset();
}
name_it = cdr(name_it);
}
@@ -216,21 +217,21 @@ void add_field(
}
}
if (override && name == override_field.name()) {
if (override_field && name == override_field->name()) {
// override field, e.g. (root collide-shape :overlay-at root)
// does not add new field, merely rewrites inherited one
if (!ts->tc(override_field.type(), type)) {
if (!ts->tc(override_field->type(), type)) {
throw std::runtime_error(
fmt::format("Wanted to override field {}, but type {} isn't child of {}",
override_field.name(), type.print(), override_field.type().print()));
override_field->name(), type.print(), override_field->type().print()));
}
if (override_field.is_inline() != is_inline || override_field.is_dynamic() != is_dynamic ||
(array_size != -1 && override_field.array_size() != array_size)) {
if (override_field->is_inline() != is_inline || override_field->is_dynamic() != is_dynamic ||
(array_size != -1 && override_field->array_size() != array_size)) {
throw std::runtime_error(
fmt::format("Wanted to override field {}, but some parameters were different",
override_field.name()));
override_field->name()));
}
structure->override_field_type(override_field.name(), type);
structure->override_field_type(override_field->name(), type);
} else {
// new unique field
int actual_offset =
+6 -6
View File
@@ -825,15 +825,15 @@ std::optional<std::vector<BitFieldDef>> get_field_defs_from_expr(const BitFieldT
return std::nullopt;
}
BitField field_info;
if (!type_info->lookup_field(maybe_field->field_name, &field_info)) {
const BitField* field_info = type_info->lookup_field(maybe_field->field_name);
if (!field_info) {
ASSERT(false);
}
if (field_info.type() == TypeSpec("symbol") || field_info.type() == TypeSpec("type")) {
if (field_info->type() == TypeSpec("symbol") || field_info->type() == TypeSpec("type")) {
maybe_field->value = strip_int_or_uint_cast(maybe_field->value);
}
if (field_info.type() == TypeSpec("float")) {
if (field_info->type() == TypeSpec("float")) {
auto stripped = strip_int_or_uint_cast(maybe_field->value);
auto integer = get_goal_integer_constant(stripped, env);
if (integer) {
@@ -845,9 +845,9 @@ std::optional<std::vector<BitFieldDef>> get_field_defs_from_expr(const BitFieldT
}
auto field_type_as_bitfield =
dynamic_cast<BitFieldType*>(env.dts->ts.lookup_type(field_info.type()));
dynamic_cast<BitFieldType*>(env.dts->ts.lookup_type(field_info->type()));
if (field_type_as_bitfield) {
maybe_field->value = cast_to_bitfield(field_type_as_bitfield, field_info.type(), pool, env,
maybe_field->value = cast_to_bitfield(field_type_as_bitfield, field_info->type(), pool, env,
maybe_field->value);
}
+11 -12
View File
@@ -1522,10 +1522,9 @@ std::string TypeInspectorResult::print_as_deftype(
continue;
}
if (old_game_type) {
Field old_field;
if (old_game_type->lookup_field(field.name(), &old_field) &&
field.type() != old_field.type()) {
field.type() = old_field.type();
const Field* old_field = old_game_type->lookup_field(field.name());
if (old_field && field.type() != old_field->type()) {
field.type() = old_field->type();
was_guess.push_back(true);
} else {
was_guess.push_back(false);
@@ -1608,17 +1607,17 @@ std::string TypeInspectorResult::print_as_deftype(
result.append(std::to_string(field.offset()));
result.append(")");
if (old_game_type) {
Field old_field;
if (old_game_type->lookup_field(field.name(), &old_field)) {
if (old_field.type() != field.type()) {
result += fmt::format(" ;; {}", old_field.type().print());
if (old_field.is_array() && !old_field.is_dynamic()) {
result += fmt::format(" {}", old_field.array_size());
const Field* old_field = old_game_type->lookup_field(field.name());
if (old_field) {
if (old_field->type() != field.type()) {
result += fmt::format(" ;; {}", old_field->type().print());
if (old_field->is_array() && !old_field->is_dynamic()) {
result += fmt::format(" {}", old_field->array_size());
}
if (old_field.is_inline()) {
if (old_field->is_inline()) {
result += " :inline";
}
if (old_field.is_dynamic()) {
if (old_field->is_dynamic()) {
result += " :dynamic";
}
}
+1 -1
View File
@@ -571,7 +571,7 @@ void inspect_cloth_data_jak3(LetElement* let, DefskelgroupElement::StaticInfo& i
if (array_set) {
// get elements
auto elts = when_body->elts().size() - 2;
for (int i = 0; i < elts; i++) {
for (size_t i = 0; i < elts; i++) {
auto parms_form = dynamic_cast<SetFormFormElement*>(when_body->at(i + 1));
if (parms_form) {
auto parms_data = dynamic_cast<DecompiledDataElement*>(parms_form->src()->at(0));
+2 -3
View File
@@ -362,14 +362,13 @@ void MercEffect::from_ref(TypedRef tr,
tri_count = read_plain_data_field<u16>(tr, "tri-count", dts);
dvert_count = read_plain_data_field<u16>(tr, "dvert-count", dts);
auto* type = dynamic_cast<StructureType*>(dts.ts.lookup_type("merc-effect"));
Field temp;
if (type->lookup_field("envmap-usage", &temp)) {
if (type->lookup_field("envmap-usage")) {
envmap_or_effect_usage = read_plain_data_field<u8>(tr, "envmap-usage", dts);
} else {
envmap_or_effect_usage = read_plain_data_field<u8>(tr, "effect-usage", dts);
}
if (type->lookup_field("texture-index", &temp)) {
if (type->lookup_field("texture-index")) {
texture_index = read_plain_data_field<u8>(tr, "texture-index", dts);
}
+19 -19
View File
@@ -11,8 +11,8 @@ void read_plain_data_field(const TypedRef& object,
u8* out) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
if (field_info.field.is_dynamic() || field_info.field.is_array() ||
field_info.field.is_inline()) {
if (field_info.field->is_dynamic() || field_info.field->is_array() ||
field_info.field->is_inline()) {
throw Error("Field {} is dynamic/array/inline and can't be used with read_plain_data_field",
field_name);
}
@@ -36,7 +36,7 @@ void read_plain_data_field(const TypedRef& object,
const auto& words = object.ref.data->words_by_seg.at(object.ref.seg);
for (int byte = 0; byte < size_bytes; byte++) {
int byte_in_words = byte + object.ref.byte_offset + field_info.field.offset();
int byte_in_words = byte + object.ref.byte_offset + field_info.field->offset();
int word_idx = byte_in_words / 4;
int byte_in_word = byte_in_words % 4;
@@ -80,13 +80,13 @@ decompiler::LinkedWord::Kind get_word_kind_for_field(const TypedRef& object,
const decompiler::DecompilerTypeSystem& dts) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
if (field_info.field.is_dynamic() || field_info.field.is_array() ||
field_info.field.is_inline()) {
if (field_info.field->is_dynamic() || field_info.field->is_array() ||
field_info.field->is_inline()) {
throw Error("Field {} is dynamic/array/inline and can't be used with get_word_kind_for_field",
field_name);
}
int byte_in_words = object.ref.byte_offset + field_info.field.offset();
int byte_in_words = object.ref.byte_offset + field_info.field->offset();
if ((byte_in_words % 4) != 0) {
throw Error("Field {} was misaligned.", field_name);
}
@@ -100,8 +100,8 @@ TypedRef get_and_check_ref_to_basic(const TypedRef& object,
const decompiler::DecompilerTypeSystem& dts) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
if (field_info.field.is_dynamic() || field_info.field.is_array() ||
field_info.field.is_inline()) {
if (field_info.field->is_dynamic() || field_info.field->is_array() ||
field_info.field->is_inline()) {
throw Error(
"Field {} is dynamic/array/inline and can't be used with get_and_check_ref_to_basic",
field_name);
@@ -113,7 +113,7 @@ TypedRef get_and_check_ref_to_basic(const TypedRef& object,
throw Error("Field {} is not a basic and can't be used with read_plain_data_field", field_name);
}
int byte_in_words = object.ref.byte_offset + field_info.field.offset();
int byte_in_words = object.ref.byte_offset + field_info.field->offset();
if ((byte_in_words % 4) != 0) {
throw Error("Field {} was misaligned.", field_name);
}
@@ -156,8 +156,8 @@ std::string read_symbol_field(const TypedRef& object,
const decompiler::DecompilerTypeSystem& dts) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
if (field_info.field.is_dynamic() || field_info.field.is_array() ||
field_info.field.is_inline()) {
if (field_info.field->is_dynamic() || field_info.field->is_array() ||
field_info.field->is_inline()) {
throw Error("Field {} is dynamic/array/inline and can't be used with read_symbol_field",
field_name);
}
@@ -167,7 +167,7 @@ std::string read_symbol_field(const TypedRef& object,
field_info.type.print());
}
int byte_in_words = object.ref.byte_offset + field_info.field.offset();
int byte_in_words = object.ref.byte_offset + field_info.field->offset();
if ((byte_in_words % 4) != 0) {
throw Error("Field {} was misaligned.", field_name);
}
@@ -187,8 +187,8 @@ std::string read_type_field(const TypedRef& object,
bool ignore_field_type) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
if (field_info.field.is_dynamic() || field_info.field.is_array() ||
field_info.field.is_inline()) {
if (field_info.field->is_dynamic() || field_info.field->is_array() ||
field_info.field->is_inline()) {
throw Error("Field {} is dynamic/array/inline and can't be used with read_type_field",
field_name);
}
@@ -198,7 +198,7 @@ std::string read_type_field(const TypedRef& object,
field_info.type.print());
}
int byte_in_words = object.ref.byte_offset + field_info.field.offset();
int byte_in_words = object.ref.byte_offset + field_info.field->offset();
if ((byte_in_words % 4) != 0) {
throw Error("Field {} was misaligned.", field_name);
}
@@ -243,8 +243,8 @@ std::string read_string_field(const TypedRef& object,
bool ignore_field_type) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
if (field_info.field.is_dynamic() || field_info.field.is_array() ||
field_info.field.is_inline()) {
if (field_info.field->is_dynamic() || field_info.field->is_array() ||
field_info.field->is_inline()) {
throw Error("Field {} is dynamic/array/inline and can't be used with read_string_field",
field_name);
}
@@ -254,7 +254,7 @@ std::string read_string_field(const TypedRef& object,
field_info.type.print());
}
int byte_in_words = object.ref.byte_offset + field_info.field.offset();
int byte_in_words = object.ref.byte_offset + field_info.field->offset();
if ((byte_in_words % 4) != 0) {
throw Error("Field {} was misaligned.", field_name);
}
@@ -273,7 +273,7 @@ Ref get_field_ref(const TypedRef& object,
const decompiler::DecompilerTypeSystem& dts) {
FieldLookupInfo field_info = dts.ts.lookup_field_info(object.type->get_name(), field_name);
Ref result = object.ref;
result.byte_offset += field_info.field.offset();
result.byte_offset += field_info.field->offset();
return result;
}
+19 -18
View File
@@ -46,10 +46,10 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
field_name_def = field_name_def.substr(1);
auto field_info = m_ts.lookup_field_info(type_info->get_name(), field_name_def);
auto field_offset = field_info.field.offset() + offset;
auto field_offset = field_info.field->offset() + offset;
if (field_info.field.is_array()) {
bool is_inline = field_info.field.is_inline();
if (field_info.field->is_array()) {
bool is_inline = field_info.field->is_inline();
// for an array field, we only accept (new 'static 'array <type> ...)
if (!field_value.is_list()) {
@@ -85,20 +85,21 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
auto array_content_type = parse_typespec(new_form.at(3), env);
if (is_inline) {
if (field_info.field.type() != array_content_type) {
if (field_info.field->type() != array_content_type) {
throw_compiler_error(field_value, "Inline array field must have the correct type");
}
} else {
// allow more specific types.
// TODO make this better.
m_ts.typecheck_and_throw(field_info.field.type(), array_content_type, "Array content type");
m_ts.typecheck_and_throw(field_info.field->type(), array_content_type,
"Array content type");
}
s64 elt_array_len = get_constant_integer_or_error(new_form.at(4), env);
if (!field_info.field.is_dynamic() && elt_array_len != field_info.field.array_size()) {
if (!field_info.field->is_dynamic() && elt_array_len != field_info.field->array_size()) {
throw_compiler_error(field_value, "Array field had an expected size of {} but got {}",
field_info.field.array_size(), elt_array_len);
field_info.field->array_size(), elt_array_len);
}
auto arg_list = get_list_as_vector(field_value.as_pair()->cdr);
@@ -107,14 +108,14 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
}
if (is_inline) {
if (field_info.field.is_dynamic()) {
if (field_info.field->is_dynamic()) {
throw_compiler_error(form, "Dynamic fields are not supported for inline");
}
fill_static_inline_array_inline(field_value, field_info.field.type(), arg_list, structure,
fill_static_inline_array_inline(field_value, field_info.field->type(), arg_list, structure,
field_offset, env);
} else {
int num_elts = arg_list.size() - 4;
if (field_info.field.is_dynamic()) {
if (field_info.field->is_dynamic()) {
// need to resize data
// first, expected original size
int expected_data_size = type_info->get_size_in_memory();
@@ -124,7 +125,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
int increase_by = stride * num_elts;
structure->data.resize(expected_data_size + increase_by);
}
fill_static_array_inline(field_value, field_info.field.type(), arg_list.data() + 4,
fill_static_array_inline(field_value, field_info.field->type(), arg_list.data() + 4,
num_elts, structure, field_offset, env);
}
@@ -132,7 +133,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
ASSERT(field_info.needs_deref); // for now...
auto deref_info = m_ts.get_deref_info(m_ts.make_pointer_typespec(field_info.type));
ASSERT(field_offset + deref_info.load_size <= int(structure->data.size()));
ASSERT(!field_info.field.is_inline());
ASSERT(!field_info.field->is_inline());
auto sr = compile_static(field_value, env);
if (!sr.is_constant_data()) {
throw_compiler_error(form, "Could not use {} for an integer field", field_value.print());
@@ -153,10 +154,10 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
} else if (is_structure(field_info.type) || is_pair(field_info.type) ||
is_symbol(field_info.type) || field_info.type == TypeSpec("object")) {
if (is_pair(field_info.type)) {
ASSERT(!field_info.field.is_inline());
ASSERT(!field_info.field->is_inline());
}
if (field_info.field.is_inline()) {
if (field_info.field->is_inline()) {
// for an inline field, we only accept (new 'static '<type> ...)
if (!field_value.is_list()) {
throw_compiler_error(field_value, "Inline field was not properly specified");
@@ -200,7 +201,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
if (sr.is_symbol()) {
if (sr.symbol_name() != "#f" && sr.symbol_name() != "_empty_") {
typecheck(form, field_info.type, sr.typespec(),
fmt::format("Field {}, containing symbol {}", field_info.field.name(),
fmt::format("Field {}, containing symbol {}", field_info.field->name(),
sr.symbol_name()));
}
structure->add_symbol_record(sr.symbol_name(), field_offset);
@@ -232,7 +233,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
auto deref_info = m_ts.get_deref_info(m_ts.make_pointer_typespec(field_info.type));
auto field_size = deref_info.load_size;
ASSERT(field_offset + field_size <= int(structure->data.size()));
ASSERT(!field_info.field.is_inline());
ASSERT(!field_info.field->is_inline());
auto sr = compile_static(field_value, env);
if (!sr.is_constant_data()) {
throw_compiler_error(form, "Could not use {} for a float field", field_value.print());
@@ -254,7 +255,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
u32 linker_val = 0xffffffff;
memcpy(structure->data.data() + field_offset, &linker_val, 4);
} else if (!sr.is_reference()) {
throw_compiler_error(form, "Invalid definition of field {}", field_info.field.name());
throw_compiler_error(form, "Invalid definition of field {}", field_info.field->name());
} else {
typecheck(form, field_info.type, sr.typespec());
ASSERT(sr.reference()->get_addr_offset() == 0);
@@ -276,7 +277,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
memcpy(structure->data.data() + field_offset, &linker_val, 4);
} else {
if (!sr.is_reference()) {
throw_compiler_error(form, "Invalid definition of field {}", field_info.field.name());
throw_compiler_error(form, "Invalid definition of field {}", field_info.field->name());
}
typecheck(form, field_info.type, sr.typespec());
ASSERT(sr.reference()->get_addr_offset() == 0);
+2 -2
View File
@@ -658,7 +658,7 @@ Val* Compiler::get_field_of_structure(const StructureType* type,
if (field.needs_deref) {
TypeSpec loc_type = m_ts.make_pointer_typespec(field.type);
auto loc =
fe->alloc_val<MemoryOffsetConstantVal>(loc_type, object, field.field.offset() + offset);
fe->alloc_val<MemoryOffsetConstantVal>(loc_type, object, field.field->offset() + offset);
auto di = m_ts.get_deref_info(loc_type);
ASSERT(di.can_deref);
ASSERT(di.mem_deref);
@@ -669,7 +669,7 @@ Val* Compiler::get_field_of_structure(const StructureType* type,
field.type.base_type() == "inline-array" ? field.type.get_single_arg() : field.type;
auto field_type_info = m_ts.lookup_type(type_for_offset);
result = fe->alloc_val<MemoryOffsetConstantVal>(
field.type, object, field.field.offset() + offset + field_type_info->get_offset());
field.type, object, field.field->offset() + offset + field_type_info->get_offset());
result->mark_as_settable();
}
return result;
+1 -1
View File
@@ -352,7 +352,7 @@ TEST(TypeSystem, FieldLookup) {
TypeSystem ts;
ts.add_builtin_types(GameVersion::Jak1);
EXPECT_EQ(ts.lookup_field_info("type", "parent").field.offset(), 8);
EXPECT_EQ(ts.lookup_field_info("type", "parent").field->offset(), 8);
EXPECT_EQ(ts.lookup_field_info("string", "data").type.print(), "(pointer uint8)");
EXPECT_ANY_THROW(ts.lookup_field_info("type", "not-a-real-field"));