diff --git a/MANIFEST b/MANIFEST index 840b7f8..0f3bd1b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -234,9 +234,6 @@ config/auto/env/test_setenv_c.in [] config/auto/env/test_unsetenv_c.in [] config/auto/format.pm [] config/auto/frames.pm [] -config/auto/frames/test_exec_cygwin_c.in [] -config/auto/frames/test_exec_linux_c.in [] -config/auto/frames/test_exec_openbsd_c.in [] config/auto/gc.pm [] config/auto/gc/test_c.in [] config/auto/gcc.pm [] @@ -258,6 +255,8 @@ config/auto/inline/test2_c.in [] config/auto/isreg.pm [] config/auto/isreg/test_c.in [] config/auto/jit.pm [] +config/auto/libjit.pm [] +config/auto/libjit/libjit_c.in [] config/auto/memalign.pm [] config/auto/memalign/test2_c.in [] config/auto/memalign/test_c.in [] @@ -310,6 +309,9 @@ config/gen/core_pmcs.pm [] config/gen/crypto.pm [] config/gen/crypto/digest_pmc.in [] config/gen/crypto/digest_t.in [] +config/gen/libjit.pm [] +config/gen/libjit/frame_builder_libjit_c.in [] +config/gen/libjit/frame_builder_libjit_h.in [] config/gen/makefiles.pm [] config/gen/makefiles/CFLAGS.in [] config/gen/makefiles/data_json.in [] @@ -1940,6 +1942,7 @@ t/steps/auto/icu-01.t [test] t/steps/auto/inline-01.t [test] t/steps/auto/isreg-01.t [test] t/steps/auto/jit-01.t [test] +t/steps/auto/libjit-01.t [test] t/steps/auto/memalign-01.t [test] t/steps/auto/msvc-01.t [test] t/steps/auto/neg_0-01.t [test] @@ -1964,6 +1967,7 @@ t/steps/gen/config_h-01.t [test] t/steps/gen/config_pm-01.t [test] t/steps/gen/core_pmcs-01.t [test] t/steps/gen/crypto-01.t [test] +t/steps/gen/libjit-01.t [test] t/steps/gen/makefiles-01.t [test] t/steps/gen/opengl-01.t [test] t/steps/gen/parrot_include-01.t [test] diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index 38d117d..772755c 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -1,6 +1,6 @@ # ex: set ro: # $Id$ -# generated by tools/dev/mk_manifest_and_skip.pl Sun Sep 27 09:00:39 2009 UT +# generated by tools/dev/mk_manifest_and_skip.pl Sun Oct 18 15:34:28 2009 UT # # This file should contain a transcript of the svn:ignore properties # of the directories in the Parrot subversion repository. (Needed for @@ -653,6 +653,10 @@ ^src/extend_vtable\.c/ ^src/fingerprint\.c$ ^src/fingerprint\.c/ +^src/frame_builder_libjit\.c$ +^src/frame_builder_libjit\.c/ +^src/frame_builder_libjit\.h$ +^src/frame_builder_libjit\.h/ ^src/glut_callbacks\.c$ ^src/glut_callbacks\.c/ ^src/install_config\.c$ diff --git a/MANIFEST.generated b/MANIFEST.generated index ff86d1e..ee0aad0 100644 --- a/MANIFEST.generated +++ b/MANIFEST.generated @@ -1,4 +1,5 @@ # $Id$ +# Please re-sort this file after *EVERY* modification # See tools/dev/install_files.pl for documentation on the # format of this file. # Please re-sort this file after *EVERY* modification @@ -7,6 +8,7 @@ blib/lib/libparrot.a [main]lib blib/lib/libparrot.dylib [main]lib blib/lib/libparrot.so.1.7.0 [main]lib blib/lib/libparrot.so [main]lib +blib/lib/libparrot.so.1.6.0 [main]lib compilers/data_json/data_json.pbc [data_json] compilers/json/JSON.pbc [json] compilers/json/JSON/grammar.pbc [json] @@ -37,9 +39,9 @@ include/parrot/exec_dep.h [main]include include/parrot/extend_vtable.h [main]include include/parrot/feature.h [main]include include/parrot/has_header.h [main]include +include/parrot/oplib/core_ops.h [main]include include/parrot/oplib/core_ops_cg.h [main]include include/parrot/oplib/core_ops_cgp.h [main]include -include/parrot/oplib/core_ops.h [main]include include/parrot/oplib/core_ops_switch.h [main]include include/parrot/oplib/ops.h [main]include include/parrot/pbcversion.h [devel]include @@ -48,30 +50,28 @@ include/parrot/platform_interface.h [main]include include/parrot/platform_limits.h [devel]include include/parrot/vtable.h [main]include install_config.fpmc [main]lib -src/install_config.o [main]lib -src/install_config.obj [main]lib -installable_parrot_config.exe [main]bin +installable_parrot [main]bin +installable_parrot.exe [main]bin installable_parrot_config [main]bin -installable_parrot_debugger.exe [main]bin +installable_parrot_config.exe [main]bin installable_parrot_debugger [main]bin -installable_parrot.exe [main]bin -installable_parrot [main]bin -installable_pbc_disassemble.exe [main]bin +installable_parrot_debugger.exe [main]bin +installable_parrot_nqp [main]bin +installable_parrot_nqp.exe [main]bin installable_pbc_disassemble [main]bin -installable_pbc_dump.exe [main]bin +installable_pbc_disassemble.exe [main]bin installable_pbc_dump [main]bin -installable_pbc_merge.exe [main]bin +installable_pbc_dump.exe [main]bin installable_pbc_merge [main]bin -installable_pbc_to_exe.exe [main]bin +installable_pbc_merge.exe [main]bin installable_pbc_to_exe [main]bin -installable_parrot_nqp.exe [main]bin -installable_parrot_nqp [main]bin +installable_pbc_to_exe.exe [main]bin lib/Parrot/Config/Generated.pm [devel]lib -libparrot.dll [main]bin -libparrot.lib [main]bin lib/Parrot/OpLib/core.pm [devel]lib -lib/Parrot/Pmc2c/PCCMETHOD_BITS.pm [devel]lib lib/Parrot/PMC.pm [devel]lib +lib/Parrot/Pmc2c/PCCMETHOD_BITS.pm [devel]lib +libparrot.dll [main]bin +libparrot.lib [main]bin parrot.pc [main]pkgconfig runtime/parrot/dynext/digest_group.bundle [library] runtime/parrot/dynext/digest_group.dll [library] @@ -97,10 +97,10 @@ runtime/parrot/dynext/match_group.bundle [library] runtime/parrot/dynext/match_group.dll [library] runtime/parrot/dynext/match_group.dylib [library] runtime/parrot/dynext/match_group.so [library] -runtime/parrot/dynext/math_ops.so [library] runtime/parrot/dynext/math_ops.bundle [library] runtime/parrot/dynext/math_ops.dll [library] runtime/parrot/dynext/math_ops.dylib [library] +runtime/parrot/dynext/math_ops.so [library] runtime/parrot/dynext/obscure_ops.bundle [library] runtime/parrot/dynext/obscure_ops.dll [library] runtime/parrot/dynext/obscure_ops.dylib [library] @@ -145,47 +145,39 @@ runtime/parrot/include/vtable_methods.pasm [main] runtime/parrot/include/warnings.pasm [main] runtime/parrot/library/CGI/QueryHash.pbc [main] runtime/parrot/library/Config/JSON.pbc [main] -runtime/parrot/library/config.pbc [main] -runtime/parrot/library/config.pir [main] runtime/parrot/library/Crow.pbc [main] +runtime/parrot/library/Data/Dumper.pbc [main] runtime/parrot/library/Data/Dumper/Base.pbc [main] runtime/parrot/library/Data/Dumper/Default.pbc [main] -runtime/parrot/library/Data/Dumper.pbc [main] runtime/parrot/library/Data/Replace.pbc [main] runtime/parrot/library/Digest/MD5.pbc [main] -runtime/parrot/library/dumper.pbc [main] runtime/parrot/library/Getopt/Obj.pbc [main] runtime/parrot/library/HTTP/Daemon.pbc [main] runtime/parrot/library/Iter.pbc [main] runtime/parrot/library/JSON.pbc [main] -runtime/parrot/library/libpcre.pbc [main] -runtime/parrot/library/Math/Random/mt19937ar.pbc [main] -runtime/parrot/library/Math/Rand.pbc [main] runtime/parrot/library/MIME/Base64.pbc [main] +runtime/parrot/library/Math/Rand.pbc [main] +runtime/parrot/library/Math/Random/mt19937ar.pbc [main] runtime/parrot/library/NCI/call_toolkit_init.pbc [main] -runtime/parrot/library/ncurses.pbc [main] -runtime/parrot/library/OpenGL_funcs.pir [main] -runtime/parrot/library/OpenGL_funcs.pbc [main] runtime/parrot/library/OpenGL.pbc [main] +runtime/parrot/library/OpenGL_funcs.pbc [main] +runtime/parrot/library/OpenGL_funcs.pir [main] runtime/parrot/library/P6object.pbc [main] -runtime/parrot/library/Parrot/Capture_PIR.pbc [main] -runtime/parrot/library/Parrot/Coroutine.pbc [main] -runtime/parrot/library/Parrot/Exception.pbc [main] -runtime/parrot/library/Parrot/HLLCompiler.pbc [main] -runtime/parrot/library/parrotlib.pbc [main] -runtime/parrot/library/pcore.pbc [main] -runtime/parrot/library/pcre.pbc [main] +runtime/parrot/library/PCT.pbc [main] runtime/parrot/library/PCT/Grammar.pbc [main] runtime/parrot/library/PCT/HLLCompiler.pbc [main] runtime/parrot/library/PCT/PAST.pbc [main] -runtime/parrot/library/PCT.pbc [main] +runtime/parrot/library/PGE.pbc [main] runtime/parrot/library/PGE/Dumper.pbc [main] runtime/parrot/library/PGE/Glob.pbc [main] runtime/parrot/library/PGE/Hs.pbc [main] -runtime/parrot/library/PGE.pbc [main] runtime/parrot/library/PGE/Perl6Grammar.pbc [main] runtime/parrot/library/PGE/Text.pbc [main] runtime/parrot/library/PGE/Util.pbc [main] +runtime/parrot/library/Parrot/Capture_PIR.pbc [main] +runtime/parrot/library/Parrot/Coroutine.pbc [main] +runtime/parrot/library/Parrot/Exception.pbc [main] +runtime/parrot/library/Parrot/HLLCompiler.pbc [main] runtime/parrot/library/Protoobject.pbc [main] runtime/parrot/library/Range.pbc [main] runtime/parrot/library/Stream/Base.pbc [main] @@ -197,22 +189,34 @@ runtime/parrot/library/Stream/ParrotIO.pbc [main] runtime/parrot/library/Stream/Replay.pbc [main] runtime/parrot/library/Stream/Sub.pbc [main] runtime/parrot/library/Stream/Writer.pbc [main] +runtime/parrot/library/TGE.pbc [tge] runtime/parrot/library/Tcl/Glob.pbc [main] runtime/parrot/library/TclLibrary.pbc [main] +runtime/parrot/library/Test/Builder.pbc [main] +runtime/parrot/library/Test/Builder/Output.pbc [main] runtime/parrot/library/Test/Builder/Test.pbc [main] -runtime/parrot/library/Test/Builder/Tester.pbc [main] runtime/parrot/library/Test/Builder/TestPlan.pbc [main] -runtime/parrot/library/Test/Builder/Output.pbc [main] -runtime/parrot/library/Test/Builder.pbc [main] +runtime/parrot/library/Test/Builder/Tester.pbc [main] runtime/parrot/library/Test/Class.pbc [main] runtime/parrot/library/Test/More.pbc [main] -runtime/parrot/library/TGE.pbc [tge] -runtime/parrot/library/uuid.pbc [main] +runtime/parrot/library/YAML/Dumper.pbc [main] runtime/parrot/library/YAML/Dumper/Base.pmc [main] runtime/parrot/library/YAML/Dumper/Default.pmc [main] -runtime/parrot/library/YAML/Dumper.pbc [main] +runtime/parrot/library/config.pbc [main] +runtime/parrot/library/config.pir [main] +runtime/parrot/library/dumper.pbc [main] +runtime/parrot/library/libpcre.pbc [main] +runtime/parrot/library/ncurses.pbc [main] +runtime/parrot/library/parrotlib.pbc [main] +runtime/parrot/library/pcore.pbc [main] +runtime/parrot/library/pcre.pbc [main] +runtime/parrot/library/uuid.pbc [main] src/call_list.txt [devel]src +src/frame_builder_libjit.c [devel]src +src/frame_builder_libjit.h [devel]src src/glut_callbacks.c [] +src/install_config.o [main]lib +src/install_config.obj [main]lib src/jit_emit.h [] src/nci.c [] src/null_config.c [] diff --git a/config/auto/frames.pm b/config/auto/frames.pm index f6f7d67..519b44e 100644 --- a/config/auto/frames.pm +++ b/config/auto/frames.pm @@ -40,21 +40,13 @@ sub runstep { sub _call_frames_buildable { my $conf = shift; - - my $osname = $conf->data->get('osname'); - my $cpuarch = $conf->data->get('cpuarch'); - my $nvsize = $conf->data->get('nvsize'); my $can_build_call_frames; if (defined $conf->options->get('buildframes')) { $can_build_call_frames = $conf->options->get('buildframes'); } else { - # TT #1132 - # Temporary disable build frames automatically. - #$can_build_call_frames = ($nvsize == 8 && $cpuarch eq 'i386' - # && $osname ne 'darwin'); - $can_build_call_frames = 0; + $can_build_call_frames = $conf->data->get('HAS_LIBJIT'); } return $can_build_call_frames; } @@ -63,36 +55,13 @@ sub _handle_can_build_call_frames { my ($self, $conf, $can_build_call_frames) = @_; if ( $can_build_call_frames ) { $conf->data->set( - cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES', + cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES', + has_exec_protect => 1, ); - # test for executable malloced memory - my $osname = $conf->data->get( 'osname' ); - if ( -e "config/auto/frames/test_exec_${osname}_c.in" ) { - $conf->cc_gen("config/auto/frames/test_exec_${osname}_c.in"); - eval { $conf->cc_build(); }; - if ($@) { - $conf->data->set( has_exec_protect => 0 ); - } - else { - my $exec_protect_test = ( - $conf->cc_run(0) !~ /ok/ && $conf->cc_run(1) =~ /ok/ - ); - if ($exec_protect_test) { - $conf->data->set( has_exec_protect => 1 ); - } - else { - $conf->data->set( has_exec_protect => 0 ); - } - } - $conf->cc_clean(); - } - else { - $conf->data->set( has_exec_protect => 0 ); - } $self->set_result( 'yes' ); } else { - $conf->data->set( cc_build_call_frames => ''); + $conf->data->set(cc_build_call_frames => ''); $self->set_result( 'no' ); } return 1; diff --git a/config/auto/frames/test_exec_cygwin_c.in b/config/auto/frames/test_exec_cygwin_c.in deleted file mode 100644 index 4871d23..0000000 --- a/config/auto/frames/test_exec_cygwin_c.in +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright (C) 2008-2009, Parrot Foundation. -$Id$ - -test for exec privs -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef PAGE_SIZE -# define PAGE_SIZE getpagesize() -#endif -# - -/* - * c equiv: - int t() { - return 1; -} -*/ - -char code[] = { - 0xB8, 0x01, 0, 0, 0, /* movl $1, %eax */ - 0xC3 /* ret */ -}; - -typedef int (*pf)(void); - -int -main(int argc, char *argv[]) -{ - pf t; - char *p; - int rc; - int prot = PROT_READ; - - if (argc != 2) { - fprintf(stderr, "usage: test 0 | 1\n"); - exit(1); - } - - if (atoi(argv[1])) - prot |= PROT_EXEC; - - p = memalign(PAGE_SIZE, PAGE_SIZE); - memcpy(p, code, sizeof (code)); - - t = (pf) p; - rc = mprotect(p, PAGE_SIZE, prot); - - if (rc) { - fprintf(stderr, "p = %p PAGE_SIZE = %d (0x%x)\n", p, - PAGE_SIZE, PAGE_SIZE); - perror("failure"); - } - - if (t() == 1) - puts("ok"); - else - return 1; - - return 0; -} - -/* - * Local variables: - * c-file-style: "parrot" - * End: - * vim: expandtab shiftwidth=4: - */ diff --git a/config/auto/frames/test_exec_linux_c.in b/config/auto/frames/test_exec_linux_c.in deleted file mode 100644 index 0090134..0000000 --- a/config/auto/frames/test_exec_linux_c.in +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright (C) 2004-2009, Parrot Foundation. -$Id$ - -test for exec privs - */ - -#include -#include -#include -#include -#include -#include -#include -#ifndef PAGE_SIZE -# define PAGE_SIZE getpagesize() -#endif - -/* - * c equiv: - int t() { - return 1; -} -*/ - -char code[] = { - 0xB8, 0x01, 0, 0, 0, /* movl $1, %eax */ - 0xC3 /* ret */ -}; - -typedef int (*pf)(void); - -int -main(int argc, char *argv[]) -{ - pf t; - char *p; - int rc; - int prot = PROT_READ; - - if (argc != 2) { - fprintf(stderr, "usage: test 0 | 1\n"); - exit(1); - } - if (atoi(argv[1])) - prot |= PROT_EXEC; - - p = memalign(PAGE_SIZE, sizeof (code)); - memcpy(p, code, sizeof (code)); - t = (pf) p; - rc = mprotect(p, PAGE_SIZE, prot); - if (rc) { - fprintf(stderr, "p = %p PAGE_SIZE = %d (0x%x)\n", p, - PAGE_SIZE, PAGE_SIZE); - perror("failure"); - } - - if (t() == 1) - puts("ok"); - else - return 1; - - return 0; -} - -/* - * Local variables: - * c-file-style: "parrot" - * End: - * vim: expandtab shiftwidth=4: - */ diff --git a/config/auto/frames/test_exec_openbsd_c.in b/config/auto/frames/test_exec_openbsd_c.in deleted file mode 100644 index 7f1826f..0000000 --- a/config/auto/frames/test_exec_openbsd_c.in +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright (C) 2004-2009, Parrot Foundation. -$Id$ - -test for exec privs -*/ - -#include -#include -#include -#include -#include -#include -#include -#ifndef PAGE_SIZE -# define PAGE_SIZE sysconf(_SC_PAGESIZE) -#endif - -/* - * c equiv: - int t() { - return 1; -} -*/ - -char code[] = { - 0xB8, 0x01, 0, 0, 0, /* movl $1, %eax */ - 0xC3 /* ret */ -}; - -typedef int (*pf)(void); - -int -main(int argc, char *argv[]) -{ - pf t; - char *p; - int rc; - int prot = PROT_READ; - - if (argc != 2) { - fprintf(stderr, "usage: test 0 | 1\n"); - exit(1); - } - if (atoi(argv[1])) - prot |= PROT_EXEC; - - p = malloc(PAGE_SIZE); - memcpy(p, code, sizeof (code)); - t = (pf) p; - rc = mprotect(p, PAGE_SIZE, prot); - if (rc) { - fprintf(stderr, "p = %p PAGE_SIZE = %d (0x%x)\n", p, - PAGE_SIZE, PAGE_SIZE); - perror("failure"); - } - - if (t() == 1) - puts("ok"); - else - return 1; - - return 0; -} - -/* - * Local variables: - * c-file-style: "parrot" - * End: - * vim: expandtab shiftwidth=4: - */ diff --git a/config/auto/libjit.pm b/config/auto/libjit.pm new file mode 100644 index 0000000..868cb1e --- /dev/null +++ b/config/auto/libjit.pm @@ -0,0 +1,120 @@ +# Copyright (C) 2009, Parrot Foundation. +# $Id$ + +=head1 NAME + +config/auto/libjit - Check whether LibJIT is installed + +=head1 DESCRIPTION + +Determines whether libjit is present is installed and functional on the system. +It is OK when it doesn't exist. + +The libjit library implements just-in-time compilation functionality. Unlike +other JITs, this one is designed to be independent of any particular virtual +machine bytecode format or language. + +libjit can be obtained from L or through +your distribution's package manager. Developer documentation is available from +L + +=cut + +package auto::libjit; + +use strict; +use warnings; + +use base 'Parrot::Configure::Step'; + +use Parrot::Configure::Utils ':auto'; + +sub _init { + my $self = shift; + my %data = ( + description => 'Is LibJIT installed', + result => '', + ); + return \%data; +} + +sub runstep { + my ($self, $conf) = @_; + + my ($verbose, $without) = $conf->options->get( qw{ + verbose + without-libjit + }); + + my ($has_libjit, $extra_libs); + if ($without) { + $has_libjit = 0; + } + else { + $extra_libs = $self->_select_lib( { + conf => $conf, + osname => $conf->data->get_p5('OSNAME'), + cc => $conf->data->get('cc'), + win32_nongcc => 'libjit.lib', + default => '-ljit', + } ); + + $conf->cc_gen('config/auto/libjit/libjit_c.in'); + eval { $conf->cc_build('', $extra_libs) }; + if ($@) { + print "cc_build() failed: $@\n" if $verbose; + $has_libjit = 0; + } + else { + my $test; + eval { $test = $conf->cc_run(); }; + if ($@) { + print "cc_run() failed: $@\n" if $verbose; + $has_libjit = 0; + } + else { + $has_libjit = + $self->_evaluate_cc_run($test, $has_libjit, $verbose); + } + } + $conf->cc_clean(); + } + + $conf->data->set( HAS_LIBJIT => $has_libjit ); + _handle_has_libjit($conf, $has_libjit, $extra_libs); + $self->set_result( $has_libjit ? 'yes' : 'no' ); + + return 1; +} + +sub _evaluate_cc_run { + my ($self, $test, $has_libjit, $verbose) = @_; + if ($test =~ m/^USES INTERPRETER: \d+/ ) { + $has_libjit = 1; + print " (yes) " if $verbose; + $self->set_result("yes"); + } + return $has_libjit; +} + +sub _handle_has_libjit { + my ($conf, $has_libjit, $extra_libs) = @_; + if ($has_libjit) { + $conf->data->set( + 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; + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/config/auto/libjit/libjit_c.in b/config/auto/libjit/libjit_c.in new file mode 100644 index 0000000..6875b92 --- /dev/null +++ b/config/auto/libjit/libjit_c.in @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2009, Parrot Foundation. + * $Id$ + */ + +#include +#include +#include + +int +main(int argc, char *argv[]) { + jit_init(); + printf("USES INTERPRETER: %i\n", jit_uses_interpreter()); + return EXIT_SUCCESS; +} + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/config/gen/libjit.pm b/config/gen/libjit.pm new file mode 100644 index 0000000..cbe784a --- /dev/null +++ b/config/gen/libjit.pm @@ -0,0 +1,217 @@ +# Copyright (C) 2009, Parrot Foundation. +# $Id$ + +=head1 NAME + +config/gen/libjit.pm - LibJIT Code Generation + +=head1 DESCRIPTION + +Populate F and +F with system appropriate +type information and automatically generated parrot function and +vtable jit wrappers. + +=cut + +package gen::libjit; + +use strict; +use warnings; + +use base 'Parrot::Configure::Step'; + +use Parrot::Configure::Utils ':gen'; + + +sub _init { + my $self = shift; + my %data = ( + description => 'Generate LibJIT specific code', + result => '', + targets => { + frame_builder_h => 'src/frame_builder_libjit.h', + frame_builder_c => 'src/frame_builder_libjit.c', + }, + templates => { + frame_builder_h => 'config/gen/libjit/frame_builder_libjit_h.in', + frame_builder_c => 'config/gen/libjit/frame_builder_libjit_c.in', + }, + wrapped_vtables => { + get_integer => [ () => 'INTVAL' ], + set_integer_native => [ ('INTVAL') => 'void' ], + get_pointer => [ () => 'void_ptr' ], + set_pointer => [ ('void_ptr') => 'void' ], + }, + wrapped_funcs => { + get_nci_I => [ qw(void_ptr void_ptr sys_int) => 'INTVAL' ], + get_nci_N => [ qw(void_ptr void_ptr sys_int) => 'FLOATVAL' ], + get_nci_S => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ], + get_nci_P => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ], + get_nci_p => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ], + + set_nci_I => [ qw(void_ptr void_ptr INTVAL) => 'void' ], + set_nci_N => [ qw(void_ptr void_ptr FLOATVAL) => 'void' ], + set_nci_S => [ qw(void_ptr void_ptr void_ptr) => 'void' ], + set_nci_P => [ qw(void_ptr void_ptr void_ptr) => 'void' ], + + Parrot_str_new => + [ qw(void_ptr void_ptr UINTVAL) => 'void_ptr' ], + Parrot_str_to_cstring => + [ qw(void_ptr void_ptr) => 'void_ptr' ], + Parrot_str_free_cstring => + [ ('void_ptr') => 'void' ], + + 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; +} + +sub runstep { + my ($self, $conf) = @_; + + my ($libjit_iv, $libjit_uv) = @{ + my $iv = $conf->data->get('iv') || ''; + { + short => [ 'jit_type_sys_short' , 'jit_type_sys_ushort' ], + int => [ 'jit_type_sys_int' , 'jit_type_sys_uint' ], + long => [ 'jit_type_sys_long' , 'jit_type_sys_ulong' ], + 'long long' => [ 'jit_type_sys_longlong', 'jit_type_sys_ulonglong' ], + }->{$iv} + or die "Couldn't determine libjity type for intval of type '$iv'"; + }; + + my $libjit_nv = do { + my $nv = $conf->data->get('nv') || ''; + { + float => 'jit_type_sys_float', + double => 'jit_type_sys_double', + 'long double' => 'jit_type_sys_long_double', + }->{$nv} + or die "Couldn't determine libjity type for floatval of type '$nv'"; + }; + + $conf->data->set( libjit_iv => $libjit_iv, + libjit_uv => $libjit_uv, + libjit_nv => $libjit_nv, ); + + my @vtable_wrappers = + map {gen_vtable_wrapper($self, $_)} keys %{$self->{wrapped_vtables}}; + my @function_wrappers = + map {gen_function_wrapper($self, $_)} keys %{$self->{wrapped_funcs}}; + + $conf->data->set( + TEMP_vtable_wrap_decls => + (join "\n", map {$_->{decl}} @vtable_wrappers), + TEMP_vtable_wrap_defns => + (join "\n", map {$_->{defn}} @vtable_wrappers), + TEMP_func_wrap_decls => + (join "\n", map {$_->{decl}} @function_wrappers), + TEMP_func_wrap_defns => + (join "\n", map {$_->{defn}} @function_wrappers) + ); + + foreach my $t (keys %{$self->{targets}}) { + $conf->genfile($self->{templates}{$t}, $self->{targets}{$t}); + $conf->append_configure_log($t); + } + + return 1; +} + +sub gen_vtable_wrapper { + my ($self, $entry_name) = @_; + + my $entry_sig = $self->{wrapped_vtables}{$entry_name}; + $_ = jit_prefix_type($_) for @$entry_sig; + + my $ret_t = pop @$entry_sig; + my $arg_t = join ", ", @$entry_sig; + + my $n_args = scalar @$entry_sig; + my $arg_decls_t = join ", ", map {'jit_value_t'} 1..$n_args; + my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args; + my $arg_v = join ", ", map {"v$_"} 1..$n_args; + + my $_arg_decls_t = $n_args ? ", $arg_decls_t" : ""; + my $_arg_decls_v = $n_args ? ", $arg_decls_v" : ""; + my $_arg_t = $n_args ? ", $arg_t" : ""; + my $_arg_v = $n_args ? ", $arg_v" : ""; + + return { decl => < <{wrapped_funcs}{$func_name}; + $_ = jit_prefix_type($_) for @$func_sig; + + my $ret_t = pop @$func_sig; + my $arg_t = join ", ", @$func_sig; + + my $n_args = scalar @$func_sig; + my $arg_decls_t = join ", ", map {'jit_value_t'} 1..$n_args; + my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args; + my $arg_v = join ", ", map {"v$_"} 1..$n_args; + + return { decl => < < + +Public interface to NCI function interface builder. + +=cut + +*/ + +void * +Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc, STRING *sig, void **priv) { + void *thunk; + char *sig_cstr; + + sig_cstr = Parrot_str_to_cstring(interp, sig); + *priv = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); + + thunk = Parrot_jit_create_thunk(interp, sig_cstr, *priv); + + Parrot_str_free_cstring(sig_cstr); + + return thunk; +} + +/* + +=item C + +This is a callback to implement the proper freeing semantics. It is called by +the ManagedStruct PMC as it is garbage collected. + +=cut + +*/ + +void +Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv) +{ + struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; + jit_context_destroy(jit->ctx); + mem_sys_free(jit->sig); + mem_sys_free(priv); +} + +/* + +=item C + +This is a callback to implement the proper cloning semantics for jit buffers. +It is called by the ManagedStruct PMC's clone() function. + +=back + +=cut + +*/ + +PMC * +Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv) +{ + PMC * const rv = pmc_new(interp, pmc->vtable->base_type); + + VTABLE_init(interp, rv); + /* copy the attributes */ + { + void (*tmpfreefunc)(PARROT_INTERP, void*, void*); + GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc); + SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc); + } + { + PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*); + GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc); + SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc); + } + + /* compile a clone of the function */ + if (PARROT_MANAGEDSTRUCT(pmc)->ptr) { + void *rv_priv; + struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; + STRING *sig = Parrot_str_new(interp, jit->sig, 0); + PARROT_MANAGEDSTRUCT(rv)->ptr = Parrot_jit_build_call_func(interp, rv, sig, &rv_priv); + } + + return rv; +} + +/* + * JIT functions + */ + +void * +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_nci_pmc, jit_pcc_sig; + jit_value_t jit_func, jit_st; + + /* populate private data */ + p = (struct jit_buffer_private_data*)priv; + p->ctx = jit_context_create(); + p->sig = mem_sys_strdup(sig); + + /* start compiling */ + jit_context_build_start(p->ctx); + + /* start JIT function */ + { + jit_type_t arg_types[] = { + 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, 3, 1); + f = jit_function_create(p->ctx, f_sig); + } + + /* get the incomming args */ + 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 */ + { + int nargs = strlen(sig) - 1; + + jit_type_t jit_args_t[nargs]; + jit_value_t jit_args_v[nargs]; + jit_value_t jit_regs[nargs]; + + 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 */ + { + jit_type_t ret_t; + jit_value_t ret_v; + + ret_t = Parrot_jit_parse_sig_ret_pre(interp, sig); + + /* make the call */ + { + jit_type_t jit_sig + = jit_type_create_signature(jit_abi_cdecl, ret_t, jit_args_t, nargs, 1); + ret_v = jit_insn_call_indirect(f, jit_func, jit_sig, jit_args_v, nargs, 0); + } + + /* get the incomming return */ + 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); + + /* compile to native callable func poitner */ + jit_function_compile(f); + jit_context_build_end(p->ctx); + + return jit_function_to_closure(f); +} + +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 */ + + for (i = 0, j = 0; i < nargs; i++) { + char c; + jit_type_t t1; + jit_value_t v1, v2, v3, v4; + switch (c = sig[i]) { + 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; + break; + case 'c': + t1 = jit_type_sys_char; + goto read_int_reg; + case 's': + t1 = jit_type_sys_short; + goto read_int_reg; + case 'i': + t1 = jit_type_sys_int; + goto read_int_reg; + case 'l': + t1 = jit_type_sys_long; + goto read_int_reg; + + 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; + break; + case 'f': + t1 = jit_type_sys_float; + goto read_float_reg; + case 'd': + t1 = jit_type_sys_double; + 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; + 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); + 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); + 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); + jit_value_set_addressable(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; + 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; + break; + case '2': + t1 = jit_type_sys_short; + goto call_get_integer; + case '3': + t1 = jit_type_sys_int; + goto call_get_integer; + 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); + jit_value_set_addressable(v4); + jit_insn_store(f, v4, v3); + 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); + jit_value_set_addressable(v4); + jit_insn_store(f, v4, v3); + 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); + break; + + case 'J': + 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; + + default: + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, + "unkown arg type '%c'", c); + return; + } + } +} + +jit_type_t +Parrot_jit_parse_sig_ret_pre(PARROT_INTERP, char *sig) { + char c; + switch (c = sig[0]) { + case 'v': + return jit_type_void; + + case 'I': + return JIT_TYPE_INTVAL; + case 'c': + return jit_type_sys_char; + case 's': + return jit_type_sys_short; + case 'i': + return jit_type_sys_int; + case 'l': + return jit_type_sys_long; + + case 'N': + return JIT_TYPE_FLOATVAL; + case 'f': + return jit_type_sys_float; + case 'd': + return jit_type_sys_double; + + case 'S': + case 't': + return jit_type_void_ptr; + + case 'p': + case 'P': + return jit_type_void_ptr; + + case 'U': + /* TODO */ + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, + "return type 'U' not yet implemented"); + return NULL; + default: + /* FAIL */ + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, + "unknown return type '%c'", c); + return NULL; + } +} + +void +Parrot_jit_parse_sig_ret_post(PARROT_INTERP, char *sig, + jit_function_t f, jit_value_t jinterp, jit_value_t st, + jit_value_t retval) { + jit_type_t t1; + jit_value_t v1, v2, v3; + switch (sig[0]) { + case 'v': + break; + + case 'I': + case 'c': + case 's': + case 'i': + case 'l': + jit__set_nci_I(f, jinterp, st, retval); + break; + + case 'N': + case 'f': + case 'd': + jit__set_nci_N(f, jinterp, st, retval); + break; + + case 'S': + jit__set_nci_S(f, jinterp, st, retval); + break; + case 't': + v1 = jit_value_create_nint_constant(f, jit_type_sys_int, 0); + v2 = jit__Parrot_str_new(f, jinterp, retval, v1); + jit__set_nci_S(f, jinterp, st, v2); + break; + + case 'P': + jit__set_nci_P(f, jinterp, st, retval); + break; + case 'p': + v1 = jit_value_create_intval_constant(f, enum_class_UnManagedStruct); + v2 = jit__pmc_new_noinit(f, jinterp, v1); + jit__vtable_set_pointer(f, jinterp, v2, retval); + jit__set_nci_P(f, jinterp, st, v2); + break; + case '2': + t1 = jit_type_sys_short; + goto create_int_pmc; + case '3': + t1 = jit_type_sys_int; + goto create_int_pmc; + case '4': + t1 = jit_type_sys_long; + create_int_pmc: + v1 = jit_insn_load_relative(f, retval, 0, t1); + v2 = jit_value_create_intval_constant(f, enum_class_Integer); + v3 = jit__pmc_new_noinit(f, jinterp, v2); + jit__vtable_set_integer_native(f, jinterp, v3, v1); + jit__set_nci_P(f, jinterp, st, v3); + break; + + case 'U': + /* ignore (failed elsewhere) */ + break; + + default: + /* ignore (failed elsewhere) */ + break; + } +} + +void +Parrot_jit_parse_sig_args_post(PARROT_INTERP, char *sig, int nargs, + jit_function_t f, jit_value_t jinterp, + jit_value_t *args, jit_value_t *regs) { + int i, j; + + sig += 1; + + for (i = 0, j = 0; i < nargs; i++) { + jit_type_t t1; + jit_value_t v1; + switch (sig[i]) { + case 't': + jit__Parrot_str_free_cstring(f, args[i]); + j++; + break; + + case 'B': + v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr); + jit__Parrot_str_free_cstring(f, v1); + j++; + break; + + case '2': + t1 = jit_type_sys_short; + goto set_integer; + case '3': + t1 = jit_type_sys_int; + goto set_integer; + case '4': + t1 = jit_type_sys_long; + set_integer: + v1 = jit_insn_load_relative(f, args[i], 0, t1); + jit__vtable_set_integer_native(f, jinterp, regs[j], v1); + j++; + break; + + case 'V': + v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr); + jit__vtable_set_pointer(f, jinterp, regs[j], v1); + j++; + break; + + case 'I': + case 'c': + case 'i': + case 'l': + case 'N': + case 'f': + case 'd': + case 'S': + case 'b': + case 'p': + case 'P': + case 'O': + case '@': + j++; + break; + + case 'U': + /* TODO */ + break; + default: + /* ignore */ + break; + } + } +} + +jit_value_t +jit_value_create_intval_constant(jit_function_t f, INTVAL i) { + return jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, i); +} + +/* + * JIT wrappers + */ + +/* custom wrappers */ +jit_value_t +jit__Buffer_bufstart(jit_function_t f, jit_value_t buf) { + return jit_insn_load_relative(f, buf, offsetof(Buffer, _bufstart), jit_type_void_ptr); +} + +/* vtable wrappers */ +@TEMP_vtable_wrap_defns@ + +/* function wrappers */ +@TEMP_func_wrap_defns@ + +#endif /* PARROT_HAS_LIBJIT */ + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/config/gen/libjit/frame_builder_libjit_h.in b/config/gen/libjit/frame_builder_libjit_h.in new file mode 100644 index 0000000..ff22e2e --- /dev/null +++ b/config/gen/libjit/frame_builder_libjit_h.in @@ -0,0 +1,96 @@ +/* frame_builder_libjit.h + * $Id$ + * Copyright (C) 2009, Parrot Foundation. + */ + +#ifndef PARROT_FRAME_BUILDER_LIBJIT_H_GUARD +#define PARROT_FRAME_BUILDER_LIBJIT_H_GUARD + + +#if defined(__cplusplus) +# define EXTERN extern "C" +#else +# define EXTERN +#endif + +#include +#include "parrot/parrot.h" +#include "frame_builder.h" + +#ifdef PARROT_HAS_LIBJIT + +# include + +/* + * JITted function state data + */ +struct jit_buffer_private_data { + jit_context_t ctx; + char *sig; +}; + +/* + * JIT types + */ + +# define JIT_TYPE_UINTVAL @libjit_uv@ +# define JIT_TYPE_INTVAL @libjit_iv@ +# define JIT_TYPE_FLOATVAL @libjit_nv@ + +/* + * JIT functions + */ + +void * +Parrot_jit_create_thunk(Interp *, char *, void *); + +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 *); + +jit_type_t +Parrot_jit_parse_sig_ret_pre(Interp *, char *); + +void +Parrot_jit_parse_sig_ret_post(Interp *, char *, jit_function_t, jit_value_t, jit_value_t, jit_value_t); + +void +Parrot_jit_parse_sig_args_post(Interp *, char *, int, jit_function_t, jit_value_t, jit_value_t *, jit_value_t *); + +jit_value_t +jit_value_create_intval_constant(jit_function_t, INTVAL); + +/* + * 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 + */ + +/* custom wrappers */ +jit_value_t +jit__Buffer_bufstart(jit_function_t, jit_value_t); + +/* vtable wrappers */ +@TEMP_vtable_wrap_decls@ + +/* function wrappers */ +@TEMP_func_wrap_decls@ + +#endif /* PARROT_HAS_LIBJIT */ +#endif /* PARROT_FRAME_BUILDER_LIBJIT_H_GUARD */ + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in index cad4f1a..823709c 100644 --- a/config/gen/makefiles/root.in +++ b/config/gen/makefiles/root.in @@ -217,6 +217,8 @@ CONFIGURE_GENERATED_FILES := \ myconfig \ $(GEN_PASM_INCLUDES) \ $(SRC_DIR)/call_list.txt \ + $(SRC_DIR)/frame_builder_libjit.h \ + $(SRC_DIR)/frame_builder_libjit.c \ MANIFEST.configure.generated \ .configure_trace.sto \ .parrot_current_rev @@ -442,6 +444,7 @@ INTERP_O_FILES := \ $(SRC_DIR)/misc$(O) \ $(SRC_DIR)/multidispatch$(O) \ $(SRC_DIR)/frame_builder$(O) \ + $(SRC_DIR)/frame_builder_libjit$(O) \ $(SRC_DIR)/nci$(O) \ $(SRC_DIR)/oo$(O) \ $(SRC_DIR)/packfile$(O) \ @@ -625,6 +628,7 @@ STR_FILES := \ $(SRC_DIR)/library.str \ $(SRC_DIR)/multidispatch.str \ $(SRC_DIR)/frame_builder.str \ + $(SRC_DIR)/frame_builder_libjit.str \ $(SRC_DIR)/nci.str \ $(SRC_DIR)/packfile.str \ $(SRC_DIR)/pmc.str \ @@ -1201,12 +1205,23 @@ $(SRC_DIR)/exit$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/exit.c $(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str \ $(SRC_DIR)/frame_builder$(O) \ - $(SRC_DIR)/pmc/pmc_unmanagedstruct.h \ + $(SRC_DIR)/frame_builder_libjit$(O) \ $(SRC_DIR)/pmc/pmc_managedstruct.h \ $(SRC_DIR)/pmc/pmc_nci.h \ $(SRC_DIR)/pmc/pmc_pointer.h -$(SRC_DIR)/frame_builder$(O) : $(SRC_DIR)/frame_builder.h $(GENERAL_H_FILES) $(SRC_DIR)/frame_builder.c $(SRC_DIR)/frame_builder.str +$(SRC_DIR)/frame_builder$(O) : \ + $(SRC_DIR)/frame_builder.h \ + $(SRC_DIR)/frame_builder.c \ + $(SRC_DIR)/frame_builder.str \ + $(GENERAL_H_FILES) + +$(SRC_DIR)/frame_builder_libjit$(O) : \ + $(SRC_DIR)/frame_builder_libjit.h \ + $(SRC_DIR)/frame_builder_libjit.c \ + $(SRC_DIR)/frame_builder_libjit.str \ + $(SRC_DIR)/frame_builder.h \ + $(GENERAL_H_FILES) $(SRC_DIR)/vtables$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/vtables.c diff --git a/lib/Parrot/Configure/Options/Conf.pm b/lib/Parrot/Configure/Options/Conf.pm index 27ca853..497d3b9 100644 --- a/lib/Parrot/Configure/Options/Conf.pm +++ b/lib/Parrot/Configure/Options/Conf.pm @@ -105,6 +105,7 @@ External Library Options: --without-gmp Build parrot without GMP support --without-opengl Build parrot without OpenGL support (GL/GLU/GLUT) --without-pcre Build parrot without pcre support + --without-libjit Build parrot without LibJIT support ICU Options: diff --git a/lib/Parrot/Configure/Options/Conf/Shared.pm b/lib/Parrot/Configure/Options/Conf/Shared.pm index 729923e..f8dd3ea 100644 --- a/lib/Parrot/Configure/Options/Conf/Shared.pm +++ b/lib/Parrot/Configure/Options/Conf/Shared.pm @@ -75,6 +75,7 @@ our @shared_valid_options = qw{ without-gettext without-gmp without-icu + without-libjit without-opengl without-pcre without-threads diff --git a/lib/Parrot/Configure/Step/List.pm b/lib/Parrot/Configure/Step/List.pm index 0b2190a..1989254 100644 --- a/lib/Parrot/Configure/Step/List.pm +++ b/lib/Parrot/Configure/Step/List.pm @@ -39,6 +39,7 @@ my @steps = qw( auto::format auto::isreg auto::arch + auto::libjit auto::jit auto::frames auto::cpu @@ -70,11 +71,16 @@ my @steps = qw( gen::parrot_include gen::opengl gen::call_list + gen::libjit gen::makefiles gen::platform gen::config_pm ); +=pod + +=cut + sub get_steps_list { return @steps; } 1; diff --git a/lib/Parrot/Distribution.pm b/lib/Parrot/Distribution.pm index 9c668b9..7b48377 100644 --- a/lib/Parrot/Distribution.pm +++ b/lib/Parrot/Distribution.pm @@ -433,6 +433,8 @@ This is to exclude automatically generated C-language files Parrot might have. include/parrot/config.h include/parrot/has_header.h src/gc/malloc.c + src/frame_builder_libjit.h + src/frame_builder_libjit.c } unless @exemptions; my $path = -f $file ? $file : $file->path; diff --git a/src/frame_builder.c b/src/frame_builder.c index e123c36..1296ac9 100644 --- a/src/frame_builder.c +++ b/src/frame_builder.c @@ -7,607 +7,130 @@ $Id$ /* HEADERIZER STOP */ #include "parrot/parrot.h" -#include "pmc/pmc_fixedintegerarray.h" -#include "pmc/pmc_unmanagedstruct.h" -#include "pmc/pmc_managedstruct.h" #include "frame_builder.h" -/* - -=over 4 - -=item C - -This is a callback to implement the proper freeing semantics. It is called by -the ManagedStruct PMC as it is garbage collected. - -=cut - -*/ - -void -Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv) +INTVAL +get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n) { - const struct jit_buffer_private_data * const jit = (struct jit_buffer_private_data*)priv; - mem_free_executable(ptr, jit->size); - free(priv); -} + if (n >= st->src.n) + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + "too few arguments passed to NCI function"); -/* + Parrot_fetch_arg_nci(interp, st); -=item C - -This is a callback to implement the proper cloning semantics for jit buffers. -It is called by the ManagedStruct PMC's clone() function. + return UVal_int(st->val); +} -=back +FLOATVAL +get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n) +{ + if (n >= st->src.n) + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + "too few arguments passed to NCI function"); -=cut + Parrot_fetch_arg_nci(interp, st); -*/ + return UVal_num(st->val); +} -PMC * -Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv) +PARROT_WARN_UNUSED_RESULT +PARROT_CANNOT_RETURN_NULL +STRING* +get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n) { - PMC * const rv = pmc_new(interp, pmc->vtable->base_type); - - VTABLE_init(interp, rv); - /* copy the attributes */ - { - void (*tmpfreefunc)(PARROT_INTERP, void*, void*); - GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc); - SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc); - } - { - PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*); - GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc); - SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc); - } - - { - void *freepriv, *clonepriv; - GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv); - GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv); - if (freepriv) { - void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); - memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data)); - SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp); - if (clonepriv == freepriv) { - /* clonepriv is a copy of freepriv, make it a copy in the clone too. */ - SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp); - clonepriv = NULL; /* disable the clonepriv copying below */ - } - } - if (clonepriv) { - void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); - memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data)); - SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp); - } - } + /* TODO or act like below? */ + if (n >= st->src.n) + Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + "too few arguments passed to NCI function"); - /* copy the execmem buffer */ - if (PARROT_MANAGEDSTRUCT(pmc)->ptr) { - struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; - void *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr; - void *newptr = mem_alloc_executable(jit->size); - if (!newptr) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "Cannot allocate executable memory"); - memcpy(newptr, ptr, jit->size); - PARROT_MANAGEDSTRUCT(rv)->ptr = newptr; - } + Parrot_fetch_arg_nci(interp, st); - return rv; + return UVal_str(st->val); } - -int -emit_is8bit(long disp) +PARROT_WARN_UNUSED_RESULT +PARROT_CAN_RETURN_NULL +PMC* +get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n) { - return disp >= -128 && disp <= 127; + /* + * excessive args are passed as NULL + * used by e.g. MMD infix like __add + */ + if (n < st->src.n) { + PMC *value; + Parrot_fetch_arg_nci(interp, st); + value = UVal_pmc(st->val); + return PMC_IS_NULL(value) ? (PMC *)NULL : value; + } + else + return NULL; } -char * -emit_disp8_32(char *pc, int disp) +PARROT_WARN_UNUSED_RESULT +PARROT_CAN_RETURN_NULL +void* +get_nci_p(PARROT_INTERP, ARGMOD(call_state *st), int n) { - if (emit_is8bit(disp)) { - *(pc++) = (char)disp; - return pc; - } - else { - *(long *)pc = disp; - return pc + 4; - } + /* + * excessive args are passed as NULL + * used by e.g. MMD infix like __add + */ + if (n < st->src.n) { + PMC *value; + Parrot_fetch_arg_nci(interp, st); + value = UVal_pmc(st->val); + return PMC_IS_NULL(value) ? (PMC *)NULL : VTABLE_get_pointer(interp, value); + } + else + return NULL; } +/* + * set return value + */ void -emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base) -{ - int scale_byte; - - switch (scale) { - case 1: - scale_byte = emit_Scale_1; - break; - case 2: - scale_byte = emit_Scale_2; - break; - case 4: - scale_byte = emit_Scale_4; - break; - case 8: - scale_byte = emit_Scale_8; - break; - default: - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "Invalid scale factor %d\n", scale); - return; - } - - *pc = (char)(scale_byte | (i == emit_None ? emit_Index_None : emit_reg_Index(i)) | - emit_reg_Base(base)); -} - -char * -emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp) +set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val) { - if (i && !scale) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "emit_r_X passed invalid scale+index combo\n"); - - if (base == emit_EBP) { - /* modrm disp */ - if (i == emit_None) { - *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10) - | reg_opcode | emit_reg_rm(emit_EBP)); - return emit_disp8_32(pc, disp); - } - /* modrm sib disp */ - else { - *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10) - | reg_opcode | emit_b100); - emit_sib(interp, pc++, scale, i, base); - return emit_disp8_32(pc, disp); - } - } - - /* modrm sib disp */ - if (base == emit_ESP) { - *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10) - | reg_opcode | emit_rm_b100); - emit_sib(interp, pc++, scale, i, emit_ESP); - return emit_disp8_32(pc, disp); - } - - /* modrm disp32 */ - if (!base && !(i && scale)) { - *(pc++) = (char)(emit_Mod_b00 | reg_opcode | emit_rm_b101); - *(long *)pc = disp; - return pc + 4; + Parrot_init_ret_nci(interp, st, "I"); + if (st->dest.i < st->dest.n) { + UVal_int(st->val) = val; + Parrot_convert_arg(interp, st); + Parrot_store_arg(interp, st); } - - /* Ok, everything should be more regular here */ - *(pc++) = (char)((disp == 0 ? emit_Mod_b00 : - (emit_is8bit(disp) ? - emit_Mod_b01 : emit_Mod_b10)) | - reg_opcode | - (!base || (scale && i) ? emit_rm_b100 : emit_reg_rm(base))); - - if (!base || (scale && i)) { - emit_sib(interp, pc++, scale, i, base); - } - if (disp) - pc = emit_disp8_32(pc, disp); - - return pc; } -char * -emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg) +void +set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val) { - if (opcode == emit_b000 && imm < 0) { - opcode = emit_b001; /* -rol => 32 + ror */ - imm = -imm; - } - - if (imm == 0) { - /* noop */ + Parrot_init_ret_nci(interp, st, "N"); + if (st->dest.i < st->dest.n) { + UVal_num(st->val) = val; + Parrot_convert_arg(interp, st); + Parrot_store_arg(interp, st); } - else if (imm == 1) { - *(pc++) = (char) 0xd1; - *(pc++) = (char) emit_alu_X_r(opcode, reg); - } - else if (imm > 1 && imm < 33) { - *(pc++) = (char) 0xc1; - *(pc++) = (char) emit_alu_X_r(opcode, reg); - *(pc++) = (char)imm; - } - else { - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "emit_shift_i_r passed invalid shift\n"); - } - - return pc; -} - -char * -emit_popl_r(char *pc, int reg) -{ - *(pc++) = (char)(0x58 | (reg - 1)); - return pc; } -unsigned char *lastpc; - -size_t -calc_signature_needs(const char *sig, int *strings) +void +set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val) { - size_t stack_size = 0; - while (*sig) { - switch (*sig) { - case 't': - (*strings)++; - stack_size +=4; - break; - case 'd': - stack_size +=8; - break; - default: - stack_size +=4; - break; - } - sig++; + Parrot_init_ret_nci(interp, st, "S"); + if (st->dest.i < st->dest.n) { + UVal_str(st->val) = val; + Parrot_convert_arg(interp, st); + Parrot_store_arg(interp, st); } - return stack_size; - } -/* - * The function generated here is called as func(interp, nci_info) - * interp ... 8(%ebp) - * nci_info ... 12(%ebp) - * - * The generate function for a specific signature looks quite similar to - * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles - * just compare the disassembly. - * - * If a non-NULL sizeptr is passed, the integer it points to will be written - * with the size of the allocated execmem buffer. - */ - -void * -Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr) +void +set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val) { - char *pc; - char *execmem; - int i = 0; - int arg_count = 0; - int string_buffer_count = 0; - const int ST_SIZE_OF = 124; - const int JIT_ALLOC_SIZE = 1024; - - char *signature_str = Parrot_str_to_cstring(interp, signature); - /* skip over the result */ - char *sig = signature_str + 1; - size_t stack_space_needed = calc_signature_needs(sig, - &string_buffer_count); - - int base_offset = 0; - int strings_offset = base_offset - (sizeof (char *) * string_buffer_count); - int st_offset = strings_offset - ST_SIZE_OF; - int args_offset = st_offset - stack_space_needed; - int temp_calls_offset = args_offset - 16; - int total_stack_needed = -temp_calls_offset; - - /* - * ESP - * 0-15, 16 bytes for utility calls - * stack_space_needed for actual NCI call - * st - * STRINGS -> char * holding space - * EBP - */ - - /* this ought to be enough - the caller of this function - * should free the function pointer returned here - */ - pc = execmem = (char *)mem_alloc_executable(JIT_ALLOC_SIZE); - if (! pc) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "Cannot allocate executable memory"); - - - /* this generated jit function will be called as (INTERP (EBP 8), func_ptr - * (ESP 12), args signature (ESP 16)) */ - - /* make stack frame, preserve %ebx */ - jit_emit_stack_frame_enter(pc); - - emitm_subl_i_r(pc, total_stack_needed, emit_ESP); - - /* Parrot_init_arg_nci(interp, &st, "S"); */ - /* args signature "S" */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - - /*&st*/ - emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - - /*interpreter*/ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); - - /* XXX FIXME This whole function require major rework */ - /* XXX FIXME if (sig && *sig) */ - /* XXX FIXME emitm_call_cfunc(pc, Parrot_init_arg_nci); */ - - while (*sig) { - emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8); - - switch (*sig) { - case '0': /* null ptr or such - doesn't consume a reg */ - jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX); - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'f': - /* FIXME emitm_call_cfunc(pc, get_nci_N); */ - emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset); - break; - case 'N': - case 'd': - /* FIXME emitm_call_cfunc(pc, get_nci_N); */ - emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset); - args_offset += 4; - break; - case 'I': /* INTVAL */ - case 'l': /* long */ - case 'i': /* int */ - /* FIXME emitm_call_cfunc(pc, get_nci_I); */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 't': /* string, pass a cstring */ - /* FIXME emitm_call_cfunc(pc, get_nci_S); */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - emitm_call_cfunc(pc, string_to_cstring_nullable); - - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - /* save off temporary allocation address */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset); - strings_offset += 4; - - /* reset ESP(4) */ - emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - break; - case 's': /* short: movswl intreg_o(base), %eax */ - /* FIXME emitm_call_cfunc(pc, get_nci_I); */ - emitm_movswl_r_r(pc, emit_EAX, emit_EAX); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'c': /* char: movsbl intreg_o(base), %eax */ - /* emitm_call_cfunc(pc, get_nci_I); */ - emitm_movsbl_r_r(pc, emit_EAX, emit_EAX); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'J': /* interpreter */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - arg_count--; - break; - case 'p': /* push pmc->data */ - /* FIXME emitm_call_cfunc(pc, get_nci_p); */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'O': /* push PMC * object in P2 */ - case 'P': /* push PMC * */ - case '@': - /* FIXME emitm_call_cfunc(pc, get_nci_P); */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'v': - break; - case 'b': /* buffer (void*) pass Buffer_bufstart(SReg) */ - /* FIXME emitm_call_cfunc(pc, get_nci_S); */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, - (size_t) &Buffer_bufstart((STRING *) NULL)); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */ - /* FIXME emitm_call_cfunc(pc, get_nci_S); */ - emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, - (size_t) &Buffer_bufstart((STRING *) NULL)); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - case 'S': - /* FIXME emitm_call_cfunc(pc, get_nci_S); */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); - break; - - - /* I have no idea how to handle these */ - case '2': - case '3': - case '4': - case 'V': - mem_free_executable(execmem, JIT_ALLOC_SIZE); - Parrot_str_free_cstring(signature_str); - return NULL; - break; - default: - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "Unknown arg Signature %c\n", *sig); - /* - * oops unknown signature: - * cleanup and try nci.c - */ - mem_free_executable(execmem, JIT_ALLOC_SIZE); - Parrot_str_free_cstring(signature_str); - return NULL; - } - args_offset +=4; - arg_count++; - sig++; + Parrot_init_ret_nci(interp, st, "P"); + if (st->dest.i < st->dest.n) { + UVal_pmc(st->val) = val; + Parrot_convert_arg(interp, st); + Parrot_store_arg(interp, st); } - - /* prepare to call VTABLE_get_pointer, set up args */ - /* interpreter - movl 8(%ebp), %eax */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); - - /* pmc - movl 12(%ebp), %eax */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - - /* get the get_pointer() pointer from the pmc's vtable */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(PMC, vtable)); - emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(VTABLE, get_pointer)); - - /* call get_pointer(), result goes into eax */ - emitm_callr(pc, emit_EAX); - emitm_addl_i_r(pc, 16, emit_ESP); - - /* call the resulting function pointer */ - emitm_callr(pc, emit_EAX); - emitm_subl_i_r(pc, 16, emit_ESP); - - /* SAVE OFF EAX */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - - /*&st*/ - emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - - /*interpreter*/ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); - - /* RESTORE BACK EAX */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - - /* now place return value in registers */ - /* first in signature is the return value */ - sig = signature_str; /* the result */ - switch (*sig) { - /* I have no idea how to handle these */ - case '2': - case '3': - case '4': - /* get integer from pointer - untested */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0); - if (*sig == 2) /* short */ - emitm_movswl_r_r(pc, emit_EAX, emit_EAX); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_I);*/ - break; - case 'f': - case 'd': - jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_N); */ - /* pop num from st(0) and mov to reg */ - break; - case 's': - /* movswl %ax, %eax */ - emitm_movswl_r_r(pc, emit_EAX, emit_EAX); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_I); */ - break; - case 'c': - /* movsbl %al, %eax */ - emitm_movsbl_r_r(pc, emit_EAX, emit_EAX); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_I); */ - break; - case 'I': /* INTVAL */ - case 'l': - case 'i': - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_I); */ - break; - case 'v': /* void - do nothing */ - break; - case 'P': - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_P); */ - break; - case 'p': /* make a new unmanaged struct */ - /* save return value on stack */ - - /* save pointer p */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12); - - /* make new pmc */ - emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4); - emitm_call_cfunc(pc, pmc_new); - - /* restore pointer p to EDX */ - emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12); - - /* copy UnManagedStruct to stack for set_nci_P call */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - - /* eax = PMC, get return value into edx */ - /* mov data(%eax), %eax - mov %edx, ptr(%eax) */ - emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data)); - emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, - offsetof(struct Parrot_UnManagedStruct_attributes, ptr)); - - /* reset EBP(4) */ - emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - - /* XXX FIXME emitm_call_cfunc(pc, set_nci_P); */ - break; - case 'S': - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - /* XXX FIXME emitm_call_cfunc(pc, set_nci_S); */ - break; - case 't': /* string */ - /* EAX is char* */ - emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */ - - /* overwrites address of st in EBP(4) */ - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - - emitm_call_cfunc(pc, Parrot_str_new); - - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); - - /* reset EBP(4) */ - emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); - emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); - - /* XXX FIXME emitm_call_cfunc(pc, set_nci_S); */ - break; - default: - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, - "Unknown return Signature %c\n", *sig); - /* - * oops unknown signature: - * cleanup and try nci.c - */ - Parrot_str_free_cstring(signature_str); - mem_free_executable(execmem, JIT_ALLOC_SIZE); - return NULL; - } - - /* free temporary strings */ - strings_offset = st_offset + ST_SIZE_OF; - for (i=0; i #include "parrot/parrot.h" -#include "parrot/hash.h" -#include "parrot/oplib/ops.h" /* * NCI interface */ + void * -Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *); +Parrot_jit_build_call_func(Interp *, PMC *, STRING *, void **); /* custom pmc callback functions */ void @@ -37,1328 +32,11 @@ Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv); PMC* Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv); -struct jit_buffer_private_data { - int size; -}; - -/* Scale factor values */ -#define emit_Scale(scale) ((scale) << 6) -#define emit_Scale_1 emit_Scale(0) -#define emit_Scale_2 emit_Scale(1) -#define emit_Scale_4 emit_Scale(2) -#define emit_Scale_8 emit_Scale(3) - -/* ESIB byte */ -#define emit_reg_Index(x) (((x)-1) << 3) -#define emit_reg_Base(x) ((x)-1) -#define emit_Index_None ((emit_b100) << 3) - /* * helper funcs - get argument n */ -/* - * if we have a delegated method like typeof_i_p, that returns an INTVAL - * and that is all in a sequence of JITted opcodes, and when these INTVAL - * is MAPped, we got a problem. So the EXT_CALL flag is disabled - mapped - * registers are saved/restored around vtable calls. - */ -#define JIT_VTABLE_OPS 1 - -/* EXEC_SHARED generates code to be used with libparrot.so - * It grabs the real address of cgp_core from the gcc generated code - * x/1i cgp_code - * jmp *0xXXXX - * x/1wx 0xXXXX - * real address of cpg_core - * s. exec_emit_end - * XXX This should be a command line option. - */ -#undef EXEC_SHARED - -extern UINTVAL ld(UINTVAL); - -#define NEG_MINUS_ZERO -/* #define NEG_ZERO_SUB */ - -/* Register codes */ -#define emit_None 0 - -/* These are + 1 the real values */ -#define emit_EAX 1 -#define emit_ECX 2 -#define emit_EDX 3 -#define emit_EBX 4 -#define emit_ESP 5 -#define emit_EBP 6 -#define emit_ESI 7 -#define emit_EDI 8 - -/* Scratch register. */ - -#define ISR1 emit_EAX -#define FSR1 0 - -#define emit_b00 0 -#define emit_b01 1 -#define emit_b10 2 -#define emit_b11 3 - -#define emit_b000 0 -#define emit_b001 1 -#define emit_b010 2 -#define emit_b011 3 -#define emit_b100 4 -#define emit_b101 5 -#define emit_b110 6 -#define emit_b111 7 - -/* Mod R/M byte */ -#define emit_reg(x) ((x) << 3) -#define emit_Mod(Mod) ((Mod) << 6) -#define emit_reg_rm(x) ((x)-1) - -/* Mod values for Mod R/M Byte */ -#define emit_Mod_b00 emit_Mod(emit_b00) -#define emit_Mod_b01 emit_Mod(emit_b01) -#define emit_Mod_b10 emit_Mod(emit_b10) - -/* special R/M values */ -#define emit_rm_b101 emit_b101 -#define emit_rm_b100 emit_b100 - -#define emit_r_m(interp, pc, reg1, b, i, s, d) \ - emit_r_X((interp), (pc), emit_reg((reg1)-1), (b), (i), (s), (d)) - -#define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1)) - -#define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2)) - -int emit_is8bit(long disp); - -char * emit_disp8_32(char *pc, int disp); - -void emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base); - -char * emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, - int scale, long disp); - -char * emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg); - -char * emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm, - int base, int i, int scale, long disp); - -char * emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2); - -char * emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg, - int base, int i, int scale, long disp); - -/* CDQ - need this to do multiply */ -#define emitm_cdq(pc) *((pc)++) = (char) 0x99 - -/* RET */ -#define emitm_ret(pc) *((pc)++) = (char) 0xc3 - -/* NOP */ -#define emit_nop(pc) *((pc)++) = (char) 0x90 - -/* PUSHes */ - -#define emitm_pushl_r(pc, reg) \ - *((pc)++) = (char) 0x50 | ((reg) - 1) - -#define emitm_pushl_i(pc, imm) { \ - *((pc)++) = (char) 0x68; \ - *(long *)(pc) = (long)(imm); \ - (pc) += 4; } - -#define emitm_pushl_m(pc, mem) { \ - *((pc)++) = (char) 0xff; \ - *((pc)++) = (char) 0x35; \ - *(long *)(pc) = (long)(mem); \ - (pc) += 4; } - -char * emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale, - long disp); - -/* POPs */ - -char * emit_popl_r(char *pc, int reg); - -# define emitm_popl_r(pc, reg) \ - (pc) = emit_popl_r((pc), (reg)) - -char * emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale, - long disp); - -/* MOVes */ - -char * emit_movb_r_r(char *pc, int reg1, int reg2); - -# define jit_emit_mov_rr_i(pc, reg2, reg1) if ((reg1) != (reg2)) { \ - *((pc)++) = (char) 0x89; \ - *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); } - -# define jit_emit_mov_ri_i(interp, pc, reg, imm) { \ - *((pc)++) = (char)(0xb8 | ((reg) - 1)); \ - *(long *)(pc) = (long)(imm); (pc) += 4; } - -# define emitm_movX_Y_Z(interp, op, pc, reg1, b, i, s, d) { \ - *((pc)++) = (char) (op); \ - (pc) = emit_r_m((interp), (pc), (reg1), (b), (i), (s), (long)(d)); } - -# define emitm_movb_r_m(interp, pc, reg1, b, i, s, d) \ - emitm_movX_Y_Z((interp), 0x88, (pc), (reg1), (b), (i), (s), (d)) - -# define emitm_movl_r_m(interp, pc, reg1, b, i, s, d) \ - emitm_movX_Y_Z((interp), 0x89, (pc), (reg1), (b), (i), (s), (d)) - -/* move byte/word with sign extension */ -# define emitm_movsbl_r_m(interp, pc, reg1, b, i, s, d) { \ - *((pc)++) = (char) 0x0f; \ - emitm_movX_Y_Z((interp), 0xBE, (pc), (reg1), (b), (i), (s), (d)); \ -} - -# define emitm_movswl_r_m(interp, pc, reg1, b, i, s, d) { \ - *((pc)++) = (char) 0x0f; \ - emitm_movX_Y_Z((interp), 0xBF, (pc), (reg1), (b), (i), (s), (d)); \ -} - -# define emitm_movsbl_r_r(pc, reg1, reg2) { \ - *((pc)++) = (char) 0x0f; \ - *((pc)++) = (char) 0xbe; \ - *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \ -} - -# define emitm_movswl_r_r(pc, reg1, reg2) { \ - *((pc)++) = (char) 0x0f; \ - *((pc)++) = (char) 0xbf; \ - *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \ -} - -# define emitm_movb_m_r(interp, pc, reg1, b, i, s, d) \ - emitm_movX_Y_Z((interp), 0x8a, (pc), (reg1), (b), (i), (s), (d)) - -# define emitm_movl_m_r(interp, pc, reg1, b, i, s, d) \ - emitm_movX_Y_Z((interp), 0x8b, (pc), (reg1), (b), (i), (s), (d)) - -# define emitm_lea_m_r(interp, pc, reg1, b, i, s, d) \ - emitm_movX_Y_Z((interp), 0x8d, (pc), (reg1), (b), (i), (s), (d)) - -char * emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i, - int scale, long disp); - -# define emitm_movl_i_m(pc, imm, b, i, s, d) { \ - *((pc)++) = (char) 0xc7; \ - (pc) = emit_r_X((interp), (pc), emit_reg(emit_b000), (b), (i), (s), (long)(d)); \ - *(long *)(pc) = (long)(imm); (pc) += 4; } - -/* Various ALU formats */ - -# define emitm_alul_r_r(pc, op, reg1, reg2) { \ - *((pc)++) = (char) (op); *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); } - -# define emitm_alub_i_r(pc, op1, op2, imm, reg) { \ - *((pc)++) = (char) (op1); *((pc)++) = (char) emit_alu_X_r((op2), (reg)); *((pc)++) = (char)(imm); } - -# define emitm_alul_i_r(pc, op1, op2, imm, reg) { \ - *((pc)++) = (char) (op1); \ - *((pc)++) = (char) emit_alu_X_r((op2), (reg)); \ - *(long *)((pc)) = (long)(imm); (pc) += 4; } - -# define emitm_alul_i_m(pc, op1, op2, imm, b, i, s, d) { \ - *((pc)++) = (char) (op1); \ - (pc) = emit_r_X((interp), (pc), emit_reg(op2), (b), (i), (s), (d)); \ - *(long *)(pc) = (long)(imm); (pc) += 4; } - -# define emitm_alul_r_m(pc, op, reg, b, i, s, d) { \ - *((pc)++) = (char) (op); \ - (pc) = emit_r_X((interp), (pc), emit_reg((reg)-1), (b), (i), (s), (long)(d)); } - -/* ADDs */ - -# define emitm_addb_r_r(pc, reg1, reg2) \ - emitm_alul_r_r((pc), 0x00, (reg1), (reg2)) - -# define emitm_addb_i_r(pc, imm, reg) \ - emitm_alub_i_r((pc), 0x83, emit_b000, (imm), (reg)) - -# define jit_emit_add_rr_i(interp, pc, reg1, reg2) \ - emitm_alul_r_r((pc), 0x01, (reg2), (reg1)) - -# define jit_emit_add_ri_i(interp, pc, reg, imm) \ - emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg)) - -# define emitm_addl_i_r(pc, imm, reg) \ - emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg)) - -# define emitm_addl_i_m(pc, imm, b, i, s, d) \ - emitm_alul_i_m((pc), 0x81, emit_b000, (imm), (b), (i), (s), (d)) - -# define emitm_addl_r_m(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x01, (reg), (b), (i), (s), (d)) - -# define emitm_addl_m_r(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x03, (reg), (b), (i), (s), (d)) - -/* SUBs */ - -# define jit_emit_sub_rr_i(interp, pc, reg1, reg2) \ - emitm_alul_r_r((pc), 0x29, (reg2), (reg1)) - -# define emitm_subl_i_r(pc, imm, reg) \ - emitm_alul_i_r((pc), 0x81, emit_b101, (imm), (reg)) - -# define jit_emit_sub_ri_i(interp, pc, r, i) emitm_subl_i_r((pc), (i), (r)) - -# define emitm_subl_r_m(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x29, (reg), (b), (i), (s), (d)) - -# define emitm_subl_m_r(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x2b, (reg), (b), (i), (s), (d)) - -# define emitm_subl_i_m(pc, imm, b, i, s, d) \ - emitm_alul_i_m((pc), 0x81, emit_b101, (imm), (b), (i), (s), (d)) - -/* These are used by both signed and unsigned EDIV, but only unsigned MUL */ -# define emitm_alu_imp_r(pc, op, reg) { \ - *((pc)++) = (char) 0xf7; \ - *((pc)++) = (char) emit_alu_X_r((op), (reg)); } - -# define emitm_alu_imp_m(pc, op, b, i, s, d) { \ - *((pc)++) = (char) 0xf7; \ - (pc) = emit_r_X((interp), (pc), emit_reg(op), (b), (i), (s), (d)); } - -/* Unsigned MUL and EDIV */ -/* EAX implicit destination in multiply and divide */ - -# define emitm_umull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b100, (reg2)) - -# define emitm_udivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b110, (reg2)) - -# define emitm_umull_m(pc, b, i, s, d) \ - emitm_alu_imp_m((pc), emit_b100, (b), (i), (s), (d)) - -# define emitm_udivl_m(pc, b, i, s, d) \ - emitm_alu_imp_m((pc), emit_b110, (b), (i), (s), (d)) - -/* Signed MUL and EDIV */ - -# define emitm_sdivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b111, (reg2)) - -# define emitm_sdivl_m(pc, b, i, s, d) \ - emitm_alu_imp_m((pc), emit_b111, (b), (i), (s), (d)) - -# define jit_emit_cdq(pc) *(pc)++ = 0x99 - -/* TEST for zero */ -# define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r((pc), 0x85, (reg1), (reg1)) - -# define emitm_smull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b101, (reg2)) - -# define jit_emit_mul_rr_i(interp, pc, reg1, reg2) { \ - *(pc)++ = 0xf; \ - emitm_alul_r_r((pc), 0xaf, (reg1), (reg2)); } - -# define emitm_smull_r_m(pc, reg1, b, i, s, d) { \ - *(pc)++ = 0xf; \ - emitm_alul_r_m((pc), 0xaf, (reg1), (b), (i), (s), (d)); } - -char * opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src); - -# define jit_emit_mul_rir_i(pc, dest, imm, src) \ - (pc) = opt_mul(interp, (pc), (dest), (imm), (src)) - - -# define jit_emit_mul_ri_i(pc, r, imm) jit_emit_mul_rir_i((pc), (r), (imm), (r)) - -# define jit_emit_mul_RIM_ii(pc, reg, imm, ofs) \ - emitm_alul_r_m((pc), 0x69, (reg), emit_EBX, emit_None, 1, (ofs)); \ - *(long *)(pc) = (long)(imm); \ - (pc) += 4; - -/* NEG */ - -# define jit_emit_neg_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b011, (reg)) - -# define emitm_negl_m(pc, b, i, s, d) \ - emitm_alu_imp_m((pc), emit_b011, (b), (i), (s), (d)) - -/* AND */ - -# define emit_andl_r_r(pc, reg1, reg2) emitm_alul_r_r((pc), 0x21, (reg1), (reg2)) -# define jit_emit_band_rr_i(interp, pc, r1, r2) emit_andl_r_r((pc), (r2), (r1)) - -# define jit_emit_band_ri_i(interp, pc, reg, imm) \ - emitm_alul_i_r((pc), 0x81, emit_b100, (imm), (reg)) - -# define emitm_andl_r_m(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x21, (reg), (b), (i), (s), (d)) - -# define emitm_andl_m_r(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x23, (reg), (b), (i), (s), (d)) - -# define emitm_andl_i_m(pc, imm, b, i, s, d) \ - emitm_alul_i_m((pc), 0x81, emit_b100, (imm), (b), (i), (s), (d)) - -/* TEST op */ -# define jit_emit_test_rr_i(pc, r1, r2) emitm_alul_r_r((pc), 0x85, (r1), (r2)) - -# define jit_emit_test_ri_i(pc, r, im) \ - emitm_alul_i_r((pc), 0xF7, emit_b000, (im), (r)) - -# define jit_emit_test_RM_i(pc, r, offs) \ - emitm_alul_r_m((pc), 0x85, (r), emit_EBX, 0, 1, (offs)) - -/* OR */ - -# define jit_emit_bor_rr_i(interp, pc, reg1, reg2) emitm_alul_r_r((pc), 0x9, (reg2), (reg1)) - -# define jit_emit_bor_ri_i(interp, pc, reg, imm) \ - emitm_alul_i_r((pc), 0x81, emit_b001, (imm), (reg)) - -# define emitm_orl_r_m(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x09, (reg), (b), (i), (s), (d)) - -# define emitm_orl_m_r(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x0b, (reg), (b), (i), (s), (d)) - -# define emitm_orl_i_m(pc, imm, b, i, s, d) \ - emitm_alul_i_m((pc), 0x81, emit_b001, (imm), (b), (i), (s), (d)) - -/* XOR */ - -# define jit_emit_bxor_rr_i(interp, pc, reg1, reg2) \ - emitm_alul_r_r((pc), 0x31, (reg2), (reg1)) - -# define jit_emit_bxor_ri_i(intepr, pc, reg, imm) \ - emitm_alul_i_r((pc), 0x81, emit_b110, (imm), (reg)) - -# define emitm_xorl_r_m(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x31, (reg), (b), (i), (s), (d)) - -# define emitm_xorl_m_r(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x33, (reg), (b), (i), (s), (d)) - -# define emitm_xorl_i_m(pc, imm, b, i, s, d) \ - emitm_alul_i_m((pc), 0x81, emit_b110, (imm), (b), (i), (s), (d)) - -/* NOT */ - -# define jit_emit_not_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b010, (reg)) -# define emitm_notl_m(pc, b, i, s, d) \ - emitm_alu_imp_m((pc), emit_b010, (b), (i), (s), (d)) - -# define jit_emit_not_M_i(interp, pc, offs) emitm_notl_m((pc), emit_EBX, 0, 1, (offs)) - -/* XCHG */ -# define jit_emit_xchg_rr_i(interp, pc, r1, r2) { \ - if ((r1) != (r2)) { \ - *((pc)++) = (char) 0x87; \ - *((pc)++) = (char) emit_alu_r_r((r1), (r2)); \ - } \ -} - -# define jit_emit_xchg_rm_i(pc, r, m) { \ - emitm_alul_r_m((pc), 0x87, (r), emit_None, emit_None, emit_None, (m)) \ -} -# define jit_emit_xchg_RM_i(interp, pc, r, offs) { \ - emitm_alul_r_m((pc), 0x87, (r), emit_EBX, emit_None, 1, (offs)) \ -} -# define jit_emit_xchg_MR_i(interp, pc, offs, r) jit_emit_xchg_RM_i((interp), (pc), (r), (offs)) - -/* SHL */ - -# define jit_emit_shl_ri_i(interp, pc, reg, imm) \ - { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); } - -# define emitm_shll_i_m(pc, imm, b, i, s, d) \ - { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); } - -# define emitm_shll_r_r(interp, pc, reg1, reg2) \ - { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); } - -# define emitm_shll_r_m(pc, reg, b, i, s, d) \ - { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); } - -/* SHR */ - -# define jit_emit_lsr_ri_i(interp, pc, reg, imm) \ - { (pc) = emit_shift_i_r((interp), (pc), emit_b101, (imm), (reg)); } - -# define emitm_shrl_i_m(pc, imm, b, i, s, d) \ - { (pc) = emit_shift_i_m((pc), emit_b101, (imm), (b), (i), (s), (d)); } - -# define emitm_shrl_r_r(interp, pc, reg1, reg2) \ - { (pc) = emit_shift_r_r((interp), (pc), emit_b101, (reg1), (reg2)); } - -# define emitm_shrl_r_m(pc, reg, b, i, s, d) \ - { (pc) = emit_shift_r_m((pc), emit_b101, (reg), (b), (i), (s), (d)); } - -/* SAL */ - -# define emitm_sall_i_r(interp, pc, imm, reg) \ - { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); } - -# define emitm_sall_i_m(pc, imm, b, i, s, d) \ - { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); } - -# define emitm_sall_r_r(interp, pc, reg1, reg2) \ - { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); } - -# define emitm_sall_r_m(pc, reg, b, i, s, d) \ - { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); } - -/* SAR */ - -# define jit_emit_shr_ri_i(interp, pc, reg, imm) \ - { (pc) = emit_shift_i_r((interp), (pc), emit_b111, (imm), (reg)); } - - -# define emitm_sarl_i_m(pc, imm, b, i, s, d) \ - { (pc) = emit_shift_i_m((pc), emit_b111, (imm), (b), (i), (s), (d)); } - -# define emitm_sarl_r_r(interp, pc, reg1, reg2) \ - { (pc) = emit_shift_r_r((interp), (pc), emit_b111, (reg1), (reg2)); } - -# define emitm_sarl_r_m(pc, reg, b, i, s, d) \ - { (pc) = emit_shift_r_m((pc), emit_b111, (reg), (b), (i), (s), (d)); } - -/* rotate */ - -# define jit_emit_rol_ri_i(interp, pc, reg, imm) \ - { (pc) = emit_shift_i_r((interp), (pc), emit_b000, (imm), (reg)); } - -# define jit_emit_ror_ri_i(interp, pc, reg, imm) \ - { (pc) = emit_shift_i_r((interp), (pc), emit_b001, (imm), (reg)); } - -/* interface, shift r1 by r2 bits */ - -# define jit_emit_shl_rr_i(interp, pc, r1, r2) \ - (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b100) - -# define jit_emit_shl_RM_i(interp, pc, r1, offs) \ - (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b100) - -/* shr seems to be the arithmetic shift */ -# define jit_emit_shr_rr_i(interp, pc, r1, r2) \ - (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b111) - -# define jit_emit_shr_RM_i(interp, pc, r1, offs) \ - (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b111) - -# define jit_emit_lsr_rr_i(interp, pc, r1, r2) \ - (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b101) - -# define jit_emit_lsr_RM_i(interp, pc, r1, offs) \ - (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b101) - -/* MOV (reg), reg */ -# define emit_movm_r_r(pc, src, dest) \ - *((pc)++) = (char) 0x8b; \ - *((pc)++) = (char) (src) | (dest) << 3 - -/* MOV X(reg), reg */ -# define emit_movb_i_r_r(pc, imm, src, dest) \ - *((pc)++) = (char)(0x8b); \ - *((p)c++) = (char)(0x40 | ((src) - 1) | ((dest) - 1) << 3); \ - *((pc)++) = (imm) - -/* INC / DEC */ -# define jit_emit_inc_r_i(pc, reg) *((pc)++) = (char)(0x40 | ((reg) - 1)) -# define jit_emit_dec_r_i(pc, reg) *((pc)++) = (char)(0x48 | ((reg) - 1)) - -/* Floating point ops */ - -# define emitm_floatop 0xd8 /* 11011000 */ -# define jit_emit_dec_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF6; } -# define jit_emit_inc_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF7; } - -# define emitm_fl_2(interp, pc, mf, opa, opb, b, i, s, d) { \ - *((pc)++) = (char)(emitm_floatop | ((mf) << 1) | (opa)); \ - (pc) = emit_r_X((interp), (pc), emit_reg(opb), (b), (i), (s), (long)(d)); } - -# define emitm_fl_3(pc, d_p_opa, opb_r, sti) { \ - *((pc)++) = (char)(emitm_floatop | (d_p_opa)); \ - *((pc)++) = (char)(0xc0 | ((opb_r) << 3) | (sti)); } - -# define emitm_fl_4(pc, op) { \ - *((pc)++) = (char)(emitm_floatop | emit_b001); \ - *((pc)++) = (char)(0xe0 | (op)); } - -/* Integer loads and stores */ -# define emitm_fildl(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 1, emit_b000, (b), (i), (s), (d)) - -# define emitm_fistpl(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 1, emit_b011, (b), (i), (s), (d)) - -# define emitm_fistl(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 1, emit_b010, (b), (i), (s), (d)) - -/* long long integer load/store */ -# define emitm_fildll(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b11, 1, emit_b101, (b), (i), (s), (d)) - -# define emitm_fistpll(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b11, 1, emit_b111, (b), (i), (s), (d)) - -/* Double loads and stores */ -# define emitm_fldl(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 1, emit_b000, (b), (i), (s), (d)) - -# define emitm_fstpl(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 1, emit_b011, (b), (i), (s), (d)) - -# define emitm_fstl(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 1, emit_b010, (b), (i), (s), (d)) - -/* long double load / store */ -# define emitm_fldt(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 1, emit_b101, (b), (i), (s), (d)) - -# define emitm_fstpt(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 1, emit_b111, (b), (i), (s), (d)) - -/* short float load / store */ -# define emitm_flds(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b00, 1, emit_b000, (b), (i), (s), (d)) - -# define emitm_fstps(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b00, 1, emit_b010, (b), (i), (s), (d)) - -#if NUMVAL_SIZE == 8 - -# define jit_emit_fload_m_n(interp, pc, address) \ - emitm_fldl((interp), (pc), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_fload_mb_n(interp, pc, base, offs) \ - emitm_fldl((interp), (pc), (base), emit_None, 1, (offs)) - -# define jit_emit_fstore_m_n(interp, pc, address) \ - emitm_fstpl((interp), (pc), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_fstore_mb_n(interp, pc, base, offs) \ - emitm_fstpl((interp), (pc), (base), emit_None, 1, (offs)) - -# define jit_emit_fst_mb_n(interp, pc, base, offs) \ - emitm_fstl((interp), (pc), (base), emit_None, 1, (offs)) - -#else /* NUMVAL_SIZE */ - -# define jit_emit_fload_m_n(interp, pc, address) \ - emitm_fldt((pc), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_fload_mb_n(interp, pc, base, offs) \ - emitm_fldt((pc), (base), emit_None, 1, (offs)) - -# define jit_emit_fstore_m_n(pc, address) \ - emitm_fstpt((pc), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_fstore_mb_n(interp, pc, base, offs) \ - emitm_fstpt((pc), (base), emit_None, 1, (offs)) - -# define jit_emit_fst_mb_n(interp, pc, base, offs) \ - emitm_fstt((pc), (base), emit_None, 1, (offs)) - -#endif /* NUMVAL_SIZE */ - -#if INTVAL_SIZE == 4 - -# define jit_emit_fload_m_i(interp, pc, address) \ - emitm_fildl((interp), (pc), emit_None, emit_None, emit_None, (address)) -# define jit_emit_fload_mb_i(interp, pc, offs) \ - emitm_fildl((interp), (pc), emit_EBX, emit_None, 1, (offs)) -# define jit_emit_fstore_m_i(pc, m) \ - emitm_fistpl((pc), emit_None, emit_None, emit_None, (m)) - -#else /* INTVAL_SIZE */ - -# define jit_emit_fload_m_i(interp, pc, address) \ - emitm_fildll((interp), (pc), emit_None, emit_None, emit_None, (address)) -# define jit_emit_fload_mb_i(interp, pc, offs) \ - emitm_fildll((interp), (pc), emit_EBX, emit_None, 1, (offs)) -# define jit_emit_fstore_m_i(pc, m) \ - emitm_fistpll((pc), emit_None, emit_None, emit_None, (m)) - -#endif /* INTVAL_SIZE */ - -/* 0xD8 ops */ -# define emitm_fadd(pc, sti) emitm_fl_3((pc), emit_b000, emit_b000, (sti)) -# define emitm_fmul(pc, sti) emitm_fl_3((pc), emit_b000, emit_b001, (sti)) -# define emitm_fsub(pc, sti) emitm_fl_3((pc), emit_b000, emit_b100, (sti)) -# define emitm_fdiv(pc, sti) emitm_fl_3((pc), emit_b000, emit_b110, (sti)) - -/* 0xD9 ops */ -# define emitm_fldz(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xee; } -# define emitm_fld1(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe8; } -# define emitm_fsqrt(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfa; } -# define emitm_fsin(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfe; } -# define emitm_fcos(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xff; } -# define emitm_fxam(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe5; } - -/* FXCH ST, ST(i) , optimize 2 consecutive fxch with same reg */ -# define emitm_fxch(pc, sti) { \ - emitm_fl_3((pc), emit_b001, emit_b001, (sti)); \ -} - -/* FLD ST, ST(i), optimized FSTP(N+1);FLD(N) => FST(N+1) */ -extern unsigned char *lastpc; -# define emitm_fld(pc, sti) do { \ - if ((unsigned char *)(pc) == (lastpc + 2) && \ - (int)(*lastpc) == (int)0xDD && \ - (int)lastpc[1] == (int)(0xD8+(sti)+1)) \ - lastpc[1] = 0xD0+(sti)+1; \ - else \ - emitm_fl_3((pc), emit_b001, emit_b000, (sti)); \ - } while (0) - -/* 0xDA, 0xDB ops */ -/* FCMOV*, FCOMI PPRO */ - -/* 0xDC like 0xD8 with reversed operands */ -# define emitm_faddr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b000, (sti)) -# define emitm_fmulr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b001, (sti)) -# define emitm_fsubr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b100, (sti)) - -/* 0xDD ops */ -/* FFree ST(i) */ -# define emitm_ffree(pc, sti) emitm_fl_3((pc), emit_b101, emit_b000, (sti)) - -/* FST ST(i) = ST */ -# define emitm_fst(pc, sti) emitm_fl_3((pc), emit_b101, emit_b010, (sti)) - -/* FSTP ST(i) = ST, POP */ -# define emitm_fstp(pc, sti) { \ - lastpc = (unsigned char*) (pc); \ - emitm_fl_3((pc), emit_b101, emit_b011, (sti)); \ -} - -/* FUCOM ST(i) <=> ST unordered compares */ -# define emitm_fucom(pc, sti) emitm_fl_3((pc), emit_b101, emit_b100, (sti)) - -/* FUCOMP ST(i) <=> ST, POP */ -# define emitm_fucomp(pc, sti) emitm_fl_3((pc), emit_b101, emit_b101, (sti)) - -/* 0xDE ops */ -/* FADDP Add ST(i) = ST + ST(i); POP */ -# define emitm_faddp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b000, (sti)) - -/* FMULP Mul ST(i) = ST * ST(i); POP */ -# define emitm_fmulp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b001, (sti)) - -/* FSUB ST = ST - ST(i) */ - -/* FSUBRP SubR ST(i) = ST - ST(i); POP */ -# define emitm_fsubrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b100, (sti)) - -/* FSUBP Sub ST(i) = ST(i) - ST; POP */ -# define emitm_fsubp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b101, (sti)) - -/* FDIVRP DivR ST(i) = ST(i) / ST(0); POP */ -# define emitm_fdivrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b110, (sti)) - -/* FDIVP Div ST(i) = ST(0) / ST(i); POP ST(0) */ -# define emitm_fdivp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b111, (sti)) - -/* 0xDF OPS: FCOMIP, FUCOMIP PPRO */ - -/* Negate - called change sign */ -# define emitm_fchs(pc) emitm_fl_4((pc), 0) - -/* ABS - ST(0) = ABS(ST(0)) */ -# define emitm_fabs(pc) emitm_fl_4((pc), 1) - -/* Comparisons */ - -# define emitm_fcom(pc, sti) emitm_fl_3((pc), emit_b000, emit_b010, (sti)) - -# define emitm_fcomp(pc, sti) emitm_fl_3((pc), emit_b000, emit_b011, (sti)) - -#ifdef PARROT_HAS_JIT_FCOMIP -# define emitm_fcomip(pc, sti) emitm_fl_3((pc), emit_b111, emit_b110, (sti)) -# define emitm_fcomi(pc, sti) emitm_fl_3((pc), emit_b011, emit_b110, (sti)) -#else -# define emitm_fcomip(pc, sti) do { \ - emitm_fcomp((pc), (sti)); \ - emitm_fstw(pc); \ - emitm_sahf(pc); \ - } while (0) -# define emitm_fcomi(pc, sti) do { \ - emitm_fcom((pc), (sti)); \ - emitm_fstw(pc); \ - emitm_sahf(pc); \ - } while (0) -#endif - -# define emitm_fcompp(pc) { *((pc)++) = (char) 0xde; *((pc)++) = (char) 0xd9; } - -# define emitm_fcom_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 0, emit_b010, (b), (i), (s), (d)) - -# define emitm_fcomp_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 0, emit_b011, (b), (i), (s), (d)) - -/* ST -= real64 */ -# define emitm_fsub_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 0, emit_b100, (b), (i), (s), (d)) - -/* ST -= int32_mem */ -# define emitm_fisub_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 0, emit_b100, (b), (i), (s), (d)) - -# define emitm_fadd_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 0, emit_b000, (b), (i), (s), (d)) - -/* ST += int32_mem */ -# define emitm_fiadd_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 0, emit_b000, (b), (i), (s), (d)) - -/* ST *= real64 */ -# define emitm_fmul_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 0, emit_b001, (b), (i), (s), (d)) - -/* ST *= int32_mem */ -# define emitm_fimul_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 0, emit_b001, (b), (i), (s), (d)) - -/* ST /= real64 */ -# define emitm_fdiv_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b10, 0, emit_b110, (b), (i), (s), (d)) - -/* ST /= int32_mem */ -# define emitm_fidiv_m(interp, pc, b, i, s, d) \ - emitm_fl_2((interp), (pc), emit_b01, 0, emit_b110, (b), (i), (s), (d)) - -/* Ops Needed to support loading EFLAGs for conditional branches */ -# define emitm_fstw(pc) emitm_fl_3((pc), emit_b111, emit_b100, emit_b000) - -# define emitm_sahf(pc) *((pc)++) = (char) 0x9e - -/* misc float */ -# define emitm_ftst(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xE4; } -# define emitm_fprem(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF8; } -# define emitm_fprem1(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF5; } - -# define emitm_fldcw(interp, pc, mem) \ - emitm_fl_2((interp), (pc), emit_b00, 1, emit_b101, 0, 0, 0, (mem)) - -#if defined(NEG_MINUS_ZERO) -# define jit_emit_neg_r_n(pc, r) { \ - if (r) { \ - emitm_fld((pc), (r)); \ - } \ - emitm_fchs(pc); \ - if (r) { \ - emitm_fstp((pc), ((r)+1)); \ - } \ - } - -# define jit_emit_neg_M_n(interp, pc, mem) { \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \ - emitm_fchs(pc); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \ - } - -#elif defined(NEG_ZERO_SUB) - -# define jit_emit_neg_r_n(pc, r) { \ - emitm_fldz(pc); \ - emitm_fsubrp((pc), ((r)+1)); \ - } - -# define jit_emit_neg_M_n(interp, pc, mem) { \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \ - emitm_fldz(pc); \ - emitm_fsubrp((pc), 1); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \ - } -#else - -# define jit_emit_neg_r_n(pc, r) { \ - if (r) { \ - emitm_fld((pc), (r)); \ - } \ - emitm_ftst(pc); \ - emitm_fstw(pc); \ - emitm_sahf(pc); \ - emitm_jxs((pc), emitm_jz, 2); \ - emitm_fchs(pc); \ - if (r) { \ - emitm_fstp((pc), ((r)+1)); \ - } \ - } - -# define jit_emit_neg_M_n(interp, pc, mem) { \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \ - emitm_ftst(pc); \ - emitm_fstw(pc); \ - emitm_sahf(pc); \ - emitm_jxs((pc), emitm_jz, 2); \ - emitm_fchs(pc); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \ - } -#endif - -# define jit_emit_sin_r_n(pc, r) \ - if (r) { \ - emitm_fld((pc), (r)); \ - } \ - emitm_fsin(pc); \ - if (r) { \ - emitm_fstp((pc), ((r)+1)); \ - } - -# define jit_emit_cos_r_n(pc, r) \ - if (r) { \ - emitm_fld((pc), (r)); \ - } \ - emitm_fcos(pc); \ - if (r) { \ - emitm_fstp((pc), ((r)+1)); \ - } - -# define jit_emit_sqrt_r_n(pc, r) \ - if (r) { \ - emitm_fld((pc), (r)); \ - } \ - emitm_fsqrt(pc); \ - if (r) { \ - emitm_fstp((pc), ((r)+1)); \ - } - -# define jit_emit_abs_r_n(pc, r) { \ - if (r) { \ - emitm_fld((pc), (r)); \ - } \ - emitm_fabs(pc); \ - if (r) { \ - emitm_fstp((pc), ((r)+1)); \ - } \ - } - -# define jit_emit_abs_r_i(pc, r) { \ - jit_emit_test_r_i((pc), (r)); \ - emitm_jxs((pc), emitm_jns, 3); \ - jit_emit_not_r_i((pc), (r)); \ - jit_emit_inc_r_i((pc), (r)); \ - } - -# define jit_emit_abs_m_n(interp, pc, mem) { \ - jit_emit_fload_m_n((interp), (pc), (mem)); \ - emitm_fabs(pc); \ - jit_emit_fstore_m_n((pc), (mem)); \ - } - -/* Integer comparisons */ -# define jit_emit_cmp_rr(pc, reg1, reg2) \ - emitm_alul_r_r((pc), 0x39, (reg2), (reg1)) -# define jit_emit_cmp_rr_i(pc, r1, r2) jit_emit_cmp_rr((pc), (r1), (r2)) - -# define emitm_cmpl_r_m(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x3b, (reg), (b), (i), (s), (d)) - -# define emitm_cmpl_m_r(pc, reg, b, i, s, d) \ - emitm_alul_r_m((pc), 0x39, (reg), (b), (i), (s), (d)) - -# define jit_emit_cmp_ri_i(interp, pc, reg, imm) \ - emitm_alul_i_r((pc), 0x81, emit_b111, (imm), (reg)) - -/* Unconditional Jump/Call */ - -# define emitm_call_cfunc(pc, func) emitm_calll((pc), (char *)(func) - (pc) - 4) - -# define emitm_calll(pc, disp) { \ - *((pc)++) = (char) 0xe8; \ - *(long *)(pc) = (disp); (pc) += 4; } - -# define emitm_callr(pc, reg) { \ - *((pc)++) = (char) 0xff; \ - *((pc)++) = (char) 0xd0 | ((reg) - 1); } - -# define emitm_callm(pc, b, i, s, d) { \ - *((pc)++) = (char) 0xff; \ - (pc) = emit_r_X((interp), (pc), emit_reg(emit_b010), (b), (i), (s), (d)); } - -# define emitm_jumps(pc, disp) { \ - *((pc)++) = (char) 0xeb; \ - *((pc)++) = (disp); } - -# define emitm_jumpl(pc, disp) { \ - *((pc)++) = (char) 0xe9; \ - *(long *)(pc) = (disp); (pc) += 4; } - -# define emitm_jumpr(pc, reg) { \ - *((pc)++) = (char) 0xff; \ - *((pc)++) = (char)(0xe0 | ((reg) - 1)); } - -# define emitm_jumpm(pc, b, i, s, d) { \ - *((pc)++) = (char) 0xff; \ - (pc) = emit_r_X((interp), (pc), emit_reg(emit_b100), (b), (i), (s), (d)); } - -/* Conditional jumps */ - -/* Short jump - 8 bit disp */ -# define emitm_jxs(pc, code, disp) { \ - *((pc)++) = (char)(0x70 | (code)); \ - *((pc)++) = (char)(disp); } - -/* Long jump - 32 bit disp */ -# define emitm_jxl(pc, code, disp) { \ - *((pc)++) = (char) 0x0f; \ - *((pc)++) = (char)(0x80 | (code)); \ - *(long *)(pc) = (disp); (pc) += 4; } - -# define emitm_jo 0 -# define emitm_jno 1 -# define emitm_jb 2 -# define emitm_jnb 3 -# define emitm_jz 4 -# define emitm_je emitm_jz -# define emitm_jnz 5 -# define emitm_jne emitm_jnz -# define emitm_jbe 6 -# define emitm_ja 7 -# define emitm_js 8 -# define emitm_jns 9 -# define emitm_jp 10 -# define emitm_jnp 11 -# define emitm_jl 12 -# define emitm_jnl 13 -# define emitm_jle 14 -# define emitm_jg 15 - -/* set byte conditional */ -# define jit_emit_setcc_r(pc, cc, r) \ - *(pc)++ = 0x0f; \ - *(pc)++ = 0x90 + (cc); \ - *(pc)++ = (char) emit_alu_X_r(0, (r)) - -/* - * core.jit interface - * - * The new offset based versions have uppercase RM or MR inside - * That's probably only during transition time - */ - -# define jit_emit_mov_mi_i(pc, dest, immediate) \ - emitm_movl_i_m((pc), (immediate), emit_None, emit_None, emit_None, (dest)) - -# define jit_emit_mov_MI_i(interp, pc, offs, immediate) \ - emitm_movl_i_m((pc), (immediate), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_mov_rm_i(interp, pc, reg, address) \ - emitm_movl_m_r((interp), (pc), (reg), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_mov_RM_i(interp, pc, reg, offs) \ - emitm_movl_m_r((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_mov_mr_i(interp, pc, address, reg) \ - emitm_movl_r_m((interp), (pc), (reg), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_mov_MR_i(interp, pc, offs, reg) \ - emitm_movl_r_m((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_mul_RM_i(interp, pc, reg, offs) \ - emitm_smull_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_sub_RM_i(interp, pc, reg, offs) \ - emitm_subl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_sub_MR_i(interp, pc, offs, reg) \ - emitm_subl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_sub_MI_i(pc, offs, imm) \ - emitm_subl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_add_RM_i(interp, pc, reg, offs) \ - emitm_addl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_add_MR_i(interp, pc, offs, reg) \ - emitm_addl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_add_MI_i(pc, offs, imm) \ - emitm_addl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_cmp_rm_i(pc, reg, address) \ - emitm_cmpl_r_m((pc), (reg), emit_None, emit_None, emit_None, (address)) - -# define jit_emit_cmp_RM_i(interp, pc, reg, offs) \ - emitm_cmpl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -# define jit_emit_cmp_MR_i(interp, pc, offs, reg) \ - emitm_cmpl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs)) - -/* high level routines, behave like real 2 register FP */ - -/* mapped float registers numbers are ST(1)-ST(4). - * scratch register is ST(0) - */ - -/* ST(i) <- numvar */ -# define jit_emit_mov_RM_n(interp, pc, r, d) { \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (d)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* ST(i) <= NUM_CONST */ -# define jit_emit_mov_ri_n(interp, pc, r, i) { \ - jit_emit_fload_m_n((interp), (pc), (i)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* ST(i) <= &INT_CONST */ -# define jit_emit_mov_ri_ni(interp, pc, r, i) { \ - jit_emit_fload_m_i((interp), (pc), (i)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* ST(i) <= INT_REG */ -# define jit_emit_mov_RM_ni(interp, pc, r, i) { \ - jit_emit_fload_mb_i((interp), (pc), (i)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* NUM_REG(i) <= &INT_CONST - * the int const i is loaded from the code memory - */ -# define jit_emit_mov_MI_ni(interp, pc, offs, i) { \ - jit_emit_fload_m_i((interp), (pc), (i)); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \ -} - -/* INT_REG <= ST(i) */ -# define jit_emit_mov_mr_in(pc, mem, r) { \ - emitm_fld((pc), (r)); \ - jit_emit_fstore_m_i((pc), (mem)); \ -} - -/* numvar <- ST(i) */ -# define jit_emit_mov_mr_n(pc, d, r) { \ - emitm_fld((pc), (r)); \ - jit_emit_fstore_m_n((pc), (d)); \ -} - -# define jit_emit_mov_MR_n(interp, pc, d, r) { \ - if (r) { \ - emitm_fld((pc), (r)); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (d)); \ - } \ - else { \ - jit_emit_fst_mb_n((interp), (pc), emit_EBX, (d)); \ - } \ -} - -/* ST(r1) <= ST(r2) */ -# define jit_emit_mov_rr_n(pc, r1, r2) { \ - if ((r1) != (r2)) { \ - if (r2) { \ - emitm_fld((pc), (r2)); \ - emitm_fstp((pc), ((r1)+1)); \ - } \ - else { \ - emitm_fst((pc), (r1)); \ - } \ - } \ -} - -/* ST(r1) xchg ST(r2) */ -# define jit_emit_xchg_rr_n(interp, pc, r1, r2) { \ - if ((r1) != (r2)) { \ - emitm_fld((pc), (r1)); \ - emitm_fld((pc), ((r2)+1)); \ - emitm_fstp((pc), ((r1)+2)); \ - emitm_fstp((pc), ((r2)+1)); \ - } \ -} - -# define jit_emit_xchg_RM_n(interp, pc, r, offs) { \ - emitm_fld((pc), (r)); \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \ - emitm_fstp((pc), ((r)+2)); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \ -} - -# define jit_emit_xchg_MR_n(interp, pc, offs, r) { \ - emitm_fld((pc), (r)); \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \ - emitm_fstp((pc), ((r)+2)); \ - jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \ -} - -# define jit_emit_finit(pc) { *((pc)++) = (char) 0xdb; *((pc)++) = (char) 0xe3; } - -/* ST(i) op= MEM */ - -# define jit_emit_xxx_rm_n(interp, op, pc, r, m) { \ - jit_emit_fload_m_n((interp), (pc), (m)); \ - emitm_f ## op ## p((pc), ((r)+1)); \ -} - -# define jit_emit_xxx_RM_n(interp, op, pc, r, offs) { \ - jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \ - emitm_f ## op ## p((pc), ((r)+1)); \ -} - -/* - * float ops in two flavors: abs memory for constants, offsets for regs - */ - -# define jit_emit_add_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), add, (pc), (r), (m)) -# define jit_emit_sub_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), sub, (pc), (r), (m)) -# define jit_emit_mul_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), mul, (pc), (r), (m)) - -# define jit_emit_add_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), add, (pc), (r), (o)) -# define jit_emit_sub_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), sub, (pc), (r), (o)) -# define jit_emit_mul_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), mul, (pc), (r), (o)) - -/* ST(r1) += ST(r2) */ -/* r1 == 0: ST(0) <- ST(0) + ST(i) - * r2 == 0: ST(i) <- ST(0) + ST(i) - */ -# define jit_emit_add_rr_n(interp, pc, r1, r2) do { \ - if (!(r1)) { \ - emitm_fadd((pc), (r2)); \ - } \ - else if (!(r2)) { \ - emitm_faddr((pc), (r1)); \ - } \ - else { \ - emitm_fld((pc), (r2)); \ - emitm_faddp((pc), ((r1)+1)); \ - } \ - } \ - while (0) -/* - * ST(r) += INT_REG - */ -# define jit_emit_add_RM_ni(pc, r, offs) { \ - emitm_fld((pc), (r)); \ - emitm_fiadd_m((pc), emit_EBX, 0, 1, (offs)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* ST(r1) -= ST(r2) */ -/* r1 == 0: ST(0) <- ST(0) - ST(i) - * r2 == 0: ST(i) <- ST(i) - ST(0) - */ -# define jit_emit_sub_rr_n(interp, pc, r1, r2) do { \ - if (!(r1)) { \ - emitm_fsub((pc), (r2)); \ - } \ - else if (!(r2)) { \ - emitm_fsubr((pc), (r1)); \ - } \ - else { \ - emitm_fld((pc), (r2)); \ - emitm_fsubp((pc), ((r1)+1)); \ - } \ - } \ - while (0) - -/* - * ST(r) -= INT_REG - */ -# define jit_emit_sub_RM_ni(pc, r, offs) { \ - emitm_fld((pc), (r)); \ - emitm_fisub_m((pc), emit_EBX, 0, 1, (offs)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -# define jit_emit_inc_r_n(pc, r) { \ - emitm_fld1(pc); \ - emitm_faddp((pc), ((r)+1)); \ -} - -# define jit_emit_dec_r_n(pc, r) { \ - emitm_fld1(pc); \ - emitm_fsubp((pc), ((r)+1)); \ -} - -/* ST(r1) *= ST(r2) */ -/* r1 == 0: ST(0) <- ST(0) * ST(i) - * r2 == 0: ST(i) <- ST(0) * ST(i) - */ -# define jit_emit_mul_rr_n(interp, pc, r1, r2) do { \ - if (!(r1)) { \ - emitm_fmul((pc), (r2)); \ - } \ - else if (!(r2)) { \ - emitm_fmulr((pc), (r1)); \ - } \ - else { \ - emitm_fld((pc), (r2)); \ - emitm_fmulp((pc), ((r1)+1)); \ - } \ - } \ - while (0) - -/* - * ST(r) *= INT_REG - */ -# define jit_emit_mul_RM_ni(pc, r, offs) { \ - emitm_fld((pc), (r)); \ - emitm_fimul_m((pc), emit_EBX, 0, 1, (offs)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* - * ST(r) /= INT_REG - */ -# define jit_emit_div_RM_ni(pc, r, offs) { \ - emitm_fld((pc), (r)); \ - emitm_fidiv_m((pc), emit_EBX, 0, 1, (offs)); \ - emitm_fstp((pc), ((r)+1)); \ -} - -/* test r for zero */ -# define jit_emit_test_r_n(pc, r) { \ - if (r) { \ - emitm_fxch((pc), (r)); \ - } \ - emitm_fxam(pc); \ - emitm_fstw(pc); \ - emitm_sahf(pc); \ - if (r) { \ - emitm_fxch((pc), (r)); \ - } \ -} - -enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL }; - -# define jit_emit_stack_frame_enter(pc) do { \ - emitm_pushl_r((pc), emit_EBP); \ - jit_emit_mov_rr_i((pc), emit_EBP, emit_ESP); \ -} while (0) - -# define jit_emit_stack_frame_leave(pc) do { \ - jit_emit_mov_rr_i((pc), emit_ESP, emit_EBP); \ - emitm_popl_r((pc), emit_EBP); \ -} while (0) - -# define jit_emit_end(pc) { \ - jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \ - emitm_popl_r((pc), emit_EDI); \ - emitm_popl_r((pc), emit_ESI); \ - emitm_popl_r((pc), emit_EBX); \ - emitm_popl_r((pc), emit_EBP); \ - emitm_ret(pc); \ - } - -size_t calc_signature_needs(const char *sig, int *strings); - -void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, - STRING *signature, int *sizeptr); - -/* - * register usage - * %edi, %esi ... mapped, preserved - * %edx, %ecx ... mapped, not preserved - * %ebx ... base pointer for register access, preserved - * %eax ... scratch, return value register - */ - -#endif /* PARROT_I386_JIT_EMIT_H_GUARD */ +#endif /* PARROT_FRAME_BUILDER_H_GUARD */ /* * Local variables: diff --git a/src/nci_test.c b/src/nci_test.c index 2044d9d..7593431 100644 --- a/src/nci_test.c +++ b/src/nci_test.c @@ -110,6 +110,8 @@ PARROT_DYNEXT_EXPORT char * nci_ttt(char *, char *); PARROT_DYNEXT_EXPORT void nci_vfff(float, float, float); PARROT_DYNEXT_EXPORT void nci_vV(const char **); PARROT_DYNEXT_EXPORT void nci_vVVV(const char **, const char **, const char **); +PARROT_DYNEXT_EXPORT int nci_i20(int, int, int, int, int, int, int, int, int, int, int, int, int, int, + int, int, int, int, int); /* Declarations for callback tests */ @@ -1191,6 +1193,50 @@ nci_vVVV(const char **ptr1, const char **ptr2, const char **ptr3) *ptr3 = "Go suck a lemon.\n"; } +/* + +=item C + +Prints and returns the nth value in a list of integers. First argument is the selector; subsequents, +the list. + +This function is designed to be outside of the range of the static frame builder as an excercise for +the dynamic frame builder. + +=cut + +*/ +PARROT_DYNEXT_EXPORT int +nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10, + int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18) { + int *selected; + switch ((sel < 0 ? -sel : sel) % 18) { + case 0: selected = &v1; break; + case 1: selected = &v2; break; + case 2: selected = &v3; break; + case 3: selected = &v4; break; + case 4: selected = &v5; break; + case 5: selected = &v6; break; + case 6: selected = &v7; break; + case 7: selected = &v8; break; + case 8: selected = &v9; break; + case 9: selected = &v10; break; + case 10: selected = &v11; break; + case 11: selected = &v12; break; + case 12: selected = &v13; break; + case 13: selected = &v14; break; + case 14: selected = &v15; break; + case 15: selected = &v16; break; + case 16: selected = &v17; break; + case 17: selected = &v18; break; + default: printf("default case reached (should never happen)"); return -1; + } + printf("%d\n", *selected); + return *selected; +} + #ifdef TEST char l2 = 4; diff --git a/t/pmc/nci.t b/t/pmc/nci.t index fbfca27..667da34 100644 --- a/t/pmc/nci.t +++ b/t/pmc/nci.t @@ -17,7 +17,7 @@ BEGIN { } use Test::More; -use Parrot::Test tests => (70 + @nci_sigs); +use Parrot::Test tests => (71 + @nci_sigs); use Parrot::Config qw(%PConfig); =head1 NAME @@ -2785,6 +2785,76 @@ It is a beautiful day! Go suck a lemon. OUTPUT +my $test_code = <<'CODE'; +.sub test :main + .local pmc libnci_test + $S0 = 'libnci_test' + libnci_test = loadlib $S0 + + .local pmc nci_i20 + nci_i20 = dlfunc libnci_test, "nci_i20", "iiiiiiiiiiiiiiiiiiii" + + .local pmc args + args = new ['FixedIntegerArray'] + args = 18 + + $I0 = 2 + args[0] = 1 + args[1] = 1 + +LOOP1: + $I1 = $I0 - 1 + $I1 = args[$I1] + + $I2 = $I0 - 2 + $I2 = args[$I2] + + $I3 = $I1 + $I2 + args[$I0] = $I3 + inc $I0 + if $I0 < 18 goto LOOP1 + + $I0 = args + dec $I0 + + $I1 = args[0] + $I2 = args[1] + $I3 = args[2] + $I4 = args[3] + $I5 = args[4] + $I6 = args[5] + $I7 = args[6] + $I8 = args[7] + $I9 = args[8] + $I10 = args[9] + $I11 = args[10] + $I12 = args[11] + $I13 = args[12] + $I14 = args[13] + $I15 = args[14] + $I16 = args[15] + $I17 = args[16] + $I18 = args[17] + +LOOP2: + nci_i20($I0, $I1, $I2, $I3, $I4, $I5, $I6, $I7, $I8, $I9, $I10, $I11, $I12, $I13, $I14, $I15, $I16, $I17, $I18) + $I0 = $I0 / 2 + if $I0 > 0 goto LOOP2 +.end +CODE +if ($PConfig{cc_build_call_frames}) { + pir_output_is($test_code, < 27; +use Test::More tests => 28; use lib qw( lib t/configure/testlib ); use_ok('config::init::defaults'); use_ok('config::auto::frames'); @@ -33,22 +33,24 @@ $conf->add_steps($pkg); $conf->options->set( %{$args} ); my $step = test_step_constructor_and_description($conf); -# To avoid a warning about an unitialized value, we will set nvsize to 8, -# cpuarch to i386 and osname to linux. +# To avoid a warning about an uninitialized value, we will set osname to linux. # This is normally done during earlier configuration steps. -$conf->data->set( nvsize => 8 ); -$conf->data->set( cpuarch => 'i386' ); $conf->data->set( osname => 'linux' ); +$conf->data->set( HAS_LIBJIT => 1 ); my $ret = $step->runstep($conf); ok( $ret, "runstep() returned true value" ); ok( defined ( $step->result() ), "Got defined result" ); -TODO: { - local $TODO = - 'build frames temporarily disabled at pcc_reapply merge: TT #1132'; - is( $step->result(), 'yes', "Result is 'yes', as expected" ); -} +is( $step->result(), 'yes', "Result is 'yes', as expected" ); + +$conf->data->set( HAS_LIBJIT => undef ); +$ret = $step->runstep($conf); +ok( $ret, "runstep() returned true value" ); +ok( defined ( $step->result() ), + "Got defined result" ); +is( $step->result(), 'no', "Result is 'no', as expected" ); + $conf->cc_clean(); $step->set_result( undef ); @@ -68,46 +70,20 @@ $can_build_call_frames = auto::frames::_call_frames_buildable($conf); ok( ! $can_build_call_frames, "_call_frames_buildable() returned false value, as expected" ); +$conf->data->set( HAS_LIBJIT => 1 ); $conf->options->set( buildframes => undef ); -$conf->data->set( osname => 'linux' ); -$conf->data->set( cpuarch => 'i386' ); -$conf->data->set( nvsize => 8 ); -$can_build_call_frames = auto::frames::_call_frames_buildable($conf); -TODO: { - local $TODO = - 'build frames temporarily disabled at pcc_reapply merge: TT #1132'; - ok( $can_build_call_frames, - "_call_frames_buildable() returned true value, as expected (i386/non darwin/8)" - ); -} - -$conf->data->set( osname => 'darwin' ); -$conf->data->set( cpuarch => 'i386' ); -$conf->data->set( nvsize => 8 ); -$can_build_call_frames = auto::frames::_call_frames_buildable($conf); -ok( ! $can_build_call_frames, - "_call_frames_buildable() returned false value, as expected (i386/darwin/8)" ); - -$conf->data->set( osname => 'linux' ); -$conf->data->set( cpuarch => 'ppc' ); -$conf->data->set( nvsize => 8 ); $can_build_call_frames = auto::frames::_call_frames_buildable($conf); -ok( ! $can_build_call_frames, - "_call_frames_buildable() returned false value, as expected (ppc/linux/8)" ); +ok( $can_build_call_frames, + "_call_frames_buildable() returned true value, as expected" ); -$conf->data->set( osname => 'linux' ); -$conf->data->set( cpuarch => 'i386' ); -$conf->data->set( nvsize => 4 ); +$conf->data->set( HAS_LIBJIT => undef ); +$conf->options->set( buildframes => 0 ); $can_build_call_frames = auto::frames::_call_frames_buildable($conf); ok( ! $can_build_call_frames, - "_call_frames_buildable() returned false value, as expected (i386/linux/4)" ); + "_call_frames_buildable() returned false value, as expected" ); ##### _handle_call_frames_buildable() ##### -$conf->data->set( nvsize => 8 ); -$conf->data->set( cpuarch => 'i386' ); -$conf->data->set( osname => 'linux' ); - my $rv; $can_build_call_frames = 0; @@ -123,19 +99,16 @@ $conf->data->set( 'cc_build_call_frames' => undef ); $conf->data->set( 'has_exec_protect' => undef ); $can_build_call_frames = 1; -my $realos = $conf->data->get( 'osname' ); -$conf->data->set( 'osname' => 'foobar' ); $rv = $step->_handle_can_build_call_frames( $conf, $can_build_call_frames ); ok( $rv, "_handle_can_build_call_frames() returned true value" ); is( $conf->data->get( 'cc_build_call_frames'), '-DCAN_BUILD_CALL_FRAMES', "cc_build_call_frames set to expected value" ); -is( $conf->data->get( 'has_exec_protect' ), 0, - "has_exec_protect is 0, as expected" ); +is( $conf->data->get( 'has_exec_protect' ), 1, + "has_exec_protect is 1, as expected" ); is( $step->result(), 'yes', "Result is 'yes', as expected" ); $conf->data->set( 'cc_build_call_frames' => undef ); $conf->data->set( 'has_exec_protect' => undef ); -$conf->data->set( 'osname' => $realos ); pass("Completed all tests in $0"); diff --git a/t/steps/auto/libjit-01.t b/t/steps/auto/libjit-01.t new file mode 100644 index 0000000..004dc6e --- /dev/null +++ b/t/steps/auto/libjit-01.t @@ -0,0 +1,173 @@ +#! perl +# Copyright (C) 2009, Parrot Foundation. +# $Id$ +# auto/libjit-01.t + +use strict; +use warnings; + +use Test::More tests => 34; +use lib qw( lib t/configure/testlib ); +use Parrot::Configure; +use Parrot::Configure::Options 'process_options'; +use Parrot::Configure::Test qw( + test_step_thru_runstep + rerun_defaults_for_testing + test_step_constructor_and_description +); +use IO::CaptureOutput qw( capture ); + +use_ok('config::init::defaults'); +use_ok('config::auto::libjit'); + +my ($args, $step_list_ref) = process_options( { + argv => [ q{--without-libjit} ], + mode => 'configure', +} ); + +my $conf = Parrot::Configure->new; + +my $serialized = $conf->pcfreeze(); + +test_step_thru_runstep( $conf, 'init::defaults', $args ); + +my $pkg = 'auto::libjit'; +my ( $step, $ret ); + +$conf->add_steps($pkg); +$conf->options->set(%$args); +$step = test_step_constructor_and_description($conf); +$ret = $step->runstep($conf); +ok( $ret, "runstep() returned true value" ); +is( $step->result(), 'no', "Result is 'no', as expected" ); +is( $conf->data->get( 'HAS_LIBJIT' ), 0, + "Got expected result with --without-libjit option" ); +$conf->cc_clean(); + +$conf->replenish($serialized); + +($args, $step_list_ref) = process_options( { + argv => [ ], + mode => q{configure}, +} ); +rerun_defaults_for_testing($conf, $args ); +$conf->add_steps($pkg); +$conf->options->set( %{$args} ); +$step = test_step_constructor_and_description($conf); +$ret = $step->runstep($conf); +ok( $ret, "runstep() returned true value" ); +like( $step->result(), qr/yes|no/, "Result is either 'yes' or 'no'" ); +ok( defined( $conf->data->get( 'HAS_LIBJIT' ) ), + "'HAS_LIBJIT' has defined value" ); +$conf->cc_clean(); + +########## _evaluate_cc_run ########## + +my ($test, $has_libjit, $verbose); + +$step->set_result( undef ); + +$test = q{USES INTERPRETER: 33}; +$has_libjit = 0; +$verbose = 0; +$has_libjit = $step->_evaluate_cc_run($test, $has_libjit, $verbose); +ok( $has_libjit, "_evaluate_cc_run() returned true value, as expected" ); +is( $step->result(), 'yes', "result is yes, as expected" ); + +$step->set_result( undef ); + +$test = q{foobar}; +$has_libjit = 0; +$verbose = 0; +$has_libjit = $step->_evaluate_cc_run($test, $has_libjit, $verbose); +ok( ! $has_libjit, "_evaluate_cc_run() returned false value, as expected" ); +ok( ! defined($step->result()), "result is undefined, as expected" ); + +$step->set_result( undef ); + +$test = q{USES INTERPRETER: 33}; +$has_libjit = 0; +$verbose = 1; +{ + my ($stdout, $stderr); + capture( + sub { $has_libjit = + $step->_evaluate_cc_run($test, $has_libjit, $verbose); }, + \$stdout, + \$stderr, + ); + ok( $has_libjit, "_evaluate_cc_run() returned true value, as expected" ); + is( $step->result(), 'yes', "result is yes, as expected" ); + like( $stdout, qr/\(yes\)/, "Got expected verbose output" ); +} + +########## _handle_has_libjit() ########## + +my $extra_libs; + +$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); +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( '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); +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( '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( ! $conf->data->get( 'libjit_has_alloca'), + "without libJIT, 'libjit_has_alloca' has false value" ); +is( $conf->data->get( 'libs' ), "", + "Got expected value for libs" ); + +################### DOCUMENTATION ################### + +=head1 NAME + +auto/libjit-01.t - test auto::libjit + +=head1 SYNOPSIS + + % prove t/steps/auto/libjit-01.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F. + +The tests in this file test auto::libjit. + +=head1 SEE ALSO + +config::auto::libjit, F. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/t/steps/gen/libjit-01.t b/t/steps/gen/libjit-01.t new file mode 100644 index 0000000..92193cf --- /dev/null +++ b/t/steps/gen/libjit-01.t @@ -0,0 +1,112 @@ +#! perl +# Copyright (C) 2009, Parrot Foundation. +# $Id$ +# gen/libjit-01.t + +use strict; +use warnings; + +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'; + +use lib 'lib'; +use Parrot::Configure; +use Parrot::Configure::Options 'process_options'; +use Parrot::Configure::Test qw( + test_step_thru_runstep + rerun_defaults_for_testing + test_step_constructor_and_description +); + +use_ok('config::gen::libjit'); + +my ($args, $step_list_ref) = process_options( + { + argv => [], + mode => 'configure', + } +); + +my $conf = Parrot::Configure->new; + +my $serialized = $conf->pcfreeze(); + +my $pkg = 'gen::libjit'; +$conf->add_steps($pkg); +$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"); + +foreach (keys %{$step->{templates}}) { + ok(-f $step->{templates}{$_}, "Able to locate $_ template") +} + +my %orig_files; +foreach (keys %{$step->{targets}}) { + if (-f (my $targ_name = $step->{targets}{$_})) { + $orig_files{$_} = tempfile(); + move($targ_name, $orig_files{$_}); + } +} + +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}}) { + ok(-f $step->{targets}{$_}, "$_ target generated"); +} + +# re-set for next test +$conf->data->set(%orig_conf); +$step->set_result( '' ); +foreach (keys %{$step->{targets}}) { + if (exists $orig_files{$_}) { + move( $orig_files{$_}, $step->{targets}{$_} ); + } else { + unlink $_; + } +} + +$conf->replenish($serialized); + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + + gen/libjit-01.t - test gen::libjit + +=head1 SYNOPSIS + + % prove t/steps/gen/libjit-01.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F. + +The tests in this file test gen::libjit. + +=head1 SEE ALSO + +config::gen::libjit, F. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: diff --git a/tools/build/nativecall.pl b/tools/build/nativecall.pl index 06341a6..f54d33c 100644 --- a/tools/build/nativecall.pl +++ b/tools/build/nativecall.pl @@ -440,17 +440,13 @@ SHIM(PMC *pmc_nci), NOTNULL(STRING *signature), SHIM(int *jitted)) return F2DPTR(VTABLE_get_pointer(interp, b)); } else { - int jit_size; - void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &jit_size); + void *priv; + void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &priv); if (result) { - struct jit_buffer_private_data *priv; *jitted = 1; temp_pmc = pmc_new(interp, enum_class_ManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)result); #ifdef PARROT_HAS_EXEC_PROTECT - priv = (struct jit_buffer_private_data *) - mem_sys_allocate(sizeof(struct jit_buffer_private_data)); - priv->size = jit_size; SETATTR_ManagedStruct_custom_free_func(interp, temp_pmc, Parrot_jit_free_buffer); SETATTR_ManagedStruct_custom_free_priv(interp, temp_pmc, priv); SETATTR_ManagedStruct_custom_clone_func(interp, temp_pmc, Parrot_jit_clone_buffer);