mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-19 14:23:13 +01:00
[svn r320] Begun work on branches out of asm blocks. Unfinished.
This commit is contained in:
@@ -791,6 +791,10 @@ struct AsmStatement : Statement
|
||||
virtual AsmStatement *isAsmStatement() { return this; }
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LLVMDC
|
||||
// non-zero if this is a branch, contains the target
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct AsmBlockStatement : CompoundStatement
|
||||
|
||||
@@ -78,6 +78,8 @@ AsmStatement::AsmStatement(Loc loc, Token *tokens) :
|
||||
refparam = 0;
|
||||
naked = 0;
|
||||
regs = 0;
|
||||
|
||||
isBranchToLabel = NULL;
|
||||
}
|
||||
|
||||
Statement *AsmStatement::syntaxCopy()
|
||||
@@ -433,6 +435,7 @@ assert(0);
|
||||
asmStmt->in_c = llvmInConstraints;
|
||||
asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end());
|
||||
asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end());
|
||||
asmStmt->isBranchToLabel = isBranchToLabel;
|
||||
asmblock->s.push_back(asmStmt);
|
||||
}
|
||||
|
||||
@@ -508,6 +511,51 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
}
|
||||
}
|
||||
|
||||
// build forwarder for in-asm branches to external labels
|
||||
// this additional asm code sets the __llvm_jump_target variable
|
||||
// to a unique value that will identify the jump target in
|
||||
// a post-asm switch
|
||||
//FIXME: Need to init __llvm_jump_target
|
||||
//FIXME: Store the value -> label mapping somewhere, so it can be referenced later
|
||||
std::string asmGotoEnd = "jmp __llvm_asm_end ; ";
|
||||
std::string outGotoSetter = asmGotoEnd;
|
||||
|
||||
size_t n = asmblock->s.size();
|
||||
for(size_t i=0; i<n; ++i)
|
||||
{
|
||||
IRAsmStmt* a = asmblock->s[i];
|
||||
|
||||
// skip non-branch statements
|
||||
if(!a->isBranchToLabel)
|
||||
continue;
|
||||
|
||||
// if internal, no special handling is necessary, skip
|
||||
std::vector<Identifier*>::const_iterator it, end;
|
||||
end = asmblock->internalLabels.end();
|
||||
bool skip = false;
|
||||
for(it = asmblock->internalLabels.begin(); it != end; ++it)
|
||||
if((*it)->equals(a->isBranchToLabel))
|
||||
skip = true;
|
||||
if(skip)
|
||||
continue;
|
||||
|
||||
// provide an in-asm target for the branch and set value
|
||||
Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string);
|
||||
outGotoSetter += a->isBranchToLabel->string;
|
||||
outGotoSetter += ": ; ";
|
||||
outGotoSetter += "nop ; "; //FIXME: Change this to set __llvm_jump_target to a unique value
|
||||
outGotoSetter += asmGotoEnd;
|
||||
}
|
||||
if(outGotoSetter != asmGotoEnd)
|
||||
{
|
||||
outGotoSetter += "__llvm_asm_end: ; ";
|
||||
IRAsmStmt* outSetterStmt = new IRAsmStmt;
|
||||
outSetterStmt->code = outGotoSetter;
|
||||
//FIXME: set other stuff
|
||||
asmblock->s.push_back(outSetterStmt);
|
||||
}
|
||||
|
||||
|
||||
// build asm block
|
||||
std::vector<LLValue*> outargs;
|
||||
std::vector<LLValue*> inargs;
|
||||
@@ -519,7 +567,7 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
std::string code;
|
||||
size_t asmIdx = 0;
|
||||
|
||||
size_t n = asmblock->s.size();
|
||||
n = asmblock->s.size();
|
||||
for (size_t i=0; i<n; ++i)
|
||||
{
|
||||
IRAsmStmt* a = asmblock->s[i];
|
||||
@@ -588,6 +636,8 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
|
||||
p->asmBlock = NULL;
|
||||
Logger::println("END ASM");
|
||||
|
||||
//FIXME: Emit goto forwarder code here
|
||||
}
|
||||
|
||||
// the whole idea of this statement is to avoid the flattening
|
||||
@@ -609,4 +659,4 @@ Statement *AsmBlockStatement::syntaxCopy()
|
||||
}
|
||||
AsmBlockStatement *cs = new AsmBlockStatement(loc, a);
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1427,7 +1427,7 @@ struct AsmProcessor
|
||||
}
|
||||
|
||||
void addLabel(char* id) {
|
||||
insnTemplate->writestring(".LDASM_");
|
||||
//insnTemplate->writestring(".LDASM_");
|
||||
insnTemplate->writestring(id);
|
||||
}
|
||||
|
||||
@@ -1911,9 +1911,12 @@ struct AsmProcessor
|
||||
asmcode->dollarLabel = lbl_num; // could make the dollar label part of the same asm..
|
||||
} else if (e->op == TOKdsymbol) {
|
||||
LabelDsymbol * lbl = (LabelDsymbol *) ((DsymbolExp *) e)->s;
|
||||
// this can probably be removed
|
||||
if (! lbl->asmLabelNum)
|
||||
lbl->asmLabelNum = ++d_priv_asm_label_serial;
|
||||
|
||||
stmt->isBranchToLabel = lbl->ident;
|
||||
|
||||
use_star = false;
|
||||
addLabel(lbl->ident->toChars());
|
||||
} else if ((decl && decl->isCodeseg())) { // if function or label
|
||||
|
||||
@@ -72,12 +72,18 @@ struct IRAsmStmt
|
||||
std::string in_c;
|
||||
std::vector<LLValue*> out;
|
||||
std::vector<LLValue*> in;
|
||||
|
||||
// if this is nonzero, it contains the target ident
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct IRAsmBlock
|
||||
{
|
||||
std::vector<IRAsmStmt*> s;
|
||||
std::set<std::string> clobs;
|
||||
|
||||
// stores the labels within the asm block
|
||||
std::vector<Identifier*> internalLabels;
|
||||
};
|
||||
|
||||
// represents the module
|
||||
|
||||
@@ -1066,10 +1066,11 @@ void LabelStatement::toIR(IRState* p)
|
||||
if (p->asmBlock)
|
||||
{
|
||||
IRAsmStmt* a = new IRAsmStmt;
|
||||
a->code = ".LDASM_";
|
||||
// a->code = ".LDASM_";
|
||||
a->code += ident->toChars();
|
||||
a->code += ":";
|
||||
p->asmBlock->s.push_back(a);
|
||||
p->asmBlock->internalLabels.push_back(ident);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user