alignment attribute for stack allocated objects
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
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
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
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