Skip to content

Commit

Permalink
Emit proper code for dynamic member access
Browse files Browse the repository at this point in the history
  • Loading branch information
RobDangerous committed Aug 27, 2024
1 parent e541900 commit 86cf632
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 48 deletions.
19 changes: 12 additions & 7 deletions Sources/backends/cstyle.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ void cstyle_write_opcode(char *code, size_t *offset, opcode *o, type_string_func
break;
case OPCODE_NOT:
indent(code, offset, *indentation);
*offset +=
sprintf(&code[*offset], "%s _%" PRIu64 " = !_%" PRIu64 ";\n", type_string(o->op_not.to.type.type), o->op_not.to.index, o->op_not.from.index);
*offset += sprintf(&code[*offset], "%s _%" PRIu64 " = !_%" PRIu64 ";\n", type_string(o->op_not.to.type.type), o->op_not.to.index, o->op_not.from.index);
break;
case OPCODE_STORE_VARIABLE:
indent(code, offset, *indentation);
Expand Down Expand Up @@ -84,15 +83,21 @@ void cstyle_write_opcode(char *code, size_t *offset, opcode *o, type_string_func
bool is_array = o->op_store_member.member_parent_array;
for (size_t i = 0; i < o->op_store_member.member_indices_size; ++i) {
if (is_array) {
*offset += sprintf(&code[*offset], "[%i]", o->op_store_member.member_indices[i]);
if (o->op_store_member.dynamic_member[i]) {
*offset += sprintf(&code[*offset], "[_% " PRIu64 "]", o->op_store_member.dynamic_member_indices[i].index);
}
else {
*offset += sprintf(&code[*offset], "[%i]", o->op_store_member.static_member_indices[i]);
}
is_array = false;
}
else {
debug_context context = {0};
check(o->op_store_member.member_indices[i] < s->members.size, context, "Member index out of bounds");
*offset += sprintf(&code[*offset], ".%s", member_string(s, s->members.m[o->op_store_member.member_indices[i]].name));
is_array = s->members.m[o->op_store_member.member_indices[i]].type.array_size > 0;
s = get_type(s->members.m[o->op_store_member.member_indices[i]].type.type);
check(!o->op_store_member.dynamic_member[i], context, "Unexpected dynamic member");
check(o->op_store_member.static_member_indices[i] < s->members.size, context, "Member index out of bounds");
*offset += sprintf(&code[*offset], ".%s", member_string(s, s->members.m[o->op_store_member.static_member_indices[i]].name));
is_array = s->members.m[o->op_store_member.static_member_indices[i]].type.array_size > 0;
s = get_type(s->members.m[o->op_store_member.static_member_indices[i]].type.type);
}
}
switch (o->type) {
Expand Down
13 changes: 7 additions & 6 deletions Sources/backends/spirv.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ static spirv_id write_op_f_ord_less_than(instructions_buffer *instructions, spir
spirv_id result = allocate_index();

uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};

write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_ORD_LESS_THAN, operands);

return result;
Expand Down Expand Up @@ -790,7 +790,7 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
hmput(index_map, o->op_var.var.index, result);
break;
}
default:
default:
break;
}

Expand Down Expand Up @@ -896,7 +896,8 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
int indices[256];
uint16_t indices_size = o->op_store_member.member_indices_size;
for (size_t i = 0; i < indices_size; ++i) {
indices[i] = (int)o->op_store_member.member_indices[i];
check(!o->op_store_member.dynamic_member[i], context, "TODO");
indices[i] = (int)o->op_store_member.static_member_indices[i];
}

type_id access_kong_type = find_access_type(indices, indices_size, o->op_store_member.to.type.type);
Expand Down Expand Up @@ -988,8 +989,8 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
case OPCODE_IF: {
write_op_selection_merge(instructions, convert_kong_index_to_spirv_id(o->op_if.end_id), SELECTION_CONTROL_NONE);

write_op_branch_conditional(instructions, convert_kong_index_to_spirv_id(o->op_if.condition.index), convert_kong_index_to_spirv_id(o->op_if.start_id),
convert_kong_index_to_spirv_id(o->op_if.end_id));
write_op_branch_conditional(instructions, convert_kong_index_to_spirv_id(o->op_if.condition.index),
convert_kong_index_to_spirv_id(o->op_if.start_id), convert_kong_index_to_spirv_id(o->op_if.end_id));

break;
}
Expand All @@ -1000,7 +1001,7 @@ static void write_function(instructions_buffer *instructions, function *f, spirv

write_op_branch(instructions, while_start_label);
write_op_label_preallocated(instructions, while_start_label);

write_op_loop_merge(instructions, while_end_label, while_continue_label, LOOP_CONTROL_NONE);

spirv_id loop_start_id = allocate_index();
Expand Down
60 changes: 38 additions & 22 deletions Sources/backends/wgsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ static void write_functions(char *code, size_t *offset) {
sprintf(&code[*offset], "_%" PRIu64 ": %s", parameter_ids[parameter_index], type_string(f->parameter_types[parameter_index].type));
}
else {
*offset +=
sprintf(&code[*offset], ", _%" PRIu64 ": %s", parameter_ids[parameter_index], type_string(f->parameter_types[parameter_index].type));
*offset += sprintf(&code[*offset], ", _%" PRIu64 ": %s", parameter_ids[parameter_index],
type_string(f->parameter_types[parameter_index].type));
}
}
*offset += sprintf(&code[*offset], ") -> @location(0) %s {\n", type_string(f->return_type.type));
Expand Down Expand Up @@ -413,8 +413,8 @@ static void write_functions(char *code, size_t *offset) {
}

indent(code, offset, indentation);
*offset += sprintf(&code[*offset], "var _%" PRIu64 ": %s = _%" PRIu64, o->op_load_member.to.index,
type_string(o->op_load_member.to.type.type), o->op_load_member.from.index);
*offset += sprintf(&code[*offset], "var _%" PRIu64 ": %s = _%" PRIu64, o->op_load_member.to.index, type_string(o->op_load_member.to.type.type),
o->op_load_member.from.index);
type *s = get_type(o->op_load_member.member_parent_type);
for (size_t i = 0; i < o->op_load_member.member_indices_size; ++i) {
*offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name));
Expand All @@ -432,17 +432,21 @@ static void write_functions(char *code, size_t *offset) {
char *last_member_name = NULL;
for (size_t i = 0; i < o->op_store_member.member_indices_size; ++i) {
if (i == o->op_store_member.member_indices_size - 1) {
last_member_name = get_name(s->members.m[o->op_store_member.member_indices[i]].name);
if (!o->op_store_member.dynamic_member[i]) {
last_member_name = get_name(s->members.m[o->op_store_member.static_member_indices[i]].name);
}
}

type_id t = s->members.m[o->op_store_member.member_indices[i]].type.type;
s = get_type(t);
if (!o->op_store_member.dynamic_member[i]) {
type_id t = s->members.m[o->op_store_member.static_member_indices[i]].type.type;
s = get_type(t);

if (i == o->op_store_member.member_indices_size - 2) {
last_last_type = t;
}
else if (i == o->op_store_member.member_indices_size - 1) {
last_type = t;
if (i == o->op_store_member.member_indices_size - 2) {
last_last_type = t;
}
else if (i == o->op_store_member.member_indices_size - 1) {
last_type = t;
}
}
}

Expand Down Expand Up @@ -471,20 +475,26 @@ static void write_functions(char *code, size_t *offset) {
bool is_array = o->op_store_member.member_parent_array;
for (size_t i = 0; i < o->op_store_member.member_indices_size; ++i) {
if (is_array) {
*offset += sprintf(&code[*offset], "[%i]", o->op_store_member.member_indices[i]);
if (o->op_store_member.dynamic_member[i]) {
*offset += sprintf(&code[*offset], "[_%" PRIu64 "]", o->op_store_member.dynamic_member_indices[i].index);
}
else {
*offset += sprintf(&code[*offset], "[%i]", o->op_store_member.static_member_indices[i]);
}
is_array = false;
}
else {
debug_context context = {0};
check(o->op_store_member.member_indices[i] < s->members.size, context, "Member index out of bounds");
check(!o->op_store_member.dynamic_member[i], context, "Unexpected dynamic member");
check(o->op_store_member.static_member_indices[i] < s->members.size, context, "Member index out of bounds");
if (i == o->op_store_member.member_indices_size - 1) {
*offset += sprintf(&code[*offset], ".%c", last_member_name[element]);
}
else {
*offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_store_member.member_indices[i]].name));
*offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_store_member.static_member_indices[i]].name));
}
is_array = s->members.m[o->op_store_member.member_indices[i]].type.array_size > 0;
s = get_type(s->members.m[o->op_store_member.member_indices[i]].type.type);
is_array = s->members.m[o->op_store_member.static_member_indices[i]].type.array_size > 0;
s = get_type(s->members.m[o->op_store_member.static_member_indices[i]].type.type);
}
}
*offset += sprintf(&code[*offset], " = _%" PRIu64 ".%c;\n", o->op_store_member.from.index, last_member_name[element]);
Expand All @@ -501,15 +511,21 @@ static void write_functions(char *code, size_t *offset) {
bool is_array = o->op_store_member.member_parent_array;
for (size_t i = 0; i < o->op_store_member.member_indices_size; ++i) {
if (is_array) {
*offset += sprintf(&code[*offset], "[%i]", o->op_store_member.member_indices[i]);
if (o->op_store_member.dynamic_member[i]) {
*offset += sprintf(&code[*offset], "[_%" PRIu64 "]", o->op_store_member.dynamic_member_indices[i].index);
}
else {
*offset += sprintf(&code[*offset], "[%i]", o->op_store_member.static_member_indices[i]);
}
is_array = false;
}
else {
debug_context context = {0};
check(o->op_store_member.member_indices[i] < s->members.size, context, "Member index out of bounds");
*offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_store_member.member_indices[i]].name));
is_array = s->members.m[o->op_store_member.member_indices[i]].type.array_size > 0;
s = get_type(s->members.m[o->op_store_member.member_indices[i]].type.type);
check(!o->op_store_member.dynamic_member[i], context, "Unexpected dynamic member");
check(o->op_store_member.static_member_indices[i] < s->members.size, context, "Member index out of bounds");
*offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_store_member.static_member_indices[i]].name));
is_array = s->members.m[o->op_store_member.static_member_indices[i]].type.array_size > 0;
s = get_type(s->members.m[o->op_store_member.static_member_indices[i]].type.type);
}
}
*offset += sprintf(&code[*offset], " = _%" PRIu64 ";\n", o->op_store_member.from.index);
Expand Down
37 changes: 25 additions & 12 deletions Sources/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ variable emit_expression(opcodes *code, block *parent, expression *e) {
emit_op(code, &o);
break;
}
case EXPRESSION_STATIC_MEMBER: {
case EXPRESSION_STATIC_MEMBER:
case EXPRESSION_DYNAMIC_MEMBER: {
variable member_var = emit_expression(code, parent, left->member.left);

opcode o;
Expand Down Expand Up @@ -285,17 +286,20 @@ variable emit_expression(opcodes *code, block *parent, expression *e) {
type_id prev_struct = left->member.left->type.type;
type *prev_s = get_type(prev_struct);
o.op_store_member.member_parent_type = prev_struct;
o.op_store_member.member_parent_array = left->member.left->type.array_size > 0;
o.op_store_member.member_parent_array = left->member.left->type.array_size > 0 || left->member.left->type.type == tex2d_type_id;

while (right->kind == EXPRESSION_STATIC_MEMBER) {
bool parent_dynamic = left->kind == EXPRESSION_DYNAMIC_MEMBER;

while (right->kind == EXPRESSION_STATIC_MEMBER || right->kind == EXPRESSION_DYNAMIC_MEMBER) {
debug_context context = {0};
check(right->type.type != NO_TYPE, context, "Part of the member does not have a type");

if (right->member.left->kind == EXPRESSION_VARIABLE) {
if (right->member.left->kind == EXPRESSION_VARIABLE && !parent_dynamic) {
bool found = false;
for (size_t i = 0; i < prev_s->members.size; ++i) {
if (prev_s->members.m[i].name == right->member.left->variable) {
o.op_store_member.member_indices[o.op_store_member.member_indices_size] = (uint16_t)i;
o.op_store_member.dynamic_member[o.op_store_member.member_indices_size] = false;
o.op_store_member.static_member_indices[o.op_store_member.member_indices_size] = (uint16_t)i;
++o.op_store_member.member_indices_size;
found = true;
break;
Expand All @@ -304,27 +308,32 @@ variable emit_expression(opcodes *code, block *parent, expression *e) {
check(found, context, "Variable for a member not found");
}
else if (right->member.left->kind == EXPRESSION_INDEX) {
o.op_store_member.member_indices[o.op_store_member.member_indices_size] = (uint16_t)right->member.left->index;
o.op_store_member.dynamic_member[o.op_store_member.member_indices_size] = false;
o.op_store_member.static_member_indices[o.op_store_member.member_indices_size] = (uint16_t)right->member.left->index;
++o.op_store_member.member_indices_size;
}
else {
debug_context context = {0};
error(context, "Malformed member construct");
variable sub_expression = emit_expression(code, parent, right->member.left);
o.op_store_member.dynamic_member[o.op_store_member.member_indices_size] = true;
o.op_store_member.dynamic_member_indices[o.op_store_member.member_indices_size] = sub_expression;
++o.op_store_member.member_indices_size;
}

prev_struct = right->member.left->type.type;
prev_s = get_type(prev_struct);
parent_dynamic = right->kind == EXPRESSION_DYNAMIC_MEMBER;
right = right->member.right;
}

{
debug_context context = {0};
check(right->type.type != NO_TYPE, context, "Part of the member does not have a type");
if (right->kind == EXPRESSION_VARIABLE) {
if (right->kind == EXPRESSION_VARIABLE && !parent_dynamic) {
bool found = false;
for (size_t i = 0; i < prev_s->members.size; ++i) {
if (prev_s->members.m[i].name == right->variable) {
o.op_store_member.member_indices[o.op_store_member.member_indices_size] = (uint16_t)i;
o.op_store_member.dynamic_member[o.op_store_member.member_indices_size] = false;
o.op_store_member.static_member_indices[o.op_store_member.member_indices_size] = (uint16_t)i;
++o.op_store_member.member_indices_size;
found = true;
break;
Expand All @@ -333,11 +342,15 @@ variable emit_expression(opcodes *code, block *parent, expression *e) {
check(found, context, "Member not found");
}
else if (right->kind == EXPRESSION_INDEX) {
o.op_store_member.member_indices[o.op_store_member.member_indices_size] = (uint16_t)right->index;
o.op_store_member.dynamic_member[o.op_store_member.member_indices_size] = false;
o.op_store_member.static_member_indices[o.op_store_member.member_indices_size] = (uint16_t)right->index;
++o.op_store_member.member_indices_size;
}
else {
error(context, "Malformed member construct");
variable sub_expression = emit_expression(code, parent, right);
o.op_store_member.dynamic_member[o.op_store_member.member_indices_size] = true;
o.op_store_member.dynamic_member_indices[o.op_store_member.member_indices_size] = sub_expression;
++o.op_store_member.member_indices_size;
}
}

Expand Down
4 changes: 3 additions & 1 deletion Sources/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ typedef struct opcode {
struct {
variable from;
variable to;
uint16_t member_indices[64];
bool dynamic_member[64];
variable dynamic_member_indices[64];
uint32_t static_member_indices[64];
type_id member_parent_type;
bool member_parent_array;
uint8_t member_indices_size;
Expand Down

0 comments on commit 86cf632

Please sign in to comment.