Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tag: RELEASE_1_1_0
Fetching contributors…

Cannot retrieve contributors at this time

425 lines (307 sloc) 11.111 kB
/*
Copyright (C) 2001-2008, Parrot Foundation.
$Id$
=head1 NAME
src/pmc/nci.pmc - Native Call Interface
=head1 DESCRIPTION
The vtable functions for the native C call functions.
=head2 Methods
=over 4
=cut
*/
#include "parrot/parrot.h"
typedef INTVAL (*nci_sub_t)(PARROT_INTERP, PMC *);
typedef INTVAL (*nci_jit_sub_t)(PARROT_INTERP, PMC *, char *);
void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info);
void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info) {
char *sig_c = Parrot_str_to_cstring(interp, sig);
size_t sig_length = strlen(sig_c);
char *param_sig = mem_allocate_n_zeroed_typed(sig_length, char);
size_t j = 0;
size_t i;
for (i = 1; i < sig_length; i++) {
switch (sig_c[i]) {
case '0': /* null ptr or such - doesn't consume a reg */
break;
case 'f':
case 'N':
case 'd':
param_sig[j++] = 'N';
break;
case 'I': /* INTVAL */
case 'l': /* long */
case 'i': /* int */
case 's': /* short */
case 'c': /* char */
param_sig[j++] = 'I';
break;
case 'S':
case 't': /* string, pass a cstring */
param_sig[j++] = 'S';
break;
case 'J': /* interpreter */
break;
case 'p': /* push pmc->data */
case 'O': /* push PMC * object in P2 */
case 'P': /* push PMC * */
case 'V': /* push PMC * */
param_sig[j++] = 'P';
case 'v':
break;
/* I have no idea how to handle these */
case '2':
case '3':
case '4':
param_sig[j++] = 'I';
break;
case '@':
param_sig[j++] = '@';
break;
case 'b': /* buffer (void*) pass PObj_bufstart(SReg) */
case 'B': /* buffer (void**) pass &PObj_bufstart(SReg) */
param_sig[j++] = 'S';
break;
default:
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_JIT_ERROR,
"Unknown param Signature %c\n", sig_c[i]);
break;
}
}
PARROT_ASSERT(j <= sig_length);
/* use only the signature-significant part of the string buffer */
if (j) {
nci_info->pcc_params_signature = string_make(interp, param_sig, j,
NULL, PObj_constant_FLAG);
}
else
nci_info->pcc_params_signature = CONST_STRING(interp, "");
mem_sys_free(param_sig);
Parrot_str_free_cstring(sig_c);
}
pmclass NCI need_ext {
ATTR STRING *signature; /* The signature. */
ATTR void *func; /* Function pointer to what we'll call. */
ATTR void *orig_func; /* Function pointer used to create func*/
ATTR STRING *pcc_params_signature; /* The signature. */
ATTR INTVAL arity; /* Cached arity of the NCI. */
ATTR INTVAL jitted; /* Is this a jitted NCI stub. */
ATTR PMC *multi_sig; /* type tuple array (?) */
/*
=item C<METHOD get_multisig()>
Return the MMD signature PMC, if any or a Null PMC.
=cut
*/
METHOD get_multisig() {
PMC *sig;
GET_ATTR_multi_sig(INTERP, SELF, sig);
if (sig == PMCNULL)
sig = PMCNULL;
RETURN(PMC *sig);
}
/*
=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.
=cut
*/
VTABLE void init() {
PMC_data(SELF) = mem_allocate_zeroed_typed(Parrot_NCI_attributes);
/* Mark that we're not a raw NCI. */
PObj_flag_CLEAR(private2, SELF);
PObj_custom_mark_SET(SELF);
PObj_active_destroy_SET(SELF);
}
/*
=item C<void set_pointer_keyed_str(STRING *key, void *func)>
Sets the specified function pointer and signature (C<*key>).
=cut
*/
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);
int jitted = 0;
char * const key_c = Parrot_str_to_cstring(INTERP, key);
/* Store the original function and signature. */
SET_ATTR_orig_func(INTERP, SELF, func);
nci_info->signature = string_make(interp, key_c, strlen(key_c),
NULL, PObj_constant_FLAG);
Parrot_str_free_cstring(key_c);
pcc_params(INTERP, key, nci_info);
/* Arity is length of that string minus one (the return type). */
nci_info->arity = Parrot_str_byte_length(INTERP, key) - 1;
/* Build call function. */
nci_info->func = (PMC *)(build_call_func(INTERP, SELF,
key, &jitted));
nci_info->jitted = jitted;
}
/*
=item C<void mark()>
Mark any referenced strings and PMCs.
=cut
*/
VTABLE void mark() {
if (PARROT_NCI(SELF)) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
if (nci_info->signature)
pobject_lives(interp, (PObj*)nci_info->signature);
if (nci_info->pcc_params_signature)
pobject_lives(interp, (PObj*)nci_info->pcc_params_signature);
}
}
/*
=item C<void destroy()>
Destroys the NCI, freeing any allocated memory.
=cut
*/
VTABLE void destroy() {
if (PMC_data(SELF)) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
mem_sys_free(nci_info);
PMC_data(SELF) = NULL;
}
}
/*
=item C<PMC *clone()>
Creates and returns a clone of the NCI.
=cut
*/
VTABLE PMC *clone() {
Parrot_NCI_attributes * const nci_info_self = PARROT_NCI(SELF);
Parrot_NCI_attributes *nci_info_ret;
void *orig_func;
PMC * const ret = pmc_new(INTERP, SELF->vtable->base_type);
PMC_data(ret) = mem_allocate_zeroed_typed(Parrot_NCI_attributes);
nci_info_ret = PARROT_NCI(ret);
/* FIXME if data is malloced (JIT/i386!) then we need
* the length of data here, to memcpy it
* ManagedStruct or Buffer?
*/
nci_info_ret->func = nci_info_self->func;
nci_info_ret->orig_func = nci_info_self->orig_func;
nci_info_ret->signature = nci_info_self->signature;
nci_info_ret->pcc_params_signature = nci_info_self->pcc_params_signature;
nci_info_ret->arity = nci_info_self->arity;
nci_info_ret->jitted = nci_info_self->jitted;
PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7);
return ret;
}
/*
=item C<INTVAL defined()>
Returns whether the NCI is defined.
=cut
*/
VTABLE INTVAL defined() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
return nci_info->func != NULL;
}
/*
=item C<opcode_t *invoke(void *next)>
Calls the associated C function, returning C<*next>. If
the invocant is a class, the PMC arguments are
shifted down.
=cut
*/
VTABLE opcode_t *invoke(void *next) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
nci_sub_t func;
void *orig_func;
PMC *cont;
GET_ATTR_orig_func(INTERP, SELF, orig_func);
func = PObj_flag_TEST(private2, SELF)
? (nci_sub_t) D2FPTR(orig_func)
: (nci_sub_t) D2FPTR(nci_info->func);
if (!func)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
"attempt to call NULL function");
if (nci_info->jitted) {
nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func);
/* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */
jit_func(INTERP, SELF, (char *) nci_info->pcc_params_signature->strstart);
}
else {
if (PObj_flag_TEST(private2, SELF)) {
/* Parrot_eprintf(interp, "RAW NCI CALL\n"); */
}
else {
/* Parrot_eprintf(interp, "HACKED %S\n", nci_info->signature); */
}
func(INTERP, SELF);
}
cont = INTERP->current_cont;
/*
* If the NCI function was tailcalled, the return result
* is already passed back to the caller of this frame
* - see Parrot_init_ret_nci(). We therefore invoke the
* return continuation here, which gets rid of this frame
* and returns the real return address
*/
if (cont && cont != NEED_CONTINUATION &&
(PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) {
cont = CONTEXT(interp)->current_cont;
next = VTABLE_invoke(INTERP, cont, next);
}
return (opcode_t *)next;
}
/*
=item C<INTVAL get_integer()>
Returns the function pointer as an integer.
=cut
*/
VTABLE INTVAL get_integer() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
return (INTVAL)nci_info->func;
}
/*
=item C<INTVAL get_bool()>
Returns the boolean value of the pointer.
=cut
*/
VTABLE INTVAL get_bool() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
return (0 != (INTVAL)nci_info->func);
}
/*
=item C<METHOD arity()>
Return the arity of the NCI (the number of arguments).
=cut
*/
METHOD arity() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
INTVAL arity = 0;
if (nci_info && nci_info->func)
arity = nci_info->arity;
else
Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INVALID_OPERATION,
"You cannot get the arity of an undefined NCI.");
RETURN(INTVAL arity);
}
}
/*
=back
=head1 SEE ALSO
F<docs/pdds/pdd03_calling_conventions.pod>.
=head1 HISTORY
Initial revision by sean 2002/08/04.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
Jump to Line
Something went wrong with that request. Please try again.