typeof and operands in named address spaces

Richard Biener richard.guenther@gmail.com
Thu Nov 5 09:45:59 GMT 2020


On Thu, Nov 5, 2020 at 9:56 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Thu, Nov 5, 2020 at 8:26 AM Richard Biener
> <richard.guenther@gmail.com> wrote:
> >
> > 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.
>
> This is very limiting assumption, which already breaks for the following test:
>
> --cut here--
> typedef struct { short a; short b; } pair_t;
>
> #define foo(_var)                     \
>   ({                             \
>     typeof((typeof(_var))0) tmp__;             \
>     asm ("mov %1, %0" : "=r"(tmp__) : "m"(_var));    \
>     tmp__;                         \
>   })
>
> __seg_fs pair_t x;
>
> pair_t
> test (void)
> {
>   pair_t y;
>
>   y = foo (x);
>   return y;
> }
> --cut here--
>
> So, what about introducing e.g. typeof_noas (not sure about the name)
> that would simply strip the address space from typeof?

Well, I think we should fix typeof to not retain the address space.  It's
probably our implementation detail of having those in TYPE_QUALS
that exposes the issue and not standard mandated.

The rvalue trick is to avoid depending on a "fixed" GCC.

Joseph should know how typeof should behave here.

Richard.

> > 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?
>
> I think that would go hand in hand with the above typeof_noas. Perhaps
> typeof_as, that would return the address space of the variable?
>
> > >     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;
>
> Indeed, this works as expected.
>
> > 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.
>
> No, because we have to use the "m" constraint for the LEA. We get the
> following error:
>
> as1.c:10:49: error: memory input 1 is not directly addressable
>
> Uros.


More information about the Gcc mailing list