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:
water111 2021-06-28 19:20:36 -04:00 committed by GitHub
parent 385b8b5785
commit 2ee48e08f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 6 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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) {

View file

@ -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))
)

View file

@ -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