summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2023-04-02 14:47:42 +0200
committerQuentin Carbonneaux <quentin@c9x.me>2023-04-02 14:48:52 +0200
commita9d3e06a57b4a77012efd6e38d67063c914b71b4 (patch)
tree61eb50a327a4d27ce1ec9ca9f98ce8a5a5524d1e
parent5fee3da6ac3b4995f0d9a6cef3a5e916208cca59 (diff)
downloadroux-a9d3e06a57b4a77012efd6e38d67063c914b71b4.tar.gz
amd64_sysv: thread-local support in Oaddr
Thanks to Lassi Pulkkinen for
flagging the issue and pointing
me to Ulrich Drepper's extensive
doc [1].

[1] https://people.redhat.com/drepper/tls.pdf
-rw-r--r--amd64/emit.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index 9b8bb5d..7b2681e 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -372,6 +372,7 @@ emitins(Ins i, Fn *fn, FILE *f)
 	int64_t val;
 	int o, t0;
 	Ins ineg;
+	char *sym;
 
 	switch (i.op) {
 	default:
@@ -490,6 +491,22 @@ emitins(Ins i, Fn *fn, FILE *f)
 		 * should use movabsq when reading movq */
 		emitf("mov%k %0, %=", &i, fn, f);
 		break;
+	case Oaddr:
+		if (!T.apple
+		&& rtype(i.arg[0]) == RCon
+		&& fn->con[i.arg[0].val].sym.type == SThr) {
+			/* derive the symbol address from the TCB
+			 * address at offset 0 of %fs */
+			assert(isreg(i.to));
+			sym = str(fn->con[i.arg[0].val].sym.id);
+			emitf("movq %%fs:0, %=", &i, fn, f);
+			fprintf(f, "\tleaq %s%s@tpoff(%%%s), %%%s\n",
+				sym[0] == '"' ? "" : T.assym, sym,
+				regtoa(i.to.val, SLong),
+				regtoa(i.to.val, SLong));
+			break;
+		}
+		goto Table;
 	case Ocall:
 		/* calls simply have a weird syntax in AT&T
 		 * assembly... */