compiler

Unnamed Compiled Systems Language Project
git clone http://frotz.net/git/compiler.git
Log | Files | Refs

commit d4188d73c444566caca6fe76efe02b34b73231ac
parent 177ad45c207d1d09f8bae4d419c8e4ca9d43ecc8
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat, 14 Mar 2020 04:58:05 -0700

compiler: handle arrays as function parameters

- we already enforce exact type match (including length)
- this arranges for arrays to be passed as reference types
  (invisible pointers, effectively)
- should revisit and see if there's a cleaner way to integrate
  with the type/item system

Diffstat:
Mdocs/todo.md | 2+-
Msrc/compiler.c | 55++++++++++++++++++++++++++++++++++++++++++++++---------
Mtest/1041-arrays.log | 8++++++++
Mtest/1041-arrays.src | 3+--
4 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/docs/todo.md b/docs/todo.md @@ -2,7 +2,6 @@ ### Compiler -- [ ] support for arrays - [ ] support for slices & string constants - [ ] support for globals, init'ing gp - [ ] support for enums, or convert enums to consts @@ -10,6 +9,7 @@ - [ ] break/continue to label - [ ] const / readonly - [ ] type inference for var definitions +- [x] support for arrays - [x] support for pointers - [x] support for structs - [x] type definition diff --git a/src/compiler.c b/src/compiler.c @@ -341,6 +341,7 @@ void gen_discard(Item val); // sets up call param #n, consuming val void gen_param(u32 n, Item val); +void gen_ref_param(u32 n, Item val); // call func, consumes parameters and func void gen_call(Item func); @@ -999,7 +1000,11 @@ void parse_primary_expr(Item x) { if (!compatible_type(param->type, y.type)) { error("incompatible type for parameter '%s'\n", param->name->text); } - gen_param(n, &y); + if (param->type->kind == tArray) { + gen_ref_param(n, &y); + } else { + gen_param(n, &y); + } param = param->next; n++; } @@ -1845,7 +1850,17 @@ u32 mul_op_to_ins(u32 op) { // parser does not know internal details like "which register is SP" // so the backend needs to initialize variable objects for it void gen_item_from_obj(Item x, Object obj) { - if ((obj->kind == oParam) || (obj->kind == oVar)) { + if (obj->kind == oParam) { + if (obj->type->kind == tArray) { + // arrays are passed by reference through parameters + // maybe this should be better represented? + u32 r = get_reg_tmp(); + emit_mem(LDW, r, SP, obj->value); + set_item(x, iRegInd, obj->type, r, 0, 0); + } else { + set_item(x, iRegInd, obj->type, SP, obj->value, 0); + } + } else if (obj->kind == oVar) { set_item(x, iRegInd, obj->type, SP, obj->value, 0); } else if (obj->kind == oGlobal) { set_item(x, iRegInd, obj->type, SB, obj->value, 0); @@ -1906,6 +1921,8 @@ void gen_load_reg(Item x, u32 r) { } x->kind = iReg; x->r = r; + x->a = 0; + x->b = 0; gen_trace("load_reg<<<", x, nil); } @@ -1944,21 +1961,33 @@ void gen_store(Item val, Item adr) { } } -// convert RegInd+off to RegInd+0 -// migrate to a tmpreg if not already -void gen_address(Item x) { - i32 r = x->r; - if (!is_tmp_reg(r)) { - r = get_reg_tmp(); +void gen_address_reg(Item x, i32 r) { + gen_trace_n("address_reg", r, x, nil); + if (x->kind != iRegInd) { + error("internal error, wrong kind"); } if (x->a > 0) { emit_opi_n(ADD, r, x->r, x->a); } else if(r != x->r) { emit_op(MOV, r, 0, x->r); } - x->r = r; + if (r != x->r) { + put_reg(x->r); + x->r = r; + } } +// convert RegInd+off to RegInd+0 +// migrate to a tmpreg if not already +void gen_address(Item x) { + if (!is_tmp_reg(x->r)) { + gen_address_reg(x, get_reg_tmp()); + } else { + gen_address_reg(x, x->r); + } +} + + void gen_index(Item x, Item idx) { gen_trace("index", x, idx); gen_address(x); @@ -2049,6 +2078,14 @@ void gen_return(Item x) { add_scope_fixup(find_scope(sFunc)); } +void gen_ref_param(u32 n, Item val) { + gen_trace_n("ref_param", n, val, nil); + if (n > 7) { + error("gen_ref_param - too many parameters"); + } + gen_address_reg(val, n); +} + void gen_param(u32 n, Item val) { gen_trace_n("param", n, val, nil); if (n > 7) { diff --git a/test/1041-arrays.log b/test/1041-arrays.log @@ -7,4 +7,12 @@ D 00000020 D 00000040 D 00000080 D 000000ff +D 00000010 +D 00000020 +D 00000030 +D 00000040 +D 00000050 +D 00000060 +D 00000070 +D 00000080 X 00000008 diff --git a/test/1041-arrays.src b/test/1041-arrays.src @@ -21,7 +21,6 @@ func start() i32 { n++; } _hexout_(m); - // todo: pass array refs correctly - //dump(data); + dump(data); return n; }