Alien-LibJIT
view release on metacpan or search on metacpan
libjit/tools/gen-apply.c view on Meta::CPAN
/*
* On x86 the extended precision numbers are 10 bytes long. However certain
* ABIs define the long double size equal to 12 bytes. The extra 2 bytes are
* for alignment purposes only and has no significance in computations.
*/
#define NFLOAT_SIGNIFICANT_BYTES (sizeof(jit_nfloat) != 12 ? sizeof(jit_nfloat) : 10)
#elif PLATFORM_IS_X86_64
/*
* On x86_64 the extended precision numbers are 10 bytes long. However certain
* ABIs define the long double size equal to 16 bytes. The extra 6 bytes are
* for alignment purposes only and has no significance in computations.
*/
#define NFLOAT_SIGNIFICANT_BYTES (sizeof(jit_nfloat) != 16 ? sizeof(jit_nfloat) : 10)
#else
#define NFLOAT_SIGNIFICANT_BYTES sizeof(jit_nfloat)
#endif
#if defined(PLATFORM_IS_GCC) || defined(PLATFORM_IS_WIN32)
/*
* Pick up pre-defined values on platforms where auto-detection doesn't work.
*/
#if defined(PLATFORM_IS_MACOSX)
#include "gen-apply-macosx.h"
#endif
/*
* Values that are detected.
*/
#ifndef JIT_APPLY_NUM_WORD_REGS
int num_word_regs = 0;
int num_float_regs = 0;
int num_double_regs = 0;
int num_nfloat_regs = 0;
int pass_stack_float_as_double = 0;
int pass_stack_float_as_nfloat = 0;
int pass_stack_double_as_nfloat = 0;
int pass_stack_nfloat_as_double = 0;
int pass_reg_float_as_double = 0;
int pass_reg_float_as_nfloat = 0;
int pass_reg_double_as_nfloat = 0;
int pass_reg_nfloat_as_double = 0;
int return_float_as_double = 0;
int return_float_as_nfloat = 0;
int return_double_as_nfloat = 0;
int return_nfloat_as_double = 0;
int floats_in_word_regs = 0;
int doubles_in_word_regs = 0;
int nfloats_in_word_regs = 0;
int return_floats_after = 0;
int return_doubles_after = 0;
int return_nfloats_after = 0;
int varargs_on_stack = 0;
int struct_return_special_reg = 0;
int struct_reg_overlaps_word_reg = 0;
int struct_return_in_reg[64];
int align_long_regs = 0;
int align_long_stack = 0;
int can_split_long = 0;
int x86_fastcall = 0;
int parent_frame_offset = 0;
int return_address_offset = 0;
int broken_frame_builtins = 0;
int max_struct_in_reg = 0;
int x86_pop_struct_return = 0;
int pad_float_regs = 0;
#else
int num_word_regs = JIT_APPLY_NUM_WORD_REGS;
int num_float_regs = JIT_APPLY_NUM_FLOAT_REGS;
int num_double_regs = JIT_APPLY_NUM_DOUBLE_REGS;
int num_nfloat_regs = JIT_APPLY_NUM_NFLOAT_REGS;
int pass_stack_float_as_double = JIT_APPLY_PASS_STACK_FLOAT_AS_DOUBLE;
int pass_stack_float_as_nfloat = JIT_APPLY_PASS_STACK_FLOAT_AS_NFLOAT;
int pass_stack_double_as_nfloat = JIT_APPLY_PASS_STACK_DOUBLE_AS_NFLOAT;
int pass_stack_nfloat_as_double = JIT_APPLY_PASS_STACK_NFLOAT_AS_DOUBLE;
int pass_reg_float_as_double = JIT_APPLY_PASS_REG_FLOAT_AS_DOUBLE;
int pass_reg_float_as_nfloat = JIT_APPLY_PASS_REG_FLOAT_AS_NFLOAT;
int pass_reg_double_as_nfloat = JIT_APPLY_PASS_REG_DOUBLE_AS_NFLOAT;
int pass_reg_nfloat_as_double = JIT_APPLY_PASS_REG_NFLOAT_AS_DOUBLE;
int return_float_as_double = JIT_APPLY_RETURN_FLOAT_AS_DOUBLE;
int return_float_as_nfloat = JIT_APPLY_RETURN_FLOAT_AS_NFLOAT;
int return_double_as_nfloat = JIT_APPLY_RETURN_DOUBLE_AS_NFLOAT;
int return_nfloat_as_double = JIT_APPLY_RETURN_NFLOAT_AS_DOUBLE;
int floats_in_word_regs = JIT_APPLY_FLOATS_IN_WORD_REGS;
int doubles_in_word_regs = JIT_APPLY_DOUBLES_IN_WORD_REGS;
int nfloats_in_word_regs = JIT_APPLY_NFLOATS_IN_WORD_REGS;
int return_floats_after = JIT_APPLY_RETURN_FLOATS_AFTER;
int return_doubles_after = JIT_APPLY_RETURN_DOUBLES_AFTER;
int return_nfloats_after = JIT_APPLY_RETURN_NFLOATS_AFTER;
int varargs_on_stack = JIT_APPLY_VARARGS_ON_STACK;
int struct_return_special_reg = JIT_APPLY_STRUCT_RETURN_SPECIAL_REG;
int struct_reg_overlaps_word_reg = JIT_APPLY_STRUCT_REG_OVERLAPS_WORD_REG;
int struct_return_in_reg[64] = JIT_APPLY_STRUCT_RETURN_IN_REG;
int align_long_regs = JIT_APPLY_ALIGN_LONG_REGS;
int align_long_stack = JIT_APPLY_ALIGN_LONG_STACK;
int can_split_long = JIT_APPLY_CAN_SPLIT_LONG;
int x86_fastcall = JIT_APPLY_X86_FASTCALL;
int parent_frame_offset = JIT_APPLY_PARENT_FRAME_OFFSET;
int return_address_offset = JIT_APPLY_RETURN_ADDRESS_OFFSET;
int broken_frame_builtins = JIT_APPLY_BROKEN_FRAME_BUILTINS;
int max_struct_in_reg = JIT_APPLY_MAX_STRUCT_IN_REG;
int x86_pop_struct_return = JIT_APPLY_X86_POP_STRUCT_RETURN;
int pad_float_regs = JIT_APPLY_PAD_FLOAT_REGS;
#endif
int max_apply_size = 0;
void *mem_copy(void *dest, const void *src, unsigned int len)
{
unsigned char *d = (unsigned char *)dest;
const unsigned char *s = (const unsigned char *)src;
while(len > 0)
{
*d++ = *s++;
--len;
}
return dest;
}
#define jit_memcpy mem_copy
void mem_set(void *dest, int value, unsigned int len)
{
unsigned char *d = (unsigned char *)dest;
while(len > 0)
{
*d++ = (unsigned char)value;
--len;
}
}
int mem_cmp(const void *s1, const void *s2, unsigned int len)
{
const unsigned char *str1 = (const unsigned char *)s1;
const unsigned char *str2 = (const unsigned char *)s2;
while(len > 0)
{
if(*str1 < *str2)
return -1;
else if(*str1 > *str2)
return 1;
++str1;
++str2;
--len;
}
return 0;
}
/*
* Detect the number of word registers that are used in function calls.
* We assume that the platform uses less than 32 registers in outgoing calls.
*/
void detect_word_regs(jit_nint arg1, jit_nint arg2, jit_nint arg3,
jit_nint arg4, jit_nint arg5, jit_nint arg6,
jit_nint arg7, jit_nint arg8, jit_nint arg9,
jit_nint arg10, jit_nint arg11, jit_nint arg12,
jit_nint arg13, jit_nint arg14, jit_nint arg15,
jit_nint arg16, jit_nint arg17, jit_nint arg18,
jit_nint arg19, jit_nint arg20, jit_nint arg21,
jit_nint arg22, jit_nint arg23, jit_nint arg24,
libjit/tools/gen-apply.c view on Meta::CPAN
align_values[2], align_values[3], align_values[4],
align_values[5], align_values[6], align_values[7],
align_values[8], align_values[9], align_values[10],
align_values[11], align_values[12], align_values[13],
align_values[14], align_values[15], align_values[16],
align_values[17], align_values[18], align_values[19]);
detect_stack_align_even_words
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
value1, value2);
}
else
{
detect_reg_split_odd_words
(align_values[0], align_values[1],
align_values[2], align_values[3], align_values[4],
align_values[5], align_values[6], align_values[7],
align_values[8], align_values[9], align_values[10],
align_values[11], align_values[12], align_values[13],
align_values[14], align_values[15], align_values[16],
align_values[17], align_values[18], align_values[19]);
detect_stack_align_odd_words
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
value1, value2);
}
}
#else /* JIT_NATIVE_INT64 */
void detect_long_alignment()
{
/* Long values are always aligned on 64-bit architectures */
}
#endif /* JIT_NATIVE_INT64 */
/*
* Determine the maximum size for the apply structure.
*/
void detect_max_sizes(void)
{
max_apply_size = (struct_return_special_reg + num_word_regs + 1)
* sizeof(jit_nint);
if(pass_reg_nfloat_as_double)
{
max_apply_size += num_float_regs * sizeof(double);
}
else
{
max_apply_size += num_float_regs * sizeof(jit_nfloat);
}
if(pad_float_regs)
{
max_apply_size += pad_float_regs * sizeof(jit_nint);
}
if(x86_fastcall && max_apply_size < 12)
{
max_apply_size = 12;
}
}
/*
* Detect the offsets of parent frame and return address pointers
* in the values returned by "__builtin_frame_address". We have to
* do this carefully, to deal with architectures that don't create
* a real frame for leaf functions.
*/
#if defined(PLATFORM_IS_GCC)
void find_frame_offset_inner(void *looking_for, void **frame)
{
int offset;
if(looking_for == (void *)frame || !frame)
{
/* Can happen on Alpha platforms */
broken_frame_builtins = 1;
return;
}
for(offset = 0; offset >= -8; --offset)
{
if(frame[offset] == looking_for)
{
parent_frame_offset = offset * sizeof(void *);
return;
}
}
for(offset = 1; offset <= 8; ++offset)
{
if(frame[offset] == looking_for)
{
parent_frame_offset = offset * sizeof(void *);
return;
}
}
}
void find_frame_offset_outer(void *looking_for)
{
void *frame_address;
#if defined(_JIT_ARCH_GET_CURRENT_FRAME)
_JIT_ARCH_GET_CURRENT_FRAME(frame_address);
#else
frame_address = __builtin_frame_address(0);
#endif
find_frame_offset_inner(looking_for, (void **)frame_address);
}
void find_return_offset(void *looking_for, void **frame)
{
int offset;
if(broken_frame_builtins)
{
return;
}
for(offset = 1; offset <= 8; ++offset)
{
if(frame[offset] == looking_for)
{
return_address_offset = offset * sizeof(void *);
return;
}
}
for(offset = 0; offset >= -8; --offset)
{
if(frame[offset] == looking_for)
{
return_address_offset = offset * sizeof(void *);
return;
}
}
}
void detect_frame_offsets(void)
{
void *frame_address, *return_address;
#if defined(_JIT_ARCH_GET_CURRENT_FRAME)
_JIT_ARCH_GET_CURRENT_FRAME(frame_address);
#else
frame_address = __builtin_frame_address(0);
#endif
return_address = __builtin_return_address(0);
find_frame_offset_outer(frame_address);
find_return_offset(return_address, frame_address);
if(parent_frame_offset == 0 && return_address_offset == 0)
{
/* Can happen on platforms like ia64 where there are so
many registers that the frame is almost never concrete */
broken_frame_builtins = 1;
}
}
#else
void detect_frame_offsets(void)
{
/* We don't know how to detect the offsets, so assume some defaults */
parent_frame_offset = 0;
return_address_offset = sizeof(void *);
}
#endif
/*
* Dump the definition of the "jit_apply_return" union, which defines
* the layout of the return value from "__builtin_apply".
*/
void dump_return_union(void)
{
const char *float_type;
const char *double_type;
const char *nfloat_type;
/* Determine the float return types */
if(return_float_as_nfloat)
{
float_type = "jit_nfloat";
}
else if(return_float_as_double)
{
float_type = "double";
}
else
{
float_type = "float";
}
if(return_double_as_nfloat)
{
double_type = "jit_nfloat";
}
else
{
double_type = "double";
}
if(return_nfloat_as_double)
{
nfloat_type = "double";
}
else
{
nfloat_type = "jit_nfloat";
}
/* Dump the definition of "jit_apply_return" */
printf("typedef union\n{\n");
printf("\tjit_nint int_value;\n");
printf("\tjit_nuint uint_value;\n");
printf("\tjit_long long_value;\n");
printf("\tjit_ulong ulong_value;\n");
if(return_floats_after)
{
printf("\tstruct { jit_ubyte pad[%d]; %s f_value; } float_value;\n",
return_floats_after, float_type);
}
else
{
printf("\tstruct { %s f_value; } float_value;\n", float_type);
}
if(return_doubles_after)
libjit/tools/gen-apply.c view on Meta::CPAN
detect_nfloat_overlap(123.78, 1, 2);
}
/* Determine if "long double" values should be demoted to "double" */
if(floats_in_word_regs)
{
pass_reg_nfloat_as_double = 1;
}
else if(num_float_regs > 0)
{
detect_float_reg_size_regs(48.67, 182.36);
}
else
{
detect_float_reg_size_stack(48.67, 182.36);
}
if(sizeof(jit_float64) == sizeof(jit_nfloat))
{
pass_stack_nfloat_as_double = 1;
pass_reg_nfloat_as_double = 1;
}
/* Determine if "float" should be promoted to "double" */
detect_float_promotion(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0,
25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0);
/* Determine if "double" should be promoted to "nfloat" */
detect_double_promotion(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0,
25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0);
/* Determine if variable arguments are always passed on the stack */
detect_varargs_on_stack(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31);
/* Detect the size and positioning of floating-point return values */
detect_float_return();
/* Detect the calling conventions for structures */
detect_struct_conventions();
/* Detect support for x86 FASTCALL handling code */
#if defined(PLATFORM_IS_X86)
x86_fastcall = 1;
floats_in_word_regs = 1;
#endif
/* Detect whether x86 platforms pop the structure return pointer */
#if defined(PLATFORM_IS_X86)
x86_pop_struct_return = 1;
/* TODO */
#endif
/* Detect the alignment of "long" values */
detect_long_alignment();
/* Detect the location of parent frames and return addresses
in the value returned by "__builtin_frame_address" */
detect_frame_offsets();
#endif
/* Determine the maximum sizes */
detect_max_sizes();
/* Print the results */
printf("/%c This file was auto-generated by \"gen-apply\" - DO NOT EDIT %c/\n\n", '*', '*');
printf("#ifndef _JIT_APPLY_RULES_H\n");
printf("#define _JIT_APPLY_RULES_H\n\n");
printf("#define JIT_APPLY_NUM_WORD_REGS %d\n", num_word_regs);
printf("#define JIT_APPLY_NUM_FLOAT_REGS %d\n", num_float_regs);
printf("#define JIT_APPLY_NUM_DOUBLE_REGS %d\n", num_double_regs);
printf("#define JIT_APPLY_NUM_NFLOAT_REGS %d\n", num_nfloat_regs);
printf("#define JIT_APPLY_PASS_STACK_FLOAT_AS_DOUBLE %d\n",
pass_stack_float_as_double);
printf("#define JIT_APPLY_PASS_STACK_FLOAT_AS_NFLOAT %d\n",
pass_stack_float_as_nfloat);
printf("#define JIT_APPLY_PASS_STACK_DOUBLE_AS_NFLOAT %d\n",
pass_stack_double_as_nfloat);
printf("#define JIT_APPLY_PASS_STACK_NFLOAT_AS_DOUBLE %d\n",
pass_stack_nfloat_as_double);
printf("#define JIT_APPLY_PASS_REG_FLOAT_AS_DOUBLE %d\n",
pass_reg_float_as_double);
printf("#define JIT_APPLY_PASS_REG_FLOAT_AS_NFLOAT %d\n",
pass_reg_float_as_nfloat);
printf("#define JIT_APPLY_PASS_REG_DOUBLE_AS_NFLOAT %d\n",
pass_reg_double_as_nfloat);
printf("#define JIT_APPLY_PASS_REG_NFLOAT_AS_DOUBLE %d\n",
pass_reg_nfloat_as_double);
printf("#define JIT_APPLY_RETURN_FLOAT_AS_DOUBLE %d\n", return_float_as_double);
printf("#define JIT_APPLY_RETURN_FLOAT_AS_NFLOAT %d\n", return_float_as_nfloat);
printf("#define JIT_APPLY_RETURN_DOUBLE_AS_NFLOAT %d\n", return_double_as_nfloat);
printf("#define JIT_APPLY_RETURN_NFLOAT_AS_DOUBLE %d\n", return_nfloat_as_double);
printf("#define JIT_APPLY_FLOATS_IN_WORD_REGS %d\n", floats_in_word_regs);
printf("#define JIT_APPLY_DOUBLES_IN_WORD_REGS %d\n", doubles_in_word_regs);
printf("#define JIT_APPLY_NFLOATS_IN_WORD_REGS %d\n", nfloats_in_word_regs);
printf("#define JIT_APPLY_RETURN_FLOATS_AFTER %d\n", return_floats_after);
printf("#define JIT_APPLY_RETURN_DOUBLES_AFTER %d\n", return_doubles_after);
printf("#define JIT_APPLY_RETURN_NFLOATS_AFTER %d\n", return_nfloats_after);
printf("#define JIT_APPLY_VARARGS_ON_STACK %d\n", varargs_on_stack);
printf("#define JIT_APPLY_STRUCT_RETURN_SPECIAL_REG %d\n", struct_return_special_reg);
printf("#define JIT_APPLY_STRUCT_REG_OVERLAPS_WORD_REG %d\n",
struct_reg_overlaps_word_reg);
printf("#define JIT_APPLY_ALIGN_LONG_REGS %d\n", align_long_regs);
printf("#define JIT_APPLY_ALIGN_LONG_STACK %d\n", align_long_stack);
printf("#define JIT_APPLY_CAN_SPLIT_LONG %d\n", can_split_long);
printf("#define JIT_APPLY_STRUCT_RETURN_IN_REG_INIT \\\n\t{");
max_struct_in_reg = 0;
for(size = 0; size < 64; size += 8)
{
flags = 0;
if(struct_return_in_reg[size])
{
flags |= 0x01;
max_struct_in_reg = size + 1;
}
if(struct_return_in_reg[size + 1])
{
flags |= 0x02;
max_struct_in_reg = size + 2;
}
if(struct_return_in_reg[size + 2])
{
flags |= 0x04;
max_struct_in_reg = size + 3;
}
if(struct_return_in_reg[size + 3])
{
flags |= 0x08;
max_struct_in_reg = size + 4;
}
if(struct_return_in_reg[size + 4])
{
flags |= 0x10;
max_struct_in_reg = size + 5;
}
if(struct_return_in_reg[size + 5])
{
flags |= 0x20;
max_struct_in_reg = size + 6;
}
if(struct_return_in_reg[size + 6])
{
flags |= 0x40;
max_struct_in_reg = size + 7;
}
if(struct_return_in_reg[size + 7])
{
flags |= 0x80;
max_struct_in_reg = size + 8;
}
if(size != 0)
{
printf(", 0x%02X", flags);
}
else
{
printf("0x%02X", flags);
}
}
printf("}\n");
printf("#define JIT_APPLY_MAX_STRUCT_IN_REG %d\n", max_struct_in_reg);
printf("#define JIT_APPLY_MAX_APPLY_SIZE %d\n", max_apply_size);
printf("#define JIT_APPLY_X86_FASTCALL %d\n", x86_fastcall);
printf("#define JIT_APPLY_PARENT_FRAME_OFFSET %d\n", parent_frame_offset);
printf("#define JIT_APPLY_RETURN_ADDRESS_OFFSET %d\n",
return_address_offset);
printf("#define JIT_APPLY_BROKEN_FRAME_BUILTINS %d\n",
broken_frame_builtins);
printf("#define JIT_APPLY_X86_POP_STRUCT_RETURN %d\n",
x86_pop_struct_return);
printf("#define JIT_APPLY_PAD_FLOAT_REGS %d\n", pad_float_regs);
printf("\n");
/* Dump the definition of the "jit_apply_return" union */
dump_return_union();
/* Dump the definition of the apply structure */
dump_apply_structure();
/* Dump the macros that are used to perform function application */
dump_apply_macros();
/* Print the footer on the output */
printf("#endif /%c _JIT_APPLY_RULES_H %c/\n", '*', '*');
/* Done */
return 0;
}
#else /* !(PLATFORM_IS_GCC || PLATFORM_IS_WIN32) */
int main(int argc, char *argv[])
{
printf("#error \"gcc is required to detect the apply rules\"\n");
return 0;
}
#endif /* !(PLATFORM_IS_GCC || PLATFORM_IS_WIN32) */
( run in 0.333 second using v1.01-cache-2.11-cpan-3d66aa2751a )