diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2019-06-18 20:42:10 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-11-30 16:53:28 +0100 |
commit | 5fee5ec362f7a243f459e6378fd49dfc89dc9fb5 (patch) | |
tree | 61d1bdbca854a903c0860406f457f06b2040be7a /gcc/d/dmd/cppmangle.c | |
parent | b3f60112edcb85b459e60f66c44a55138b1cef49 (diff) | |
download | gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.zip gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.tar.gz gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.tar.bz2 |
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
The D front-end is now itself written in D, in order to build GDC, you
will need a working GDC compiler (GCC version 9.1 or later).
GCC changes:
- Add support for bootstrapping the D front-end.
These add the required components in order to have a D front-end written
in D itself. Because the compiler front-end only depends on the core
runtime modules, only libdruntime is built for the bootstrap stages.
D front-end changes:
- Import dmd v2.098.0-beta.1.
Druntime changes:
- Import druntime v2.098.0-beta.1.
Phobos changes:
- Import phobos v2.098.0-beta.1.
The jump from v2.076.1 to v2.098.0 covers nearly 4 years worth of
development on the D programming language and run-time libraries.
ChangeLog:
* Makefile.def: Add bootstrap to libbacktrace, libphobos, zlib, and
libatomic.
* Makefile.in: Regenerate.
* Makefile.tpl (POSTSTAGE1_HOST_EXPORTS): Fix command for GDC.
(STAGE1_CONFIGURE_FLAGS): Add --with-libphobos-druntime-only if
target-libphobos-bootstrap.
(STAGE2_CONFIGURE_FLAGS): Likewise.
* configure: Regenerate.
* configure.ac: Add support for bootstrapping D front-end.
config/ChangeLog:
* acx.m4 (ACX_PROG_GDC): New m4 function.
gcc/ChangeLog:
* Makefile.in (GDC): New variable.
(GDCFLAGS): New variable.
* configure: Regenerate.
* configure.ac: Add call to ACX_PROG_GDC. Substitute GDCFLAGS.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd b8384668f.
* Make-lang.in (d-warn): Use strict warnings.
(DMD_WARN_CXXFLAGS): Remove.
(DMD_COMPILE): Remove.
(CHECKING_DFLAGS): Define.
(WARN_DFLAGS): Define.
(ALL_DFLAGS): Define.
(DCOMPILE.base): Define.
(DCOMPILE): Define.
(DPOSTCOMPILE): Define.
(DLINKER): Define.
(DLLINKER): Define.
(D_FRONTEND_OBJS): Add new dmd front-end objects.
(D_GENERATED_SRCS): Remove.
(D_GENERATED_OBJS): Remove.
(D_ALL_OBJS): Remove D_GENERATED_OBJS.
(d21$(exeext)): Build using DLLINKER and -static-libphobos.
(d.tags): Remove dmd/*.c and dmd/root/*.c.
(d.mostlyclean): Remove D_GENERATED_SRCS, d/idgen$(build_exeext),
d/impcnvgen$(build_exeext).
(D_INCLUDES): Include $(srcdir)/d/dmd/res.
(CFLAGS-d/id.o): Remove.
(CFLAGS-d/impcnvtab.o): Remove.
(d/%.o): Build using DCOMPILE and DPOSTCOMPILE. Update dependencies
from d/dmd/%.c to d/dmd/%.d.
(d/idgen$(build_exeext)): Remove.
(d/impcnvgen$(build_exeext)): Remove.
(d/id.c): Remove.
(d/id.h): Remove.
(d/impcnvtab.c): Remove.
(d/%.dmdgen.o): Remove.
(D_SYSTEM_H): Remove.
(d/idgen.dmdgen.o): Remove.
(d/impcnvgen.dmdgen.o): Remove.
* config-lang.in (boot_language): New variable.
* d-attribs.cc: Include dmd/expression.h.
* d-builtins.cc: Include d-frontend.h.
(build_frontend_type): Update for new front-end interface.
(d_eval_constant_expression): Likewise.
(d_build_builtins_module): Likewise.
(maybe_set_builtin_1): Likewise.
(d_build_d_type_nodes): Likewise.
* d-codegen.cc (d_decl_context): Likewise.
(declaration_reference_p): Likewise.
(declaration_type): Likewise.
(parameter_reference_p): Likewise.
(parameter_type): Likewise.
(get_array_length): Likewise.
(build_delegate_cst): Likewise.
(build_typeof_null_value): Likewise.
(identity_compare_p): Likewise.
(lower_struct_comparison): Likewise.
(build_filename_from_loc): Likewise.
(build_assert_call): Remove LIBCALL_SWITCH_ERROR.
(build_bounds_index_condition): Call LIBCALL_ARRAYBOUNDS_INDEXP on
bounds error.
(build_bounds_slice_condition): Call LIBCALL_ARRAYBOUNDS_SLICEP on
bounds error.
(array_bounds_check): Update for new front-end interface.
(checkaction_trap_p): Handle CHECKACTION_context.
(get_function_type): Update for new front-end interface.
(d_build_call): Likewise.
* d-compiler.cc: Remove include of dmd/scope.h.
(Compiler::genCmain): Remove.
(Compiler::paintAsType): Update for new front-end interface.
(Compiler::onParseModule): Likewise.
* d-convert.cc (convert_expr): Remove call to LIBCALL_ARRAYCAST.
(convert_for_rvalue): Update for new front-end interface.
(convert_for_assignment): Likewise.
(convert_for_condition): Likewise.
(d_array_convert): Likewise.
* d-diagnostic.cc (error): Remove.
(errorSupplemental): Remove.
(warning): Remove.
(warningSupplemental): Remove.
(deprecation): Remove.
(deprecationSupplemental): Remove.
(message): Remove.
(vtip): New.
* d-frontend.cc (global): Remove.
(Global::_init): Remove.
(Global::startGagging): Remove.
(Global::endGagging): Remove.
(Global::increaseErrorCount): Remove.
(Loc::Loc): Remove.
(Loc::toChars): Remove.
(Loc::equals): Remove.
(isBuiltin): Update for new front-end interface.
(eval_builtin): Likewise.
(getTypeInfoType): Likewise.
(inlineCopy): Remove.
* d-incpath.cc: Include d-frontend.h.
(add_globalpaths): Call d_gc_malloc to allocate Strings.
(add_filepaths): Likewise.
* d-lang.cc: Include dmd/id.h, dmd/root/file.h, d-frontend.h. Remove
include of dmd/mars.h, id.h.
(entrypoint_module): Remove.
(entrypoint_root_module): Remove.
(deps_write_string): Update for new front-end interface.
(deps_write): Likewise.
(d_init_options): Call rt_init. Remove setting global params that are
default initialized by the front-end.
(d_handle_option): Handle OPT_fcheckaction_, OPT_fdump_c___spec_,
OPT_fdump_c___spec_verbose, OPT_fextern_std_, OPT_fpreview,
OPT_revert, OPT_fsave_mixins_, and OPT_ftransition.
(d_post_options): Propagate dip1021 and dip1000 preview flags to
dip25, and flag_diagnostics_show_caret to printErrorContext.
(d_add_entrypoint_module): Remove.
(d_parse_file): Update for new front-end interface.
(d_type_promotes_to): Likewise.
(d_types_compatible_p): Likewise.
* d-longdouble.cc (CTFloat::zero): Remove.
(CTFloat::one): Remove.
(CTFloat::minusone): Remove.
(CTFloat::half): Remove.
* d-system.h (POSIX): Remove.
(realpath): Remove.
(isalpha): Remove.
(isalnum): Remove.
(isdigit): Remove.
(islower): Remove.
(isprint): Remove.
(isspace): Remove.
(isupper): Remove.
(isxdigit): Remove.
(tolower): Remove.
(_mkdir): Remove.
(INT32_MAX): Remove.
(INT32_MIN): Remove.
(INT64_MIN): Remove.
(UINT32_MAX): Remove.
(UINT64_MAX): Remove.
* d-target.cc: Include calls.h.
(target): Remove.
(define_float_constants): Remove initialization of snan.
(Target::_init): Update for new front-end interface.
(Target::isVectorTypeSupported): Likewise.
(Target::isVectorOpSupported): Remove cases for unordered operators.
(TargetCPP::typeMangle): Update for new front-end interface.
(TargetCPP::parameterType): Likewise.
(Target::systemLinkage): Likewise.
(Target::isReturnOnStack): Likewise.
(Target::isCalleeDestroyingArgs): Define.
(Target::preferPassByRef): Define.
* d-tree.h (d_add_entrypoint_module): Remove.
* decl.cc (gcc_attribute_p): Update for new front-end interface.
(apply_pragma_crt): Define.
(DeclVisitor::visit(PragmaDeclaration *)): Handle pragmas
crt_constructor and crt_destructor.
(DeclVisitor::visit(TemplateDeclaration *)): Update for new front-end
interface.
(DeclVisitor::visit): Likewise.
(DeclVisitor::finish_vtable): Likewise.
(get_symbol_decl): Error if template has more than one nesting
context. Update for new front-end interface.
(make_thunk): Update for new front-end interface.
(get_vtable_decl): Likewise.
* expr.cc (ExprVisitor::visit): Likewise.
(build_return_dtor): Likewise.
* imports.cc (ImportVisitor::visit): Likewise.
* intrinsics.cc: Include dmd/expression.h. Remove include of
dmd/mangle.h.
(maybe_set_intrinsic): Update for new front-end interface.
* intrinsics.def (INTRINSIC_ROL): Update intrinsic signature.
(INTRINSIC_ROR): Likewise.
(INTRINSIC_ROR_TIARG): Likewise.
(INTRINSIC_TOPREC): Likewise.
(INTRINSIC_TOPRECL): Likewise.
(INTRINSIC_TAN): Update intrinsic module and signature.
(INTRINSIC_ISNAN): Likewise.
(INTRINSIC_ISFINITE): Likewise.
(INTRINSIC_COPYSIGN): Define intrinsic.
(INTRINSIC_COPYSIGNI): Define intrinsic.
(INTRINSIC_EXP): Update intrinsic module.
(INTRINSIC_EXPM1): Likewise.
(INTRINSIC_EXP2): Likewise.
(INTRINSIC_LOG): Likewise.
(INTRINSIC_LOG2): Likewise.
(INTRINSIC_LOG10): Likewise.
(INTRINSIC_POW): Likewise.
(INTRINSIC_ROUND): Likewise.
(INTRINSIC_FLOORF): Likewise.
(INTRINSIC_FLOOR): Likewise.
(INTRINSIC_FLOORL): Likewise.
(INTRINSIC_CEILF): Likewise.
(INTRINSIC_CEIL): Likewise.
(INTRINSIC_CEILL): Likewise.
(INTRINSIC_TRUNC): Likewise.
(INTRINSIC_FMIN): Likewise.
(INTRINSIC_FMAX): Likewise.
(INTRINSIC_FMA): Likewise.
(INTRINSIC_VA_ARG): Update intrinsic signature.
(INTRINSIC_VASTART): Likewise.
* lang.opt (fcheck=): Add alternate aliases for contract switches.
(fcheckaction=): New option.
(check_action): New Enum and EnumValue entries.
(fdump-c++-spec-verbose): New option.
(fdump-c++-spec=): New option.
(fextern-std=): New option.
(extern_stdcpp): New Enum and EnumValue entries
(fpreview=): New options.
(frevert=): New options.
(fsave-mixins): New option.
(ftransition=): Update options.
* modules.cc (get_internal_fn): Replace Prot with Visibility.
(build_internal_fn): Likewise.
(build_dso_cdtor_fn): Likewise.
(build_module_tree): Remove check for __entrypoint module.
* runtime.def (P5): Define.
(ARRAYBOUNDS_SLICEP): Define.
(ARRAYBOUNDS_INDEXP): Define.
(NEWTHROW): Define.
(ADCMP2): Remove.
(ARRAYCAST): Remove.
(SWITCH_STRING): Remove.
(SWITCH_USTRING): Remove.
(SWITCH_DSTRING): Remove.
(SWITCH_ERROR): Remove.
* toir.cc (IRVisitor::visit): Update for new front-end interface.
(IRVisitor::check_previous_goto): Remove checks for case and default
statements.
(IRVisitor::visit(SwitchStatement *)): Remove handling of string
switch conditions.
* typeinfo.cc: Include d-frontend.h.
(get_typeinfo_kind): Update for new front-end interface.
(make_frontend_typeinfo): Likewise.
(TypeInfoVisitor::visit): Likewise.
(builtin_typeinfo_p): Likewise.
(get_typeinfo_decl): Likewise.
(build_typeinfo): Likewise.
* types.cc (valist_array_p): Likewise.
(make_array_type): Likewise.
(merge_aggregate_types): Likewise.
(TypeVisitor::visit(TypeBasic *)): Likewise.
(TypeVisitor::visit(TypeFunction *)): Likewise.
(TypeVisitor::visit(TypeStruct *)): Update comment.
* verstr.h: Removed.
* d-frontend.h: New file.
gcc/po/ChangeLog:
* EXCLUDES: Remove d/dmd sources from list.
gcc/testsuite/ChangeLog:
* gdc.dg/Wcastresult2.d: Update test.
* gdc.dg/asm1.d: Likewise.
* gdc.dg/asm2.d: Likewise.
* gdc.dg/asm3.d: Likewise.
* gdc.dg/gdc282.d: Likewise.
* gdc.dg/imports/gdc170.d: Likewise.
* gdc.dg/intrinsics.d: Likewise.
* gdc.dg/pr101672.d: Likewise.
* gdc.dg/pr90650a.d: Likewise.
* gdc.dg/pr90650b.d: Likewise.
* gdc.dg/pr94777a.d: Likewise.
* gdc.dg/pr95250.d: Likewise.
* gdc.dg/pr96869.d: Likewise.
* gdc.dg/pr98277.d: Likewise.
* gdc.dg/pr98457.d: Likewise.
* gdc.dg/simd1.d: Likewise.
* gdc.dg/simd2a.d: Likewise.
* gdc.dg/simd2b.d: Likewise.
* gdc.dg/simd2c.d: Likewise.
* gdc.dg/simd2d.d: Likewise.
* gdc.dg/simd2e.d: Likewise.
* gdc.dg/simd2f.d: Likewise.
* gdc.dg/simd2g.d: Likewise.
* gdc.dg/simd2h.d: Likewise.
* gdc.dg/simd2i.d: Likewise.
* gdc.dg/simd2j.d: Likewise.
* gdc.dg/simd7951.d: Likewise.
* gdc.dg/torture/gdc309.d: Likewise.
* gdc.dg/torture/pr94424.d: Likewise.
* gdc.dg/torture/pr94777b.d: Likewise.
* lib/gdc-utils.exp (gdc-convert-args): Handle new compiler options.
(gdc-convert-test): Handle CXXFLAGS, EXTRA_OBJC_SOURCES, and ARG_SETS
test directives.
(gdc-do-test): Only import modules in the test run directory.
* gdc.dg/pr94777c.d: New test.
* gdc.dg/pr96156b.d: New test.
* gdc.dg/pr96157c.d: New test.
* gdc.dg/simd_ctfe.d: New test.
* gdc.dg/torture/simd17344.d: New test.
* gdc.dg/torture/simd20052.d: New test.
* gdc.dg/torture/simd6.d: New test.
* gdc.dg/torture/simd7.d: New test.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime e6caaab9.
* libdruntime/Makefile.am (D_EXTRA_FLAGS): Build libdruntime with
-fpreview=dip1000, -fpreview=fieldwise, and -fpreview=dtorfields.
(ALL_DRUNTIME_SOURCES): Add DRUNTIME_DSOURCES_STDCXX.
(DRUNTIME_DSOURCES): Update list of C binding modules.
(DRUNTIME_DSOURCES_STDCXX): Likewise.
(DRUNTIME_DSOURCES_LINUX): Likewise.
(DRUNTIME_DSOURCES_OPENBSD): Likewise.
(DRUNTIME_DISOURCES): Remove __entrypoint.di.
* libdruntime/Makefile.in: Regenerated.
* libdruntime/__entrypoint.di: Removed.
* libdruntime/gcc/deh.d (_d_isbaseof): Update signature.
(_d_createTrace): Likewise.
(__gdc_begin_catch): Remove reference to the exception.
(_d_throw): Increment reference count of thrown object before unwind.
(__gdc_personality): Chain exceptions with Throwable.chainTogether.
* libdruntime/gcc/emutls.d: Update imports.
* libdruntime/gcc/sections/elf.d: Update imports.
(DSO.moduleGroup): Update signature.
* libdruntime/gcc/sections/macho.d: Update imports.
(DSO.moduleGroup): Update signature.
* libdruntime/gcc/sections/pecoff.d: Update imports.
(DSO.moduleGroup): Update signature.
* src/MERGE: Merge upstream phobos 5ab9ad256.
* src/Makefile.am (D_EXTRA_DFLAGS): Add -fpreview=dip1000 and
-fpreview=dtorfields flags.
(PHOBOS_DSOURCES): Update list of std modules.
* src/Makefile.in: Regenerate.
* testsuite/lib/libphobos.exp (libphobos-dg-test): Handle assembly
compile types.
(dg-test): Override.
(additional_prunes): Define.
(libphobos-dg-prune): Filter any additional_prunes set by tests.
* testsuite/libphobos.aa/test_aa.d: Update test.
* testsuite/libphobos.druntime/druntime.exp (version_flags): Add
-fversion=CoreUnittest.
* testsuite/libphobos.druntime_shared/druntime_shared.exp
(version_flags): Add -fversion=CoreUnittest -fversion=Shared.
* testsuite/libphobos.exceptions/unknown_gc.d: Update test.
* testsuite/libphobos.hash/test_hash.d: Update test.
* testsuite/libphobos.phobos/phobos.exp (version_flags): Add
-fversion=StdUnittest
* testsuite/libphobos.phobos_shared/phobos_shared.exp (version_flags):
Likewise.
* testsuite/libphobos.shared/host.c: Update test.
* testsuite/libphobos.shared/load.d: Update test.
* testsuite/libphobos.shared/load_13414.d: Update test.
* testsuite/libphobos.thread/fiber_guard_page.d: Update test.
* testsuite/libphobos.thread/tlsgc_sections.d: Update test.
* testsuite/testsuite_flags.in: Add -fpreview=dip1000 to --gdcflags.
* testsuite/libphobos.shared/link_mod_collision.d: Removed.
* testsuite/libphobos.shared/load_mod_collision.d: Removed.
* testsuite/libphobos.betterc/betterc.exp: New test.
* testsuite/libphobos.config/config.exp: New test.
* testsuite/libphobos.gc/gc.exp: New test.
* testsuite/libphobos.imports/imports.exp: New test.
* testsuite/libphobos.lifetime/lifetime.exp: New test.
* testsuite/libphobos.unittest/unittest.exp: New test.
Diffstat (limited to 'gcc/d/dmd/cppmangle.c')
-rw-r--r-- | gcc/d/dmd/cppmangle.c | 1168 |
1 files changed, 0 insertions, 1168 deletions
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c deleted file mode 100644 index baf64c5..0000000 --- a/gcc/d/dmd/cppmangle.c +++ /dev/null @@ -1,1168 +0,0 @@ - -/* Compiler implementation of the D programming language - * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved - * written by Walter Bright - * http://www.digitalmars.com - * Distributed under the Boost Software License, Version 1.0. - * http://www.boost.org/LICENSE_1_0.txt - * https://github.com/D-Programming-Language/dmd/blob/master/src/cppmangle.c - */ - -/** - * Do mangling for C++ linkage. - * - * References: - * Follows Itanium C++ ABI 1.86 section 5.1 - * http://refspecs.linux-foundation.org/cxxabi-1.86.html#mangling - * which is where the grammar comments come from. - * - * Bugs: - * https://issues.dlang.org/query.cgi - * enter `C++, mangling` as the keywords. - */ - -#include "root/dsystem.h" - -#include "mars.h" -#include "dsymbol.h" -#include "mtype.h" -#include "scope.h" -#include "init.h" -#include "expression.h" -#include "attrib.h" -#include "declaration.h" -#include "template.h" -#include "id.h" -#include "enum.h" -#include "import.h" -#include "aggregate.h" -#include "target.h" - -typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param); -int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL); - -class CppMangleVisitor : public Visitor -{ - Objects components; // array of components available for substitution - OutBuffer *buf; // append the mangling to buf[] - public: - Loc loc; // location for use in error messages - - // Write <seq-id> to buf - void write_seq_id(size_t i) - { - if (i >= 36) - { - write_seq_id(i / 36); - i %= 36; - } - i += (i < 10) ? '0' : 'A' - 10; - buf->writeByte((char)i); - } - - bool substitute(RootObject *p) - { - //printf("substitute %s\n", p ? p->toChars() : NULL); - int i = find(p); - if (i >= 0) - { - //printf("\tmatch\n"); - /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ... - */ - buf->writeByte('S'); - if (i) - { - write_seq_id(i - 1); - } - buf->writeByte('_'); - return true; - } - return false; - } - - /****** - * See if `p` exists in components[] - * Returns: - * index if found, -1 if not - */ - int find(RootObject *p) - { - //printf("find %p %d %s\n", p, p.dyncast(), p ? p.toChars() : NULL); - for (size_t i = 0; i < components.length; i++) - { - if (p == components[i]) - return (int)i; - } - return -1; - } - - /********************* - * Append p to components[] - */ - void append(RootObject *p) - { - //printf("append %p %d %s\n", p, p.dyncast(), p ? p.toChars() : "null"); - components.push(p); - } - - /************************ - * Determine if symbol is indeed the global ::std namespace. - * Params: - * s = symbol to check - * Returns: - * true if it is ::std - */ - static bool isStd(Dsymbol *s) - { - return (s && - s->ident == Id::std && // the right name - s->isNspace() && // g++ disallows global "std" for other than a namespace - !getQualifier(s)); // at global level - } - - /************************ - * Determine if type is a C++ fundamental type. - * Params: - * t = type to check - * Returns: - * true if it is a fundamental type - */ - static bool isFundamentalType(Type *t) - { - // First check the target whether some specific ABI is being followed. - bool isFundamental; - if (target.cpp.fundamentalType(t, isFundamental)) - return isFundamental; - if (t->ty == Tenum) - { - // Peel off enum type from special types. - TypeEnum *te = (TypeEnum *)t; - if (te->sym->isSpecial()) - t = te->sym->getMemtype(Loc()); - } - - // Fundamental arithmetic types: - // 1. integral types: bool, char, int, ... - // 2. floating point types: float, double, real - // 3. void - // 4. null pointer: std::nullptr_t (since C++11) - if (t->ty == Tvoid || t->ty == Tbool) - return true; - else if (t->ty == Tnull && global.params.cplusplus >= CppStdRevisionCpp11) - return true; - else - return t->isTypeBasic() && (t->isintegral() || t->isreal()); - } - - /****************************** - * Write the mangled representation of the template arguments. - * Params: - * ti = the template instance - */ - void template_args(TemplateInstance *ti) - { - /* <template-args> ::= I <template-arg>+ E - */ - if (!ti) // could happen if std::basic_string is not a template - return; - buf->writeByte('I'); - for (size_t i = 0; i < ti->tiargs->length; i++) - { - RootObject *o = (*ti->tiargs)[i]; - TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration(); - assert(td); - TemplateParameter *tp = (*td->parameters)[i]; - - /* - * <template-arg> ::= <type> # type or template - * ::= X <expression> E # expression - * ::= <expr-primary> # simple expressions - * ::= I <template-arg>* E # argument pack - */ - if (tp->isTemplateTupleParameter()) - { - buf->writeByte('I'); // argument pack - - // mangle the rest of the arguments as types - for (size_t j = i; j < ti->tiargs->length; j++) - { - Type *t = isType((*ti->tiargs)[j]); - assert(t); - t->accept(this); - } - - buf->writeByte('E'); - break; - } - if (tp->isTemplateTypeParameter()) - { - Type *t = isType(o); - assert(t); - t->accept(this); - } - else if (TemplateValueParameter *tv = tp->isTemplateValueParameter()) - { - // <expr-primary> ::= L <type> <value number> E # integer literal - if (tv->valType->isintegral()) - { - Expression *e = isExpression(o); - assert(e); - buf->writeByte('L'); - tv->valType->accept(this); - uinteger_t val = e->toUInteger(); - if (!tv->valType->isunsigned() && (sinteger_t)val < 0) - { - val = -val; - buf->writeByte('n'); - } - buf->printf("%llu", val); - buf->writeByte('E'); - } - else - { - ti->error("Internal Compiler Error: C++ `%s` template value parameter is not supported", tv->valType->toChars()); - fatal(); - } - } - else if (tp->isTemplateAliasParameter()) - { - Dsymbol *d = isDsymbol(o); - Expression *e = isExpression(o); - if (d && d->isFuncDeclaration()) - { - bool is_nested = d->toParent3() && - !d->toParent3()->isModule() && - ((TypeFunction*)d->isFuncDeclaration()->type)->linkage == LINKcpp; - if (is_nested) - buf->writeByte('X'); - buf->writeByte('L'); - mangle_function(d->isFuncDeclaration()); - buf->writeByte('E'); - if (is_nested) - buf->writeByte('E'); - } - else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration()) - { - VarDeclaration *vd = ((VarExp*)e)->var->isVarDeclaration(); - buf->writeByte('L'); - mangle_variable(vd, true); - buf->writeByte('E'); - } - else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember) - { - if (!substitute(d)) - { - cpp_mangle_name(d, false); - } - } - else - { - ti->error("Internal Compiler Error: `%s` is unsupported parameter for C++ template", o->toChars()); - fatal(); - } - } - else if (tp->isTemplateThisParameter()) - { - ti->error("Internal Compiler Error: C++ `%s` template this parameter is not supported", o->toChars()); - fatal(); - } - else - { - assert(0); - } - } - buf->writeByte('E'); - } - - void source_name(Dsymbol *s) - { - //printf("source_name(%s)\n", s->toChars()); - if (TemplateInstance *ti = s->isTemplateInstance()) - { - if (!substitute(ti->tempdecl)) - { - append(ti->tempdecl); - const char *name = ti->tempdecl->toAlias()->ident->toChars(); - buf->printf("%d", strlen(name)); - buf->writestring(name); - } - template_args(ti); - } - else - { - const char *name = s->ident->toChars(); - buf->printf("%d", strlen(name)); - buf->writestring(name); - } - } - - /******** - * See if s is actually an instance of a template - * Params: - * s = symbol - * Returns: - * if s is instance of a template, return the instance, otherwise return s - */ - Dsymbol *getInstance(Dsymbol *s) - { - Dsymbol *p = s->toParent3(); - if (p) - { - if (TemplateInstance *ti = p->isTemplateInstance()) - return ti; - } - return s; - } - - /******** - * Get qualifier for `s`, meaning the symbol - * that s is in the symbol table of. - * The module does not count as a qualifier, because C++ - * does not have modules. - * Params: - * s = symbol that may have a qualifier - * Returns: - * qualifier, NULL if none - */ - static Dsymbol *getQualifier(Dsymbol *s) - { - Dsymbol *p = s->toParent3(); - return (p && !p->isModule()) ? p : NULL; - } - - // Detect type char - static bool isChar(RootObject *o) - { - Type *t = isType(o); - return (t && t->equals(Type::tchar)); - } - - // Detect type ::std::char_traits<char> - static bool isChar_traits_char(RootObject *o) - { - return isIdent_char(Id::char_traits, o); - } - - // Detect type ::std::allocator<char> - static bool isAllocator_char(RootObject *o) - { - return isIdent_char(Id::allocator, o); - } - - // Detect type ::std::ident<char> - static bool isIdent_char(Identifier *ident, RootObject *o) - { - Type *t = isType(o); - if (!t || t->ty != Tstruct) - return false; - Dsymbol *s = ((TypeStruct*)t)->toDsymbol(NULL); - if (s->ident != ident) - return false; - Dsymbol *p = s->toParent3(); - if (!p) - return false; - TemplateInstance *ti = p->isTemplateInstance(); - if (!ti) - return false; - Dsymbol *q = getQualifier(ti); - return isStd(q) && ti->tiargs->length == 1 && isChar((*ti->tiargs)[0]); - } - - /*** - * Detect template args <char, ::std::char_traits<char>> - * and write st if found. - * Returns: - * true if found - */ - bool char_std_char_traits_char(TemplateInstance *ti, const char *st) - { - if (ti->tiargs->length == 2 && - isChar((*ti->tiargs)[0]) && - isChar_traits_char((*ti->tiargs)[1])) - { - buf->writestring(st); - return true; - } - return false; - } - - - void prefix_name(Dsymbol *s) - { - //printf("prefix_name(%s)\n", s->toChars()); - if (!substitute(s)) - { - Dsymbol *si = getInstance(s); - Dsymbol *p = getQualifier(si); - if (p) - { - if (isStd(p)) - { - TemplateInstance *ti = si->isTemplateInstance(); - if (ti) - { - if (s->ident == Id::allocator) - { - buf->writestring("Sa"); - template_args(ti); - append(ti); - return; - } - if (s->ident == Id::basic_string) - { - // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>> - if (ti->tiargs->length == 3 && - isChar((*ti->tiargs)[0]) && - isChar_traits_char((*ti->tiargs)[1]) && - isAllocator_char((*ti->tiargs)[2])) - - { - buf->writestring("Ss"); - return; - } - buf->writestring("Sb"); // ::std::basic_string - template_args(ti); - append(ti); - return; - } - - // ::std::basic_istream<char, ::std::char_traits<char>> - if (s->ident == Id::basic_istream && - char_std_char_traits_char(ti, "Si")) - return; - - // ::std::basic_ostream<char, ::std::char_traits<char>> - if (s->ident == Id::basic_ostream && - char_std_char_traits_char(ti, "So")) - return; - - // ::std::basic_iostream<char, ::std::char_traits<char>> - if (s->ident == Id::basic_iostream && - char_std_char_traits_char(ti, "Sd")) - return; - } - buf->writestring("St"); - } - else - prefix_name(p); - } - source_name(si); - if (!isStd(si)) - { - /* Do this after the source_name() call to keep components[] - * in the right order. - * https://issues.dlang.org/show_bug.cgi?id=17947 - */ - append(si); - } - } - } - - void cpp_mangle_name(Dsymbol *s, bool qualified) - { - //printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified); - Dsymbol *p = s->toParent3(); - Dsymbol *se = s; - bool write_prefix = true; - if (p && p->isTemplateInstance()) - { - se = p; - if (find(p->isTemplateInstance()->tempdecl) >= 0) - write_prefix = false; - p = p->toParent3(); - } - - if (p && !p->isModule()) - { - /* The N..E is not required if: - * 1. the parent is 'std' - * 2. 'std' is the initial qualifier - * 3. there is no CV-qualifier or a ref-qualifier for a member function - * ABI 5.1.8 - */ - if (isStd(p) && !qualified) - { - TemplateInstance *ti = se->isTemplateInstance(); - if (s->ident == Id::allocator) - { - buf->writestring("Sa"); // "Sa" is short for ::std::allocator - template_args(ti); - } - else if (s->ident == Id::basic_string) - { - // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>> - if (ti->tiargs->length == 3 && - isChar((*ti->tiargs)[0]) && - isChar_traits_char((*ti->tiargs)[1]) && - isAllocator_char((*ti->tiargs)[2])) - - { - buf->writestring("Ss"); - return; - } - buf->writestring("Sb"); // ::std::basic_string - template_args(ti); - } - else - { - // ::std::basic_istream<char, ::std::char_traits<char>> - if (s->ident == Id::basic_istream) - { - if (char_std_char_traits_char(ti, "Si")) - return; - } - else if (s->ident == Id::basic_ostream) - { - if (char_std_char_traits_char(ti, "So")) - return; - } - else if (s->ident == Id::basic_iostream) - { - if (char_std_char_traits_char(ti, "Sd")) - return; - } - buf->writestring("St"); - source_name(se); - } - } - else - { - buf->writeByte('N'); - if (write_prefix) - prefix_name(p); - source_name(se); - buf->writeByte('E'); - } - } - else - source_name(se); - append(s); - } - - void CV_qualifiers(Type *t) - { - // CV-qualifiers are 'r': restrict, 'V': volatile, 'K': const - if (t->isConst()) - buf->writeByte('K'); - } - - void mangle_variable(VarDeclaration *d, bool is_temp_arg_ref) - { - // fake mangling for fields to fix https://issues.dlang.org/show_bug.cgi?id=16525 - if (!(d->storage_class & (STCextern | STCfield | STCgshared))) - { - d->error("Internal Compiler Error: C++ static non-`__gshared` non-`extern` variables not supported"); - fatal(); - } - - Dsymbol *p = d->toParent3(); - if (p && !p->isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE" - { - buf->writestring("_ZN"); - prefix_name(p); - source_name(d); - buf->writeByte('E'); - } - else //char beta[6] should mangle as "beta" - { - if (!is_temp_arg_ref) - { - buf->writestring(d->ident->toChars()); - } - else - { - buf->writestring("_Z"); - source_name(d); - } - } - } - - void mangle_function(FuncDeclaration *d) - { - //printf("mangle_function(%s)\n", d->toChars()); - /* - * <mangled-name> ::= _Z <encoding> - */ - buf->writestring("_Z"); - this->mangle_function_encoding(d); - } - - void mangle_function_encoding(FuncDeclaration *d) - { - //printf("mangle_function_encoding(%s)\n", d->toChars()); - /* - * <encoding> ::= <function name> <bare-function-type> - * ::= <data name> - * ::= <special-name> - */ - TypeFunction *tf = (TypeFunction *)d->type; - - if (getFuncTemplateDecl(d)) - { - /* It's an instance of a function template - */ - TemplateInstance *ti = d->parent->isTemplateInstance(); - assert(ti); - Dsymbol *p = ti->toParent3(); - if (p && !p->isModule() && tf->linkage == LINKcpp) - { - buf->writeByte('N'); - CV_qualifiers(d->type); - prefix_name(p); - if (d->isCtorDeclaration()) - buf->writestring("C1"); - else if (d->isDtorDeclaration()) - buf->writestring("D1"); - else - source_name(ti); - buf->writeByte('E'); - } - else - source_name(ti); - headOfType(tf->nextOf()); // mangle return type - } - else - { - Dsymbol *p = d->toParent3(); - if (p && !p->isModule() && tf->linkage == LINKcpp) - { - /* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E - * ::= N [<CV-qualifiers>] <template-prefix> <template-args> E - */ - buf->writeByte('N'); - CV_qualifiers(d->type); - - /* <prefix> ::= <prefix> <unqualified-name> - * ::= <template-prefix> <template-args> - * ::= <template-param> - * ::= # empty - * ::= <substitution> - * ::= <prefix> <data-member-prefix> - */ - prefix_name(p); - //printf("p: %s\n", buf.peekChars()); - - if (d->isCtorDeclaration()) - { - buf->writestring("C1"); - } - else if (d->isDtorDeclaration()) - { - buf->writestring("D1"); - } - else - { - source_name(d); - } - buf->writeByte('E'); - } - else - { - source_name(d); - } - } - - if (tf->linkage == LINKcpp) //Template args accept extern "C" symbols with special mangling - { - assert(tf->ty == Tfunction); - mangleFunctionParameters(tf->parameterList.parameters, - tf->parameterList.varargs); - } - } - - void mangleFunctionParameters(Parameters *parameters, int varargs) - { - struct ParamsCppMangle - { - int numparams; - CppMangleVisitor *mangler; - - static int dg(void *ctx, size_t, Parameter *fparam) - { - ParamsCppMangle *p = (ParamsCppMangle *)ctx; - CppMangleVisitor *mangler = p->mangler; - Type *t = target.cpp.parameterType(fparam); - if (t->ty == Tsarray) - { - // Static arrays in D are passed by value; no counterpart in C++ - t->error(mangler->loc, "Internal Compiler Error: unable to pass static array `%s` to extern(C++) function, use pointer instead", - t->toChars()); - fatal(); - } - mangler->headOfType(t); - p->numparams++; - return 0; - } - }; - - ParamsCppMangle p; - p.numparams = 0; - p.mangler = this; - - if (parameters) - Parameter_foreach(parameters, &ParamsCppMangle::dg, (void*)&p); - - if (varargs) - buf->writeByte('z'); - else if (!p.numparams) - buf->writeByte('v'); // encode (void) parameters - } - -public: - CppMangleVisitor(OutBuffer *buf, Loc loc) - : components(), buf(buf), loc(loc) - { - } - - /***** - * Entry point. Append mangling to buf[] - * Params: - * s = symbol to mangle - */ - void mangleOf(Dsymbol *s) - { - if (VarDeclaration *vd = s->isVarDeclaration()) - { - mangle_variable(vd, false); - } - else if (FuncDeclaration *fd = s->isFuncDeclaration()) - { - mangle_function(fd); - } - else - { - assert(0); - } - } - - /****** The rest is type mangling ************/ - - void error(Type *t) - { - const char *p; - if (t->isImmutable()) - p = "`immutable` "; - else if (t->isShared()) - p = "`shared` "; - else - p = ""; - t->error(loc, "Internal Compiler Error: %stype `%s` can not be mapped to C++", p, t->toChars()); - fatal(); //Fatal, because this error should be handled in frontend - } - - /**************************** - * Mangle a type, - * treating it as a Head followed by a Tail. - * Params: - * t = Head of a type - */ - void headOfType(Type *t) - { - if (t->ty == Tclass) - { - mangleTypeClass((TypeClass*)t, true); - } - else - { - // For value types, strip const/immutable/shared from the head of the type - t->mutableOf()->unSharedOf()->accept(this); - } - } - - void visit(Type *t) - { - error(t); - } - - /****** - * Write out 1 or 2 character basic type mangling. - * Handle const and substitutions. - * Params: - * t = type to mangle - * p = if not 0, then character prefix - * c = mangling character - */ - void writeBasicType(Type *t, char p, char c) - { - // Only do substitutions for non-fundamental types. - if (!isFundamentalType(t) || t->isConst()) - { - if (substitute(t)) - return; - else - append(t); - } - CV_qualifiers(t); - if (p) - buf->writeByte(p); - buf->writeByte(c); - } - - void visit(TypeNull *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - writeBasicType(t, 'D', 'n'); - } - - void visit(TypeNoreturn *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - writeBasicType(t, 0, 'v'); // mangle like `void` - } - - void visit(TypeBasic *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - // Handle any target-specific basic types. - if (const char *tm = target.cpp.typeMangle(t)) - { - // Only do substitutions for non-fundamental types. - if (!isFundamentalType(t) || t->isConst()) - { - if (substitute(t)) - return; - else - append(t); - } - CV_qualifiers(t); - buf->writestring(tm); - return; - } - - /* <builtin-type>: - * v void - * w wchar_t - * b bool - * c char - * a signed char - * h unsigned char - * s short - * t unsigned short - * i int - * j unsigned int - * l long - * m unsigned long - * x long long, __int64 - * y unsigned long long, __int64 - * n __int128 - * o unsigned __int128 - * f float - * d double - * e long double, __float80 - * g __float128 - * z ellipsis - * Dd 64 bit IEEE 754r decimal floating point - * De 128 bit IEEE 754r decimal floating point - * Df 32 bit IEEE 754r decimal floating point - * Dh 16 bit IEEE 754r half-precision floating point - * Di char32_t - * Ds char16_t - * u <source-name> # vendor extended type - */ - - char c; - char p = 0; - switch (t->ty) - { - case Tvoid: c = 'v'; break; - case Tint8: c = 'a'; break; - case Tuns8: c = 'h'; break; - case Tint16: c = 's'; break; - case Tuns16: c = 't'; break; - case Tint32: c = 'i'; break; - case Tuns32: c = 'j'; break; - case Tfloat32: c = 'f'; break; - case Tint64: - c = (target.c.longsize == 8 ? 'l' : 'x'); - break; - case Tuns64: - c = (target.c.longsize == 8 ? 'm' : 'y'); - break; - case Tint128: c = 'n'; break; - case Tuns128: c = 'o'; break; - case Tfloat64: c = 'd'; break; - case Tfloat80: c = 'e'; break; - case Tbool: c = 'b'; break; - case Tchar: c = 'c'; break; - case Twchar: c = 't'; break; // unsigned short (perhaps use 'Ds' ? - case Tdchar: c = 'w'; break; // wchar_t (UTF-32) (perhaps use 'Di' ? - case Timaginary32: p = 'G'; c = 'f'; break; // 'G' means imaginary - case Timaginary64: p = 'G'; c = 'd'; break; - case Timaginary80: p = 'G'; c = 'e'; break; - case Tcomplex32: p = 'C'; c = 'f'; break; // 'C' means complex - case Tcomplex64: p = 'C'; c = 'd'; break; - case Tcomplex80: p = 'C'; c = 'e'; break; - - default: - return error(t); - } - writeBasicType(t, p, c); - } - - void visit(TypeVector *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - if (substitute(t)) - return; - append(t); - CV_qualifiers(t); - - // Handle any target-specific vector types. - if (const char *tm = target.cpp.typeMangle(t)) - { - buf->writestring(tm); - } - else - { - assert(t->basetype && t->basetype->ty == Tsarray); - assert(((TypeSArray *)t->basetype)->dim); - buf->writestring("U8__vector"); //-- Gnu ABI v.3 - t->basetype->nextOf()->accept(this); - } - } - - void visit(TypeSArray *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - if (!substitute(t)) - append(t); - CV_qualifiers(t); - buf->writeByte('A'); - buf->printf("%llu", t->dim ? t->dim->toInteger() : 0); - buf->writeByte('_'); - t->next->accept(this); - } - - void visit(TypePointer *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - if (substitute(t)) - return; - CV_qualifiers(t); - buf->writeByte('P'); - t->next->accept(this); - append(t); - } - - void visit(TypeReference *t) - { - //printf("TypeReference %s\n", t->toChars()); - if (substitute(t)) - return; - buf->writeByte('R'); - t->next->accept(this); - append(t); - } - - void visit(TypeFunction *t) - { - /* - * <function-type> ::= F [Y] <bare-function-type> E - * <bare-function-type> ::= <signature type>+ - * # types are possible return type, then parameter types - */ - - /* ABI says: - "The type of a non-static member function is considered to be different, - for the purposes of substitution, from the type of a namespace-scope or - static member function whose type appears similar. The types of two - non-static member functions are considered to be different, for the - purposes of substitution, if the functions are members of different - classes. In other words, for the purposes of substitution, the class of - which the function is a member is considered part of the type of - function." - - BUG: Right now, types of functions are never merged, so our simplistic - component matcher always finds them to be different. - We should use Type::equals on these, and use different - TypeFunctions for non-static member functions, and non-static - member functions of different classes. - */ - if (substitute(t)) - return; - buf->writeByte('F'); - if (t->linkage == LINKc) - buf->writeByte('Y'); - Type *tn = t->next; - if (t->isref) - tn = tn->referenceTo(); - tn->accept(this); - mangleFunctionParameters(t->parameterList.parameters, - t->parameterList.varargs); - buf->writeByte('E'); - append(t); - } - - void visit(TypeStruct *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - //printf("TypeStruct %s\n", t->toChars()); - doSymbol(t); - } - - - void visit(TypeEnum *t) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - /* __c_(u)long(long) and others get special mangling - */ - Identifier *id = t->sym->ident; - //printf("enum id = '%s'\n", id->toChars()); - if (id == Id::__c_long) - return writeBasicType(t, 0, 'l'); - else if (id == Id::__c_ulong) - return writeBasicType(t, 0, 'm'); - else if (id == Id::__c_wchar_t) - return writeBasicType(t, 0, 'w'); - else if (id == Id::__c_longlong) - return writeBasicType(t, 0, 'x'); - else if (id == Id::__c_ulonglong) - return writeBasicType(t, 0, 'y'); - else if (id == Id::__c_complex_float) - return writeBasicType(t, 'C', 'f'); - else if (id == Id::__c_complex_double) - return writeBasicType(t, 'C', 'd'); - else if (id == Id::__c_complex_real) - return writeBasicType(t, 'C', 'e'); - - doSymbol(t); - } - - /**************** - * Write structs and enums. - * Params: - * t = TypeStruct or TypeEnum - */ - void doSymbol(Type *t) - { - if (substitute(t)) - return; - CV_qualifiers(t); - - // Handle any target-specific struct types. - if (const char *tm = target.cpp.typeMangle(t)) - { - buf->writestring(tm); - } - else - { - Dsymbol *s = t->toDsymbol(NULL); - Dsymbol *p = s->toParent3(); - if (p && p->isTemplateInstance()) - { - /* https://issues.dlang.org/show_bug.cgi?id=17947 - * Substitute the template instance symbol, not the struct/enum symbol - */ - if (substitute(p)) - return; - } - if (!substitute(s)) - { - cpp_mangle_name(s, t->isConst()); - } - } - if (t->isConst()) - append(t); - } - - void visit(TypeClass *t) - { - mangleTypeClass(t, false); - } - - /************************ - * Mangle a class type. - * If it's the head, treat the initial pointer as a value type. - * Params: - * t = class type - * head = true for head of a type - */ - void mangleTypeClass(TypeClass *t, bool head) - { - if (t->isImmutable() || t->isShared()) - return error(t); - - /* Mangle as a <pointer to><struct> - */ - if (substitute(t)) - return; - if (!head) - CV_qualifiers(t); - buf->writeByte('P'); - - CV_qualifiers(t); - - { - Dsymbol *s = t->toDsymbol(NULL); - Dsymbol *p = s->toParent3(); - if (p && p->isTemplateInstance()) - { - /* https://issues.dlang.org/show_bug.cgi?id=17947 - * Substitute the template instance symbol, not the class symbol - */ - if (substitute(p)) - return; - } - } - - if (!substitute(t->sym)) - { - cpp_mangle_name(t->sym, t->isConst()); - } - if (t->isConst()) - append(NULL); // C++ would have an extra type here - append(t); - } - - const char *mangle_typeinfo(Dsymbol *s) - { - buf->writestring("_ZTI"); - cpp_mangle_name(s, false); - return buf->extractChars(); - } -}; - -const char *toCppMangleItanium(Dsymbol *s) -{ - //printf("toCppMangleItanium(%s)\n", s->toChars()); - OutBuffer buf; - CppMangleVisitor v(&buf, s->loc); - v.mangleOf(s); - return buf.extractChars(); -} - -const char *cppTypeInfoMangleItanium(Dsymbol *s) -{ - //printf("cppTypeInfoMangleItanium(%s)\n", s->toChars()); - OutBuffer buf; - buf.writestring("_ZTI"); // "TI" means typeinfo structure - CppMangleVisitor v(&buf, s->loc); - v.cpp_mangle_name(s, false); - return buf.extractChars(); -} - -const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset) -{ - //printf("cppThunkMangleItanium(%s)\n", fd.toChars()); - OutBuffer buf; - buf.printf("_ZThn%u_", offset); // "Th" means thunk, "n%u" is the call offset - CppMangleVisitor v(&buf, fd->loc); - v.mangle_function_encoding(fd); - return buf.extractChars(); -} |