commit - 4ad9f211ea27642003a96861098c30b3fa400ae2
commit + e453131942fb3a20b680d275b691cd990e28e06d
blob - fed129b2a44c7f40698e6dc7c4d6e46c1e996fd4
blob + fd0bba6443b30a1a1f9fe59e05b22a5b92474144
--- cc/irc/irc.c
+++ cc/irc/irc.c
+#include <strings.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
+#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
-// use an arena to speed up memory allocations
+/* use an arena to speed up memory allocations */
#define ENABLE_ARENA 1
-// enable debugging prints
+/* enable debugging prints */
#define ENABLE_DEBUG 1
-// maximum number of registers per function
+/* maximum number of registers per function */
#define NREGS 128
-// maximum number of arguments for a function/call
+/* maximum number of arguments for a function/call */
#define MAXARGS 8
-// maximum number of PHI values
+/* maximum number of PHI values */
#define MAXPHI 8
int ignore_nan = 0;
-// ERROR HANDLING
+/* ERROR HANDLING */
int linenum;
return 0;
}
-// MEMORY
+/* MEMORY */
#if ENABLE_ARENA
{
void *ptr;
- // TODO: consider returning heap memory
+ /* TODO: consider returning heap memory */
if (alen + num > sizeof (arena))
error ("arena out of memory");
alen += num;
# if ENABLE_DEBUG
total_alloc += num;
-# endif // ENABLE_DEBUG
+# endif /* ENABLE_DEBUG */
memset (ptr, 0, num);
return ptr;
}
return s;
}
-// LEXER
+/* LEXER */
enum {
TK_INT = 128,
len = 0;
s = alloc (cap + 1);
- // TODO: implement escape sequences
+ /* TODO: implement escape sequences */
while ((ch = nextch ()) != '"') {
if (len == cap) {
cap *= 2;
}
}
-// AST DATA TYPES
+/* AST DATA TYPES */
enum dtype_type {
DT_NONE,
- DT_DPTR, // pointer to data memory (ds)
- DT_FPTR, // segment+pointer
- DT_SPTR, // pointer to stack memory (ss)
+ DT_DPTR, /* pointer to data memory (ds) */
+ DT_FPTR, /* segment+pointer */
+ DT_SPTR, /* pointer to stack memory (ss) */
DT_LABEL,
DT_BYTE,
DT_WORD,
};
enum expr_type {
- EX_REG, // .reg
- EX_INT, // .i
- EX_FLOAT, // .f
- EX_ALLOCA, // .alloca
- EX_ADD, // .bin
- EX_SUB, // .bin
- EX_AND, // .bin
- EX_OR, // .bin
- EX_XOR, // .bin
- EX_LSL, // .bin
- EX_LSR, // .bin
- EX_ASR, // .bin
- EX_MUL, // .bin
- EX_UDIV, // .bin
- EX_SDIV, // .bin
- EX_EQ, // .bin
- EX_NE, // .bin
- EX_ULT, // .bin
- EX_UGT, // .bin
- EX_ULE, // .bin
- EX_UGE, // .bin
- EX_SLT, // .bin
- EX_SGT, // .bin
- EX_SLE, // .bin
- EX_SGE, // .bin
- EX_FEQ, // .bin
- EX_FNE, // .bin
- EX_FLT, // .bin
- EX_FGT, // .bin
- EX_FLE, // .bin
- EX_FGE, // .bin
- EX_PTRADD, // .bin
- EX_READ, // .read
- EX_CALL, // .call
- EX_PHI, // .phi
- EX_PEXT, // .reg
- EX_ZEXT, // .reg
- EX_SEXT, // .reg
- EX_TRUNC, // .reg
- EX_PCAST, // .reg
- EX_LOOKUP, // .s
+ EX_REG, /* .reg */
+ EX_INT, /* .i */
+ EX_FLOAT, /* .f */
+ EX_ALLOCA, /* .alloca */
+ EX_ADD, /* .bin */
+ EX_SUB, /* .bin */
+ EX_AND, /* .bin */
+ EX_OR, /* .bin */
+ EX_XOR, /* .bin */
+ EX_LSL, /* .bin */
+ EX_LSR, /* .bin */
+ EX_ASR, /* .bin */
+ EX_MUL, /* .bin */
+ EX_UDIV, /* .bin */
+ EX_SDIV, /* .bin */
+ EX_EQ, /* .bin */
+ EX_NE, /* .bin */
+ EX_ULT, /* .bin */
+ EX_UGT, /* .bin */
+ EX_ULE, /* .bin */
+ EX_UGE, /* .bin */
+ EX_SLT, /* .bin */
+ EX_SGT, /* .bin */
+ EX_SLE, /* .bin */
+ EX_SGE, /* .bin */
+ EX_FEQ, /* .bin */
+ EX_FNE, /* .bin */
+ EX_FLT, /* .bin */
+ EX_FGT, /* .bin */
+ EX_FLE, /* .bin */
+ EX_FGE, /* .bin */
+ EX_PTRADD, /* .bin */
+ EX_READ, /* .read */
+ EX_CALL, /* .call */
+ EX_PHI, /* .phi */
+ EX_PEXT, /* .reg */
+ EX_ZEXT, /* .reg */
+ EX_SEXT, /* .reg */
+ EX_TRUNC, /* .reg */
+ EX_PCAST, /* .reg */
+ EX_LOOKUP, /* .s */
};
struct call {
char *s;
struct {
struct regimm num;
- int off; // only valid if ri.is_imm
+ int off; /* only valid if ri.is_imm */
} alloca;
struct {
int l;
enum ir_type {
IR_NOP,
- IR_LET, // .let
- IR_WRITE, // .write
- IR_RET, // .ri
- IR_LABEL, // .reg
- IR_GOTO, // .reg
- IR_BR, // .br
+ IR_LET, /* .let */
+ IR_WRITE, /* .write */
+ IR_RET, /* .ri */
+ IR_LABEL, /* .reg */
+ IR_GOTO, /* .reg */
+ IR_BR, /* .br */
};
struct ir {
- struct ir *next, *prev; // next/prev IR in current block
- struct ir *bnext, *bprev; // next/prev block of IR
- struct ir *bhead; // head of current IR block
+ struct ir *next, *prev; /* next/prev IR in current block */
+ struct ir *bnext, *bprev; /* next/prev block of IR */
+ struct ir *bhead; /* head of current IR block */
enum ir_type type;
int line;
struct dtype dt;
struct ir *ir;
- // R_LOCAL/R_PARAM: stack offset
- // R_LABEL: self-reference
+ /* R_LOCAL/R_PARAM: stack offset */
+ /* R_LABEL: self-reference */
int off;
};
};
enum symbol_type {
- SYM_FUNC, // .fn
- SYM_VAR, // .dt
+ SYM_FUNC, /* .fn */
+ SYM_VAR, /* .dt */
};
struct symbol {
};
};
-// (persistent)
+/* (persistent) */
struct symbol *symhead = NULL;
-// MISC
+/* MISC */
-// allocate temporary memory (freed after processing current unit)
+/* allocate temporary memory (freed after processing current unit) */
#define new(T) ((T *)alloc (sizeof (T)))
-// allocate persistent memory (not freed across units)
+/* allocate persistent memory (not freed across units) */
#define pnew(T) ((T *)pmalloc (sizeof (T)))
}
}
-// PARSER
+/* PARSER */
#define expect(exp) (lex () != (exp) ? error ("expected " #exp) : 0)
#define stalloc(fn, nbytes) ((fn)->stoff -= (((nbytes) + 1) & ~1))
if (tk != ';')
error ("invalid phi");
- // TODO: assert_dt_*
- // TODO: check that there are no instructions (except IR_LABEL) before this
+ /* TODO: assert_dt_* */
+ /* TODO: check that there are no instructions (except IR_LABEL) before this */
} else if (strcmp (lval.s, "pcast") == 0) {
e->type = EX_PCAST;
expect (TK_REG);
return 0;
}
-// return:
-// 0 = normal IR
-// 1 = end of basic block (e.g. goto)
-// 2 = start of basic block (label)
+/* return: */
+/* 0 = normal IR */
+/* 1 = end of basic block (e.g. goto) */
+/* 2 = start of basic block (label) */
stmt (fn, ir, tk)
struct func *fn;
struct ir *ir;
sym = sym_new (SYM_FUNC, fn->name, 0);
sym->fn.nargs = 0;
- // parse parameter list
+ /* parse parameter list */
while (1) {
tk = lex ();
switch (tk) {
}
switch (stmt (fn, ir, tk)) {
- case 0: // normal IR
+ case 0: /* normal IR */
if (bhead == NULL)
error ("dead instruction");
prev = ir;
break;
- case 1: // end of basic block
+ case 1: /* end of basic block */
if (bhead == NULL)
error ("invalid end of a basic block");
bhead = NULL;
prev = NULL;
break;
- case 2: // start of basic block
+ case 2: /* start of basic block */
if (prev != NULL || bhead != NULL)
error ("invalid start of a basic block");
return 0;
}
-// IR PRINTING
+/* IR PRINTING */
print_dt (file, dt)
FILE *file;
return 0;
}
-// ASM MISC
+/* ASM MISC */
int nlbl;
char *reg8[] = { "al", "bl", "cl", "dl" };
char *reg16[] = { "ax", "bx", "cx", "dx", "es" };
-// ASM GEN
+/* ASM GEN */
loadb (instr, dest, src)
char *instr;
case DT_SPTR:
if (imm != 0)
error ("it is illegal initialize a pointer to stack memory with anything else than 0");
- // fallthrough
+ /* fallthrough */
case DT_DWORD:
case DT_FPTR:
loadimmr (instr, "ax", imm & 0xffff);
}
}
-// yes, this function is absolutely ridiculous
+/* yes, this function is absolutely ridiculous */
loadpwri (fn, instr, dest, src, off)
struct func *fn;
char *instr;
return 0;
}
-// constant multiply
+/* constant multiply */
cmul (reg, i)
char *reg;
{
struct reg *reg;
struct regimm *shamt;
{
- // TODO: optimize byte-aligned shift (eg lsl $0, 8)
+ /* TODO: optimize byte-aligned shift (eg lsl $0, 8) */
struct dtype *dt = ®->dt;
assert (shamt->dt->type == DT_BYTE);
case DT_LDOUBLE:
fprintf (stderr, "%d: warning: loading an ldouble by immediate will cause the result to be truncated", linenum);
- // fallthrough
+ /* fallthrough */
case DT_DOUBLE:
printf ("\tpush %d\n", (int)((e->i >> 48) & 0xffff));
break;
case DT_LDOUBLE:
fprintf (stderr, "%d: warning: loading an ldouble by immediate will cause the result to be truncated", linenum);
- // fallthrough
+ /* fallthrough */
case DT_DOUBLE:
dbint.d = e->f;
printf ("\tpush %d\n", (int)((dbint.l >> 48) & 0xffff));
switch (dt->type) {
case DT_FPTR:
puts ("\tmov dx, ss");
- // fallthrough
+ /* fallthrough */
case DT_SPTR:
if (e->alloca.num.is_imm) {
printf ("\tlea ax, [bp + %d]\n", e->alloca.off);
break;
case DT_DWORD:
case DT_QWORD:
- // TODO: multiply using FPU
+ /* TODO: multiply using FPU */
call_muldiv ("mul", fn, dt, e);
break;
case DT_FLOAT:
printf ("\tadd sp, %d\n", cnt);
break;
case EX_PHI:
- // TODO: check that all sources actually jump to this phi.
- // It's correct that this is empty,
- // since the value is set in the jumping instruction.
+ /* TODO: check that all sources actually jump to this phi. */
+ /* It's correct that this is empty, */
+ /* since the value is set in the jumping instruction. */
break;
case EX_PEXT:
r = &fn->regs[e->reg];
return 0;
}
-// phi's are crazy. I'm surprised this actually works.
-// You are not expected to understand this.
+/* phi's are crazy. I'm surprised this actually works. */
+/* You are not expected to understand this. */
check_phi (fn, from, to)
struct func *fn;
struct ir *from;
struct expr *e;
int i, mylbl;
- // check for corruption of basic block structure
+ /* check for corruption of basic block structure */
assert (from->bhead != NULL && from->bhead->prev == NULL);
- // check that the destination is actually a label
+ /* check that the destination is actually a label */
assert_dt_label (&to->dt);
- // check if this jump can be referenced in a phi
+ /* check if this jump can be referenced in a phi */
if (from->bhead->type != IR_LABEL) {
if (from->bhead->bprev != NULL) {
- // this should never happen
+ /* this should never happen */
error ("broken basic block");
} else {
- // first instruction of a function
+ /* first instruction of a function */
return 0;
}
}
- // origin basic block label
+ /* origin basic block label */
mylbl = from->bhead->reg;
phi = to->ir->next;
assert (phi != NULL);
- // only the first instruction after a label can be a phi
+ /* only the first instruction after a label can be a phi */
if (phi->type != IR_LET || phi->let.val.type != EX_PHI)
return 0;
case DT_QWORD:
puts ("\tor ax, bx");
puts ("\tor ax, cx");
- // fallthrough
+ /* fallthrough */
case DT_DWORD:
case DT_FPTR:
puts ("\tor ax, dx");
- // fallthrough
+ /* fallthrough */
case DT_WORD:
case DT_DPTR:
case DT_SPTR:
case DT_FLOAT:
case DT_DOUBLE:
case DT_LDOUBLE:
- // TODO
+ /* TODO */
error ("TODO: IR_BR for floats");
break;
}
return 0;
}
-// MAIN
+/* MAIN */
main (void)
{