shithub: scc

Download patch

ref: 9207b9207c803a7af47b567badd3d5eb22ebfa3f
parent: c8caef1d8146964be3fe2ca62b59306c393fa77e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Apr 22 13:14:09 EDT 2016

[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.

--- a/cc2/arch/qbe/arch.h
+++ b/cc2/arch/qbe/arch.h
@@ -104,4 +104,25 @@
 	ASBORD,
 	ASBXORD,
 	ASCPLD,
+
+	ASEXTBW,
+	ASUEXTBW,
+	ASEXTBL,
+	ASUEXTBL,
+	ASEXTHW,
+	ASUEXTHW,
+	ASEXTHL,
+	ASUEXTHL,
+	ASEXTWL,
+	ASUEXTWL,
+
+	ASSTOL,
+	ASSTOW,
+	ASDTOL,
+	ASDTOW,
+
+	ASSWTOD,
+	ASSWTOS,
+	ASSLTOD,
+	ASSLTOS
 };
--- 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 @@
 	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 @@
 	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();
--- a/cc2/arch/qbe/code.c
+++ b/cc2/arch/qbe/code.c
@@ -9,7 +9,7 @@
 
 #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);
@@ -16,12 +16,12 @@
 	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 @@
 	[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 @@
 }
 
 static void
-load(void)
+unary(void)
 {
 	struct opdata *p = &optbl[pc->op];
 	char to[ADDR_LEN], from[ADDR_LEN];