| #!/usr/bin/perl -s |
| # |
| # This file is part of Cygwin. |
| # |
| # This software is a copyrighted work licensed under the terms of the |
| # Cygwin license. Please consult the file "CYGWIN_LICENSE" for |
| # details. |
| # |
| my $tls = shift; |
| my $tls_out = shift; |
| my $tgt = shift; |
| # FIXME? This method obviously requires a 64 bit OS to build tlsoffsets64.h |
| # Another method which doesn't requires to run an executable would be to |
| # generate assembler code accessing the various struct members and analyzing |
| # it, but that's arguably a lot more effort. |
| my $tgt_opt = $tgt eq 'x86_64' ? '-m64' : '-m32'; |
| open TLS, '<', $tls or die "$0: couldn't open tls file \"$tls\" - $!\n"; |
| my $struct = ''; |
| my @fields = (); |
| my $def = ''; |
| $tls = join('', <TLS>); |
| $tls =~ s/\A.*\n#pragma once\n//os; |
| $tls =~ s/\n[^\n]*gentls_offsets[^\n]*\n(.+)\Z/$1/os; |
| my $pre = $`; |
| substr($tls, 0, length($pre)) = ''; |
| $pre .= "\n//*/"; |
| $tls =~ s%/\*\s*gentls_offsets.*?/\*\s*gentls_offsets\s*\*/%%ogs; |
| foreach ($tls =~ /^.*\n/mg) { |
| /^}|\s*(?:typedef|const)/o and do { |
| $def .= $_ ; |
| next; |
| }; |
| $def .= $_ if $struct; |
| if (!s/;.*$//o) { |
| if (!$struct && /^\s*(?:struct|class)\s*([a-z_0-9]+)/o) { |
| $def .= $_; |
| $struct = $1 |
| } |
| next; |
| } |
| s/(?:\[[^\]]*\]|struct|class)//o; |
| s/^\s+\S+\s+//o; |
| s/[\*\s()]+//go; |
| for my $f (split(/,/)) { |
| push(@fields, $f); |
| } |
| } |
| close TLS; |
| open TMP, '>', "/tmp/$$.cc" or die "$0: couldn't open temporary index file \"/tmp/$$.c\" - $!\n"; |
| print TMP <<EOF; |
| #define __INSIDE_CYGWIN__ |
| #ifndef __x86_64__ |
| #define __attribute__(X) |
| #endif |
| #define __reg1 |
| #define __reg2 |
| #define __reg3 |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <signal.h> |
| #include <windows.h> |
| $pre |
| $def |
| int |
| main(int argc, char **argv) |
| { |
| $struct *foo; |
| # define foo_beg ((char *) foo) |
| # define offset(f) ((unsigned)((int) (((char *) &(foo->f)) - foo_beg) - CYGTLS_PADSIZE)) |
| # define poffset(f) ((unsigned)(((char *) &(foo->f)) - ((char *) foo))) |
| EOF |
| print TMP 'puts ("//;# autogenerated: Do not edit.\n");', "\n\n"; |
| print TMP "printf (\"//; \$tls::start_offset = -%d;\\n\", CYGTLS_PADSIZE);\n"; |
| for my $f (@fields) { |
| print TMP ' printf ("//; $tls::', $f, ' = %d;\n", ', "offset($f));\n"; |
| print TMP ' printf ("//; $tls::p', $f, ' = %d;\n", ', "poffset($f));\n"; |
| } |
| print TMP ' puts ("//; __DATA__\n");', "\n"; |
| for my $f (@fields) { |
| print TMP ' printf ("#define tls_', $f, ' (%d)\n", ', "offset($f));\n"; |
| print TMP ' printf ("#define tls_p', $f, ' (%d)\n", ', "poffset($f));\n"; |
| } |
| |
| print TMP <<EOF; |
| |
| exit (0); |
| } |
| EOF |
| close TMP; |
| my @avoid_headers = qw'-D_XMMINTRIN_H_INCLUDED -D_ADXINTRIN_H_INCLUDED -D_EMMINTRIN_H_INCLUDED -D_X86INTRIN_H_INCLUDED'; |
| my @cmd = (@ARGV, @avoid_headers, '-o', "/tmp/$$-1.cc", '-E', "/tmp/$$.cc"); |
| $ENV{CCWRAP_VERBOSE}=1; |
| system @cmd; |
| system 'g++', "$tgt_opt", '-o', "/tmp/$$.a.out", "/tmp/$$-1.cc" and |
| ($? == 127 && system 'c++', "$tgt_opt", '-o', "/tmp/$$.a.out", "/tmp/$$-1.cc") and |
| die "$0: couldn't generate executable for offset calculation \"/tmp/$$.a.out\" - $!\n"; |
| open TLS_OUT, '>', $tls_out or die "$0: couldn't open tls index file \"$tls_out\" - $!\n"; |
| open OFFS, '-|', "/tmp/$$.a.out" or die "$0: couldn't run \"/tmp/$$.a.out\" - $!\n"; |
| print TLS_OUT <OFFS>; |
| close OFFS; |
| close TLS_OUT; |
| unlink "/tmp/$$.cc", "/tmp/$$-1.cc", "/tmp/$$-1.d", "/tmp/$$.a.out"; |
| exit(0); |