commit - cb0082f76c61614ad0472450d9261e2b4f2f5a8e
commit + d25b45cd908aa3299de02f2507191f81b809ccec
blob - 4f23305e9e7be27e144bad3bccb5a7ae6dba821f
blob + 427805bfeeec25b80643c8f9cf56953e25109e7d
--- cc/irc/TODO
+++ cc/irc/TODO
- add function pointers
- rename DT_FPTR to DT_PTR
- implement builtin functions
+- support for double and long double
blob - 06da2b1c5ba8a468173c41413ce0c9a5a83164a8
blob + 148a4780ca0535b5c9b54ed2cb2d00a891441a32
--- cc/irc/irc.c
+++ cc/irc/irc.c
// enable debugging prints
#define ENABLE_DEBUG 1
-// enable support for floating point numbers
-#define ENABLE_FLOAT 1
-
// ERROR HANDLING
int linenum;
parse_int_or_float (int neg)
{
-#if ENABLE_FLOAT
long i = 0;
double f, s;
f = i;
s = 0.1;
+ nextch ();
while (isdigit (peekch ())) {
f = f + s * (nextch () - '0');
lval.f = neg ? -f : f;
return TK_FLOAT;
-#else
- parse_int ();
- if (neg)
- lval.i = -lval.i;
- return TK_INT;
-#endif
}
isname (ch)
DT_WORD,
DT_DWORD,
DT_QWORD,
+ DT_FLOAT,
};
struct dtype {
union {
int reg;
long imm;
+ double f;
};
};
enum expr_type {
EX_REG, // .reg
EX_INT, // .i
+ EX_FLOAT, // .f
EX_ALLOCA, // .alloca
EX_ADD, // .bin
EX_SUB, // .bin
union {
int reg;
long i;
+ double f;
struct {
int num;
int off;
return 2;
case DT_DWORD:
case DT_FPTR:
+ case DT_FLOAT:
return 4;
case DT_QWORD:
return 8;
return 0;
}
+assert_dt_is_number (dt)
+struct dtype *dt;
+{
+ switch (dt->type) {
+ case DT_BYTE:
+ case DT_WORD:
+ case DT_DWORD:
+ case DT_QWORD:
+ case DT_FLOAT:
+ return 0;
+ case DT_NONE:
+ case DT_LABEL:
+ case DT_DPTR:
+ case DT_FPTR:
+ case DT_SPTR:
+ return error ("this operation is only supported for numbers (byte, word, dword, qword, float)");
+ }
+}
+
assert_dt_is_int (dt)
struct dtype *dt;
{
case DT_DWORD:
case DT_QWORD:
return 0;
+ case DT_FLOAT:
case DT_NONE:
case DT_LABEL:
case DT_DPTR:
dt->type = DT_DWORD;
} else if (strcmp (lval.s, "qword") == 0) {
dt->type = DT_QWORD;
+ } else if (strcmp (lval.s, "float") == 0) {
+ dt->type = DT_FLOAT;
} else {
err:
error ("expected dtype");
return 0;
}
-expr_bin (fn, dt, e, t)
+expr_bin (fn, dt, e, t, allow_float)
struct func *fn;
struct dtype *dt;
struct expr *e;
assert_dt_eq (dt, &fn->regs[e->bin.l].dt);
assert_dt_eq (dt, e->bin.r.dt);
- assert_dt_is_int (dt);
+
+ if (allow_float) {
+ assert_dt_is_number (dt);
+ } else {
+ assert_dt_is_int (dt);
+ }
return 0;
}
expect (';');
assert_dt_eq (dt, &fn->regs[e->reg].dt);
return 0;
+ } else if (tk == TK_FLOAT) {
+ e->type = EX_FLOAT;
+ e->f = lval.f;
+ expect (';');
+ return 0;
}
if (tk != TK_IDENT)
e->alloca.off = fn->stoff;
expect (';');
} else if (strcmp (lval.s, "add") == 0) {
- expr_bin (fn, dt, e, EX_ADD);
+ expr_bin (fn, dt, e, EX_ADD, 1);
} else if (strcmp (lval.s, "sub") == 0) {
- expr_bin (fn, dt, e, EX_SUB);
+ expr_bin (fn, dt, e, EX_SUB, 1);
} else if (strcmp (lval.s, "and") == 0) {
- expr_bin (fn, dt, e, EX_AND);
+ expr_bin (fn, dt, e, EX_AND, 0);
} else if (strcmp (lval.s, "or") == 0) {
- expr_bin (fn, dt, e, EX_OR);
+ expr_bin (fn, dt, e, EX_OR, 0);
} else if (strcmp (lval.s, "xor") == 0) {
- expr_bin (fn, dt, e, EX_XOR);
+ expr_bin (fn, dt, e, EX_XOR, 0);
} else if (strcmp (lval.s, "mul") == 0) {
- expr_bin (fn, dt, e, EX_MUL);
+ expr_bin (fn, dt, e, EX_MUL, 1);
} else if (strcmp (lval.s, "udiv") == 0) {
- expr_bin (fn, dt, e, EX_UDIV);
+ expr_bin (fn, dt, e, EX_UDIV, 0);
} else if (strcmp (lval.s, "sdiv") == 0) {
- expr_bin (fn, dt, e, EX_SDIV);
+ expr_bin (fn, dt, e, EX_SDIV, 1);
} else if (strcmp (lval.s, "lsl") == 0) {
expr_shift (fn, dt, e, EX_LSL);
} else if (strcmp (lval.s, "lsr") == 0) {
expect (TK_IDENT);
}
- fprintf (stderr, "%s\n", lval.s);
if (strcmp (lval.s, "section") == 0) {
expect (TK_STRING);
section = lval.s;
break;
case DT_QWORD:
printf ("qword");
+ break;
+ case DT_FLOAT:
+ printf ("float");
break;
case DT_DPTR:
putchar ('*');
switch (e->type) {
case EX_INT:
printf ("%ld", e->i);
+ break;
+ case EX_FLOAT:
+ printf ("%f", e->f);
break;
case EX_REG:
printf ("$%d", e->reg);
return loadw (instr, AX, src);
case DT_DWORD:
case DT_FPTR:
+ case DT_FLOAT:
return loaddw (instr, src);
case DT_QWORD:
return loadqw (instr, src);
// fallthrough
case DT_DWORD:
case DT_FPTR:
+ case DT_FLOAT:
loadimmr (instr, "ax", imm & 0xffff);
loadimmr (instr, "dx", (imm >> 16) & 0xffff);
break;
case DT_DPTR:
case DT_FPTR:
case DT_SPTR:
- error ("cannot add/sub pointers");
+ case DT_FLOAT:
+ error ("cannot add/sub pointers or floats");
break;
}
return 0;
switch (dt->type) {
case DT_NONE:
case DT_LABEL:
+ case DT_FLOAT:
abort ();
break;
case DT_DPTR:
case DT_DPTR:
case DT_FPTR:
case DT_SPTR:
+ case DT_FLOAT:
abort ();
break;
case DT_BYTE:
case DT_QWORD:
call_muldiv (instr, fn, dt, e);
break;
+ case DT_FLOAT:
+ error ("division not implemented for DT_FLOAT");
+ break;
}
return 0;
}
struct dtype *dt;
struct expr *e;
{
+ union {
+ float f;
+ int32_t i;
+ } flint;
struct regimm *ri;
struct reg *r;
char *s;
switch (e->type) {
case EX_INT:
- loadimm (NULL, dt, e->i);
+ switch (dt->type) {
+ case DT_NONE:
+ case DT_LABEL:
+ abort ();
+ break;
+
+ case DT_BYTE:
+ case DT_WORD:
+ case DT_DWORD:
+ case DT_QWORD:
+ case DT_DPTR:
+ case DT_FPTR:
+ case DT_SPTR:
+ loadimm (NULL, dt, e->i);
+ break;
+
+ case DT_FLOAT:
+ printf ("\tpush %d\n", (int)((e->i >> 16) & 0xffff));
+ printf ("\tpush %d\n", (int)(e->i & 0xffff));
+ puts ("\tmov bx, sp");
+ puts ("\tfild dword [bx]");
+ puts ("\tadd sp, 4");
+ break;
+ }
+ break;
+ case EX_FLOAT:
+ switch (dt->type) {
+ case DT_FLOAT:
+ flint.f = e->f;
+ printf ("\tpush %d\n", (int)((flint.i >> 16) & 0xffff));
+ printf ("\tpush %d\n", (int)(flint.i & 0xffff));
+ puts ("\tmov bx, sp");
+ puts ("\tfld dword [bx]");
+ puts ("\tadd sp, 4");
+ break;
+
+ case DT_NONE:
+ case DT_LABEL:
+ case DT_DPTR:
+ case DT_FPTR:
+ case DT_SPTR:
+ case DT_BYTE:
+ case DT_WORD:
+ case DT_DWORD:
+ case DT_QWORD:
+ abort ();
+ break;
+ }
break;
case EX_REG:
case EX_PCAST:
// TODO: multiply using FPU
call_muldiv ("mul", fn, dt, e);
break;
+ case DT_FLOAT:
+ error ("multiplication not implemented for DT_FLOAT");
+ break;
}
break;
case EX_UDIV:
break;
case DT_DWORD:
case DT_FPTR:
+ case DT_FLOAT:
printf ("\tmov ax, word [%s + %d * 4 + 0]\n", s, e->read.off);
printf ("\tmov dx, word [%s + %d * 4 + 2]\n", s, e->read.off);
break;
break;
case DT_DWORD:
case DT_FPTR:
+ case DT_FLOAT:
puts ("\tpush dx");
puts ("\tpush ax");
break;
case DT_FPTR:
case DT_SPTR:
case DT_BYTE:
+ case DT_FLOAT:
abort ();
break;
case DT_WORD:
case DT_FPTR:
case DT_SPTR:
case DT_BYTE:
+ case DT_FLOAT:
abort ();
break;
case DT_WORD:
case DT_FPTR:
case DT_SPTR:
case DT_QWORD:
+ case DT_FLOAT:
abort ();
break;
case DT_DWORD:
printf ("\tmov word [ss:bp + %d + 4], bx\n", r->off);
printf ("\tmov word [ss:bp + %d + 6], cx\n", r->off);
break;
+ case DT_FLOAT:
+ printf ("\tfstp dword [ss:bp + %d]\n", r->off);
+ break;
}
break;
case IR_WRITE:
break;
case DT_DWORD:
case DT_FPTR:
+ case DT_FLOAT:
printf ("\tmov word [%s + %d * 4 + 0], ax\n", reg, ir->write.off);
printf ("\tmov word [%s + %d * 4 + 2], dx\n", reg, ir->write.off);
break;
case DT_SPTR:
puts ("\ttest ax, ax");
break;
+ case DT_FLOAT:
+ error ("TODO: IR_BR for DT_FLOAT");
+ break;
}
check_phi (fn, ir, &fn->regs[ir->br.yes]);
blob - 05c15c8dcacdf5ca56fbddf41a9e6cea2c331754
blob + fd81b7745aec197bf813bfd56d8670172c319f2d
--- cc/irc/test.ir
+++ cc/irc/test.ir
pub section ".text.custom" fn custom_section (): qword {
ret 0;
}
+
+fn floats (): float {
+ let $0: float = 1.2;
+ let $1: float = 42;
+ ret $0;
+}