commit c9609c601b47b56b6e1843141a121fd207be61f1
parent 944cd3a1e6b81b2dceb5eca779fb07a2e82d68d3
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 31 May 2016 08:39:44 +0200
[cc2-qbe] Add basic support for calls in qbe
This is a preliminar patch which add supports for calls in qbe,
but it does not pass the parameters to the function call, so it
only can be used for functions without parameters. It also
does not support void functions.
Diffstat:
3 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h
@@ -132,4 +132,11 @@ enum asmop {
ASJMP,
ASBRANCH,
ASRET,
+ ASCALLB,
+ ASCALLH,
+ ASCALLW,
+ ASCALLS,
+ ASCALLL,
+ ASCALLD,
+ ASCALL,
};
diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
@@ -4,6 +4,7 @@
#include "arch.h"
#include "../../cc2.h"
+#include "../../../inc/sizes.h"
enum lflags {
FORCE = 1 << 0,
@@ -232,6 +233,38 @@ cast(Node *nd)
}
static Node *
+call(Node *np)
+{
+ int n, op;
+ Type *tp = &np->type;
+ Node *tmp, *p, *pars[NR_FUNPARAM];
+
+ for (n = 0, p = np->right; p; p = p->right)
+ pars[n] = cgen(p->left);
+
+ switch (tp->size) {
+ case 1:
+ op = ASCALLB;
+ break;
+ case 2:
+ op = ASCALLH;
+ break;
+ case 4:
+ op = (tp->flags & INTF) ? ASCALLW : ASCALLS;
+ break;
+ case 8:
+ op = (tp->flags & INTF) ? ASCALLL : ASCALLD;
+ break;
+ default:
+ abort();
+ }
+ code(op, tmpnode(np), np->left, NULL);
+ code(ASCALL, NULL, NULL, NULL);
+
+ return np;
+}
+
+static Node *
abbrev(Node *np)
{
Node *tmp;
@@ -259,8 +292,10 @@ cgen(Node *np)
return NULL;
setlabel(np->label);
- np->left = cgen(np->left);
- np->right = cgen(np->right);
+ if (np->op != OCALL) {
+ np->left = cgen(np->left);
+ np->right = cgen(np->right);
+ }
tp = &np->type;
switch (np->op) {
@@ -354,6 +389,7 @@ cgen(Node *np)
case OCOMMA:
return np->right;
case OCALL:
+ return call(np);
case OFIELD:
case OASK:
case OCOLON:
diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c
@@ -10,7 +10,7 @@
#define ADDR_LEN (INTIDENTSIZ+64)
static void binary(void), unary(void), store(void), jmp(void), ret(void),
- branch(void);
+ branch(void), call(void), ecall(void);
static struct opdata {
void (*fun)(void);
@@ -126,6 +126,13 @@ static struct opdata {
[ASBRANCH] = {.fun = branch},
[ASJMP] = {.fun = jmp},
[ASRET] = {.fun = ret},
+ [ASCALLB] = {.fun = call, .letter = 'b'},
+ [ASCALLH] = {.fun = call, .letter = 'h'},
+ [ASCALLW] = {.fun = call, .letter = 'w'},
+ [ASCALLS] = {.fun = call, .letter = 's'},
+ [ASCALLL] = {.fun = call, .letter = 'l'},
+ [ASCALLD] = {.fun = call, .letter = 'd'},
+ [ASCALL] = {.fun = ecall},
};
static char buff[ADDR_LEN];
@@ -396,6 +403,23 @@ unary(void)
}
static void
+call(void)
+{
+ struct opdata *p = &optbl[pc->op];
+ char to[ADDR_LEN], from[ADDR_LEN];
+
+ strcpy(to, addr2txt(&pc->to));
+ strcpy(from, addr2txt(&pc->from1));
+ printf("\t%s =%c\tcall\t%s(", to, p->letter, from);
+}
+
+static void
+ecall(void)
+{
+ puts(")");
+}
+
+static void
ret(void)
{
if (pc->from1.kind == SNONE)