Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

split NCI signature parser out from nci.pmc

this will allow multiple NCI backends (static compiler, static runtime, libffi) to share the same parser

also miscelaneous fixes to get fulltest mostly working (svn props mostly)


git-svn-id: https://svn.parrot.org/parrot/branches/gsoc_nci@49693 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
commit c64fa8d39a5e314a0080315e8d0e033c5860e9cf 1 parent e99d1ef
@plobsing plobsing authored
View
11 MANIFEST
@@ -1,7 +1,7 @@
# ex: set ro:
# $Id$
#
-# generated by tools/dev/mk_manifest_and_skip.pl Wed Sep 29 04:41:54 2010 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Wed Oct 27 07:17:39 2010 UT
#
# See below for documentation on the format of this file.
#
@@ -214,6 +214,8 @@ config/auto/inline/test2_c.in []
config/auto/isreg.pm []
config/auto/isreg/test_c.in []
config/auto/jit.pm []
+config/auto/libffi.pm []
+config/auto/libffi/test_c.in []
config/auto/llvm.pm []
config/auto/llvm/hello.c []
config/auto/memalign.pm []
@@ -266,6 +268,9 @@ config/gen/config_pm/config_lib_pir.in []
config/gen/config_pm/config_pir.in []
config/gen/config_pm/myconfig.in []
config/gen/core_pmcs.pm []
+config/gen/libffi.pm []
+config/gen/libffi/nci-ffi.pmc.in []
+config/gen/libffi/nci.pmc.in []
config/gen/makefiles.pm []
config/gen/makefiles/docs.in []
config/gen/makefiles/editor.in []
@@ -1331,6 +1336,7 @@ src/nci/core_thunks.c []
src/nci/core_thunks.nci []
src/nci/extra_thunks.c []
src/nci/extra_thunks.nci []
+src/nci/signatures.c []
src/nci_test.c []
src/oo.c []
src/ops/bit.ops []
@@ -1988,6 +1994,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/libffi-01.t [test]
t/steps/auto/llvm-01.t [test]
t/steps/auto/memalign-01.t [test]
t/steps/auto/msvc-01.t [test]
@@ -2013,6 +2020,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/libffi-01.t [test]
t/steps/gen/makefiles-01.t [test]
t/steps/gen/opengl-01.t [test]
t/steps/gen/platform-01.t [test]
@@ -2129,6 +2137,7 @@ tools/dev/mk_nci_thunks.pl []
tools/dev/mk_packfile_pbc []
tools/dev/mk_rpm_manifests.pl []
tools/dev/nci_test_gen.pl []
+tools/dev/nci_thunk_gen.nqp []
tools/dev/nci_thunk_gen.pir []
tools/dev/ncidef2pasm.pl []
tools/dev/nm.pl []
View
13 MANIFEST.SKIP
@@ -1,6 +1,6 @@
# ex: set ro:
# $Id$
-# generated by tools/dev/mk_manifest_and_skip.pl Thu Sep 23 09:20:45 2010 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Wed Oct 27 07:17:39 2010 UT
#
# This file should contain a transcript of the svn:ignore properties
# of the directories in the Parrot subversion repository. (Needed for
@@ -845,8 +845,6 @@
^src/packfile/.*\.o/
^src/packfile/.*\.obj$
^src/packfile/.*\.obj/
-^src/packfile/.*\.str$
-^src/packfile/.*\.str/
# generated from svn:ignore of 'src/pmc/'
^src/pmc/.*\.c$
^src/pmc/.*\.c/
@@ -1032,9 +1030,6 @@
^t/op/.*\.pir/
^t/op/.*_pbcexe.*$
^t/op/.*_pbcexe.*/
-# generated from svn:ignore of 't/op/testlib/'
-^t/op/testlib/.*\.pbc$
-^t/op/testlib/.*\.pbc/
# generated from svn:ignore of 't/perl/'
^t/perl/Parrot_Test_1\.pasm$
^t/perl/Parrot_Test_1\.pasm/
@@ -1051,9 +1046,6 @@
^t/pmc/.*\.pir/
^t/pmc/.*_pbcexe.*$
^t/pmc/.*_pbcexe.*/
-# generated from svn:ignore of 't/pmc/testlib/'
-^t/pmc/testlib/.*\.pbc$
-^t/pmc/testlib/.*\.pbc/
# generated from svn:ignore of 't/src/'
^t/src/.*_.*$
^t/src/.*_.*/
@@ -1085,9 +1077,6 @@
^t/tools/pmc2c\..*\.h/
^t/tools/pmc2c\..*\.pmc$
^t/tools/pmc2c\..*\.pmc/
-# generated from svn:ignore of 'tools/dev/'
-^tools/dev/mk_language_shell\.pl$
-^tools/dev/mk_language_shell\.pl/
# Local variables:
# mode: text
# buffer-read-only: t
View
4 config/auto/libffi.pm
@@ -54,7 +54,7 @@ sub runstep {
my $libffi_options_cflags = '';
my $libffi_options_libs = '';
my $libffi_options_linkflags = '';
-
+
if ($pkgconfig_exec) {
$libffi_options_linkflags = capture_output($pkgconfig_exec, 'libffi --libs-only-L');
chomp $libffi_options_linkflags;
@@ -70,7 +70,7 @@ sub runstep {
cc => $conf->data->get('cc'),
default => $libffi_options_libs . ' ' . $libffi_options_cflags,
} );
-
+
$conf->cc_gen('config/auto/libffi/test_c.in');
eval { $conf->cc_build( $libffi_options_cflags, $libffi_options_libs ) };
my $has_libffi = 0;
View
4 config/gen/libffi.pm
@@ -25,7 +25,7 @@ sub _init {
my %data;
$data{description} = q{Moving approriate NCI files into place};
-
+
return \%data;
}
@@ -39,7 +39,7 @@ sub runstep {
else {
}
- copy_if_diff( $nci_file, "src/pmc/nci.pmc" );
+ copy_if_diff( $nci_file, "src/pmc/nci.pmc" );
return 1;
}
View
211 config/gen/libffi/nci.pmc.in
@@ -25,169 +25,72 @@ The vtable functions for the native C call functions.
PARROT_IGNORABLE_RESULT
static nci_thunk_t /*@alt void@*/
build_func(PARROT_INTERP,
- ARGMOD(Parrot_NCI_attributes *nci_info))
+ ARGMOD(Parrot_NCI_attributes *nci))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
- FUNC_MODIFIES(*nci_info);
-
-static void pcc_params(PARROT_INTERP,
- ARGIN(STRING *sig),
- ARGMOD(Parrot_NCI_attributes *nci_info),
- size_t sig_length)
- __attribute__nonnull__(1)
- __attribute__nonnull__(2)
- __attribute__nonnull__(3)
- FUNC_MODIFIES(*nci_info);
+ FUNC_MODIFIES(*nci);
#define ASSERT_ARGS_build_func __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(nci_info))
-#define ASSERT_ARGS_pcc_params __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(sig) \
- , PARROT_ASSERT_ARG(nci_info))
+ , PARROT_ASSERT_ARG(nci))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
+/*
-static void
-pcc_params(PARROT_INTERP, ARGIN(STRING *sig), ARGMOD(Parrot_NCI_attributes *nci_info),
- size_t sig_length)
-{
- ASSERT_ARGS(pcc_params)
-
- /* NCI and PCC have a 1 to 1 mapping except an
- extra char in PCC for invocant and slurpy */
- size_t buf_length = sig_length + 2 + 1;
-
- /* avoid malloc churn on common signatures */
- char static_buf[16];
- char * const sig_buf = sig_length <= sizeof static_buf ?
- static_buf :
- (char *)mem_sys_allocate(buf_length);
-
- size_t j = 0;
- size_t i;
-
- for (i = 0; i < sig_length; ++i) {
- const INTVAL c = Parrot_str_indexed(interp, sig, i);
-
- PARROT_ASSERT(j < buf_length - 1);
-
- switch (c) {
- case (INTVAL)'0': /* null ptr or such - doesn't consume a reg */
- break;
- case (INTVAL)'f':
- case (INTVAL)'N':
- case (INTVAL)'d':
- sig_buf[j++] = 'N';
- break;
- case (INTVAL)'I': /* INTVAL */
- case (INTVAL)'l': /* long */
- case (INTVAL)'i': /* int */
- case (INTVAL)'s': /* short */
- case (INTVAL)'c': /* char */
- sig_buf[j++] = 'I';
- break;
- case (INTVAL)'S':
- case (INTVAL)'t': /* string, pass a cstring */
- sig_buf[j++] = 'S';
- break;
- case (INTVAL)'J': /* interpreter */
- break;
- case (INTVAL)'p': /* push pmc->data */
- case (INTVAL)'P': /* push PMC * */
- case (INTVAL)'V': /* push PMC * */
- case (INTVAL)'2':
- case (INTVAL)'3':
- case (INTVAL)'4':
- sig_buf[j++] = 'P';
- break;
- case (INTVAL)'v':
- /* null return */
- if (j == 0)
- sig_buf[j++] = '\0';
- break;
- case (INTVAL)'O': /* push PMC * invocant */
- sig_buf[j++] = 'P';
- sig_buf[j++] = 'i';
- break;
- case (INTVAL)'@': /* push PMC * slurpy */
- sig_buf[j++] = 'P';
- sig_buf[j++] = 's';
- break;
- case (INTVAL)'b': /* buffer (void*) pass Buffer_bufstart(SReg) */
- case (INTVAL)'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */
- sig_buf[j++] = 'S';
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL,
- EXCEPTION_JIT_ERROR,
- "Unknown param Signature %c\n", (char)c);
- break;
- }
- }
-
- PARROT_ASSERT(j < buf_length);
- sig_buf[j++] = '\0';
-
-
- nci_info->pcc_return_signature =
- Parrot_str_new(interp, sig_buf, 1);
+=item C<static nci_thunk_t build_func(PARROT_INTERP, Parrot_NCI_attributes
+*nci)>
- nci_info->pcc_params_signature = j ?
- Parrot_str_new(interp, sig_buf + 1, j - 1) :
- CONST_STRING(interp, "");
+Actually build the NCI thunk.
- if (sig_buf != static_buf)
- mem_sys_free(sig_buf);
-}
+=cut
-/* actually build the NCI thunk */
+*/
PARROT_IGNORABLE_RESULT
static nci_thunk_t
-build_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
+build_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci))
{
ASSERT_ARGS(build_func)
- STRING * const key = nci_info->signature;
- const size_t key_length = Parrot_str_byte_length(interp, key);
+ nci->signature = Parrot_nci_parse_signature(interp, nci->sig_str);
+ Parrot_nci_sig_to_pcc(interp, nci->signature,
+ &nci->pcc_params_signature,
+ &nci->pcc_return_signature);
- pcc_params(interp, key, nci_info, key_length);
-
- /* Arity is length of that string minus one (the return type). */
- nci_info->arity = key_length - 1;
+ /* Arity is length of the signature minus one (the return type). */
+ nci->arity = VTABLE_elements(interp, nci->signature) - 1;
/* Build call function. */
- nci_info->fb_info = build_call_func(interp, key);
- nci_info->func = F2DPTR(VTABLE_get_pointer(interp, nci_info->fb_info));
+ nci->fb_info = build_call_func(interp, nci->sig_str);
+ nci->func = F2DPTR(VTABLE_get_pointer(interp, nci->fb_info));
- return (nci_thunk_t)nci_info->func;
+ return (nci_thunk_t)nci->func;
}
pmclass NCI auto_attrs provides invokable {
/* NCI thunk handling attributes */
- ATTR STRING *signature; /* The signature. */
- ATTR void *func; /* Function pointer to call. */
- ATTR PMC *fb_info; /* Frame-builder info */
- ATTR void *orig_func; /* Function pointer
- * used to create func */
+ ATTR PMC *signature; /* parsed signature */
+ ATTR STRING *sig_str; /* signature string */
+ ATTR void *func; /* function pointer to call */
+ ATTR PMC *fb_info; /* frame-builder info */
+ ATTR void *orig_func; /* pointer to wrapped function */
+
/* Parrot Sub-ish attributes */
ATTR STRING *pcc_params_signature;
ATTR STRING *pcc_return_signature;
- ATTR INTVAL arity; /* Cached arity of the NCI. */
+ ATTR INTVAL arity;
/* MMD fields */
- ATTR STRING *long_signature; /* The full signature. */
- ATTR PMC *multi_sig; /* type tuple array (?) */
+ ATTR STRING *long_signature;
+ ATTR PMC *multi_sig;
/*
=item C<METHOD get_multisig()>
-Return the MMD signature PMC, if any or a Null PMC.
+Return the MMD signature PMC, if any or C<PMCNULL>.
=cut
@@ -203,20 +106,6 @@ Return the MMD signature PMC, if any or a Null PMC.
/*
-=item C<METHOD set_raw_nci_ptr(void *func)>
-
-Sets the specified function pointer and raw flag.
-
-=cut
-
-*/
-
- METHOD make_raw_nci(PMC *func) {
- VTABLE_set_pointer(interp, SELF, (void *)func);
- }
-
-/*
-
=item C<void init()>
Initializes the NCI with a C<NULL> function pointer.
@@ -226,11 +115,13 @@ Initializes the NCI with a C<NULL> function pointer.
*/
VTABLE void init() {
- /* Mark that we're not a raw NCI. */
- PObj_flag_CLEAR(private2, SELF);
PObj_custom_mark_SET(SELF);
}
+ VTABLE void *get_pointer() {
+ return PARROT_NCI(SELF)->orig_func;
+ }
+
/*
=item C<void set_pointer_keyed_str(STRING *key, void *func)>
@@ -241,15 +132,6 @@ Sets the specified function pointer and signature (C<*key>).
*/
- VTABLE void set_pointer(void *ptr) {
- SET_ATTR_orig_func(INTERP, SELF, ptr);
- PObj_flag_SET(private2, SELF);
- }
-
- VTABLE void *get_pointer() {
- return PARROT_NCI(SELF)->orig_func;
- }
-
VTABLE void set_pointer_keyed_str(STRING *key, void *func) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
@@ -260,12 +142,12 @@ Sets the specified function pointer and signature (C<*key>).
if (!PObj_constant_TEST(key)) {
char * const key_c = Parrot_str_to_cstring(INTERP, key);
const size_t key_length = Parrot_str_byte_length(interp, key);
- key = string_make(interp, key_c, key_length,
- NULL, PObj_constant_FLAG);
+ key = Parrot_str_new_init(interp, key_c, key_length,
+ Parrot_default_encoding_ptr, PObj_constant_FLAG);
Parrot_str_free_cstring(key_c);
}
- nci_info->signature = key;
+ nci_info->sig_str = key;
}
/*
@@ -281,12 +163,14 @@ Mark any referenced strings and PMCs.
if (PARROT_NCI(SELF)) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
+ Parrot_gc_mark_PMC_alive(interp, nci_info->signature);
Parrot_gc_mark_PMC_alive(interp, nci_info->fb_info);
- Parrot_gc_mark_STRING_alive(interp, nci_info->signature);
- Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
- Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
- Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig);
+
+ Parrot_gc_mark_STRING_alive(interp, nci_info->sig_str);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_return_signature);
}
}
@@ -316,10 +200,11 @@ Creates and returns a clone of the NCI.
nci_info_ret->fb_info = nci_info_self->fb_info;
nci_info_ret->orig_func = nci_info_self->orig_func;
nci_info_ret->signature = nci_info_self->signature;
+ nci_info_ret->sig_str = nci_info_self->sig_str;
nci_info_ret->pcc_params_signature = nci_info_self->pcc_params_signature;
nci_info_ret->pcc_return_signature = nci_info_self->pcc_params_signature;
nci_info_ret->arity = nci_info_self->arity;
- PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7);
+ PObj_get_FLAGS(ret) = PObj_get_FLAGS(SELF);
return ret;
}
@@ -359,9 +244,7 @@ class, the PMC arguments are shifted down.
PMC *cont;
GET_ATTR_orig_func(INTERP, SELF, orig_func);
- func = PObj_flag_TEST(private2, SELF)
- ? (nci_thunk_t) D2FPTR(orig_func)
- : (nci_thunk_t) D2FPTR(nci_info->func);
+ func = (nci_thunk_t)D2FPTR(nci_info->func);
GET_ATTR_fb_info(INTERP, SELF, fb_info);
@@ -462,10 +345,6 @@ Return the arity of the NCI (the number of arguments).
F<docs/pdds/pdd03_calling_conventions.pod>.
-=head1 HISTORY
-
-Initial revision by sean 2002/08/04.
-
=cut
*/
View
2  config/gen/makefiles/root.in
@@ -487,6 +487,7 @@ INTERP_O_FILES = \
src/multidispatch$(O) \
src/namespace$(O) \
src/nci/api$(O) \
+ src/nci/signatures$(O) \
src/nci/core_thunks$(O) \
#IF(has_extra_nci_thunks): src/nci/extra_thunks$(O) \
src/oo$(O) \
@@ -694,6 +695,7 @@ STR_FILES = \
src/nci/api.str \
src/nci/core_thunks.str \
#IF(has_extra_nci_thunks): src/nci/extra_thunks.str \
+ src/nci/signatures.str \
src/packfile.str \
src/packfile/pf_items.str \
src/pmc.str \
View
60 include/parrot/nci.h
@@ -19,6 +19,36 @@ typedef PMC *(*nci_fb_func_t)(PARROT_INTERP, PMC *user_data, STRING *signature);
typedef void (*nci_thunk_t)(PARROT_INTERP, PMC *, PMC *);
typedef void (*native_pcc_method_t)(PARROT_INTERP);
+typedef enum {
+ enum_nci_sig_void,
+ enum_nci_sig_null,
+ enum_nci_sig_interp,
+
+ enum_nci_sig_float,
+ enum_nci_sig_double,
+ enum_nci_sig_numval,
+
+ enum_nci_sig_char,
+ enum_nci_sig_short,
+ enum_nci_sig_int,
+ enum_nci_sig_long,
+ enum_nci_sig_intval,
+
+ enum_nci_sig_string,
+ enum_nci_sig_cstring,
+ enum_nci_sig_cstringref,
+ enum_nci_sig_bufref,
+
+ enum_nci_sig_ptr,
+ enum_nci_sig_pmc,
+ enum_nci_sig_pmcinv,
+ enum_nci_sig_pmcslurp,
+ enum_nci_sig_ptrref,
+ enum_nci_sig_shortref,
+ enum_nci_sig_intref,
+ enum_nci_sig_longref
+} nci_sig_elem_t;
+
void Parrot_nci_load_core_thunks(PARROT_INTERP);
void Parrot_nci_load_extra_thunks(PARROT_INTERP);
@@ -36,6 +66,36 @@ PMC * build_call_func(PARROT_INTERP, ARGIN(STRING *signature))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: src/nci/api.c */
+/* HEADERIZER BEGIN: src/nci/signatures.c */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
+
+PARROT_CANNOT_RETURN_NULL
+PMC * Parrot_nci_parse_signature(PARROT_INTERP, ARGIN(STRING *sig_str))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
+void Parrot_nci_sig_to_pcc(PARROT_INTERP,
+ ARGIN(PMC *sig_pmc),
+ ARGOUT(STRING **params_sig),
+ ARGOUT(STRING **ret_sig))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3)
+ __attribute__nonnull__(4)
+ FUNC_MODIFIES(*params_sig)
+ FUNC_MODIFIES(*ret_sig);
+
+#define ASSERT_ARGS_Parrot_nci_parse_signature __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(sig_str))
+#define ASSERT_ARGS_Parrot_nci_sig_to_pcc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(sig_pmc) \
+ , PARROT_ASSERT_ARG(params_sig) \
+ , PARROT_ASSERT_ARG(ret_sig))
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
+/* HEADERIZER END: src/nci/signatures.c */
+
#endif /* PARROT_NCI_H_GUARD */
/*
View
2  lib/Parrot/Configure/Options/Conf.pm
@@ -101,7 +101,7 @@ External Library Options:
--without-gettext Build parrot without gettext support
--without-gmp Build parrot without GMP support
- --without-libffi Build parrot without libffi support
+ --without-libffi Build parrot without libffi support
--without-opengl Build parrot without OpenGL support (GL/GLU/GLUT)
--without-readline Build parrot without readline support
--without-pcre Build parrot without pcre support
View
4 lib/Parrot/Configure/Step/List.pm
@@ -61,13 +61,13 @@ my @steps = qw(
auto::ctags
auto::revision
auto::icu
- auto::libffi
+ auto::libffi
gen::config_h
gen::core_pmcs
gen::opengl
gen::makefiles
gen::platform
- gen::libffi
+ gen::libffi
gen::config_pm
);
View
256 src/nci/signatures.c
@@ -0,0 +1,256 @@
+/* nci/signatures.c
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/nci/signatures.c - Native Call Interface signature processing routines
+
+=head1 DESCRIPTION
+
+This file implements functionality for parsing NCI signatures and generating PCC
+signatures.
+
+=head2 Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+#include "parrot/nci.h"
+#include "signatures.str"
+
+/* HEADERIZER HFILE: include/parrot/nci.h */
+
+/*
+
+=item C<PMC * Parrot_nci_parse_signature(PARROT_INTERP, STRING *sig_str)>
+
+Parse a signature string to a NCI signature PMC.
+
+=cut
+
+*/
+
+PARROT_CANNOT_RETURN_NULL
+PMC *
+Parrot_nci_parse_signature(PARROT_INTERP, ARGIN(STRING *sig_str))
+{
+ ASSERT_ARGS(Parrot_nci_parse_signature)
+
+ const size_t sig_length = Parrot_str_byte_length(interp, sig_str);
+
+ size_t j = 0;
+ size_t i;
+
+ PMC *sig_pmc = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
+
+ for (i = 0; i < sig_length; ++i) {
+ const INTVAL c = Parrot_str_indexed(interp, sig_str, i);
+ nci_sig_elem_t e;
+
+ PARROT_ASSERT(c == (char)c);
+
+ switch ((char)c) {
+ case '0': /* null ptr or such - doesn't consume a reg */
+ e = enum_nci_sig_void;
+ break;
+
+ case 'f':
+ e = enum_nci_sig_float;
+ break;
+ case 'd':
+ e = enum_nci_sig_double;
+ break;
+ case 'N':
+ e = enum_nci_sig_numval;
+ break;
+
+ case 'c': /* char */
+ e = enum_nci_sig_char;
+ break;
+ case 's': /* short */
+ e = enum_nci_sig_short;
+ break;
+ case 'i': /* int */
+ e = enum_nci_sig_int;
+ break;
+ case 'l': /* long */
+ e = enum_nci_sig_long;
+ break;
+ case 'I': /* INTVAL */
+ e = enum_nci_sig_intval;
+ break;
+
+ case 'S':
+ e = enum_nci_sig_string;
+ break;
+ case 't': /* string, pass a cstring */
+ e = enum_nci_sig_cstring;
+ break;
+
+ case 'J': /* interpreter */
+ e = enum_nci_sig_interp;
+ break;
+
+ case 'p': /* push pmc->data */
+ e = enum_nci_sig_ptr;
+ break;
+ case 'P': /* push PMC * */
+ e = enum_nci_sig_pmc;
+ break;
+ case 'V': /* push PMC * */
+ e = enum_nci_sig_ptrref;
+ break;
+ case '2':
+ e = enum_nci_sig_shortref;
+ break;
+ case '3':
+ e = enum_nci_sig_intref;
+ break;
+ case '4':
+ e = enum_nci_sig_longref;
+ break;
+
+ case 'O': /* push PMC * invocant */
+ e = enum_nci_sig_pmcinv;
+ break;
+ case '@': /* push PMC * slurpy */
+ e = enum_nci_sig_pmcslurp;
+ break;
+
+ case 'b': /* buffer (void*) pass Buffer_bufstart(SReg) */
+ e = enum_nci_sig_cstringref;
+ break;
+ case 'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */
+ e = enum_nci_sig_bufref;
+ break;
+
+ case 'v':
+ e = enum_nci_sig_void;
+ break;
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL,
+ EXCEPTION_JIT_ERROR,
+ "Unknown param Signature %c\n", (char)c);
+ break;
+ }
+
+ VTABLE_push_integer(interp, sig_pmc, e);
+ }
+
+ return sig_pmc;
+}
+
+
+/*
+
+=item C<void Parrot_nci_sig_to_pcc(PARROT_INTERP, PMC *sig_pmc, STRING
+**params_sig, STRING **ret_sig)>
+
+Determine the PCC signatures for a given NCI signature PMC.
+
+=cut
+
+*/
+
+void
+Parrot_nci_sig_to_pcc(PARROT_INTERP, ARGIN(PMC *sig_pmc), ARGOUT(STRING **params_sig),
+ ARGOUT(STRING **ret_sig))
+{
+ ASSERT_ARGS(Parrot_nci_sig_to_pcc)
+
+ size_t sig_len = VTABLE_elements(interp, sig_pmc);
+
+ /* PCC sigs are 1 char long except for array slurpy, named slurpy (not possible with NCI),
+ and invocant */
+ size_t buf_len = sig_len + 2 + 1;
+
+ /* avoid malloc churn on common signatures */
+ char static_buf[16];
+ char * const sig_buf = sig_len <= sizeof static_buf ?
+ static_buf :
+ (char *)mem_sys_allocate(buf_len);
+
+ size_t i, j;
+
+ for (i = 0, j = 0; i < sig_len; i++) {
+ const nci_sig_elem_t e = (nci_sig_elem_t)VTABLE_get_integer_keyed_int(interp, sig_pmc, i);
+
+ PARROT_ASSERT(j < buf_len - 1);
+
+ switch (e) {
+ case enum_nci_sig_void:
+ /* null return */
+ if (j == 0)
+ sig_buf[j++] = '\0';
+ break;
+ case enum_nci_sig_null:
+ case enum_nci_sig_interp:
+ break;
+ case enum_nci_sig_float:
+ case enum_nci_sig_double:
+ case enum_nci_sig_numval:
+ sig_buf[j++] = 'N';
+ break;
+ case enum_nci_sig_char:
+ case enum_nci_sig_short:
+ case enum_nci_sig_int:
+ case enum_nci_sig_long:
+ case enum_nci_sig_intval:
+ sig_buf[j++] = 'I';
+ break;
+ case enum_nci_sig_string:
+ case enum_nci_sig_cstring:
+ case enum_nci_sig_cstringref:
+ case enum_nci_sig_bufref:
+ sig_buf[j++] = 'S';
+ break;
+ case enum_nci_sig_ptr:
+ case enum_nci_sig_pmc:
+ case enum_nci_sig_ptrref:
+ case enum_nci_sig_shortref:
+ case enum_nci_sig_intref:
+ case enum_nci_sig_longref:
+ sig_buf[j++] = 'P';
+ break;
+ case enum_nci_sig_pmcinv:
+ sig_buf[j++] = 'P';
+ sig_buf[j++] = 'i';
+ break;
+ case enum_nci_sig_pmcslurp:
+ sig_buf[j++] = 'P';
+ sig_buf[j++] = 's';
+ break;
+ }
+ }
+
+ PARROT_ASSERT(j < buf_len);
+ sig_buf[j++] = '\0';
+
+ *ret_sig = Parrot_str_new(interp, sig_buf, 1);
+ *params_sig = j ?
+ Parrot_str_new(interp, &sig_buf[1], j - 1) :
+ CONST_STRING(interp, "");
+
+ if (sig_buf != static_buf)
+ mem_sys_free(sig_buf);
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
View
1,268 src/pmc/nci.pmc
@@ -18,9 +18,6 @@ The vtable functions for the native C call functions.
*/
-/* Cheat with this include, for whatever reason the space is required */
-# include "ffi.h"
-
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
@@ -28,800 +25,72 @@ The vtable functions for the native C call functions.
PARROT_IGNORABLE_RESULT
static nci_thunk_t /*@alt void@*/
build_func(PARROT_INTERP,
- ARGMOD(Parrot_NCI_attributes *nci_info))
- __attribute__nonnull__(1)
- __attribute__nonnull__(2)
- FUNC_MODIFIES(*nci_info);
-
-static void pcc_params(PARROT_INTERP,
- ARGIN(STRING *sig),
- ARGMOD(Parrot_NCI_attributes *nci_info),
- size_t sig_length)
+ ARGMOD(Parrot_NCI_attributes *nci))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
- __attribute__nonnull__(3)
- FUNC_MODIFIES(*nci_info);
+ FUNC_MODIFIES(*nci);
#define ASSERT_ARGS_build_func __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(nci_info))
-#define ASSERT_ARGS_pcc_params __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(sig) \
- , PARROT_ASSERT_ARG(nci_info))
+ , PARROT_ASSERT_ARG(nci))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
-static
-INTVAL
-parse_sig(PARROT_INTERP, STRING *sig, size_t sig_length, Parrot_NCI_attributes *nci_info);
-
-static
-size_t
-parse_return(PARROT_INTERP, STRING* sig, size_t sig_length,
- Parrot_NCI_attributes * nci_info, ffi_type **return_type);
-
-static
-size_t
-parse_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
- Parrot_NCI_attributes *nci_info, ffi_type ***arg_types);
-
-static
-size_t
-parse_identifier(PARROT_INTERP,
- STRING* sig, size_t start, size_t end,
- ffi_type** sig_obj,
- char* pmc_type, size_t *pmc_count,
- char* translation, size_t *translation_length);
-
-static
-size_t
-parse_structure(PARROT_INTERP, STRING* sig, size_t start, size_t end,
- ffi_type** sig_obj, char* pmc_type);
-
-static
-INTVAL
-parse_prefix(INTVAL c);
-
-static
-size_t
-structure_length(PARROT_INTERP, STRING* sig, size_t start, size_t end);
-
-static
-size_t
-count_args(PARROT_INTERP, STRING* sig, size_t start, size_t end);
-
-static
-size_t
-find_matching(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
- INTVAL start_character, INTVAL end_character);
-
-#define IS_DIGIT(x) (((x) == '0') || ((x) == '1') || ((x) == '2') || ((x) == '3') \
- || ((x) == '4') || ((x) == '5') || ((x) == '6') || ((x) == '7') \
- || ((x) == '8') || ((x) == '9'))
-
-#define IS_PREFIX(x) (((x) == '*') || ((x) == 'u'))
-
-#define IS_OLD_TYPE(x) (((x) == 'P') || ((x) == 'J') || ((x) == 'N') || ((x) == 'S') \
- || ((x) == 'O') || ((x) == '@') || ((x) == 'B') || ((x) == 'p') \
- || ((x) == '2') || ((x) == '3') || ((x) == '4') || ((x) == 'U') \
- || ((x) == 'V'))
-
-#define IS_TYPE(x) (((x) == 'i') || ((x) == 'v') || ((x) == 'l') || ((x) == 't') \
- || ((x) == 'c') || ((x) == 'b') || ((x) == 'f') || ((x) == 'd') \
- || ((x) == 's') || IS_OLD_TYPE(x))
-
-#define IS_POSTFIX(x) ((x) == '{') /* || IS_DIGIT(x)) */
-#define IS_INFIX(x) ((x) == '|')
-#define IS_START_CIRCUMFIX(x) ((x) == '(')
-#define IS_END_CIRCUMFIX(x) ((x) == ')')
-#define IS_NOT_END_CIRCUMFIX(x) ((x) != ')')
-
-#define PREFIX_POINTER (1<<0)
-#define PREFIX_SIGNED ( 0)
-#define PREFIX_UNSIGNED (1<<1)
-#define PREFIX_NATIVE (1<<2)
-
-typedef struct pmc_holder_t {
- PMC* p;
- union {
- INTVAL* ival;
- void** pval;
- };
-} pmc_holder_t;
-
-/*
-
-=item C<static INTVAL parse_sig(PARROT_INTERP, STRING *sig,
- size_t sig_length, Parrot_NCI_attributes *nci_info)>
-
-Parse a full signature. All signatures should contain a return type and a list of
-arguments. "vv" Would be the shortest "void fn(void)" signature you can legally make.
-
-See C<parse_return> and C<parse_args> to see how the signature is broken down.
-
-=cut
-
-*/
-
-static INTVAL
-parse_sig(PARROT_INTERP, STRING *sig, size_t sig_length, Parrot_NCI_attributes *nci_info) {
- ffi_cif cif;
- ffi_type *return_type;
- ffi_type **arg_types;
-
- if (sig_length) {
- size_t i = parse_return(interp, sig, sig_length, nci_info, &return_type);
- if (i < sig_length)
- parse_args(interp, sig, i, sig_length, nci_info, &arg_types);
- else {
- arg_types = mem_internal_allocate_n_zeroed_typed(1, ffi_type*);
- arg_types[0] = &ffi_type_void;
- nci_info->pcc_params_signature = string_make(interp, "", 1, NULL, 0);
- nci_info->arg_translation = NULL;
- nci_info->arity = 0;
- }
- }
- else {
- arg_types = mem_internal_allocate_n_zeroed_typed(1, ffi_type*);
- arg_types[0] = &ffi_type_void;
- return_type = &ffi_type_void;
- nci_info->pcc_params_signature = string_make(interp, "", 1, NULL, 0);
- nci_info->arg_translation = NULL;
- nci_info->arity = 0;
- }
-
- if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
- nci_info->arity, return_type, arg_types) == FFI_OK) {
- nci_info->cif = (void*)mem_internal_allocate_typed(ffi_cif);
- memcpy(nci_info->cif, &cif, sizeof (ffi_cif));
- nci_info->arg_types = arg_types;
-
- return 1;
- }
-
- if (arg_types) {
- mem_sys_free(arg_types);
- }
-
- /* TODO: Throw Error here. */
- printf("Bad signature\n");
-
- return 0;
-}
-
-/*
-
-=item C<static size_t parse_return(PARROT_INTERP, STRING *sig, size_t sig_length,
- Parrot_NCI_attributes* nci_info, ffi_type **return_type)>
-
-Parses the return type. This assumes the first identifier is the return type.
-
-See C<parse_identifier> to see how a single identifer is parsed.
-
-=cut
-
-*/
-
-static size_t
-parse_return(PARROT_INTERP, STRING *sig, size_t sig_length,
- Parrot_NCI_attributes* nci_info, ffi_type **return_type) {
- char *t = mem_allocate_n_zeroed_typed(2, char);
- size_t j = 0, k = 0;
- /* Should be 1 character plus a NULL" */
- char * result_sig = mem_allocate_n_zeroed_typed(2, char);
- size_t result_length = parse_identifier(interp,
- sig, 0, sig_length,
- return_type,
- result_sig, &j,
- t, &k);
-
- nci_info->pcc_return_signature = string_make(interp, result_sig, 2, NULL, 0);
- nci_info->return_translation = (void*)t;
- mem_sys_free(result_sig);
- return result_length;
-}
-
-/*
-
-=item C<static size_t parse_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
- Parrot_NCI_attributes *nci_info, ffi_type ***arg_types)>
-
-Parses the signatures arguments. It takes an offset to know where to start looking.
-This should fill out a list of C<ffi_type*> args.
-
-See C<parse_identifier> to see how a single identifer is parsed.
-
-=cut
-
-*/
-
-static size_t
-parse_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
- Parrot_NCI_attributes *nci_info, ffi_type ***arg_types) {
- size_t i = start;
- size_t arg_count = 0;
- size_t argc = count_args(interp, sig, start, sig_length);
- char* parrot_types = mem_allocate_n_zeroed_typed(argc + 1, char);
- size_t parrot_types_length = 0;
- char* translation_types = mem_allocate_n_zeroed_typed(argc + 1, char);
- size_t translation_length = 0;
-
- *arg_types = mem_internal_allocate_n_zeroed_typed(argc + 1, ffi_type*);
-
- while (i < sig_length) {
- ffi_type *ident;
- i = parse_identifier(interp,
- sig, i, sig_length,
- &ident,
- parrot_types, &parrot_types_length,
- translation_types, &translation_length);
- (*arg_types)[arg_count] = ident;
- arg_count++;
- }
-
- nci_info->pcc_params_signature = string_make(interp, parrot_types,
- strlen(parrot_types), NULL, 0);
- nci_info->arg_translation = translation_types;
- nci_info->arity = arg_count;
-
- mem_sys_free(parrot_types);
-
- return i;
-}
-
-/*
-
-=item C<static size_t parse_identifier(PARROT_INTERP, STRING *sig, size_t start,
- size_t sig_length, ffi_type **type_obj,
- char **type, size_t *pmc_count,
- char **translation, size_t *translation_count)>
-
-Parse an identifier and build its representation used for PCC and any translations
-that are needed.
-
-An example of a transation is "t", it will take a STRING* and convert it to a
-char* for the function call.
-
-=cut
-
-*/
-
-static size_t
-parse_identifier(PARROT_INTERP,
- STRING *sig, size_t start, size_t sig_length,
- ffi_type **type_obj,
- char *type, size_t *pmc_count,
- char *translation, size_t *translation_count) {
- size_t i = start;
- INTVAL done = 0;
-
- while (!done && i < sig_length) {
- INTVAL c = Parrot_str_indexed(interp, sig, i);
- int prefix = 0;
- while (IS_PREFIX(c)) {
- prefix |= parse_prefix(c);
- i++;
-
- if (i < sig_length)
- c = Parrot_str_indexed(interp, sig, i);
- else
- return i;
- }
-
- if (IS_START_CIRCUMFIX(c)) {
- i = parse_structure(interp, sig, i + 1, sig_length, type_obj, type);
- i++;
-
- if (i < sig_length)
- c = Parrot_str_indexed(interp, sig, i);
- else
- return i;
- }
- else if (IS_TYPE(c)) {
- if (prefix & PREFIX_POINTER) {
- *type_obj = &ffi_type_pointer;
- continue;
- }
- translation[(*translation_count)++] = ' ';
- switch (c) {
- case (INTVAL)' ':
- case (INTVAL)'0': /* null ptr or such - doesn't consume a reg */
- break;
- case (INTVAL)'c':
- translation[(*translation_count) - 1] = 'c';
- type[(*pmc_count)++] = 'I';
- if (prefix & PREFIX_UNSIGNED) {
- *type_obj = &ffi_type_uchar;
- }
- else {
- *type_obj = &ffi_type_schar;
- }
- break;
- case (INTVAL)'B':
- translation[(*translation_count) - 1] = 'B';
- type[(*pmc_count)++] = 'S';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'b':
- translation[(*translation_count) - 1] = 'b';
- type[(*pmc_count)++] = 'S';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'s':
- translation[(*translation_count) - 1] = 's';
- type[(*pmc_count)++] = 'I';
- if (prefix & PREFIX_UNSIGNED) {
- *type_obj = &ffi_type_ushort;
- }
- else {
- *type_obj = &ffi_type_sshort;
- }
- break;
- case (INTVAL)'I': /* INTVAL */
- case (INTVAL)'i':
- translation[(*translation_count) - 1] = 'i';
- type[(*pmc_count)++] = 'I';
- if (prefix & PREFIX_UNSIGNED) {
- *type_obj = &ffi_type_uint;
- }
- else {
- *type_obj = &ffi_type_sint;
- }
- break;
- case (INTVAL)'l':
- translation[(*translation_count) - 1] = 'l';
- type[(*pmc_count)++] = 'I';
- if (prefix & PREFIX_UNSIGNED) {
- *type_obj = &ffi_type_ulong;
- }
- else {
- *type_obj = &ffi_type_slong;
- }
- break;
- case (INTVAL)'q':
- translation[(*translation_count) - 1] = 'q';
- type[(*pmc_count)++] = 'I';
- if (prefix & PREFIX_UNSIGNED) {
- *type_obj = &ffi_type_uint64;
- }
- else {
- *type_obj = &ffi_type_sint64;
- }
- break;
- case (INTVAL)'J': /* interpreter */
- translation[(*translation_count) - 1] = 'J';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'p': /* push pmc->data */
- translation[(*translation_count) - 1] = 'p';
- type[(*pmc_count)++] = 'P';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'2':
- translation[(*translation_count) - 1] = '2';
- type[(*pmc_count)++] = 'P';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'3':
- translation[(*translation_count) - 1] = '3';
- type[(*pmc_count)++] = 'P';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'4':
- translation[(*translation_count) - 1] = '4';
- type[(*pmc_count)++] = 'P';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'P': /* push PMC * */
- translation[(*translation_count) - 1] = 'P';
- type[(*pmc_count)++] = 'P';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'V': /* push PMC * */
- translation[(*translation_count) - 1] = 'V';
- type[(*pmc_count)++] = 'P';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'S':
- type[(*pmc_count)++] = 'S';
- *type_obj = &ffi_type_pointer;
- case (INTVAL)'t':
- translation[(*translation_count) - 1] = 't';
- type[(*pmc_count)++] = 'S';
- *type_obj = &ffi_type_pointer;
- break;
- case (INTVAL)'v':
- type[(*pmc_count)++] = 'v';
- *type_obj = &ffi_type_void;
- break;
-#if (DOUBLE_SIZE == 4) /* FLOATVAL is a float */
- case (INTVAL)'N':
-#endif
- case (INTVAL)'f':
- translation[(*translation_count) - 1] = 'f';
- type[(*pmc_count)++] = 'N';
- *type_obj = &ffi_type_float;
- break;
-#if (DOUBLE_SIZE == 8) /* FLOATVAL is a double */
- case (INTVAL)'N':
-#endif
- case (INTVAL)'d':
- translation[(*translation_count) - 1] = 'd';
- type[(*pmc_count)++] = 'N';
- *type_obj = &ffi_type_double;
- break;
-#if (DOUBLE_SIZE > 8) /* FLOATVAL is a long double */
- case (INTVAL)'N':
-#endif
- case (INTVAL)'D':
- translation[(*translation_count) - 1] = 'D';
- type[(*pmc_count)++] = 'N';
- *type_obj = &ffi_type_longdouble;
- break;
- case (INTVAL)'O': /* push PMC * invocant */
- *type_obj = &ffi_type_pointer;
- type[(*pmc_count)++] = 'P';
- type[(*pmc_count)++] = 'i';
- break;
- case (INTVAL)'@': /* push PMC * slurpy */
- *type_obj = &ffi_type_pointer;
- type[(*pmc_count)++] = 'P';
- type[(*pmc_count)++] = 's';
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL,
- EXCEPTION_JIT_ERROR,
- "Unknown param Signature %c\n", (char)c);
- break;
- }
- i++;
-
- if (i < sig_length)
- c = Parrot_str_indexed(interp, sig, i);
- else
- return i;
- }
- else {
- Parrot_ex_throw_from_c_args(interp, NULL,
- EXCEPTION_JIT_ERROR,
- "Unknown param Signature %c\n", (char)c);
- }
-
- /*
- * Parse postfix ops
- * TODO: Parse postfix ops, currently I skip them.
- */
- while (IS_POSTFIX(c)) {
- i++;
- if (i < sig_length)
- c = Parrot_str_indexed(interp, sig, i);
- else
- return i;
- }
-
- if ((i < sig_length) && (c == (INTVAL)'|')) {
- /* Its a union, parse it special. */
- }
- else {
- done = 1;
- }
- }
-
- return i;
-}
-
-/*
-
-=item C<static INTVAL parse_prefix(INTVAL c)>
-
-Parse a prefix character.
-
-=cut
-
-*/
-
-static INTVAL
-parse_prefix(INTVAL c) {
- switch (c) {
- case '*':
- return PREFIX_POINTER;
- break;
- case 'u':
- return PREFIX_UNSIGNED;
- break;
- default:
- return 0;
- break;
- }
-
- return 0;
-}
-
/*
-=item C<static size_t parse_structure(PARROT_INTERP, STRING* sig, size_t start,
- size_t sig_length, ffi_type **type_obj, char* pmc_type)>
+=item C<static nci_thunk_t build_func(PARROT_INTERP, Parrot_NCI_attributes
+*nci)>
-Parses a stucture.
-TODO: This should auto inflate to an UnmanagedStruct or a ManagedStruct in the future.
+Actually build the NCI thunk.
=cut
*/
-static size_t
-parse_structure(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
- ffi_type **type_obj, char* pmc_type) {
- size_t i = start;
- size_t struct_len = structure_length(interp, sig, start, sig_length);
- size_t element_counter = 0;
- INTVAL c;
-
- *type_obj = (ffi_type*)mem_internal_allocate_typed(ffi_type*);
- (*type_obj)->elements = mem_internal_allocate_n_zeroed_typed(struct_len + 1, ffi_type*);
-
- (*type_obj)->size = (*type_obj)->alignment = 0;
- (*type_obj)->type = FFI_TYPE_STRUCT;
-
- c = Parrot_str_indexed(interp, sig, i);
- while (i < sig_length && IS_NOT_END_CIRCUMFIX(c)) {
- i = parse_identifier(interp, sig, i, sig_length,
- &(*type_obj)->elements[element_counter],
- NULL, 0, NULL, 0);
- element_counter++;
- c = Parrot_str_indexed(interp, sig, i);
- }
-
- (*type_obj)->elements[struct_len] = NULL;
-
- return i;
-}
-
-/*
-
-=item C<static size_t structure_length(PARROT_INTERP, STRING* sig,
- size_t start, size_t sig_length)>
-
-Calculates the number of items in a stucture for size purposes.
-
-=cut
-
-*/
-
-static size_t
-structure_length(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length) {
- size_t len = 0;
- size_t i = start;
- INTVAL depth = 0;
- INTVAL c = Parrot_str_indexed(interp, sig, i);
- while (i < sig_length && depth != -1) {
- if (IS_START_CIRCUMFIX(c)) depth++;
- else if (IS_END_CIRCUMFIX(c)) depth--;
- else if (depth == 0 && (IS_TYPE(c))) len++;
- i++;
- c = Parrot_str_indexed(interp, sig, i);
- }
-
- return len;
-}
-
-/*
-
-=item C<static size_t find_matching(PARROT_INTERP, STRING* sig, size_t start,
- size_t sig_length, INTVAL start_character, INTVAL end_character)>
-
-Find matching symbols, used for finding the start and stop of a stucture, it is
-also recursive to handle structures inside of structures.
-
-=cut
-
-*/
-
-static size_t
-find_matching(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length,
- INTVAL start_character, INTVAL end_character) {
- size_t i = start;
- INTVAL c = Parrot_str_indexed(interp, sig, i);
- while (i < sig_length && c != end_character) {
- if (c == start_character)
- i = find_matching(interp, sig, i, sig_length, start_character, end_character);
- i++;
- c = Parrot_str_indexed(interp, sig, i);
- }
-
- return i;
-}
-
-/*
-
-=item C<size_t count_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length)>
-
-Counts the number of arguments from a given starting point. It only counts
-identiers, not prefix, infix or postfix modifiers. Structures are considered as
-1 item in most cases.
-
-=cut
-
-*/
-
-static size_t
-count_args(PARROT_INTERP, STRING* sig, size_t start, size_t sig_length) {
- size_t length = 0;
- size_t i = start;
-
- while (i < sig_length) {
- const INTVAL c = Parrot_str_indexed(interp, sig, i);
- if (IS_START_CIRCUMFIX(c)) {
- i = find_matching(interp, sig, i + 1, sig_length, '(', ')');
- length++;
- }
- else if (IS_TYPE(c)) {
- length++;
- }
- i++;
- }
-
- return length;
-}
-
-static void
-pcc_params(PARROT_INTERP, ARGIN(STRING *sig), ARGMOD(Parrot_NCI_attributes *nci_info),
- size_t sig_length)
-{
- ASSERT_ARGS(pcc_params)
-
- /* NCI and PCC have a 1 to 1 mapping except an
- extra char in PCC for invocant and slurpy */
- size_t buf_length = sig_length + 2 + 1;
-
- /* avoid malloc churn on common signatures */
- char static_buf[16];
- char * const sig_buf = sig_length <= sizeof static_buf ?
- static_buf :
- (char *)mem_sys_allocate(buf_length);
-
- size_t j = 0;
- size_t i;
-
- for (i = 0; i < sig_length; ++i) {
- const INTVAL c = Parrot_str_indexed(interp, sig, i);
-
- PARROT_ASSERT(j < buf_length - 1);
-
- switch (c) {
- case (INTVAL)'0': /* null ptr or such - doesn't consume a reg */
- break;
- case (INTVAL)'f':
- case (INTVAL)'N':
- case (INTVAL)'d':
- sig_buf[j++] = 'N';
- break;
- case (INTVAL)'I': /* INTVAL */
- case (INTVAL)'l': /* long */
- case (INTVAL)'i': /* int */
- case (INTVAL)'s': /* short */
- case (INTVAL)'c': /* char */
- sig_buf[j++] = 'I';
- break;
- case (INTVAL)'S':
- case (INTVAL)'t': /* string, pass a cstring */
- sig_buf[j++] = 'S';
- break;
- case (INTVAL)'J': /* interpreter */
- break;
- case (INTVAL)'p': /* push pmc->data */
- case (INTVAL)'P': /* push PMC * */
- case (INTVAL)'V': /* push PMC * */
- case (INTVAL)'2':
- case (INTVAL)'3':
- case (INTVAL)'4':
- sig_buf[j++] = 'P';
- break;
- case (INTVAL)'v':
- /* null return */
- if (j == 0)
- sig_buf[j++] = '\0';
- break;
- case (INTVAL)'O': /* push PMC * invocant */
- sig_buf[j++] = 'P';
- sig_buf[j++] = 'i';
- break;
- case (INTVAL)'@': /* push PMC * slurpy */
- sig_buf[j++] = 'P';
- sig_buf[j++] = 's';
- break;
- case (INTVAL)'b': /* buffer (void*) pass Buffer_bufstart(SReg) */
- case (INTVAL)'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */
- sig_buf[j++] = 'S';
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL,
- EXCEPTION_JIT_ERROR,
- "Unknown param Signature %c\n", (char)c);
- break;
- }
- }
-
- PARROT_ASSERT(j < buf_length);
- sig_buf[j++] = '\0';
-
-
- nci_info->pcc_return_signature =
- Parrot_str_new(interp, sig_buf, 1);
-
- nci_info->pcc_params_signature = j ?
- Parrot_str_new(interp, sig_buf + 1, j - 1) :
- CONST_STRING(interp, "");
-
- if (sig_buf != static_buf)
- mem_sys_free(sig_buf);
-}
-
-PARROT_IGNORABLE_RESULT
-static ffi_cif*
-build_libffi_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
-{
- ASSERT_ARGS(build_func)
-
- STRING * const key = nci_info->signature;
- const size_t key_length = Parrot_str_byte_length(interp, key);
-
- INTVAL r = parse_sig(interp, nci_info->signature, key_length, nci_info);
-
- return (ffi_cif*)nci_info->cif;
-}
-
-/* actually build the NCI thunk */
-
PARROT_IGNORABLE_RESULT
static nci_thunk_t
-build_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci_info))
+build_func(PARROT_INTERP, ARGMOD(Parrot_NCI_attributes *nci))
{
ASSERT_ARGS(build_func)
- STRING * const key = nci_info->signature;
- const size_t key_length = Parrot_str_byte_length(interp, key);
-
- pcc_params(interp, key, nci_info, key_length);
+ nci->signature = Parrot_nci_parse_signature(interp, nci->sig_str);
+ Parrot_nci_sig_to_pcc(interp, nci->signature,
+ &nci->pcc_params_signature,
+ &nci->pcc_return_signature);
- /* Arity is length of that string minus one (the return type). */
- nci_info->arity = key_length - 1;
+ /* Arity is length of the signature minus one (the return type). */
+ nci->arity = VTABLE_elements(interp, nci->signature) - 1;
/* Build call function. */
- nci_info->fb_info = build_call_func(interp, key);
- nci_info->func = F2DPTR(VTABLE_get_pointer(interp, nci_info->fb_info));
+ nci->fb_info = build_call_func(interp, nci->sig_str);
+ nci->func = F2DPTR(VTABLE_get_pointer(interp, nci->fb_info));
- return (nci_thunk_t)nci_info->func;
+ return (nci_thunk_t)nci->func;
}
pmclass NCI auto_attrs provides invokable {
/* NCI thunk handling attributes */
- /* NCI thunk handling attributes */
- ATTR STRING *signature; /* The signature. */
- ATTR void *func; /* Function pointer to call. */
- ATTR void *orig_func;
- ATTR PMC *fb_info; /* Frame-builder info */
- ATTR void *cif; /* Function interface */
- ATTR void *arg_types; /* Used for building the libffi call interface */
+ ATTR PMC *signature; /* parsed signature */
+ ATTR STRING *sig_str; /* signature string */
+ ATTR void *func; /* function pointer to call */
+ ATTR PMC *fb_info; /* frame-builder info */
+ ATTR void *orig_func; /* pointer to wrapped function */
/* Parrot Sub-ish attributes */
ATTR STRING *pcc_params_signature;
ATTR STRING *pcc_return_signature;
- ATTR void *arg_translation;
- ATTR void *return_translation;
- ATTR INTVAL arity; /* Cached arity of the NCI. */
+ ATTR INTVAL arity;
/* MMD fields */
- ATTR STRING *long_signature; /* The full signature. */
- ATTR PMC *multi_sig; /* type tuple array (?) */
+ ATTR STRING *long_signature;
+ ATTR PMC *multi_sig;
/*
=item C<METHOD get_multisig()>
-Return the MMD signature PMC, if any or a Null PMC.
+Return the MMD signature PMC, if any or C<PMCNULL>.
=cut
@@ -837,20 +106,6 @@ Return the MMD signature PMC, if any or a Null PMC.
/*
-=item C<METHOD set_raw_nci_ptr(void *func)>
-
-Sets the specified function pointer and raw flag.
-
-=cut
-
-*/
-
- METHOD make_raw_nci(PMC *func) {
- VTABLE_set_pointer(interp, SELF, (void *)func);
- }
-
-/*
-
=item C<void init()>
Initializes the NCI with a C<NULL> function pointer.
@@ -860,11 +115,13 @@ Initializes the NCI with a C<NULL> function pointer.
*/
VTABLE void init() {
- /* Mark that we're not a raw NCI. */
- PObj_flag_CLEAR(private2, SELF);
PObj_custom_mark_SET(SELF);
}
+ VTABLE void *get_pointer() {
+ return PARROT_NCI(SELF)->orig_func;
+ }
+
/*
=item C<void set_pointer_keyed_str(STRING *key, void *func)>
@@ -875,30 +132,22 @@ Sets the specified function pointer and signature (C<*key>).
*/
- VTABLE void set_pointer(void *ptr) {
- SET_ATTR_orig_func(INTERP, SELF, ptr);
- PObj_flag_SET(private2, SELF);
- }
-
- VTABLE void *get_pointer() {
- return PARROT_NCI(SELF)->orig_func;
- }
-
VTABLE void set_pointer_keyed_str(STRING *key, void *func) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
/* Store the original function and signature. */
- SET_ATTR_func(INTERP, SELF, func);
+ SET_ATTR_orig_func(INTERP, SELF, func);
/* ensure that the STRING signature is constant */
if (!PObj_constant_TEST(key)) {
char * const key_c = Parrot_str_to_cstring(INTERP, key);
const size_t key_length = Parrot_str_byte_length(interp, key);
- key = string_make(interp, key_c, key_length, NULL, 0);
+ key = Parrot_str_new_init(interp, key_c, key_length,
+ Parrot_default_encoding_ptr, PObj_constant_FLAG);
Parrot_str_free_cstring(key_c);
}
- nci_info->signature = key;
+ nci_info->sig_str = key;
}
/*
@@ -914,36 +163,17 @@ Mark any referenced strings and PMCs.
if (PARROT_NCI(SELF)) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
+ Parrot_gc_mark_PMC_alive(interp, nci_info->signature);
Parrot_gc_mark_PMC_alive(interp, nci_info->fb_info);
- Parrot_gc_mark_STRING_alive(interp, nci_info->signature);
- Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
- Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_return_signature);
- Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig);
- }
- }
-
-/*
-=item C<void destroy()>
-
-Free all of the memory used internally to store various things, like libffi call signatures.
-
-=cut
-
-*/
-
- VTABLE void destroy() {
- if (PARROT_NCI(SELF)) {
- Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
- mem_sys_free(nci_info->cif);
- mem_sys_free(nci_info->arg_translation);
- mem_sys_free(nci_info->arg_types);
- mem_sys_free(nci_info->return_translation);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->sig_str);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature);
+ Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_return_signature);
}
}
-
/*
=item C<PMC *clone()>
@@ -957,7 +187,7 @@ Creates and returns a clone of the NCI.
VTABLE PMC *clone() {
Parrot_NCI_attributes * const nci_info_self = PARROT_NCI(SELF);
Parrot_NCI_attributes *nci_info_ret;
- void *cif;
+ void *orig_func;
PMC * const ret = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
nci_info_ret = PARROT_NCI(ret);
@@ -969,12 +199,12 @@ Creates and returns a clone of the NCI.
nci_info_ret->func = nci_info_self->func;
nci_info_ret->fb_info = nci_info_self->fb_info;
nci_info_ret->orig_func = nci_info_self->orig_func;
- nci_info_ret->cif = nci_info_self->cif;
nci_info_ret->signature = nci_info_self->signature;
+ nci_info_ret->sig_str = nci_info_self->sig_str;
nci_info_ret->pcc_params_signature = nci_info_self->pcc_params_signature;
nci_info_ret->pcc_return_signature = nci_info_self->pcc_params_signature;
nci_info_ret->arity = nci_info_self->arity;
- PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7);
+ PObj_get_FLAGS(ret) = PObj_get_FLAGS(SELF);
return ret;
}
@@ -1006,391 +236,29 @@ class, the PMC arguments are shifted down.
*/
VTABLE opcode_t *invoke(void *next) {
- Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
+ Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
+ nci_thunk_t func;
+ PMC *fb_info;
char *sig_str;
+ void *orig_func;
PMC *cont;
- INTVAL return_size = sizeof (void*);
- PMC *ctx = CURRENT_CONTEXT(interp);
- PMC *call_object = Parrot_pcc_get_signature(interp, ctx);
- void (*func)(void*,void*,void*); /* a function pointer for our function to call */
-
- if (PObj_flag_TEST(private2, SELF)) {
- void *orig_func;
- PMC *fb_info;
- GET_ATTR_orig_func(INTERP, SELF, orig_func);
- GET_ATTR_fb_info(INTERP, SELF, fb_info);
-
- func = (void (*)(void*, void*, void*))orig_func;
-
- if (!func) {
- /* build the thunk only when necessary */
- func = (void (*)(void*, void*, void*))build_func(interp, nci_info);
-
- if (!func)
- Parrot_ex_throw_from_c_args(INTERP, NULL,
- EXCEPTION_INVALID_OPERATION,
- "attempt to call NULL function");
- }
-
- func = (void (*)(void*, void*, void*))(orig_func);
- func(INTERP, SELF, fb_info);
- }
- else {
- PMC *positional, *arg_iter;
- STRING *void_return;
- void **values, **middle_man = NULL, **pcc_ptr, **translation_pointers = NULL, **pcc_val = NULL;
- void *return_data;
- size_t count, i, j_offset;
- char *tmp_sig;
- ffi_cif *cif, pcc_cif;
- ffi_type **pcc_args;
-
- cif = (ffi_cif*)nci_info->cif;
- func = (void (*)(void*, void*, void*))nci_info->func;
-
- if (!cif) {
- /* build the thunk only when necessary */
- cif = build_libffi_func(interp, nci_info);
-
- if (!cif && !func)
- Parrot_ex_throw_from_c_args(INTERP, NULL,
- EXCEPTION_INVALID_OPERATION,
-
- "attempt to call NULL function");
- }
- if (nci_info->arity > 0) {
- size_t pcc_argc, pcc_values_offset, pcc_values_size, values_size;
- /* Function has arguments */
- pcc_args = mem_internal_allocate_n_zeroed_typed(nci_info->arity + 4, ffi_type*);
- tmp_sig = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature);
-
- pcc_args[0] = &ffi_type_pointer;
- pcc_args[1] = &ffi_type_pointer;
- pcc_args[2] = &ffi_type_pointer;
- pcc_values_size = 0;
- values_size = 0;
- pcc_argc = Parrot_str_length(interp, nci_info->pcc_params_signature);
-
- /* Add up the size of memory needed for the actual call */
- for (i = 0; i < (size_t)nci_info->arity; i++) {
- values_size += cif->arg_types[i]->size;
- }
-
- pcc_ptr = (void**)mem_internal_allocate_n_zeroed_typed(pcc_argc + 4, void*);
-
- /* Setup Parrot_pcc_fill_params_from_c_args required arguments */
- pcc_ptr[0] = &interp;
- pcc_ptr[1] = &call_object;
- pcc_ptr[2] = &tmp_sig;
-
- pcc_val = (void**)mem_internal_allocate_n_zeroed_typed(pcc_argc, void*);
- values = (void**)mem_internal_allocate_zeroed(values_size + sizeof(void*));
- /* Middle man is used to contain */
- middle_man = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
-
- /* Add up the size of the pcc arguments */
- for (i = 0; i < pcc_argc; i++) {
- pcc_args[i + 3] = &ffi_type_pointer;
- if (tmp_sig[i] == 'N') {
- pcc_val[i] = malloc(sizeof(FLOATVAL));
- pcc_ptr[i+3] = &pcc_val[i];
- }
- else if (tmp_sig[i] == 'I') {
- pcc_val[i] = malloc(sizeof(INTVAL));
- pcc_ptr[i+3] = &pcc_val[i];
- }
- else if (tmp_sig[i] == 'P' || tmp_sig[i] == 'S') {
- pcc_val[i] = malloc(sizeof(void*));
- pcc_ptr[i+3] = &pcc_val[i];
- }
- }
-
- if (ffi_prep_cif(&pcc_cif, FFI_DEFAULT_ABI, 3 + pcc_argc,
- &ffi_type_void, pcc_args) != FFI_OK) {
- Parrot_ex_throw_from_c_args(INTERP, NULL,
- EXCEPTION_INVALID_OPERATION,
- "Bad signature generated for Parrot_pcc_fill_params_from_c_args in NCI");
- }
-
- ffi_call(&pcc_cif, FFI_FN(Parrot_pcc_fill_params_from_c_args), NULL, pcc_ptr);
-
- Parrot_str_free_cstring(tmp_sig);
-
- /*
- * Apply Argument Transformations
- * this is mostly to transform STRING* into char*
- * and add the parrot interp argument if it needs it
- * but other transformations might apply later, like packing an
- * object into a ManagedStruct
- */
- j_offset = 0;
- translation_pointers = mem_internal_allocate_n_zeroed_typed(nci_info->arity, void*);
- for (i = 0; i < (size_t)nci_info->arity; i++) {
- switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
- case 'J':
- values[i] = &interp;
- j_offset++;
- break;
- case 't':
- if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
- translation_pointers[i] = (char*) NULL;
- }
- else {
- translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
- }
- values[i] = &translation_pointers[i];
- break;
- case 'B':
- if (STRING_IS_NULL(*(STRING**)pcc_val[i - j_offset])) {
- translation_pointers[i] = (char*) NULL;
- }
- else {
- translation_pointers[i] = Parrot_str_to_cstring(interp, *(STRING**)pcc_val[i - j_offset]);
- }
- middle_man[i] = &translation_pointers[i];
- values[i] = &middle_man[i];
- break;
- case 'b':
- values[i] = &Buffer_bufstart(*(STRING**)pcc_val[i - j_offset]);
- break;
- case 'c':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(char);
- *((char**)translation_pointers)[i] = (char)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case '2':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(short);
- *((pmc_holder_t*)translation_pointers[i])->ival = (short)VTABLE_get_integer(interp, *(PMC**)pcc_ptr[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
- break;
- case 's':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(short);
- *((short**)translation_pointers)[i] = (short)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case '3':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(int);
- *((pmc_holder_t*)translation_pointers[i])->ival = (int)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
- break;
- case 'i':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(int);
- *((int**)translation_pointers)[i] = (int)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case '4':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->ival = (INTVAL*)mem_internal_allocate_zeroed_typed(long);
- *((pmc_holder_t*)translation_pointers[i])->ival = (long)VTABLE_get_integer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->ival;
- break;
- case 'l':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(long);
- *((long**)translation_pointers)[i] = (long)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case 'q':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(long long);
- *((long long**)translation_pointers)[i] = (long long)*(INTVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case 'V':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(pmc_holder_t);
- ((pmc_holder_t*)translation_pointers[i])->p = *(PMC**)pcc_val[i - j_offset];
- ((pmc_holder_t*)translation_pointers[i])->pval = (void**)mem_internal_allocate_zeroed_typed(void*);
- *((pmc_holder_t*)translation_pointers[i])->pval = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
- (void *)NULL : (void*)VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &((pmc_holder_t*)translation_pointers[i])->pval;
- break;
- case 'P':
- translation_pointers[i] = *(PMC**)pcc_val[i - j_offset];
- values[i] = &translation_pointers[i];
- break;
- case 'p':
- translation_pointers[i] = PMC_IS_NULL(*(PMC**)pcc_val[i - j_offset]) ?
- (void *)NULL : VTABLE_get_pointer(interp, *(PMC**)pcc_val[i - j_offset]);
- values[i] = &translation_pointers[i];
- break;
- case 'f':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(float);
- *((float**)translation_pointers)[i] = (float)*(FLOATVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case 'd':
- translation_pointers[i] = mem_internal_allocate_zeroed_typed(double);
- *((double**)translation_pointers)[i] = *(FLOATVAL*)pcc_val[i - j_offset];
- values[i] = translation_pointers[i];
- break;
- case ' ':
- default:
- break;
- }
- }
-
- if (pcc_args) {
- mem_sys_free(pcc_args);
- }
- if (pcc_ptr) {
- mem_sys_free(pcc_ptr);
- }
- if (pcc_val) {
- for (i = 0; i < pcc_argc; i++) {
- mem_sys_free(pcc_val[i]);
- }
- mem_sys_free(pcc_val);
- }
- }
- else {
- /* No arguments */
- values = NULL;
- }
+ GET_ATTR_orig_func(INTERP, SELF, orig_func);
+ func = (nci_thunk_t)D2FPTR(nci_info->func);
- /*
- * This will allow for any type of datat to be returned.
- * Including one day Structures
- */
- return_data = mem_internal_allocate_zeroed(cif->rtype->size);
-
- ffi_call(cif, FFI_FN(func), return_data, values);
-
- if (cif->rtype != &ffi_type_void) {
- char *s;
- PMC *ret_object;
- s = Parrot_str_to_cstring(interp, nci_info->pcc_return_signature);
- switch (*(char*)nci_info->return_translation) {
- case 'p':
- {
- PMC *final_destination = PMCNULL;
-
- if (*(void**)return_data != NULL) {
- final_destination = Parrot_pmc_new(interp, enum_class_UnManagedStruct);
- VTABLE_set_pointer(interp, final_destination, *(void**)return_data);
- }
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, final_destination);
-
- }
- break;
- case 't':
- {
- STRING *final_destination = Parrot_str_new(interp, *(char**)return_data, 0);
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, final_destination);
- }
- break;
- case 'f':
- {
- FLOATVAL final_destination = *(float*)return_data;
-
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, final_destination);
- }
- break;
- default:
- switch (s[0]) {
- case 'N':
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, *(FLOATVAL*)return_data);
- case 'I':
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, *(INTVAL*)return_data);
- case 'P':
- case 'S':
- default:
- ret_object = Parrot_pcc_build_call_from_c_args(interp,
- call_object,
- s, *(void**)return_data);
- }
- break;
- }
- Parrot_str_free_cstring(s);
- }
+ GET_ATTR_fb_info(INTERP, SELF, fb_info);
- /*
- * Free memory used for cstrings,
- * and any other translations that use temporary memory
- */
- for (i = 0; i < (size_t)nci_info->arity; i++) {
- switch ((INTVAL)((char*)nci_info->arg_translation)[i]) {
- case (INTVAL)'B':
- if (translation_pointers[i]) {
- Parrot_str_free_cstring((char*)translation_pointers[i]);
- }
- break;
- case (INTVAL)'t':
- if (translation_pointers[i]) {
- Parrot_str_free_cstring((char*)translation_pointers[i]);
- }
- break;
- case (INTVAL)'2':
- VTABLE_set_integer_native(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (INTVAL)*(short*)((pmc_holder_t*)translation_pointers[i])->ival);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
- break;
- case (INTVAL)'3':
- VTABLE_set_integer_native(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (INTVAL)*(int*)((pmc_holder_t*)translation_pointers[i])->ival);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
- break;
- case (INTVAL)'4':
- VTABLE_set_integer_native(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (INTVAL)*(long*)((pmc_holder_t*)translation_pointers[i])->ival);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
- break;
- case (INTVAL)'V':
- VTABLE_set_pointer(interp,
- ((pmc_holder_t*)translation_pointers[i])->p,
- (PMC*)*((pmc_holder_t*)translation_pointers[i])->pval);
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
- break;
- case (INTVAL)'d':
- case (INTVAL)'c':
- case (INTVAL)'s':
- case (INTVAL)'i':
- case (INTVAL)'l':
- case (INTVAL)'q':
- if (translation_pointers[i]) {
- mem_sys_free(translation_pointers[i]);
- }
- break;
- default:
- break;
- }
- }
+ if (!func) {
+ /* build the thunk only when necessary */
+ func = build_func(interp, nci_info);
- if (nci_info->arity > 0 && middle_man) {
- mem_sys_free(middle_man);
- }
- if (return_data) {
- mem_sys_free(return_data);
- }
- if (values) {
- mem_sys_free(values);
- }
+ if (!func)
+ Parrot_ex_throw_from_c_args(INTERP, NULL,
+ EXCEPTION_INVALID_OPERATION,
+ "attempt to call NULL function");
}
+ func(INTERP, SELF, fb_info);
cont = INTERP->current_cont;
/*
@@ -1438,7 +306,7 @@ Returns the boolean value of the pointer.
VTABLE INTVAL get_bool() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
- return (0 != (INTVAL)nci_info->cif);
+ return (0 != (INTVAL)nci_info->orig_func);
}
/*
@@ -1455,16 +323,11 @@ Return the arity of the NCI (the number of arguments).
INTVAL arity = 0;
if (nci_info) {
- if (PObj_flag_TEST(private2, SELF)) {
- }
- else {
- if (!nci_info->cif) {
- nci_info->cif = build_libffi_func(interp, nci_info);
- }
- if (nci_info->cif) {
- arity = nci_info->arity;
- RETURN(INTVAL arity);
- }
+ if (!nci_info->func)
+ build_func(INTERP, nci_info);
+ if (nci_info->func) {
+ arity = nci_info->arity;
+ RETURN(INTVAL arity);
}
}
@@ -1482,12 +345,6 @@ Return the arity of the NCI (the number of arguments).
F<docs/pdds/pdd03_calling_conventions.pod>.
-=head1 HISTORY
-
-Initial revision by sean 2002/08/04.
-
-Updates by John Harrison, Summer 2010, GSoC.
-
=cut
*/
@@ -1498,4 +355,3 @@ Updates by John Harrison, Summer 2010, GSoC.
* End:
* vim: expandtab shiftwidth=4:
*/
-
View
2  t/steps/gen/libffi-01.t
@@ -24,7 +24,7 @@ use IO::CaptureOutput qw( capture );
########## regular ##########
-sub
+sub
pass("Completed all tests in $0");
Please sign in to comment.
Something went wrong with that request. Please try again.