[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
Created:Fri Nov 13 1992
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2212
Total number of notes:11045

2088.0. "alloca() for OpenVMS VAX?" by RDGENG::WOOD_J ([email protected]) Mon Feb 10 1997 11:08

A software vendor is trying to port his application to OpenVMS VAX. The
application has UNIX origins, and runs on Digital UNIX and OpenVMS Alpha.
The application uses the alloca() routine to allocate temporary space on
the stack. alloca() is supported on Digital UNIX (via alloca.h), and also on 
OpenVMS Alpha (via builtins.h & __ALLOCA). It does not appear to be supported
on OpenVMS VAX: with DEC C v5.5, builtins.h has a definition for __ALLOCA
but this is conditional on __VMS and __ALPHA, the latter of course being false.

The software vendor tried to write his own version of alloca() using MACRO.
The routine allocated stack space and returned it in the caller's context 
(after fiddling with the call-frames a bit). But when the routine is callled
from DEC C, he gets spurious stack corruptions. It looks like the compiler 
assumes that the Stack Pointer never moves, other than in response to its own
instructions (e.g. PUSHL). Hence, after calling their own version of alloca(), 
it's still addressing temporary variables relative to where it thought SP was
before. Presumably this is why it has to be a built-in function for Alpha AXP.

Are there any intentions to implement alloca() for OpenVMS VAX?

Or any possible workarounds?

Thanks,
  John Wood
  Software Partner Engineering
T.RTitleUserPersonal
Name
DateLines
2088.1A risky workaround???HPCGRP::MANLEYMon Feb 10 1997 11:409
> Or any possible workarounds?

Within the customers alloca, perhaps the call frame and everything between
it and the previous frame can be relocated, leaving the alloca'd space above
the relocated data. This may work, and then again it may not. It certainly
won't work if pointers to stack allocated data are loaded before alloca is
called.

2088.2VAX MACRO my_allocaHNDYMN::MCCARTHYA Quinn Martin ProductionMon Feb 10 1997 12:1287
Try this (I think it modifies the stack in the way you want) - I think it still
compiles (I cut it down from another example).

This is UNSUPPORTED !!

Brian J.

#define alloca my_alloca 

    s = alloca (size);

--------------------------------------
File: my_alloca.mar
--------------------------------------

        .TITLE  my_alloca 

       .page
        .SBTTL  DECLARATIONS

        $SFDEF                  ; stack frame symbols
        .DSABL  GBL             ; Force all external symbols to be declared

        .PSECT  $CODE,PIC,RD,SHR,NOWRT,LONG

	.ENTRY  __my_alloca, ^M<R2,R3,R4,R5>
;
; What we want to do here is adjust the stack pointer ahead by the value
; in 4(ap) and return the pointer to the adjusted stack to the caller in r0
; Note:
;	We do not add the size of this call frame to the 
;	adjusted value because when this routine is called, 
;	this frame is created on the stack, that means we already
;	have 44 bytes allocated (that is:
; 		Handler - Address	 0
;  		PSL			 4
;  		AP			 8
;  		FP			16
;  		PC			20
;  		R2 SAVE			24
;  		R3 SAVE			28
;  		R4 SAVE			32
;  		R5 SAVE			36
;  		ARG COUNT		40
;  		FIRST ARG		44
;
; 	When we move the SP down
;	by the requested amount, and then point FP at that new location,
;	when the RET pops things off the stack, it is taking that
;	44 bytes back off off from the newly adjusted stack.  We are left with
;	exactly the amount requested (plus any padding)
;

	;
	; Add 3 to requested value, then use the BICL2 instruction to
	; make sure the request is a multiple of 4 (longword aligned).  
	; Me, think of using the BICL2 instruction myself? nope.  I checked 
	; other sources for the word align and found several examples.  
	;
	ADDL3	#3, 4(AP), R0	
	BICL2	#3, R0
	; 
	; Move the stack down requested amount
	;
	SUBL	R0, SP
	;
	; Move the contents of the current frame into the area we just 
	; allocated on the stack. 
	;
	MOVC3	#44, (FP), (SP)
	;
	; Subtract the size of this frame (44 bytes) from the current FP and
	; that is the address of the stack storage requested. (since this 
	; routine has no local storage, FP and SP were equal when we entered)
	;
        SUBL3	#44, FP, R0
	;
	; The last thing to do is to change the frame pointer to be where we
	; moved the SP to.  This will cause the RET statement to clear this
	; "new" stack off the frame and set SP to the location at the bottom
	; of the stack.
	; 
	MOVL	SP, FP

	RET

	.END
2088.3Great example!TAVENG::BORISBoris Gubenko, ISEMon Feb 10 1997 13:339
  Great example! Worked like a champ for me.

  (vfork() on VAX does similar manipulations with stack frames).

  btw, I could never understand what alloca() is good for and why allocation
  a memory from the stack is better than allocation from heap (I mean malloc()).

  Boris
2088.4HPCGRP::MANLEYMon Feb 10 1997 13:426
Re: .2

It shouldn't be hard to convince yourself that R0 is always returns the address
44 bytes below the current FP. ;-)

2088.5Why alloca() ?SUBPAC::FARICELLIMon Feb 10 1997 14:0115
>>  btw, I could never understand what alloca() is good for and why allocation
>>  a memory from the stack is better than allocation from heap

   1) Dynamic memory allocated via alloca() is automatically freed at the
      exit of the routine.

   2) Some malloc() implementations may incur a lot of overhead
      when allocating and deallocating lots of small pieces of memory.
      Some poorly implemented malloc()'s maintained free()'d memory on
      a linear linked list, for example.
      One piece of ancient wisdom was to always roll your own memory
      management if you had this situation and you needed performance.

   -- John Faricelli
2088.6.2 doesn't work for me...RDGENG::WOOD_J[email protected]Tue Feb 11 1997 03:50113
I tried the Macro example from .2, but it didn't work for me.

Whilst I appreciate the discaimer in .2 about it being unsupported,
I wonder if I'm doing something wrong since the .3 reply implied
it worked.

Below is my test program. I compile with /debug/noopt using DEC C v5.5
on OpenVMS VAX v6.2. When I run using the debugger I get an access
violation when sub() tries to initialize the 23rd element of the
ip[] array. I don't understand why. I did change the Macro32 code
so that the call-entry of __my_alloca becomes my_alloca.

Thanks,
  John Wood
-------------

From debugger:

   728:     /* initialize array allocated on stack */
   729:     ip = p;                                 
   730:     for (j = 0; j < i; j++)                 
-> 731:         ip[j] = j;                          
   732:                        
                     
Line   731: MOVL     B^-12(FP),R0
-> 	    MOVL     B^-12(FP),@B^-16(FP)[R0]
	    ADDL3    B^-12(FP),S^#1,R0
 	    MOVL     R0,B^-12(FP)DBG> Step

%SYSTEM-F-ACCVIO, access violation, reason mask=04, virtual address=00000072,
PC=00000390, PSL=03C00011
DBG>

---------

test program:

/*
    test_alloca.c - example program to call alloca()


    VAX:
        $ cc/debug/noopt/lis/mach test_alloca.c
        $ macro/debug/lis my_alloca.mar
        $ link/debug/map/full test_alloca, my_alloca
*/

#include <stdio.h>

    /* DEC C on OpenVMS Alpha */
#if defined (__VMS) && defined (__alpha)
#include <builtins.h>
#endif

    /* DEC C on OpenVMS VAX : use VAX Macro routine my_alloca() for alloca() */
#if defined (__VMS) && defined (__vax)
#define alloca my_alloca
void *my_alloca( int size );
#endif

    /* cc on Digital UNIX v4.0 */
#if defined (__DECC) && defined (__alpha) && defined (__unix__)
#include <alloca.h>
#endif


void sub2( int i, int *ip )
{
    int j;

    printf( "sub2: i = %d\n", i );

    /* display contents of array */
    for (j = 0; j < i; j++)
    {
        printf( " %5d", ip[j] );
        if (((j+1) % 10) == 0)
            printf( "\n" );
    }
    printf( "\n" );
}


void sub( int i )
{
    void *p;
    int j;
    int *ip;


    /* check value of "j" before & after call to alloca to ensure local */
    /* variables are being preserved */
    j = i;
    printf( "sub(): value of j before calling alloca() is %d\n", j );
    p = alloca( i*sizeof(int) );
    printf( "sub(): value of j after calling alloca() is %d\n", j );

    printf( "sub(): addr from alloca() is %p; (j = %d)\n", p, j );

    /* initialize array allocated on stack */
    ip = p;
    for (j = 0; j < i; j++)
        ip[j] = j;

    /* now call subroutine to manipulate alloca'd data */
    sub2( i, ip );
}
 
int main()
{
    sub( 123 );
}

2088.7easy for DEC C to implement on OpenVMS VAX?RDGENG::WOOD_J[email protected]Tue Feb 11 1997 05:205
Are there no plans for DEC C for VAX to implement alloca()?

Wouldn't a built-in __ALLOCA for VAX just have to decrement
the SP by the required amount (-whilst keeping stack longword-
aligned) ?  I.e. wouldn't this be easy to implement?
2088.8there were no plans two years agoHNDYMN::MCCARTHYA Quinn Martin ProductionTue Feb 11 1997 05:537
>>Are there no plans for DEC C for VAX to implement alloca()?

The previous example was written several years ago and at that time there were
no plans to add alloca() to OpenVMS VAX.  I don't think that position has
changed.

bjm
2088.9known failing caseHNDYMN::MCCARTHYA Quinn Martin ProductionTue Feb 11 1997 05:579
As to why it does not work (but a work around was sent to me via mail) may
be the layout of the local variables by the compiler.  

The example assumes that all stack space that will be used by the compiler has
been pre-allocated prior to calling the routine.  If that is not the case, and 
the compiler tries to allocate more memory after the function prologue, then
the example will fail - that's the one case that I know of, there may be more.

bjm
2088.10c-allocaMUCTEC::BECKERHartmut B., VMS &amp; Languages, MunichTue Feb 11 1997 07:578
In the recent kits of gnu emacs and gcc there is a c implementation of alloca.
It allocates memory on the heap, keeps track of the allocated memeory and in
each call checks and cleans up unused memory. As one can see it's different
from the original idea but should be portable. Also I assume it is more
expensive than simple stack manipulation. Maybe it can serve as a
workaround.

Hartmut
2088.11macro my_alloca example HNDYMN::MCCARTHYA Quinn Martin ProductionTue Feb 11 1997 09:1192
A fix to .2 (that has been deleted to avoid bad hacks from getting out :-))

Brian

Try this (I think it modifies the stack in the way you want) - I think it still
compiles (I cut it down from another example).

This is UNSUPPORTED !!


Brian J.

#define alloca my_alloca 

    s = alloca (size);

--------------------------------------
File: my_alloca.mar
--------------------------------------

        .TITLE  my_alloca 

       .page
        .SBTTL  DECLARATIONS

        $SFDEF                  ; stack frame symbols
        .DSABL  GBL             ; Force all external symbols to be declared

        .PSECT  $CODE,PIC,RD,SHR,NOWRT,LONG

	.ENTRY  __my_alloca, ^M<R2,R3,R4,R5>
;
; What we want to do here is adjust the stack pointer ahead by the value
; in 4(ap) and return the pointer to the adjusted stack to the caller in r0
; Note:
;	We do not add the size of this call frame to the 
;	adjusted value because when this routine is called, 
;	this frame is created on the stack, that means we already
;	have 44 bytes allocated (that is:
; 		Handler - Address	 0
;  		PSL			 4
;  		AP			 8
;  		FP			16
;  		PC			20
;  		R2 SAVE			24
;  		R3 SAVE			28
;  		R4 SAVE			32
;  		R5 SAVE			36
;  		ARG COUNT		40
;  		FIRST ARG		44
;
; 	When we move the SP down
;	by the requested amount, and then point FP at that new location,
;	when the RET pops things off the stack, it is taking that
;	44 bytes back off off from the newly adjusted stack.  We are left with
;	exactly the amount requested (plus any padding)
;

	;
	; Add 3 to requested value, then use the BICL2 instruction to
	; make sure the request is a multiple of 4 (longword aligned).  
	; Me, think of using the BICL2 instruction myself? nope.  I checked 
	; other sources for the word align and found several examples.  
	;
	ADDL3	#3, 4(AP), R0	
	BICL2	#3, R0
	; 
	; Move the stack down requested amount
	;
	SUBL	R0, SP
	;
	; Move the contents of the current frame into the area we just 
	; allocated on the stack. 
	;
	MOVC3	#44, (FP), (SP)
	;
	; Add the size of this frame (44 bytes) to the current SP and
	; that is the address of the stack storage requested. 
	;
        ADDL3	#44, SP, R0
	;
	; The last thing to do is to change the frame pointer to be where we
	; moved the SP to.  This will cause the RET statement to clear this
	; "new" stack off the frame and set SP to the location at the bottom
	; of the stack.
	; 
	MOVL	SP, FP

	RET

	.END

2088.12Currently no plans for alloca on VAXCXXC::REPETERich Peterson 381-1802 ZKO2-3/N30Tue Feb 11 1997 15:4215
If it were as easy for the compiler to do as decrementing SP, then the
original idea of having a little macro routine do just that would have
worked.  But of course this showed the problem that the compiled code
bases its addressing of locals off of SP, assuming a compile-time
fixed size stack frame.  So the "easy" fix in the compiler is to
implement and test a different addressing model that sets up and
addresses locals off of FP instead of SP in any function containing
a call to (builtin) alloca.  This is exactly what the GEM-based Alpha
compiler does.

Given the length of time that VAX C and DEC C on VAX have have survived
without an alloca, and given the VAX-specific engineering and testing
investment needed to get this on VAX safely (this part of the compiler
is written in MACRO), there would have to be some major commitment to
new VAX orders hinging on it to make it worthwhile...
2088.13thanksRDGENG::WOOD_J[email protected]Wed Feb 12 1997 03:196
    Thanks for all the replies.
    
    Hopefully the Macro workaround will be adequate for the s/w vendor.
    
    Regards,
      John
2088.14A C version of alloca ... uses a private stack ...HPCGRP::MANLEYWed Feb 12 1997 13:0195
John,

>    Hopefully the Macro workaround will be adequate for the s/w vendor.

If the generated code uses SP as a base register for temporary local stack
resident data, as .0 and some of the replies seem to indicate, the macro
workaround will not fix the problem.

The code below mimics alloca behavior by creating (and managing?) a private
stack. Its operation should not interfere with the compiler's use of SP. It
seems to work fine with your test program.

        - Dwight -

--------------------------------------------------------------------------------


/*
	Written: 12-February-1997, D.P Manley, Digital Equipment Corporation.

	This subroutine was written to mimic the behavior of alloca on OpenVMS
	VAX. It creates and manages a 1MB private stack apart from the real
	stack, and will not interfere with compiler use of SP as a base address.

	NOTE -  The technique used to reclaim stack space assigned to inactive
		call frames is imperfect and you may need to adjust stack size
		accordingly.
*/

#pragma builtins

#define ALLOCA_STACK_SIZE 262144		/* A 1MB private stack	      */
#define ALLOCA_CALL_DEPTH 1024			/* A 1024 deep call tree      */
#define FP 13					/* R13 is the Frame Pointer   */
/*
	The first call frame is forced to be located at the top of P1 space.
	It's stack index is set to the top of the stack.
*/	
static	long	*ALLOCA_FP[ ALLOCA_CALL_DEPTH+1 ] = {0x7ffffff0,0};
static	long	ALLOCA_SP[  ALLOCA_CALL_DEPTH+1 ] = {ALLOCA_STACK_SIZE,0};
static 	long 	ALLOCA_STACK[ ALLOCA_STACK_SIZE ];

void	*alloca( int size )
{	int  i,index;
        long *alloca_frame,current_frame;
/* 
        Longword count requested
*/
	index = ( size+3 >> 2 );
/*
	Get alloca's frame pointer, and from it, get caller's frame pointer.
*/
        alloca_frame  = _READ_GPR(FP);
        current_frame = alloca_frame[3];
/* 
	Search the FP stack for the caller's frame pointer or the correct
	place to insert it.
*/
	for( i=0;i<ALLOCA_CALL_DEPTH, current_frame<ALLOCA_FP[i];i++ );
/*
	If the exceeded frame stack depth has been exceeded, return a null
	pointer.
*/
        if( i == ALLOCA_CALL_DEPTH ) return( 0 );
/*
	If the current frame is found on the frame stack, then adjust its 
	stack index. Otherwise, push the current frame onto the frame stack
	and generate its stack index from the previous stack index and the
	request size.
*/
        if( current_frame == ALLOCA_FP[i] )	
	   ALLOCA_SP[i]-=index;
	else{
	   ALLOCA_FP[i] = current_frame;
	   ALLOCA_SP[i] = ALLOCA_SP[i-1]-index;
	}
/*
	The next two fields are cleared, because no active call frames exist
	below the current frame. Clearing these fields ensures that no future
	frame gets inserted below an inactive frame.
*/
        ALLOCA_FP[i+1] = 0;
	ALLOCA_SP[i+1] = 0;
/*
	If the stack index for the current frame has been decremented below
	zero, return a null pointer. Otherwise, return the address of the
	allocated stack entry.
*/
	if( ALLOCA_SP[i] < 0 )
           return( 0 );
        else
           return(&ALLOCA_STACK[ALLOCA_SP[i]]);
}

2088.15product manager for DEC C for OpenVMS VAX?RDGENG::WOOD_J[email protected]Mon Feb 17 1997 04:448
The s/w vendor is not happy with any of the proposed solutions.

Who is the Product Manager for DEC C for OpenVMS VAX, so that
I can get an official response please?

Thanks,
  John Wood
  Software Partner Engineering
2088.16VTX IR Has PM InformationXDELTA::HOFFMANSteve, OpenVMS EngineeringMon Feb 17 1997 11:0122
:The s/w vendor is not happy with any of the proposed solutions.

   Interesting -- the customer is objecting to a non-standard feature
   that's known to cause problems in most implementations that even
   have it.  (I can understand their, uh, disappointment here -- they
   might want to look at C++ constructor and destructors, or at recoding
   their application(s) to use standard interfaces and routines.)

:Who is the Product Manager for DEC C for OpenVMS VAX, so that
:I can get an official response please?

   From VTX IR:

DEC C V5.2 for OpenVMS

CONTACTS:

Corporate: Anne Persels (Product Manager), DTN 381-0992, (603) 881-0992,
           ZKO, [email protected]
           Alan Belancik (Product Marketing), DTN 381-0363, (603) 881-0363,
           ZKO, [email protected]

2088.17DECCXL::OUELLETTEWed Feb 19 1997 17:354
Anne Persels is the DEC C for VMS product manager.
Alan Belancik is doing something different now (data warehousing?).

R.