diff options
author | Chris Lattner <sabre@nondot.org> | 2008-05-22 06:19:37 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-05-22 06:19:37 +0000 |
commit | f6a048c3a8f6ae660a8253145adf7b5119f61667 (patch) | |
tree | af78ace7c4576c45b2f9ebc12e8c1eaa30767ead /lib/Target/CBackend/CBackend.cpp | |
parent | ea21ad49261a6a9d1614c01e631c2cdc4d554b84 (diff) |
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
Diffstat (limited to 'lib/Target/CBackend/CBackend.cpp')
-rw-r--r-- | lib/Target/CBackend/CBackend.cpp | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index f52322bef2..e72d8aed0a 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -2598,11 +2598,8 @@ void CWriter::lowerIntrinsics(Function &F) { } void CWriter::visitCallInst(CallInst &I) { - //check if we have inline asm - if (isInlineAsm(I)) { - visitInlineAsm(I); - return; - } + if (isa<InlineAsm>(I.getOperand(0))) + return visitInlineAsm(I); bool WroteCallee = false; @@ -2920,53 +2917,64 @@ void CWriter::visitInlineAsm(CallInst &CI) { InlineAsm* as = cast<InlineAsm>(CI.getOperand(0)); std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints(); 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; - 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(), E = Constraints.end(); I != E; ++I) { assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); - std::string c = - InterpretASMConstraint(*I); - switch(I->Type) { - default: - assert(0 && "Unknown asm constraint"); - break; + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + switch (I->Type) { + default: assert(0 && "Unknown asm constraint"); case InlineAsm::isInput: { - if (c.size()) { - Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI)); - ++count; //consume arg - } + assert(ValueCount >= ResultVals.size() && "Input can't refer to result"); + Value *V = CI.getOperand(ValueCount-ResultVals.size()); + Input.push_back(std::make_pair(C, V)); break; } case InlineAsm::isOutput: { - if (c.size()) { - Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c), - count ? CI.getOperand(count) : &CI)); - ++count; //consume arg - } - break; - } - case InlineAsm::isClobber: { - if (c.size()) - Clobber += ",\"" + c + "\""; + std::pair<Value*, int> V; + if (ValueCount < ResultVals.size()) + V = ResultVals[ValueCount]; + else + V = std::make_pair(CI.getOperand(ValueCount-ResultVals.size()), -1); + Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+C), + V)); 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()); Out << "__asm__ volatile (\"" << asmstr << "\"\n"; Out << " :"; - for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(), - E = Output.end(); I != E; ++I) { - Out << "\"" << I->first << "\"("; - writeOperandRaw(I->second); + for (unsigned i = 0, e = Output.size(); i != e; ++i) { + if (i) + Out << ", "; + Out << "\"" << Output[i].first << "\"("; + writeOperandRaw(Output[i].second.first); + if (Output[i].second.second != -1) + Out << ".field" << Output[i].second.second; // Multiple retvals. Out << ")"; - if (I + 1 != E) - Out << ","; } Out << "\n :"; for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(), |