Pliant announce forum

Pliant announce forum

Pliant release 49

This debate has been automatically converted from the old Pliant forum
Message posted by maybe hubert.tonneau@heliosam.fr on 2000/10/29 03:37:21
Pliant release 49 is on the wire at http://pliant.cx/archive/pliant-49.tgz
and http://pliant.cx/archive/pliant-49.zip

It's mainly bug fixes (Win32 users had serious problems with the previous
releases) and the FTP server now works.
The SMTP server should be for the next one, also the new web mailer is
already in.
Message posted by maybe Hubert Tonneau on 2000/10/29 04:29:12
Ben Cooley might well succeed to compile release 49 of Pliant using VC++
since the calling convention specification in module
/pliant/language/declare/call.c is now more flexible.

In each specification, there are now two areas for specifying the modifyed
registers. The first one is specifying the ones that Pliant is allowed
to modify (not save/restore at the function begin/end), and the second one
is specifying the registers that external functions might modify when
called.
So, setting more registers in the second list will raise the probably
of Pliant to work properly with your compiler.
Message posted by maybe Ben Cooley on 2000/10/30 21:09:35
Hot Dog!

I spent several days trying to figure out why Pliant wouldn't work under VC++.  
It seemed to have been a problem with functions that were automatically inlined.
Apparently a register was being mangled in these instances.  I traced through the 
optimization module, but couldn't find where the problem occured.  Just as a
note.. Pliant heavily needs small line by line comments as to what variables
are, what they do, and what the purpose of varioius functions and snipets of 
code do.  Without any internal documentation, debugging on the order that I
was trying to do is very very difficult.

I'll download the new version and see if I can get it to run in VC++.
Message posted by maybe Hubert Tonneau on 2000/10/30 21:31:53
While upgrading Pliant for OS/2, I found in the Watcom documentation the
detailed explaination about various calling conventions.
For Win32, the exact right one is:

#if defined(_WIN32_API_) && defined(_i386_)
  static Int external_call_registers[1];
  static Int external_modify_registers[3] = {Register_EAX,Register_ECX,Register_EDX};
  static Int external_return_registers[1] = {Register_EAX};
  static struct CompilingRules external_rules = {
    Function_flag_has_side_effects|
    Function_flag_byvalue_result_first|
    Function_flag_mapped_result_first|
    Function_flag_ro_byvalue|
    Function_flag_result_byvalue|
    Function_flag_push_reversed,
    external_call_registers, 0,
    external_modify_registers, 3,
    external_modify_registers, 3,
    external_return_registers, 1 };
#endif

It means that in releases earlier than 49, Pliant was assuming that it
could avoid to save/restore the EBX in all functions marked with
'external_calling_convention' which is wrong, so it could generate
buggy code.
With release 49, I introduced a more sophisticated mechanism that enables
to specify one rule for Pliant functions, and one another for external
ones, so it should now work, even if the release 49 declaration was
suboptimal.

So, for release 50, I could switch back to the previous model since I
now know the exact values, but experimenting with release 49 model is
still probably easier.
Message posted by maybe Ben Cooley on 2000/10/31 09:59:36
Pliant now compiles and runs fine under MSVC (at least as far as I can tell).
The changes to the files in order to add MSVC support are as follows.  (I've 
done it so many times that I know by heart where the code is..)

In atomic.c the following code must be added. (Note that MSVC considers these
functions to be 'intrinsic' meaning they are compiled to assembly code directly.

#if defined(_i386_) && defined(_MSVC_)

  #include <windows.h>

  // The following Interlocked functions are expanded inline with MSVC..

  INLINE Void atomic_increment(volatile Int *adr) {
    InterlockedIncrement(adr); }

  INLINE Bool atomic_decrement_and_test_zero(volatile Int *variable) {
    return InterlockedDecrement(variable) == 0; }

  INLINE Void atomic_add(volatile Int *variable,Int value) {
    InterlockedExchangeAdd(variable, value); }

  INLINE Int atomic_read_and_set(volatile Int *variable,Int value) {
    return (Int)InterlockedExchange(variable, value); }

#endif

In call.c the following block must be added..

#if defined(_MSVC_) && defined(_i386_)
  #ifdef _REGISTERS_
    static Int pliant_call_registers[4] = {Register_EAX,Register_EDX,Register_EBX,Register_ECX};
    static Int pliant_modify_registers[1] = {Register_EAX};
    static Int pliant_return_registers[1] = {Register_EAX};
    static struct CompilingRules compiler_rules = {
      Function_flag_byvalue_result_first|
      Function_flag_mapped_result_first|
      Function_flag_ro_byvalue|
      Function_flag_result_byvalue|
      Function_flag_push_reversed|
      Function_flag_modify_call_registers,
      pliant_call_registers, 4,
      pliant_modify_registers, 1,
      pliant_modify_registers, 1,
      pliant_return_registers, 1 };
  #else
    static Int pliant_call_registers[1];
    static Int pliant_modify_registers[4] = {Register_EAX,Register_EDX,Register_EBX,Register_ECX};
    static Int pliant_return_registers[1] = {Register_EAX};
    static struct CompilingRules compiler_rules = {
      Function_flag_byvalue_result_first|
      Function_flag_mapped_result_first|
      Function_flag_ro_byvalue|
      Function_flag_result_byvalue|
      Function_flag_push_reversed|
      Function_flag_not_popped,
      pliant_call_registers, 0,
      pliant_modify_registers, 1,
      pliant_modify_registers, 4,
      pliant_return_registers, 1 };
  #endif

  static Int varargs_call_registers[1];
  static Int varargs_modify_registers[4] = {Register_EAX,Register_EDX,Register_EBX,Register_ECX};
  static Int varargs_return_registers[1] = {Register_EAX};
  static struct CompilingRules varargs_rules = {
    Function_flag_has_side_effects|
    Function_flag_byvalue_result_first|
    Function_flag_mapped_result_first|
    Function_flag_ro_byvalue|
    Function_flag_result_byvalue|
    Function_flag_push_reversed|
    Function_flag_not_popped,
    varargs_call_registers, 0,
    varargs_modify_registers, 1,
    varargs_modify_registers, 4,
    varargs_return_registers, 1 };
#endif

This is basically a copy of the WATCOM block with _MSVC_ at the top.  It seemed
to work fine.

To compile pliant as an executable with the _EXE_ macro, the _EXTERN_ macro
must be remarked out of the 'main' funciton declaration in startup.c.  I think
this is a bug in the WATCOM and GCC version as well.  (To debug I usually compile
to an EXE and not a DLL by the way.)

I also added the following code at the top of pliant.c to disable Microsoft's
Lint warnings.  The warnings I get are mostly signed/unsigned mismatch, 
unused variables (why are there unused variables), and other riffraff.

#ifdef _MSVC_
#pragma warning( disable : 4146 )
#pragma warning( disable : 4090 )
#pragma warning( disable : 4024 )
#pragma warning( disable : 4101 )
#pragma warning( disable : 4244 )
#pragma warning( disable : 4018 )
#pragma warning( disable : 4113 )
#endif
The compiler macros must be documented as follows..
_CHECK_ - Enables pliant debug check macros (good idea)
_WIN32_API_ - Causes pliant to use the Win32 api instead of say Linux
_i386_ - Tells pliant to use the 386 instruction set
_MSVC_ - Tells pliant to use the _MSVC_ specific macros
_EXE_ - Turn this on if you want to generate an _EXE_ file.  Use _DLL_ for a dll.
c_debugging_level=x - Sets the debugging level of the exe you generate 0-2

I got everything to precompile, but I haven't actually checked to see if the interpreter or any of the software works.  However getting the precompiled dump files is a major achievement.  Anyhow, I'll cross my fingers.

If this works, I can go ahead and finish the source debugger and editor and
post it.  It'd be nice to have an IDE with syntax highlighting, source debugging
and the like.
Message posted by maybe Hubert Tonneau on 2000/10/31 14:32:41
> Pliant now compiles and runs fine under MSVC

Great !

I have included your changes in the main tree so that you don't have to
apply them with each new release.

About your calling convention, do you use _REGISTERS_ or not ?
I bet you're not since you have not listed it in your comments about what
must be declared.

Theres is no make-win32-i386-msvc.bat in your changes. Does it mean
that you can compile only in an IDE ?

> static Int pliant_modify_registers[4] = {Register_EAX,Register_EDX,Register_EBX,Register_ECX};
> static Int pliant_return_registers[1] = {Register_EAX};

If not using registers calling convention, I'd like you to test the
following: 

     static Int pliant_call_registers[1];
     static Int pliant_modify_registers[3] = {Register_EAX,Register_EDX,Register_ECX};
     static Int pliant_return_registers[1] = {Register_EAX};
     static struct CompilingRules compiler_rules = {
       Function_flag_byvalue_result_first|
       Function_flag_mapped_result_first|
       Function_flag_ro_byvalue|
       Function_flag_result_byvalue|
       Function_flag_push_reversed|
       Function_flag_not_popped,
       pliant_call_registers, 0,
       pliant_modify_registers, 3,
       pliant_modify_registers, 3,
       pliant_return_registers, 1 };

which means try the call.c I mailed directly to use yesturday, because it
will do extacly that.

What you have works since Pliant release 49 is more consevative (it uses
less registers than it assumes the C compiler does), but I think the above
is the right declaration: EAX EDX ECX are the modifyed registers
when using stack calling convention as opposed to registers calling
convention.
Message posted by maybe Ben Cooley on 2000/10/31 21:30:14
No, the _REGISTERS_ macro doesn't work.  I've tried the GCC, WATCOM, and a few 
of my own combinations.  Unfortunately nothing does the trick.  Could you
send a detailed explanation of the structure so that I can figure it out.  Also
a good bit of tiny sample code that I can compile that will use all the registers
and cause the system to crash unless the settings are set right would be helpful.

There also may be a problem with the total registers.  Microsoft actually uses
all 7 registers (eax,ebx,ecx,edx,esi,edi,ebp) as gp registers.  In unoptimized
compiles ebp gets retained as a base pointer, though it 'does' get used when
doing optimized compiles (i think), the rest are used all the time.  Could
this be the problem?
Message posted by maybe Ben Cooley on 2000/10/31 21:35:07
OOPS

Your _REGISTER_ block seems to work.  Sorry I didn't read your message before I 
posted my last message.   So looks like everything is hunky dory then.  I'll 
post the .BAT file when I've tested it.

Ben