[comp.sources.d] Simulation of 'alloca' -- can it be done in TurboC or MSC?

mike2@lcuxa.UUCP (M S Slomin) (05/19/88)

Quick question: has anyone worked out a way to simulate the 'alloca'
function in either TurboC or MSC (DOS for those who don't know)?

Alloca is a memory allocation analogue to an automatic variable.  Just
as an automatic variable exists only while a function is in progress,
alloca allocates memory only while a function is in progress, and when
the function exits that memory is freed.  Obviously, this can be 
implemented with malloc/free combinations, but the automatic approach
seems cleaner, which perhaps explains why many programmers use alloca
if it is available.  It would be nice to implement this.

Thanks for the help.

					Mike Slomin
					bellcore!lcuxa!mike2

dg@lakart.UUCP (David Goodenough) (05/24/88)

From article <203@lcuxa.UUCP>, by mike2@lcuxa.UUCP (M S Slomin):
> Quick question: has anyone worked out a way to simulate the 'alloca'
> function in either TurboC or MSC (DOS for those who don't know)?

Write it in assembler. I don't know how to do alloca in C in a portable
manner. Come to that - since you have to mess with your frame/stack pointer
I don't think it can be done in anything other than assembler. Sure can't
on a z80.

CAVEAT for my z80 implementetion, you are advised NOT TO USE in a complex
expression (where temp results need to be stacked)  think about it!!

.extern	_alloca
_alloca:
	pop	de
	pop	hl
	call	#neg			; negate argument
	add	hl,sp			; allocate the space
	push	hl
	push	de			; put args back so return works
	ret				; home we go - hl points to space.

This should be fairly easy to convert to 8086 assembler (What, your C compiler
can't talk in assembler?? :-) Different segments may be a pain - this space
will be in SS:, and I can just see referencing through a 16 bit pointer as DS:
UGH!!. Still if you send back a 32 bit pointer SEG:OFFSET or make sure
DS: and SS: are the same, you should be flying.
-- 
	dg@lakart.UUCP - David Goodenough		+---+
							| +-+-+
	....... !harvard!adelie!cfisun!lakart!dg	+-+-+ |
						  	  +---+

kent@happym.UUCP (Kent Forschmiedt) (05/26/88)

I don't know about TurboC, but MSC seems to use a conventional stack 
structure.  The alloca() that I use actually uses malloc() and 
free(), but saves a tag pointing to the current stack frame whenever 
a block is alloca()'d.  When alloca() is called, it free()'s all of 
the blocks whose tags point below (on a down-growing stack) the 
current frame.  I think that this scheme will work with any 
implementation that uses a real stack, but probably not if frames 
are randomly allocated from a heap, and I doubt that TurboC uses 
such an unconventional scheme. 
-- 
--
	Kent Forschmiedt -- kent@happym.UUCP, tikal!camco!happym!kent
	Happy Man Corporation  206-282-9598

darrylo@hpsrli.HP.COM (Darryl Okahata) (05/28/88)

In comp.sources.d, dg@lakart.UUCP (David Goodenough) writes:

> From article <203@lcuxa.UUCP>, by mike2@lcuxa.UUCP (M S Slomin):
> > Quick question: has anyone worked out a way to simulate the 'alloca'
> > function in either TurboC or MSC (DOS for those who don't know)?
> 
> Write it in assembler. I don't know how to do alloca in C in a portable
     [ ... ]
> .extern	_alloca
> _alloca:
> 	pop	de
> 	pop	hl
> 	call	#neg			; negate argument
> 	add	hl,sp			; allocate the space
> 	push	hl
> 	push	de			; put args back so return works
> 	ret				; home we go - hl points to space.
> 
> This should be fairly easy to convert to 8086 assembler (What, your C compiler
> can't talk in assembler?? :-) Different segments may be a pain - this space
     [ ... ]

     Whoa, it's not as easy as it seems.  Take the following code fragment,
for example:

	foo(a)
	int	a;
	{
		char	*here;

		here = NULL;
		if (a == 17) {
			char	*there;

			there = alloca(SOME_NUMBER);
			bar(there);
			here = there;
		}
		blech(here);
	}

The problem in the above code fragment is that the stack frame allocated at
the start of the if statement block is deallocated at the end of the block.
If the above Z80 code was translated into 80x8x code (taking care to move
the stack pointer BELOW the allocated area because of interrupts), that
code will not work for the above code fragment.  Why?  Because, at the end
of the if block, code will be generated to reset the stack pointer to the
value it had at the beginning of the if block (and, chances are, if a
simple ADD SP,n is used, the system will eventually crash because the stack
pointer was modified by alloca() and is not where it should be).

> 	dg@lakart.UUCP - David Goodenough		+---+
> 							| +-+-+
> 	....... !harvard!adelie!cfisun!lakart!dg	+-+-+ |
> 						  	  +---+

     -- Darryl Okahata
	{hplabs!hpccc!, hpfcla!} hpsrla!darrylo
	CompuServe: 75206,3074

Disclaimer: the above is the author's personal opinion and is not the
opinion or policy of his employer or of the little green men that
have been following him all day.

skip@skipnyc.UUCP (Skip Gilbrech) (05/28/88)

In article <203@lcuxa.UUCP> mike2@lcuxa.UUCP (M S Slomin) writes:
>Quick question: has anyone worked out a way to simulate the 'alloca'
>function in either TurboC or MSC (DOS for those who don't know)?

I hate to point this out ;-) but MSC has had 'alloca' in their library
at least since the 4.0 release... Check out the library reference
(don't know about TurboC).
-- 
Skip Gilbrech                           UUCP: uunet!pwcmrd!skip
PaineWebber, NYC                              attmail!skipnyc!skip

james@bigtex.uucp (James Van Artsdalen) (05/28/88)

IN article <134@lakart.UUCP>, dg@lakart.UUCP (David Goodenough) wrote:
> From article <203@lcuxa.UUCP>, by mike2@lcuxa.UUCP (M S Slomin):
> > Quick question: has anyone worked out a way to simulate the 'alloca'
> > function in either TurboC or MSC (DOS for those who don't know)?

MS-C 5.0 has alloca().

> Write it in assembler. I don't know how to do alloca in C in a portable
> manner. Come to that - since you have to mess with your frame/stack pointer
> I don't think it can be done in anything other than assembler. Sure can't
> on a z80.

There is a version in C in the GNU gawk distribution.  I can mail it to anyone
who can't get it from the archives.  I doubt it's quick, but it is supposed
to be portable.  They use malloc() to allocate, and some heuristic to detect
when the stack pointer is different than it was the last invocation: I'm not
sure of exactly how they work it.

> This should be fairly easy to convert to 8086 assembler (What, your C compiler
> can't talk in assembler?? :-) Different segments may be a pain - this space
> will be in SS:, and I can just see referencing through a 16 bit pointer as DS:
> UGH!!. Still if you send back a 32 bit pointer SEG:OFFSET or make sure
> DS: and SS: are the same, you should be flying.

DS: and ES: are typically going to be the same in a small model program (or
in native 386 mode).  For Microport 386, I just put this in my malloc.h
include file:

asm char *alloca(n)
{
%mem	n
	subl	n,  %esp
	andl	$-4, %esp
	mov	%esp,%eax
%reg	n
	subl	n,  %esp
	andl	$-4, %esp
	mov	%esp,%eax
%con	n
	subl	n,  %esp
	andl	$-4, %esp
	mov	%esp,%eax
}

Note that it longword-aligns the allocated area.
-- 
James R. Van Artsdalen   ...!ut-sally!utastro!bigtex!james   "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

james@bigtex.uucp (James Van Artsdalen) (05/30/88)

IN article <3100002@hpsrli.HP.COM>, darrylo@hpsrli.HP.COM (Darryl Okahata) wrote:
> [ code fragment deleted ]
> The problem in the above code fragment is that the stack frame allocated at
> the start of the if statement block is deallocated at the end of the block.

As near as I can tell, that is indeed the nature of alloca(), and hence the
code in question is not in error.  Perhaps some Joe Vaxhacker out there can
say what the BSD code really does.  The Microsoft C code does what the 8080
code shown in the original posting did, and my alloca() has gotten away with
it too thus far.

The BSD 4.3 manuals are, shall we say, somewhat less than definitive on the
matter.
-- 
James R. Van Artsdalen   ...!ut-sally!utastro!bigtex!james   "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

mouse@mcgill-vision.UUCP (der Mouse) (06/03/88)

In article <443@happym.UUCP>, kent@happym.UUCP (Kent Forschmiedt) writes:
> I don't know about TurboC, but MSC seems to use a conventional stack
> structure.  The alloca() that I use actually uses malloc() and
> free(), but saves a tag pointing to the current stack frame whenever
> a block is alloca()'d.  When alloca() is called, it free()'s all of
> the blocks whose tags point below (on a down-growing stack) the
> current frame.  I think that this scheme will work with any
> implementation that uses a real stack, [...]

I doubt it.  How about

main()
{
 while (1)
  { test();
  }
}

test()
{
 char *foo;
 char *alloca();

 foo = alloca(10);
}

With a proper alloca() (free on return), this will be an infinite loop.
With the scheme you suggest, it will slowly chew up memory, ten bytes
at a crack.  Unless you have some scheme for putting serial numbers in
stack frames, so you can tell one call to test() from the next....

					der Mouse

			uucp: mouse@mcgill-vision.uucp
			arpa: mouse@larry.mcrcim.mcgill.edu