Skip to content

Commit

Permalink
#74 add support for structs with flexible array member
Browse files Browse the repository at this point in the history
  • Loading branch information
dibyendumajumdar committed Nov 12, 2021
1 parent 2d1cc9b commit ae566b2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 19 deletions.
65 changes: 47 additions & 18 deletions src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -2967,6 +2967,45 @@ static int emit_op_C__unsafe(Function *fn, Instruction *insn)
return 0;
}

static C_Type *get_typeof(Function *fn, C_Scope *global_scope, Pseudo *tagname) {
C_Type *ty = hashmap_get(&global_scope->tags, tagname->constant->s->str);
if (ty == NULL) {
C_VarScope *vc = hashmap_get(&global_scope->vars, tagname->constant->s->str);
if (vc && vc->type_def) {
ty = vc->type_def;
} else {
TextBuffer message;
raviX_buffer_init(&message, 128);
raviX_buffer_add_fstring(&message, "Unknown type '%s'", tagname->constant->s->str);
fn->api->error_message(fn->api->context, message.buf);
raviX_buffer_free(&message);
return NULL;
}
}
return ty;
}

static C_Member *get_flexible_member(C_Type *type) {
if (type->kind != TY_STRUCT)
return NULL;
C_Member *last_member = NULL;
for (C_Member *m = type->members; m != NULL; m = m->next)
last_member = m;
if (last_member->ty->kind == TY_ARRAY && last_member->ty->array_len == 0) {
return last_member;
}
return NULL;
}

static void emit_sizeof_expression(Function *fn, const char *main_type, C_Member *flexible_member) {
raviX_buffer_add_fstring(&fn->body, "sizeof(%s)", main_type);
if (flexible_member != NULL) {
raviX_buffer_add_fstring(&fn->body, " + (sizeof ((%s *)0)->%.*s[0])", main_type,
flexible_member->name->len,
flexible_member->name->loc);
}
}

static int emit_op_C__new(Function *fn, Instruction *insn)
{
LinearizerState *linearizer = fn->proc->linearizer;
Expand Down Expand Up @@ -2999,23 +3038,10 @@ static int emit_op_C__new(Function *fn, Instruction *insn)
Pseudo *size = get_operand(insn, 1);
Pseudo *target = get_target(insn, 0);
// Add utility in chibicc to find a type
C_Type *ty = hashmap_get(&global_scope->tags, tagname->constant->s->str);
size_t tagsz = 0;
if (ty != NULL) {
tagsz = ty->size;
} else {
C_VarScope *vc = hashmap_get(&global_scope->vars, tagname->constant->s->str);
if (vc && vc->type_def) {
tagsz = vc->type_def->size;
} else {
TextBuffer message;
raviX_buffer_init(&message, 128);
raviX_buffer_add_fstring(&message, "Unknown type '%s'", tagname->constant->s->str);
fn->api->error_message(fn->api->context, message.buf);
raviX_buffer_free(&message);
goto Lexit;
}
}
C_Type *ty = get_typeof(fn, global_scope, tagname);
if (ty == NULL)
goto Lexit;
C_Member *flexible_member = get_flexible_member(ty);

raviX_buffer_add_string(&fn->body, "{\n");
raviX_buffer_add_string(&fn->body, " TValue *raviX__elements = ");
Expand All @@ -3027,7 +3053,10 @@ static int emit_op_C__new(Function *fn, Instruction *insn)

raviX_buffer_add_string(&fn->body, " if (ttisinteger(raviX__elements)) {\n");
raviX_buffer_add_string(&fn->body, " lua_Integer n = ivalue(raviX__elements);\n");
raviX_buffer_add_fstring(&fn->body, " Udata *u = luaS_newudata(L, %d * n);\n", (int)tagsz);
raviX_buffer_add_fstring(&fn->body, " size_t raviX__size = ");
emit_sizeof_expression(fn, tagname->constant->s->str, flexible_member);
raviX_buffer_add_fstring(&fn->body, "* n;\n");
raviX_buffer_add_fstring(&fn->body, " Udata *u = luaS_newudata(L, raviX__size);\n");
raviX_buffer_add_string(&fn->body, " setuvalue(L, raviX__target, u);\n");
raviX_buffer_add_string(&fn->body, " }\n");
raviX_buffer_add_string(&fn->body, " else {\n");
Expand Down
4 changes: 3 additions & 1 deletion tests/input/t10_embed_C.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
C__decl [[
typedef struct MyStruct {
int a;
long a;
int variable_length[];
} MyStruct;
]]

Expand All @@ -9,6 +10,7 @@ function demo(u: Userdata)
C__unsafe(u) [[
MyStruct *s = (MyStruct *) u.ptr;
]]
local u1 = C__new('MyStruct',1)

end
#
Expand Down

0 comments on commit ae566b2

Please sign in to comment.