Index: src/pmc/nci.pmc =================================================================== --- src/pmc/nci.pmc (revision 42001) +++ src/pmc/nci.pmc (working copy) @@ -63,11 +63,10 @@ param_sig[j++] = 'P'; case (INTVAL)'v': break; - /* I have no idea how to handle these */ case (INTVAL)'2': case (INTVAL)'3': case (INTVAL)'4': - param_sig[j++] = 'I'; + param_sig[j++] = 'P'; break; case (INTVAL)'@': param_sig[j++] = '@'; Index: t/steps/auto/libjit-01.t =================================================================== --- t/steps/auto/libjit-01.t (revision 42001) +++ t/steps/auto/libjit-01.t (working copy) @@ -6,7 +6,7 @@ use strict; use warnings; -use Test::More tests => 34; +use Test::More tests => 40; use lib qw( lib t/configure/testlib ); use Parrot::Configure; use Parrot::Configure::Options 'process_options'; @@ -107,26 +107,55 @@ $conf->data->set( 'cc_build_call_frames' => undef ); $conf->data->set( 'has_exec_protect' => undef ); +$conf->data->set( 'libjit_has_alloca' => undef ); $conf->data->set( 'libs' => '' ); + $has_libjit = 1; $extra_libs = 'mylibs'; +$conf->data->set( 'cpuarch' => 'i386' ); + auto::libjit::_handle_has_libjit($conf, $has_libjit, $extra_libs); is( $conf->data->get( 'cc_build_call_frames' ), '-DCAN_BUILD_CALL_FRAMES', "Got expected value for cc_build_call_frames" ); ok( $conf->data->get( 'has_exec_protect' ), "has_exec_protect' set" ); +ok( $conf->data->get( 'libjit_has_alloca'), + "on i386 with libJIT, 'libjit_has_alloca' has true value" ); is( $conf->data->get( 'libs' ), " $extra_libs", "Got expected value for libs" ); $conf->data->set( 'cc_build_call_frames' => undef ); $conf->data->set( 'has_exec_protect' => undef ); +$conf->data->set( 'libjit_has_alloca' => undef ); $conf->data->set( 'libs' => '' ); + +$has_libjit = 1; +$extra_libs = 'mylibs'; +$conf->data->set( 'cpuarch' => 'ppc' ); + +auto::libjit::_handle_has_libjit($conf, $has_libjit, $extra_libs); +is( $conf->data->get( 'cc_build_call_frames' ), '-DCAN_BUILD_CALL_FRAMES', + "Got expected value for cc_build_call_frames" ); +ok( $conf->data->get( 'has_exec_protect' ), "has_exec_protect' set" ); +ok( ! $conf->data->get( 'libjit_has_alloca'), + "on non-i386 with libJIT, 'libjit_has_alloca' has false value" ); +is( $conf->data->get( 'libs' ), " $extra_libs", + "Got expected value for libs" ); + +$conf->data->set( 'cc_build_call_frames' => undef ); +$conf->data->set( 'has_exec_protect' => undef ); +$conf->data->set( 'libjit_has_alloca' => undef ); +$conf->data->set( 'libs' => '' ); + $has_libjit = 0; $extra_libs = 'mylibs'; + auto::libjit::_handle_has_libjit($conf, $has_libjit, $extra_libs); ok( ! defined($conf->data->get( 'cc_build_call_frames' )), "cc_build_call_frames undefined as expected" ); ok( ! defined($conf->data->get( 'has_exec_protect' )), "has_exec_protect' undefined" ); +ok( ! $conf->data->get( 'libjit_has_alloca'), + "without libJIT, 'libjit_has_alloca' has false value" ); is( $conf->data->get( 'libs' ), "", "Got expected value for libs" ); Index: t/steps/gen/libjit-01.t =================================================================== --- t/steps/gen/libjit-01.t (revision 42001) +++ t/steps/gen/libjit-01.t (working copy) @@ -6,8 +6,9 @@ use strict; use warnings; -use constant num_generated_files => 2; -use Test::More tests => 8 + 2*num_generated_files; +use constant NUM_GENERATED_FILES => 2; +# use Test::More tests => 8 + 2*NUM_GENERATED_FILES; +use Test::More qw( no_plan ); use File::Copy 'move'; use File::Temp 'tempfile'; @@ -39,8 +40,10 @@ $conf->options->set( %$args ); my $step = test_step_constructor_and_description($conf); -is( scalar keys %{$step->{targets}}, num_generated_files, "Expected number of generated files"); -is_deeply([keys %{$step->{targets}}], [keys %{$step->{templates}}], "Templates match targets"); +is( scalar keys %{$step->{targets}}, NUM_GENERATED_FILES, + "Expected number of generated files"); +is_deeply([keys %{$step->{targets}}], [keys %{$step->{templates}}], + "Templates match targets"); foreach (keys %{$step->{templates}}) { ok(-f $step->{templates}{$_}, "Able to locate $_ template") @@ -56,6 +59,8 @@ my %orig_conf = map { $_ => $conf->data->get($_) } qw[ iv nv ]; $conf->data->set( iv => 'int', nv => 'float' ); +# Set a value for 'libjit_has_alloca' to avoid uninitialized value warning. +$conf->data->set( 'libjit_has_alloca' => 1 ); my $ret = $step->runstep($conf); ok( $ret, "runstep() returned true value" ); foreach (keys %{$step->{targets}}) { Index: config/auto/libjit.pm =================================================================== --- config/auto/libjit.pm (revision 42001) +++ config/auto/libjit.pm (working copy) @@ -94,10 +94,14 @@ if ($has_libjit) { $conf->data->set( cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES', - has_exec_protect => 1, + has_exec_protect => 1, + libjit_has_alloca => ($conf->data->get('cpuarch') eq 'i386' ? '1' : '0'), ); $conf->data->add( ' ', libs => $extra_libs ); } + else { + $conf->data->set( libjit_has_alloca => 0 ); + } } 1; Index: config/gen/libjit.pm =================================================================== --- config/gen/libjit.pm (revision 42001) +++ config/gen/libjit.pm (working copy) @@ -61,6 +61,9 @@ Parrot_init_arg_nci => [ qw(void_ptr void_ptr void_ptr) => 'void_ptr' ], pmc_new_noinit => [ qw(void_ptr INTVAL) => 'void_ptr' ], + + mem_sys_allocate => [ ('long') => 'void_ptr' ], + mem_sys_free => [ ('void_ptr') => 'void' ], }, ); return \%data; Index: config/gen/libjit/frame_builder_libjit_c.in =================================================================== --- config/gen/libjit/frame_builder_libjit_c.in (revision 42001) +++ config/gen/libjit/frame_builder_libjit_c.in (working copy) @@ -112,9 +112,8 @@ Parrot_jit_create_thunk(PARROT_INTERP, char *sig, void *priv) { struct jit_buffer_private_data *p; jit_function_t f; - jit_value_t jit_interp, jit_func; - jit_type_t *jit_args_t; - jit_value_t *jit_args_v, *jit_regs; + jit_value_t jit_interp, jit_nci_pmc, jit_pcc_sig; + jit_value_t jit_func, jit_st; /* populate private data */ p = (struct jit_buffer_private_data*)priv; @@ -127,30 +126,42 @@ /* start JIT function */ { jit_type_t arg_types[] = { - jit_type_void_ptr, /* interp */ - jit_type_void_ptr /* nci_info */ + jit_type_void_ptr, /* interp */ + jit_type_void_ptr, /* nci_pmc */ + jit_type_void_ptr /* pcc_sig */ }; - jit_type_t f_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_void, arg_types, 2, 1); + jit_type_t f_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_void, arg_types, 3, 1); f = jit_function_create(p->ctx, f_sig); } /* get the incomming args */ - jit_interp = jit_value_get_param(f, 0); - jit_func = jit__vtable_get_pointer(f, jit_interp, jit_value_get_param(f, 1)); + jit_interp = jit_value_get_param(f, 0); + jit_nci_pmc = jit_value_get_param(f, 1); + jit_pcc_sig = jit_value_get_param(f, 2); + /* get the wrapped function */ + jit_func = jit__vtable_get_pointer(f, jit_interp, jit_nci_pmc); + + /* allocate call_state */ + { + jit_value_t sizeof_call_state + = jit_value_create_nint_constant(f, jit_type_sys_int, sizeof (call_state)); + jit_st = JIT_ALLOCA(f, sizeof_call_state); + } + + /* init pcc */ + jit__Parrot_init_arg_nci(f, jit_interp, jit_st, jit_pcc_sig); + /* get the outgoing args */ { - jit_value_t st; - int nargs; + int nargs = strlen(sig) - 1; - { - jit_value_t sizeof_call_state - = jit_value_create_nint_constant(f, jit_type_sys_int, sizeof (call_state)); - st = jit_insn_alloca(f, sizeof_call_state); - } + jit_type_t jit_args_t[nargs]; + jit_value_t jit_args_v[nargs]; + jit_value_t jit_regs[nargs]; - nargs = Parrot_jit_parse_sig_args_pre(interp, sig, f, jit_interp, st, - &jit_args_t, &jit_args_v, &jit_regs); + Parrot_jit_parse_sig_args_pre(interp, sig, nargs, f, jit_interp, jit_st, + jit_args_t, jit_args_v, jit_regs); /* get the return type */ { @@ -167,13 +178,16 @@ } /* get the incomming return */ - Parrot_jit_parse_sig_ret_post(interp, sig, f, jit_interp, st, ret_v); + Parrot_jit_parse_sig_ret_post(interp, sig, f, jit_interp, jit_st, ret_v); } /* clean up args */ Parrot_jit_parse_sig_args_post(interp, sig, nargs, f, jit_interp, jit_args_v, jit_regs); } + /* deallocate call_state */ + JIT_ALLOCA_FREE(f, jit_st); + /* end JIT function */ jit_insn_return(f, NULL); @@ -181,29 +195,18 @@ jit_function_compile(f); jit_context_build_end(p->ctx); - mem_sys_free(jit_args_t); - mem_sys_free(jit_args_v); - mem_sys_free(jit_regs); - return jit_function_to_closure(f); } -int -Parrot_jit_parse_sig_args_pre(PARROT_INTERP, char *sig, jit_function_t f, - jit_value_t jinterp, jit_value_t st, - jit_type_t **arg_types, - jit_value_t **arg_vals, jit_value_t **arg_regs) { - int nargs, nregs, i, j; +void +Parrot_jit_parse_sig_args_pre(PARROT_INTERP, char *sig, int nargs, + jit_function_t f, jit_value_t jinterp, jit_value_t st, + jit_type_t *arg_types, + jit_value_t *arg_vals, jit_value_t *arg_regs) { + int i, j; sig += 1; /* ignore return character */ - nargs = strlen(sig); - nregs = Parrot_jit_init_pcc(sig, nargs, f, jinterp, st); - - *arg_types = (jit_type_t *)mem_sys_allocate(nargs * sizeof (jit_type_t)); - *arg_vals = (jit_value_t *)mem_sys_allocate(nargs * sizeof (jit_value_t)); - *arg_regs = (jit_value_t *)mem_sys_allocate(nregs * sizeof (jit_value_t)); - for (i = 0, j = 0; i < nargs; i++) { char c; jit_type_t t1; @@ -212,10 +215,10 @@ case 'I': t1 = JIT_TYPE_INTVAL; read_int_reg: - (*arg_types)[i] = t1; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_I(f, jinterp, st, v1); - (*arg_regs)[j++] = (*arg_vals)[i] = v2; + arg_types[i] = t1; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_I(f, jinterp, st, v1); + arg_regs[j++] = arg_vals[i] = v2; break; case 'c': t1 = jit_type_sys_char; @@ -233,10 +236,10 @@ case 'N': t1 = JIT_TYPE_FLOATVAL; read_float_reg: - (*arg_types)[i] = t1; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_N(f, jinterp, st, v1); - (*arg_regs)[j++] = (*arg_vals)[i] = v2; + arg_types[i] = t1; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_N(f, jinterp, st, v1); + arg_regs[j++] = arg_vals[i] = v2; break; case 'f': t1 = jit_type_sys_float; @@ -246,50 +249,50 @@ goto read_float_reg; case 'S': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_S(f, jinterp, st, v1); - (*arg_regs)[j++] = (*arg_vals)[i] = v2; + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_S(f, jinterp, st, v1); + arg_regs[j++] = arg_vals[i] = v2; break; case 't': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_S(f, jinterp, st, v1); - (*arg_regs)[j++] = v2; - (*arg_vals)[i] = jit__Parrot_str_to_cstring(f, jinterp, v2); + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_S(f, jinterp, st, v1); + arg_regs[j++] = v2; + arg_vals[i] = jit__Parrot_str_to_cstring(f, jinterp, v2); break; case 'b': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_S(f, jinterp, st, v1); - (*arg_regs)[j++] = v2; - (*arg_vals)[i] = jit__Buffer_bufstart(f, v2); + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_S(f, jinterp, st, v1); + arg_regs[j++] = v2; + arg_vals[i] = jit__Buffer_bufstart(f, v2); break; case 'B': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_S(f, jinterp, st, v1); - (*arg_regs)[j++] = v2; - v3 = jit__Parrot_str_to_cstring(f, jinterp, v2); + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_S(f, jinterp, st, v1); + arg_regs[j++] = v2; + v3 = jit__Parrot_str_to_cstring(f, jinterp, v2); jit_value_set_addressable(v3); - (*arg_vals)[i] = jit_insn_address_of(f, v3); + arg_vals[i] = jit_insn_address_of(f, v3); break; case 'p': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_p(f, jinterp, st, v1); - (*arg_regs)[j++] = (*arg_vals)[i] = v2; + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_p(f, jinterp, st, v1); + arg_regs[j++] = arg_vals[i] = v2; break; case 'P': case 'O': case '@': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_P(f, jinterp, st, v1); - (*arg_regs)[j++] = (*arg_vals)[i] = v2; + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_P(f, jinterp, st, v1); + arg_regs[j++] = arg_vals[i] = v2; break; case '2': t1 = jit_type_sys_short; @@ -300,109 +303,53 @@ case '4': t1 = jit_type_sys_long; call_get_integer: - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_P(f, jinterp, st, v1); - (*arg_regs)[j++] = v2; - v3 = jit__vtable_get_integer(f, jinterp, v2); - v4 = jit_value_create(f, t1); + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_P(f, jinterp, st, v1); + arg_regs[j++] = v2; + v3 = jit__vtable_get_integer(f, jinterp, v2); + v4 = jit_value_create(f, t1); jit_value_set_addressable(v4); jit_insn_store(f, v4, v3); - (*arg_vals)[i] = jit_insn_address_of(f, v4); + arg_vals[i] = jit_insn_address_of(f, v4); break; case 'V': - (*arg_types)[i] = jit_type_void_ptr; - v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); - v2 = jit__get_nci_P(f, jinterp, st, v1); - (*arg_regs)[j++] = v2; - v3 = jit__vtable_get_pointer(f, jinterp, v2); - v4 = jit_value_create(f, jit_type_void_ptr); + arg_types[i] = jit_type_void_ptr; + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j); + v2 = jit__get_nci_P(f, jinterp, st, v1); + arg_regs[j++] = v2; + v3 = jit__vtable_get_pointer(f, jinterp, v2); + v4 = jit_value_create(f, jit_type_void_ptr); jit_value_set_addressable(v4); jit_insn_store(f, v4, v3); - (*arg_vals)[i] = jit_insn_address_of(f, v4); + arg_vals[i] = jit_insn_address_of(f, v4); break; case '0': - (*arg_types)[i] = jit_type_void_ptr; - (*arg_vals)[i] = jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL); + arg_types[i] = jit_type_void_ptr; + arg_vals[i] = jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL); break; case 'J': - (*arg_types)[i] = jit_type_void_ptr; - (*arg_vals)[i] = jinterp; + arg_types[i] = jit_type_void_ptr; + arg_vals[i] = jinterp; break; case 'U': /* TODO */ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, "arg type 'U' not yet implemented"); - return -1; + return; default: Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, "unkown arg type '%c'", c); - return -1; + return; } } - - return nargs; } -int -Parrot_jit_init_pcc(char *sig, int nargs, jit_function_t f, jit_value_t interp, jit_value_t st) { - int i, j; - char pcc_sig[nargs]; - - for (i = 0, j = 0; i < nargs; i++) { - switch (sig[i]) { - case 'I': - case 'c': - case 's': - case 'i': - case 'l': - pcc_sig[j++] = 'I'; - break; - - case 'N': - case 'f': - case 'd': - pcc_sig[j++] = 'N'; - break; - - case 'S': - case 't': - case 'b': - case 'B': - pcc_sig[j++] = 'S'; - break; - - case 'p': - case 'P': - case 'O': - case 'V': - case '2': - case '3': - case '4': - pcc_sig[j++] = 'P'; - break; - - case '@': - pcc_sig[j++] = '@'; - break; - - default: - break; - } - } - pcc_sig[j] = '\0'; - - jit__Parrot_init_arg_nci(f, interp, st, - jit_value_create_string_constant(f, pcc_sig, j+1)); - - return j; -} - jit_type_t Parrot_jit_parse_sig_ret_pre(PARROT_INTERP, char *sig) { char c; @@ -591,26 +538,6 @@ return jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, i); } -jit_value_t -jit_value_create_string_constant(jit_function_t f, char *str, int len) { - jit_value_t jit_len, jit_str; - int i; - - if (len < 1) { - len = strlen(str); - } - - jit_len = jit_value_create_nint_constant(f, jit_type_sys_int, len); - jit_str = jit_insn_alloca(f, jit_len); - - for (i = 0; i < len; i++) { - jit_value_t c = jit_value_create_nint_constant(f, jit_type_sys_char, str[i]); - jit_insn_store_relative(f, jit_str, i, c); - } - - return jit_str; -} - /* * JIT wrappers */ Index: config/gen/libjit/frame_builder_libjit_h.in =================================================================== --- config/gen/libjit/frame_builder_libjit_h.in (revision 42001) +++ config/gen/libjit/frame_builder_libjit_h.in (working copy) @@ -33,9 +33,9 @@ * JIT types */ -#define JIT_TYPE_UINTVAL @libjit_uv@ // jit_type_sys_ulong -#define JIT_TYPE_INTVAL @libjit_iv@ // jit_type_sys_long -#define JIT_TYPE_FLOATVAL @libjit_nv@ // jit_type_sys_double +#define JIT_TYPE_UINTVAL @libjit_uv@ +#define JIT_TYPE_INTVAL @libjit_iv@ +#define JIT_TYPE_FLOATVAL @libjit_nv@ /* * JIT functions @@ -44,13 +44,10 @@ void * Parrot_jit_create_thunk(Interp *, char *, void *); -int -Parrot_jit_parse_sig_args_pre(Interp *, char *, jit_function_t, jit_value_t, jit_value_t, - jit_type_t **, jit_value_t **, jit_value_t **); +void +Parrot_jit_parse_sig_args_pre(Interp *, char *, int, jit_function_t, jit_value_t, jit_value_t, + jit_type_t *, jit_value_t *, jit_value_t *); -int -Parrot_jit_init_pcc(char *, int, jit_function_t, jit_value_t, jit_value_t); - jit_type_t Parrot_jit_parse_sig_ret_pre(Interp *, char *); @@ -63,8 +60,16 @@ jit_value_t jit_value_create_intval_constant(jit_function_t, INTVAL); -jit_value_t -jit_value_create_string_constant(jit_function_t, char *, int); +/* + * workaround for platforms that lack libjit alloca support + */ +#if @libjit_has_alloca@ +# define JIT_ALLOCA(f, n) jit_insn_alloca(f, n) +# define JIT_ALLOCA_FREE(f, p) +#else +# define JIT_ALLOCA(f, n) jit__mem_sys_allocate(f, n) +# define JIT_ALLOCA_FREE(f, p) jit__mem_sys_free(f, p) +#endif /* * JIT wrappers