Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/scripts/gentls_offsets')
-rwxr-xr-xwinsup/cygwin/scripts/gentls_offsets100
1 files changed, 100 insertions, 0 deletions
diff --git a/winsup/cygwin/scripts/gentls_offsets b/winsup/cygwin/scripts/gentls_offsets
new file mode 100755
index 000000000..0adb702a3
--- /dev/null
+++ b/winsup/cygwin/scripts/gentls_offsets
@@ -0,0 +1,100 @@
+#!/usr/bin/env bash
+#set -x
+input_file=$1
+output_file=$2
+tmp_file=/tmp/${output_file}.$$
+
+trap "rm -f ${tmp_file}" 0 1 2 15
+
+# Preprocess cygtls.h and filter out only the member lines from
+# class _cygtls to generate an input file for the cross compiler
+# to generate the member offsets for tlsoffsets-$(target_cpu).h.
+${CXXCOMPILE} -E -P "${input_file}" 2> /dev/null | \
+gawk '
+ BEGIN {
+ # marker is used to split out the member lines from class _cygtls
+ marker=0;
+ # Prepare the input file for the subsequent compiler run.
+ # Prepend value of __CYGTLS_PADSIZE__ so we can compute the offsets
+ # up and down at the same time
+ print "#include \"winsup.h\"";
+ print "#include \"cygtls.h\"";
+ print "extern \"C\" const uint32_t __CYGTLS__start_offset = __CYGTLS_PADSIZE__;";
+ }
+ /^class _cygtls$/ {
+ # Ok, bump marker, next we are expecting a "public:" line
+ marker=1;
+ }
+ /^public:/ {
+ # We are only interested in the lines between the first (marker == 2)
+ # and the second (marker == 3) "public:" line in class _cygtls. These
+ # are where the members are defined.
+ if (marker > 0) ++marker;
+ if (marker > 2) exit;
+ }
+ {
+ if (marker == 2 && $1 != "public:") {
+ # Filter out function names
+ $0 = gensub (/\(\*(\w+)\)\s*\([^\)]*\)/, "\\1", "g");
+ # Filter out leading asterisk
+ $NF = gensub (/^\**(\w+)/, "\\1", "g", $NF);
+ # Filter out trailing array expression
+ $NF = gensub (/(\w+)\s*\[[^\]]*\]/, "\\1", "g", $NF);
+ $NF = gensub (/(\w+);/, "\\1", "g", $NF);
+ print "extern \"C\" const uint32_t __CYGTLS__" $NF " = offsetof (class _cygtls, " $NF ");";
+ }
+ }
+' | \
+# Now run the compiler to generate an assembler file.
+${CXXCOMPILE} -x c++ -g0 -S - -o ${tmp_file} && \
+# The assembler file consists of lines like these:
+#
+# __CYGTLS__foo
+# .long 42
+# .globl __CYGTLS__foo
+# .align 4
+#
+# From this info, generate the tlsoffsets file.
+start_offset=$(gawk '\
+ BEGIN {
+ varname=""
+ }
+ /^__CYGTLS__/ {
+ varname = gensub (/__CYGTLS__(\w+):/, "\\1", "g");
+ }
+ /\s*\.long\s+/ {
+ if (length (varname) > 0) {
+ if (varname == "start_offset") {
+ print $2;
+ }
+ varname = "";
+ }
+ }
+' ${tmp_file}) && \
+gawk -v start_offset="$start_offset" '\
+ BEGIN {
+ varname=""
+ }
+ /^__CYGTLS__/ {
+ varname = gensub (/__CYGTLS__(\w+):/, "\\1", "g");
+ }
+ /\s*\.space\s*4/ {
+ if (length (varname) > 0) {
+ printf (".equ _cygtls.%s, %d\n", varname, -start_offset);
+ printf (".equ _cygtls.%s_p, 0\n", varname);
+ varname = "";
+ }
+ }
+ /\s*\.long\s+/ {
+ if (length (varname) > 0) {
+ if (varname == "start_offset") {
+ printf (".equ _cygtls.%s, -%u\n", varname, start_offset);
+ } else {
+ value = $2;
+ printf (".equ _cygtls.%s, %d\n", varname, value - start_offset);
+ printf (".equ _cygtls.%s_p, %d\n", varname, value);
+ }
+ varname = "";
+ }
+ }
+' ${tmp_file} > "${output_file}"