From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 3AA4A3842436; Wed, 9 Dec 2020 09:51:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3AA4A3842436 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/ibuclaw/heads/darwin)] d: Implement __traits(getTargetInfo) X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/users/ibuclaw/heads/darwin X-Git-Oldrev: 684dd9ca5f7575d59e01bc7429ebf5252932b958 X-Git-Newrev: 7518645e673973d2d164a5c7f0f6a7f7d0ed3267 Message-Id: <20201209095109.3AA4A3842436@sourceware.org> Date: Wed, 9 Dec 2020 09:51:09 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Dec 2020 09:51:09 -0000 https://gcc.gnu.org/g:7518645e673973d2d164a5c7f0f6a7f7d0ed3267 commit 7518645e673973d2d164a5c7f0f6a7f7d0ed3267 Author: Iain Buclaw Date: Fri Dec 4 23:04:21 2020 +0100 d: Implement __traits(getTargetInfo) Diff: --- gcc/config/aarch64/aarch64-d.c | 23 +++++++ gcc/config/arm/arm-d.c | 53 +++++++++++++--- gcc/config/darwin-d.c | 26 ++++++++ gcc/config/dragonfly-d.c | 26 ++++++++ gcc/config/freebsd-d.c | 26 ++++++++ gcc/config/glibc-d.c | 26 ++++++++ gcc/config/i386/i386-d.c | 28 +++++++++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.h | 3 +- gcc/config/mips/mips-d.c | 30 +++++++++ gcc/config/netbsd-d.c | 26 ++++++++ gcc/config/pa/pa-d.c | 28 +++++++++ gcc/config/riscv/riscv-d.c | 46 ++++++++++++++ gcc/config/rs6000/rs6000-d.c | 30 +++++++++ gcc/config/s390/s390-d.c | 30 +++++++++ gcc/config/sol2-d.c | 26 ++++++++ gcc/config/sparc/sparc-d.c | 28 +++++++++ gcc/d/d-builtins.cc | 31 ++++++--- gcc/d/d-compiler.cc | 4 +- gcc/d/d-frontend.cc | 2 +- gcc/d/d-target.cc | 90 +++++++++++++++++++++++++++ gcc/d/d-target.def | 20 ++++++ gcc/d/d-target.h | 15 +++++ gcc/d/d-tree.h | 2 +- gcc/d/dmd/idgen.c | 1 + gcc/d/dmd/target.h | 1 + gcc/d/dmd/traits.c | 24 +++++++ gcc/doc/tm.texi | 14 +++++ gcc/doc/tm.texi.in | 4 ++ libphobos/libdruntime/core/sys/posix/setjmp.d | 3 +- 30 files changed, 646 insertions(+), 21 deletions(-) diff --git a/gcc/config/aarch64/aarch64-d.c b/gcc/config/aarch64/aarch64-d.c index 69efd8df3d2..b01367a33ec 100644 --- a/gcc/config/aarch64/aarch64-d.c +++ b/gcc/config/aarch64/aarch64-d.c @@ -29,3 +29,26 @@ aarch64_d_target_versions (void) d_add_builtin_version ("AArch64"); d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +aarch64_d_handle_target_float_abi (void) +{ + const char *abi = "hard"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +aarch64_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", aarch64_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c index e6c751c1e6c..138463e561b 100644 --- a/gcc/config/arm/arm-d.c +++ b/gcc/config/arm/arm-d.c @@ -36,18 +36,57 @@ arm_d_target_versions (void) d_add_builtin_version ("ARM_Thumb"); } - if (TARGET_HARD_FLOAT_ABI) + if (arm_float_abi == ARM_FLOAT_ABI_HARD) d_add_builtin_version ("ARM_HardFloat"); - else - { - if (TARGET_SOFT_FLOAT) - d_add_builtin_version ("ARM_SoftFloat"); - else if (TARGET_HARD_FLOAT) + else if (arm_float_abi == ARM_FLOAT_ABI_SOFT) + d_add_builtin_version ("ARM_SoftFloat"); + else if (arm_float_abi == ARM_FLOAT_ABI_SOFTFP) d_add_builtin_version ("ARM_SoftFP"); - } if (TARGET_SOFT_FLOAT) d_add_builtin_version ("D_SoftFloat"); else if (TARGET_HARD_FLOAT) d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +arm_d_handle_target_float_abi (void) +{ + const char *abi; + + switch (arm_float_abi) + { + case ARM_FLOAT_ABI_HARD: + abi = "hard"; + break; + + case ARM_FLOAT_ABI_SOFT: + abi = "soft"; + break; + + case ARM_FLOAT_ABI_SOFTFP: + abi = "softfp"; + break; + + default: + abi = ""; + break; + } + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +arm_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", arm_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/darwin-d.c b/gcc/config/darwin-d.c index ced07ce006a..7b8c72efe27 100644 --- a/gcc/config/darwin-d.c +++ b/gcc/config/darwin-d.c @@ -32,9 +32,35 @@ darwin_d_os_builtins (void) d_add_builtin_version ("darwin"); } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +darwin_d_handle_target_object_format (void) +{ + const char *objfmt = "macho"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Darwin targets. */ + +static void +darwin_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", darwin_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS darwin_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO darwin_d_register_target_info + /* Define TARGET_D_MINFO_SECTION for Darwin targets. */ #undef TARGET_D_MINFO_SECTION diff --git a/gcc/config/dragonfly-d.c b/gcc/config/dragonfly-d.c index 70ec820b75d..dac561e21d7 100644 --- a/gcc/config/dragonfly-d.c +++ b/gcc/config/dragonfly-d.c @@ -31,7 +31,33 @@ dragonfly_d_os_builtins (void) d_add_builtin_version ("Posix"); } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +dragonfly_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for DragonFly targets. */ + +static void +dragonfly_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", dragonfly_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS dragonfly_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO dragonfly_d_register_target_info + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/freebsd-d.c b/gcc/config/freebsd-d.c index d79d82b5aa4..d8cf0dbab83 100644 --- a/gcc/config/freebsd-d.c +++ b/gcc/config/freebsd-d.c @@ -36,7 +36,33 @@ freebsd_d_os_builtins (void) d_add_builtin_version ("Posix"); } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +freebsd_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for FreeBSD targets. */ + +static void +freebsd_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", freebsd_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS freebsd_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO freebsd_d_register_target_info + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/glibc-d.c b/gcc/config/glibc-d.c index 7eb9e315f00..ca5bcc52dac 100644 --- a/gcc/config/glibc-d.c +++ b/gcc/config/glibc-d.c @@ -42,7 +42,33 @@ glibc_d_os_builtins (void) #endif } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +glibc_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Glibc targets. */ + +static void +glibc_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", glibc_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS glibc_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO glibc_d_register_target_info + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c index 56fec11846e..9e40c2c2c66 100644 --- a/gcc/config/i386/i386-d.c +++ b/gcc/config/i386/i386-d.c @@ -42,3 +42,31 @@ ix86_d_target_versions (void) else d_add_builtin_version ("D_SoftFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +ix86_d_handle_target_float_abi (void) +{ + const char *abi; + + if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387)) + abi = "soft"; + else + abi = "hard"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +ix86_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", ix86_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 65347a59b79..91bb77c6a4c 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void); /* In i386-d.c */ extern void ix86_d_target_versions (void); +extern void ix86_d_register_target_info (void); /* In winnt.c */ extern void i386_pe_unique_section (tree, int); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index d157d30ec17..aa5dcae983e 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -799,8 +799,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /* Target Pragmas. */ #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas () -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS ix86_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info #ifndef CC1_SPEC #define CC1_SPEC "%(cc1_cpu) " diff --git a/gcc/config/mips/mips-d.c b/gcc/config/mips/mips-d.c index a9d4ba1f0b3..cd4f97a81d3 100644 --- a/gcc/config/mips/mips-d.c +++ b/gcc/config/mips/mips-d.c @@ -54,3 +54,33 @@ mips_d_target_versions (void) d_add_builtin_version ("D_SoftFloat"); } } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +mips_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_HARD_FLOAT_ABI) + abi = "hard"; + else if (TARGET_SOFT_FLOAT_ABI) + abi = "soft"; + else + abi = ""; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +mips_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", mips_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/netbsd-d.c b/gcc/config/netbsd-d.c index 7c30d02b556..c7708edebff 100644 --- a/gcc/config/netbsd-d.c +++ b/gcc/config/netbsd-d.c @@ -33,7 +33,33 @@ netbsd_d_os_builtins (void) d_add_builtin_version ("NetBSD"); } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +netbsd_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for NetBSD targets. */ + +static void +netbsd_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", netbsd_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS netbsd_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO netbsd_d_register_target_info + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/pa/pa-d.c b/gcc/config/pa/pa-d.c index dda555858e3..b792985a623 100644 --- a/gcc/config/pa/pa-d.c +++ b/gcc/config/pa/pa-d.c @@ -37,3 +37,31 @@ pa_d_target_versions (void) else d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +pa_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT) + abi = "soft"; + else + abi = "hard"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +pa_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", pa_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/riscv/riscv-d.c b/gcc/config/riscv/riscv-d.c index 0fb08b49a30..34e7bc590a8 100644 --- a/gcc/config/riscv/riscv-d.c +++ b/gcc/config/riscv/riscv-d.c @@ -37,3 +37,49 @@ riscv_d_target_versions (void) else d_add_builtin_version ("D_SoftFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +riscv_d_handle_target_float_abi (void) +{ + const char *abi; + + switch (riscv_abi) + { + case ABI_ILP32E: + case ABI_ILP32: + case ABI_LP64: + abi = "soft"; + break; + + case ABI_ILP32F: + case ABI_LP64F: + abi = "single"; + break; + + case ABI_ILP32D: + case ABI_LP64D: + abi = "double"; + break; + + default: + abi = ""; + break; + } + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +riscv_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", riscv_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c index fd16e80aafd..d503a838c21 100644 --- a/gcc/config/rs6000/rs6000-d.c +++ b/gcc/config/rs6000/rs6000-d.c @@ -43,3 +43,33 @@ rs6000_d_target_versions (void) d_add_builtin_version ("D_SoftFloat"); } } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +rs6000_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_HARD_FLOAT) + abi = "hard"; + else if (TARGET_SOFT_FLOAT) + abi = "soft"; + else + abi = ""; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +rs6000_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", rs6000_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/s390/s390-d.c b/gcc/config/s390/s390-d.c index 5a70e066e00..375c06a632a 100644 --- a/gcc/config/s390/s390-d.c +++ b/gcc/config/s390/s390-d.c @@ -39,3 +39,33 @@ s390_d_target_versions (void) else if (TARGET_HARD_FLOAT) d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +s390_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_HARD_FLOAT) + abi = "hard"; + else if (TARGET_SOFT_FLOAT) + abi = "soft"; + else + abi = ""; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +s390_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", s390_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/sol2-d.c b/gcc/config/sol2-d.c index 27068f83082..dc542b4d5ee 100644 --- a/gcc/config/sol2-d.c +++ b/gcc/config/sol2-d.c @@ -33,7 +33,33 @@ solaris_d_os_builtins (void) d_add_builtin_version ("Solaris"); \ } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +solaris_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Solaris targets. */ + +static void +solaris_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "objectFormat", solaris_d_handle_target_object_format }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS solaris_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO solaris_d_register_target_info + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/sparc/sparc-d.c b/gcc/config/sparc/sparc-d.c index 53163c6f32e..f28693ff652 100644 --- a/gcc/config/sparc/sparc-d.c +++ b/gcc/config/sparc/sparc-d.c @@ -46,3 +46,31 @@ sparc_d_target_versions (void) d_add_builtin_version ("SPARC_SoftFloat"); } } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +sparc_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_FPU) + abi = "hard"; + else + abi = "soft"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +sparc_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", sparc_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index 72e2d3a7168..b599931ae52 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -332,11 +332,12 @@ build_frontend_type (tree type) } /* Attempt to convert GCC evaluated CST to a D Frontend Expression. + LOC is the location in the source file where this CST is being evaluated. This is used for getting the CTFE value out of a const-folded builtin, returns NULL if it cannot convert CST. */ Expression * -d_eval_constant_expression (tree cst) +d_eval_constant_expression (const Loc &loc, tree cst) { STRIP_TYPE_NOPS (cst); Type *type = build_frontend_type (TREE_TYPE (cst)); @@ -353,23 +354,23 @@ d_eval_constant_expression (tree cst) real_value re = TREE_REAL_CST (TREE_REALPART (cst)); real_value im = TREE_REAL_CST (TREE_IMAGPART (cst)); complex_t value = complex_t (ldouble (re), ldouble (im)); - return ComplexExp::create (Loc (), value, type); + return ComplexExp::create (loc, value, type); } else if (code == INTEGER_CST) { dinteger_t value = TREE_INT_CST_LOW (cst); - return IntegerExp::create (Loc (), value, type); + return IntegerExp::create (loc, value, type); } else if (code == REAL_CST) { real_value value = TREE_REAL_CST (cst); - return RealExp::create (Loc (), ldouble (value), type); + return RealExp::create (loc, ldouble (value), type); } else if (code == STRING_CST) { const void *string = TREE_STRING_POINTER (cst); size_t len = TREE_STRING_LENGTH (cst); - return StringExp::create (Loc (), CONST_CAST (void *, string), len); + return StringExp::create (loc, CONST_CAST (void *, string), len); } else if (code == VECTOR_CST) { @@ -380,17 +381,31 @@ d_eval_constant_expression (tree cst) for (size_t i = 0; i < nunits; i++) { Expression *elem - = d_eval_constant_expression (VECTOR_CST_ELT (cst, i)); + = d_eval_constant_expression (loc, VECTOR_CST_ELT (cst, i)); if (elem == NULL) return NULL; (*elements)[i] = elem; } - Expression *e = ArrayLiteralExp::create (Loc (), elements); + Expression *e = ArrayLiteralExp::create (loc, elements); e->type = type->isTypeVector ()->basetype; - return VectorExp::create (Loc (), e, type); + return VectorExp::create (loc, e, type); + } + else if (code == ADDR_EXPR) + { + /* Special handling for trees constructed by build_string_literal. + What we receive is an `&"string"[0]' expression, strip off the + outer ADDR_EXPR and ARRAY_REF to get to the underlying CST. */ + tree pointee = TREE_OPERAND (cst, 0); + + if (TREE_CODE (pointee) != ARRAY_REF + || TREE_OPERAND (pointee, 1) != integer_zero_node + || TREE_CODE (TREE_OPERAND (pointee, 0)) != STRING_CST) + return NULL; + + return d_eval_constant_expression (loc, TREE_OPERAND (pointee, 0)); } } diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc index ffa7f78c82e..f737d8d9686 100644 --- a/gcc/d/d-compiler.cc +++ b/gcc/d/d-compiler.cc @@ -133,7 +133,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type) cst = native_interpret_expr (vectype, buffer, len); - Expression *e = d_eval_constant_expression (cst); + Expression *e = d_eval_constant_expression (expr->loc, cst); gcc_assert (e != NULL && e->op == TOKvector); return e->isVectorExp ()->e1; @@ -143,7 +143,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type) /* Normal interpret cast. */ cst = native_interpret_expr (build_ctype (type), buffer, len); - Expression *e = d_eval_constant_expression (cst); + Expression *e = d_eval_constant_expression (expr->loc, cst); gcc_assert (e != NULL); return e; diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc index da34e902275..91335307150 100644 --- a/gcc/d/d-frontend.cc +++ b/gcc/d/d-frontend.cc @@ -195,7 +195,7 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments) /* Builtin should be successfully evaluated. Will only return NULL if we can't convert it. */ if (TREE_CONSTANT (result) && TREE_CODE (result) != CALL_EXPR) - e = d_eval_constant_expression (result); + e = d_eval_constant_expression (loc, result); return e; } diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index cd136524eb9..5424ad0ae28 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -44,6 +44,25 @@ along with GCC; see the file COPYING3. If not see Target target; +/* Table `__traits(getTargetInfo)' keys. */ +static vec target_info_table; + +/* Internal key handlers for `__traits(getTargetInfo)'. */ +static tree d_handle_target_cpp_std (void); +static tree d_handle_target_cpp_runtime_library (void); + +/* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists + which are always available. */ +static const struct d_target_info_spec d_language_target_info[] = +{ + /* { name, handler } */ + { "cppStd", d_handle_target_cpp_std }, + { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library }, + { "floatAbi", NULL }, + { "objectFormat", NULL }, + { NULL, NULL }, +}; + /* Initialize the floating-point constants for TYPE. */ @@ -167,6 +186,12 @@ Target::_init (const Param &) real_convert (&CTFloat::one.rv (), mode, &dconst1); real_convert (&CTFloat::minusone.rv (), mode, &dconstm1); real_convert (&CTFloat::half.rv (), mode, &dconsthalf); + + /* Initialize target info tables, the keys required by the language are added + last, so that the OS and CPU handlers can override. */ + targetdm.d_register_cpu_target_info (); + targetdm.d_register_os_target_info (); + d_add_target_info_handlers (d_language_target_info); } /* Return GCC memory alignment size for type TYPE. */ @@ -413,3 +438,68 @@ Target::toArgTypes (Type *) /* Not implemented, however this is not currently used anywhere. */ return NULL; } + + +/* Add all target info in HANDLERS to TARGET_INFO_TABLE for use by + Target::getTargetInfo(). */ + +void +d_add_target_info_handlers (const d_target_info_spec *handlers) +{ + gcc_assert (handlers != NULL); + + if (target_info_table.is_empty ()) + target_info_table.create (8); + + for (size_t i = 0; handlers[i].name != NULL; i++) + target_info_table.safe_push (handlers[i]); +} + +/* Handle a call to `__traits(getTargetInfo, "cppStd")'. */ + +tree +d_handle_target_cpp_std (void) +{ + return build_integer_cst (global.params.cplusplus); +} + +/* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'. */ + +tree +d_handle_target_cpp_runtime_library (void) +{ + /* The driver only ever optionally links to libstdc++. */ + const char *libstdcxx = "libstdc++"; + return build_string_literal (strlen (libstdcxx) + 1, libstdcxx); +} + +/* Look up the target info KEY in the available getTargetInfo tables, and return + the result as an Expression, or NULL if KEY is not found. When the key must + always exist, but is not supported, an empty string expression is returned. + LOC is the location to use for the returned expression. */ + +Expression * +Target::getTargetInfo (const char *key, const Loc &loc) +{ + unsigned ix; + d_target_info_spec *spec; + + FOR_EACH_VEC_ELT (target_info_table, ix, spec) + { + tree result; + + if (strcmp (key, spec->name) != 0) + continue; + + /* Get the requested information, or empty string if unhandled. */ + if (spec->handler) + result = (spec->handler) (); + else + result = build_string_literal (1, ""); + + gcc_assert (result); + return d_eval_constant_expression (loc, result); + } + + return NULL; +} diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def index 728cba70335..4471d5155cc 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -46,6 +46,26 @@ relating to the target operating system.", void, (void), hook_void_void) +/* getTargetInfo keys relating to the target CPU. */ +DEFHOOK +(d_register_cpu_target_info, + "Register all target information keys relating to the target CPU using the\n\ +function @code{d_add_target_info_handlers}, which takes a\n\ +@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}). The keys\n\ +added by this hook are made available at compile time by the\n\ +@code{__traits(getTargetInfo)} extension, the result is an expression\n\ +describing the requested target information.", + void, (void), + hook_void_void) + +/* getTargetInfo keys relating to the target OS. */ +DEFHOOK +(d_register_os_target_info, + "Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to\n\ +the target operating system.", + void, (void), + hook_void_void) + /* ModuleInfo section name and brackets. */ DEFHOOKPOD (d_minfo_section, diff --git a/gcc/d/d-target.h b/gcc/d/d-target.h index d4413e47c61..8d3d6545a1c 100644 --- a/gcc/d/d-target.h +++ b/gcc/d/d-target.h @@ -31,4 +31,19 @@ extern struct gcc_targetdm targetdm; /* Used by target to add predefined version idenditiers. */ extern void d_add_builtin_version (const char *); +/* Structure describing a supported key for `__traits(getTargetInfo)' and a + function to handle it. */ +struct d_target_info_spec +{ + /* The name of the key or NULL to mark the end of a table of keys. */ + const char *name; + /* Function to handle this key, the return value of the handler must be a CST. + This pointer may be NULL if no special handling is required, for instance, + the key must always be available according to the D language spec. */ + tree (*handler) (); +}; + +/* Used by target to add getTargetInfo handlers. */ +extern void d_add_target_info_handlers (const d_target_info_spec *); + #endif /* GCC_D_TARGET_H */ diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 31fe5181912..f5cf9d3f214 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -496,7 +496,7 @@ extern void d_init_builtins (void); extern void d_register_builtin_type (tree, const char *); extern void d_build_builtins_module (Module *); extern void d_maybe_set_builtin (Module *); -extern Expression *d_eval_constant_expression (tree); +extern Expression *d_eval_constant_expression (const Loc &, tree); extern void d_init_versions (void); /* In d-codegen.cc. */ diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c index 16f3b5f29ec..316c5e3b0dd 100644 --- a/gcc/d/dmd/idgen.c +++ b/gcc/d/dmd/idgen.c @@ -360,6 +360,7 @@ Msgtable msgtable[] = { "getUnitTests", NULL }, { "getVirtualIndex", NULL }, { "getPointerBitmap", NULL }, + { "getTargetInfo", NULL }, // For C++ mangling { "allocator", NULL }, diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h index f2a55d6a134..20b505220e7 100644 --- a/gcc/d/dmd/target.h +++ b/gcc/d/dmd/target.h @@ -105,6 +105,7 @@ public: // ABI and backend. LINK systemLinkage(); TypeTuple *toArgTypes(Type *t); + Expression *getTargetInfo(const char* name, const Loc& loc); }; extern Target target; diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c index bc1e2c3c234..f859749be14 100644 --- a/gcc/d/dmd/traits.c +++ b/gcc/d/dmd/traits.c @@ -31,6 +31,7 @@ #include "module.h" #include "attrib.h" #include "parse.h" +#include "target.h" #include "root/speller.h" typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s); @@ -265,6 +266,7 @@ TraitsInitializer::TraitsInitializer() "getUnitTests", "getVirtualIndex", "getPointerBitmap", + "getTargetInfo", NULL }; @@ -1471,6 +1473,28 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc) { return pointerBitmap(e); } + else if (e->ident == Id::getTargetInfo) + { + if (dim != 1) + return dimError(e, 1, dim); + + Expression *ex = isExpression((*e->args)[0]); + StringExp *se = ex ? ex->ctfeInterpret()->toStringExp() : NULL; + if (!ex || !se || se->len == 0) + { + e->error("string expected as argument of __traits `%s` instead of `%s`", e->ident->toChars(), ex->toChars()); + return new ErrorExp(); + } + se = se->toUTF8(sc); + + Expression *r = target.getTargetInfo(se->toPtr(), e->loc); + if (!r) + { + e->error("`getTargetInfo` key `\"%s\"` not supported by this implementation", se->toPtr()); + return new ErrorExp(); + } + return semantic(r, sc); + } if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars)) e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index d9b855c13ac..8e8475dfdd9 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10801,6 +10801,20 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions relating to the target operating system. @end deftypefn +@deftypefn {D Target Hook} void TARGET_D_REGISTER_CPU_TARGET_INFO (void) +Register all target information keys relating to the target CPU using the +function @code{d_add_target_info_handlers}, which takes a +@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}). The keys +added by this hook are made available at compile time by the +@code{__traits(getTargetInfo)} extension, the result is an expression +describing the requested target information. +@end deftypefn + +@deftypefn {D Target Hook} void TARGET_D_REGISTER_OS_TARGET_INFO (void) +Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to +the target operating system. +@end deftypefn + @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION Contains the name of the section in which module info references should be placed. This section is expected to be bracketed by two symbols to indicate diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index ad568581fd4..a14ae7780a5 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7355,6 +7355,10 @@ floating-point support; they are not included in this mechanism. @hook TARGET_D_OS_VERSIONS +@hook TARGET_D_REGISTER_CPU_TARGET_INFO + +@hook TARGET_D_REGISTER_OS_TARGET_INFO + @hook TARGET_D_MINFO_SECTION @hook TARGET_D_MINFO_START_NAME diff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d index 38d4f7086f2..3f5cb2a8241 100644 --- a/libphobos/libdruntime/core/sys/posix/setjmp.d +++ b/libphobos/libdruntime/core/sys/posix/setjmp.d @@ -151,7 +151,8 @@ version (CRuntime_Glibc) c_long __pc; c_long[12] __regs; c_long __sp; - double[12] __fpregs; + static if (__traits(getTargetInfo, "floatAbi") == "double") + double[12] __fpregs; } alias __jmp_buf = __riscv_jmp_buf[1]; }