scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

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:
cc2/arch/qbe/arch.h | 21+++++++++++++++++++++
cc2/arch/qbe/cgen.c | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
cc2/arch/qbe/code.c | 35+++++++++++++++++++++++++++--------
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];