harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Mconfigure | 1+
Ainclude/typedef.h | 9+++++++++
Msrc/check.c | 1+
Msrc/main.c | 18++++++++++++++++--
Asrc/typedef.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 + } + } +}