diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-03-18 14:11:56 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-03-18 14:11:56 -0400 |
| commit | d94c1057accb197ec3b957fb91ff75597ac54c40 (patch) | |
| tree | c47be271bc392b9169eec84bfb8d27db8334af74 /structs.c | |
| parent | bff3666d604972f1f38f15c49388cd39d08bee88 (diff) | |
Improve codegen for enums by eliminating unnecessary methods
Diffstat (limited to 'structs.c')
| -rw-r--r-- | structs.c | 52 |
1 files changed, 21 insertions, 31 deletions
@@ -11,30 +11,6 @@ #include "typecheck.h" #include "builtins/util.h" -static bool is_plain_data(env_t *env, type_t *t) -{ - switch (t->tag) { - case BoolType: case IntType: case NumType: case PointerType: case FunctionType: - return true; - case StructType: { - for (arg_t *arg = Match(t, StructType)->fields; arg; arg = arg->next) { - if (!is_plain_data(env, get_arg_type(env, arg))) - return false; - } - return true; - } - case EnumType: { - for (tag_t *tag = Match(t, EnumType)->tags; tag; tag = tag->next) { - if (!is_plain_data(env, tag->type)) - return false; - } - return true; - } - default: - return false; - } -} - static CORD compile_str_method(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); @@ -152,24 +128,38 @@ void compile_struct_def(env_t *env, ast_t *ast) CORD_appendf(&env->code->typedefs, "extern const TypeInfo %r;\n", full_name); type_t *t = Table_str_get(*env->types, def->name); + assert(t && t->tag == StructType); + auto struct_ = Match(t, StructType); CORD typeinfo = CORD_asprintf("public const TypeInfo %r = {%zu, %zu, {.tag=CustomInfo, .CustomInfo={", full_name, type_size(t), type_align(t)); typeinfo = CORD_all(typeinfo, ".as_text=(void*)", full_name, "$as_text, "); env->code->funcs = CORD_all(env->code->funcs, compile_str_method(env, ast)); - if (t->tag != StructType || Match(t, StructType)->fields) { - typeinfo = CORD_all(typeinfo, ".compare=(void*)", full_name, "$compare, "); - env->code->funcs = CORD_all(env->code->funcs, compile_compare_method(env, ast)); + + if (struct_->fields && !struct_->fields->next) { // Single member, can just use its methods + type_t *member_t = struct_->fields->type; + switch (member_t->tag) { + case TextType: + typeinfo = CORD_all(typeinfo, ".hash=(void*)", type_to_cord(member_t), "__hash", ", "); + // fallthrough + case IntType: case NumType: + typeinfo = CORD_all(typeinfo, ".compare=(void*)", type_to_cord(member_t), "__compare, " + ".equal=(void*)", type_to_cord(member_t), "__equal, "); + // fallthrough + case BoolType: goto got_methods; + default: break; + } } - if (!t || !is_plain_data(env, t)) { - env->code->funcs = CORD_all( - env->code->funcs, compile_equals_method(env, ast), - compile_hash_method(env, ast)); + if (struct_->fields) { + env->code->funcs = CORD_all(env->code->funcs, compile_compare_method(env, ast), + compile_equals_method(env, ast), compile_hash_method(env, ast)); typeinfo = CORD_all( typeinfo, + ".compare=(void*)", full_name, "$compare, " ".equal=(void*)", full_name, "$equal, " ".hash=(void*)", full_name, "$hash"); } + got_methods:; typeinfo = CORD_cat(typeinfo, "}}};\n"); env->code->typeinfos = CORD_all(env->code->typeinfos, typeinfo); |
