static void print_expr(char k, const struct ir* ir)
{
- tracef(k, "%s", ir_names[ir->opcode]);
+ tracef(k, "%s", ir_data[ir->opcode].name);
if (ir->size)
tracef(k, "%d", ir->size);
+ if (ir->type)
+ tracef(k, ".%s",
+ ((ir->type == IRT_INT) ? "I" :
+ (ir->type == IRT_FLOAT) ? "F" :
+ (ir->type == IRT_ANY) ? "*" :
+ "?"));
tracef(k, "(");
switch (ir->opcode)
#include "ircodes.h"
-enum
-{
- IRR_LB = -1,
- IRR_AB = -2,
- IRR_SP = -3,
- IRR_RR = -4,
-};
-
-enum
-{
- IRS_1,
- IRS_2,
- IRS_4,
- IRS_8
-};
-
struct ir
{
int id;
enum ir_opcode opcode;
int size;
+ enum ir_type type;
struct ir* left;
struct ir* right;
union
extern void pass_remove_dead_blocks(struct procedure* proc);
extern void pass_eliminate_trivial_blocks(struct procedure* proc);
extern void pass_instruction_selector(struct procedure* proc);
+extern void pass_type_inference(struct procedure* proc);
extern void procedure_compile(struct procedure* proc);
--- /dev/null
+#include "mcg.h"
+
+static enum ir_type search_for_type(struct ir* ir, enum ir_type desired)
+{
+ const struct ir_data* data;
+
+ if (ir->type != IRT_UNSET)
+ return ir->type;
+
+ data = &ir_data[ir->opcode];
+ if (ir->left)
+ ir->left->type = search_for_type(ir->left, data->lefttype);
+ if (ir->right)
+ ir->right->type = search_for_type(ir->right, data->righttype);
+
+ switch (data->returntype)
+ {
+ case IRT_ANY:
+ if (desired == IRT_FLOAT)
+ ir->opcode++;
+ return desired;
+
+ case IRT_UNSET:
+ assert(!((data->lefttype == IRT_ANY) && (data->righttype == IRT_ANY)));
+ if (((data->lefttype == IRT_ANY) && (ir->left->type == IRT_FLOAT)) ||
+ ((data->righttype == IRT_ANY) && (ir->right->type == IRT_FLOAT)))
+ {
+ ir->opcode++;
+ return IRT_FLOAT;
+ }
+ if ((data->lefttype == IRT_ANY) && (ir->left->type == IRT_ANY))
+ ir->left->type = IRT_INT;
+ if ((data->righttype == IRT_ANY) && (ir->right->type == IRT_ANY))
+ ir->right->type = IRT_INT;
+ return IRT_INT;
+
+ default:
+ return data->returntype;
+ }
+}
+
+static void push_types_up(struct basicblock* bb)
+{
+ int i;
+
+ for (i=0; i<bb->irs_count; i++)
+ {
+ struct ir* ir = bb->irs[i];
+ ir->type = search_for_type(ir, ir->type);
+ }
+}
+
+void pass_type_inference(struct procedure* proc)
+{
+ int i;
+
+ for (i=0; i<proc->blocks_count; i++)
+ push_types_up(proc->blocks[i]);
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
+
pass_eliminate_trivial_blocks(proc);
pass_remove_dead_blocks(proc);
pass_convert_stack_ops(proc);
+ pass_type_inference(proc);
print_blocks('2', proc);
normalrule {
name = "ircodes",
- outleaves = { "ircodes.h", "ircodes.c" },
+ outleaves = { "ircodes-dyn.h", "ircodes.c" },
ins = {
"./ircodes.sh",
"./ir.dat"
clibrary {
name = "lib",
srcs = {
- matching(filenamesof("+ircodes"), "%.c$")
+ matching(filenamesof("+ircodes"), "%.c$"),
+ },
+ deps = {
+ "+ircodes",
+ "./ircodes.h"
},
hdrs = {
matching(filenamesof("+ircodes"), "%.h$"),
+ "./ircodes.h",
"./mcgg.h"
}
}
return p;
}
-static void registerterminal(const char* name, int iropcode, int size)
+static void registerterminal(const struct ir_data* data, int iropcode, int size)
{
- const char* s = (size == 0) ? name : stringf("%s%d", name, size);
+ const char* s = (size == 0) ? data->name : stringf("%s%d", data->name, size);
int esn = ir_to_esn(iropcode, size);
term(s, esn);
for (i=0; i<IR__COUNT; i++)
{
- if (ir_flags[i] & IRF_SIZED)
+ if (ir_data[i].flags & IRF_SIZED)
{
- registerterminal(ir_names[i], i, 1);
- registerterminal(ir_names[i], i, 2);
- registerterminal(ir_names[i], i, 4);
- registerterminal(ir_names[i], i, 8);
+ registerterminal(&ir_data[i], i, 1);
+ registerterminal(&ir_data[i], i, 2);
+ registerterminal(&ir_data[i], i, 4);
+ registerterminal(&ir_data[i], i, 8);
}
else
- registerterminal(ir_names[i], i, 0);
+ registerterminal(&ir_data[i], i, 0);
}
}
# Flags:
# S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
# V: has no size (use in JUMP, CJUMP, RET forms)
+#
+# Types:
+# I, F: integer, float
+# A: any (will be coerced to I or F during IR postprocessing)
+#
+# Any instruction with an A type must be followed by the corresponding F
+# version.
# Simple terminals
-S CONST
-S REG
-S LABEL
-S BLOCK
-V PAIR
-S ANY
-S LOCAL
-S PHI
+SA.. CONST
+SF.. CONSTF
+SA.. REG
+SF.. REGF
+SI.. LABEL
+SI.. BLOCK
+V... PAIR
+SA.. ANY
+SF.. ANYF
+S... LOCAL
+S... PHI
# Magic stack operations
-S PUSH
-S POP
+S.A. PUSH
+S.F. PUSHF
+SA.. POP
+SF.. POPF
+
+#... Memory operations
+SAI. LOAD
+SFI. LOADF
+S.IA STORE
+S.IF STOREF
-# Memory operations
-S LOAD
-S STORE
-
# Arithemetic operations
-S ADD
-S SUB
-S MUL
-S DIV
-S MOD
-S NEG
-
-S ADDF
-S SUBF
-S MULF
-S DIVF
-S NEGF
-
-S AND
-S OR
-S EOR
-S NOT
-
+SIII ADD
+SIII SUB
+SIII MUL
+SIII DIV
+SIII MOD
+SIII NEG
+
+SFFF ADDF
+SFFF SUBF
+SFFF MULF
+SFFF DIVF
+SFFF NEGF
+
+SIII AND
+SIII OR
+SIII EOR
+SIII NOT
+
# Conversions
-S CII1
-S CII2
-S CII4
-S CII8
-
-S CIU1
-S CIU2
-S CIU4
-S CIU8
-
+SIII CII1
+SIII CII2
+SIII CII4
+SIII CII8
+
+SIII CIU1
+SIII CIU2
+SIII CIU4
+SIII CIU8
+
# Tristate comparisons
-S COMPARES
-S COMPAREU
-
+SIII COMPARES
+SIII COMPAREU
+
# Boolean comparisons
-S IFEQ
-S IFLT
-S IFLE
-
+SIII IFEQ
+SIII IFLT
+SIII IFLE
+
# Procedures
-V CALL
-
+VI.. CALL
+
# Flow control --- these never return
-V JUMP
-V CJUMPEQ
-V CJUMPLT
-V CJUMPLE
-V RET
+V.I. JUMP
+VIII CJUMPEQ
+VIII CJUMPLT
+VIII CJUMPLE
+V... RET
# Special
-S STACKADJUST
-S GETRET
-S SETRET
+SI.. STACKADJUST
+SA.. GETRET
+SF.. GETRETF
+S.A. SETRET
+S.F. SETRETF
--- /dev/null
+#ifndef IRCODES_H
+#define IRCODES_H
+
+enum
+{
+ IRF_SIZED = 1,
+};
+
+enum ir_type
+{
+ IRT_UNSET = 0,
+ IRT_INT,
+ IRT_FLOAT,
+ IRT_ANY
+};
+
+struct ir_data
+{
+ const char* name;
+ int flags;
+ enum ir_type returntype;
+ enum ir_type lefttype;
+ enum ir_type righttype;
+};
+
+extern const struct ir_data ir_data[];
+
+#include "ircodes-dyn.h"
+
+#endif
+
+/* vim: set sw=4 ts=4 expandtab : */
+
END {
print "\tIR__COUNT"
print "};"
- print ""
- print "enum {"
- print "\tIRF_SIZED = 1"
- print "};"
- print ""
- print "extern const char* ir_names[IR__COUNT];"
- print "extern const char ir_flags[IR__COUNT];"
}
EOF
awk -f - $in >$source << "EOF"
BEGIN {
print "#include \"ircodes.h\""
- print "const char* ir_names[IR__COUNT] = {"
- }
-
- /^ *[^# ]+/ {
- printf("\t\"%s\",\n", $2)
+ print "const struct ir_data ir_data[IR__COUNT] = {"
}
- END {
- print "};"
+ function char_to_type(c) {
+ if (c == "I") return "IRT_INT"
+ if (c == "F") return "IRT_FLOAT"
+ if (c == "A") return "IRT_ANY"
+ return "IRT_UNSET"
}
-EOF
-awk -f - $in >>$source << "EOF"
- BEGIN {
- print ""
- print "const char ir_flags[IR__COUNT] = {"
+ function char_to_flags(c) {
+ if (c == "S") return "IRF_SIZED"
+ return "0"
}
/^ *[^# ]+/ {
- if ($1 == "S")
- print("\tIRF_SIZED,")
- else
- print("\t0,")
+ printf("\t{ \"%s\", ", $2)
+ printf("%s, ", char_to_flags(substr($1, 1, 1)))
+ printf("%s, ", char_to_type(substr($1, 2, 1)))
+ printf("%s, ", char_to_type(substr($1, 3, 1)))
+ printf("%s", char_to_type(substr($1, 4, 1)))
+ printf(" },\n")
}
END {