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