/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* this code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */

#include <stdio.h>

// Try to determine the vtable layout generated by G++
// Produces the offset at which the first vtable entry can be
// found, and the factor to apply for subsequent entries on stdout.
// Example output:
//    #define GCC_VTABLE_START        0xc
//    #define GCC_VTABLE_FACTOR       0x8

class test {
public:
      virtual int     t1(void);
      virtual int     t2(void);
      int             x;
};

test::test() { this->x = 0x12121212; };

int test::t1(void) { return 1; }
int test::t2(void) { return 2; }

void die(char *x) {
      fprintf(stderr, "%s\n", x);
      exit(1);
}

int 
main()
{
      int             i;
      test           *t = new test();
      int            *tp = (int *) t;
      int             off1 = -1;
      int             off2 = -1;
      int             factor;
      int             factorshift;

      if (*tp++ != 0x12121212)
              die("Integer element test::x not found!");
      tp = (int *) *tp;
      for (i = 0; i < 10; i++) {
              if (tp[i] == (int) t->t1)
                      off1 = i;
              if (tp[i] == (int) t->t2)
                      off2 = i;
      }
      if (off1 == -1 || off2 == -1)
              die("Could not determine offset into vtable!");
      factor = (off2 - off1) * 4;
      factorshift = -1;
      while (factor) {
              factorshift++;
              factor >>= 1;
      }
      printf("/* Automatically generated by vtable_layout_x86.cpp */\n");
      printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4);
      printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4);
      printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift);
      exit(0);
}
