alignment attribute for stack allocated objects

2006-12-19 Thread Maurizio Vitale
I'm tying to hunt down the cause of a bug I'm experiencing and it all  
boils down to a possible misunderstanding

on my part on the semantics of the 'aligned' attribute.

Is the 'aligned' attribute supposed to work for objects allocated on  
the stack (I'm on x86_64, gcc 4.1.1)?


The only caveat in the GCC documentation is about the linker not  
being able to honor an alignment
request, but I'd guess that applies to globals. For dynamic and auto  
allocation seems to me that
GCC has to generate the appropriate alignment code, but I haven't  
found any distinction between

different types of allocations in the documentations.

Thanks,

Maurizio






Re: Coroutines

2006-06-17 Thread Maurizio Vitale
I'm looking at the very same problem, hoping to get very lightweight  
user-level threads for use in discrete event simulation.


It would be very nice if it was possible to write an inlined piece of  
assembler that saved the program counter and the stack pointer and  
then be able to say to GCC that everything is clobbered by those few  
lines of assembler.
Ideally this clobber should include all registers, including callee- 
saved registers, otherwise you need to explicitly save at least  
those. With that "über"-clobber I think it would be possible to  
implement very cheap context switches, where only the registers that  
GCC knows are required when resuming the context are actually saved.
All attempts to say clobber-all that I've made result in problems,  
typically failure to reload.


Is there a safe way to say to GCC that everything is clobbered in a  
way that is safe across all possible optimization settings?

I'm particularly interested in the x86_64 target.

On a side note, when writing this type of context-switching code one  
would often need to insert (local) labels in the assembler to serve  
as target for thread resumption. GCC is very aggressive in removing  
labels which according to C/C++ semantics he can prove are never  
reached. It would be nice to have an attribute to say "please, GCC,  
for reasons I cannot explain to you, this label will actually be  
reached eventually".
This is particularly useful combined with the "über"-clobber of  
above, otherwise GCC could easily convince himself that not too much  
needs to be saved.


-- Maurizio

On Jun 17, 2006, at 5:28 AM, Gabriel Dos Reis wrote:


Andrew Haley <[EMAIL PROTECTED]> writes:

| Dustin Laurence writes:
|  > On Fri, Jun 16, 2006 at 02:05:13PM -0700, Mike Stump wrote:
|  >
|  > > If every language were going to have the feature, then,  
moving it
|  > > down into the mid-end or back-end might make sense, but I  
don't think

|  > > it does in this case.
|  >
|  > Personally, I'd like, and use, decent coroutines in C.  But  
perhaps I am

|  > the only one.
|  >
|  > > I wouldn't start with pthreads I don't think.
|  >
|  > That was my thought--I played with it some but I intended it  
as a bit of
|  > threads practice.  Using threads to emulate a synchronous  
construct just

|  > seems *wrong.*
|
| You need a way to switch from one stack to another, but why not  
leave

| open the possibility of implementing this in a number of different
| ways?

Yup.

| You need detach() and resume() [in Simula notation] and these
| can be provided either by low-level stack-switching or by invoking a
| pthreads library.

I wouldn't use a thread library because many uses of coroutine are to
implement low-cost, efficient, alternatives to thread where, for  
example,

the full power of threads are not essential.

-- Gaby






x86_64 ABI

2006-07-13 Thread Maurizio Vitale
my understanding of the x86_64 ABI is that the following structure  
should be passed in registers:


struct data {
unsigned int x;
unsigned int y;
unsigned long z;
};

but when I compile:

#include 

struct data {
  unsigned int  x   : 32;
  unsigned int  y   : 32;
  unsigned long dummy   : 64;
} ;

#ifdef __cplusplus
extern "C" int foo (data t);
#else
extern int foo (struct data t);
#endif

#ifndef __cplusplus
struct
#endif
datad;

int
main (int argc, char* argv[])
{
  d.x = 1; d.y = 2;

  printf ("an integer %d", foo(d));

  return 0;
}

I get different results, depending on whether I compile it as C or C+ 
+ code. I'm using gcc 4.1.1 (but the same happens with 3.4.5).


In C I get:
main:
.LFB12:
subq$8, %rsp
.LCFI0:
movl$1, d+8(%rip)
movl$2, d+12(%rip)
movqd(%rip), %rdi
movqd+8(%rip), %rsi
callfoo

so the argument gets passed in registers.

But in C++ the result is different and the data structure is passed  
on the stack.

main:
.LFB13:
subq$24, %rsp
.LCFI0:
movl$1, d+8(%rip)
movqd(%rip), %rdi
movl$2, d+12(%rip)
movqd+8(%rip), %rsi
movq%rdi, (%rsp)
movq%rsi, 8(%rsp)
callfoo

My understanding of the ABI is that the data structure should be  
passed in registers, but in any case the behavior should be the same  
for C and C++ when data is POD. In the example if foo was a C  
function the code produced by g++ would be wrong. In this case it  
would also be very dangerous because the data structure happens to be  
_also_ in the right registers, but I expect small changes to the code  
to make it fail.
Unless g++ is actually passing the argument in registers and what's  
wrong is the spurious pushes onto the stack.


Maurizio Vitale





x86_64 ABI

2007-08-08 Thread Maurizio Vitale

with reference to the following:

  struct data {
data (long v) : m_data (v) {}
data (const data&) {}
long  m_data;
  };

  data foo (data v) {
return v;
  }

my reading of the x86_64 ABI (v .98, sept 2006) on page 17 is that
data should have class MEMORY when passed as argument to function foo.
This because it has a non-trivial copy constructor 
(it is not implicitely declared).

But GCC 4.1.1 and a more recent version from svn give (for foo):

  .globl _Z3foo4data
  .type   _Z3foo4data, @function
  _Z3foo4data:
  .LFB8:
  movq%rdi, %rax
  ret
  .LFE8:

[so v is passed in a register]

The gimple dump (from the svn version) is:

  data::data(long int) (this, v)
  {
this->m_data = v;
  }


  data::data(const data&) (this, D.2481)
  {

  }


  data foo(data) (v)
  {
struct data & D.2509;

D.2509 = ;
__comp_ctor  (D.2509, v);
return ;
  }

which seems to confirm v in a register.

So the question is whether my reading of the ABI is wrong (and why).
Thanks a lot and best regards,

   Maurizio