harec

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

commit 83effe96530902378e457ffd20335865bb93d552
parent 7b8980d2534d02e53c6a7aa1aa6b8b9cce3e4076
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun,  4 Jul 2021 18:00:33 -0400

gen: split off genutil.c

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mconfigure | 1+
Minclude/gen.h | 20++++++++++++++++++++
Msrc/gen.c | 143-------------------------------------------------------------------------------
Asrc/genutil.c | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 170 insertions(+), 143 deletions(-)

diff --git a/configure b/configure @@ -9,6 +9,7 @@ harec() { src/emit.c \ src/eval.c \ src/gen.c \ + src/genutil.c \ src/identifier.c \ src/lex.c \ src/main.c \ diff --git a/include/gen.h b/include/gen.h @@ -57,6 +57,26 @@ void gen(const struct unit *unit, struct type_store *store, struct qbe_program *out); +// genutil.c +char *gen_name(struct gen_context *ctx, const char *fmt); +void qval_temp(struct gen_context *ctx, struct qbe_value *out, + const struct gen_temp *temp); +void gen_qtemp(struct gen_context *ctx, struct qbe_value *out, + const struct qbe_type *type, const char *fmt); +void gen_direct(struct gen_context *ctx, struct gen_temp *temp, + const struct type *type, const char *fmt); +void temp_workcopy(struct gen_context *ctx, struct qbe_value *qval, + const struct qbe_type *qtype, const struct gen_temp *temp, + const char *fmt); +void alloc_temp(struct gen_context *ctx, struct gen_temp *temp, + const struct type *type, const char *fmt); +void load_temp(struct gen_context *ctx, struct qbe_value *out, + const struct gen_temp *temp); +void temp_address(struct gen_temp *temp, const struct type *type); +void temp_deref(struct gen_temp *temp); +const struct gen_binding *binding_lookup(struct gen_context *ctx, + const struct scope_object *obj); + // qinstr.c enum qbe_instr alloc_for_align(size_t align); enum qbe_instr store_for_type(struct gen_context *ctx, const struct type *type); diff --git a/src/gen.c b/src/gen.c @@ -8,149 +8,6 @@ #include "types.h" #include "util.h" -static char * -gen_name(struct gen_context *ctx, const char *fmt) -{ - int n = snprintf(NULL, 0, fmt, ctx->id); - char *str = xcalloc(1, n + 1); - snprintf(str, n + 1, fmt, ctx->id); - ++ctx->id; - return str; -} - -// Initializes a qval with a qbe temporary for a given gen temporary. -static void -qval_temp(struct gen_context *ctx, - struct qbe_value *out, - const struct gen_temp *temp) -{ - out->kind = QV_TEMPORARY; - out->type = qtype_lookup(ctx, temp->type, true); - out->name = temp->name; -} - -// Initializes a qbe_value as a qbe temporary for the given qbe type. -static void -gen_qtemp(struct gen_context *ctx, struct qbe_value *out, - const struct qbe_type *type, const char *fmt) -{ - out->kind = QV_TEMPORARY; - out->type = type; - out->name = gen_name(ctx, fmt); -} - -// Generates a direct temporary of the given type, which must be a primitive -// type. -static void -gen_direct(struct gen_context *ctx, struct gen_temp *temp, - const struct type *type, const char *fmt) -{ - assert(type->size != 0 && type->size != SIZE_UNDEFINED); - temp->type = type; - temp->name = gen_name(ctx, fmt); - temp->indirect = false; - const struct qbe_type *qtype = qtype_lookup(ctx, type, false); - assert(qtype->stype != Q__AGGREGATE && qtype->stype != Q__VOID); -} - -// Emits a qbe copy instruction which makes a working copy of a gen temporary. -static void -temp_workcopy(struct gen_context *ctx, struct qbe_value *qval, - const struct qbe_type *qtype, - const struct gen_temp *temp, const char *fmt) -{ - struct qbe_value qtemp = {0}; - gen_qtemp(ctx, qval, qtype, fmt); - qval_temp(ctx, &qtemp, temp); - pushi(ctx->current, qval, Q_COPY, &qtemp, NULL); -} - -// Allocates a temporary of the given type on the stack in the current -// function's preamble. -static void -alloc_temp(struct gen_context *ctx, struct gen_temp *temp, - const struct type *type, const char *fmt) -{ - assert(type->size != 0 && type->size != SIZE_UNDEFINED); - temp->type = type; - temp->name = gen_name(ctx, fmt); - temp->indirect = true; - - struct qbe_value out = { - .kind = QV_TEMPORARY, - .type = ctx->arch.ptr, - .name = temp->name, - }; - struct qbe_value size; - constl(&size, type->size); - pushprei(ctx->current, &out, alloc_for_align(type->align), &size, NULL); -} - -// Loads a gen temporary into a qbe temporary. For types representable in qbe's -// type system, this loads the actual value into a qbe temporary. Otherwise, -// this behaves equivalently to qval_temp, but sets the temporary type to the -// platform's pointer type (e.g. =l). -static void -load_temp(struct gen_context *ctx, - struct qbe_value *out, - const struct gen_temp *temp) -{ - const struct qbe_type *qtype = qtype_lookup(ctx, temp->type, true); - assert(qtype->stype != Q__VOID); - - out->kind = QV_TEMPORARY; - if (qtype->stype == Q__AGGREGATE) { - assert(temp->indirect); - out->name = temp->name; - out->type = ctx->arch.ptr; - } else { - out->name = gen_name(ctx, "load.%d"); - out->type = qtype; - - struct qbe_value src; - qval_temp(ctx, &src, temp); - if (temp->indirect) { - enum qbe_instr instr = load_for_type(ctx, temp->type); - pushi(ctx->current, out, instr, &src, NULL); - } else { - pushi(ctx->current, out, Q_COPY, &src, NULL); - } - } -} - -// Obtains the address of a temporary and changes it to the given pointer type. -static void -temp_address(struct gen_temp *temp, const struct type *type) -{ - assert(type_dealias(type)->storage == STORAGE_POINTER); - assert(temp->indirect); - temp->indirect = false; - temp->type = type; -} - -// Dereferences a temporary, changing it to an indirect address to its referent -// type. -static void -temp_deref(struct gen_temp *temp) -{ - assert(type_dealias(temp->type)->storage == STORAGE_POINTER); - assert(!temp->indirect); - temp->indirect = true; - temp->type = temp->type->pointer.referent; -} - -static const struct gen_binding * -binding_lookup(struct gen_context *ctx, const struct scope_object *obj) -{ - for (struct gen_binding *binding = ctx->bindings; - binding; binding = binding->next) { - if (binding->object == obj) { - return binding; - } - } - abort(); // Invariant -} - static void gen_copy_memcpy(struct gen_context *ctx, const struct gen_temp *dest, diff --git a/src/genutil.c b/src/genutil.c @@ -0,0 +1,149 @@ +#include <stdio.h> +#include <stdlib.h> +#include "gen.h" +#include "qbe.h" +#include "util.h" + +char * +gen_name(struct gen_context *ctx, const char *fmt) +{ + int n = snprintf(NULL, 0, fmt, ctx->id); + char *str = xcalloc(1, n + 1); + snprintf(str, n + 1, fmt, ctx->id); + ++ctx->id; + return str; +} + +// Initializes a qval with a qbe temporary for a given gen temporary. +void +qval_temp(struct gen_context *ctx, + struct qbe_value *out, + const struct gen_temp *temp) +{ + out->kind = QV_TEMPORARY; + out->type = qtype_lookup(ctx, temp->type, true); + out->name = temp->name; +} + +// Initializes a qbe_value as a qbe temporary for the given qbe type. +void +gen_qtemp(struct gen_context *ctx, struct qbe_value *out, + const struct qbe_type *type, const char *fmt) +{ + out->kind = QV_TEMPORARY; + out->type = type; + out->name = gen_name(ctx, fmt); +} + +// Generates a direct temporary of the given type, which must be a primitive +// type. +void +gen_direct(struct gen_context *ctx, struct gen_temp *temp, + const struct type *type, const char *fmt) +{ + assert(type->size != 0 && type->size != SIZE_UNDEFINED); + temp->type = type; + temp->name = gen_name(ctx, fmt); + temp->indirect = false; + const struct qbe_type *qtype = qtype_lookup(ctx, type, false); + assert(qtype->stype != Q__AGGREGATE && qtype->stype != Q__VOID); +} + +// Emits a qbe copy instruction which makes a working copy of a gen temporary. +void +temp_workcopy(struct gen_context *ctx, struct qbe_value *qval, + const struct qbe_type *qtype, + const struct gen_temp *temp, const char *fmt) +{ + struct qbe_value qtemp = {0}; + gen_qtemp(ctx, qval, qtype, fmt); + qval_temp(ctx, &qtemp, temp); + pushi(ctx->current, qval, Q_COPY, &qtemp, NULL); +} + +// Allocates a temporary of the given type on the stack in the current +// function's preamble. +void +alloc_temp(struct gen_context *ctx, struct gen_temp *temp, + const struct type *type, const char *fmt) +{ + assert(type->size != 0 && type->size != SIZE_UNDEFINED); + temp->type = type; + temp->name = gen_name(ctx, fmt); + temp->indirect = true; + + struct qbe_value out = { + .kind = QV_TEMPORARY, + .type = ctx->arch.ptr, + .name = temp->name, + }; + struct qbe_value size; + constl(&size, type->size); + pushprei(ctx->current, &out, alloc_for_align(type->align), &size, NULL); +} + +// Loads a gen temporary into a qbe temporary. For types representable in qbe's +// type system, this loads the actual value into a qbe temporary. Otherwise, +// this behaves equivalently to qval_temp, but sets the temporary type to the +// platform's pointer type (e.g. =l). +void +load_temp(struct gen_context *ctx, + struct qbe_value *out, + const struct gen_temp *temp) +{ + // TODO: Audit me + const struct qbe_type *qtype = qtype_lookup(ctx, temp->type, true); + assert(qtype->stype != Q__VOID); + + out->kind = QV_TEMPORARY; + if (qtype->stype == Q__AGGREGATE) { + assert(temp->indirect); + out->name = temp->name; + out->type = ctx->arch.ptr; + } else { + out->name = gen_name(ctx, "load.%d"); + out->type = qtype; + + struct qbe_value src; + qval_temp(ctx, &src, temp); + if (temp->indirect) { + enum qbe_instr instr = load_for_type(ctx, temp->type); + pushi(ctx->current, out, instr, &src, NULL); + } else { + pushi(ctx->current, out, Q_COPY, &src, NULL); + } + } +} + +// Obtains the address of a temporary and changes it to the given pointer type. +void +temp_address(struct gen_temp *temp, const struct type *type) +{ + assert(type_dealias(type)->storage == STORAGE_POINTER); + assert(temp->indirect); + temp->indirect = false; + temp->type = type; +} + +// Dereferences a temporary, changing it to an indirect address to its referent +// type. +void +temp_deref(struct gen_temp *temp) +{ + assert(type_dealias(temp->type)->storage == STORAGE_POINTER); + assert(!temp->indirect); + temp->indirect = true; + temp->type = temp->type->pointer.referent; +} + +const struct gen_binding * +binding_lookup(struct gen_context *ctx, const struct scope_object *obj) +{ + for (struct gen_binding *binding = ctx->bindings; + binding; binding = binding->next) { + if (binding->object == obj) { + return binding; + } + } + abort(); // Invariant +}