From d15a3bacacbafacf30eccb27c08fd0307e58dddd Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 11 May 2013 18:43:41 +0200 Subject: [PATCH 1/4] Minor cleanup. --- gen/asm-x86.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gen/asm-x86.h b/gen/asm-x86.h index 3f47850e..2d243326 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -22,6 +22,7 @@ #if defined(_MSC_VER) #include #endif +#include "gen/llvmhelpers.h" // printLabelName #ifndef ASM_X86_64 namespace AsmParserx8632 @@ -2496,7 +2497,7 @@ namespace AsmParserx8664 } else { - // Plain memory reference to variable + // Plain memory reference to variable or reference to label. /* If in a reg, DMD moves to memory.. even with -O, so we'll do the same by always using the "m" contraint. From 8b9deecf3421a25746e1aa6b49f95585260351fd Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 11 May 2013 20:12:25 +0200 Subject: [PATCH 2/4] Remove dead code. --- gen/asmstmt.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index d7260586..d3a8217b 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -149,8 +149,6 @@ AsmParserCommon* asmparser = NULL; #include "asm-x86.h" // x86_64 assembly parser #undef ASM_X86_64 -bool d_have_inline_asm() { return true; } - Statement *AsmStatement::semantic(Scope *sc) { if (sc->func && sc->func->isSafe()) From 15fd67be0344b25a7b499686a1dc42845702ce63 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 11 May 2013 20:18:34 +0200 Subject: [PATCH 3/4] Remove code for unimplemented goto-into-asm check. The check was never fully implemented. We need to look into this again, as currently we fail with a fairly unintellegible LLVM ICE (added as GitHub #). --- dmd2/statement.c | 3 --- dmd2/statement.h | 1 - gen/llvmhelpers.cpp | 6 ------ 3 files changed, 10 deletions(-) diff --git a/dmd2/statement.c b/dmd2/statement.c index 463363ca..96034062 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -5509,9 +5509,6 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) #endif this->lblock = NULL; this->fwdrefs = NULL; -#if IN_LLVM - this->asmLabel = false; -#endif } Statement *LabelStatement::syntaxCopy() diff --git a/dmd2/statement.h b/dmd2/statement.h index 4ff0ddee..7c9766d1 100644 --- a/dmd2/statement.h +++ b/dmd2/statement.h @@ -943,7 +943,6 @@ struct LabelStatement : Statement void toIR(IRState *irs); #if IN_LLVM - bool asmLabel; // for labels inside inline assembler void toNakedIR(IRState *irs); #endif }; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 76f64787..90546920 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -232,12 +232,6 @@ void DtoGoto(Loc loc, Identifier* target, TryFinallyStatement* sourceFinally) fatal(); } - // if the target label is inside inline asm, error - if(lblstmt->asmLabel) { - error(loc, "cannot goto to label %s inside an inline asm block", target->toChars()); - fatal(); - } - // find target basic block std::string labelname = gIR->func()->gen->getScopedLabelName(target->toChars()); llvm::BasicBlock*& targetBB = gIR->func()->gen->labelToBB[labelname]; From 5742a0219cfd7c638a7f7b846bc91e00d94ad73a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 11 May 2013 20:57:42 +0200 Subject: [PATCH 4/4] Fix inline asm labels in template functions. This is a giant kludge to avoid a redesign of the inline asm handling code. I'd be glad if somebody came up with a better solution. GitHub: Fixes #340. --- gen/asm-x86.h | 4 +++- gen/asmstmt.cpp | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/gen/asm-x86.h b/gen/asm-x86.h index 2d243326..8e1e5334 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -1890,7 +1890,9 @@ namespace AsmParserx8664 void addLabel ( char* id ) { - printLabelName(insnTemplate, sc->func->mangle(), id); + // We need to delay emitting the actual function name, see + // replace_func_name in asmstmt.cpp for details. + printLabelName(insnTemplate, "<>", id); } /* Determines whether the operand is a register, memory reference diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index d3a8217b..8acc2e00 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -149,6 +149,26 @@ AsmParserCommon* asmparser = NULL; #include "asm-x86.h" // x86_64 assembly parser #undef ASM_X86_64 +/** + * Replaces <> with the name of the currently codegen'd function. + * + * This kludge is required to handle labels correctly, as the instruction + * strings for jumps, … are generated during semantic3, but attribute inference + * might change the function type (and hence the mangled name) right at the end + * of semantic3. + */ +static void replace_func_name(IRState* p, std::string& insnt) +{ + static const std::string needle("<>"); + + size_t pos; + while (std::string::npos != (pos = insnt.find(needle))) + { + // This will only happen for few instructions, and only once for those. + insnt.replace(pos, needle.size(), p->func()->decl->mangle(false)); + } +} + Statement *AsmStatement::semantic(Scope *sc) { if (sc->func && sc->func->isSafe()) @@ -442,6 +462,8 @@ AsmStatement::toIR(IRState * irs) // excessive commas are removed later... + replace_func_name(irs, code->insnTemplate); + // push asm statement IRAsmStmt* asmStmt = new IRAsmStmt; asmStmt->code = code->insnTemplate; @@ -836,6 +858,7 @@ void AsmStatement::toNakedIR(IRState *p) AsmCode * code = (AsmCode *) asmcode; // build asm stmt + replace_func_name(p, code->insnTemplate); p->nakedAsm << "\t" << code->insnTemplate << std::endl; }