Przemyslaw Czerpak wrote (on 2007-06-xx):
I know but without own linker seems that we cannot fully drop code
segment (see above) but maybe you will know some possible tricks for
this problem.
Przemyslaw Czerpak wrote:
If we also add support for calling PCODE function without executing C ones
then we will have nice VM to emulate MT mode in platforms which do not
have native MT support.
Hi,
the question about PCODE functions without C stub is mentioned not the
first time on the list. I'll try to say some ideas about possible
implementation of "pure PCODE functions".
We use a standard linkers to link Harbour code, thus we need to use
extern/public label to indicate linker dependencies. This should remains
true also for pure PCODE functions, if we want to use standard linkers.
The first idea that cames to mind is that we need export not C stub
address of PCODE function (we have this solution now), but we need to
export address of PCODE itself, or perhaps address of some structure
containing the PCODE. This way we can drop C stub and have pure PCODE
functions.
But we have one more fundamental restriction here: functions'
extern/public labels should have the same type regardless its
implementation (PCODE or C). Let's have module BB containing function
BFUNC(), and module AA which calls function BFUNC(). Code in module AA
do not know, if BFUNC() is implemented in pure PCODE or real C code, so
exported public BFUNC() label should have the same type.
This leads to conclusion: if the want to drop C stub for PCODE
functions, we must export some structure of pure PCODE functions, and we
must export a compatible structure for real C code! I.e. Harbour level C
code functions can not be exported as function addresses.
So, let's talk about the structure of Harbour function. PCODE is not
self contained. It can not be evaluated without associated symbol table.
In current implementation, C stub makes a binding of PCODE and symbol
table. If we want to drop C stub, we must include symbol table address
into function structure. I find modified HB_SYMB a good candidate for
the function structure. I'll try to indicate ideas by C code (well, it's
more pseudo-C).
.prg module compiled .c code:
// Public function AAA
static BYTE pcode_HB_FUN_AAA[] = { ... };
HB_SYMB HB_FUN_AAA = {"AAA", HB_FS_PUBLIC | HB_FS_LOCAL | HB_FS_PCODE,
pcode_HB_FUN_AAA, symbol };
// Static function BBB
static BYTE pcode_HB_FUN_BBB[] = { ... };
static HB_SYMB HB_FUN_BBB = {"BBB", HB_FS_LOCAL | HB_FS_PCODE,
pcode_HB_FUN_BBB, symbols };
// External function CCC
extern HB_SYMB HB_FUN_CCC;
static HB_SYMB ext_HB_FUN_CCC = {"CCC", 0,
&HB_FUN_CCC, NULL };
// Symbol table
static HB_SYMB* symbols = {&HB_FUN_AAA, &HB_FUN_BBB, &ext_HB_FUN_CCC};
You can see it's recursive structures (symbols is used in HB_SYMB, but
defined later), I'm not sure if we can define such structures in C. If
such definitions are wrong, the last member of HB_SYMB could be assigned
by hb_vmProcessSymbols().
I do not like that symbol table becomes the array of symbol pointers,
but not the array of symbols. But I can not get the idea how to make
addresses of some array's element public. It's not a problem in
assembler. Can it be done in C?
Let's look to Harbour functions implemented in C.
HB_FUNC( CCC )
{
hb_retni( hb_parni( 1 ) );
}
can be preprocessored to:
HB_SYMB HB_FUN_CCC = {"CCC", HB_FS_PUBLIC,
func_HB_FUN_CCC, NULL};
void func_HB_FUN_CCC( void )
{
hb_retni( hb_parni( 1 ) );
}
After this change hb_vmExecute() requires only one PHB_SYMB parameter.
HB_PCODEFUNC structure for dynamic functions is also not required,
because all data (PCODE address and symbol table address) is contained
in the HB_SYMB.
HB_FUNC_EXEC(...) is also a hb_vmExecute() call, because we do not have
direct C function calls anymore, our functinos are HB_SYMB structures.
So,
HB_FUNC_EXEC( AAA )
is
hb_vmExecute( HB_FUN_AAA )
and hb_vmExecute() should check if function has HB_FS_PCODE bit and take
a decision: run virtual machine, or do a real C function call.
BTW, symbols member of HB_SYMB could point not to symbol table (array of
PHB_SYMB), but to structure similar to current HB_SYMBOLS. In this case
it would be much more easy to get filename of module, we can include
unique module id into structure, etc.
static HB_SYMBOLS* symbols =
{ "module.prg",
{&HB_FUN_AAA, &HB_FUN_BBB, &ext_HB_FUN_CCC}, // symbol table
0xDEADBEEF, // unique ID
...
};
I know there are some issues related to export of variable (not
function) labels from .dll. I don't know the exact problems, and
possibly the proposed ideas are related to these problems, because here
we export variable of HB_SYMB* (HB_SYMB?) type, but not a function address.
Best regards,
Mindaugas
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour