Replaced the block splicer with a trivial block eliminator (which rewrites
jumps to blocks which contain only a jump). Don't bother storing the bb graph in the ir nodes; we can find it on demand by walking the tree instead --- slower, but much easier to understand and more robust. Added a terrible map library.
This commit is contained in:
parent
f8bbf9e87d
commit
ed67d427c9
16 changed files with 276 additions and 171 deletions
|
@ -6,6 +6,11 @@
|
|||
int NAME##_count; \
|
||||
int NAME##_max
|
||||
|
||||
#define STATICARRAY(TYPE, NAME) \
|
||||
static TYPE** NAME; \
|
||||
static int NAME##_count; \
|
||||
static int NAME##_max
|
||||
|
||||
#define APPEND(ARRAY, VALUE) \
|
||||
array_append((void***) &ARRAY, &ARRAY##_count, &ARRAY##_max, VALUE)
|
||||
|
||||
|
|
|
@ -13,24 +13,8 @@ static void print_blocks(char k, struct procedure* proc)
|
|||
tracef(k, "%c:\n", k);
|
||||
tracef(k, "%c: BLOCK: %s\n", k, bb->name);
|
||||
|
||||
tracef(k, "%c: from:", k);
|
||||
for (int j=0; j<bb->inblocks_count; j++)
|
||||
{
|
||||
struct basicblock* obb = bb->inblocks[j];
|
||||
tracef(k, " %s", obb->name);
|
||||
}
|
||||
tracef(k, "\n");
|
||||
tracef(k, "%c: to:", k);
|
||||
for (int j=0; j<bb->outblocks_count; j++)
|
||||
{
|
||||
struct basicblock* obb = bb->outblocks[j];
|
||||
tracef(k, " %s", obb->name);
|
||||
}
|
||||
tracef(k, "\n");
|
||||
|
||||
for (int j=0; j<bb->irs_count; j++)
|
||||
ir_print(k, bb->irs[j]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,9 +24,9 @@ void compile(struct procedure* proc)
|
|||
|
||||
print_blocks('1', proc);
|
||||
|
||||
pass_eliminate_trivial_blocks(proc);
|
||||
pass_remove_dead_blocks(proc);
|
||||
pass_convert_stack_ops(proc);
|
||||
pass_splice_adjacent_blocks(proc);
|
||||
|
||||
print_blocks('2', proc);
|
||||
}
|
||||
|
|
|
@ -66,21 +66,21 @@ struct ir* new_localir(int offset)
|
|||
return ir;
|
||||
}
|
||||
|
||||
struct ir* ir_find(struct ir* ir, int opcode)
|
||||
struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user)
|
||||
{
|
||||
if (ir->opcode == opcode)
|
||||
if (cb(ir, user))
|
||||
return ir;
|
||||
|
||||
if (ir->left && !ir->left->is_sequence)
|
||||
{
|
||||
struct ir* irr = ir_find(ir->left, opcode);
|
||||
struct ir* irr = ir_walk(ir->left, cb, user);
|
||||
if (irr)
|
||||
return irr;
|
||||
}
|
||||
|
||||
if (ir->right && !ir->right->is_sequence)
|
||||
{
|
||||
struct ir* irr = ir_find(ir->right, opcode);
|
||||
struct ir* irr = ir_walk(ir->right, cb, user);
|
||||
if (irr)
|
||||
return irr;
|
||||
}
|
||||
|
@ -88,6 +88,19 @@ struct ir* ir_find(struct ir* ir, int opcode)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool finder_cb(struct ir* ir, void* user)
|
||||
{
|
||||
int opcode = *(int*)user;
|
||||
if (ir->opcode == opcode)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ir* ir_find(struct ir* ir, int opcode)
|
||||
{
|
||||
return ir_walk(ir, finder_cb, &opcode);
|
||||
}
|
||||
|
||||
static void print_expr(char k, const struct ir* ir)
|
||||
{
|
||||
tracef(k, "%s", ir_names[ir->opcode]);
|
||||
|
@ -110,18 +123,6 @@ static void print_expr(char k, const struct ir* ir)
|
|||
tracef(k, "%s", ir->u.bvalue->name);
|
||||
break;
|
||||
|
||||
case IR_PHI:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<ir->u.phivalue.imports_count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
tracef(k, ", ");
|
||||
tracef(k, "$%d", ir->u.phivalue.imports[i]->id);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
if (ir->left)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef IR_H
|
||||
#define IR_H
|
||||
|
||||
#include "ircodes.h"
|
||||
|
||||
enum
|
||||
{
|
||||
IRR_LB = -1,
|
||||
|
@ -20,7 +22,7 @@ enum
|
|||
struct ir
|
||||
{
|
||||
int id;
|
||||
int opcode;
|
||||
enum ir_opcode opcode;
|
||||
int size;
|
||||
struct ir* left;
|
||||
struct ir* right;
|
||||
|
@ -30,10 +32,6 @@ struct ir
|
|||
int rvalue;
|
||||
const char* lvalue;
|
||||
struct basicblock* bvalue;
|
||||
struct
|
||||
{
|
||||
ARRAY(struct ir, imports);
|
||||
} phivalue;
|
||||
} u;
|
||||
bool is_sequence : 1;
|
||||
};
|
||||
|
@ -53,11 +51,11 @@ extern struct ir* new_bbir(struct basicblock* bb);
|
|||
extern struct ir* new_anyir(int size);
|
||||
extern struct ir* new_localir(int offset);
|
||||
|
||||
typedef bool ir_walker_t(struct ir* node, void* user);
|
||||
extern struct ir* ir_walk(struct ir* ir, ir_walker_t* callback, void* user);
|
||||
extern struct ir* ir_find(struct ir* ir, int opcode);
|
||||
|
||||
extern void ir_print(char k, const struct ir* ir);
|
||||
|
||||
#include "ircodes.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ source=$3
|
|||
|
||||
awk -f - $in >$header << "EOF"
|
||||
BEGIN {
|
||||
print "enum {"
|
||||
print "enum ir_opcode {"
|
||||
}
|
||||
|
||||
/^[^#]+/ {
|
||||
|
|
|
@ -39,7 +39,7 @@ bool tracing(char k)
|
|||
{
|
||||
case 'E': return false;
|
||||
case '0': return false;
|
||||
case '1': return true;
|
||||
case '1': return false;
|
||||
case '2': return true;
|
||||
default: return true;
|
||||
}
|
||||
|
|
58
mach/proto/mcg/map.c
Normal file
58
mach/proto/mcg/map.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include "mcg.h"
|
||||
|
||||
static void extend(struct map_node** map, int* count, int* max)
|
||||
{
|
||||
if (*count == *max)
|
||||
{
|
||||
int newmax = (*max == 0) ? 8 : (*max * 2);
|
||||
struct map_node* newmap = realloc(*map, newmax * sizeof(struct map_node));
|
||||
if (!newmap)
|
||||
fatal("memory allocation failure");
|
||||
|
||||
*max = newmax;
|
||||
*map = newmap;
|
||||
}
|
||||
}
|
||||
|
||||
void map_set(struct map_node** map, int* count, int* max, void* left, void* right)
|
||||
{
|
||||
int i;
|
||||
struct map_node* node;
|
||||
|
||||
for (i=0; i<*count; i++)
|
||||
{
|
||||
node = &(*map)[i];
|
||||
if (node->left == left)
|
||||
{
|
||||
node->right = right;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extend(map, count, max);
|
||||
node = &(*map)[*count];
|
||||
node->left = left;
|
||||
node->right = right;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
void map_add(struct map_node** map, int* count, int* max, void* left, void* right)
|
||||
{
|
||||
int i;
|
||||
struct map_node* node;
|
||||
|
||||
for (i=0; i<*count; i++)
|
||||
{
|
||||
node = &(*map)[i];
|
||||
if ((node->left == left) && (node->right == right))
|
||||
return;
|
||||
}
|
||||
|
||||
extend(map, count, max);
|
||||
node = &(*map)[*count];
|
||||
node->left = left;
|
||||
node->right = right;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
26
mach/proto/mcg/map.h
Normal file
26
mach/proto/mcg/map.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
struct map_node
|
||||
{
|
||||
void* left;
|
||||
void* right;
|
||||
};
|
||||
|
||||
#define _MAP(MODIFIER, NAME) \
|
||||
MODIFIER struct map_node* NAME; \
|
||||
MODIFIER int NAME##_count; \
|
||||
MODIFIER int NAME##_max
|
||||
|
||||
#define MAP(NAME) _MAP(, NAME)
|
||||
#define STATICMAP(NAME) _MAP(static, NAME)
|
||||
|
||||
#define MAP_SET(MAP, LEFT, RIGHT) \
|
||||
map_set(&MAP, &MAP##_count, &MAP##_max, LEFT, RIGHT)
|
||||
|
||||
extern void map_set(struct map_node** map, int* count, int* max, void* left, void* right);
|
||||
extern void map_add(struct map_node** map, int* count, int* max, void* left, void* right);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include "em_flag.h"
|
||||
#include "em_ptyp.h"
|
||||
#include "array.h"
|
||||
#include "map.h"
|
||||
#include "ir.h"
|
||||
|
||||
extern char em_pseu[][4];
|
||||
|
@ -78,10 +79,7 @@ struct basicblock
|
|||
const char* name;
|
||||
ARRAY(struct insn, insns);
|
||||
ARRAY(struct ir, irs);
|
||||
ARRAY(struct basicblock, inblocks);
|
||||
ARRAY(struct basicblock, outblocks);
|
||||
ARRAY(struct ir, inparams);
|
||||
ARRAY(struct ir, outparams);
|
||||
bool is_fake : 1;
|
||||
bool is_root : 1;
|
||||
bool is_terminated : 1;
|
||||
};
|
||||
|
@ -116,7 +114,7 @@ extern void tb_regvar(arith offset, int size, int type, int priority);
|
|||
|
||||
extern void pass_convert_stack_ops(struct procedure* proc);
|
||||
extern void pass_remove_dead_blocks(struct procedure* proc);
|
||||
extern void pass_splice_adjacent_blocks(struct procedure* proc);
|
||||
extern void pass_eliminate_trivial_blocks(struct procedure* proc);
|
||||
|
||||
extern void compile(struct procedure* proc);
|
||||
|
||||
|
|
|
@ -128,14 +128,6 @@ static void queue_insn_block(int opcode, struct basicblock* left, struct basicbl
|
|||
insn->u.bvalue.right = right;
|
||||
APPEND(code_bb->insns, insn);
|
||||
|
||||
APPENDU(code_bb->outblocks, left);
|
||||
APPENDU(left->inblocks, code_bb);
|
||||
if (right)
|
||||
{
|
||||
APPENDU(code_bb->outblocks, right);
|
||||
APPENDU(right->inblocks, code_bb);
|
||||
}
|
||||
|
||||
terminate_block();
|
||||
}
|
||||
|
||||
|
@ -256,7 +248,12 @@ static void parse_pseu(void)
|
|||
*/
|
||||
|
||||
if (data_bb)
|
||||
APPENDU(data_bb->outblocks, bb_get(label));
|
||||
{
|
||||
struct insn* insn = new_insn(op_bra);
|
||||
insn->paramtype = PARAM_BVALUE;
|
||||
insn->u.bvalue.left = bb_get(label);
|
||||
APPEND(data_bb->insns, insn);
|
||||
}
|
||||
|
||||
data_offset(label, 0, ro);
|
||||
break;
|
||||
|
@ -361,6 +358,7 @@ void parse_em(void)
|
|||
const char* label = dlabel_to_str(insn.em_dlb);
|
||||
data_label(label);
|
||||
data_bb = bb_get(label);
|
||||
data_bb->is_fake = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "mcg.h"
|
||||
|
||||
STATICMAP(graph);
|
||||
STATICARRAY(struct ir, pops);
|
||||
STATICARRAY(struct ir, pushes);
|
||||
|
||||
static struct ir* get_last_push(struct basicblock* bb)
|
||||
{
|
||||
int i;
|
||||
|
@ -37,61 +41,93 @@ static struct ir* get_first_pop(struct basicblock* bb)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void convert_block(struct basicblock* bb)
|
||||
static bool collect_outputs_cb(struct ir* ir, void* user)
|
||||
{
|
||||
struct basicblock* caller = user;
|
||||
|
||||
if (ir->opcode == IR_BLOCK)
|
||||
MAP_SET(graph, caller, ir->u.bvalue);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void make_bb_graph(struct procedure* proc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
graph_count = 0;
|
||||
for (i=0; i<proc->blocks_count; i++)
|
||||
{
|
||||
struct basicblock* bb = proc->blocks[i];
|
||||
for (j=0; j<bb->irs_count; j++)
|
||||
ir_walk(bb->irs[j], collect_outputs_cb, bb);
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_block(struct procedure* proc, struct basicblock* bb)
|
||||
{
|
||||
int i, j;
|
||||
struct ir* ir;
|
||||
|
||||
pushes_count = pops_count = 0;
|
||||
for (;;)
|
||||
{
|
||||
struct ir* lastpush = get_last_push(bb);
|
||||
if (!lastpush)
|
||||
return;
|
||||
|
||||
/* Abort unless *every* success block of this one starts with a pop
|
||||
/* Abort unless *every* successor block of this one starts with a pop
|
||||
* of the same size... */
|
||||
|
||||
for (i=0; i<bb->outblocks_count; i++)
|
||||
for (i=0; i<graph_count; i++)
|
||||
{
|
||||
struct basicblock* outbb = bb->outblocks[i];
|
||||
|
||||
ir = get_first_pop(outbb);
|
||||
if (!ir || (ir->size != lastpush->size))
|
||||
return;
|
||||
|
||||
/* Also abort unless *every* predecessor block of the one we've
|
||||
* just found *also* ends in a push of the same size. */
|
||||
|
||||
for (j=0; j<outbb->inblocks_count; j++)
|
||||
if (graph[i].left == bb)
|
||||
{
|
||||
struct basicblock* inbb = outbb->inblocks[i];
|
||||
struct basicblock* outbb = graph[i].right;
|
||||
|
||||
ir = get_last_push(inbb);
|
||||
ir = get_first_pop(outbb);
|
||||
if (!ir || (ir->size != lastpush->size))
|
||||
return;
|
||||
APPENDU(pops, ir);
|
||||
|
||||
/* Also abort unless *every* predecessor block of the one we've
|
||||
* just found *also* ends in a push of the same size. */
|
||||
|
||||
for (j=0; j<graph_count; j++)
|
||||
{
|
||||
if (graph[j].right == outbb)
|
||||
{
|
||||
struct basicblock* inbb = graph[j].left;
|
||||
|
||||
ir = get_last_push(inbb);
|
||||
if (!ir || (ir->size != lastpush->size))
|
||||
return;
|
||||
APPENDU(pushes, ir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Okay, now we can wire them all up. */
|
||||
|
||||
for (i=0; i<bb->outblocks_count; i++)
|
||||
for (i=0; i<pushes_count; i++)
|
||||
{
|
||||
struct basicblock* outbb = bb->outblocks[i];
|
||||
struct ir* phi = get_first_pop(outbb);
|
||||
phi->opcode = IR_PHI;
|
||||
struct ir* ir = pushes[i];
|
||||
assert(ir->is_sequence);
|
||||
*ir = *ir->left;
|
||||
ir->is_sequence = true;
|
||||
}
|
||||
|
||||
/* Also abort unless *every* predecessor block of the one we've
|
||||
* just found *also* ends in a push of the same size. */
|
||||
for (i=0; i<pops_count; i++)
|
||||
{
|
||||
struct ir* ir = pops[i];
|
||||
struct ir* pushir = pushes[0];
|
||||
struct ir* phi = new_ir1(IR_PHI, ir->size, pushir);
|
||||
|
||||
for (j=0; j<outbb->inblocks_count; j++)
|
||||
{
|
||||
struct basicblock* inbb = outbb->inblocks[j];
|
||||
for (j=1; j<pushes_count; j++)
|
||||
phi = new_ir2(IR_PHI, ir->size, phi, pushes[j]);
|
||||
|
||||
ir = get_last_push(inbb);
|
||||
*ir = *ir->left;
|
||||
ir->is_sequence = true;
|
||||
APPEND(phi->u.phivalue.imports, ir);
|
||||
}
|
||||
phi->is_sequence = ir->is_sequence;
|
||||
*ir = *phi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +136,10 @@ void pass_convert_stack_ops(struct procedure* proc)
|
|||
{
|
||||
int i;
|
||||
|
||||
make_bb_graph(proc);
|
||||
|
||||
for (i=0; i<proc->blocks_count; i++)
|
||||
convert_block(proc->blocks[i]);
|
||||
convert_block(proc, proc->blocks[i]);
|
||||
}
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#include "mcg.h"
|
||||
|
||||
void pass_remove_dead_blocks(struct procedure* proc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
again:
|
||||
/* Starts at 1 because we don't want to remove the root block! */
|
||||
for (i=1; i<proc->blocks_count; i++)
|
||||
{
|
||||
struct basicblock* bb = proc->blocks[i];
|
||||
|
||||
if (bb->inblocks_count == 0)
|
||||
{
|
||||
/* Nobody uses this block; disconnect it from its output
|
||||
* blocks. */
|
||||
for (j=0; j<bb->outblocks_count; j++)
|
||||
REMOVE(bb->outblocks[j]->inblocks, bb);
|
||||
|
||||
REMOVE(proc->blocks, bb);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
||||
|
41
mach/proto/mcg/pass_eliminatetrivialblocks.c
Normal file
41
mach/proto/mcg/pass_eliminatetrivialblocks.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "mcg.h"
|
||||
|
||||
static bool rewrite_jumps_cb(struct ir* ir, void* user)
|
||||
{
|
||||
if (ir->opcode == IR_BLOCK)
|
||||
{
|
||||
struct basicblock* bb = ir->u.bvalue;
|
||||
if ((bb->irs_count > 0)
|
||||
&& (bb->irs[0]->opcode == IR_JUMP)
|
||||
&& (bb->irs[0]->left->opcode == IR_BLOCK))
|
||||
{
|
||||
ir->u.bvalue = bb->irs[0]->left->u.bvalue;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rewrite_jumps(struct basicblock* bb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<bb->irs_count; i++)
|
||||
{
|
||||
struct ir* ir = bb->irs[i];
|
||||
ir_walk(ir, rewrite_jumps_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void pass_eliminate_trivial_blocks(struct procedure* proc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<proc->blocks_count; i++)
|
||||
{
|
||||
struct basicblock* bb = proc->blocks[i];
|
||||
rewrite_jumps(bb);
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
40
mach/proto/mcg/pass_removedeadblocks.c
Normal file
40
mach/proto/mcg/pass_removedeadblocks.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include "mcg.h"
|
||||
|
||||
STATICARRAY(struct basicblock, used);
|
||||
|
||||
static void walk_blocks(struct basicblock* bb);
|
||||
|
||||
static bool walk_blocks_cb(struct ir* ir, void* user)
|
||||
{
|
||||
if (ir->opcode == IR_BLOCK)
|
||||
walk_blocks(ir->u.bvalue);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void walk_blocks(struct basicblock* bb)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!CONTAINS(used, bb))
|
||||
{
|
||||
APPENDU(used, bb);
|
||||
|
||||
for (i=0; i<bb->irs_count; i++)
|
||||
ir_walk(bb->irs[i], walk_blocks_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void pass_remove_dead_blocks(struct procedure* proc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
used_count = 0;
|
||||
walk_blocks(proc->blocks[0]);
|
||||
|
||||
proc->blocks_count = 0;
|
||||
for (i=0; i<used_count; i++)
|
||||
APPEND(proc->blocks, used[i]);
|
||||
}
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#include "mcg.h"
|
||||
|
||||
void pass_splice_adjacent_blocks(struct procedure* proc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
again:
|
||||
for (i=0; i<proc->blocks_count; i++)
|
||||
{
|
||||
struct basicblock* bb = proc->blocks[i];
|
||||
if (bb->outblocks_count == 1)
|
||||
{
|
||||
struct basicblock* outbb = bb->outblocks[0];
|
||||
if (outbb->inblocks_count == 1)
|
||||
{
|
||||
struct ir* lastir = bb->irs[bb->irs_count-1];
|
||||
|
||||
if ((lastir->opcode == IR_JUMP)
|
||||
&& (lastir->left->opcode == IR_BLOCK)
|
||||
&& (lastir->left->u.bvalue == outbb))
|
||||
{
|
||||
/* Remove jump instruction. */
|
||||
|
||||
bb->irs_count--;
|
||||
|
||||
REMOVE(bb->outblocks, outbb);
|
||||
REMOVE(outbb->inblocks, bb);
|
||||
|
||||
for (j=0; j<outbb->irs_count; j++)
|
||||
APPEND(bb->irs, outbb->irs[j]);
|
||||
for (j=0; j<outbb->outblocks_count; j++)
|
||||
{
|
||||
APPENDU(bb->outblocks, outbb->outblocks[j]);
|
||||
APPENDU(outbb->outblocks[j]->inblocks, bb);
|
||||
REMOVE(outbb->outblocks[j]->inblocks, outbb);
|
||||
}
|
||||
|
||||
REMOVE(proc->blocks, outbb);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
||||
|
|
@ -531,8 +531,6 @@ static void insn_ivalue(int opcode, arith value)
|
|||
case op_csa:
|
||||
case op_csb:
|
||||
{
|
||||
struct basicblock* data_bb;
|
||||
int i;
|
||||
const char* helper = aprintf(".%s%d",
|
||||
(opcode == op_csa) ? "csa" : "csb",
|
||||
value);
|
||||
|
@ -542,16 +540,10 @@ static void insn_ivalue(int opcode, arith value)
|
|||
fatal("csa/csb are only supported if they refer "
|
||||
"directly to a descriptor block");
|
||||
|
||||
/* Splice the outgoing bbs in the data block into our own. */
|
||||
/* Turn the label reference into a block. */
|
||||
|
||||
data_bb = bb_get(descriptor->u.lvalue);
|
||||
for (i=0; i<data_bb->outblocks_count; i++)
|
||||
{
|
||||
struct basicblock* bb = data_bb->outblocks[i];
|
||||
printf("\t; may jump to %s\n", bb->name);
|
||||
APPENDU(current_bb->outblocks, bb);
|
||||
APPENDU(bb->inblocks, current_bb);
|
||||
}
|
||||
descriptor->opcode = IR_BLOCK;
|
||||
descriptor->u.bvalue = bb_get(descriptor->u.lvalue);
|
||||
|
||||
push(descriptor);
|
||||
materialise_stack();
|
||||
|
|
Loading…
Reference in a new issue