mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
Allow setting a field with partially defined field (#646)
* allow setting a field with partially defined field * actually run the test
This commit is contained in:
parent
385b8b5785
commit
2ee48e08f3
|
@ -453,6 +453,27 @@ Type* TypeSystem::lookup_type_allow_partial_def(const std::string& name) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get load size for a type. Will succeed if one of the two conditions is true:
|
||||
* - Is a fully defined type.
|
||||
* - Is partially defined, but structure is in the parent.
|
||||
* This should be safe to use to load a value from a field.
|
||||
*/
|
||||
int TypeSystem::get_load_size_allow_partial_def(const TypeSpec& ts) const {
|
||||
auto fully_defined_it = m_types.find(ts.base_type());
|
||||
if (fully_defined_it != m_types.end()) {
|
||||
return fully_defined_it->second->get_load_size();
|
||||
}
|
||||
|
||||
auto partial_def = lookup_type_allow_partial_def(ts);
|
||||
if (!tc(TypeSpec("structure"), ts)) {
|
||||
throw_typesystem_error("Cannot perform a load or store from partially defined type {}",
|
||||
ts.print());
|
||||
}
|
||||
assert(partial_def->get_load_size() == 4);
|
||||
return partial_def->get_load_size();
|
||||
}
|
||||
|
||||
MethodInfo TypeSystem::declare_method(const std::string& type_name,
|
||||
const std::string& method_name,
|
||||
bool no_virtual,
|
||||
|
|
|
@ -154,6 +154,8 @@ class TypeSystem {
|
|||
Type* lookup_type_allow_partial_def(const TypeSpec& ts) const;
|
||||
Type* lookup_type_allow_partial_def(const std::string& name) const;
|
||||
|
||||
int get_load_size_allow_partial_def(const TypeSpec& ts) const;
|
||||
|
||||
MethodInfo declare_method(const std::string& type_name,
|
||||
const std::string& method_name,
|
||||
bool no_virtual,
|
||||
|
|
|
@ -237,17 +237,15 @@ Val* Compiler::do_set(const goos::Object& form, Val* dest, RegVal* src_in_reg, V
|
|||
// setting somewhere in memory
|
||||
auto base = as_mem_deref->base;
|
||||
auto base_as_mco = dynamic_cast<MemoryOffsetConstantVal*>(base);
|
||||
int load_size = m_ts.get_load_size_allow_partial_def(as_mem_deref->type());
|
||||
if (base_as_mco) {
|
||||
// if it is a constant offset, we can use a fancy x86-64 addressing mode to simplify
|
||||
auto ti = m_ts.lookup_type(as_mem_deref->type());
|
||||
env->emit(std::make_unique<IR_StoreConstOffset>(
|
||||
src_in_reg, base_as_mco->offset, base_as_mco->base->to_gpr(env), ti->get_load_size()));
|
||||
env->emit(std::make_unique<IR_StoreConstOffset>(src_in_reg, base_as_mco->offset,
|
||||
base_as_mco->base->to_gpr(env), load_size));
|
||||
return src_in_reg;
|
||||
} else {
|
||||
// nope, the pointer to dereference is some complicated thing.
|
||||
auto ti = m_ts.lookup_type(as_mem_deref->type());
|
||||
env->emit(std::make_unique<IR_StoreConstOffset>(src_in_reg, 0, base->to_gpr(env),
|
||||
ti->get_load_size()));
|
||||
env->emit(std::make_unique<IR_StoreConstOffset>(src_in_reg, 0, base->to_gpr(env), load_size));
|
||||
return src_in_reg;
|
||||
}
|
||||
} else if (as_pair) {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
(declare-type fake-type basic)
|
||||
(deftype type-containing-fake-type (basic)
|
||||
((field fake-type))
|
||||
)
|
||||
|
||||
(let ((obj (new 'stack 'type-containing-fake-type)))
|
||||
(-> obj field)
|
||||
(set! (-> obj field) (the fake-type #f))
|
||||
(format #t "~A~%" (-> obj field))
|
||||
)
|
|
@ -545,6 +545,12 @@ TEST_F(WithGameTests, InlinedPackedBasics) {
|
|||
"0\n"});
|
||||
}
|
||||
|
||||
TEST_F(WithGameTests, PartialDefineTypeField) {
|
||||
runner.run_static_test(env, testCategory, "test-partial-define-type-field.gc",
|
||||
{"#f\n"
|
||||
"0\n"});
|
||||
}
|
||||
|
||||
// VECTOR FLOAT TESTS
|
||||
|
||||
// ---- One off Tests
|
||||
|
|
Loading…
Reference in a new issue