This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]