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/asm-x86.h b/gen/asm-x86.h index 3f47850e..8e1e5334 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 @@ -1889,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 @@ -2496,7 +2499,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. diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index d7260586..8acc2e00 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -149,7 +149,25 @@ AsmParserCommon* asmparser = NULL; #include "asm-x86.h" // x86_64 assembly parser #undef ASM_X86_64 -bool d_have_inline_asm() { return true; } +/** + * 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) { @@ -444,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; @@ -838,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; } 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];