This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: indirect function support
On Tue, May 18, 2010 at 3:37 PM, Nathan Sidwell <nathan@codesourcery.com> wrote:
> H.J. Lu wrote:
>
>> Is that a good idea to ask programmers to do name mangling by
>> hand? ?It can be quite complicated for ?complex C++ classes
>> and they have to update the alias when member functions are changed.
>> We need to make it easy to use.
>
> The alias attribute already requires this (for non-member functions, for
> member functions, alias was simply broken). ?While it would be nice to
> improve alias, I don't see why that should be a requirement of adding ifunc
> support to alias.
It is not about adding ifunc support to alias. It is about providing a user
friendly ifunc implementation.
> Do you have a use case of using ifunc for member functions? ?Perhaps that
> would help.
>
I am enclosing a C++ testcase for my ifunc attribute proposal. It shows
how one can use ifunc on member functions.
How does your proposal work with C++ template and C++ member function
overload?
Thanks.
--
H.J.
---
/* This is a demo for STT_GNU_IFUNC. See ifunc.txt at
http://groups.google.com/group/generic-abi
*/
#include <stdio.h>
#include <cpuid.h>
#include <iostream>
using namespace std;
class cpuid
{
private:
static void x86 (void)
{
printf ("I am an x86\n");
}
static void sse (void)
{
printf ("I have SSE\n");
}
static void sse2 (void)
{
printf ("I have SSE2\n");
}
static void sse3 (void)
{
printf ("I have SSE3\n");
}
static void ssse3 (void)
{
printf ("I have SSSE3\n");
}
static void sse4_1 (void)
{
printf ("I have SSE4.1\n");
}
static void sse4_2 (void)
{
printf ("I have SSE4.2\n");
}
public:
/* feature is an indirec function. */
static void __attribute__ ((ifunc)) feature (void)
{
unsigned int eax, ebx, ecx, edx;
__cpuid (1, eax, ebx, ecx, edx);
if (ecx & bit_SSE4_2)
return cpuid::sse4_2;
if (ecx & bit_SSE4_1)
return cpuid::sse4_1;
if (ecx & bit_SSSE3)
return cpuid::ssse3;
if (ecx & bit_SSE3)
return cpuid::sse3;
if (edx & bit_SSE2)
return cpuid::sse2;
if (edx & bit_SSE)
return cpuid::sse;
return cpuid::x86;
}
};
class long_mode
{
private:
void lm_yes (void)
{
printf ("I support 64bit.\n");
}
void lm_no (void)
{
printf ("I don't support 64bit.\n");
}
public:
/* lm is an indirec function. */
void __attribute__ ((ifunc)) lm (void)
{
unsigned int eax, ebx, ecx, edx;
__cpuid (0x80000001, eax, ebx, ecx, edx);
if (edx & bit_LM)
return &long_mode::lm_yes;
else
return &long_mode::lm_no;
}
};
class Foo
{
private:
virtual void foo1 ()
{
printf ("I am %s\n", __PRETTY_FUNCTION__);
}
public:
virtual void __attribute__ ((ifunc)) foo ()
{
return &Foo::foo1;
}
};
class Bar : public Foo
{
private:
void foo1 ()
{
printf ("I am %s\n", __PRETTY_FUNCTION__);
}
public:
void foo ()
{
printf ("I am %s\n", __PRETTY_FUNCTION__);
}
};
class X
{
private:
virtual void foo1 ()
{
printf ("I am %s\n", __PRETTY_FUNCTION__);
}
virtual void foo1 (int x)
{
printf ("%d: I am %s\n", x, __PRETTY_FUNCTION__);
}
public:
virtual void foo ();
virtual void foo (int);
};
void
__attribute__ ((ifunc))
X::foo ()
{
return &X::foo1;
}
void
__attribute__ ((ifunc))
X::foo (int)
{
return &X::foo1;
}
class Y : public X
{
private:
void foo1 ()
{
printf ("I am %s\n", __PRETTY_FUNCTION__);
}
void foo1 (int x)
{
printf ("%d: I am %s\n", x, __PRETTY_FUNCTION__);
}
public:
void foo ()
{
printf ("I am %s\n", __PRETTY_FUNCTION__);
}
void foo (int x)
{
printf ("%d: I am %s\n", x, __PRETTY_FUNCTION__);
}
};
template <class T>
class Z
{
private:
virtual void foo1 ()
{
cout << __PRETTY_FUNCTION__ << endl;
}
virtual void foo1 (T x)
{
cout << x << ": " << __PRETTY_FUNCTION__ << endl;
}
public:
virtual void foo ();
virtual void foo (int);
};
template <class T>
void
__attribute__ ((ifunc))
Z<T>::foo ()
{
return &Z<T>::foo1;
}
template <class T>
void
__attribute__ ((ifunc))
Z<T>::foo (int)
{
return &Z<T>::foo1;
}
template <class T>
class FOO : public Z<T>
{
private:
void foo1 ()
{
cout << __PRETTY_FUNCTION__ << endl;
}
void foo1 (T x)
{
cout << x << ": " << __PRETTY_FUNCTION__ << endl;
}
public:
void foo ()
{
cout << __PRETTY_FUNCTION__ << endl;
}
void foo (int x)
{
cout << x << ": " << __PRETTY_FUNCTION__ << endl;
}
};
int
main ()
{
int i;
class cpuid c;
class long_mode l;
/* Run it under gdb to see how feature and lm are called. */
for (i = 0; i < 5; i++)
{
c.feature ();
l.lm ();
}
Foo f;
f.foo ();
Bar b;
b.foo ();
X x;
x.foo ();
x.foo (30);
Y y;
y.foo ();
y.foo (50);
Z<int> z;
z.foo ();
z.foo (300);
FOO<int> foo;
foo.foo ();
foo.foo (-300);
return 0;
}