Skip to content

Commit

Permalink
RISC-V: Implement TLS Descriptors.
Browse files Browse the repository at this point in the history
This implements TLS Descriptors (TLSDESC) as specified in [1].

The 4-instruction sequence is implemented as a single RTX insn for
simplicity, but this can be revisited later if instruction scheduling or
more flexible RA is desired.

The default remains to be the traditional TLS model, but can be configured
with --with-tls={trad,desc}. The choice can be revisited once toolchain
and libc support ships.

[1]: riscv-non-isa/riscv-elf-psabi-doc#373.

gcc/Changelog:
	* config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
	* config.gcc: Add --with_tls configuration option to change the
	default TLS flavor.
	* config/riscv/riscv.h: Add TARGET_TLSDESC determined from
	-mtls-dialect and with_tls defaults.
	* config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
	two TLS flavors.
	* config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
	* config/riscv/riscv.md: Add instruction sequence for TLSDESC.
	* config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
	sequence length data for TLSDESC.
	(riscv_legitimize_tls_address): Add lowering of TLSDESC.
	* doc/install.texi: Document --with-tls for RISC-V.
	* doc/invoke.texi: Document -mtls-dialect for RISC-V.
	* testsuite/gcc.target/riscv/tls_1.x: Add TLSDESC GD test case.
	* testsuite/gcc.target/riscv/tlsdesc.c: Same as above.
  • Loading branch information
ishitatsuyuki committed Mar 29, 2024
1 parent 4b8e7b5 commit 3a36aea
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 11 deletions.
15 changes: 14 additions & 1 deletion gcc/config.gcc
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,7 @@ riscv*-*-linux*)
# Force .init_array support. The configure script cannot always
# automatically detect that GAS supports it, yet we require it.
gcc_cv_initfini_array=yes
with_tls=${with_tls:-trad}
;;
riscv*-*-elf* | riscv*-*-rtems*)
tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
Expand Down Expand Up @@ -2534,6 +2535,7 @@ riscv*-*-freebsd*)
# Force .init_array support. The configure script cannot always
# automatically detect that GAS supports it, yet we require it.
gcc_cv_initfini_array=yes
with_tls=${with_tls:-trad}
;;

loongarch*-*-linux*)
Expand Down Expand Up @@ -4671,7 +4673,7 @@ case "${target}" in
;;

riscv*-*-*)
supported_defaults="abi arch tune riscv_attribute isa_spec"
supported_defaults="abi arch tune riscv_attribute isa_spec tls"

case "${target}" in
riscv-* | riscv32*) xlen=32 ;;
Expand Down Expand Up @@ -4801,6 +4803,17 @@ case "${target}" in
;;
esac
fi
# Handle --with-tls.
case "$with_tls" in
"" \
| trad | desc)
# OK
;;
*)
echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2
exit 1
;;
esac

# Handle --with-multilib-list.
if test "x${with_multilib_list}" != xdefault; then
Expand Down
6 changes: 6 additions & 0 deletions gcc/config/riscv/riscv-opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,10 @@ enum rvv_vector_bits_enum {
#define TARGET_MAX_LMUL \
(int) (rvv_max_lmul == RVV_DYNAMIC ? RVV_M8 : rvv_max_lmul)

/* TLS types. */
enum riscv_tls_type {
TLS_TRADITIONAL,
TLS_DESCRIPTORS
};

#endif /* ! GCC_RISCV_OPTS_H */
5 changes: 3 additions & 2 deletions gcc/config/riscv/riscv-protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ enum riscv_symbol_type {
SYMBOL_TLS,
SYMBOL_TLS_LE,
SYMBOL_TLS_IE,
SYMBOL_TLS_GD
SYMBOL_TLS_GD,
SYMBOL_TLSDESC,
};
#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)

/* Classifies an address.
Expand Down
24 changes: 20 additions & 4 deletions gcc/config/riscv/riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference. */
case SYMBOL_PCREL: return 2; /* AUIPC + the reference. */
case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference. */
case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference. */
case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference. */
case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference. */
default: gcc_unreachable ();
Expand Down Expand Up @@ -2220,7 +2221,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
static rtx
riscv_legitimize_tls_address (rtx loc)
{
rtx dest, tp, tmp;
rtx dest, tp, tmp, a0;
enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);

#if 0
Expand All @@ -2236,9 +2237,24 @@ riscv_legitimize_tls_address (rtx loc)
/* Rely on section anchors for the optimization that LDM TLS
provides. The anchor's address is loaded with GD TLS. */
case TLS_MODEL_GLOBAL_DYNAMIC:
tmp = gen_rtx_REG (Pmode, GP_RETURN);
dest = gen_reg_rtx (Pmode);
emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
if (TARGET_TLSDESC)
{
static unsigned seqno;
tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
dest = gen_reg_rtx (Pmode);

emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
emit_insn (gen_add3_insn (dest, a0, tp));
seqno++;
}
else
{
tmp = gen_rtx_REG (Pmode, GP_RETURN);
dest = gen_reg_rtx (Pmode);
emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
loc);
}
break;

case TLS_MODEL_INITIAL_EXEC:
Expand Down
9 changes: 7 additions & 2 deletions gcc/config/riscv/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ extern const char *riscv_arch_help (int argc, const char **argv);
--with-abi is ignored if -mabi is specified.
--with-tune is ignored if -mtune or -mcpu is specified.
--with-isa-spec is ignored if -misa-spec is specified.
--with-tls is ignored if -mtls-dialect is specified.
But using default -march/-mtune value if -mcpu don't have valid option. */
#define OPTION_DEFAULT_SPECS \
Expand All @@ -73,8 +74,9 @@ extern const char *riscv_arch_help (int argc, const char **argv);
{"arch", "%{!march=*:" \
" %{!mcpu=*:-march=%(VALUE)}" \
" %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" }, \
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
{"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
{"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
{"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"}, \

#ifdef IN_LIBGCC2
#undef TARGET_64BIT
Expand Down Expand Up @@ -1228,4 +1230,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
#define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
#define HAVE_PRE_MODIFY_DISP TARGET_XTHEADMEMIDX

/* Check TLS Descriptors mechanism is selected. */
#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)

#endif /* ! GCC_RISCV_H */
20 changes: 19 additions & 1 deletion gcc/config/riscv/riscv.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
UNSPEC_TLS_LE
UNSPEC_TLS_IE
UNSPEC_TLS_GD

UNSPEC_TLSDESC
;; High part of PC-relative address.
UNSPEC_AUIPC

Expand Down Expand Up @@ -2089,6 +2089,24 @@
(set_attr "type" "load")
(set_attr "mode" "<MODE>")])

(define_insn "@tlsdesc<mode>"
[(set (reg:P A0_REGNUM)
(unspec:P
[(match_operand:P 0 "symbolic_operand" "")
(match_operand:P 1 "const_int_operand")]
UNSPEC_TLSDESC))
(clobber (reg:P T0_REGNUM))]
"TARGET_TLSDESC"
{
return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
"<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
"addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
"jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
}
[(set_attr "type" "multi")
(set_attr "length" "16")
(set_attr "mode" "<MODE>")])

(define_insn "auipc<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P
Expand Down
14 changes: 14 additions & 0 deletions gcc/config/riscv/riscv.opt
Original file line number Diff line number Diff line change
Expand Up @@ -606,3 +606,17 @@ Enum(rvv_vector_bits) String(zvl) Value(RVV_VECTOR_BITS_ZVL)
mrvv-vector-bits=
Target RejectNegative Joined Enum(rvv_vector_bits) Var(rvv_vector_bits) Init(RVV_VECTOR_BITS_SCALABLE)
-mrvv-vector-bits=<string> Set the kind of bits for an RVV vector register.

Enum
Name(tls_type) Type(enum riscv_tls_type)
The possible TLS dialects:

EnumValue
Enum(tls_type) String(trad) Value(TLS_TRADITIONAL)

EnumValue
Enum(tls_type) String(desc) Value(TLS_DESCRIPTORS)

mtls-dialect=
Target RejectNegative Joined Enum(tls_type) Var(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
Specify TLS dialect.
3 changes: 3 additions & 0 deletions gcc/doc/install.texi
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,9 @@ Specify the default TLS dialect, for systems were there is a choice.
For ARM targets, possible values for @var{dialect} are @code{gnu} or
@code{gnu2}, which select between the original GNU dialect and the GNU TLS
descriptor-based dialect.
For RISC-V targets, possible values for @var{dialect} are @code{trad} or
@code{desc}, which select between the traditional GNU dialect and the GNU TLS
descriptor-based dialect.

@item --enable-multiarch
Specify whether to enable or disable multiarch support. The default is
Expand Down
13 changes: 12 additions & 1 deletion gcc/doc/invoke.texi
Original file line number Diff line number Diff line change
Expand Up @@ -1262,7 +1262,8 @@ See RS/6000 and PowerPC Options.
-minline-atomics -mno-inline-atomics
-minline-strlen -mno-inline-strlen
-minline-strcmp -mno-inline-strcmp
-minline-strncmp -mno-inline-strncmp}
-minline-strncmp -mno-inline-strncmp
-mtls-dialect=desc -mtls-dialect=trad}

@emph{RL78 Options}
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs
Expand Down Expand Up @@ -30975,6 +30976,16 @@ which register to use as base register for reading the canary,
and from what offset from that base register. There is no default
register or offset as this is entirely for use within the Linux
kernel.

@opindex mtls-dialect=desc
@item -mtls-dialect=desc
Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
of TLS variables.

@opindex mtls-dialect=trad
@item -mtls-dialect=trad
Use traditional TLS as the thread-local storage mechanism for dynamic accesses
of TLS variables. This is the default.
@end table

@node RL78 Options
Expand Down
5 changes: 5 additions & 0 deletions gcc/testsuite/gcc.target/riscv/tls_1.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern __thread unsigned gd;

unsigned get() {
return gd;
}
12 changes: 12 additions & 0 deletions gcc/testsuite/gcc.target/riscv/tlsdesc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* { dg-require-effective-target tls_native } */
/* { dg-options "-O2 -fpic -mtls-dialect=desc --save-temps" } */
/* { dg-require-effective-target fpic } */

#include "tls_1.x"

/* { dg-final { scan-assembler-times "auipc\t\[a-x0-9\]+,%tlsdesc_hi" 1 } } */
/* { dg-final { scan-assembler-times "lw\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "ld\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv64 } } } }*/
/* { dg-final { scan-assembler-times "addi\ta0,\[a-x0-9\]+,%tlsdesc_add_lo" 1 } } */
/* { dg-final { scan-assembler-times "jalr\tt0,\[a-x0-9\]+,%tlsdesc_call" 1 } } */
/* { dg-final { cleanup-saved-temps } } */

0 comments on commit 3a36aea

Please sign in to comment.