Add support for multiple-return values in inline asm. This should

get inline asm working as well as it did previously with the CBE
with the new MRV support for inline asm.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51420 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-05-22 06:19:37 +00:00
parent ea21ad4926
commit f6a048c3a8
2 changed files with 61 additions and 34 deletions

View File

@ -2598,11 +2598,8 @@ void CWriter::lowerIntrinsics(Function &F) {
} }
void CWriter::visitCallInst(CallInst &I) { void CWriter::visitCallInst(CallInst &I) {
//check if we have inline asm if (isa<InlineAsm>(I.getOperand(0)))
if (isInlineAsm(I)) { return visitInlineAsm(I);
visitInlineAsm(I);
return;
}
bool WroteCallee = false; bool WroteCallee = false;
@ -2920,53 +2917,64 @@ void CWriter::visitInlineAsm(CallInst &CI) {
InlineAsm* as = cast<InlineAsm>(CI.getOperand(0)); InlineAsm* as = cast<InlineAsm>(CI.getOperand(0));
std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints(); std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints();
std::vector<std::pair<std::string, Value*> > Input; std::vector<std::pair<std::string, Value*> > Input;
std::vector<std::pair<std::string, Value*> > Output; std::vector<std::pair<std::string, std::pair<Value*, int> > > Output;
std::string Clobber; std::string Clobber;
int count = CI.getType() == Type::VoidTy ? 1 : 0; unsigned ValueCount = 0;
std::vector<std::pair<Value*, int> > ResultVals;
if (CI.getType() == Type::VoidTy)
;
else if (const StructType *ST = dyn_cast<StructType>(CI.getType())) {
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
ResultVals.push_back(std::make_pair(&CI, (int)i));
} else {
ResultVals.push_back(std::make_pair(&CI, -1));
}
for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(), for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
E = Constraints.end(); I != E; ++I) { E = Constraints.end(); I != E; ++I) {
assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
std::string c = std::string C = InterpretASMConstraint(*I);
InterpretASMConstraint(*I); if (C.empty()) continue;
switch(I->Type) {
default: switch (I->Type) {
assert(0 && "Unknown asm constraint"); default: assert(0 && "Unknown asm constraint");
break;
case InlineAsm::isInput: { case InlineAsm::isInput: {
if (c.size()) { assert(ValueCount >= ResultVals.size() && "Input can't refer to result");
Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI)); Value *V = CI.getOperand(ValueCount-ResultVals.size());
++count; //consume arg Input.push_back(std::make_pair(C, V));
}
break; break;
} }
case InlineAsm::isOutput: { case InlineAsm::isOutput: {
if (c.size()) { std::pair<Value*, int> V;
Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c), if (ValueCount < ResultVals.size())
count ? CI.getOperand(count) : &CI)); V = ResultVals[ValueCount];
++count; //consume arg else
} V = std::make_pair(CI.getOperand(ValueCount-ResultVals.size()), -1);
break; Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+C),
} V));
case InlineAsm::isClobber: {
if (c.size())
Clobber += ",\"" + c + "\"";
break; break;
} }
case InlineAsm::isClobber:
Clobber += ",\"" + C + "\"";
continue; // Not an actual argument.
} }
++ValueCount; // Consumes an argument.
} }
//fix up the asm string for gcc // Fix up the asm string for gcc.
std::string asmstr = gccifyAsm(as->getAsmString()); std::string asmstr = gccifyAsm(as->getAsmString());
Out << "__asm__ volatile (\"" << asmstr << "\"\n"; Out << "__asm__ volatile (\"" << asmstr << "\"\n";
Out << " :"; Out << " :";
for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(), for (unsigned i = 0, e = Output.size(); i != e; ++i) {
E = Output.end(); I != E; ++I) { if (i)
Out << "\"" << I->first << "\"("; Out << ", ";
writeOperandRaw(I->second); Out << "\"" << Output[i].first << "\"(";
writeOperandRaw(Output[i].second.first);
if (Output[i].second.second != -1)
Out << ".field" << Output[i].second.second; // Multiple retvals.
Out << ")"; Out << ")";
if (I + 1 != E)
Out << ",";
} }
Out << "\n :"; Out << "\n :";
for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(), for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(),

View File

@ -0,0 +1,19 @@
; RUN: llvm-as < %s | llc -march=c
declare {i32, i32} @foo()
define i32 @test() {
%A = call {i32, i32} @foo()
%B = getresult {i32, i32} %A, 0
%C = getresult {i32, i32} %A, 1
%D = add i32 %B, %C
ret i32 %D
}
define i32 @test2() {
%A = call {i32, i32} asm sideeffect "...", "={cx},={di},~{dirflag},~{fpsr},~{flags},~{memory}"()
%B = getresult {i32, i32} %A, 0
%C = getresult {i32, i32} %A, 1
%D = add i32 %B, %C
ret i32 %D
}