C-sparse
view release on metacpan or search on metacpan
src/sparse-0.4.4/example.c view on Meta::CPAN
/*
* Fake "call" linearization just as a taster..
*/
static void generate_call(SCTX_ struct bb_state *state, struct instruction *insn)
{
int offset = 0;
pseudo_t arg;
FOR_EACH_PTR(insn->arguments, arg) {
output_insn(sctx_ state, "pushl %s", generic(sctx_ state, arg));
offset += 4;
} END_FOR_EACH_PTR(arg);
flush_reg(sctx_ state, hardregs+0);
flush_reg(sctx_ state, hardregs+1);
flush_reg(sctx_ state, hardregs+2);
output_insn(sctx_ state, "call %s", show_pseudo(sctx_ insn->func));
if (offset)
output_insn(sctx_ state, "addl $%d,%%esp", offset);
if (insn->target && insn->target != VOID)
add_pseudo_reg(sctx_ state, insn->target, hardregs+0);
}
static void generate_select(SCTX_ struct bb_state *state, struct instruction *insn)
{
const char *cond;
struct hardreg *src1, *src2, *dst;
src1 = getreg(sctx_ state, insn->src2, NULL);
dst = copy_reg(sctx_ state, src1, insn->target);
add_pseudo_reg(sctx_ state, insn->target, dst);
src2 = getreg(sctx_ state, insn->src3, insn->target);
if (state->cc_target == insn->src1) {
cond = conditional[state->cc_opcode];
} else {
struct hardreg *reg = getreg(sctx_ state, insn->src1, NULL);
output_insn(sctx_ state, "testl %s,%s", reg->name, reg->name);
cond = "ne";
}
output_insn(sctx_ state, "sel%s %s,%s", cond, src2->name, dst->name);
}
struct asm_arg {
const struct ident *name;
const char *value;
pseudo_t pseudo;
struct hardreg *reg;
};
static void replace_asm_arg(SCTX_ char **dst_p, struct asm_arg *arg)
{
char *dst = *dst_p;
int len = strlen(arg->value);
memcpy(dst, arg->value, len);
*dst_p = dst + len;
}
static void replace_asm_percent(SCTX_ const char **src_p, char **dst_p, struct asm_arg *args, int nr)
{
const char *src = *src_p;
char c;
int index;
c = *src++;
switch (c) {
case '0' ... '9':
index = c - '0';
if (index < nr)
replace_asm_arg(sctx_ dst_p, args+index);
break;
}
*src_p = src;
return;
}
static void replace_asm_named(SCTX_ const char **src_p, char **dst_p, struct asm_arg *args, int nr)
{
const char *src = *src_p;
const char *end = src;
for(;;) {
char c = *end++;
if (!c)
return;
if (c == ']') {
int i;
*src_p = end;
for (i = 0; i < nr; i++) {
const struct ident *ident = args[i].name;
int len;
if (!ident)
continue;
len = ident->len;
if (memcmp(src, ident->name, len))
continue;
replace_asm_arg(sctx_ dst_p, args+i);
return;
}
}
}
}
static const char *replace_asm_args(SCTX_ const char *str, struct asm_arg *args, int nr)
{
static char buffer[1000];
char *p = buffer;
for (;;) {
char c = *str;
*p = c;
if (!c)
return buffer;
str++;
switch (c) {
case '%':
if (*str == '%') {
str++;
p++;
continue;
}
replace_asm_percent(sctx_ &str, &p, args, nr);
continue;
case '[':
replace_asm_named(sctx_ &str, &p, args, nr);
continue;
default:
break;
}
p++;
}
}
#define MAX_ASM_ARG (50)
static struct asm_arg asm_arguments[MAX_ASM_ARG];
static struct asm_arg *generate_asm_inputs(SCTX_ struct bb_state *state, struct asm_constraint_list *list, struct asm_arg *arg)
{
struct asm_constraint *entry;
FOR_EACH_PTR(list, entry) {
const char *constraint = entry->constraint;
pseudo_t pseudo = entry->pseudo;
struct hardreg *reg, *orig;
const char *string;
int index;
string = "undef";
switch (*constraint) {
case 'r':
string = getreg(sctx_ state, pseudo, NULL)->name;
break;
case '0' ... '9':
index = *constraint - '0';
reg = asm_arguments[index].reg;
orig = find_in_reg(sctx_ state, pseudo);
if (orig)
move_reg(sctx_ state, orig, reg);
else
fill_reg(sctx_ state, reg, pseudo);
string = reg->name;
break;
default:
string = generic(sctx_ state, pseudo);
break;
}
output_insn(sctx_ state, "# asm input \"%s\": %s : %s", constraint, show_pseudo(sctx_ pseudo), string);
arg->name = entry->ident;
arg->value = string;
arg->pseudo = NULL;
arg->reg = NULL;
arg++;
} END_FOR_EACH_PTR(entry);
return arg;
}
static struct asm_arg *generate_asm_outputs(SCTX_ struct bb_state *state, struct asm_constraint_list *list, struct asm_arg *arg)
{
struct asm_constraint *entry;
( run in 0.963 second using v1.01-cache-2.11-cpan-39bf76dae61 )