On Wed, Nov 4, 2020 at 7:33 PM Uros Bizjak via Gcc <gcc@gcc.gnu.org> wrote: > > Hello! > > I was looking at the recent linux patch series [1] where segment > qualifiers (named address spaces) were introduced to handle percpu > variables. In the patch [2], the author mentions that: > > --q-- > Unfortunately, gcc does not provide a way to remove segment > qualifiers, which is needed to use typeof() to create local instances > of the per-cpu variable. For this reason, do not use the segment > qualifier for per-cpu variables, and do casting using the segment > qualifier instead. > --/q-- > > The core of the problem can be seen with the following testcase: > > --cut here-- > #define foo(_var) \ > ({ \ > typeof(_var) tmp__; \
Looks like writing typeof((typeof(_var))0) tmp__; makes it work. Assumes there's a literal zero for the type of course. Basically I try to get at a rvalue for the typeof. Is there a way to query the address space of an object so I can put another variable in the same address space? > asm ("mov %1, %0" : "=r"(tmp__) : "m"(_var)); \ > tmp__; \ > }) > > __seg_fs int x; > > int test (void) > { > int y; > > y = foo (x); > return y; > } > --cut here-- > > when compiled with -O2 for x86 target, the compiler reports: > > pcpu.c: In function ‘test’: > pcpu.c:14:3: error: ‘__seg_fs’ specified for auto variable ‘tmp__’ > > It looks to me that the compiler should remove address space > information when typeof is used, otherwise, there is no way to use > typeof as intended in the above example. > > A related problem is exposed when we want to cast address from the > named address space to a generic address space (e.g. to use it with > LEA): > > --cut here-- > typedef __UINTPTR_TYPE__ uintptr_t; > > __seg_fs int x; > > uintptr_t test (void) > { > uintptr_t *p = (uintptr_t *) &y; uintptr_t *p = (uintptr_t *)(uintptr_t) &y; works around the warning. I think the wording you cite suggests (uintptr_t) &y here, not sure if there's a reliable way to get the lea with just a uintptr_t operand though. > uintptr_t addr; > > asm volatile ("lea %1, %0" : "=r"(addr) : "m"(*p)); > > return addr; > } > --cut here-- > > The gcc documentation advises explicit casts: > > --q-- > This means that explicit casts are required to convert pointers > between these address spaces and the generic address space. In > practice the application should cast to 'uintptr_t' and apply the > segment base offset that it installed previously. > --/q-- > > However, a warning is emitted when compiling the above example: > > pcpu1.c: In function ‘test’: > pcpu1.c:7:18: warning: cast to generic address space pointer from > disjoint __seg_fs address space pointer > > but the desired result is obtained nevertheless. > > lea x(%rip), %rax > > As shown in the referred patchset, named address spaces have quite > some optimization potential, please see [1] for the list. > > [1] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg2053461.html > [2] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg2053462.html > > Uros.