commit d88ed58bf9b8a45370f057a87445dc2999f8925f
parent 07224cfd65b66af47614403abb395efc5220c230
Author: Brian Swetland <swetland@frotz.net>
Date: Tue, 7 Dec 2021 02:46:00 -0800
compiler2: progress
- codegen for INDEXing arrays
- fix typo in ast kind name array
- tidy up SYM_IS_* flags and add _REFERENCE
- set type in AST_NAME nodes
Diffstat:
2 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/src/codegen-risc5-simple.c b/src/codegen-risc5-simple.c
@@ -381,6 +381,50 @@ u32 gen_logical_op(Ast node, u32 cc, u32 sc) {
return r;
}
+u32 gen_array_addr(Ast node) {
+ err_ast = node;
+ if (node->type->kind != TYPE_ARRAY) {
+ error("cannot deref non-array type");
+ }
+ if (node->kind == AST_NAME) {
+ u32 base;
+ i32 offset;
+ sym_get_loc(node->sym, &base, &offset);
+ u32 r = get_reg_tmp();
+ if (node->sym->kind == SYM_PARAM) {
+ // arrays here are ptr-to-array, so deref that
+ emit_mem(LDW, r, base, offset);
+ } else {
+ // arrays elsewhere are inline, so just add offset
+ emit_opi(ADD, r, base, offset);
+ }
+ return r;
+ } else if (node->kind == AST_INDEX) {
+ error("not ready for [][]");
+ } else {
+ error("cannot dereference this");
+ }
+ return 0;
+}
+
+u32 gen_array_read(Ast node) {
+ u32 raddr = gen_array_addr(node->c0);
+ u32 roff = gen_expr(node->c1);
+
+ u32 sz = node->c0->type->base->size;
+ if (sz > 1) {
+ emit_opi(MUL, roff, roff, sz);
+ }
+ emit_op(ADD, raddr, raddr, roff);
+ if (sz == 1) {
+ emit_mem(LDB, roff, raddr, 0);
+ } else {
+ emit_mem(LDW, roff, raddr, 0);
+ }
+ put_reg(raddr);
+ return roff;
+}
+
u32 gen_expr(Ast node) {
err_ast = node;
gen_src_xref(node);
@@ -437,6 +481,8 @@ u32 gen_expr(Ast node) {
return r;
} else if (node->kind == AST_CALL) {
return gen_call(node);
+ } else if (node->kind == AST_INDEX) {
+ return gen_array_read(node);
} else {
error("gen_expr cannot handle %s\n", ast_kind[node->kind]);
}
diff --git a/src/compiler2.c b/src/compiler2.c
@@ -95,8 +95,8 @@ enum {
str ast_kind[AST_FIELD + 1] = {
"NAME", "U32", "STR", "BINOP", "UNOP", "DEREF", "INDEX",
"BLOCK", "EXPR", "CALL", "WHILE", "IF",
- "RETURN", "BREAK", "CONTINUE", "IFELSE"
- "LOCAL", "PROGRAM", "TYPEDEF", "ENUMDEF", "FUNCDEF",
+ "RETURN", "BREAK", "CONTINUE", "IFELSE",
+ "PROGRAM", "TYPEDEF", "ENUMDEF", "FUNCDEF",
"GLOBAL", "LOCAL", "FIELD",
};
@@ -139,7 +139,7 @@ struct TypeRec {
Type base; // pointer-to, func-return-type, array-of
Symbol sym; // if not anonymous
Symbol first; // list of params or fields
- u32 len; // array, params
+ u32 len; // array elem count, param count
u32 size; // in bytes, local stack for funcs
};
@@ -158,11 +158,12 @@ str sym_kind[SYM_FIELD + 1] = {
};
enum {
- SYM_IS_READ_ONLY = 1,
- SYM_IS_PUBLIC = 2,
- SYM_IS_DEFINED = 4,
- SYM_IS_BUILTIN = 8,
- SYM_IS_PLACED = 16, // exists at addr in sym->value
+ SYM_IS_READ_ONLY = 0x01,
+ SYM_IS_PUBLIC = 0x02,
+ SYM_IS_DEFINED = 0x04,
+ SYM_IS_BUILTIN = 0x08,
+ SYM_IS_PLACED = 0x10, // exists at addr in sym->value
+ SYM_IS_REFERENCE = 0x20, // stored as pointer-to-type
};
struct SymbolRec {
@@ -1109,6 +1110,7 @@ Ast parse_operand() {
}
node = ast_make_name(ctx.ident);
node->sym = sym;
+ node->type = sym->type;
} else {
error("invalid expression");
}