Skip to content

Commit e541679

Browse files
committed
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
1 parent 7d0b6f0 commit e541679

File tree

2 files changed

+61
-34
lines changed

2 files changed

+61
-34
lines changed

llvm/lib/Target/CBackend/CBackend.cpp

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,11 +2592,8 @@ void CWriter::lowerIntrinsics(Function &F) {
25922592
}
25932593

25942594
void CWriter::visitCallInst(CallInst &I) {
2595-
//check if we have inline asm
2596-
if (isInlineAsm(I)) {
2597-
visitInlineAsm(I);
2598-
return;
2599-
}
2595+
if (isa<InlineAsm>(I.getOperand(0)))
2596+
return visitInlineAsm(I);
26002597

26012598
bool WroteCallee = false;
26022599

@@ -2914,53 +2911,64 @@ void CWriter::visitInlineAsm(CallInst &CI) {
29142911
InlineAsm* as = cast<InlineAsm>(CI.getOperand(0));
29152912
std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints();
29162913
std::vector<std::pair<std::string, Value*> > Input;
2917-
std::vector<std::pair<std::string, Value*> > Output;
2914+
std::vector<std::pair<std::string, std::pair<Value*, int> > > Output;
29182915
std::string Clobber;
2919-
int count = CI.getType() == Type::VoidTy ? 1 : 0;
2916+
unsigned ValueCount = 0;
2917+
2918+
std::vector<std::pair<Value*, int> > ResultVals;
2919+
if (CI.getType() == Type::VoidTy)
2920+
;
2921+
else if (const StructType *ST = dyn_cast<StructType>(CI.getType())) {
2922+
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
2923+
ResultVals.push_back(std::make_pair(&CI, (int)i));
2924+
} else {
2925+
ResultVals.push_back(std::make_pair(&CI, -1));
2926+
}
2927+
29202928
for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
29212929
E = Constraints.end(); I != E; ++I) {
29222930
assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
2923-
std::string c =
2924-
InterpretASMConstraint(*I);
2925-
switch(I->Type) {
2926-
default:
2927-
assert(0 && "Unknown asm constraint");
2928-
break;
2931+
std::string C = InterpretASMConstraint(*I);
2932+
if (C.empty()) continue;
2933+
2934+
switch (I->Type) {
2935+
default: assert(0 && "Unknown asm constraint");
29292936
case InlineAsm::isInput: {
2930-
if (c.size()) {
2931-
Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI));
2932-
++count; //consume arg
2933-
}
2937+
assert(ValueCount >= ResultVals.size() && "Input can't refer to result");
2938+
Value *V = CI.getOperand(ValueCount-ResultVals.size());
2939+
Input.push_back(std::make_pair(C, V));
29342940
break;
29352941
}
29362942
case InlineAsm::isOutput: {
2937-
if (c.size()) {
2938-
Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c),
2939-
count ? CI.getOperand(count) : &CI));
2940-
++count; //consume arg
2941-
}
2942-
break;
2943-
}
2944-
case InlineAsm::isClobber: {
2945-
if (c.size())
2946-
Clobber += ",\"" + c + "\"";
2943+
std::pair<Value*, int> V;
2944+
if (ValueCount < ResultVals.size())
2945+
V = ResultVals[ValueCount];
2946+
else
2947+
V = std::make_pair(CI.getOperand(ValueCount-ResultVals.size()), -1);
2948+
Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+C),
2949+
V));
29472950
break;
29482951
}
2952+
case InlineAsm::isClobber:
2953+
Clobber += ",\"" + C + "\"";
2954+
continue; // Not an actual argument.
29492955
}
2956+
++ValueCount; // Consumes an argument.
29502957
}
29512958

2952-
//fix up the asm string for gcc
2959+
// Fix up the asm string for gcc.
29532960
std::string asmstr = gccifyAsm(as->getAsmString());
29542961

29552962
Out << "__asm__ volatile (\"" << asmstr << "\"\n";
29562963
Out << " :";
2957-
for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(),
2958-
E = Output.end(); I != E; ++I) {
2959-
Out << "\"" << I->first << "\"(";
2960-
writeOperandRaw(I->second);
2964+
for (unsigned i = 0, e = Output.size(); i != e; ++i) {
2965+
if (i)
2966+
Out << ", ";
2967+
Out << "\"" << Output[i].first << "\"(";
2968+
writeOperandRaw(Output[i].second.first);
2969+
if (Output[i].second.second != -1)
2970+
Out << ".field" << Output[i].second.second; // Multiple retvals.
29612971
Out << ")";
2962-
if (I + 1 != E)
2963-
Out << ",";
29642972
}
29652973
Out << "\n :";
29662974
for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(),
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; RUN: llvm-as < %s | llc -march=c
2+
3+
declare {i32, i32} @foo()
4+
5+
define i32 @test() {
6+
%A = call {i32, i32} @foo()
7+
%B = getresult {i32, i32} %A, 0
8+
%C = getresult {i32, i32} %A, 1
9+
%D = add i32 %B, %C
10+
ret i32 %D
11+
}
12+
13+
define i32 @test2() {
14+
%A = call {i32, i32} asm sideeffect "...", "={cx},={di},~{dirflag},~{fpsr},~{flags},~{memory}"()
15+
%B = getresult {i32, i32} %A, 0
16+
%C = getresult {i32, i32} %A, 1
17+
%D = add i32 %B, %C
18+
ret i32 %D
19+
}

0 commit comments

Comments
 (0)