harec

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

commit 2501f5630ea984629189a1585abc0c1f40b0d0ad
parent 1e39643dc342926d80fedd5ce6bc6aae7e075060
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 31 Dec 2020 16:27:46 -0500

all: bootstrap runtime

Diffstat:
MMakefile | 4++++
Minclude/ast.h | 3++-
Minclude/check.h | 14++++++++++++--
Minclude/scope.h | 11++++++++---
Minclude/type_store.h | 2++
Art/+linux/start.s | 6++++++
Mrt/+linux/syscall+x86_64.s | 28++++++++++++++--------------
Mrt/Makefile | 11++++-------
Mrt/abort.ha | 4++--
Mrt/configure | 19++++++++++++++++++-
Art/rtmain.ha | 7+++++++
Msrc/check.c | 48++++++++++++++++++++++--------------------------
Msrc/gen.c | 4++--
Msrc/main.c | 3++-
Msrc/parse.c | 1+
Msrc/scope.c | 11+++++------
Msrc/type_store.c | 3+++
17 files changed, 114 insertions(+), 65 deletions(-)

diff --git a/Makefile b/Makefile @@ -19,6 +19,10 @@ include rt/Makefile $(CPP) $(CFLAGS) -MM -MT $@ $< >> $(OUTDIR)/cppcache @$(CC) -c $(CFLAGS) -o $@ $< +.s.o: + @printf 'AS\t$@\n' + @$(AS) -o $@ $< + docs: clean: diff --git a/include/ast.h b/include/ast.h @@ -2,12 +2,13 @@ #define HARE_AST_H #include <stdbool.h> #include <stdint.h> -#include "check.h" #include "expr.h" #include "identifier.h" #include "lex.h" #include "types.h" +struct ast_type; + enum ast_import_mode { AST_IMPORT_IDENTIFIER, // use foo::bar; AST_IMPORT_ALIAS, // use foo::bar = x::y; diff --git a/include/check.h b/include/check.h @@ -3,11 +3,19 @@ #include <stdbool.h> #include "identifier.h" #include "types.h" +#include "type_store.h" -struct context; struct expression; struct scope; +struct context { + struct type_store store; + const struct type *current_fntype; + struct identifier *ns; + struct scope *unit; + struct scope *scope; +}; + enum func_decl_flags { FN_FINI = 1 << 0, FN_INIT = 1 << 1, @@ -51,7 +59,9 @@ struct unit { struct ast_expression; struct ast_unit; -void check(const struct ast_unit *aunit, struct unit *unit); +void check(struct context *ctx, + const struct ast_unit *aunit, + struct unit *unit); void check_expression(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr); diff --git a/include/scope.h b/include/scope.h @@ -12,7 +12,10 @@ enum object_type { // XXX: This might be better as a hash map struct scope_object { enum object_type otype; - struct identifier ident; + // name is the name of the object within this scope (for lookups) + // ident is the global identifier + // (these may be different in some cases) + struct identifier name, ident; const struct type *type; struct expression *value; // For O_CONST struct scope_object *next; @@ -35,9 +38,11 @@ struct scope *scope_pop(struct scope **stack, enum trace_sys sys); void scope_free(struct scope *scope); void scope_free_all(struct scopes *scopes); -const struct scope_object *scope_insert(struct scope *scope, - enum object_type otype, const struct identifier *ident, +const struct scope_object *scope_insert( + struct scope *scope, enum object_type otype, + const struct identifier *ident, const struct identifier *name, const struct type *type, struct expression *value); + const struct scope_object *scope_lookup(struct scope *scope, const struct identifier *ident); diff --git a/include/type_store.h b/include/type_store.h @@ -21,6 +21,8 @@ bool type_is_assignable(struct type_store *store, const struct type *to, const struct type *from); bool type_is_castable(const struct type *to, const struct type *from); +struct ast_type; + const struct type *type_store_lookup_atype( struct type_store *store, const struct ast_type *atype); diff --git a/rt/+linux/start.s b/rt/+linux/start.s @@ -0,0 +1,6 @@ +.text +.global _start +_start: + xor %rbp, %rbp + movq %rsp, %rdi + call rt.start_ha diff --git a/rt/+linux/syscall+x86_64.s b/rt/+linux/syscall+x86_64.s @@ -1,27 +1,27 @@ .text -.global sys.syscall0 -sys.syscall0: +.global rt.syscall0 +rt.syscall0: movq %rdi, %rax syscall ret -.global sys.syscall1 -sys.syscall1: +.global rt.syscall1 +rt.syscall1: movq %rdi, %rax movq %rsi, %rdi syscall ret -.global sys.syscall2 -sys.syscall2: +.global rt.syscall2 +rt.syscall2: movq %rdi, %rax movq %rsi, %rdi movq %rdx, %rsi syscall ret -.global sys.syscall3 -sys.syscall3: +.global rt.syscall3 +rt.syscall3: movq %rdi, %rax movq %rsi, %rdi movq %rdx, %rsi @@ -29,8 +29,8 @@ sys.syscall3: syscall ret -.global sys.syscall4 -sys.syscall4: +.global rt.syscall4 +rt.syscall4: movq %rdi, %rax movq %r8, %r10 movq %rsi, %rdi @@ -39,8 +39,8 @@ sys.syscall4: syscall ret -.global sys.syscall5 -sys.syscall5: +.global rt.syscall5 +rt.syscall5: movq %rdi, %rax movq %r8, %r10 movq %rsi, %rdi @@ -50,8 +50,8 @@ sys.syscall5: syscall ret -.global sys.syscall6 -sys.syscall6: +.global rt.syscall6 +rt.syscall6: movq %rdi, %rax movq %r8, %r10 movq %rsi, %rdi diff --git a/rt/Makefile b/rt/Makefile @@ -1,14 +1,11 @@ -libhart_srcs=\ +libhart_srcs+=\ rt/abort.ha \ - rt/malloc.ha \ - rt/memcmp.ha \ - rt/memcpy.ha \ - rt/memset.ha + rt/rtmain.ha -libhart.a: $(libhart_srcs) +libhart.a: harec $(libhart_srcs) $(libhart_objs) @printf 'HAREC\t$@\n' @./harec -N rt -o $@.ssa $(libhart_srcs) @qbe -o $@.s $@.ssa @$(AS) -o $@.o $@.s - @$(AR) -csr $@ $@.o + @$(AR) -csr $@ $@.o $(libhart_objs) @rm $@.o $@.s $@.ssa diff --git a/rt/abort.ha b/rt/abort.ha @@ -1,9 +1,9 @@ export @noreturn @symbol("rt.abort") fn _abort(msg: str) void = { - const prefix = "Abort: "; + const prefix = "Abort: ", newline = "\n"; // XXX: This causes const to fall off, we should catch that (may need // spec update) write(2, prefix: *const char, len(prefix)); write(2, msg: *const char, len(msg)); - write(2, "\n": *const char, 1z); + write(2, newline: *const char, 1z); kill(getpid(), SIGABRT); }; diff --git a/rt/configure b/rt/configure @@ -2,5 +2,22 @@ all="$all rt" rt() { - echo "rt: libhart.a" + case $(uname) in + Linux) + cat <<-EOF + libhart_srcs=\ + rt/+linux/syscallno+x86_64.ha \ + rt/+linux/syscalls.ha + + libhart_objs=\ + rt/+linux/syscall+x86_64.o + + rt: libhart.a rt/+linux/start.o + EOF + ;; + *) + printf "rt not supported for %s\n" "$(uname)" >&2 + exit 1 + ;; + esac } diff --git a/rt/rtmain.ha b/rt/rtmain.ha @@ -0,0 +1,7 @@ +@symbol("main") fn main() int; +fn exit(status: int) void; + +export fn start_ha(iv: [*]uintptr) void = { + main(); + exit(0); +}; diff --git a/src/check.c b/src/check.c @@ -13,14 +13,6 @@ #include "types.h" #include "util.h" -struct context { - struct type_store store; - const struct type *current_fntype; - struct identifier *ns; - struct scope *unit; - struct scope *scope; -}; - static void mkident(struct context *ctx, struct identifier *out, const struct identifier *in) { @@ -38,7 +30,7 @@ expect(const struct location *loc, bool constraint, char *fmt, ...) va_list ap; va_start(ap, fmt); - fprintf(stderr, "Error: %s:%d:%d: ", + fprintf(stderr, "Error %s:%d:%d: ", loc->path, loc->lineno, loc->colno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); @@ -64,7 +56,7 @@ check_expr_access(struct context *ctx, obj = scope_lookup(ctx->scope, &aexpr->access.ident); char buf[1024]; identifier_unparse_static(&aexpr->access.ident, buf, sizeof(buf)); - expect(&aexpr->loc, obj, "Unknown object", buf); + expect(&aexpr->loc, obj, "Unknown object '%s'", buf); if (obj->otype == O_CONST) { // Lower constants *expr = *obj->value; @@ -256,7 +248,7 @@ check_expr_binding(struct context *ctx, "Initializer is not assignable to binding type"); const struct scope_object *obj = scope_insert( - ctx->scope, O_BIND, &ident, type, NULL); + ctx->scope, O_BIND, &ident, &ident, type, NULL); binding->object = obj; binding->initializer = initializer; @@ -766,7 +758,8 @@ check_function(struct context *ctx, }; const struct type *type = type_store_lookup_atype( &ctx->store, params->type); - scope_insert(decl->func.scope, O_BIND, &ident, type, NULL); + scope_insert(decl->func.scope, O_BIND, + &ident, &ident, type, NULL); params = params->next; } @@ -844,8 +837,12 @@ scan_function(struct context *ctx, const struct ast_function_decl *decl) assert(fntype); // TODO: Forward references struct identifier ident = {0}; - mkident(ctx, &ident, &decl->ident); - scope_insert(ctx->unit, O_DECL, &ident, fntype, NULL); + if (decl->symbol) { + ident.name = strdup(decl->symbol); + } else { + mkident(ctx, &ident, &decl->ident); + } + scope_insert(ctx->unit, O_DECL, &ident, &decl->ident, fntype, NULL); char buf[1024]; identifier_unparse_static(&decl->ident, buf, sizeof(buf)); @@ -880,7 +877,7 @@ scan_const(struct context *ctx, const struct ast_global_decl *decl) struct identifier ident = {0}; mkident(ctx, &ident, &decl->ident); - scope_insert(ctx->unit, O_CONST, &ident, type, value); + scope_insert(ctx->unit, O_CONST, &ident, &decl->ident, type, value); trleave(TR_SCAN, NULL); } @@ -909,11 +906,10 @@ scan_declarations(struct context *ctx, const struct ast_decls *decls) } void -check(const struct ast_unit *aunit, struct unit *unit) +check(struct context *ctx, const struct ast_unit *aunit, struct unit *unit) { - struct context ctx = {0}; - ctx.store.check_context = &ctx; - ctx.ns = unit->ns; + ctx->store.check_context = ctx; + ctx->ns = unit->ns; // Top-level scope management involves: // @@ -923,7 +919,7 @@ check(const struct ast_unit *aunit, struct unit *unit) // // Further down the call frame, subsequent functions will create // sub-scopes for each declaration, expression-list, etc. - ctx.unit = scope_push(&ctx.scope, TR_MAX); + ctx->unit = scope_push(&ctx->scope, TR_MAX); struct scopes *subunit_scopes; struct scopes **next = &subunit_scopes; @@ -931,13 +927,13 @@ check(const struct ast_unit *aunit, struct unit *unit) // First pass populates the type graph for (const struct ast_subunit *su = &aunit->subunits; su; su = su->next) { - scope_push(&ctx.scope, TR_SCAN); + scope_push(&ctx->scope, TR_SCAN); assert(!su->imports); // TODO - scan_declarations(&ctx, &su->decls); + scan_declarations(ctx, &su->decls); *next = xcalloc(1, sizeof(struct scopes)); - (*next)->scope = scope_pop(&ctx.scope, TR_SCAN); + (*next)->scope = scope_pop(&ctx->scope, TR_SCAN); next = &(*next)->next; } @@ -946,9 +942,9 @@ check(const struct ast_unit *aunit, struct unit *unit) struct declarations **next_decl = &unit->declarations; for (const struct ast_subunit *su = &aunit->subunits; su; su = su->next) { - ctx.scope = scope->scope; - trenter(TR_CHECK, "scope %p", ctx.scope); - next_decl = check_declarations(&ctx, &su->decls, next_decl); + ctx->scope = scope->scope; + trenter(TR_CHECK, "scope %p", ctx->scope); + next_decl = check_declarations(ctx, &su->decls, next_decl); trleave(TR_CHECK, NULL); scope = scope->next; } diff --git a/src/gen.c b/src/gen.c @@ -100,10 +100,12 @@ qval_for_object(struct gen_context *ctx, binding = binding_lookup(ctx, obj); val->kind = QV_TEMPORARY; val->indirect = true; + val->name = strdup(binding->name); break; case O_DECL: val->kind = QV_GLOBAL; val->indirect = false; + val->name = ident_to_sym(&obj->ident); break; case O_CONST: assert(0); // Invariant (lowered in check) @@ -115,8 +117,6 @@ qval_for_object(struct gen_context *ctx, } else { val->type = &qbe_long; // XXX: ARCH } - - val->name = binding ? strdup(binding->name) : ident_to_sym(&obj->ident); } static void diff --git a/src/main.c b/src/main.c @@ -125,7 +125,8 @@ main(int argc, char *argv[]) return 0; } - check(&aunit, &unit); + struct context ctx = {0}; + check(&ctx, &aunit, &unit); if (stage == STAGE_CHECK) { return 0; } diff --git a/src/parse.c b/src/parse.c @@ -6,6 +6,7 @@ #include <stdlib.h> #include <string.h> #include "ast.h" +#include "check.h" #include "identifier.h" #include "lex.h" #include "parse.h" diff --git a/src/scope.c b/src/scope.c @@ -62,14 +62,13 @@ scope_free_all(struct scopes *scopes) } const struct scope_object * -scope_insert(struct scope *scope, - enum object_type otype, - const struct identifier *ident, - const struct type *type, - struct expression *value) +scope_insert(struct scope *scope, enum object_type otype, + const struct identifier *ident, const struct identifier *name, + const struct type *type, struct expression *value) { struct scope_object *o = xcalloc(1, sizeof(struct scope_object)); identifier_dup(&o->ident, ident); + identifier_dup(&o->name, name); o->otype = otype; o->type = type; o->value = value; @@ -87,7 +86,7 @@ scope_lookup(struct scope *scope, const struct identifier *ident) { struct scope_object *o = scope->objects; while (o) { - if (identifier_eq(&o->ident, ident)) { + if (identifier_eq(&o->name, ident)) { return o; } o = o->next; diff --git a/src/type_store.c b/src/type_store.c @@ -320,6 +320,9 @@ static bool type_eq_type(struct type_store *store, const struct type *a, const struct type *b) { + if (a == b) { + return true; + } if (a->storage != b->storage || a->flags != b->flags) { return false; }