mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-04-03 16:32:57 +00:00
fix access to fields of vector members
When ast_member encounters the result of an ast_entfield it has to replace the ast_entfield's codegen as we cannot evaluate the field access first. We then perform the same action as ast_entfield but call vectorMember on the field before issuing the load/address instruction. This effectively turns the codegen of the following ast structure: member_of { field_of { entity, a_vector } memberid } into the one of this structure: field_of { entity, member_of { a_vector memberid } }
This commit is contained in:
parent
4c48bae203
commit
0b94d7583c
3 changed files with 53 additions and 3 deletions
38
ast.cpp
38
ast.cpp
|
@ -2098,13 +2098,45 @@ bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out)
|
|||
compile_error(m_context, "not an l-value (member access)");
|
||||
return false;
|
||||
}
|
||||
if (m_outl) {
|
||||
if (lvalue && m_outl) {
|
||||
*out = m_outl;
|
||||
return true;
|
||||
}
|
||||
if (!lvalue && m_outr) {
|
||||
*out = m_outr;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_owner->codegen(func, false, &vec))
|
||||
return false;
|
||||
if (ast_istype(m_owner, ast_entfield)) {
|
||||
ir_value *ent, *field;
|
||||
auto entfield = reinterpret_cast<ast_entfield*>(m_owner);
|
||||
if (!entfield->m_entity->codegen(func, false, &ent))
|
||||
return false;
|
||||
if (!entfield->m_field->codegen(func, false, &vec))
|
||||
return false;
|
||||
field = vec->vectorMember(m_field);
|
||||
if (lvalue) {
|
||||
*out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("mefa"),
|
||||
ent, field);
|
||||
} else {
|
||||
*out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("mefv"),
|
||||
ent, field, m_vtype);
|
||||
}
|
||||
if (!*out) {
|
||||
compile_error(m_context, "failed to create %s instruction (output type %s)",
|
||||
(lvalue ? "ADDRESS" : "FIELD"),
|
||||
type_name[m_vtype]);
|
||||
return false;
|
||||
}
|
||||
if (lvalue)
|
||||
m_outl = *out;
|
||||
else
|
||||
m_outr = *out;
|
||||
return (*out != nullptr);
|
||||
} else {
|
||||
if (!m_owner->codegen(func, false, &vec))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vec->m_vtype != TYPE_VECTOR &&
|
||||
!(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))
|
||||
|
|
13
tests/vecfields.qc
Normal file
13
tests/vecfields.qc
Normal file
|
@ -0,0 +1,13 @@
|
|||
.vector v1;
|
||||
|
||||
float set(entity e, float v) {
|
||||
e.v1.y = v;
|
||||
return e.v1.y;
|
||||
}
|
||||
|
||||
void main() {
|
||||
entity e = spawn();
|
||||
e.v1 = '1 2 3';
|
||||
print(ftos(set(e, 42)), " => ");
|
||||
print(vtos(e.v1), "\n");
|
||||
}
|
5
tests/vecfields.tmpl
Normal file
5
tests/vecfields.tmpl
Normal file
|
@ -0,0 +1,5 @@
|
|||
I: vecfields.qc
|
||||
D: vector field member accesses
|
||||
T: -execute
|
||||
C: -std=gmqcc -fftepp
|
||||
M: 42 => '1 42 3'
|
Loading…
Reference in a new issue