summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTanya Lattner <tonic@nondot.org>2008-05-22 20:50:33 +0000
committerTanya Lattner <tonic@nondot.org>2008-05-22 20:50:33 +0000
commite54167947591d6c6b536751a066cf483c13faa88 (patch)
tree52ec8b16180aa1db04374a1e38f39e56f02d4eec
parent7d0b6f04937b6201b0f431f0559f341c7a025e2a (diff)
downloadllvm-e54167947591d6c6b536751a066cf483c13faa88.tar.gz
Merge from mainline.
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. llvm-svn: 51437
-rw-r--r--llvm/lib/Target/CBackend/CBackend.cpp76
-rw-r--r--llvm/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll19
2 files changed, 61 insertions, 34 deletions
diff --git a/llvm/lib/Target/CBackend/CBackend.cpp b/llvm/lib/Target/CBackend/CBackend.cpp
index d6ccefc8467b..2d7e27917e08 100644
--- a/llvm/lib/Target/CBackend/CBackend.cpp
+++ b/llvm/lib/Target/CBackend/CBackend.cpp
@@ -2592,11 +2592,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;
@@ -2914,53 +2911,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(),
diff --git a/llvm/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll b/llvm/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll
new file mode 100644
index 000000000000..16bf23e4d88e
--- /dev/null
+++ b/llvm/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll
@@ -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
+}