Re-re-add the type inference layer, now I know more about how things work.
Remove that terrible float promotion code.
This commit is contained in:
parent
11b0bc1055
commit
b1a3d76d6f
|
@ -105,7 +105,9 @@ struct ir* ir_find(struct ir* ir, int opcode)
|
||||||
static void print_expr(char k, const struct ir* ir)
|
static void print_expr(char k, const struct ir* ir)
|
||||||
{
|
{
|
||||||
tracef(k, "%s", ir_data[ir->opcode].name);
|
tracef(k, "%s", ir_data[ir->opcode].name);
|
||||||
if (ir->size)
|
if (ir->type)
|
||||||
|
tracef(k, ".%c", ir->type);
|
||||||
|
else if (ir->size)
|
||||||
tracef(k, "%d", ir->size);
|
tracef(k, "%d", ir->size);
|
||||||
tracef(k, "(");
|
tracef(k, "(");
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ struct ir
|
||||||
int id;
|
int id;
|
||||||
enum ir_opcode opcode;
|
enum ir_opcode opcode;
|
||||||
int size;
|
int size;
|
||||||
|
char type;
|
||||||
struct ir* left;
|
struct ir* left;
|
||||||
struct ir* right;
|
struct ir* right;
|
||||||
struct ir* root;
|
struct ir* root;
|
||||||
|
|
|
@ -109,11 +109,11 @@ extern void pass_convert_stack_ops(void);
|
||||||
extern void pass_eliminate_trivial_blocks(void);
|
extern void pass_eliminate_trivial_blocks(void);
|
||||||
extern void pass_find_phi_congruence_groups(void);
|
extern void pass_find_phi_congruence_groups(void);
|
||||||
extern void pass_group_irs(void);
|
extern void pass_group_irs(void);
|
||||||
|
extern void pass_infer_types(void);
|
||||||
extern void pass_insert_moves(void);
|
extern void pass_insert_moves(void);
|
||||||
extern void pass_instruction_selector(void);
|
extern void pass_instruction_selector(void);
|
||||||
extern void pass_live_vreg_analysis(void);
|
extern void pass_live_vreg_analysis(void);
|
||||||
extern void pass_add_prologue_epilogue(void);
|
extern void pass_add_prologue_epilogue(void);
|
||||||
extern void pass_promote_float_ops(void);
|
|
||||||
extern void pass_register_allocator(void);
|
extern void pass_register_allocator(void);
|
||||||
extern void pass_remove_dead_blocks(void);
|
extern void pass_remove_dead_blocks(void);
|
||||||
extern void pass_remove_dead_phis(void);
|
extern void pass_remove_dead_phis(void);
|
||||||
|
|
|
@ -1,122 +0,0 @@
|
||||||
#include "mcg.h"
|
|
||||||
|
|
||||||
static ARRAYOF(struct ir) pending;
|
|
||||||
static ARRAYOF(struct ir) promotable;
|
|
||||||
|
|
||||||
static void addall(struct ir* ir)
|
|
||||||
{
|
|
||||||
if (array_appendu(&pending, ir))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ir->left)
|
|
||||||
addall(ir->left);
|
|
||||||
if (ir->right)
|
|
||||||
addall(ir->right);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void collect_irs(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
pending.count = 0;
|
|
||||||
promotable.count = 0;
|
|
||||||
for (i=0; i<cfg.preorder.count; i++)
|
|
||||||
{
|
|
||||||
struct basicblock* bb = cfg.preorder.item[i];
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j=0; j<bb->irs.count; j++)
|
|
||||||
addall(bb->irs.item[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void promote(struct ir* ir)
|
|
||||||
{
|
|
||||||
switch (ir->opcode)
|
|
||||||
{
|
|
||||||
case IR_CONST:
|
|
||||||
case IR_POP:
|
|
||||||
case IR_LOAD:
|
|
||||||
array_appendu(&promotable, ir);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IR_NOP:
|
|
||||||
promote(ir->left);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IR_PHI:
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0; i<ir->u.phivalue.count; i++)
|
|
||||||
promote(ir->u.phivalue.item[i].right);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void search_for_promotable_irs(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<pending.count; i++)
|
|
||||||
{
|
|
||||||
struct ir* ir = pending.item[i];
|
|
||||||
|
|
||||||
switch (ir->opcode)
|
|
||||||
{
|
|
||||||
case IR_ADDF:
|
|
||||||
case IR_SUBF:
|
|
||||||
case IR_MULF:
|
|
||||||
case IR_DIVF:
|
|
||||||
case IR_NEGF:
|
|
||||||
case IR_COMPAREF1:
|
|
||||||
case IR_COMPAREF2:
|
|
||||||
case IR_COMPAREF4:
|
|
||||||
case IR_COMPAREF8:
|
|
||||||
case IR_CFF1:
|
|
||||||
case IR_CFF2:
|
|
||||||
case IR_CFF4:
|
|
||||||
case IR_CFF8:
|
|
||||||
if (ir->left)
|
|
||||||
promote(ir->left);
|
|
||||||
if (ir->right)
|
|
||||||
promote(ir->right);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void modify_promotable_irs(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<promotable.count; i++)
|
|
||||||
{
|
|
||||||
struct ir* ir = promotable.item[i];
|
|
||||||
|
|
||||||
switch (ir->opcode)
|
|
||||||
{
|
|
||||||
case IR_ADDF:
|
|
||||||
case IR_SUBF:
|
|
||||||
case IR_MULF:
|
|
||||||
case IR_DIVF:
|
|
||||||
case IR_NEGF:
|
|
||||||
case IR_PHI:
|
|
||||||
case IR_NOP:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ir->opcode++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pass_promote_float_ops(void)
|
|
||||||
{
|
|
||||||
collect_irs();
|
|
||||||
search_for_promotable_irs();
|
|
||||||
modify_promotable_irs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
|
277
mach/proto/mcg/pass_typeinference.c
Normal file
277
mach/proto/mcg/pass_typeinference.c
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
#include "mcg.h"
|
||||||
|
|
||||||
|
static bool changed;
|
||||||
|
static ARRAYOF(struct ir) irs;
|
||||||
|
|
||||||
|
static void addall(struct ir* ir)
|
||||||
|
{
|
||||||
|
if (array_appendu(&irs, ir))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ir->left)
|
||||||
|
addall(ir->left);
|
||||||
|
if (ir->right)
|
||||||
|
addall(ir->right);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void collect_irs(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
irs.count = 0;
|
||||||
|
for (i=0; i<cfg.preorder.count; i++)
|
||||||
|
{
|
||||||
|
struct basicblock* bb = cfg.preorder.item[i];
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j=0; j<bb->irs.count; j++)
|
||||||
|
addall(bb->irs.item[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char effective_type(struct ir* ir, char type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 'I':
|
||||||
|
case 'F':
|
||||||
|
case 'L':
|
||||||
|
case 'D':
|
||||||
|
return type;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
if (ir->size == EM_wordsize)
|
||||||
|
return 'I';
|
||||||
|
else if (ir->size == (EM_wordsize*2))
|
||||||
|
return 'L';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
if (ir->size == EM_wordsize)
|
||||||
|
return 'F';
|
||||||
|
else if (ir->size == (EM_wordsize*2))
|
||||||
|
return 'D';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scan_irs(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<irs.count; i++)
|
||||||
|
{
|
||||||
|
struct ir* ir = irs.item[i];
|
||||||
|
|
||||||
|
if (ir->opcode == IR_PHI)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
/* Phis are special. We treat them as ?=? for every import value.
|
||||||
|
* */
|
||||||
|
|
||||||
|
if (ir->type)
|
||||||
|
{
|
||||||
|
/* Push this type to all our children. */
|
||||||
|
|
||||||
|
for (j=0; j<ir->u.phivalue.count; j++)
|
||||||
|
{
|
||||||
|
struct ir* child = ir->u.phivalue.item[j].right;
|
||||||
|
if (!child->type)
|
||||||
|
{
|
||||||
|
child->type = ir->type;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Pull our type from the first child with a set type; we
|
||||||
|
* ignore the rest, as the next iteration will push our type to
|
||||||
|
* them. It's possible for our children to have conflicting
|
||||||
|
* types. There's not much we can do about that so we just have
|
||||||
|
* to live with it and intelligently insert casts. */
|
||||||
|
|
||||||
|
for (j=0; j<ir->u.phivalue.count; j++)
|
||||||
|
{
|
||||||
|
struct ir* child = ir->u.phivalue.item[j].right;
|
||||||
|
if (child->type)
|
||||||
|
{
|
||||||
|
/* Found one! */
|
||||||
|
ir->type = child->type;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const struct ir_data* ird = &ir_data[ir->opcode];
|
||||||
|
|
||||||
|
if (!ir->type)
|
||||||
|
{
|
||||||
|
char etype = effective_type(ir, ird->returntype);
|
||||||
|
if (etype)
|
||||||
|
{
|
||||||
|
ir->type = etype;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir->left && !ir->left->type)
|
||||||
|
{
|
||||||
|
const struct ir_data* leftird = &ir_data[ir->left->opcode];
|
||||||
|
if (leftird->returntype == '?')
|
||||||
|
{
|
||||||
|
char etype = effective_type(ir, ird->lefttype);
|
||||||
|
if (etype)
|
||||||
|
{
|
||||||
|
ir->left->type = etype;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir->right && !ir->right->type)
|
||||||
|
{
|
||||||
|
const struct ir_data* rightird = &ir_data[ir->right->opcode];
|
||||||
|
if (rightird->returntype == '?')
|
||||||
|
{
|
||||||
|
char etype = effective_type(ir, ird->righttype);
|
||||||
|
if (etype)
|
||||||
|
{
|
||||||
|
ir->right->type = etype;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ir->type && (ird->returntype == '?'))
|
||||||
|
{
|
||||||
|
if ((ird->lefttype == '?') && ir->left->type)
|
||||||
|
{
|
||||||
|
ir->type = ir->left->type;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ird->righttype == '?') && ir->right->type)
|
||||||
|
{
|
||||||
|
ir->type = ir->right->type;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir->type && (ird->lefttype == '?') && !ir->left->type)
|
||||||
|
{
|
||||||
|
ir->left->type = ir->type;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir->type && (ird->righttype == '?') && !ir->right->type)
|
||||||
|
{
|
||||||
|
ir->right->type = ir->type;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void propagate_types(void)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
changed = false;
|
||||||
|
|
||||||
|
scan_irs();
|
||||||
|
}
|
||||||
|
while (changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assign_fallback_types(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<irs.count; i++)
|
||||||
|
{
|
||||||
|
struct ir* ir = irs.item[i];
|
||||||
|
const struct ir_data* ird = &ir_data[ir->opcode];
|
||||||
|
|
||||||
|
if (!ir->type && (ird->returntype == '?'))
|
||||||
|
ir->type = effective_type(ir, 'i');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ir* new_copy(char wanted, char real, struct ir* ir)
|
||||||
|
{
|
||||||
|
struct ir* copy;
|
||||||
|
int opcode;
|
||||||
|
|
||||||
|
if ((wanted == 'F') && (real == 'I'))
|
||||||
|
opcode = IR_COPYI;
|
||||||
|
else if ((wanted == 'D') && (real == 'L'))
|
||||||
|
opcode = IR_COPYI;
|
||||||
|
else if ((wanted == 'I') && (real == 'F'))
|
||||||
|
opcode = IR_COPYF;
|
||||||
|
else if ((wanted == 'L') && (real == 'D'))
|
||||||
|
opcode = IR_COPYF;
|
||||||
|
else
|
||||||
|
fatal("type mismatch: parent IR wanted %c, child IR provided %c",
|
||||||
|
wanted, real);
|
||||||
|
|
||||||
|
copy = new_ir1(opcode, ir->size, ir);
|
||||||
|
copy->type = wanted;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_copies(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Insert copies for normal IR nodes. */
|
||||||
|
|
||||||
|
for (i=0; i<irs.count; i++)
|
||||||
|
{
|
||||||
|
struct ir* ir = irs.item[i];
|
||||||
|
const struct ir_data* ird = &ir_data[ir->opcode];
|
||||||
|
|
||||||
|
if (ir->left)
|
||||||
|
{
|
||||||
|
char wanted = effective_type(ir, ird->lefttype);
|
||||||
|
char real = ir->left->type;
|
||||||
|
|
||||||
|
if (wanted && (wanted != real))
|
||||||
|
{
|
||||||
|
struct ir* copy = new_copy(wanted, real, ir->left);
|
||||||
|
copy->root = ir->root;
|
||||||
|
ir->left = copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir->right)
|
||||||
|
{
|
||||||
|
char wanted = effective_type(ir, ird->righttype);
|
||||||
|
char real = ir->right->type;
|
||||||
|
|
||||||
|
if (wanted && (wanted != real))
|
||||||
|
{
|
||||||
|
struct ir* copy = new_copy(wanted, real, ir->right);
|
||||||
|
copy->root = ir->root;
|
||||||
|
ir->right = copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pass_infer_types(void)
|
||||||
|
{
|
||||||
|
collect_irs();
|
||||||
|
propagate_types();
|
||||||
|
assign_fallback_types();
|
||||||
|
insert_copies();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
|
@ -184,7 +184,7 @@ void procedure_compile(struct procedure* proc)
|
||||||
pass_convert_locals_to_ssa();
|
pass_convert_locals_to_ssa();
|
||||||
print_blocks('5');
|
print_blocks('5');
|
||||||
pass_remove_dead_phis();
|
pass_remove_dead_phis();
|
||||||
pass_promote_float_ops();
|
pass_infer_types();
|
||||||
print_blocks('6');
|
print_blocks('6');
|
||||||
|
|
||||||
pass_instruction_selector();
|
pass_instruction_selector();
|
||||||
|
|
199
util/mcgg/ir.dat
199
util/mcgg/ir.dat
|
@ -1,123 +1,138 @@
|
||||||
# Flags:
|
# Flags:
|
||||||
# S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
|
# S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
|
||||||
# V: has no size (use in JUMP, CJUMP, RET forms)
|
# V: has no size (use in JUMP, CJUMP, RET forms)
|
||||||
|
#
|
||||||
|
# Types:
|
||||||
|
#
|
||||||
|
# I, F, L, D: int, float, long, double
|
||||||
|
# i, F: int, float; promoted to long, double based on size
|
||||||
|
# .: ignore this parameter
|
||||||
|
# ?: pull/push types from other ? parameters
|
||||||
|
|
||||||
# Simple terminals
|
# Simple terminals
|
||||||
S CONST # must be followed by float form
|
S ?=.. CONST # must be followed by float form
|
||||||
S CONSTF
|
S ?=.. CONSTF
|
||||||
V REG
|
V ?=.. REG
|
||||||
V NOP
|
V ?=?. NOP
|
||||||
S LABEL
|
S I=.. LABEL
|
||||||
S BLOCK
|
S I=.. BLOCK
|
||||||
V PAIR
|
V ?=.. PAIR
|
||||||
S ANY
|
S ?=.. ANY
|
||||||
S LOCAL
|
S ?=.. LOCAL
|
||||||
V PHI
|
V ?=.. PHI
|
||||||
|
|
||||||
# Magic stack operations
|
# Magic stack operations
|
||||||
S PUSH
|
S ?=?. PUSH
|
||||||
S POP # must be followed by float form
|
S ?=.. POP
|
||||||
S POPF
|
S ?=.. POPF
|
||||||
|
|
||||||
#... Memory operations
|
# Memory operations
|
||||||
S LOAD # must be followed by float form
|
S ?=I. LOAD # must be followed by float form
|
||||||
S LOADF
|
S f=I. LOADF
|
||||||
S STORE
|
S ?=I? STORE
|
||||||
S STOREF
|
S ?=If STOREF
|
||||||
|
|
||||||
# Arithemetic operations
|
# Arithemetic operations
|
||||||
S ADD
|
S i=ii ADD
|
||||||
S SUB
|
S i=ii SUB
|
||||||
S MUL
|
S i=ii MUL
|
||||||
S DIV
|
S i=ii DIV
|
||||||
S DIVU
|
S i=ii DIVU
|
||||||
S MOD
|
S i=ii MOD
|
||||||
S MODU
|
S i=ii MODU
|
||||||
S NEG
|
S i=ii NEG
|
||||||
|
|
||||||
S ADDF
|
S f=ff ADDF
|
||||||
S SUBF
|
S f=ff SUBF
|
||||||
S MULF
|
S f=ff MULF
|
||||||
S DIVF
|
S f=ff DIVF
|
||||||
S NEGF
|
S f=ff NEGF
|
||||||
|
|
||||||
S AND
|
S i=ii AND
|
||||||
S OR
|
S i=ii OR
|
||||||
S EOR
|
S i=ii EOR
|
||||||
S NOT
|
S i=ii NOT
|
||||||
S ASL
|
S i=ii ASL
|
||||||
S ASR
|
S i=ii ASR
|
||||||
S LSL
|
S i=ii LSL
|
||||||
S LSR
|
S i=ii LSR
|
||||||
|
|
||||||
# Conversions
|
# Bitwise conversions
|
||||||
S CII1
|
# (Remember, these don't change the value, merely move it)
|
||||||
S CII2
|
S i=f. COPYF
|
||||||
S CII4
|
S f=i. COPYI
|
||||||
S CII8
|
|
||||||
|
|
||||||
S CIU1
|
# Semantic conversions
|
||||||
S CIU2
|
S F=D. D2F
|
||||||
S CIU4
|
S D=F. F2D
|
||||||
S CIU8
|
|
||||||
|
|
||||||
S CUI1
|
S I=I. CII1
|
||||||
S CUI2
|
S I=I. CII2
|
||||||
S CUI4
|
S I=I. CII4
|
||||||
S CUI8
|
S L=L. CII8
|
||||||
|
|
||||||
S CFI1
|
S I=I. CIU1
|
||||||
S CFI2
|
S I=I. CIU2
|
||||||
S CFI4
|
S I=I. CIU4
|
||||||
S CFI8
|
S L=L. CIU8
|
||||||
|
|
||||||
S CIF1
|
S I=I. CUI1
|
||||||
S CIF2
|
S I=I. CUI2
|
||||||
S CIF4
|
S I=I. CUI4
|
||||||
S CIF8
|
S L=L. CUI8
|
||||||
|
|
||||||
S CFF1
|
S I=F. CFI1
|
||||||
S CFF2
|
S I=F. CFI2
|
||||||
S CFF4
|
S I=F. CFI4
|
||||||
S CFF8
|
S L=D. CFI8
|
||||||
|
|
||||||
|
S I=F. CIF1
|
||||||
|
S I=F. CIF2
|
||||||
|
S I=F. CIF4
|
||||||
|
S L=D. CIF8
|
||||||
|
|
||||||
|
S F=F. CFF1
|
||||||
|
S F=F. CFF2
|
||||||
|
S F=F. CFF4
|
||||||
|
S D=D. CFF8
|
||||||
|
|
||||||
# Tristate comparisons
|
# Tristate comparisons
|
||||||
S COMPARES1
|
S I=II COMPARES1
|
||||||
S COMPARES2
|
S I=II COMPARES2
|
||||||
S COMPARES4
|
S I=II COMPARES4
|
||||||
S COMPARES8
|
S I=LL COMPARES8
|
||||||
|
|
||||||
S COMPAREU1
|
S I=II COMPAREU1
|
||||||
S COMPAREU2
|
S I=II COMPAREU2
|
||||||
S COMPAREU4
|
S I=II COMPAREU4
|
||||||
S COMPAREU8
|
S I=LL COMPAREU8
|
||||||
|
|
||||||
S COMPAREF1
|
S I=FF COMPAREF1
|
||||||
S COMPAREF2
|
S I=FF COMPAREF2
|
||||||
S COMPAREF4
|
S I=FF COMPAREF4
|
||||||
S COMPAREF8
|
S I=DD COMPAREF8
|
||||||
|
|
||||||
# Tristate to boolean conversion
|
# Tristate to boolean conversion
|
||||||
S IFEQ
|
S I=I. IFEQ
|
||||||
S IFLT
|
S I=I. IFLT
|
||||||
S IFLE
|
S I=I. IFLE
|
||||||
|
|
||||||
# Procedures
|
# Procedures
|
||||||
S CALL
|
S i=.. CALL
|
||||||
|
|
||||||
# Flow control --- these never return
|
# Flow control --- these never return
|
||||||
V JUMP
|
V .=i. JUMP
|
||||||
V CJUMPEQ
|
V .=i. CJUMPEQ
|
||||||
V CJUMPLT
|
V .=i. CJUMPLT
|
||||||
V CJUMPLE
|
V .=i. CJUMPLE
|
||||||
V RET
|
V .=.. RET
|
||||||
|
|
||||||
# Special
|
# Special
|
||||||
S STACKADJUST
|
S ?=i. STACKADJUST
|
||||||
S SETRET
|
S ?=i. SETRET
|
||||||
S GETFP
|
S i=.. GETFP
|
||||||
S GETSP
|
S i=.. GETSP
|
||||||
S SETSP
|
S ?=i. SETSP
|
||||||
S CHAINFP
|
S i=i. CHAINFP
|
||||||
S FPTOARGS
|
S i=i. FPTOARGS
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ struct ir_data
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
int flags;
|
int flags;
|
||||||
|
char returntype;
|
||||||
|
char lefttype;
|
||||||
|
char righttype;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct ir_data ir_data[];
|
extern const struct ir_data ir_data[];
|
||||||
|
|
|
@ -10,7 +10,7 @@ awk -f - $in >$header << "EOF"
|
||||||
}
|
}
|
||||||
|
|
||||||
/^ *[^# ]+/ {
|
/^ *[^# ]+/ {
|
||||||
print "\tIR_" $2 ","
|
print "\tIR_" $3 ","
|
||||||
}
|
}
|
||||||
|
|
||||||
END {
|
END {
|
||||||
|
@ -30,9 +30,18 @@ awk -f - $in >$source << "EOF"
|
||||||
return "0"
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function char_to_type(c) {
|
||||||
|
if (c ~ /[A-Za-z]/) return "'"c"'"
|
||||||
|
if (c == "?") return "'?'"
|
||||||
|
if (c == ".") return "0"
|
||||||
|
}
|
||||||
|
|
||||||
/^ *[^# ]+/ {
|
/^ *[^# ]+/ {
|
||||||
printf("\t{ \"%s\", ", $2)
|
printf("\t{ \"%s\", ", $3)
|
||||||
printf("%s", char_to_flags(substr($1, 1, 1)))
|
printf("%s, ", char_to_flags(substr($1, 1, 1)))
|
||||||
|
printf("%s, ", char_to_type(substr($2, 1, 1)))
|
||||||
|
printf("%s, ", char_to_type(substr($2, 3, 1)))
|
||||||
|
printf("%s, ", char_to_type(substr($2, 4, 1)))
|
||||||
printf(" },\n")
|
printf(" },\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue