commit 8013c0388602bef2e589f867a9bff8fa196247c7
parent f6ede3c51c169d6115b12de5cce5b1881d0b3247
Author: Roberto E. Vargas Caballero <Roberto E. Vargas Caballero>
Date: Fri, 22 Apr 2016 17:14:09 +0200
[cc2-qbe] Add conversion between types
After this patch, we can begin to use char and short,
because they are correctly promoted. It also includes
conversion between float-float, integer-float and float-integer.
Diffstat:
3 files changed, 122 insertions(+), 9 deletions(-)
diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h
@@ -104,4 +104,25 @@ enum asmop {
ASBORD,
ASBXORD,
ASCPLD,
+
+ ASEXTBW,
+ ASUEXTBW,
+ ASEXTBL,
+ ASUEXTBL,
+ ASEXTHW,
+ ASUEXTHW,
+ ASEXTHL,
+ ASUEXTHL,
+ ASEXTWL,
+ ASUEXTWL,
+
+ ASSTOL,
+ ASSTOW,
+ ASDTOL,
+ ASDTOW,
+
+ ASSWTOD,
+ ASSWTOS,
+ ASSLTOD,
+ ASSLTOS
};
diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
@@ -1,4 +1,5 @@
+#include <assert.h>
#include <stdlib.h>
#include "arch.h"
@@ -135,6 +136,76 @@ load(Node *np)
return new;
}
+static Node *
+cast(Node *nd, Node *ns)
+{
+ Type *ts, *td;
+ Node *tmp;
+ int op, disint, sisint;
+ extern Type uint32type, int32type;
+
+ if ((ns->flags & (ISTMP|ISCONS)) == 0)
+ ns = nd->left = load(ns);
+ td = &nd->type;
+ ts = &ns->type;
+ disint = (td->flags & INTF) != 0;
+ sisint = (ts->flags & INTF) != 0;
+
+ if (disint && sisint) {
+ if (td->size <= ts->size)
+ return nd;
+ assert(td->size == 4 || td->size == 8);
+ switch (ts->size) {
+ case 1:
+ op = (td->size == 4) ? ASEXTBW : ASEXTBL;
+ break;
+ case 2:
+ op = (td->size == 4) ? ASEXTHW : ASEXTHL;
+ break;
+ case 4:
+ op = ASEXTWL;
+ break;
+ default:
+ abort();
+ }
+ op += (td->flags & SIGNF) == 0;
+ } else if (disint) {
+ /* conversion from float to int */
+ switch (ts->size) {
+ case 4:
+ op = (td->size == 8) ? ASSTOL : ASSTOW;
+ break;
+ case 8:
+ op = (td->size == 8) ? ASDTOL : ASDTOW;
+ break;
+ default:
+ abort();
+ }
+ /* TODO: Add signess */
+ } else {
+ /* conversion from int to float */
+ switch (ts->size) {
+ case 1:
+ case 2:
+ tmp = tmpnode(newnode());
+ tmp->type = (ts->flags&SIGNF) ? int32type : uint32type;
+ tmp->left = ns;
+ nd->left = ns = cast(tmp, ns);
+ case 4:
+ op = (td->size == 8) ? ASSWTOD : ASSWTOS;
+ break;
+ case 8:
+ op = (td->size == 8) ? ASSLTOD : ASSLTOS;
+ break;
+ default:
+ abort();
+ }
+ /* TODO: Add signess */
+ }
+ code(op, tmpnode(nd), ns, NULL);
+ return nd;
+}
+
Node *
cgen(Node *np)
{
@@ -206,11 +277,13 @@ cgen(Node *np)
case OBLOOP:
case OELOOP:
return NULL;
+ case OCAST:
+ assert(r == NULL);
+ return cast(np, l);
case OPAR:
case ONEG:
case OADDR:
case OPTR:
- case OCAST:
case OINC:
case ODEC:
abort();
diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c
@@ -9,19 +9,19 @@
#define ADDR_LEN (IDENTSIZ+64)
-static void binary(void), load(void), store(void);
+static void binary(void), unary(void), store(void);
static struct opdata {
void (*fun)(void);
char *txt;
char letter;
} optbl [] = {
- [ASLDB] = {.fun = load, .txt = "load", .letter = 'b'},
- [ASLDH] = {.fun = load, .txt = "load", .letter = 'h'},
- [ASLDW] = {.fun = load, .txt = "load", .letter = 'w'},
- [ASLDL] = {.fun = load, .txt = "load", .letter = 'l'},
- [ASLDS] = {.fun = load, .txt = "load", .letter = 's'},
- [ASLDD] = {.fun = load, .txt = "load", .letter = 'd'},
+ [ASLDB] = {.fun = unary, .txt = "load", .letter = 'b'},
+ [ASLDH] = {.fun = unary, .txt = "load", .letter = 'h'},
+ [ASLDW] = {.fun = unary, .txt = "load", .letter = 'w'},
+ [ASLDL] = {.fun = unary, .txt = "load", .letter = 'l'},
+ [ASLDS] = {.fun = unary, .txt = "load", .letter = 's'},
+ [ASLDD] = {.fun = unary, .txt = "load", .letter = 'd'},
[ASSTB] = {.fun = store, .txt = "store", .letter = 'b'},
[ASSTH] = {.fun = store, .txt = "store", .letter = 'h'},
@@ -99,6 +99,25 @@ static struct opdata {
[ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'},
[ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'},
[ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'},
+
+ [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'},
+ [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'},
+ [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'},
+ [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'},
+ [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'},
+ [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'},
+ [ASEXTWL] = {.fun = unary, .txt = "extsh", .letter = 'l'},
+ [ASUEXTWL]= {.fun = unary, .txt = "extuh", .letter = 'l'},
+
+ [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
+ [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
+ [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
+ [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
+
+ [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
+ [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
+ [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
+ [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
};
/*
@@ -354,7 +373,7 @@ store(void)
}
static void
-load(void)
+unary(void)
{
struct opdata *p = &optbl[pc->op];
char to[ADDR_LEN], from[ADDR_LEN];