Cygwin: uname: add host machine tag to sysname.
[newlib-cygwin.git] / winsup / cygwin / scripts / gentls_offsets
blob040b5de6b5511ba0adeb248e0c3daba2bc5371c1
1 #!/usr/bin/env bash
2 #set -x
3 input_file=$1
4 output_file=$2
5 tmp_file=/tmp/${output_file}.$$
7 trap "rm -f ${tmp_file}" 0 1 2 15
9 # Preprocess cygtls.h and filter out only the member lines from
10 # class _cygtls to generate an input file for the cross compiler
11 # to generate the member offsets for tlsoffsets-$(target_cpu).h.
12 ${CXXCOMPILE} -E -P "${input_file}" 2> /dev/null | \
13 gawk '
14 BEGIN {
15 # marker is used to split out the member lines from class _cygtls
16 marker=0;
17 # Prepare the input file for the subsequent compiler run.
18 # Prepend value of __CYGTLS_PADSIZE__ so we can compute the offsets
19 # up and down at the same time
20 print "#include \"winsup.h\"";
21 print "#include \"cygtls.h\"";
22 print "extern \"C\" const uint32_t __CYGTLS__start_offset = __CYGTLS_PADSIZE__;";
24 /^class _cygtls$/ {
25 # Ok, bump marker, next we are expecting a "public:" line
26 marker=1;
28 /^public:/ {
29 # We are only interested in the lines between the first (marker == 2)
30 # and the second (marker == 3) "public:" line in class _cygtls. These
31 # are where the members are defined.
32 if (marker > 0) ++marker;
33 if (marker > 2) exit;
36 if (marker == 2 && $1 != "public:") {
37 # Filter out function names
38 $0 = gensub (/\(\*(\w+)\)\s*\([^\)]*\)/, "\\1", "g");
39 # Filter out leading asterisk
40 $NF = gensub (/^\**(\w+)/, "\\1", "g", $NF);
41 # Filter out trailing array expression
42 $NF = gensub (/(\w+)\s*\[[^\]]*\]/, "\\1", "g", $NF);
43 $NF = gensub (/(\w+);/, "\\1", "g", $NF);
44 print "extern \"C\" const uint32_t __CYGTLS__" $NF " = offsetof (class _cygtls, " $NF ");";
47 ' | \
48 # Now run the compiler to generate an assembler file.
49 ${CXXCOMPILE} -x c++ -g0 -S - -o ${tmp_file} && \
50 # The assembler file consists of lines like these:
52 # __CYGTLS__foo
53 # .long 42
54 # .globl __CYGTLS__foo
55 # .align 4
57 # From this info, generate the tlsoffsets file.
58 start_offset=$(gawk '\
59 BEGIN {
60 varname=""
62 /^__CYGTLS__/ {
63 varname = gensub (/__CYGTLS__(\w+):/, "\\1", "g");
65 /\s*\.long\s+/ {
66 if (length (varname) > 0) {
67 if (varname == "start_offset") {
68 print $2;
70 varname = "";
73 ' ${tmp_file}) && \
74 gawk -v start_offset="$start_offset" '\
75 BEGIN {
76 varname=""
78 /^__CYGTLS__/ {
79 varname = gensub (/__CYGTLS__(\w+):/, "\\1", "g");
81 /\s*\.space\s*4/ {
82 if (length (varname) > 0) {
83 printf (".equ _cygtls.%s, %d\n", varname, -start_offset);
84 printf (".equ _cygtls.%s_p, 0\n", varname);
85 varname = "";
88 /\s*\.long\s+/ {
89 if (length (varname) > 0) {
90 if (varname == "start_offset") {
91 printf (".equ _cygtls.%s, -%u\n", varname, start_offset);
92 } else {
93 value = $2;
94 printf (".equ _cygtls.%s, %d\n", varname, value - start_offset);
95 printf (".equ _cygtls.%s_p, %d\n", varname, value);
97 varname = "";
100 ' ${tmp_file} > "${output_file}"
101 # Check if the `context' member is 16 bytes aligned. Delete output_file
102 # and bail out with error if not.
103 MOD=$(awk '/_cygtls.context_p/{ print $3 % 16; }' "${output_file}")
104 if [ $MOD -ne 0 ]
105 then
106 echo "Error: _cygtls.context member is not 16 bytes aligned!"
107 rm "${output_file}"
108 exit 1