commit f18d5152969b68aba46c3bf4cdd535f98871d47d
parent 7baef61a2fd12be1bb3de899fa87233b147810ff
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 20 Jan 2021 15:52:04 -0500
Initial support for typedef generation
Diffstat:
5 files changed, 124 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
@@ -19,6 +19,7 @@ harec() {
src/scope.c \
src/trace.c \
src/type_store.c \
+ src/typedef.c \
src/types.c \
src/utf8.c \
src/util.c
diff --git a/include/typedef.h b/include/typedef.h
@@ -0,0 +1,9 @@
+#ifndef HARE_TYPEDEF_H
+#define HARE_TYPEDEF_H
+#include <stdio.h>
+
+struct unit;
+
+void emit_typedefs(struct unit *unit, FILE *out);
+
+#endif
diff --git a/src/check.c b/src/check.c
@@ -1425,6 +1425,7 @@ scan_type(struct context *ctx, const struct ast_type_decl *decl)
struct identifier ident = {0};
mkident(ctx, &ident, &decl->ident);
scope_insert(ctx->unit, O_TYPE, &ident, &decl->ident, type, NULL);
+
if (type->storage == TYPE_STORAGE_ENUM) {
for (struct type_enum_value *value = type->_enum.values; value;
value = value->next) {
diff --git a/src/main.c b/src/main.c
@@ -11,6 +11,7 @@
#include "lex.h"
#include "parse.h"
#include "qbe.h"
+#include "typedef.h"
#include "util.h"
static void
@@ -53,7 +54,7 @@ parse_stage(const char *s)
int
main(int argc, char *argv[])
{
- char *output = NULL;
+ char *output = NULL, *typedefs = NULL;
struct unit unit = {0};
struct lexer lexer;
@@ -66,7 +67,8 @@ main(int argc, char *argv[])
case 'T':
assert(0); // TODO: Build tags
case 't':
- assert(0); // TODO: Typedefs
+ typedefs = optarg;
+ break;
case 'N':
unit.ns = xcalloc(1, sizeof(struct identifier));
FILE *in = fmemopen(optarg, strlen(optarg), "r");
@@ -131,6 +133,17 @@ main(int argc, char *argv[])
return 0;
}
+ if (typedefs) {
+ FILE *out = fopen(typedefs, "w");
+ if (!out) {
+ fprintf(stderr, "Unable to open %s for writing: %s\n",
+ typedefs, strerror(errno));
+ return 1;
+ }
+ emit_typedefs(&unit, out);
+ fclose(out);
+ }
+
struct qbe_program prog = {0};
gen(&unit, &prog);
if (stage == STAGE_GEN) {
@@ -149,5 +162,6 @@ main(int argc, char *argv[])
}
}
emit(&prog, out);
+ fclose(out);
return 0;
}
diff --git a/src/typedef.c b/src/typedef.c
@@ -0,0 +1,97 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "check.h"
+#include "identifier.h"
+#include "typedef.h"
+
+static void
+emit_type(const struct type *type, FILE *out)
+{
+ if (type->flags & TYPE_CONST) {
+ fprintf(out, "const ");
+ }
+
+ switch (type->storage) {
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_NULL:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ case TYPE_STORAGE_VOID:
+ fprintf(out, "%s", type_storage_unparse(type->storage));
+ break;
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ assert(0); // TODO
+ }
+}
+
+static void
+emit_func(struct declaration *decl, FILE *out)
+{
+ char *ident = identifier_unparse(&decl->ident); // TODO: Emit @symbol
+
+ const struct type *fntype = decl->func.type;
+ fprintf(out, "export%s fn %s(",
+ (fntype->func.flags & FN_NORETURN) ? " @noreturn" : "",
+ ident);
+
+ for (struct type_func_param *param = fntype->func.params;
+ param; param = param->next) {
+ emit_type(param->type, out);
+ if (param->next) {
+ fprintf(out, ", ");
+ }
+ }
+
+ fprintf(out, ") ");
+ emit_type(fntype->func.result, out);
+ fprintf(out, ";\n");
+ free(ident);
+}
+
+void
+emit_typedefs(struct unit *unit, FILE *out)
+{
+ for (struct declarations *decls = unit->declarations;
+ decls; decls = decls->next) {
+ struct declaration *decl = decls->decl;
+ if (!decl->exported) {
+ continue;
+ }
+
+ switch (decl->type) {
+ case DECL_FUNC:
+ emit_func(decl, out);
+ break;
+ case DECL_TYPE:
+ assert(0); // TODO
+ case DECL_GLOBAL:
+ assert(0); // TODO
+ case DECL_CONSTANT:
+ assert(0); // TODO
+ }
+ }
+}