mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-13 17:06:15 +00:00
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:
parent
ea21ad4926
commit
f6a048c3a8
@ -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) {
|
switch (I->Type) {
|
||||||
default:
|
default: assert(0 && "Unknown asm constraint");
|
||||||
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 << "\"(";
|
|
||||||
writeOperandRaw(I->second);
|
|
||||||
Out << ")";
|
|
||||||
if (I + 1 != E)
|
|
||||||
Out << ", ";
|
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 << ")";
|
||||||
}
|
}
|
||||||
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(),
|
||||||
|
19
test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll
Normal file
19
test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll
Normal 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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user