From eb98f5750dab11041fb67218e6df36cf4382260c Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 6 Aug 2018 06:37:28 +0200 Subject: [PATCH 01/10] Update to gcc-9-20180805 --- gcc.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc.version b/gcc.version index adcdbbd2e..4d6efce21 100644 --- a/gcc.version +++ b/gcc.version @@ -1 +1 @@ -gcc-9-20180729 +gcc-9-20180805 From e8c9c10e4f60e376dc90084f8e693496ccb638af Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 13 Aug 2018 07:59:46 +0200 Subject: [PATCH 02/10] Update to gcc-9-20180812 --- gcc.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc.version b/gcc.version index 4d6efce21..5eef2eaa5 100644 --- a/gcc.version +++ b/gcc.version @@ -1 +1 @@ -gcc-9-20180805 +gcc-9-20180812 From 47685335665775950bfd3e34b747da69c1153211 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 21 Aug 2018 06:36:14 +0200 Subject: [PATCH 03/10] Update to gcc-9-20180819 --- gcc.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc.version b/gcc.version index 5eef2eaa5..662fc3d68 100644 --- a/gcc.version +++ b/gcc.version @@ -1 +1 @@ -gcc-9-20180812 +gcc-9-20180819 From b25ac31e995c3dc598d7c87c4bc4cf9366c7ac8e Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 29 Aug 2018 11:51:49 +0200 Subject: [PATCH 04/10] Remove the -fproperty command-line option --- gcc/d/ChangeLog | 6 ++++++ gcc/d/d-builtins.cc | 4 ++++ gcc/d/d-lang.cc | 4 ---- gcc/d/lang.opt | 4 ---- gcc/testsuite/gdc.test/d_do_test.exp | 3 --- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 9b8944ff0..237592ca3 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,4 +1,10 @@ +2018-08-25 Iain Buclaw + + * lang.opt (fproperty): Remove option. + * d-lang.cc (d_handle_option): Remove case for OPT_fproperty. + 2018-07-23 Eugene Wissner + * d-lang.cc (d_handle_option): Change function argument to HOST_WIDE_INT. * lang.opt (Walloca-larger-than=, Wno-alloca-larger-than): New options. * opt.texi (Walloca-larger-than=, Wno-alloca-larger-than): Likewise. diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index 8ff428449..2363552ac 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -430,12 +430,16 @@ d_init_versions (void) VersionCondition::addPredefinedGlobalIdent ("D_Coverage"); if (flag_pic) VersionCondition::addPredefinedGlobalIdent ("D_PIC"); + if (global.params.doDocComments) VersionCondition::addPredefinedGlobalIdent ("D_Ddoc"); + if (global.params.useUnitTests) VersionCondition::addPredefinedGlobalIdent ("unittest"); + if (global.params.useAssert) VersionCondition::addPredefinedGlobalIdent ("assert"); + if (global.params.useArrayBounds == BOUNDSCHECKoff) VersionCondition::addPredefinedGlobalIdent ("D_NoBoundsChecks"); diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 0d908b2ec..a0d28246b 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -514,10 +514,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, global.params.useIn = value; break; - case OPT_fproperty: - global.params.enforcePropertySyntax = value; - break; - case OPT_frelease: global.params.release = value; break; diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt index d2f8d8631..2eb74f354 100644 --- a/gcc/d/lang.opt +++ b/gcc/d/lang.opt @@ -269,10 +269,6 @@ fpreconditions D Var(flag_preconditions) Generate code for precondition contracts. -fproperty -D -This switch is deprecated; do not use. - frelease D Compile release version. diff --git a/gcc/testsuite/gdc.test/d_do_test.exp b/gcc/testsuite/gdc.test/d_do_test.exp index 4a7333913..a3c49165b 100644 --- a/gcc/testsuite/gdc.test/d_do_test.exp +++ b/gcc/testsuite/gdc.test/d_do_test.exp @@ -92,9 +92,6 @@ proc gdc-convert-args { base args } { } elseif [string match "-O" $arg] { lappend out "-O2" - } elseif [string match "-property" $arg] { - lappend out "-fproperty" - } elseif [string match "-release" $arg] { lappend out "-frelease" From b748a7d965f83aca78a68635438ed500acbbd6ef Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 29 Aug 2018 13:02:54 +0200 Subject: [PATCH 05/10] Backport GccAsmStatement patches --- gcc/d/ChangeLog | 3 + gcc/d/Make-lang.in | 2 + gcc/d/d-frontend.cc | 9 - gcc/d/dfrontend/dinterpret.c | 28 --- gcc/d/dfrontend/func.c | 3 - gcc/d/dfrontend/hdrgen.c | 60 ------ gcc/d/dfrontend/iasm.c | 45 +++++ gcc/d/dfrontend/iasmgcc.c | 359 +++++++++++++++++++++++++++++++++ gcc/d/dfrontend/parse.c | 234 --------------------- gcc/d/dfrontend/parse.h | 6 - gcc/d/dfrontend/statement.c | 57 +++--- gcc/d/dfrontend/statement.h | 56 ++--- gcc/d/dfrontend/statementsem.c | 69 +------ gcc/d/dfrontend/visitor.h | 10 +- gcc/d/toir.cc | 4 +- 15 files changed, 476 insertions(+), 469 deletions(-) create mode 100644 gcc/d/dfrontend/iasm.c create mode 100644 gcc/d/dfrontend/iasmgcc.c diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 237592ca3..5c1bafa04 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,7 +1,10 @@ 2018-08-25 Iain Buclaw + * Make-lang.in (D_FRONTEND_OBJS): Add iasm.o, iasmgcc.o * lang.opt (fproperty): Remove option. * d-lang.cc (d_handle_option): Remove case for OPT_fproperty. + * toir.cc (IRVisitor::visit(ExtAsmStatement)): Rename override to + GccAsmStatement. 2018-07-23 Eugene Wissner diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in index 1b87e0ac4..a224a2bdc 100644 --- a/gcc/d/Make-lang.in +++ b/gcc/d/Make-lang.in @@ -94,6 +94,8 @@ D_FRONTEND_OBJS = \ d/filename.o \ d/func.o \ d/hdrgen.o \ + d/iasm.o \ + d/iasmgcc.o \ d/identifier.o \ d/imphint.o \ d/init.o \ diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc index 512bf1dda..63dfda9b4 100644 --- a/gcc/d/d-frontend.cc +++ b/gcc/d/d-frontend.cc @@ -428,15 +428,6 @@ CTFloat::hash (real_t r) /* Implements backend-specific interfaces used by the frontend. */ -/* Semantically analyze AsmStatement where SC is the scope. */ - -Statement * -asmSemantic (AsmStatement *s, Scope *sc) -{ - sc->func->hasReturnExp |= 8; - return s; -} - /* Determine return style of function - whether in registers or through a hidden pointer to the caller's stack. */ diff --git a/gcc/d/dfrontend/dinterpret.c b/gcc/d/dfrontend/dinterpret.c index 3e980720e..0d4aed15f 100644 --- a/gcc/d/dfrontend/dinterpret.c +++ b/gcc/d/dfrontend/dinterpret.c @@ -689,16 +689,6 @@ class CtfeCompiler : public Visitor // we can't compile asm statements } -#ifdef IN_GCC - void visit(ExtAsmStatement *) - { - #if LOGCOMPILE - printf("%s ExtAsmStatement::ctfeCompile\n", s->loc.toChars()); - #endif - // we can't compile ext asm statements - } -#endif - void ctfeCompile(Statement *s) { s->accept(this); @@ -1998,24 +1988,6 @@ class Interpreter : public Visitor result = CTFEExp::cantexp; } -#ifdef IN_GCC - void visit(ExtAsmStatement *s) - { - #if LOG - printf("%s ExtAsmStatement::interpret()\n", s->loc.toChars()); - #endif - if (istate->start) - { - if (istate->start != s) - return; - istate->start = NULL; - } - - s->error("extended asm statements cannot be interpreted at compile time"); - result = CTFEExp::cantexp; - } -#endif - void visit(ImportStatement *s) { #if LOG diff --git a/gcc/d/dfrontend/func.c b/gcc/d/dfrontend/func.c index afb9b06a6..124e53451 100644 --- a/gcc/d/dfrontend/func.c +++ b/gcc/d/dfrontend/func.c @@ -211,9 +211,6 @@ class StatementRewriteWalker : public Visitor visitStmt(s->statement); } void visit(AsmStatement *) { } -#ifdef IN_GCC - void visit(ExtAsmStatement *) { } -#endif void visit(ImportStatement *) { } }; diff --git a/gcc/d/dfrontend/hdrgen.c b/gcc/d/dfrontend/hdrgen.c index ece60b59c..f84c8885f 100644 --- a/gcc/d/dfrontend/hdrgen.c +++ b/gcc/d/dfrontend/hdrgen.c @@ -655,66 +655,6 @@ class PrettyPrintVisitor : public Visitor buf->writenl(); } -#ifdef IN_GCC - void visit(ExtAsmStatement *s) - { - buf->writestring ("gcc asm { "); - - if (s->insn) - buf->writestring (s->insn->toChars()); - - buf->writestring (" : "); - - if (s->args) - { - for (size_t i = 0; i < s->args->dim; i++) - { - Identifier *name = (*s->names)[i]; - Expression *constr = (*s->constraints)[i]; - Expression *arg = (*s->args)[i]; - - if (name) - { - buf->writestring ("["); - buf->writestring (name->toChars()); - buf->writestring ("] "); - } - - if (constr) - { - buf->writestring (constr->toChars()); - buf->writestring (" "); - } - - if (arg) - buf->writestring (arg->toChars()); - - if (i < s->outputargs - 1) - buf->writestring (", "); - else if (i == s->outputargs - 1) - buf->writestring (" : "); - else if (i < s->args->dim - 1) - buf->writestring (", "); - } - } - - if (s->clobbers) - { - buf->writestring (" : "); - for (size_t i = 0; i < s->clobbers->dim; i++) - { - Expression *clobber = (*s->clobbers)[i]; - buf->writestring (clobber->toChars()); - if (i < s->clobbers->dim - 1) - buf->writestring (", "); - } - } - - buf->writestring ("; }"); - buf->writenl(); - } -#endif - void visit(ImportStatement *s) { for (size_t i = 0; i < s->imports->dim; i++) diff --git a/gcc/d/dfrontend/iasm.c b/gcc/d/dfrontend/iasm.c new file mode 100644 index 000000000..79071d28a --- /dev/null +++ b/gcc/d/dfrontend/iasm.c @@ -0,0 +1,45 @@ + +/* Compiler implementation of the D programming language + * Copyright (C) 2018 by The D Language Foundation, All Rights Reserved + * 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/iasm.c + */ + +/* Inline assembler for the D programming language compiler + */ + +#include "scope.h" +#include "declaration.h" +#include "statement.h" + +#ifdef IN_GCC +Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc); +#else +Statement *inlineAsmSemantic(InlineAsmStatement *s, Scope *sc); +#endif + +Statement *asmSemantic(AsmStatement *s, Scope *sc) +{ + //printf("AsmStatement::semantic()\n"); + + FuncDeclaration *fd = sc->parent->isFuncDeclaration(); + assert(fd); + + if (!s->tokens) + return NULL; + + // Assume assembler code takes care of setting the return value + sc->func->hasReturnExp |= 8; + +#ifdef IN_GCC + GccAsmStatement *eas = new GccAsmStatement(s->loc, s->tokens); + return gccAsmSemantic(eas, sc); +#else + InlineAsmStatement *ias = new InlineAsmStatement(s->loc, s->tokens); + return inlineAsmSemantic(ias, sc); +#endif +} diff --git a/gcc/d/dfrontend/iasmgcc.c b/gcc/d/dfrontend/iasmgcc.c new file mode 100644 index 000000000..8a8a5faa5 --- /dev/null +++ b/gcc/d/dfrontend/iasmgcc.c @@ -0,0 +1,359 @@ + +/* Compiler implementation of the D programming language + * Copyright (C) 2018 by The D Language Foundation, All Rights Reserved + * All Rights Reserved + * written by Iain Buclaw + * 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/iasmgcc.c + */ + +/* Inline assembler for the GCC D compiler. + */ + +#include "scope.h" +#include "declaration.h" +#include "parse.h" +#include "statement.h" + +Expression *semantic(Expression *e, Scope *sc); +Statement *semantic(Statement *s, Scope *sc); + +/*********************************** + * Parse list of extended asm input or output operands. + * Grammar: + * | Operands: + * | SymbolicName(opt) StringLiteral AssignExpression + * | SymbolicName(opt) StringLiteral AssignExpression , Operands + * | + * | SymbolicName: + * | [ Identifier ] + * Params: + * p = parser state + * s = asm statement to parse + * Returns: + * number of operands added to the gcc asm statement + */ +static int parseExtAsmOperands(Parser *p, GccAsmStatement *s) +{ + int numargs = 0; + + while (1) + { + Expression *arg = NULL; + Identifier *name = NULL; + Expression *constraint = NULL; + + switch (p->token.value) + { + case TOKsemicolon: + case TOKcolon: + case TOKeof: + return numargs; + + case TOKlbracket: + if (p->peekNext() == TOKidentifier) + { + p->nextToken(); + name = p->token.ident; + p->nextToken(); + } + else + { + p->error(s->loc, "expected identifier after `[`"); + goto Lerror; + } + p->check(TOKrbracket); + // fall through + + case TOKstring: + constraint = p->parsePrimaryExp(); + arg = p->parseAssignExp(); + + if (!s->args) + { + s->names = new Identifiers(); + s->constraints = new Expressions(); + s->args = new Expressions(); + } + s->names->push(name); + s->args->push(arg); + s->constraints->push(constraint); + numargs++; + + if (p->token.value == TOKcomma) + p->nextToken(); + break; + + default: + p->error("expected constant string constraint for operand, not `%s`", + p->token.toChars()); + goto Lerror; + } + } +Lerror: + while (p->token.value != TOKrcurly && + p->token.value != TOKsemicolon && + p->token.value != TOKeof) + p->nextToken(); + + return numargs; +} + +/*********************************** + * Parse list of extended asm clobbers. + * Grammar: + * | Clobbers: + * | StringLiteral + * | StringLiteral , Clobbers + * Params: + * p = parser state + * Returns: + * array of parsed clobber expressions + */ +static Expressions *parseExtAsmClobbers(Parser *p) +{ + Expressions *clobbers = NULL; + + while (1) + { + Expression *clobber; + + switch (p->token.value) + { + case TOKsemicolon: + case TOKcolon: + case TOKeof: + return clobbers; + + case TOKstring: + clobber = p->parsePrimaryExp(); + if (!clobbers) + clobbers = new Expressions(); + clobbers->push(clobber); + + if (p->token.value == TOKcomma) + p->nextToken(); + break; + + default: + p->error("expected constant string constraint for clobber name, not `%s`", + p->token.toChars()); + goto Lerror; + } + } +Lerror: + while (p->token.value != TOKrcurly && + p->token.value != TOKsemicolon && + p->token.value != TOKeof) + p->nextToken(); + + return clobbers; +} + +/*********************************** + * Parse list of extended asm goto labels. + * Grammar: + * | GotoLabels: + * | Identifier + * | Identifier , GotoLabels + * Params: + * p = parser state + * Returns: + * array of parsed goto labels + */ +static Identifiers *parseExtAsmGotoLabels(Parser *p) +{ + Identifiers *labels = NULL; + + while (1) + { + switch (p->token.value) + { + case TOKsemicolon: + case TOKeof: + return labels; + + case TOKidentifier: + if (!labels) + labels = new Identifiers(); + labels->push(p->token.ident); + + if (p->nextToken() == TOKcomma) + p->nextToken(); + break; + + default: + p->error("expected identifier for goto label name, not `%s`", + p->token.toChars()); + goto Lerror; + } + } +Lerror: + while (p->token.value != TOKrcurly && + p->token.value != TOKsemicolon && + p->token.value != TOKeof) + p->nextToken(); + + return labels; +} + +/*********************************** + * Parse a gcc asm statement. + * There are three forms of inline asm statements, basic, extended, and goto. + * Grammar: + * | AsmInstruction: + * | BasicAsmInstruction + * | ExtAsmInstruction + * | GotoAsmInstruction + * | + * | BasicAsmInstruction: + * | Expression + * | + * | ExtAsmInstruction: + * | Expression : Operands(opt) : Operands(opt) : Clobbers(opt) + * | + * | GotoAsmInstruction: + * | Expression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt) + * Params: + * p = parser state + * s = asm statement to parse + * Returns: + * the parsed gcc asm statement + */ +static GccAsmStatement *parseGccAsm(Parser *p, GccAsmStatement *s) +{ + s->insn = p->parseExpression(); + if (p->token.value == TOKsemicolon) + goto Ldone; + + // No semicolon followed after instruction template, treat as extended asm. + for (int section = 0; section < 4; ++section) + { + p->check(TOKcolon); + + switch (section) + { + case 0: + s->outputargs = parseExtAsmOperands(p, s); + break; + + case 1: + parseExtAsmOperands(p, s); + break; + + case 2: + s->clobbers = parseExtAsmClobbers(p); + break; + + case 3: + s->labels = parseExtAsmGotoLabels(p); + break; + + default: + assert(0); + } + + if (p->token.value == TOKsemicolon) + goto Ldone; + } +Ldone: + p->check(TOKsemicolon); + + return s; +} + +/*********************************** + * Parse and run semantic analysis on a GccAsmStatement. + * Params: + * s = gcc asm statement being parsed + * sc = the scope where the asm statement is located + * Returns: + * the completed gcc asm statement, or null if errors occurred + */ +Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc) +{ + //printf("GccAsmStatement::semantic()\n"); + Parser p(sc->_module, (const utf8_t *)";", 1, false); + + // Make a safe copy of the token list before parsing. + Token *toklist = NULL; + Token **ptoklist = &toklist; + + for (Token *token = s->tokens; token; token = token->next) + { + *ptoklist = Token::alloc(); + memcpy(*ptoklist, token, sizeof(Token)); + ptoklist = &(*ptoklist)->next; + *ptoklist = NULL; + } + p.token = *toklist; + + // Parse the gcc asm statement. + s = parseGccAsm(&p, s); + if (p.errors) + return NULL; + s->stc = sc->stc; + + // Fold the instruction template string. + if (s->insn->op == TOKmixin) + s->insn = ((CompileExp *)s->insn)->e1; + s->insn = semantic(s->insn, sc); + s->insn->ctfeInterpret(); + + if (s->insn->op != TOKstring || ((StringExp *) s->insn)->sz != 1) + s->insn->error("asm instruction template must be a constant char string"); + + if (s->labels && s->outputargs) + s->error("extended asm statements with labels cannot have output constraints"); + + // Analyse all input and output operands. + if (s->args) + { + for (size_t i = 0; i < s->args->dim; i++) + { + Expression *e = (*s->args)[i]; + e = semantic(e, sc); + // Check argument is a valid lvalue/rvalue. + if (i < s->outputargs) + e = e->modifiableLvalue(sc, NULL); + else if (e->checkValue()) + e = new ErrorExp(); + (*s->args)[i] = e; + + e = (*s->constraints)[i]; + e = semantic(e, sc); + assert(e->op == TOKstring && ((StringExp *) e)->sz == 1); + (*s->constraints)[i] = e; + } + } + + // Analyse all clobbers. + if (s->clobbers) + { + for (size_t i = 0; i < s->clobbers->dim; i++) + { + Expression *e = (*s->clobbers)[i]; + e = semantic(e, sc); + assert(e->op == TOKstring && ((StringExp *) e)->sz == 1); + (*s->clobbers)[i] = e; + } + } + + // Analyse all goto labels. + if (s->labels) + { + for (size_t i = 0; i < s->labels->dim; i++) + { + Identifier *ident = (*s->labels)[i]; + GotoStatement *gs = new GotoStatement(s->loc, ident); + if (!s->gotos) + s->gotos = new GotoStatements(); + s->gotos->push(gs); + semantic(gs, sc); + } + } + + return s; +} diff --git a/gcc/d/dfrontend/parse.c b/gcc/d/dfrontend/parse.c index 87502903f..f29559209 100644 --- a/gcc/d/dfrontend/parse.c +++ b/gcc/d/dfrontend/parse.c @@ -5773,17 +5773,6 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc /* { */ error("matching '}' expected, not end of file"); goto Lerror; - -#ifdef IN_GCC - case TOKstring: - // If the first token is a string, parse as extended asm. - if (! toklist) - { - s = parseExtAsm(stc); - statements->push(s); - continue; - } -#endif /* fall through */ default: @@ -5838,229 +5827,6 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc return s; } -#ifdef IN_GCC -/*********************************** - * Parse list of extended asm input or output operands. - * ExtAsmOperand: - * [Identifier] StringLiteral (Identifier), ... - */ -int Parser::parseExtAsmOperands(Expressions *args, Identifiers *names, Expressions *constraints) -{ - int numargs = 0; - - while (1) - { - Expression *arg = NULL; - Identifier *name = NULL; - Expression *constraint = NULL; - - switch (token.value) - { - case TOKsemicolon: - case TOKcolon: - case TOKeof: - return numargs; - - case TOKlbracket: - nextToken(); - if (token.value == TOKidentifier) - { - name = token.ident; - nextToken(); - } - else - { - error("expected identifier after '['"); - return numargs; - } - check(TOKrbracket); - // fall through - - default: - constraint = parsePrimaryExp(); - if (constraint->op != TOKstring) - { - error(constraint->loc, "expected constant string constraint for operand, not '%s'", constraint->toChars()); - goto Lerror; - } - arg = parseAssignExp(); - - args->push(arg); - names->push(name); - constraints->push(constraint); - numargs++; - - if (token.value == TOKcomma) - nextToken(); - break; - } - } -Lerror: - while (token.value != TOKrcurly && - token.value != TOKsemicolon && - token.value != TOKeof) - nextToken(); - - return numargs; -} - -/*********************************** - * Parse list of extended asm clobbers. - * ExtAsmClobbers: - * StringLiteral, ... - */ -Expressions *Parser::parseExtAsmClobbers() -{ - Expressions *clobbers = NULL; - - while (1) - { - Expression *clobber; - - switch (token.value) - { - case TOKsemicolon: - case TOKcolon: - case TOKeof: - return clobbers; - - case TOKstring: - clobber = parseAssignExp(); - if (!clobbers) - clobbers = new Expressions; - clobbers->push(clobber); - - if (token.value == TOKcomma) - nextToken(); - break; - - default: - error("expected constant string constraint for clobber name, not '%s'", token.toChars()); - goto Lerror; - } - } -Lerror: - while (token.value != TOKrcurly && - token.value != TOKsemicolon && - token.value != TOKeof) - nextToken(); - - return clobbers; -} - -/*********************************** - * Parse list of extended asm goto labels. - * ExtAsmGotoLabels: - * Identifier, ... - */ -Identifiers *Parser::parseExtAsmGotoLabels() -{ - Identifiers *labels = NULL; - - while (1) - { - switch (token.value) - { - case TOKsemicolon: - case TOKeof: - return labels; - - case TOKidentifier: - if (!labels) - labels = new Identifiers(); - labels->push(token.ident); - - if (nextToken() == TOKcomma) - nextToken(); - break; - - default: - error("expected identifier for goto label name, not '%s'", token.toChars()); - goto Lerror; - } - } -Lerror: - while (token.value != TOKrcurly && - token.value != TOKsemicolon && - token.value != TOKeof) - nextToken(); - - return labels; -} - -/*********************************** - * Parse an extended asm statement. - * ExtAsmStatement: - * asm { StringLiterals [ : InputOperands [ : OutputOperands [ : Clobbers [ : GotoLabels ] ] ] ] } - */ - -Statement *Parser::parseExtAsm(StorageClass stc) -{ - Expressions *args = NULL; - Identifiers *names = NULL; - Expressions *constraints = NULL; - int outputargs = 0; - Expressions *clobbers = NULL; - Identifiers *labels = NULL; - Loc loc = token.loc; - - Expression *insn = parseExpression(); - if (token.value == TOKsemicolon) - goto Ldone; - - for (int section = 0; section < 4; ++section) - { - check(TOKcolon); - - switch (section) - { - case 0: - if (!args) - { - args = new Expressions; - constraints = new Expressions; - names = new Identifiers; - } - outputargs = parseExtAsmOperands(args, names, constraints); - break; - - case 1: - parseExtAsmOperands(args, names, constraints); - break; - - case 2: - clobbers = parseExtAsmClobbers(); - break; - - case 3: - labels = parseExtAsmGotoLabels(); - break; - - default: - assert(0); - } - - switch (token.value) - { - case TOKsemicolon: - goto Ldone; - - case TOKeof: - error("matching '}' expected, not end of file"); - goto Ldone; - - default: - continue; - } - } - Ldone: - check(TOKsemicolon); - - return new ExtAsmStatement(loc, stc, insn, args, names, - constraints, outputargs, clobbers, labels); -} -#endif - void Parser::check(TOK value) { check(token.loc, value); diff --git a/gcc/d/dfrontend/parse.h b/gcc/d/dfrontend/parse.h index 5a2e64253..9403c0a20 100644 --- a/gcc/d/dfrontend/parse.h +++ b/gcc/d/dfrontend/parse.h @@ -128,12 +128,6 @@ class Parser : public Lexer void checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident); /** endPtr used for documented unittests */ Statement *parseStatement(int flags, const utf8_t** endPtr = NULL, Loc *pEndloc = NULL); -#ifdef IN_GCC - Statement *parseExtAsm(StorageClass stc); - int parseExtAsmOperands(Expressions *args, Identifiers *names, Expressions *constraints); - Expressions *parseExtAsmClobbers(); - Identifiers *parseExtAsmGotoLabels(); -#endif Initializer *parseInitializer(); Expression *parseDefaultInitExp(); void check(Loc loc, TOK value); diff --git a/gcc/d/dfrontend/statement.c b/gcc/d/dfrontend/statement.c index 886fc5a7c..02aa1af6c 100644 --- a/gcc/d/dfrontend/statement.c +++ b/gcc/d/dfrontend/statement.c @@ -192,9 +192,6 @@ bool Statement::comeFrom() void visit(DefaultStatement *) { stop = true; } void visit(LabelStatement *) { stop = true; } void visit(AsmStatement *) { stop = true; } -#ifdef IN_GCC - void visit(ExtAsmStatement *) { stop = true; } -#endif }; ComeFrom cf; @@ -1579,6 +1576,19 @@ AsmStatement::AsmStatement(Loc loc, Token *tokens) : Statement(loc) { this->tokens = tokens; +} + +Statement *AsmStatement::syntaxCopy() +{ + return new AsmStatement(loc, tokens); +} + + +/************************ InlineAsmStatement **********************************/ + +InlineAsmStatement::InlineAsmStatement(Loc loc, Token *tokens) + : AsmStatement(loc, tokens) +{ asmcode = NULL; asmalign = 0; refparam = false; @@ -1586,44 +1596,33 @@ AsmStatement::AsmStatement(Loc loc, Token *tokens) regs = 0; } -Statement *AsmStatement::syntaxCopy() +Statement *InlineAsmStatement::syntaxCopy() { - return new AsmStatement(loc, tokens); + return new InlineAsmStatement(loc, tokens); } -#ifdef IN_GCC -/************************ ExtAsmStatement ***************************************/ +/************************ GccAsmStatement ***************************************/ -ExtAsmStatement::ExtAsmStatement(Loc loc, StorageClass stc, Expression *insn, - Expressions *args, Identifiers *names, - Expressions *constraints, int outputargs, - Expressions *clobbers, Identifiers *labels) - : Statement(loc) +GccAsmStatement::GccAsmStatement(Loc loc, Token *tokens) + : AsmStatement(loc, tokens) { - this->stc = stc; - this->insn = insn; - this->args = args; - this->names = names; - this->constraints = constraints; - this->outputargs = outputargs; - this->clobbers = clobbers; - this->labels = labels; + this->stc = STCundefined; + this->insn = NULL; + this->args = NULL; + this->outputargs = 0; + this->names = NULL; + this->constraints = NULL; + this->clobbers = NULL; + this->labels = NULL; this->gotos = NULL; } -Statement *ExtAsmStatement::syntaxCopy() +Statement *GccAsmStatement::syntaxCopy() { - Expressions *c_args = Expression::arraySyntaxCopy(args); - Expressions *c_constraints = Expression::arraySyntaxCopy(constraints); - Expressions *c_clobbers = Expression::arraySyntaxCopy(clobbers); - - return new ExtAsmStatement(loc, stc, insn->syntaxCopy(), c_args, names, - c_constraints, outputargs, c_clobbers, labels); + return new GccAsmStatement(loc, tokens); } -#endif - /************************ CompoundAsmStatement ***************************************/ CompoundAsmStatement::CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc) diff --git a/gcc/d/dfrontend/statement.h b/gcc/d/dfrontend/statement.h index 02b4bd7ed..fb16cd39c 100644 --- a/gcc/d/dfrontend/statement.h +++ b/gcc/d/dfrontend/statement.h @@ -725,15 +725,42 @@ class AsmStatement : public Statement { public: Token *tokens; + + AsmStatement(Loc loc, Token *tokens); + Statement *syntaxCopy(); + void accept(Visitor *v) { v->visit(this); } +}; + +class InlineAsmStatement : public AsmStatement +{ +public: code *asmcode; unsigned asmalign; // alignment of this statement unsigned regs; // mask of registers modified (must match regm_t in back end) bool refparam; // true if function parameter is referenced bool naked; // true if function is to be naked - AsmStatement(Loc loc, Token *tokens); + InlineAsmStatement(Loc loc, Token *tokens); Statement *syntaxCopy(); + void accept(Visitor *v) { v->visit(this); } +}; +// A GCC asm statement - assembler instructions with D expression operands +class GccAsmStatement : public AsmStatement +{ +public: + StorageClass stc; // attributes of the asm {} block + Expression *insn; // string expression that is the template for assembler code + Expressions *args; // input and output operands of the statement + unsigned outputargs; // of the operands in 'args', the number of output operands + Identifiers *names; // list of symbolic names for the operands + Expressions *constraints; // list of string constants specifying constraints on operands + Expressions *clobbers; // list of string constants specifying clobbers and scratch registers + Identifiers *labels; // list of goto labels + GotoStatements *gotos; // of the goto labels, the equivalent statements they represent + + GccAsmStatement(Loc loc, Token *tokens); + Statement *syntaxCopy(); void accept(Visitor *v) { v->visit(this); } }; @@ -761,31 +788,4 @@ class ImportStatement : public Statement void accept(Visitor *v) { v->visit(this); } }; -#ifdef IN_GCC - -// Assembler instructions with D expression operands -class ExtAsmStatement : public Statement -{ -public: - StorageClass stc; - Expression *insn; - Expressions *args; - Identifiers *names; - Expressions *constraints; // Array of StringExp's - unsigned outputargs; - Expressions *clobbers; // Array of StringExp's - Identifiers *labels; - GotoStatements *gotos; - - ExtAsmStatement(Loc loc, StorageClass stc, Expression *insn, - Expressions *args, Identifiers *names, - Expressions *constraints, int outputargs, - Expressions *clobbers, Identifiers *labels); - Statement *syntaxCopy(); - - void accept(Visitor *v) { v->visit(this); } -}; - -#endif - #endif /* DMD_STATEMENT_H */ diff --git a/gcc/d/dfrontend/statementsem.c b/gcc/d/dfrontend/statementsem.c index e986dcdb1..0bc6b5db5 100644 --- a/gcc/d/dfrontend/statementsem.c +++ b/gcc/d/dfrontend/statementsem.c @@ -3453,72 +3453,12 @@ class StatementSemanticVisitor : public Visitor result = asmSemantic(s, sc); } -#ifdef IN_GCC - void visit(ExtAsmStatement *s) - { - // Fold the instruction template string. - s->insn = semantic(s->insn, sc); - s->insn->ctfeInterpret(); - - if (s->insn->op != TOKstring || ((StringExp *) s->insn)->sz != 1) - s->insn->error("instruction template must be a constant char string"); - - if (s->labels && s->outputargs) - s->error("extended asm statements with labels cannot have output constraints"); - - // Analyse all input and output operands. - if (s->args) - { - for (size_t i = 0; i < s->args->dim; i++) - { - Expression *e = (*s->args)[i]; - e = semantic(e, sc); - // Check argument is a valid lvalue/rvalue. - if (i < s->outputargs) - e = e->modifiableLvalue(sc, NULL); - else if (e->checkValue()) - e = new ErrorExp(); - (*s->args)[i] = e; - - e = (*s->constraints)[i]; - e = semantic(e, sc); - assert(e->op == TOKstring && ((StringExp *) e)->sz == 1); - (*s->constraints)[i] = e; - } - } - - // Analyse all clobbers. - if (s->clobbers) - { - for (size_t i = 0; i < s->clobbers->dim; i++) - { - Expression *e = (*s->clobbers)[i]; - e = semantic(e, sc); - assert(e->op == TOKstring && ((StringExp *) e)->sz == 1); - (*s->clobbers)[i] = e; - } - } - - // Analyse all goto labels. - if (s->labels) - { - for (size_t i = 0; i < s->labels->dim; i++) - { - Identifier *ident = (*s->labels)[i]; - GotoStatement *gs = new GotoStatement(s->loc, ident); - if (!s->gotos) - s->gotos = new GotoStatements(); - s->gotos->push(gs); - semantic(gs, sc); - } - } - - result = s; - } -#endif - void visit(CompoundAsmStatement *cas) { + // Apply postfix attributes of the asm block to each statement. + sc = sc->push(); + sc->stc |= cas->stc; + for (size_t i = 0; i < cas->statements->dim; i++) { Statement *s = (*cas->statements)[i]; @@ -3535,6 +3475,7 @@ class StatementSemanticVisitor : public Visitor if (!(cas->stc & (STCtrusted|STCsafe)) && sc->func->setUnsafe()) cas->error("asm statement is assumed to be @system - mark it with '@trusted' if it is not"); + sc->pop(); result = cas; } diff --git a/gcc/d/dfrontend/visitor.h b/gcc/d/dfrontend/visitor.h index 27371987b..37e20e6f1 100644 --- a/gcc/d/dfrontend/visitor.h +++ b/gcc/d/dfrontend/visitor.h @@ -54,9 +54,8 @@ class DebugStatement; class GotoStatement; class LabelStatement; class AsmStatement; -#ifdef IN_GCC -class ExtAsmStatement; -#endif +class InlineAsmStatement; +class GccAsmStatement; class CompoundAsmStatement; class ImportStatement; @@ -346,9 +345,8 @@ class Visitor virtual void visit(GotoStatement *s) { visit((Statement *)s); } virtual void visit(LabelStatement *s) { visit((Statement *)s); } virtual void visit(AsmStatement *s) { visit((Statement *)s); } -#ifdef IN_GCC - virtual void visit(ExtAsmStatement *s) { visit((Statement *)s); } -#endif + virtual void visit(InlineAsmStatement *s) { visit((AsmStatement *)s); } + virtual void visit(GccAsmStatement *s) { visit((AsmStatement *)s); } virtual void visit(CompoundAsmStatement *s) { visit((CompoundStatement *)s); } virtual void visit(ImportStatement *s) { visit((Statement *)s); } diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc index 197588155..6fa1c38c1 100644 --- a/gcc/d/toir.cc +++ b/gcc/d/toir.cc @@ -1254,7 +1254,7 @@ class IRVisitor : public Visitor /* D Inline Assembler is not implemented, as would require a writing an assembly parser for each supported target. Instead we leverage - GCC extended assembler using the ExtAsmStatement class. */ + GCC extended assembler using the GccAsmStatement class. */ void visit (AsmStatement *) { @@ -1264,7 +1264,7 @@ class IRVisitor : public Visitor /* Build a GCC extended assembler expression, whose components are an INSN string, some OUTPUTS, some INPUTS, and some CLOBBERS. */ - void visit (ExtAsmStatement *s) + void visit (GccAsmStatement *s) { StringExp *insn = (StringExp *)s->insn; tree outputs = NULL_TREE; From c15cf439dda9dc5bc39537a153e2ec1a01a13612 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 27 Aug 2018 08:23:54 +0200 Subject: [PATCH 06/10] Update to gcc-9-20180826 --- gcc.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc.version b/gcc.version index 662fc3d68..d31312091 100644 --- a/gcc.version +++ b/gcc.version @@ -1 +1 @@ -gcc-9-20180819 +gcc-9-20180826 From 7b2e6a51ff26d30a1520fafff14af893bf6a543d Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 29 Aug 2018 13:19:07 +0200 Subject: [PATCH 07/10] Refresh GCC patches against 9-20180826 --- gcc/d/patches/patch-gcc-9.patch | 26 +++++++++++++------------- gcc/d/patches/patch-targetdm-9.patch | 18 +++++++++--------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/gcc/d/patches/patch-gcc-9.patch b/gcc/d/patches/patch-gcc-9.patch index f8e3f8ebd..270555de1 100644 --- a/gcc/d/patches/patch-gcc-9.patch +++ b/gcc/d/patches/patch-gcc-9.patch @@ -4,7 +4,7 @@ relevant documentation about the GDC front end. --- a/gcc/config/powerpcspe/powerpcspe.c +++ b/gcc/config/powerpcspe/powerpcspe.c -@@ -32025,11 +32025,12 @@ rs6000_output_function_epilogue (FILE *f +@@ -32026,11 +32026,12 @@ rs6000_output_function_epilogue (FILE *f use language_string. C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. Java is 13. Objective-C is 14. Objective-C++ isn't assigned @@ -21,7 +21,7 @@ relevant documentation about the GDC front end. else if (! strcmp (language_string, "GNU F77") --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c -@@ -28146,11 +28146,12 @@ rs6000_output_function_epilogue (FILE *f +@@ -28333,11 +28333,12 @@ rs6000_output_function_epilogue (FILE *f use language_string. C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. Java is 13. Objective-C is 14. Objective-C++ isn't assigned @@ -93,7 +93,7 @@ relevant documentation about the GDC front end. in the @file{gcc} subdirectory of the object directory. You can also --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi -@@ -1424,6 +1424,15 @@ Go source code. +@@ -1438,6 +1438,15 @@ Go source code. @item @var{file}.brig BRIG files (binary representation of HSAIL). @@ -109,7 +109,7 @@ relevant documentation about the GDC front end. @item @var{file}.ads Ada source code file that contains a library unit declaration (a declaration of a package, subprogram, or generic, or a generic -@@ -1470,6 +1479,7 @@ objective-c objective-c-header objecti +@@ -1484,6 +1493,7 @@ objective-c objective-c-header objecti objective-c++ objective-c++-header objective-c++-cpp-output assembler assembler-with-cpp ada @@ -147,7 +147,7 @@ relevant documentation about the GDC front end. @xref{Top, GNAT Reference Manual, About This Guide, gnat_rm, --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c -@@ -5498,6 +5498,16 @@ is_ada (void) +@@ -5506,6 +5506,16 @@ is_ada (void) return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83; } @@ -164,7 +164,7 @@ relevant documentation about the GDC front end. /* Remove the specified attribute if present. Return TRUE if removal was successful. */ -@@ -24438,6 +24448,8 @@ gen_compile_unit_die (const char *filena +@@ -24472,6 +24482,8 @@ gen_compile_unit_die (const char *filena language = DW_LANG_ObjC; else if (strcmp (language_string, "GNU Objective-C++") == 0) language = DW_LANG_ObjC_plus_plus; @@ -173,7 +173,7 @@ relevant documentation about the GDC front end. else if (dwarf_version >= 5 || !dwarf_strict) { if (strcmp (language_string, "GNU Go") == 0) -@@ -26038,7 +26050,7 @@ declare_in_namespace (tree thing, dw_die +@@ -26072,7 +26084,7 @@ declare_in_namespace (tree thing, dw_die if (ns_context != context_die) { @@ -182,7 +182,7 @@ relevant documentation about the GDC front end. return ns_context; if (DECL_P (thing)) gen_decl_die (thing, NULL, NULL, ns_context); -@@ -26061,7 +26073,7 @@ gen_namespace_die (tree decl, dw_die_ref +@@ -26095,7 +26107,7 @@ gen_namespace_die (tree decl, dw_die_ref { /* Output a real namespace or module. */ context_die = setup_namespace_context (decl, comp_unit_die ()); @@ -191,7 +191,7 @@ relevant documentation about the GDC front end. ? DW_TAG_module : DW_TAG_namespace, context_die, decl); /* For Fortran modules defined in different CU don't add src coords. */ -@@ -26127,7 +26139,7 @@ gen_decl_die (tree decl, tree origin, st +@@ -26161,7 +26173,7 @@ gen_decl_die (tree decl, tree origin, st break; case CONST_DECL: @@ -200,7 +200,7 @@ relevant documentation about the GDC front end. { /* The individual enumerators of an enum type get output when we output the Dwarf representation of the relevant enum type itself. */ -@@ -26727,7 +26739,7 @@ dwarf2out_decl (tree decl) +@@ -26761,7 +26773,7 @@ dwarf2out_decl (tree decl) case CONST_DECL: if (debug_info_level <= DINFO_LEVEL_TERSE) return; @@ -209,7 +209,7 @@ relevant documentation about the GDC front end. return; if (TREE_STATIC (decl) && decl_function_context (decl)) context_die = lookup_decl_die (DECL_CONTEXT (decl)); -@@ -29122,6 +29134,7 @@ prune_unused_types_walk_local_classes (d +@@ -29162,6 +29174,7 @@ prune_unused_types_walk_local_classes (d case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: @@ -217,7 +217,7 @@ relevant documentation about the GDC front end. break; case DW_TAG_subprogram: -@@ -29155,6 +29168,7 @@ prune_unused_types_walk (dw_die_ref die) +@@ -29195,6 +29208,7 @@ prune_unused_types_walk (dw_die_ref die) case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: @@ -225,7 +225,7 @@ relevant documentation about the GDC front end. if (die->die_perennial_p) break; -@@ -29181,7 +29195,6 @@ prune_unused_types_walk (dw_die_ref die) +@@ -29221,7 +29235,6 @@ prune_unused_types_walk (dw_die_ref die) case DW_TAG_volatile_type: case DW_TAG_typedef: case DW_TAG_array_type: diff --git a/gcc/d/patches/patch-targetdm-9.patch b/gcc/d/patches/patch-targetdm-9.patch index f64337c3d..9589d18b2 100644 --- a/gcc/d/patches/patch-targetdm-9.patch +++ b/gcc/d/patches/patch-targetdm-9.patch @@ -82,7 +82,7 @@ The following OS versions are implemented: MACHMODE_H = machmode.h mode-classes.def HOOKS_H = hooks.h HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H) -@@ -1188,6 +1193,9 @@ C_TARGET_OBJS=@c_target_objs@ +@@ -1187,6 +1192,9 @@ C_TARGET_OBJS=@c_target_objs@ # Target specific, C++ specific object file CXX_TARGET_OBJS=@cxx_target_objs@ @@ -225,7 +225,7 @@ The following OS versions are implemented: c_target_objs="aarch64-c.o" cxx_target_objs="aarch64-c.o" + d_target_objs="aarch64-d.o" - extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o" + extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o aarch64-speculation.o" target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c" target_has_targetm_common=yes ;; @@ -308,7 +308,7 @@ The following OS versions are implemented: ;; *-*-netbsd*) tm_p_file="${tm_p_file} netbsd-protos.h" -@@ -3203,6 +3227,10 @@ if [ "$common_out_file" = "" ]; then +@@ -3231,6 +3255,10 @@ if [ "$common_out_file" = "" ]; then fi fi @@ -319,7 +319,7 @@ The following OS versions are implemented: # Support for --with-cpu and related options (and a few unrelated options, # too). case ${with_cpu} in -@@ -4813,6 +4841,7 @@ case ${target} in +@@ -4845,6 +4873,7 @@ case ${target} in out_file="${cpu_type}/${cpu_type}.c" c_target_objs="${c_target_objs} ${cpu_type}-c.o" cxx_target_objs="${cxx_target_objs} ${cpu_type}-c.o" @@ -381,9 +381,9 @@ The following OS versions are implemented: +/* Defined in aarch64-d.c */ +extern void aarch64_d_target_versions (void); + - rtl_opt_pass *make_pass_fma_steering (gcc::context *ctxt); + rtl_opt_pass *make_pass_fma_steering (gcc::context *); + rtl_opt_pass *make_pass_track_speculation (gcc::context *); - poly_uint64 aarch64_regmode_natural_size (machine_mode); --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -26,6 +26,9 @@ @@ -565,7 +565,7 @@ The following OS versions are implemented: +} --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h -@@ -373,6 +373,9 @@ extern void arm_lang_object_attributes_i +@@ -375,6 +375,9 @@ extern void arm_lang_object_attributes_i extern void arm_register_target_pragmas (void); extern void arm_cpu_cpp_builtins (struct cpp_reader *); @@ -1300,7 +1300,7 @@ The following OS versions are implemented: +extern void s390_d_target_versions (void); --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h -@@ -194,6 +194,9 @@ enum processor_flags +@@ -200,6 +200,9 @@ enum processor_flags /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() s390_cpu_cpp_builtins (pfile) @@ -1309,7 +1309,7 @@ The following OS versions are implemented: + #ifdef DEFAULT_TARGET_64BIT #define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP \ - | MASK_OPT_HTM | MASK_OPT_VX) + | MASK_OPT_HTM | MASK_OPT_VX) --- a/gcc/config/s390/t-s390 +++ b/gcc/config/s390/t-s390 @@ -25,3 +25,7 @@ s390-c.o: $(srcdir)/config/s390/s390-c.c From fe63ab35706beee47c57e7b253ba8287803a657d Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 29 Aug 2018 13:20:59 +0200 Subject: [PATCH 08/10] fix Bug 303: libgphobos.spec not found linking stage2 --- gcc/d/patches/patch-toplev-9.patch | 108 +++++++++++++++-------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/gcc/d/patches/patch-toplev-9.patch b/gcc/d/patches/patch-toplev-9.patch index 55d9d8095..b57a069da 100644 --- a/gcc/d/patches/patch-toplev-9.patch +++ b/gcc/d/patches/patch-toplev-9.patch @@ -78,20 +78,22 @@ This implements building of libphobos library in GCC. AR="$(AR)"; export AR; \ AS="$(AS)"; export AS; \ CC_FOR_BUILD="$(CC_FOR_BUILD)"; export CC_FOR_BUILD; \ -@@ -256,6 +259,12 @@ POSTSTAGE1_HOST_EXPORTS = \ +@@ -256,6 +259,14 @@ POSTSTAGE1_HOST_EXPORTS = \ CC_FOR_BUILD="$$CC"; export CC_FOR_BUILD; \ $(POSTSTAGE1_CXX_EXPORT) \ $(LTO_EXPORTS) \ + GDC="$$r/$(HOST_SUBDIR)/prev-gcc/gdc$(exeext) -B$$r/$(HOST_SUBDIR)/prev-gcc/ \ + -B$(build_tooldir)/bin/ $(GDC_FLAGS_FOR_TARGET) \ ++ -B$$r/prev-$(TARGET_SUBDIR)/libphobos/src \ + -I$$r/prev-$(TARGET_SUBDIR)/libphobos/libdruntime -I$$s/libphobos/libdruntime \ -+ -L$$r/prev-$(TARGET_SUBDIR)/libphobos/src/.libs"; \ ++ -L$$r/prev-$(TARGET_SUBDIR)/libphobos/src/.libs \ ++ -L$$r/prev-$(TARGET_SUBDIR)/libphobos/libdruntime/.libs"; \ + export GDC; \ + GDC_FOR_BUILD="$$GDC"; export GDC_FOR_BUILD; \ GNATBIND="$$r/$(HOST_SUBDIR)/prev-gcc/gnatbind"; export GNATBIND; \ LDFLAGS="$(POSTSTAGE1_LDFLAGS) $(BOOT_LDFLAGS)"; export LDFLAGS; \ HOST_LIBS="$(POSTSTAGE1_LIBS)"; export HOST_LIBS; -@@ -278,6 +287,7 @@ BASE_TARGET_EXPORTS = \ +@@ -278,6 +289,7 @@ BASE_TARGET_EXPORTS = \ CXXFLAGS="$(CXXFLAGS_FOR_TARGET)"; export CXXFLAGS; \ GFORTRAN="$(GFORTRAN_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GFORTRAN; \ GOC="$(GOC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GOC; \ @@ -99,7 +101,7 @@ This implements building of libphobos library in GCC. DLLTOOL="$(DLLTOOL_FOR_TARGET)"; export DLLTOOL; \ LD="$(COMPILER_LD_FOR_TARGET)"; export LD; \ LDFLAGS="$(LDFLAGS_FOR_TARGET)"; export LDFLAGS; \ -@@ -342,6 +352,7 @@ CXX_FOR_BUILD = @CXX_FOR_BUILD@ +@@ -342,6 +354,7 @@ CXX_FOR_BUILD = @CXX_FOR_BUILD@ DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@ GFORTRAN_FOR_BUILD = @GFORTRAN_FOR_BUILD@ GOC_FOR_BUILD = @GOC_FOR_BUILD@ @@ -107,7 +109,7 @@ This implements building of libphobos library in GCC. LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ LD_FOR_BUILD = @LD_FOR_BUILD@ NM_FOR_BUILD = @NM_FOR_BUILD@ -@@ -399,6 +410,7 @@ STRIP = @STRIP@ +@@ -399,6 +412,7 @@ STRIP = @STRIP@ WINDRES = @WINDRES@ WINDMC = @WINDMC@ @@ -115,7 +117,7 @@ This implements building of libphobos library in GCC. GNATBIND = @GNATBIND@ GNATMAKE = @GNATMAKE@ -@@ -408,6 +420,7 @@ LIBCFLAGS = $(CFLAGS) +@@ -408,6 +422,7 @@ LIBCFLAGS = $(CFLAGS) CXXFLAGS = @CXXFLAGS@ LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates GOCFLAGS = $(CFLAGS) @@ -123,7 +125,7 @@ This implements building of libphobos library in GCC. CREATE_GCOV = create_gcov -@@ -574,6 +587,7 @@ CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @CXX_ +@@ -574,6 +589,7 @@ CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @CXX_ RAW_CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @RAW_CXX_FOR_TARGET@ GFORTRAN_FOR_TARGET=$(STAGE_CC_WRAPPER) @GFORTRAN_FOR_TARGET@ GOC_FOR_TARGET=$(STAGE_CC_WRAPPER) @GOC_FOR_TARGET@ @@ -131,7 +133,7 @@ This implements building of libphobos library in GCC. DLLTOOL_FOR_TARGET=@DLLTOOL_FOR_TARGET@ LD_FOR_TARGET=@LD_FOR_TARGET@ -@@ -598,6 +612,7 @@ LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARG +@@ -598,6 +614,7 @@ LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARG LIBCXXFLAGS_FOR_TARGET = $(CXXFLAGS_FOR_TARGET) -fno-implicit-templates LDFLAGS_FOR_TARGET = @LDFLAGS_FOR_TARGET@ GOCFLAGS_FOR_TARGET = -O2 -g @@ -139,7 +141,7 @@ This implements building of libphobos library in GCC. FLAGS_FOR_TARGET = @FLAGS_FOR_TARGET@ SYSROOT_CFLAGS_FOR_TARGET = @SYSROOT_CFLAGS_FOR_TARGET@ -@@ -622,7 +637,7 @@ all: +@@ -622,7 +639,7 @@ all: # This is the list of directories that may be needed in RPATH_ENVVAR # so that programs built for the target machine work. @@ -148,7 +150,7 @@ This implements building of libphobos library in GCC. @if target-libstdc++-v3 TARGET_LIB_PATH_libstdc++-v3 = $$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs: -@@ -644,6 +659,10 @@ TARGET_LIB_PATH_liboffloadmic = $$r/$(TA +@@ -644,6 +661,10 @@ TARGET_LIB_PATH_liboffloadmic = $$r/$(TA TARGET_LIB_PATH_libssp = $$r/$(TARGET_SUBDIR)/libssp/.libs: @endif target-libssp @@ -159,7 +161,7 @@ This implements building of libphobos library in GCC. @if target-libgomp TARGET_LIB_PATH_libgomp = $$r/$(TARGET_SUBDIR)/libgomp/.libs: @endif target-libgomp -@@ -778,6 +797,8 @@ BASE_FLAGS_TO_PASS = \ +@@ -778,6 +799,8 @@ BASE_FLAGS_TO_PASS = \ "STAGE1_LANGUAGES=$(STAGE1_LANGUAGES)" \ "GNATBIND=$(GNATBIND)" \ "GNATMAKE=$(GNATMAKE)" \ @@ -168,7 +170,7 @@ This implements building of libphobos library in GCC. "AR_FOR_TARGET=$(AR_FOR_TARGET)" \ "AS_FOR_TARGET=$(AS_FOR_TARGET)" \ "CC_FOR_TARGET=$(CC_FOR_TARGET)" \ -@@ -789,6 +810,8 @@ BASE_FLAGS_TO_PASS = \ +@@ -789,6 +812,8 @@ BASE_FLAGS_TO_PASS = \ "GFORTRAN_FOR_TARGET=$(GFORTRAN_FOR_TARGET)" \ "GOC_FOR_TARGET=$(GOC_FOR_TARGET)" \ "GOCFLAGS_FOR_TARGET=$(GOCFLAGS_FOR_TARGET)" \ @@ -177,7 +179,7 @@ This implements building of libphobos library in GCC. "LD_FOR_TARGET=$(LD_FOR_TARGET)" \ "LIPO_FOR_TARGET=$(LIPO_FOR_TARGET)" \ "LDFLAGS_FOR_TARGET=$(LDFLAGS_FOR_TARGET)" \ -@@ -851,6 +874,7 @@ EXTRA_HOST_FLAGS = \ +@@ -851,6 +876,7 @@ EXTRA_HOST_FLAGS = \ 'DLLTOOL=$(DLLTOOL)' \ 'GFORTRAN=$(GFORTRAN)' \ 'GOC=$(GOC)' \ @@ -185,7 +187,7 @@ This implements building of libphobos library in GCC. 'LD=$(LD)' \ 'LIPO=$(LIPO)' \ 'NM=$(NM)' \ -@@ -875,6 +899,7 @@ STAGE1_FLAGS_TO_PASS = \ +@@ -875,6 +901,7 @@ STAGE1_FLAGS_TO_PASS = \ POSTSTAGE1_FLAGS_TO_PASS = \ CC="$${CC}" CC_FOR_BUILD="$${CC_FOR_BUILD}" \ CXX="$${CXX}" CXX_FOR_BUILD="$${CXX_FOR_BUILD}" \ @@ -193,7 +195,7 @@ This implements building of libphobos library in GCC. GNATBIND="$${GNATBIND}" \ LDFLAGS="$${LDFLAGS}" \ HOST_LIBS="$${HOST_LIBS}" \ -@@ -907,6 +932,8 @@ EXTRA_TARGET_FLAGS = \ +@@ -907,6 +934,8 @@ EXTRA_TARGET_FLAGS = \ 'GFORTRAN=$$(GFORTRAN_FOR_TARGET) $$(XGCC_FLAGS_FOR_TARGET) $$(TFLAGS)' \ 'GOC=$$(GOC_FOR_TARGET) $$(XGCC_FLAGS_FOR_TARGET) $$(TFLAGS)' \ 'GOCFLAGS=$$(GOCFLAGS_FOR_TARGET)' \ @@ -202,7 +204,7 @@ This implements building of libphobos library in GCC. 'LD=$(COMPILER_LD_FOR_TARGET)' \ 'LDFLAGS=$$(LDFLAGS_FOR_TARGET)' \ 'LIBCFLAGS=$$(LIBCFLAGS_FOR_TARGET)' \ -@@ -1008,6 +1035,7 @@ configure-target: \ +@@ -1008,6 +1037,7 @@ configure-target: \ maybe-configure-target-libobjc \ maybe-configure-target-libgo \ maybe-configure-target-libhsail-rt \ @@ -210,7 +212,7 @@ This implements building of libphobos library in GCC. maybe-configure-target-libtermcap \ maybe-configure-target-winsup \ maybe-configure-target-libgloss \ -@@ -1170,6 +1198,7 @@ all-target: maybe-all-target-libgfortran +@@ -1170,6 +1200,7 @@ all-target: maybe-all-target-libgfortran all-target: maybe-all-target-libobjc all-target: maybe-all-target-libgo all-target: maybe-all-target-libhsail-rt @@ -218,7 +220,7 @@ This implements building of libphobos library in GCC. all-target: maybe-all-target-libtermcap all-target: maybe-all-target-winsup all-target: maybe-all-target-libgloss -@@ -1261,6 +1290,7 @@ info-target: maybe-info-target-libgfortr +@@ -1261,6 +1292,7 @@ info-target: maybe-info-target-libgfortr info-target: maybe-info-target-libobjc info-target: maybe-info-target-libgo info-target: maybe-info-target-libhsail-rt @@ -226,7 +228,7 @@ This implements building of libphobos library in GCC. info-target: maybe-info-target-libtermcap info-target: maybe-info-target-winsup info-target: maybe-info-target-libgloss -@@ -1345,6 +1375,7 @@ dvi-target: maybe-dvi-target-libgfortran +@@ -1345,6 +1377,7 @@ dvi-target: maybe-dvi-target-libgfortran dvi-target: maybe-dvi-target-libobjc dvi-target: maybe-dvi-target-libgo dvi-target: maybe-dvi-target-libhsail-rt @@ -234,7 +236,7 @@ This implements building of libphobos library in GCC. dvi-target: maybe-dvi-target-libtermcap dvi-target: maybe-dvi-target-winsup dvi-target: maybe-dvi-target-libgloss -@@ -1429,6 +1460,7 @@ pdf-target: maybe-pdf-target-libgfortran +@@ -1429,6 +1462,7 @@ pdf-target: maybe-pdf-target-libgfortran pdf-target: maybe-pdf-target-libobjc pdf-target: maybe-pdf-target-libgo pdf-target: maybe-pdf-target-libhsail-rt @@ -242,7 +244,7 @@ This implements building of libphobos library in GCC. pdf-target: maybe-pdf-target-libtermcap pdf-target: maybe-pdf-target-winsup pdf-target: maybe-pdf-target-libgloss -@@ -1513,6 +1545,7 @@ html-target: maybe-html-target-libgfortr +@@ -1513,6 +1547,7 @@ html-target: maybe-html-target-libgfortr html-target: maybe-html-target-libobjc html-target: maybe-html-target-libgo html-target: maybe-html-target-libhsail-rt @@ -250,7 +252,7 @@ This implements building of libphobos library in GCC. html-target: maybe-html-target-libtermcap html-target: maybe-html-target-winsup html-target: maybe-html-target-libgloss -@@ -1597,6 +1630,7 @@ TAGS-target: maybe-TAGS-target-libgfortr +@@ -1597,6 +1632,7 @@ TAGS-target: maybe-TAGS-target-libgfortr TAGS-target: maybe-TAGS-target-libobjc TAGS-target: maybe-TAGS-target-libgo TAGS-target: maybe-TAGS-target-libhsail-rt @@ -258,7 +260,7 @@ This implements building of libphobos library in GCC. TAGS-target: maybe-TAGS-target-libtermcap TAGS-target: maybe-TAGS-target-winsup TAGS-target: maybe-TAGS-target-libgloss -@@ -1681,6 +1715,7 @@ install-info-target: maybe-install-info- +@@ -1681,6 +1717,7 @@ install-info-target: maybe-install-info- install-info-target: maybe-install-info-target-libobjc install-info-target: maybe-install-info-target-libgo install-info-target: maybe-install-info-target-libhsail-rt @@ -266,7 +268,7 @@ This implements building of libphobos library in GCC. install-info-target: maybe-install-info-target-libtermcap install-info-target: maybe-install-info-target-winsup install-info-target: maybe-install-info-target-libgloss -@@ -1765,6 +1800,7 @@ install-pdf-target: maybe-install-pdf-ta +@@ -1765,6 +1802,7 @@ install-pdf-target: maybe-install-pdf-ta install-pdf-target: maybe-install-pdf-target-libobjc install-pdf-target: maybe-install-pdf-target-libgo install-pdf-target: maybe-install-pdf-target-libhsail-rt @@ -274,7 +276,7 @@ This implements building of libphobos library in GCC. install-pdf-target: maybe-install-pdf-target-libtermcap install-pdf-target: maybe-install-pdf-target-winsup install-pdf-target: maybe-install-pdf-target-libgloss -@@ -1849,6 +1885,7 @@ install-html-target: maybe-install-html- +@@ -1849,6 +1887,7 @@ install-html-target: maybe-install-html- install-html-target: maybe-install-html-target-libobjc install-html-target: maybe-install-html-target-libgo install-html-target: maybe-install-html-target-libhsail-rt @@ -282,7 +284,7 @@ This implements building of libphobos library in GCC. install-html-target: maybe-install-html-target-libtermcap install-html-target: maybe-install-html-target-winsup install-html-target: maybe-install-html-target-libgloss -@@ -1933,6 +1970,7 @@ installcheck-target: maybe-installcheck- +@@ -1933,6 +1972,7 @@ installcheck-target: maybe-installcheck- installcheck-target: maybe-installcheck-target-libobjc installcheck-target: maybe-installcheck-target-libgo installcheck-target: maybe-installcheck-target-libhsail-rt @@ -290,7 +292,7 @@ This implements building of libphobos library in GCC. installcheck-target: maybe-installcheck-target-libtermcap installcheck-target: maybe-installcheck-target-winsup installcheck-target: maybe-installcheck-target-libgloss -@@ -2017,6 +2055,7 @@ mostlyclean-target: maybe-mostlyclean-ta +@@ -2017,6 +2057,7 @@ mostlyclean-target: maybe-mostlyclean-ta mostlyclean-target: maybe-mostlyclean-target-libobjc mostlyclean-target: maybe-mostlyclean-target-libgo mostlyclean-target: maybe-mostlyclean-target-libhsail-rt @@ -298,7 +300,7 @@ This implements building of libphobos library in GCC. mostlyclean-target: maybe-mostlyclean-target-libtermcap mostlyclean-target: maybe-mostlyclean-target-winsup mostlyclean-target: maybe-mostlyclean-target-libgloss -@@ -2101,6 +2140,7 @@ clean-target: maybe-clean-target-libgfor +@@ -2101,6 +2142,7 @@ clean-target: maybe-clean-target-libgfor clean-target: maybe-clean-target-libobjc clean-target: maybe-clean-target-libgo clean-target: maybe-clean-target-libhsail-rt @@ -306,7 +308,7 @@ This implements building of libphobos library in GCC. clean-target: maybe-clean-target-libtermcap clean-target: maybe-clean-target-winsup clean-target: maybe-clean-target-libgloss -@@ -2185,6 +2225,7 @@ distclean-target: maybe-distclean-target +@@ -2185,6 +2227,7 @@ distclean-target: maybe-distclean-target distclean-target: maybe-distclean-target-libobjc distclean-target: maybe-distclean-target-libgo distclean-target: maybe-distclean-target-libhsail-rt @@ -314,7 +316,7 @@ This implements building of libphobos library in GCC. distclean-target: maybe-distclean-target-libtermcap distclean-target: maybe-distclean-target-winsup distclean-target: maybe-distclean-target-libgloss -@@ -2269,6 +2310,7 @@ maintainer-clean-target: maybe-maintaine +@@ -2269,6 +2312,7 @@ maintainer-clean-target: maybe-maintaine maintainer-clean-target: maybe-maintainer-clean-target-libobjc maintainer-clean-target: maybe-maintainer-clean-target-libgo maintainer-clean-target: maybe-maintainer-clean-target-libhsail-rt @@ -322,7 +324,7 @@ This implements building of libphobos library in GCC. maintainer-clean-target: maybe-maintainer-clean-target-libtermcap maintainer-clean-target: maybe-maintainer-clean-target-winsup maintainer-clean-target: maybe-maintainer-clean-target-libgloss -@@ -2409,6 +2451,7 @@ check-target: \ +@@ -2409,6 +2453,7 @@ check-target: \ maybe-check-target-libobjc \ maybe-check-target-libgo \ maybe-check-target-libhsail-rt \ @@ -330,7 +332,7 @@ This implements building of libphobos library in GCC. maybe-check-target-libtermcap \ maybe-check-target-winsup \ maybe-check-target-libgloss \ -@@ -2589,6 +2632,7 @@ install-target: \ +@@ -2589,6 +2634,7 @@ install-target: \ maybe-install-target-libobjc \ maybe-install-target-libgo \ maybe-install-target-libhsail-rt \ @@ -338,7 +340,7 @@ This implements building of libphobos library in GCC. maybe-install-target-libtermcap \ maybe-install-target-winsup \ maybe-install-target-libgloss \ -@@ -2693,6 +2737,7 @@ install-strip-target: \ +@@ -2693,6 +2739,7 @@ install-strip-target: \ maybe-install-strip-target-libobjc \ maybe-install-strip-target-libgo \ maybe-install-strip-target-libhsail-rt \ @@ -346,7 +348,7 @@ This implements building of libphobos library in GCC. maybe-install-strip-target-libtermcap \ maybe-install-strip-target-winsup \ maybe-install-strip-target-libgloss \ -@@ -46944,6 +46989,464 @@ maintainer-clean-target-libhsail-rt: +@@ -46944,6 +46991,464 @@ maintainer-clean-target-libhsail-rt: @@ -811,7 +813,7 @@ This implements building of libphobos library in GCC. .PHONY: configure-target-libtermcap maybe-configure-target-libtermcap maybe-configure-target-libtermcap: @if gcc-bootstrap -@@ -52329,6 +52832,14 @@ check-gcc-brig: +@@ -52329,6 +52834,14 @@ check-gcc-brig: (cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-brig); check-brig: check-gcc-brig check-target-libhsail-rt @@ -826,7 +828,7 @@ This implements building of libphobos library in GCC. # The gcc part of install-no-fixedincludes, which relies on an intimate # knowledge of how a number of gcc internal targets (inter)operate. Delegate. -@@ -55521,6 +56032,7 @@ configure-target-libgfortran: stage_last +@@ -55521,6 +56034,7 @@ configure-target-libgfortran: stage_last configure-target-libobjc: stage_last configure-target-libgo: stage_last configure-target-libhsail-rt: stage_last @@ -834,7 +836,7 @@ This implements building of libphobos library in GCC. configure-target-libtermcap: stage_last configure-target-winsup: stage_last configure-target-libgloss: stage_last -@@ -55555,6 +56067,7 @@ configure-target-libgfortran: maybe-all- +@@ -55555,6 +56069,7 @@ configure-target-libgfortran: maybe-all- configure-target-libobjc: maybe-all-gcc configure-target-libgo: maybe-all-gcc configure-target-libhsail-rt: maybe-all-gcc @@ -842,7 +844,7 @@ This implements building of libphobos library in GCC. configure-target-libtermcap: maybe-all-gcc configure-target-winsup: maybe-all-gcc configure-target-libgloss: maybe-all-gcc -@@ -56550,6 +57063,11 @@ configure-target-libgo: maybe-configure- +@@ -56550,6 +57065,11 @@ configure-target-libgo: maybe-configure- all-target-libgo: maybe-all-target-libbacktrace all-target-libgo: maybe-all-target-libffi all-target-libgo: maybe-all-target-libatomic @@ -854,7 +856,7 @@ This implements building of libphobos library in GCC. configure-target-libstdc++-v3: maybe-configure-target-libgomp configure-stage1-target-libstdc++-v3: maybe-configure-stage1-target-libgomp configure-stage2-target-libstdc++-v3: maybe-configure-stage2-target-libgomp -@@ -56593,6 +57111,7 @@ all-stageautofeedback-target-libstdc++-v +@@ -56593,6 +57113,7 @@ all-stageautofeedback-target-libstdc++-v install-target-libgo: maybe-install-target-libatomic install-target-libgfortran: maybe-install-target-libquadmath install-target-libgfortran: maybe-install-target-libgcc @@ -862,7 +864,7 @@ This implements building of libphobos library in GCC. install-target-libsanitizer: maybe-install-target-libstdc++-v3 install-target-libsanitizer: maybe-install-target-libgcc install-target-libvtv: maybe-install-target-libstdc++-v3 -@@ -56717,6 +57236,7 @@ configure-target-libgfortran: maybe-all- +@@ -56717,6 +57238,7 @@ configure-target-libgfortran: maybe-all- configure-target-libobjc: maybe-all-target-libgcc configure-target-libgo: maybe-all-target-libgcc configure-target-libhsail-rt: maybe-all-target-libgcc @@ -870,7 +872,7 @@ This implements building of libphobos library in GCC. configure-target-libtermcap: maybe-all-target-libgcc configure-target-winsup: maybe-all-target-libgcc configure-target-libgloss: maybe-all-target-libgcc -@@ -56755,6 +57275,8 @@ configure-target-libgo: maybe-all-target +@@ -56755,6 +57277,8 @@ configure-target-libgo: maybe-all-target configure-target-libhsail-rt: maybe-all-target-newlib maybe-all-target-libgloss @@ -898,20 +900,22 @@ This implements building of libphobos library in GCC. AR="$(AR)"; export AR; \ AS="$(AS)"; export AS; \ CC_FOR_BUILD="$(CC_FOR_BUILD)"; export CC_FOR_BUILD; \ -@@ -259,6 +262,12 @@ POSTSTAGE1_HOST_EXPORTS = \ +@@ -259,6 +262,14 @@ POSTSTAGE1_HOST_EXPORTS = \ CC_FOR_BUILD="$$CC"; export CC_FOR_BUILD; \ $(POSTSTAGE1_CXX_EXPORT) \ $(LTO_EXPORTS) \ + GDC="$$r/$(HOST_SUBDIR)/prev-gcc/gdc$(exeext) -B$$r/$(HOST_SUBDIR)/prev-gcc/ \ + -B$(build_tooldir)/bin/ $(GDC_FLAGS_FOR_TARGET) \ ++ -B$$r/prev-$(TARGET_SUBDIR)/libphobos/src \ + -I$$r/prev-$(TARGET_SUBDIR)/libphobos/libdruntime -I$$s/libphobos/libdruntime \ -+ -L$$r/prev-$(TARGET_SUBDIR)/libphobos/src/.libs"; \ ++ -L$$r/prev-$(TARGET_SUBDIR)/libphobos/src/.libs \ ++ -L$$r/prev-$(TARGET_SUBDIR)/libphobos/libdruntime/.libs"; \ + export GDC; \ + GDC_FOR_BUILD="$$GDC"; export GDC_FOR_BUILD; \ GNATBIND="$$r/$(HOST_SUBDIR)/prev-gcc/gnatbind"; export GNATBIND; \ LDFLAGS="$(POSTSTAGE1_LDFLAGS) $(BOOT_LDFLAGS)"; export LDFLAGS; \ HOST_LIBS="$(POSTSTAGE1_LIBS)"; export HOST_LIBS; -@@ -281,6 +290,7 @@ BASE_TARGET_EXPORTS = \ +@@ -281,6 +292,7 @@ BASE_TARGET_EXPORTS = \ CXXFLAGS="$(CXXFLAGS_FOR_TARGET)"; export CXXFLAGS; \ GFORTRAN="$(GFORTRAN_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GFORTRAN; \ GOC="$(GOC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GOC; \ @@ -919,7 +923,7 @@ This implements building of libphobos library in GCC. DLLTOOL="$(DLLTOOL_FOR_TARGET)"; export DLLTOOL; \ LD="$(COMPILER_LD_FOR_TARGET)"; export LD; \ LDFLAGS="$(LDFLAGS_FOR_TARGET)"; export LDFLAGS; \ -@@ -345,6 +355,7 @@ CXX_FOR_BUILD = @CXX_FOR_BUILD@ +@@ -345,6 +357,7 @@ CXX_FOR_BUILD = @CXX_FOR_BUILD@ DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@ GFORTRAN_FOR_BUILD = @GFORTRAN_FOR_BUILD@ GOC_FOR_BUILD = @GOC_FOR_BUILD@ @@ -927,7 +931,7 @@ This implements building of libphobos library in GCC. LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ LD_FOR_BUILD = @LD_FOR_BUILD@ NM_FOR_BUILD = @NM_FOR_BUILD@ -@@ -402,6 +413,7 @@ STRIP = @STRIP@ +@@ -402,6 +415,7 @@ STRIP = @STRIP@ WINDRES = @WINDRES@ WINDMC = @WINDMC@ @@ -935,7 +939,7 @@ This implements building of libphobos library in GCC. GNATBIND = @GNATBIND@ GNATMAKE = @GNATMAKE@ -@@ -411,6 +423,7 @@ LIBCFLAGS = $(CFLAGS) +@@ -411,6 +425,7 @@ LIBCFLAGS = $(CFLAGS) CXXFLAGS = @CXXFLAGS@ LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates GOCFLAGS = $(CFLAGS) @@ -943,7 +947,7 @@ This implements building of libphobos library in GCC. CREATE_GCOV = create_gcov -@@ -497,6 +510,7 @@ CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @CXX_ +@@ -497,6 +512,7 @@ CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @CXX_ RAW_CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @RAW_CXX_FOR_TARGET@ GFORTRAN_FOR_TARGET=$(STAGE_CC_WRAPPER) @GFORTRAN_FOR_TARGET@ GOC_FOR_TARGET=$(STAGE_CC_WRAPPER) @GOC_FOR_TARGET@ @@ -951,7 +955,7 @@ This implements building of libphobos library in GCC. DLLTOOL_FOR_TARGET=@DLLTOOL_FOR_TARGET@ LD_FOR_TARGET=@LD_FOR_TARGET@ -@@ -521,6 +535,7 @@ LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARG +@@ -521,6 +537,7 @@ LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARG LIBCXXFLAGS_FOR_TARGET = $(CXXFLAGS_FOR_TARGET) -fno-implicit-templates LDFLAGS_FOR_TARGET = @LDFLAGS_FOR_TARGET@ GOCFLAGS_FOR_TARGET = -O2 -g @@ -959,7 +963,7 @@ This implements building of libphobos library in GCC. FLAGS_FOR_TARGET = @FLAGS_FOR_TARGET@ SYSROOT_CFLAGS_FOR_TARGET = @SYSROOT_CFLAGS_FOR_TARGET@ -@@ -622,6 +637,7 @@ EXTRA_HOST_FLAGS = \ +@@ -622,6 +639,7 @@ EXTRA_HOST_FLAGS = \ 'DLLTOOL=$(DLLTOOL)' \ 'GFORTRAN=$(GFORTRAN)' \ 'GOC=$(GOC)' \ @@ -967,7 +971,7 @@ This implements building of libphobos library in GCC. 'LD=$(LD)' \ 'LIPO=$(LIPO)' \ 'NM=$(NM)' \ -@@ -646,6 +662,7 @@ STAGE1_FLAGS_TO_PASS = \ +@@ -646,6 +664,7 @@ STAGE1_FLAGS_TO_PASS = \ POSTSTAGE1_FLAGS_TO_PASS = \ CC="$${CC}" CC_FOR_BUILD="$${CC_FOR_BUILD}" \ CXX="$${CXX}" CXX_FOR_BUILD="$${CXX_FOR_BUILD}" \ @@ -975,7 +979,7 @@ This implements building of libphobos library in GCC. GNATBIND="$${GNATBIND}" \ LDFLAGS="$${LDFLAGS}" \ HOST_LIBS="$${HOST_LIBS}" \ -@@ -678,6 +695,8 @@ EXTRA_TARGET_FLAGS = \ +@@ -678,6 +697,8 @@ EXTRA_TARGET_FLAGS = \ 'GFORTRAN=$$(GFORTRAN_FOR_TARGET) $$(XGCC_FLAGS_FOR_TARGET) $$(TFLAGS)' \ 'GOC=$$(GOC_FOR_TARGET) $$(XGCC_FLAGS_FOR_TARGET) $$(TFLAGS)' \ 'GOCFLAGS=$$(GOCFLAGS_FOR_TARGET)' \ From 005e6ffe1ba8ee989c1fa0caa30076856fe9e54e Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 29 Aug 2018 23:09:20 +0200 Subject: [PATCH 09/10] Backport C++ mangling fixes --- gcc/d/ChangeLog | 5 + gcc/d/d-target.cc | 38 +- gcc/d/dfrontend/cppmangle.c | 2342 +++++++++++------------------------ gcc/d/dfrontend/denum.c | 28 + gcc/d/dfrontend/enum.h | 1 + gcc/d/dfrontend/idgen.c | 2 + gcc/d/dfrontend/mtype.c | 21 +- gcc/d/dfrontend/target.h | 2 +- 8 files changed, 806 insertions(+), 1633 deletions(-) diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 5c1bafa04..4f8233e76 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,8 @@ +2018-08-29 Iain Buclaw + + * d-target.cc (Target::prefixName): Remove function. + (Target::cppParameterType): New function. + 2018-08-25 Iain Buclaw * Make-lang.in (D_FRONTEND_OBJS): Add iasm.o, iasmgcc.o diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index a178564ef..0c0be1822 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -431,13 +431,6 @@ Target::isVectorOpSupported (Type *type, TOK op, Type *) return true; } -/* Apply any target-specific prefixes based on the given linkage. */ - -void -Target::prefixName (OutBuffer *, LINK) -{ -} - /* Return the symbol mangling of S for C++ linkage. */ const char * @@ -469,6 +462,37 @@ Target::cppTypeMangle (Type *type) return NULL; } +/* Return the type that will really be used for passing the given parameter + ARG to an extern(C++) function. */ + +Type * +Target::cppParameterType (Parameter *arg) +{ + Type *t = arg->type->merge2 (); + if (arg->storageClass & (STCout | STCref)) + t = t->referenceTo (); + else if (arg->storageClass & STClazy) + { + /* Mangle as delegate. */ + Type *td = TypeFunction::create (NULL, t, 0, LINKd); + td = TypeDelegate::create (td); + t = t->merge2 (); + } + + /* Could be a va_list, which we mangle as a pointer. */ + if (t->ty == Tsarray && Type::tvalist->ty == Tsarray) + { + Type *tb = t->toBasetype ()->mutableOf (); + if (tb == Type::tvalist) + { + tb = t->nextOf ()->pointerTo (); + t = tb->castMod (t->mod); + } + } + + return t; +} + /* Return the default system linkage for the target. */ LINK diff --git a/gcc/d/dfrontend/cppmangle.c b/gcc/d/dfrontend/cppmangle.c index bd548105a..dc1705cca 100644 --- a/gcc/d/dfrontend/cppmangle.c +++ b/gcc/d/dfrontend/cppmangle.c @@ -9,6 +9,19 @@ * 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 #include #include @@ -31,269 +44,387 @@ typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param); int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL); -/* Do mangling for C++ linkage. - * No attempt is made to support mangling of templates, operator - * overloading, or special functions. - * - * So why don't we use the C++ ABI for D name mangling? - * Because D supports a lot of things (like modules) that the C++ - * ABI has no concept of. These affect every D mangled name, - * so nothing would be compatible anyway. - */ - -/* - * Follows Itanium C++ ABI 1.86 - */ - class CppMangleVisitor : public Visitor { - Objects components; - OutBuffer buf; - bool is_top_level; - bool components_on; + Objects components; // array of components available for substitution + OutBuffer *buf; // append the mangling to buf[] + Loc loc; // location for use in error messages - void writeBase36(size_t i) + public: + // Write to buf + void write_seq_id(size_t i) { if (i >= 36) { - writeBase36(i / 36); + write_seq_id(i / 36); i %= 36; } - if (i < 10) - buf.writeByte((char)(i + '0')); - else if (i < 36) - buf.writeByte((char)(i - 10 + 'A')); - else - assert(0); + i += (i < 10) ? '0' : 'A' - 10; + buf->writeByte((char)i); } bool substitute(RootObject *p) { //printf("substitute %s\n", p ? p->toChars() : NULL); - if (components_on) - for (size_t i = 0; i < components.dim; i++) + int i = find(p); + if (i >= 0) + { + //printf("\tmatch\n"); + /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ... + */ + buf->writeByte('S'); + if (i) { - //printf(" component[%d] = %s\n", i, components[i] ? components[i]->toChars() : NULL); - if (p == components[i]) - { - //printf("\tmatch\n"); - /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ... - */ - buf.writeByte('S'); - if (i) - writeBase36(i - 1); - buf.writeByte('_'); - return true; - } + write_seq_id(i - 1); } + buf->writeByte('_'); + return true; + } return false; } - bool exist(RootObject *p) + /****** + * See if `p` exists in components[] + * Returns: + * index if found, -1 if not + */ + int find(RootObject *p) { - //printf("exist %s\n", p ? p->toChars() : "NULL"); - if (components_on) - for (size_t i = 0; i < components.dim; i++) - { - if (p == components[i]) - { - return true; - } - } - return false; + //printf("find %p %d %s\n", p, p.dyncast(), p ? p.toChars() : NULL); + for (size_t i = 0; i < components.dim; i++) + { + if (p == components[i]) + return (int)i; + } + return -1; } - void store(RootObject *p) + /********************* + * Append p to components[] + */ + void append(RootObject *p) { - //printf("store %s\n", p ? p->toChars() : NULL); - if (components_on) - components.push(p); + //printf("append %p %d %s\n", p, p.dyncast(), p ? p.toChars() : "null"); + components.push(p); } - void source_name(Dsymbol *s, bool skipname = false) + /************************ + * 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) { - //printf("source_name(%s)\n", s->toChars()); - TemplateInstance *ti = s->isTemplateInstance(); - if (ti) - { - if (!skipname && !substitute(ti->tempdecl)) - { - store(ti->tempdecl); - const char *name = ti->tempdecl->toAlias()->ident->toChars(); - buf.printf("%d%s", strlen(name), name); - } - buf.writeByte('I'); - bool is_var_arg = false; - for (size_t i = 0; i < ti->tiargs->dim; i++) - { - RootObject *o = (RootObject *)(*ti->tiargs)[i]; + 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 + } - TemplateParameter *tp = NULL; - TemplateValueParameter *tv = NULL; - TemplateTupleParameter *tt = NULL; - if (!is_var_arg) - { - TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration(); - assert(td); - tp = (*td->parameters)[i]; - tv = tp->isTemplateValueParameter(); - tt = tp->isTemplateTupleParameter(); - } - /* - * ::= # type or template - * ::= # simple expressions - */ + /****************************** + * Write the mangled representation of the template arguments. + * Params: + * ti = the template instance + */ + void template_args(TemplateInstance *ti) + { + /* ::= I + 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->dim; i++) + { + RootObject *o = (*ti->tiargs)[i]; + TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration(); + assert(td); + TemplateParameter *tp = (*td->parameters)[i]; + + /* + * ::= # type or template + * ::= X E # expression + * ::= # simple expressions + * ::= I * E # argument pack + */ + if (tp->isTemplateTupleParameter()) + { + buf->writeByte('I'); // argument pack - if (tt) + // mangle the rest of the arguments as types + for (size_t j = i; j < ti->tiargs->dim; j++) { - buf.writeByte('I'); - is_var_arg = true; - tp = NULL; + Type *t = isType((*ti->tiargs)[j]); + assert(t); + t->accept(this); } - if (tv) + buf->writeByte('E'); + break; + } + if (tp->isTemplateTypeParameter()) + { + Type *t = isType(o); + assert(t); + t->accept(this); + } + else if (TemplateValueParameter *tv = tp->isTemplateValueParameter()) + { + // ::= L E # integer literal + if (tv->valType->isintegral()) { - // ::= L E # integer literal - if (tv->valType->isintegral()) - { - Expression *e = isExpression(o); - assert(e); - buf.writeByte('L'); - tv->valType->accept(this); - if (tv->valType->isunsigned()) - { - buf.printf("%llu", e->toUInteger()); - } - else - { - sinteger_t val = e->toInteger(); - if (val < 0) - { - val = -val; - buf.writeByte('n'); - } - buf.printf("%lld", val); - } - buf.writeByte('E'); - } - else + 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) { - s->error("Internal Compiler Error: C++ %s template value parameter is not supported", tv->valType->toChars()); - fatal(); + val = -val; + buf->writeByte('n'); } + buf->printf("%llu", val); + buf->writeByte('E'); } - else if (!tp || tp->isTemplateTypeParameter()) + else { - Type *t = isType(o); - assert(t); - t->accept(this); + ti->error("Internal Compiler Error: C++ `%s` template value parameter is not supported", tv->valType->toChars()); + fatal(); } - else if (tp->isTemplateAliasParameter()) + } + else if (tp->isTemplateAliasParameter()) + { + Dsymbol *d = isDsymbol(o); + Expression *e = isExpression(o); + if (d && d->isFuncDeclaration()) { - Dsymbol *d = isDsymbol(o); - Expression *e = isExpression(o); - if (!d && !e) - { - s->error("Internal Compiler Error: %s is unsupported parameter for C++ template: (%s)", o->toChars()); - fatal(); - } - if (d && d->isFuncDeclaration()) - { - bool is_nested = d->toParent() && !d->toParent()->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 + bool is_nested = d->toParent() && + !d->toParent()->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)) { - s->error("Internal Compiler Error: %s is unsupported parameter for C++ template", o->toChars()); - fatal(); + cpp_mangle_name(d, false); } - } else { - s->error("Internal Compiler Error: C++ templates support only integral value, type parameters, alias templates and alias function parameters"); + ti->error("Internal Compiler Error: `%s` is unsupported parameter for C++ template", o->toChars()); fatal(); } } - if (is_var_arg) + else if(tp->isTemplateThisParameter()) { - buf.writeByte('E'); + ti->error("Internal Compiler Error: C++ `%s` template this parameter is not supported", o->toChars()); + fatal(); } - buf.writeByte('E'); - return; + 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%s", strlen(name), name); + 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->toParent(); + 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->toParent(); + 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 + static bool isChar_traits_char(RootObject *o) + { + return isIdent_char(Id::char_traits, o); + } + + // Detect type ::std::allocator + static bool isAllocator_char(RootObject *o) + { + return isIdent_char(Id::allocator, o); + } + + // Detect type ::std::ident + 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->toParent(); + if (!p) + return false; + TemplateInstance *ti = p->isTemplateInstance(); + if (!ti) + return false; + Dsymbol *q = getQualifier(ti); + return isStd(q) && ti->tiargs->dim == 1 && isChar((*ti->tiargs)[0]); + } + + /*** + * Detect template args > + * and write st if found. + * Returns: + * true if found + */ + bool char_std_char_traits_char(TemplateInstance *ti, const char *st) + { + if (ti->tiargs->dim == 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 *p = s->toParent(); - if (p && p->isTemplateInstance()) + Dsymbol *si = getInstance(s); + Dsymbol *p = getQualifier(si); + if (p) { - s = p; - if (exist(p->isTemplateInstance()->tempdecl)) + if (isStd(p)) { - p = NULL; - } - else - { - p = p->toParent(); - } - } + 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, ::std::allocator> + if (ti->tiargs->dim == 3 && + isChar((*ti->tiargs)[0]) && + isChar_traits_char((*ti->tiargs)[1]) && + isAllocator_char((*ti->tiargs)[2])) - if (p && !p->isModule()) - { - if (p->ident == Id::std && is_initial_qualifier(p)) - buf.writestring("St"); + { + buf->writestring("Ss"); + return; + } + buf->writestring("Sb"); // ::std::basic_string + template_args(ti); + append(ti); + return; + } + + // ::std::basic_istream> + if (s->ident == Id::basic_istream && + char_std_char_traits_char(ti, "Si")) + return; + + // ::std::basic_ostream> + if (s->ident == Id::basic_ostream && + char_std_char_traits_char(ti, "So")) + return; + + // ::std::basic_iostream> + if (s->ident == Id::basic_iostream && + char_std_char_traits_char(ti, "Sd")) + return; + } + buf->writestring("St"); + } else prefix_name(p); } - if (!(s->ident == Id::std && is_initial_qualifier(s))) - store(s); - source_name(s); - } - } - - /* Is s the initial qualifier? - */ - bool is_initial_qualifier(Dsymbol *s) - { - Dsymbol *p = s->toParent(); - if (p && p->isTemplateInstance()) - { - if (exist(p->isTemplateInstance()->tempdecl)) + source_name(si); + if (!isStd(si)) { - return true; + /* 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); } - p = p->toParent(); } - - return !p || p->isModule(); } void cpp_mangle_name(Dsymbol *s, bool qualified) @@ -301,12 +432,12 @@ class CppMangleVisitor : public Visitor //printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified); Dsymbol *p = s->toParent(); Dsymbol *se = s; - bool dont_write_prefix = false; + bool write_prefix = true; if (p && p->isTemplateInstance()) { se = p; - if (exist(p->isTemplateInstance()->tempdecl)) - dont_write_prefix = true; + if (find(p->isTemplateInstance()->tempdecl) >= 0) + write_prefix = false; p = p->toParent(); } @@ -318,87 +449,70 @@ class CppMangleVisitor : public Visitor * 3. there is no CV-qualifier or a ref-qualifier for a member function * ABI 5.1.8 */ - if (p->ident == Id::std && - is_initial_qualifier(p) && - !qualified) + if (isStd(p) && !qualified) { + TemplateInstance *ti = se->isTemplateInstance(); if (s->ident == Id::allocator) { - buf.writestring("Sa"); // "Sa" is short for ::std::allocator - source_name(se, true); + buf->writestring("Sa"); // "Sa" is short for ::std::allocator + template_args(ti); } else if (s->ident == Id::basic_string) { - components_on = false; // turn off substitutions - buf.writestring("Sb"); // "Sb" is short for ::std::basic_string - size_t off = buf.offset; - source_name(se, true); - components_on = true; - - // Replace ::std::basic_string < char, ::std::char_traits, ::std::allocator > - // with Ss - //printf("xx: '%.*s'\n", (int)(buf.offset - off), buf.data + off); - if (buf.offset - off >= 26 && - memcmp(buf.data + off, "IcSt11char_traitsIcESaIcEE", 26) == 0) + // ::std::basic_string, ::std::allocator> + if (ti->tiargs->dim == 3 && + isChar((*ti->tiargs)[0]) && + isChar_traits_char((*ti->tiargs)[1]) && + isAllocator_char((*ti->tiargs)[2])) + { - buf.remove(off - 2, 28); - buf.insert(off - 2, (const char *)"Ss", 2); + buf->writestring("Ss"); return; } - buf.setsize(off); - source_name(se, true); + buf->writestring("Sb"); // ::std::basic_string + template_args(ti); } - else if (s->ident == Id::basic_istream || - s->ident == Id::basic_ostream || - s->ident == Id::basic_iostream) + else { - /* Replace - * ::std::basic_istream > with Si - * ::std::basic_ostream > with So - * ::std::basic_iostream > with Sd - */ - size_t off = buf.offset; - components_on = false; // turn off substitutions - source_name(se, true); - components_on = true; - - //printf("xx: '%.*s'\n", (int)(buf.offset - off), buf.data + off); - if (buf.offset - off >= 21 && - memcmp(buf.data + off, "IcSt11char_traitsIcEE", 21) == 0) + // ::std::basic_istream> + if (s->ident == Id::basic_istream) { - buf.remove(off, 21); - char mbuf[2]; - mbuf[0] = 'S'; - mbuf[1] = 'i'; - if (s->ident == Id::basic_ostream) - mbuf[1] = 'o'; - else if(s->ident == Id::basic_iostream) - mbuf[1] = 'd'; - buf.insert(off, mbuf, 2); - return; + if (char_std_char_traits_char(ti, "Si")) + return; } - buf.setsize(off); - buf.writestring("St"); - source_name(se); - } - else - { - buf.writestring("St"); + 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 (!dont_write_prefix) + buf->writeByte('N'); + if (write_prefix) prefix_name(p); source_name(se); - buf.writeByte('E'); + buf->writeByte('E'); } } else source_name(se); - store(s); + 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) @@ -406,27 +520,27 @@ class CppMangleVisitor : public Visitor // 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"); + d->error("Internal Compiler Error: C++ static non-`__gshared` non-`extern` variables not supported"); fatal(); } Dsymbol *p = d->toParent(); if (p && !p->isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE" { - buf.writestring("_ZN"); + buf->writestring("_ZN"); prefix_name(p); source_name(d); - buf.writeByte('E'); + buf->writeByte('E'); } else //char beta[6] should mangle as "beta" { if (!is_temp_arg_ref) { - buf.writestring(d->ident->toChars()); + buf->writestring(d->ident->toChars()); } else { - buf.writestring("_Z"); + buf->writestring("_Z"); source_name(d); } } @@ -438,153 +552,140 @@ class CppMangleVisitor : public Visitor /* * ::= _Z * ::= - * ::= - * ::= + * ::= + * ::= */ TypeFunction *tf = (TypeFunction *)d->type; - buf.writestring("_Z"); - Dsymbol *p = d->toParent(); - TemplateDeclaration *ftd = getFuncTemplateDecl(d); - - if (p && !p->isModule() && tf->linkage == LINKcpp && !ftd) + buf->writestring("_Z"); + if (getFuncTemplateDecl(d)) { - buf.writeByte('N'); - if (d->type->isConst()) - buf.writeByte('K'); - prefix_name(p); - - // See ABI 5.1.8 Compression - - // Replace ::std::allocator with Sa - if (buf.offset >= 17 && memcmp(buf.data, "_ZN3std9allocator", 17) == 0) - { - buf.remove(3, 14); - buf.insert(3, (const char *)"Sa", 2); - } - - // Replace ::std::basic_string with Sb - if (buf.offset >= 21 && memcmp(buf.data, "_ZN3std12basic_string", 21) == 0) - { - buf.remove(3, 18); - buf.insert(3, (const char *)"Sb", 2); - } - - // Replace ::std with St - if (buf.offset >= 7 && memcmp(buf.data, "_ZN3std", 7) == 0) + /* It's an instance of a function template + */ + TemplateInstance *ti = d->parent->isTemplateInstance(); + assert(ti); + Dsymbol *p = ti->toParent(); + if (p && !p->isModule() && tf->linkage == LINKcpp) { - buf.remove(3, 4); - buf.insert(3, (const char *)"St", 2); + 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'); } - if (buf.offset >= 8 && memcmp(buf.data, "_ZNK3std", 8) == 0) + else + source_name(ti); + headOfType(tf->nextOf()); // mangle return type + } + else + { + Dsymbol *p = d->toParent(); + if (p && !p->isModule() && tf->linkage == LINKcpp) { - buf.remove(4, 4); - buf.insert(4, (const char *)"St", 2); - } + /* ::= N [] E + * ::= N [] E + */ + buf->writeByte('N'); + CV_qualifiers(d->type); + + /* ::= + * ::= + * ::= + * ::= # empty + * ::= + * ::= + */ + prefix_name(p); + //printf("p: %s\n", buf.peekString()); - if (d->isDtorDeclaration()) - { - buf.writestring("D1"); + if (d->isCtorDeclaration()) + { + buf->writestring("C1"); + } + else if (d->isDtorDeclaration()) + { + buf->writestring("D1"); + } + else + { + source_name(d); + } + buf->writeByte('E'); } else { source_name(d); } - buf.writeByte('E'); - } - else if (ftd) - { - source_name(p); - this->is_top_level = true; - tf->nextOf()->accept(this); - this->is_top_level = false; - } - else - { - source_name(d); } if (tf->linkage == LINKcpp) //Template args accept extern "C" symbols with special mangling { assert(tf->ty == Tfunction); - argsCppMangle(tf->parameters, tf->varargs); + mangleFunctionParameters(tf->parameters, tf->varargs); } } - static int paramsCppMangleDg(void *ctx, size_t, Parameter *fparam) + void mangleFunctionParameters(Parameters *parameters, int varargs) { - CppMangleVisitor *mangler = (CppMangleVisitor *)ctx; - - Type *t = fparam->type->merge2(); - if (fparam->storageClass & (STCout | STCref)) - t = t->referenceTo(); - else if (fparam->storageClass & STClazy) - { - // Mangle as delegate - Type *td = new TypeFunction(NULL, t, 0, LINKd); - td = new TypeDelegate(td); - t = t->merge(); - } -#ifdef IN_GCC - if (t->ty == Tsarray && Type::tvalist->ty == Tsarray) + struct ParamsCppMangle { - // Could be a va_list, which we mangle as a pointer. - Type *tb = t->toBasetype()->mutableOf(); - if (tb == Type::tvalist) + int numparams; + CppMangleVisitor *mangler; + + static int dg(void *ctx, size_t, Parameter *fparam) { - tb = t->nextOf()->pointerTo(); - t = tb->castMod(t->mod); + ParamsCppMangle *p = (ParamsCppMangle *)ctx; + CppMangleVisitor *mangler = p->mangler; + Type *t = Target::cppParameterType(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; } - } -#else - if (t->ty == Tsarray) - { - // Mangle static arrays as pointers - t->error(Loc(), "Internal Compiler Error: unable to pass static array to extern(C++) function."); - t->error(Loc(), "Use pointer instead."); - fatal(); - //t = t->nextOf()->pointerTo(); - } -#endif + }; - /* If it is a basic, enum or struct type, - * then don't mark it const - */ - mangler->is_top_level = true; - if ((t->ty == Tenum || t->ty == Tstruct || t->ty == Tpointer || t->isTypeBasic()) && t->isConst()) - t->mutableOf()->accept(mangler); - else - t->accept(mangler); - mangler->is_top_level = false; - return 0; - } + ParamsCppMangle p; + p.numparams = 0; + p.mangler = this; - void argsCppMangle(Parameters *parameters, int varargs) - { if (parameters) - Parameter_foreach(parameters, ¶msCppMangleDg, (void*)this); + Parameter_foreach(parameters, &ParamsCppMangle::dg, (void*)&p); if (varargs) - buf.writestring("z"); - else if (!parameters || !parameters->dim) - buf.writeByte('v'); // encode ( ) parameters + buf->writeByte('z'); + else if (!p.numparams) + buf->writeByte('v'); // encode (void) parameters } public: - CppMangleVisitor() - : components(), buf(), is_top_level(false), components_on(true) + CppMangleVisitor(OutBuffer *buf, Loc loc) + : components(), buf(buf), loc(loc) { } - char *mangleOf(Dsymbol *s) + /***** + * Entry point. Append mangling to buf[] + * Params: + * s = symbol to mangle + */ + void mangleOf(Dsymbol *s) { - VarDeclaration *vd = s->isVarDeclaration(); - FuncDeclaration *fd = s->isFuncDeclaration(); - if (vd) + if (VarDeclaration *vd = s->isVarDeclaration()) { mangle_variable(vd, false); } - else if (fd) + else if (FuncDeclaration *fd = s->isFuncDeclaration()) { mangle_function(fd); } @@ -592,45 +693,91 @@ class CppMangleVisitor : public Visitor { assert(0); } - Target::prefixName(&buf, LINKcpp); - return buf.extractString(); } - void visit(Type *t) + /****** The rest is type mangling ************/ + + void error(Type *t) { -#ifdef IN_GCC - /* Make this the 'vendor extended type' when there is no - * C++ analog. - * u - */ - if (substitute(t)) - return; - assert(t->deco); - buf.printf("u%d%s", strlen(t->deco), t->deco); - store(t); -#else - if (t->isImmutable() || t->isShared()) + 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) { - t->error(Loc(), "Internal Compiler Error: shared or immutable types can not be mapped to C++ (%s)", t->toChars()); + mangleTypeClass((TypeClass*)t, true); } else { - t->error(Loc(), "Internal Compiler Error: type %s can not be mapped to C++\n", t->toChars()); + // For value types, strip const/immutable/shared from the head of the type + t->mutableOf()->unSharedOf()->accept(this); } - fatal(); //Fatal, because this error should be handled in frontend -#endif } - void visit(TypeBasic *t) + void visit(Type *t) { - /* ABI spec says: - * v void - * w wchar_t - * b bool - * c char - * a signed char - * h unsigned char - * s short + 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) + { + if (p || 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(TypeBasic *t) + { + if (t->isImmutable() || t->isShared()) + return error(t); + + /* : + * 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 @@ -645,6 +792,12 @@ class CppMangleVisitor : public Visitor * 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 # vendor extended type */ @@ -652,149 +805,121 @@ class CppMangleVisitor : public Visitor 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 - case Tdchar: c = 'w'; break; // wchar_t (UTF-32) - - case Timaginary32: p = 'G'; c = 'f'; break; - case Timaginary64: p = 'G'; c = 'd'; break; - case Timaginary80: p = 'G'; c = 'e'; break; - case Tcomplex32: p = 'C'; c = 'f'; break; - case Tcomplex64: p = 'C'; c = 'd'; break; - case Tcomplex80: p = 'C'; c = 'e'; break; - - default: visit((Type *)t); return; - } - if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - if (p || t->isConst()) - { - if (substitute(t)) - { - return; - } - else - { - store(t); - } - } - - if (t->isConst()) - buf.writeByte('K'); + 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; - // Handle any target-specific basic types. - if (const char *tm = Target::cppTypeMangle(t)) - { - buf.writestring(tm); - } - else - { - if (p) - buf.writeByte(p); - buf.writeByte(c); + default: + // Handle any target-specific basic types. + if (const char *tm = Target::cppTypeMangle(t)) + { + if (substitute(t)) + return; + else + append(t); + CV_qualifiers(t); + buf->writestring(tm); + return; + } + return error(t); } + writeBasicType(t, p, c); } - void visit(TypeVector *t) { - is_top_level = false; + if (t->isImmutable() || t->isShared()) + return error(t); + if (substitute(t)) return; - store(t); - if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - if (t->isConst()) - buf.writeByte('K'); + append(t); + CV_qualifiers(t); // Handle any target-specific vector types. if (const char *tm = Target::cppTypeMangle(t)) { - buf.writestring(tm); + buf->writestring(tm); } else { assert(t->basetype && t->basetype->ty == Tsarray); assert(((TypeSArray *)t->basetype)->dim); - //buf.printf("Dv%llu_", ((TypeSArray *)t->basetype)->dim->toInteger());// -- Gnu ABI v.4 - buf.writestring("U8__vector"); //-- Gnu ABI v.3 +#if 0 + buf->writestring("Dv"); + buf->printf("%llu", ((TypeSArray *)t->basetype)->dim->toInteger()); // -- Gnu ABI v.4 + buf->writeByte('_'); +#else + buf->writestring("U8__vector"); //-- Gnu ABI v.3 +#endif t->basetype->nextOf()->accept(this); } } void visit(TypeSArray *t) { - is_top_level = false; - if (!substitute(t)) - store(t); if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - if (t->isConst()) - buf.writeByte('K'); - buf.printf("A%llu_", t->dim ? t->dim->toInteger() : 0); - t->next->accept(this); - } - - void visit(TypeDArray *t) - { - visit((Type *)t); - } + return error(t); - void visit(TypeAArray *t) - { - visit((Type *)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) { - is_top_level = false; + if (t->isImmutable() || t->isShared()) + return error(t); + if (substitute(t)) return; - if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - if (t->isConst()) - buf.writeByte('K'); - buf.writeByte('P'); + CV_qualifiers(t); + buf->writeByte('P'); t->next->accept(this); - store(t); + append(t); } void visit(TypeReference *t) { - is_top_level = false; + //printf("TypeReference %s\n", t->toChars()); if (substitute(t)) return; - buf.writeByte('R'); + buf->writeByte('R'); t->next->accept(this); - store(t); + append(t); } void visit(TypeFunction *t) { - is_top_level = false; /* * ::= F [Y] E * ::= + @@ -819,1198 +944,167 @@ class CppMangleVisitor : public Visitor */ if (substitute(t)) return; - buf.writeByte('F'); + buf->writeByte('F'); if (t->linkage == LINKc) - buf.writeByte('Y'); + buf->writeByte('Y'); Type *tn = t->next; if (t->isref) tn = tn->referenceTo(); tn->accept(this); - argsCppMangle(t->parameters, t->varargs); - buf.writeByte('E'); - store(t); - } - - void visit(TypeDelegate *t) - { - visit((Type *)t); + mangleFunctionParameters(t->parameters, t->varargs); + buf->writeByte('E'); + append(t); } void visit(TypeStruct *t) { + if (t->isImmutable() || t->isShared()) + return error(t); + + /* __c_long and __c_ulong get special mangling + */ Identifier *id = t->sym->ident; //printf("struct id = '%s'\n", id->toChars()); - char c; if (id == Id::__c_long) - c = 'l'; + return writeBasicType(t, 0, 'l'); else if (id == Id::__c_ulong) - c = 'm'; - else - c = 0; - if (c) - { - if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - if (t->isConst()) - { - if (substitute(t)) - { - return; - } - else - { - store(t); - } - } + return writeBasicType(t, 0, 'm'); - if (t->isConst()) - buf.writeByte('K'); + //printf("TypeStruct %s\n", t->toChars()); + doSymbol(t); + } - buf.writeByte(c); - return; - } - is_top_level = false; + void visit(TypeEnum *t) + { + if (t->isImmutable() || t->isShared()) + return error(t); + + /* __c_(u)long(long) 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_longlong) + return writeBasicType(t, 0, 'x'); + else if (id == Id::__c_ulonglong) + return writeBasicType(t, 0, 'y'); + + doSymbol(t); + } + /**************** + * Write structs and enums. + * Params: + * t = TypeStruct or TypeEnum + */ + void doSymbol(Type *t) + { if (substitute(t)) return; - if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - if (t->isConst()) - buf.writeByte('K'); + CV_qualifiers(t); // Handle any target-specific struct types. if (const char *tm = Target::cppTypeMangle(t)) { - buf.writestring(tm); + buf->writestring(tm); } else { - if (!substitute(t->sym)) + Dsymbol *s = t->toDsymbol(NULL); + Dsymbol *p = s->toParent(); + if (p && p->isTemplateInstance()) { - cpp_mangle_name(t->sym, t->isConst()); + /* https://issues.dlang.org/show_bug.cgi?id=17947 + * Substitute the template instance symbol, not the struct/enum symbol + */ + if (substitute(p)) + return; } - - if (t->isImmutable() || t->isShared()) + if (!substitute(s)) { - visit((Type *)t); + cpp_mangle_name(s, t->isConst()); } } - if (t->isConst()) - store(t); + append(t); } - void visit(TypeEnum *t) + void visit(TypeClass *t) { - is_top_level = false; - if (substitute(t)) - return; - - if (t->isConst()) - buf.writeByte('K'); - - if (!substitute(t->sym)) - { - cpp_mangle_name(t->sym, t->isConst()); - } - - if (t->isImmutable() || t->isShared()) - { - visit((Type *)t); - } - - if (t->isConst()) - store(t); + mangleTypeClass(t, false); } - void visit(TypeClass *t) + /************************ + * 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 + */ if (substitute(t)) return; - if (t->isImmutable() || t->isShared()) + if (!head) + CV_qualifiers(t); + buf->writeByte('P'); + + CV_qualifiers(t); + { - visit((Type *)t); + Dsymbol *s = t->toDsymbol(NULL); + Dsymbol *p = s->toParent(); + 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 (t->isConst() && !is_top_level) - buf.writeByte('K'); - is_top_level = false; - buf.writeByte('P'); - - if (t->isConst()) - buf.writeByte('K'); if (!substitute(t->sym)) { cpp_mangle_name(t->sym, t->isConst()); } if (t->isConst()) - store(NULL); - store(t); + append(NULL); // C++ would have an extra type here + append(t); } const char *mangle_typeinfo(Dsymbol *s) { - buf.writestring("_ZTI"); + buf->writestring("_ZTI"); cpp_mangle_name(s, false); - return buf.extractString(); + return buf->extractString(); } }; const char *toCppMangleItanium(Dsymbol *s) { //printf("toCppMangleItanium(%s)\n", s->toChars()); - CppMangleVisitor v; - return v.mangleOf(s); + OutBuffer buf; + CppMangleVisitor v(&buf, s->loc); + v.mangleOf(s); + return buf.extractString(); } const char *cppTypeInfoMangleItanium(Dsymbol *s) { //printf("cppTypeInfoMangleItanium(%s)\n", s->toChars()); - CppMangleVisitor v; - return v.mangle_typeinfo(s); -} - -// Windows DMC and Microsoft Visual C++ mangling -#define VC_SAVED_TYPE_CNT 10 -#define VC_SAVED_IDENT_CNT 10 - -class VisualCPPMangler : public Visitor -{ - const char *saved_idents[VC_SAVED_IDENT_CNT]; - Type *saved_types[VC_SAVED_TYPE_CNT]; - - // IS_NOT_TOP_TYPE: when we mangling one argument, we can call visit several times (for base types of arg type) - // but we must save only arg type: - // For example: if we have an int** argument, we should save "int**" but visit will be called for "int**", "int*", "int" - // This flag is set up by the visit(NextType, ) function and should be reset when the arg type output is finished. - // MANGLE_RETURN_TYPE: return type shouldn't be saved and substituted in arguments - // IGNORE_CONST: in some cases we should ignore CV-modifiers. - - enum Flags - { - IS_NOT_TOP_TYPE = 0x1, - MANGLE_RETURN_TYPE = 0x2, - IGNORE_CONST = 0x4, - IS_DMC = 0x8 - }; - - int flags; OutBuffer buf; - - VisualCPPMangler(VisualCPPMangler *rvl) - : flags(0), buf() - { - flags |= (rvl->flags & IS_DMC); - memcpy(&saved_idents, &rvl->saved_idents, sizeof(const char*) * VC_SAVED_IDENT_CNT); - memcpy(&saved_types, &rvl->saved_types, sizeof(Type*) * VC_SAVED_TYPE_CNT); - } - -public: - VisualCPPMangler(bool isdmc) - : flags(0), buf() - { - if (isdmc) - { - flags |= IS_DMC; - } - memset(&saved_idents, 0, sizeof(const char*) * VC_SAVED_IDENT_CNT); - memset(&saved_types, 0, sizeof(Type*) * VC_SAVED_TYPE_CNT); - } - - void visit(Type *type) - { - if (type->isImmutable() || type->isShared()) - { - type->error(Loc(), "Internal Compiler Error: shared or immutable types can not be mapped to C++ (%s)", type->toChars()); - } - else - { - type->error(Loc(), "Internal Compiler Error: type %s can not be mapped to C++\n", type->toChars()); - } - fatal(); // Fatal, because this error should be handled in frontend - } - - void visit(TypeBasic *type) - { - //printf("visit(TypeBasic); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (type->isImmutable() || type->isShared()) - { - visit((Type*)type); - return; - } - - if (type->isConst() && ((flags & IS_NOT_TOP_TYPE) || (flags & IS_DMC))) - { - if (checkTypeSaved(type)) - return; - } - - if ((type->ty == Tbool) && checkTypeSaved(type))// try to replace long name with number - { - return; - } - mangleModifier(type); - switch (type->ty) - { - case Tvoid: buf.writeByte('X'); break; - case Tint8: buf.writeByte('C'); break; - case Tuns8: buf.writeByte('E'); break; - case Tint16: buf.writeByte('F'); break; - case Tuns16: buf.writeByte('G'); break; - case Tint32: buf.writeByte('H'); break; - case Tuns32: buf.writeByte('I'); break; - case Tfloat32: buf.writeByte('M'); break; - case Tint64: buf.writestring("_J"); break; - case Tuns64: buf.writestring("_K"); break; - case Tint128: buf.writestring("_L"); break; - case Tuns128: buf.writestring("_M"); break; - case Tfloat64: buf.writeByte('N'); break; - case Tbool: buf.writestring("_N"); break; - case Tchar: buf.writeByte('D'); break; - case Tdchar: buf.writeByte('I'); break; // unsigned int - - case Tfloat80: - if (flags & IS_DMC) - buf.writestring("_Z"); // DigitalMars long double - else - buf.writestring("_T"); // Intel long double - break; - - case Twchar: - if (flags & IS_DMC) - buf.writestring("_Y"); // DigitalMars wchar_t - else - buf.writestring("_W"); // Visual C++ wchar_t - break; - - default: visit((Type*)type); return; - } - flags &= ~IS_NOT_TOP_TYPE; - flags &= ~IGNORE_CONST; - } - - void visit(TypeVector *type) - { - //printf("visit(TypeVector); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (checkTypeSaved(type)) - return; - buf.writestring("T__m128@@"); // may be better as __m128i or __m128d? - flags &= ~IS_NOT_TOP_TYPE; - flags &= ~IGNORE_CONST; - } - - void visit(TypeSArray *type) - { - // This method can be called only for static variable type mangling. - //printf("visit(TypeSArray); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (checkTypeSaved(type)) - return; - // first dimension always mangled as const pointer - if (flags & IS_DMC) - buf.writeByte('Q'); - else - buf.writeByte('P'); - - flags |= IS_NOT_TOP_TYPE; - assert(type->next); - if (type->next->ty == Tsarray) - { - mangleArray((TypeSArray*)type->next); - } - else - { - type->next->accept(this); - } - } - - // attention: D int[1][2]* arr mapped to C++ int arr[][2][1]; (because it's more typical situation) - // There is not way to map int C++ (*arr)[2][1] to D - void visit(TypePointer *type) - { - //printf("visit(TypePointer); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (type->isImmutable() || type->isShared()) - { - visit((Type*)type); - return; - } - - assert(type->next); - if (type->next->ty == Tfunction) - { - const char *arg = mangleFunctionType((TypeFunction*)type->next); // compute args before checking to save; args should be saved before function type - - // If we've mangled this function early, previous call is meaningless. - // However we should do it before checking to save types of function arguments before function type saving. - // If this function was already mangled, types of all it arguments are save too, thus previous can't save - // anything if function is saved. - if (checkTypeSaved(type)) - return; - - if (type->isConst()) - buf.writeByte('Q'); // const - else - buf.writeByte('P'); // mutable - - buf.writeByte('6'); // pointer to a function - buf.writestring(arg); - flags &= ~IS_NOT_TOP_TYPE; - flags &= ~IGNORE_CONST; - return; - } - else if (type->next->ty == Tsarray) - { - if (checkTypeSaved(type)) - return; - mangleModifier(type); - - if (type->isConst() || !(flags & IS_DMC)) - buf.writeByte('Q'); // const - else - buf.writeByte('P'); // mutable - - if (global.params.is64bit) - buf.writeByte('E'); - flags |= IS_NOT_TOP_TYPE; - - mangleArray((TypeSArray*)type->next); - return; - } - else - { - if (checkTypeSaved(type)) - return; - mangleModifier(type); - - if (type->isConst()) - { - buf.writeByte('Q'); // const - } - else - { - buf.writeByte('P'); // mutable - } - - if (global.params.is64bit) - buf.writeByte('E'); - flags |= IS_NOT_TOP_TYPE; - type->next->accept(this); - } - } - - void visit(TypeReference *type) - { - //printf("visit(TypeReference); type = %s\n", type->toChars()); - if (checkTypeSaved(type)) - return; - - if (type->isImmutable() || type->isShared()) - { - visit((Type*)type); - return; - } - - buf.writeByte('A'); // mutable - - if (global.params.is64bit) - buf.writeByte('E'); - flags |= IS_NOT_TOP_TYPE; - assert(type->next); - if (type->next->ty == Tsarray) - { - mangleArray((TypeSArray*)type->next); - } - else - { - type->next->accept(this); - } - } - - void visit(TypeFunction *type) - { - const char *arg = mangleFunctionType(type); - - if ((flags & IS_DMC)) - { - if (checkTypeSaved(type)) - return; - } - else - { - buf.writestring("$$A6"); - } - buf.writestring(arg); - flags &= ~(IS_NOT_TOP_TYPE | IGNORE_CONST); - } - - void visit(TypeStruct *type) - { - Identifier *id = type->sym->ident; - char c; - if (id == Id::__c_long_double) - c = 'O'; // VC++ long double - else if (id == Id::__c_long) - c = 'J'; // VC++ long - else if (id == Id::__c_ulong) - c = 'K'; // VC++ unsigned long - else - c = 0; - - if (c) - { - if (type->isImmutable() || type->isShared()) - { - visit((Type*)type); - return; - } - - if (type->isConst() && ((flags & IS_NOT_TOP_TYPE) || (flags & IS_DMC))) - { - if (checkTypeSaved(type)) - return; - } - - mangleModifier(type); - buf.writeByte(c); - } - else - { - if (checkTypeSaved(type)) - return; - //printf("visit(TypeStruct); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - mangleModifier(type); - if (type->sym->isUnionDeclaration()) - buf.writeByte('T'); - else - buf.writeByte(type->cppmangle == CPPMANGLEclass ? 'V' : 'U'); - mangleIdent(type->sym); - } - flags &= ~IS_NOT_TOP_TYPE; - flags &= ~IGNORE_CONST; - } - - void visit(TypeEnum *type) - { - //printf("visit(TypeEnum); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (checkTypeSaved(type)) - return; - mangleModifier(type); - buf.writeByte('W'); - - switch (type->sym->memtype->ty) - { - case Tchar: - case Tint8: - buf.writeByte('0'); - break; - case Tuns8: - buf.writeByte('1'); - break; - case Tint16: - buf.writeByte('2'); - break; - case Tuns16: - buf.writeByte('3'); - break; - case Tint32: - buf.writeByte('4'); - break; - case Tuns32: - buf.writeByte('5'); - break; - case Tint64: - buf.writeByte('6'); - break; - case Tuns64: - buf.writeByte('7'); - break; - default: - visit((Type*)type); - break; - } - - mangleIdent(type->sym); - flags &= ~IS_NOT_TOP_TYPE; - flags &= ~IGNORE_CONST; - } - - // D class mangled as pointer to C++ class - // const(Object) mangled as Object const* const - void visit(TypeClass *type) - { - //printf("visit(TypeClass); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (checkTypeSaved(type)) - return; - if (flags & IS_NOT_TOP_TYPE) - mangleModifier(type); - - if (type->isConst()) - buf.writeByte('Q'); - else - buf.writeByte('P'); - - if (global.params.is64bit) - buf.writeByte('E'); - - flags |= IS_NOT_TOP_TYPE; - mangleModifier(type); - - buf.writeByte(type->cppmangle == CPPMANGLEstruct ? 'U' : 'V'); - - mangleIdent(type->sym); - flags &= ~IS_NOT_TOP_TYPE; - flags &= ~IGNORE_CONST; - } - - char *mangleOf(Dsymbol *s) - { - VarDeclaration *vd = s->isVarDeclaration(); - FuncDeclaration *fd = s->isFuncDeclaration(); - if (vd) - { - mangleVariable(vd); - } - else if (fd) - { - mangleFunction(fd); - } - else - { - assert(0); - } - return buf.extractString(); - } -private: - - void mangleFunction(FuncDeclaration *d) - { - // ? - assert(d); - buf.writeByte('?'); - mangleIdent(d); - - if (d->needThis()) // ::= - { - // Pivate methods always non-virtual in D and it should be mangled as non-virtual in C++ - //printf("%s: isVirtualMethod = %d, isVirtual = %d, vtblIndex = %d, interfaceVirtual = %p\n", - //d->toChars(), d->isVirtualMethod(), d->isVirtual(), (int)d->vtblIndex, d->interfaceVirtual); - if (d->isVirtual() && (d->vtblIndex != -1 || d->interfaceVirtual || d->overrideInterface())) - { - switch (d->protection.kind) - { - case PROTprivate: - buf.writeByte('E'); - break; - case PROTprotected: - buf.writeByte('M'); - break; - default: - buf.writeByte('U'); - break; - } - } - else - { - switch (d->protection.kind) - { - case PROTprivate: - buf.writeByte('A'); - break; - case PROTprotected: - buf.writeByte('I'); - break; - default: - buf.writeByte('Q'); - break; - } - } - if (global.params.is64bit) - buf.writeByte('E'); - if (d->type->isConst()) - { - buf.writeByte('B'); - } - else - { - buf.writeByte('A'); - } - } - else if (d->isMember2()) // static function - { // ::= - switch (d->protection.kind) - { - case PROTprivate: - buf.writeByte('C'); - break; - case PROTprotected: - buf.writeByte('K'); - break; - default: - buf.writeByte('S'); - break; - } - } - else // top-level function - { // ::= Y - buf.writeByte('Y'); - } - - const char *args = mangleFunctionType((TypeFunction *)d->type, (bool)d->needThis(), d->isCtorDeclaration() || d->isDtorDeclaration()); - buf.writestring(args); - } - - void mangleVariable(VarDeclaration *d) - { - // ::= ? - assert(d); - // 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(); - } - buf.writeByte('?'); - mangleIdent(d); - - assert((d->storage_class & STCfield) || !d->needThis()); - - Dsymbol *parent = d->toParent(); - while (parent && parent->isNspace()) - { - parent = parent->toParent(); - } - if (parent && parent->isModule()) // static member - { - buf.writeByte('3'); - } - else - { - switch (d->protection.kind) - { - case PROTprivate: - buf.writeByte('0'); - break; - case PROTprotected: - buf.writeByte('1'); - break; - default: - buf.writeByte('2'); - break; - } - } - - char cv_mod = 0; - Type *t = d->type; - - if (t->isImmutable() || t->isShared()) - { - visit((Type*)t); - return; - } - if (t->isConst()) - { - cv_mod = 'B'; // const - } - else - { - cv_mod = 'A'; // mutable - } - - if (t->ty != Tpointer) - t = t->mutableOf(); - - t->accept(this); - - if ((t->ty == Tpointer || t->ty == Treference || t->ty == Tclass) && global.params.is64bit) - { - buf.writeByte('E'); - } - - buf.writeByte(cv_mod); - } - - void mangleName(Dsymbol *sym, bool dont_use_back_reference = false) - { - //printf("mangleName('%s')\n", sym->toChars()); - const char *name = NULL; - bool is_dmc_template = false; - if (sym->isDtorDeclaration()) - { - buf.writestring("?1"); - return; - } - if (TemplateInstance *ti = sym->isTemplateInstance()) - { - VisualCPPMangler tmp((flags & IS_DMC) ? true : false); - tmp.buf.writeByte('?'); - tmp.buf.writeByte('$'); - tmp.buf.writestring(ti->name->toChars()); - tmp.saved_idents[0] = ti->name->toChars(); - tmp.buf.writeByte('@'); - if (flags & IS_DMC) - { - tmp.mangleIdent(sym->parent, true); - is_dmc_template = true; - } - - bool is_var_arg = false; - for (size_t i = 0; i < ti->tiargs->dim; i++) - { - RootObject *o = (*ti->tiargs)[i]; - - TemplateParameter *tp = NULL; - TemplateValueParameter *tv = NULL; - TemplateTupleParameter *tt = NULL; - if (!is_var_arg) - { - TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration(); - assert(td); - tp = (*td->parameters)[i]; - tv = tp->isTemplateValueParameter(); - tt = tp->isTemplateTupleParameter(); - } - - if (tt) - { - is_var_arg = true; - tp = NULL; - } - if (tv) - { - if (tv->valType->isintegral()) - { - - tmp.buf.writeByte('$'); - tmp.buf.writeByte('0'); - - Expression *e = isExpression(o); - assert(e); - - if (tv->valType->isunsigned()) - { - tmp.mangleNumber(e->toUInteger()); - } - else if(is_dmc_template) - { - // NOTE: DMC mangles everything based on - // unsigned int - tmp.mangleNumber(e->toInteger()); - } - else - { - sinteger_t val = e->toInteger(); - if (val < 0) - { - val = -val; - tmp.buf.writeByte('?'); - } - tmp.mangleNumber(val); - } - } - else - { - sym->error("Internal Compiler Error: C++ %s template value parameter is not supported", tv->valType->toChars()); - fatal(); - } - } - else if (!tp || tp->isTemplateTypeParameter()) - { - Type *t = isType(o); - assert(t); - t->accept(&tmp); - } - else if (tp->isTemplateAliasParameter()) - { - Dsymbol *d = isDsymbol(o); - Expression *e = isExpression(o); - if (!d && !e) - { - sym->error("Internal Compiler Error: %s is unsupported parameter for C++ template", o->toChars()); - fatal(); - } - if (d && d->isFuncDeclaration()) - { - tmp.buf.writeByte('$'); - tmp.buf.writeByte('1'); - tmp.mangleFunction(d->isFuncDeclaration()); - } - else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration()) - { - tmp.buf.writeByte('$'); - if (flags & IS_DMC) - tmp.buf.writeByte('1'); - else - tmp.buf.writeByte('E'); - tmp.mangleVariable(((VarExp*)e)->var->isVarDeclaration()); - } - else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember) - { - - Dsymbol *ds = d->isTemplateDeclaration()->onemember; - if (flags & IS_DMC) - { - tmp.buf.writeByte('V'); - } - else - { - if (ds->isUnionDeclaration()) - { - tmp.buf.writeByte('T'); - } - else if (ds->isStructDeclaration()) - { - tmp.buf.writeByte('U'); - } - else if (ds->isClassDeclaration()) - { - tmp.buf.writeByte('V'); - } - else - { - sym->error("Internal Compiler Error: C++ templates support only integral value, type parameters, alias templates and alias function parameters"); - fatal(); - } - } - tmp.mangleIdent(d); - } - else - { - sym->error("Internal Compiler Error: %s is unsupported parameter for C++ template: (%s)", o->toChars()); - fatal(); - } - - } - else - { - sym->error("Internal Compiler Error: C++ templates support only integral value, type parameters, alias templates and alias function parameters"); - fatal(); - } - } - name = tmp.buf.extractString(); - } - else - { - name = sym->ident->toChars(); - } - assert(name); - if (is_dmc_template) - { - if (checkAndSaveIdent(name)) - return; - } - else - { - if (dont_use_back_reference) - { - saveIdent(name); - } - else - { - if (checkAndSaveIdent(name)) - return; - } - } - buf.writestring(name); - buf.writeByte('@'); - } - - // returns true if name already saved - bool checkAndSaveIdent(const char *name) - { - for (size_t i = 0; i < VC_SAVED_IDENT_CNT; i++) - { - if (!saved_idents[i]) // no saved same name - { - saved_idents[i] = name; - break; - } - - if (!strcmp(saved_idents[i], name)) // ok, we've found same name. use index instead of name - { - buf.writeByte(i + '0'); - return true; - } - } - return false; - } - - void saveIdent(const char *name) - { - for (size_t i = 0; i < VC_SAVED_IDENT_CNT; i++) - { - if (!saved_idents[i]) // no saved same name - { - saved_idents[i] = name; - break; - } - - if (!strcmp(saved_idents[i], name)) // ok, we've found same name. use index instead of name - { - return; - } - } - } - - void mangleIdent(Dsymbol *sym, bool dont_use_back_reference = false) - { - // ::= @ - // ::= - // ::= - - // ::= @ - // ::= ?$ @