Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-dump.c view on Meta::CPAN
if((type & JIT_OPCODE_SRC1_MASK) != 0)
{
type >>= 4;
}
if((type & JIT_OPCODE_SRC2_MASK) != 0)
{
type >>= 8;
}
/* Dump the value, prefixed appropriately */
switch(type)
{
case JIT_OPCODE_DEST_INT:
{
jit_dump_value(stream, func, value, "i");
}
break;
case JIT_OPCODE_DEST_LONG:
{
jit_dump_value(stream, func, value, "l");
}
break;
case JIT_OPCODE_DEST_FLOAT32:
{
jit_dump_value(stream, func, value, "f");
}
break;
case JIT_OPCODE_DEST_FLOAT64:
{
jit_dump_value(stream, func, value, "d");
}
break;
case JIT_OPCODE_DEST_NFLOAT:
{
jit_dump_value(stream, func, value, "D");
}
break;
case JIT_OPCODE_DEST_ANY:
{
/* Intuit the prefix from the value if the type is "any" */
jit_dump_value(stream, func, value, 0);
}
break;
}
}
/*@
* @deftypefun void jit_dump_insn (FILE *@var{stream}, jit_function_t @var{func}, jit_value_t @var{value})
* Dump the contents of an instruction to a stdio stream.
* @end deftypefun
@*/
void jit_dump_insn(FILE *stream, jit_function_t func, jit_insn_t insn)
{
const char *name;
const char *infix_name;
int opcode, flags;
jit_nint reg;
/* Bail out if we have insufficient information for the dump */
if(!stream || !func || !insn)
{
return;
}
/* Get the opcode details */
opcode = insn->opcode;
if(opcode < JIT_OP_NOP || opcode >= JIT_OP_NUM_OPCODES)
{
fprintf(stream, "unknown opcode %d\n", opcode);
return;
}
name = jit_opcodes[opcode].name;
flags = jit_opcodes[opcode].flags;
infix_name = 0;
/* Dump branch, call, or register information */
if((flags & JIT_OPCODE_IS_BRANCH) != 0)
{
if(opcode == JIT_OP_BR)
{
fprintf(stream, "goto .L%ld", (long)(jit_insn_get_label(insn)));
return;
}
if(opcode == JIT_OP_CALL_FINALLY || opcode == JIT_OP_CALL_FILTER)
{
fprintf(stream, "%s .L%ld", name, (long)(jit_insn_get_label(insn)));
return;
}
fprintf(stream, "if ");
}
else if((flags & JIT_OPCODE_IS_CALL) != 0)
{
if(insn->value1)
fprintf(stream, "%s %s", name, (const char *)(insn->value1));
else
fprintf(stream, "%s 0x08%lx", name, (long)(jit_nuint)(insn->dest));
return;
}
else if((flags & JIT_OPCODE_IS_CALL_EXTERNAL) != 0)
{
if(insn->value1)
fprintf(stream, "%s %s (0x%08lx)", name,
(const char *)(insn->value1),
(long)(jit_nuint)(insn->dest));
else
fprintf(stream, "%s 0x08%lx", name,
(long)(jit_nuint)(insn->dest));
return;
}
else if((flags & JIT_OPCODE_IS_REG) != 0)
{
reg = jit_value_get_nint_constant(jit_insn_get_value2(insn));
fputs(name, stream);
putc('(', stream);
jit_dump_value(stream, func, jit_insn_get_value1(insn), 0);
fputs(", ", stream);
fputs(jit_reg_name(reg), stream);
putc(')', stream);
return;
}
else if((flags & JIT_OPCODE_IS_ADDROF_LABEL) != 0)
{
dump_value(stream, func, jit_insn_get_dest(insn), flags & JIT_OPCODE_DEST_MASK);
fprintf(stream, " = ");
fprintf(stream, "address_of_label .L%ld",
(long)(jit_insn_get_label(insn)));
return;
}
else if((flags & JIT_OPCODE_IS_JUMP_TABLE) != 0)
{
jit_label_t *labels;
jit_nint num_labels, label;
labels = (jit_label_t *)jit_value_get_nint_constant(jit_insn_get_value1(insn));
num_labels = jit_value_get_nint_constant(jit_insn_get_value2(insn));
fprintf(stream, "%s ", name);
dump_value(stream, func, jit_insn_get_dest(insn), flags & JIT_OPCODE_DEST_MASK);
printf(" : {");
for(label = 0; label < num_labels; label++)
{
printf(" .L%ld", (long) labels[label]);
}
printf(" }");
return;
}
/* Output the destination information */
if((flags & JIT_OPCODE_DEST_MASK) != JIT_OPCODE_DEST_EMPTY &&
!jit_insn_dest_is_value(insn))
{
dump_value(stream, func, jit_insn_get_dest(insn),
flags & JIT_OPCODE_DEST_MASK);
fprintf(stream, " = ");
}
/* Dump the details of the operation */
switch(flags & JIT_OPCODE_OPER_MASK)
{
case JIT_OPCODE_OPER_ADD: infix_name = " + "; break;
case JIT_OPCODE_OPER_SUB: infix_name = " - "; break;
case JIT_OPCODE_OPER_MUL: infix_name = " * "; break;
case JIT_OPCODE_OPER_DIV: infix_name = " / "; break;
case JIT_OPCODE_OPER_REM: infix_name = " % "; break;
case JIT_OPCODE_OPER_NEG: infix_name = "-"; break;
case JIT_OPCODE_OPER_AND: infix_name = " & "; break;
case JIT_OPCODE_OPER_OR: infix_name = " | "; break;
case JIT_OPCODE_OPER_XOR: infix_name = " ^ "; break;
case JIT_OPCODE_OPER_NOT: infix_name = "~"; break;
case JIT_OPCODE_OPER_EQ: infix_name = " == "; break;
case JIT_OPCODE_OPER_NE: infix_name = " != "; break;
case JIT_OPCODE_OPER_LT: infix_name = " < "; break;
case JIT_OPCODE_OPER_LE: infix_name = " <= "; break;
case JIT_OPCODE_OPER_GT: infix_name = " > "; break;
case JIT_OPCODE_OPER_GE: infix_name = " >= "; break;
case JIT_OPCODE_OPER_SHL: infix_name = " << "; break;
case JIT_OPCODE_OPER_SHR: infix_name = " >> "; break;
case JIT_OPCODE_OPER_SHR_UN: infix_name = " >>> "; break;
case JIT_OPCODE_OPER_COPY: infix_name = ""; break;
case JIT_OPCODE_OPER_ADDRESS_OF: infix_name = "&"; break;
}
if(infix_name)
{
if((flags & JIT_OPCODE_SRC2_MASK) != 0)
{
/* Binary operation with a special operator name */
dump_value(stream, func, jit_insn_get_value1(insn),
flags & JIT_OPCODE_SRC1_MASK);
fputs(infix_name, stream);
dump_value(stream, func, jit_insn_get_value2(insn),
flags & JIT_OPCODE_SRC2_MASK);
}
else
{
/* Unary operation with a special operator name */
fputs(infix_name, stream);
dump_value(stream, func, jit_insn_get_value1(insn),
flags & JIT_OPCODE_SRC1_MASK);
}
}
else
{
/* Not a special operator, so use the opcode name */
if(!jit_strncmp(name, "br_", 3))
{
name += 3;
}
fputs(name, stream);
if((flags & (JIT_OPCODE_SRC1_MASK | JIT_OPCODE_SRC2_MASK)) != 0)
{
putc('(', stream);
if(jit_insn_dest_is_value(insn))
{
dump_value(stream, func, jit_insn_get_dest(insn),
flags & JIT_OPCODE_DEST_MASK);
fputs(", ", stream);
}
dump_value(stream, func, jit_insn_get_value1(insn),
flags & JIT_OPCODE_SRC1_MASK);
if((flags & JIT_OPCODE_SRC2_MASK) != 0)
{
fputs(", ", stream);
dump_value(stream, func, jit_insn_get_value2(insn),
flags & JIT_OPCODE_SRC2_MASK);
}
putc(')', stream);
}
}
/* Dump the "then" information on a conditional branch */
if((flags & JIT_OPCODE_IS_BRANCH) != 0)
{
fprintf(stream, " then goto .L%ld", (long)(jit_insn_get_label(insn)));
}
}
#if defined(JIT_BACKEND_INTERP)
/*
* Dump the interpreted bytecode representation of a function.
*/
static void dump_interp_code(FILE *stream, void **pc, void **end)
{
int opcode;
const jit_opcode_info_t *info;
while(pc < end)
{
/* Fetch the next opcode */
opcode = (int)(jit_nint)(*pc);
/* Dump the address of the opcode */
fprintf(stream, "\t%08lX: ", (long)(jit_nint)pc);
++pc;
/* Get information about this opcode */
if(opcode < JIT_OP_NUM_OPCODES)
{
info = &(jit_opcodes[opcode]);
}
else
{
info = &(_jit_interp_opcodes[opcode - JIT_OP_NUM_OPCODES]);
}
/* Dump the name of the opcode */
fputs(info->name, stream);
/* Dump additional parameters from the opcode stream */
switch(info->flags & JIT_OPCODE_INTERP_ARGS_MASK)
{
case JIT_OPCODE_NINT_ARG:
{
fprintf(stream, " %ld", (long)(jit_nint)(*pc));
++pc;
}
break;
case JIT_OPCODE_NINT_ARG_TWO:
{
fprintf(stream, " %ld, %ld",
(long)(jit_nint)(pc[0]), (long)(jit_nint)(pc[1]));
pc += 2;
}
break;
case JIT_OPCODE_CONST_LONG:
{
jit_ulong value;
jit_memcpy(&value, pc, sizeof(jit_ulong));
pc += (sizeof(jit_ulong) + sizeof(void *) - 1) /
sizeof(void *);
fprintf(stream, " 0x%lX%08lX",
(long)((value >> 32) & jit_max_uint),
(long)(value & jit_max_uint));
}
break;
case JIT_OPCODE_CONST_FLOAT32:
{
jit_float32 value;
jit_memcpy(&value, pc, sizeof(jit_float32));
pc += (sizeof(jit_float32) + sizeof(void *) - 1) /
sizeof(void *);
fprintf(stream, " %f", (double)value);
}
break;
case JIT_OPCODE_CONST_FLOAT64:
{
jit_float64 value;
jit_memcpy(&value, pc, sizeof(jit_float64));
pc += (sizeof(jit_float64) + sizeof(void *) - 1) /
sizeof(void *);
fprintf(stream, " %f", (double)value);
}
break;
case JIT_OPCODE_CONST_NFLOAT:
{
jit_nfloat value;
jit_memcpy(&value, pc, sizeof(jit_nfloat));
pc += (sizeof(jit_nfloat) + sizeof(void *) - 1) /
sizeof(void *);
fprintf(stream, " %f", (double)value);
}
break;
case JIT_OPCODE_CALL_INDIRECT_ARGS:
{
fprintf(stream, " %ld", (long)(jit_nint)(pc[1]));
pc += 2;
}
break;
default:
{
if((info->flags & (JIT_OPCODE_IS_BRANCH |
JIT_OPCODE_IS_ADDROF_LABEL)) != 0)
{
fprintf(stream, " %08lX",
(long)(jit_nint)((pc - 1) + (jit_nint)(*pc)));
++pc;
}
else if((info->flags & JIT_OPCODE_IS_CALL) != 0)
{
fprintf(stream, " 0x%lX", (long)(jit_nint)(*pc));
++pc;
}
else if((info->flags & JIT_OPCODE_IS_CALL_EXTERNAL) != 0)
{
fprintf(stream, " 0x%lX, %ld",
(long)(jit_nint)(pc[1]), (long)(jit_nint)(pc[2]));
pc += 3;
}
else if((info->flags & JIT_OPCODE_IS_JUMP_TABLE) != 0)
{
jit_nint label, num_labels;
num_labels = (jit_nint)pc[0];
for(label = 1; label <= num_labels; label++)
{
fprintf(stream, " %lX",
(long)(jit_nint)pc[label]);
}
pc += 1 + num_labels;
}
}
break;
}
/* Terminate the current disassembly line */
putc('\n', stream);
}
}
#else /* !JIT_BACKEND_INTERP */
/*
* Dump the native object code representation of a function to stream.
*/
static void dump_object_code(FILE *stream, void *start, void *end)
{
char cmdline[BUFSIZ];
unsigned char *pc = (unsigned char *)start;
FILE *file;
int ch;
#if JIT_WIN32_PLATFORM
/*
* NOTE: If libjit is compiled on cygwin with -mno-cygwin flag then
* fopen("/tmp/foo.s", ...) will use the root folder of the current
* drive. That is the full file name will be like "c:/tmp/foo". But
* the ``as'' and ``objdump'' utilities still use the cygwin's root.
* So "as /tmp/foo.s" will look for "c:/cygwin/tmp/foo.s". To avoid
* this ambiguity the file name has to contian the drive spec (e.g.
* fopen("c:/tmp/foo.s", ...) and "as c;/tmp/foo.s"). Here we assume
* that the TMP or TEMP environment variables always contain it.
*/
char s_path[BUFSIZ];
char o_path[BUFSIZ];
char *tmp_dir = getenv("TMP");
if(tmp_dir == NULL)
{
tmp_dir = getenv("TEMP");
if(tmp_dir == NULL)
{
tmp_dir = "c:/tmp";
}
}
sprintf(s_path, "%s/libjit-dump.s", tmp_dir);
sprintf(o_path, "%s/libjit-dump.o", tmp_dir);
#else
const char *s_path = "/tmp/libjit-dump.s";
const char *o_path = "/tmp/libjit-dump.o";
#endif
file = fopen(s_path, "w");
if(!file)
{
return;
}
fflush(stream);
while(pc < (unsigned char *)end)
{
fprintf(file, ".byte %d\n", (int)(*pc));
++pc;
}
fclose(file);
sprintf(cmdline, "as %s -o %s", s_path, o_path);
system(cmdline);
sprintf(cmdline, "objdump --adjust-vma=%ld -d %s > %s",
(long)(jit_nint)start, o_path, s_path);
system(cmdline);
file = fopen(s_path, "r");
if(file)
{
while((ch = getc(file)) != EOF)
{
putc(ch, stream);
}
fclose(file);
}
unlink(s_path);
unlink(o_path);
putc('\n', stream);
fflush(stream);
}
#endif /* !JIT_BACKEND_INTERP */
( run in 1.509 second using v1.01-cache-2.11-cpan-796a6f069b2 )