Merge pull request #345 from klickverbot/template-function-label

Fix inline asm labels in template functions.
This commit is contained in:
David Nadlinger
2013-05-11 12:24:30 -07:00
5 changed files with 27 additions and 13 deletions

View File

@@ -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()

View File

@@ -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
};

View File

@@ -22,6 +22,7 @@
#if defined(_MSC_VER)
#include <ctype.h>
#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, "<<func>>", 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.

View File

@@ -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 <<func>> 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("<<func>>");
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;
}

View File

@@ -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];