summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-04-25 16:10:45 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-04-25 16:10:45 -0400
commita161b75a01eee7249f989c3a85d92b69c1818370 (patch)
treefb65753b6e84b102787523a8948bc5507400f3b3
parent7ee5fc2721e40471f01f9377dd901ded4b969a33 (diff)
stop copying whole fn body unless necessary when generating an instance
-rw-r--r--copy.c50
-rw-r--r--err.c5
-rw-r--r--test.toc61
-rw-r--r--tests/arr.toc2
-rw-r--r--tests/arr2.toc2
-rw-r--r--tests/arr3.toc4
-rw-r--r--tests/bf.toc73
-rw-r--r--tests/control_flow.toc4
-rw-r--r--tests/defer.toc2
-rw-r--r--tests/foreign.toc2
-rw-r--r--tests/misc.toc2
-rw-r--r--tests/new.toc4
-rw-r--r--tests/nms.toc2
-rw-r--r--tests/sizeof.toc4
-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.toc5
-rw-r--r--tests/use.toc4
-rw-r--r--types.c13
-rw-r--r--types.h22
20 files changed, 116 insertions, 145 deletions
diff --git a/copy.c b/copy.c
index 7da09d4..13615ac 100644
--- a/copy.c
+++ b/copy.c
@@ -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;
diff --git a/err.c b/err.c
index 01e3de2..1a78e64 100644
--- a/err.c
+++ b/err.c
@@ -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:");
}
}
}
diff --git a/test.toc b/test.toc
index 0b84b8a..790a115 100644
--- a/test.toc
+++ b/test.toc
@@ -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;
diff --git a/types.c b/types.c
index 2be1237..e111148 100644
--- a/types.c
+++ b/types.c
@@ -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, &param->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 */
diff --git a/types.h b/types.h
index fd02a05..d81df36 100644
--- a/types.h
+++ b/types.h
@@ -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;