aboutsummaryrefslogtreecommitdiff
path: root/structs.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-03-18 14:11:56 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-03-18 14:11:56 -0400
commitd94c1057accb197ec3b957fb91ff75597ac54c40 (patch)
treec47be271bc392b9169eec84bfb8d27db8334af74 /structs.c
parentbff3666d604972f1f38f15c49388cd39d08bee88 (diff)
Improve codegen for enums by eliminating unnecessary methods
Diffstat (limited to 'structs.c')
-rw-r--r--structs.c52
1 files changed, 21 insertions, 31 deletions
diff --git a/structs.c b/structs.c
index cebc9a77..51cc7c93 100644
--- a/structs.c
+++ b/structs.c
@@ -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);