diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-04-25 16:10:45 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-04-25 16:10:45 -0400 |
commit | a161b75a01eee7249f989c3a85d92b69c1818370 (patch) | |
tree | fb65753b6e84b102787523a8948bc5507400f3b3 | |
parent | 7ee5fc2721e40471f01f9377dd901ded4b969a33 (diff) |
stop copying whole fn body unless necessary when generating an instance
-rw-r--r-- | copy.c | 50 | ||||
-rw-r--r-- | err.c | 5 | ||||
-rw-r--r-- | test.toc | 61 | ||||
-rw-r--r-- | tests/arr.toc | 2 | ||||
-rw-r--r-- | tests/arr2.toc | 2 | ||||
-rw-r--r-- | tests/arr3.toc | 4 | ||||
-rw-r--r-- | tests/bf.toc | 73 | ||||
-rw-r--r-- | tests/control_flow.toc | 4 | ||||
-rw-r--r-- | tests/defer.toc | 2 | ||||
-rw-r--r-- | tests/foreign.toc | 2 | ||||
-rw-r--r-- | tests/misc.toc | 2 | ||||
-rw-r--r-- | tests/new.toc | 4 | ||||
-rw-r--r-- | tests/nms.toc | 2 | ||||
-rw-r--r-- | tests/sizeof.toc | 4 | ||||
-rw-r--r-- | tests/std/io.toc (renamed from tests/io.toc) | 0 | ||||
-rw-r--r-- | tests/std/mem.toc (renamed from tests/mem.toc) | 0 | ||||
-rw-r--r-- | tests/types.toc | 5 | ||||
-rw-r--r-- | tests/use.toc | 4 | ||||
-rw-r--r-- | types.c | 13 | ||||
-rw-r--r-- | types.h | 22 |
20 files changed, 116 insertions, 145 deletions
@@ -184,14 +184,12 @@ static inline void *copier_malloc(Copier *c, size_t n) { } enum { - COPY_FN_EXPR_DONT_COPY_HEADER = 0x01, - COPY_FN_EXPR_DONT_COPY_BODY = 0x02 + COPY_FN_EXPR_DONT_COPY_BODY = 0x01 }; static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, U8 flags) { *fout = *fin; bool copy_body = (flags & COPY_FN_EXPR_DONT_COPY_BODY) == 0; - bool copy_header = (flags & COPY_FN_EXPR_DONT_COPY_HEADER) == 0; if (fin->flags & FN_EXPR_FOREIGN) { copy_expr(c, fout->foreign.name_expr = copier_malloc(c, sizeof *fin->foreign.name_expr), fin->foreign.name_expr); @@ -202,29 +200,25 @@ static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, U8 flags) { memcpy(fout->foreign.ctypes, fin->foreign.ctypes, nctypes * sizeof(CType)); } else { Block *prev = c->block; - if (copy_body) { - c->block = &fout->body; - idents_create(&fout->body.idents, c->allocr, &fout->body); - } - if (copy_header) { - size_t i; - size_t nparam_decls = arr_len(fin->params); - fout->params = NULL; - arr_set_lena(fout->params, nparam_decls, c->allocr); - for (i = 0; i < nparam_decls; ++i) - copy_decl(c, fout->params + i, fin->params + i); - size_t nret_decls = arr_len(fin->ret_decls); - if (fin->ret_decls) { - fout->ret_decls = NULL; - arr_set_lena(fout->ret_decls, nret_decls, c->allocr); - for (i = 0; i < nret_decls; ++i) - copy_decl(c, fout->ret_decls + i, fin->ret_decls + i); - } - copy_type(c, &fout->ret_type, &fin->ret_type); + c->block = &fout->body; + idents_create(&fout->body.idents, c->allocr, &fout->body); + size_t i; + size_t nparam_decls = arr_len(fin->params); + fout->params = NULL; + arr_set_lena(fout->params, nparam_decls, c->allocr); + for (i = 0; i < nparam_decls; ++i) + copy_decl(c, fout->params + i, fin->params + i); + size_t nret_decls = arr_len(fin->ret_decls); + if (fin->ret_decls) { + fout->ret_decls = NULL; + arr_set_lena(fout->ret_decls, nret_decls, c->allocr); + for (i = 0; i < nret_decls; ++i) + copy_decl(c, fout->ret_decls + i, fin->ret_decls + i); } + copy_type(c, &fout->ret_type, &fin->ret_type); c->block = prev; if (copy_body) { - copy_block(c, &fout->body, &fin->body, copy_body ? COPY_BLOCK_DONT_CREATE_IDENTS : 0); + copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS); } } } @@ -377,7 +371,6 @@ static void copy_decl(Copier *c, Declaration *out, Declaration *in) { out->idents[i] = in->idents[i]; assert(c->block); copier_ident_translate(c, &out->idents[i]); - out->idents[i]->decl = out; } @@ -430,14 +423,13 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) { } } -/* COPY_BLOCK_DONT_CREATE_IDENTS is for copy_fn_expr */ +/* COPY_BLOCK_DONT_CREATE_IDENTS is for copy_fn_expr, etc. */ static void copy_block(Copier *c, Block *out, Block *in, U8 flags) { assert(!(in->flags & BLOCK_FINDING_TYPES)); - Identifiers out_idents = out->idents; - *out = *in; + out->flags = in->flags; + out->kind = in->kind; out->parent = c->block; - if (flags & COPY_BLOCK_DONT_CREATE_IDENTS) - out->idents = out_idents; /* reset Identifiers */ + out->where = in->where; size_t nstmts = arr_len(in->stmts); out->stmts = NULL; Block *prev = c->block; @@ -172,15 +172,14 @@ static void warn_print_header_(Location where) { err_print_line_file(where); } - +static void info_print(Location where, const char *fmt, ...); static void err_print_footer_(Location where, bool show_ctx_stack) { ErrCtx *ctx = where.file->ctx; err_fprint(ctx, "\n\t"); print_location_highlight(err_ctx_file(ctx), where); if (ctx && show_ctx_stack) { arr_foreach(ctx->instance_stack, Location, inst) { - err_fprint(ctx, "While generating this instance of a function or struct:\n\t"); - print_location_highlight(err_ctx_file(ctx), *inst); + info_print(*inst, "While generating this instance of a function or struct:"); } } } @@ -1,48 +1,27 @@ +#include "std/mem.toc", mem; #include "std/io.toc", io; -#include "std/mem.toc"; - -main ::= fn() { - nums := news(int, 10); - for x, i := &nums { - *x = i*i; - } - l := slice_to_ll(nums); - p := &l; - while p { - io.puti(p.head); - p = p.tail; +calculation ::= fn() int { + total := 0; + i := mem.new(int); + *i = 3; + ns := mem.news(int, 10); + for n, i := &ns { + if i % 2 == 0 { + *n = i; + } } - f: Foo; - f.k = -173; - f.b = new(Bar); - f.b.f.b = new(Bar); - f.b.f.b.f.k = 9; - io.puti(f.k); - io.puti(f.b.f.k); - io.puti(f.b.f.b.f.k); -} - -slice_to_ll ::= fn(t::=, slice: []t) use ll: LinkedList(t) { - head = slice[0]; - if slice.len == 1 { - tail = 0 as &LinkedList(t); - } else { - tail = new(LinkedList(t)); - *tail = slice_to_ll(slice[1:]); + for n := ns { + total += n; } + total += *i; + mem.del(i); + mem.dels(ns); + total } -LinkedList ::= struct (of :: Type) { - head: of; - tail: &LinkedList(of); -} - -Foo ::= struct { - k: int; - b: &Bar; -} - -Bar ::= struct { - f: Foo; +main ::= fn() { + io.puti(calculation()); + x ::= calculation(); + io.puti(x); } diff --git a/tests/arr.toc b/tests/arr.toc index 5fb8328..3af9edd 100644 --- a/tests/arr.toc +++ b/tests/arr.toc @@ -1,4 +1,4 @@ -#include "mem.toc"; +#include "std/mem.toc"; puti ::= fn(x: int) { //tcc's giving me "incompatible types for redefinition of 'printf'" for some reason (even though the declarations have the exact same type) #C("#ifndef __TINYC__ diff --git a/tests/arr2.toc b/tests/arr2.toc index 9d6aa34..189512a 100644 --- a/tests/arr2.toc +++ b/tests/arr2.toc @@ -1,4 +1,4 @@ -#include "mem.toc"; +#include "std/mem.toc"; puti ::= fn(x: int) { #C("#ifndef __TINYC__ extern int printf(const char *fmt, ...); diff --git a/tests/arr3.toc b/tests/arr3.toc index 4310d64..25c5554 100644 --- a/tests/arr3.toc +++ b/tests/arr3.toc @@ -1,5 +1,5 @@ -#include "io.toc"; -#include "mem.toc"; +#include "std/io.toc"; +#include "std/mem.toc"; arr_add ::= fn(t ::=, a : &Arr(t), x : t) { diff --git a/tests/bf.toc b/tests/bf.toc index d300bc9..166601b 100644 --- a/tests/bf.toc +++ b/tests/bf.toc @@ -1,43 +1,50 @@ -#include "mem.toc"; +#include "std/mem.toc"; + readfile ::= fn(filename: []char) []char { #C("extern void *fopen(char *name, char const *mode); extern char *fgets(char *buf, size_t sz, void *f);"); - fp : &u8 = #C("fopen(&(((char *)filename.data)[0]), \"r\")"); - contents := news(char, 1); - contents_sz : int; - contents_len : int; - buffer : [1024]char; - while #C("fgets(buffer, 1024, fp)") { - buffer_len : int; - while buffer[buffer_len] { - buffer_len = buffer_len + 1; - } - if contents_sz < contents_len + buffer_len { - old_contents := contents; - contents_sz = 2*contents_sz + 1024; - contents = news(char, contents_sz); - i := 0; - while i < contents_len { - contents[i] = old_contents[i]; - i = i + 1; - } - dels(old_contents); - } - i := 0; - while i < buffer_len { - contents[contents_len] = buffer[i]; - contents_len = contents_len + 1; - i = i + 1; - } - } - contents[contents_len] = 0 as char; - contents +#C(" +extern int printf(const char *fmt, ...); +extern void exit(int); +"); + fp : &u8 = #C("(u8 *)fopen(&(((char *)filename.data)[0]), \"r\")"); + if !fp { + #C("printf(\"Couldn't open file\\n\"); exit(-1);"); + } + contents := news(char, 1); + contents_sz : int; + contents_len : int; + buffer : [1024]char; + while #C("fgets(buffer, 1024, fp)") { + buffer_len : int; + while buffer[buffer_len] { + buffer_len = buffer_len + 1; + } + if contents_sz < contents_len + buffer_len { + old_contents := contents; + contents_sz = 2*contents_sz + 1024; + contents = news(char, contents_sz); + i := 0; + while i < contents_len { + contents[i] = old_contents[i]; + i = i + 1; + } + dels(old_contents); + } + i := 0; + while i < buffer_len { + contents[contents_len] = buffer[i]; + contents_len = contents_len + 1; + i = i + 1; + } + } + contents[contents_len] = 0 as char; + contents }; puti ::= fn(x: int) { - #C("#ifndef __TINYC__ + #C(" extern int printf(const char *fmt, ...); -#endif "); #C("printf(\"%ld\\n\", x);"); }; diff --git a/tests/control_flow.toc b/tests/control_flow.toc index 923a40b..043d4b7 100644 --- a/tests/control_flow.toc +++ b/tests/control_flow.toc @@ -1,4 +1,4 @@ -#include "io.toc", io; +#include "std/io.toc", io; f ::= fn() int { total := 0; @@ -28,4 +28,4 @@ main ::= fn() { x ::= f(); io.puti(x); io.puti(f()); -}
\ No newline at end of file +} diff --git a/tests/defer.toc b/tests/defer.toc index 578668d..ec06a19 100644 --- a/tests/defer.toc +++ b/tests/defer.toc @@ -1,4 +1,4 @@ -#include "io.toc", io; +#include "std/io.toc", io; plusone ::= fn(n : int) x := n { defer x += 1; diff --git a/tests/foreign.toc b/tests/foreign.toc index d88a223..92038d9 100644 --- a/tests/foreign.toc +++ b/tests/foreign.toc @@ -22,4 +22,4 @@ hw ::= fn() int { main ::= fn() { hw(); x ::= hw(); -};
\ No newline at end of file +}; diff --git a/tests/misc.toc b/tests/misc.toc index 26ecf3e..5dcd1eb 100644 --- a/tests/misc.toc +++ b/tests/misc.toc @@ -1,4 +1,4 @@ -#include "io.toc", io; +#include "std/io.toc", io; main ::= fn() { x ::= 3; diff --git a/tests/new.toc b/tests/new.toc index bb6a5fa..790a115 100644 --- a/tests/new.toc +++ b/tests/new.toc @@ -1,5 +1,5 @@ -#include "mem.toc", mem; -#include "io.toc", io; +#include "std/mem.toc", mem; +#include "std/io.toc", io; calculation ::= fn() int { total := 0; diff --git a/tests/nms.toc b/tests/nms.toc index 413da8d..32c2955 100644 --- a/tests/nms.toc +++ b/tests/nms.toc @@ -1,5 +1,5 @@ io ::= nms { - #include "io.toc"; + #include "std/io.toc"; }; n ::= nms { diff --git a/tests/sizeof.toc b/tests/sizeof.toc index 0bc806b..5a97985 100644 --- a/tests/sizeof.toc +++ b/tests/sizeof.toc @@ -1,4 +1,4 @@ -#include "io.toc", io; +#include "std/io.toc", io; Point3D ::= struct { x, y, z: f32; @@ -14,4 +14,4 @@ main ::= fn() { x ::= calculation(); io.puti(x); io.puti(calculation()); -}
\ No newline at end of file +} diff --git a/tests/io.toc b/tests/std/io.toc index 2c82dc9..2c82dc9 100644 --- a/tests/io.toc +++ b/tests/std/io.toc diff --git a/tests/mem.toc b/tests/std/mem.toc index 6d16895..6d16895 100644 --- a/tests/mem.toc +++ b/tests/std/mem.toc diff --git a/tests/types.toc b/tests/types.toc index 4ef55e8..7262637 100644 --- a/tests/types.toc +++ b/tests/types.toc @@ -1,6 +1,5 @@ -#include "io.toc", io; -#include "mem.toc"; - +#include "std/io.toc", io; +#include "std/mem.toc"; main ::= fn() { nums := news(int, 10); diff --git a/tests/use.toc b/tests/use.toc index f1228f6..98e9221 100644 --- a/tests/use.toc +++ b/tests/use.toc @@ -1,5 +1,5 @@ -#include "io.toc", io; -#include "mem.toc", mem; +#include "std/io.toc", io; +#include "std/mem.toc", mem; use mem; @@ -548,7 +548,6 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { bool entered_fn = false; size_t param_idx; FnExpr *prev_fn = tr->fn; - FnExpr fn_copy = {0}; Declaration *last_param = arr_last_ptr(f->params); bool has_varargs = last_param && (last_param->flags & DECL_ANNOTATES_TYPE) && type_is_builtin(&last_param->type, BUILTIN_VARARGS); @@ -556,11 +555,6 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { f->flags |= FN_EXPR_HAS_VARARGS; /* f has compile time params/varargs, but it's not an instance! */ bool generic = !(flags & TYPE_OF_FN_IS_INSTANCE) && (fn_has_any_const_params(f) || has_varargs); - if (generic) { - Copier cop = copier_create(tr->allocr, &f->body); - copy_fn_expr(&cop, &fn_copy, f, COPY_FN_EXPR_DONT_COPY_BODY); - f = &fn_copy; - } size_t idx = 0; bool has_constant_params = false; /* reserve space for return type */ @@ -2231,6 +2225,7 @@ static Status types_expr(Typer *tr, Expression *e) { Copier cop = copier_create(tr->allocr, base->struc->body.parent); HashTable *table = &base->struc->instances; StructDef struc; + /* @OPTIM: don't copy struct body */ copy_struct(&cop, &struc, base->struc); size_t nparams = 0; @@ -2391,7 +2386,7 @@ static Status types_expr(Typer *tr, Expression *e) { /* param->expr hasn't been typed or evaluated, because we passed type_of_fn a "generic" function */ /* we actually need to make a copy of this, so that copy_fn_expr still works later */ Expression default_arg; - Copier cop = copier_create(tr->allocr, tr->block); + Copier cop = copier_create(tr->allocr, &fn_decl->body); copy_expr(&cop, &default_arg, ¶m->expr); if (!types_expr(tr, &default_arg)) return false; @@ -2496,7 +2491,7 @@ static Status types_expr(Typer *tr, Expression *e) { original_fn = fn; fn_copy = typer_malloc(tr, sizeof *fn_copy); Copier cop = copier_create(tr->allocr, fn->body.parent); - copy_fn_expr(&cop, fn_copy, fn, 0); + copy_fn_expr(&cop, fn_copy, fn, COPY_FN_EXPR_DONT_COPY_BODY); if (has_varargs) { /* set value of varargs param decl */ @@ -2749,6 +2744,8 @@ static Status types_expr(Typer *tr, Expression *e) { arr_cleara(table_index_type.tuple, tr->allocr); arr_cleara(table_index.tuple, tr->allocr); } else { + Copier cop = copier_create(tr->allocr, fn_copy->body.parent); + copy_block(&cop, &fn_copy->body, &original_fn->body, COPY_BLOCK_DONT_CREATE_IDENTS); c->instance->fn = fn_copy; /* fix parameter and return types (they were kind of problematic before, because we didn't know about the instance) */ fn_copy->instance_id = 1+original_fn->instances->n; /* let's help cgen out and assign a non-zero ID to this */ @@ -483,6 +483,7 @@ typedef enum { typedef U8 BlockFlags; typedef struct Block { + /* NOTE: make sure you check copy.c when you add something to this */ BlockFlags flags; BlockKind kind; struct { @@ -510,7 +511,6 @@ typedef struct StructDef { /* these two only exist after resolving (before then, it's scope.stmts) */ Field *fields; Location where; - StructFlags flags; /* use this instead of fields when looking up a field, because it will include "use"d things. this only consists of statements which are declarations after typing (and not #ifs, @@ -531,6 +531,7 @@ typedef struct StructDef { /* if name is NULL, use this */ IdentID id; } c; + StructFlags flags; } StructDef; @@ -625,17 +626,6 @@ typedef struct WhileExpr { } WhileExpr; -enum { - FOR_IS_RANGE = 0x01 -}; - - -enum { - FN_EXPR_FOREIGN = 0x01, - FN_EXPR_EXPORT = 0x02, /* set by sdecls_cgen.c */ - FN_EXPR_HAS_VARARGS = 0x04 -}; - typedef enum { CTYPE_NONE = 0x00, CTYPE_CHAR = 0x01, @@ -883,6 +873,14 @@ typedef struct Declaration { } Declaration; typedef Declaration *DeclarationPtr; +enum { + FOR_IS_RANGE = 0x01 +}; +enum { + FN_EXPR_FOREIGN = 0x01, + FN_EXPR_EXPORT = 0x02, /* set by sdecls_cgen.c */ + FN_EXPR_HAS_VARARGS = 0x04 +}; typedef struct ForExpr { U8 flags; Declaration header; |