llvm.org GIT mirror llvm / b649740
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_23@51437 91177308-0d34-0410-b5e6-96231b3b80d8 Tanya Lattner 12 years ago
2 changed file(s) with 65 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
25912591 }
25922592
25932593 void CWriter::visitCallInst(CallInst &I) {
2594 //check if we have inline asm
2595 if (isInlineAsm(I)) {
2596 visitInlineAsm(I);
2597 return;
2598 }
2594 if (isa(I.getOperand(0)))
2595 return visitInlineAsm(I);
25992596
26002597 bool WroteCallee = false;
26012598
29132910 InlineAsm* as = cast(CI.getOperand(0));
29142911 std::vector Constraints = as->ParseConstraints();
29152912 std::vector > Input;
2916 std::vectorValue*> > Output;
2913 std::vectorstd::pair > > Output;
29172914 std::string Clobber;
2918 int count = CI.getType() == Type::VoidTy ? 1 : 0;
2915 unsigned ValueCount = 0;
2916
2917 std::vector > ResultVals;
2918 if (CI.getType() == Type::VoidTy)
2919 ;
2920 else if (const StructType *ST = dyn_cast(CI.getType())) {
2921 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
2922 ResultVals.push_back(std::make_pair(&CI, (int)i));
2923 } else {
2924 ResultVals.push_back(std::make_pair(&CI, -1));
2925 }
2926
29192927 for (std::vector::iterator I = Constraints.begin(),
29202928 E = Constraints.end(); I != E; ++I) {
29212929 assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
2922 std::string c =
2923 InterpretASMConstraint(*I);
2924 switch(I->Type) {
2925 default:
2926 assert(0 && "Unknown asm constraint");
2930 std::string C = InterpretASMConstraint(*I);
2931 if (C.empty()) continue;
2932
2933 switch (I->Type) {
2934 default: assert(0 && "Unknown asm constraint");
2935 case InlineAsm::isInput: {
2936 assert(ValueCount >= ResultVals.size() && "Input can't refer to result");
2937 Value *V = CI.getOperand(ValueCount-ResultVals.size());
2938 Input.push_back(std::make_pair(C, V));
29272939 break;
2928 case InlineAsm::isInput: {
2929 if (c.size()) {
2930 Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI));
2931 ++count; //consume arg
2932 }
2940 }
2941 case InlineAsm::isOutput: {
2942 std::pair V;
2943 if (ValueCount < ResultVals.size())
2944 V = ResultVals[ValueCount];
2945 else
2946 V = std::make_pair(CI.getOperand(ValueCount-ResultVals.size()), -1);
2947 Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+C),
2948 V));
29332949 break;
29342950 }
2935 case InlineAsm::isOutput: {
2936 if (c.size()) {
2937 Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c),
2938 count ? CI.getOperand(count) : &CI));
2939 ++count; //consume arg
2940 }
2941 break;
2942 }
2943 case InlineAsm::isClobber: {
2944 if (c.size())
2945 Clobber += ",\"" + c + "\"";
2946 break;
2947 }
2948 }
2951 case InlineAsm::isClobber:
2952 Clobber += ",\"" + C + "\"";
2953 continue; // Not an actual argument.
2954 }
2955 ++ValueCount; // Consumes an argument.
29492956 }
29502957
2951 //fix up the asm string for gcc
2958 // Fix up the asm string for gcc.
29522959 std::string asmstr = gccifyAsm(as->getAsmString());
29532960
29542961 Out << "__asm__ volatile (\"" << asmstr << "\"\n";
29552962 Out << " :";
2956 for (std::vector >::iterator I =Output.begin(),
2957 E = Output.end(); I != E; ++I) {
2958 Out << "\"" << I->first << "\"(";
2959 writeOperandRaw(I->second);
2963 for (unsigned i = 0, e = Output.size(); i != e; ++i) {
2964 if (i)
2965 Out << ", ";
2966 Out << "\"" << Output[i].first << "\"(";
2967 writeOperandRaw(Output[i].second.first);
2968 if (Output[i].second.second != -1)
2969 Out << ".field" << Output[i].second.second; // Multiple retvals.
29602970 Out << ")";
2961 if (I + 1 != E)
2962 Out << ",";
29632971 }
29642972 Out << "\n :";
29652973 for (std::vector >::iterator I = Input.begin(),
0 ; RUN: llvm-as < %s | llc -march=c
1
2 declare {i32, i32} @foo()
3
4 define i32 @test() {
5 %A = call {i32, i32} @foo()
6 %B = getresult {i32, i32} %A, 0
7 %C = getresult {i32, i32} %A, 1
8 %D = add i32 %B, %C
9 ret i32 %D
10 }
11
12 define i32 @test2() {
13 %A = call {i32, i32} asm sideeffect "...", "={cx},={di},~{dirflag},~{fpsr},~{flags},~{memory}"()
14 %B = getresult {i32, i32} %A, 0
15 %C = getresult {i32, i32} %A, 1
16 %D = add i32 %B, %C
17 ret i32 %D
18 }