diff options
-rw-r--r-- | lib/Target/CBackend/CBackend.cpp | 128 | ||||
-rw-r--r-- | test/CodeGen/CBackend/2008-06-04-IndirectMem.ll | 12 |
2 files changed, 95 insertions, 45 deletions
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 16abb05..6829218 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -2956,10 +2956,6 @@ static std::string gccifyAsm(std::string asmstr) { 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, std::pair<Value*, int> > > Output; - std::string Clobber; - unsigned ValueCount = 0; std::vector<std::pair<Value*, int> > ResultVals; if (CI.getType() == Type::VoidTy) @@ -2971,61 +2967,103 @@ void CWriter::visitInlineAsm(CallInst &CI) { ResultVals.push_back(std::make_pair(&CI, -1)); } + // Fix up the asm string for gcc and emit it. + Out << "__asm__ volatile (\"" << gccifyAsm(as->getAsmString()) << "\"\n"; + Out << " :"; + + unsigned ValueCount = 0; + bool IsFirst = true; + + // Convert over all the output constraints. for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(), - E = Constraints.end(); I != E; ++I) { + E = Constraints.end(); I != E; ++I) { + + if (I->Type != InlineAsm::isOutput) { + ++ValueCount; + continue; // Ignore non-output constraints. + } + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); std::string C = InterpretASMConstraint(*I); if (C.empty()) continue; - switch (I->Type) { - default: assert(0 && "Unknown asm constraint"); - case InlineAsm::isInput: { - assert(ValueCount >= ResultVals.size() && "Input can't refer to result"); - Value *V = CI.getOperand(ValueCount-ResultVals.size()+1); - Input.push_back(std::make_pair(C, V)); - break; - } - case InlineAsm::isOutput: { - std::pair<Value*, int> V; - if (ValueCount < ResultVals.size()) - V = ResultVals[ValueCount]; - else - V = std::make_pair(CI.getOperand(ValueCount-ResultVals.size()+1), -1); - Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+C), - V)); - break; - } - case InlineAsm::isClobber: - Clobber += ",\"" + C + "\""; - continue; // Not an actual argument. + if (!IsFirst) { + Out << ", "; + IsFirst = false; } - ++ValueCount; // Consumes an argument. + + // Unpack the dest. + Value *DestVal; + int DestValNo = -1; + + if (ValueCount < ResultVals.size()) { + DestVal = ResultVals[ValueCount].first; + DestValNo = ResultVals[ValueCount].second; + } else + DestVal = CI.getOperand(ValueCount-ResultVals.size()+1); + + if (I->isEarlyClobber) + C = "&"+C; + + Out << "\"=" << C << "\"(" << GetValueName(DestVal); + if (DestValNo != -1) + Out << ".field" << DestValNo; // Multiple retvals. + Out << ")"; + ++ValueCount; } - // Fix up the asm string for gcc. - std::string asmstr = gccifyAsm(as->getAsmString()); - Out << "__asm__ volatile (\"" << asmstr << "\"\n"; - Out << " :"; - for (unsigned i = 0, e = Output.size(); i != e; ++i) { - if (i) + // Convert over all the input constraints. + Out << "\n :"; + IsFirst = true; + ValueCount = 0; + for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + if (I->Type != InlineAsm::isInput) { + ++ValueCount; + continue; // Ignore non-input constraints. + } + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { Out << ", "; - Out << "\"" << Output[i].first << "\"(" - << GetValueName(Output[i].second.first); - if (Output[i].second.second != -1) - Out << ".field" << Output[i].second.second; // Multiple retvals. + IsFirst = false; + } + + assert(ValueCount >= ResultVals.size() && "Input can't refer to result"); + Value *SrcVal = CI.getOperand(ValueCount-ResultVals.size()+1); + + Out << "\"" << C << "\"("; + if (!I->isIndirect) + writeOperand(SrcVal); + else + writeOperandDeref(SrcVal); Out << ")"; } - Out << "\n :"; - for (unsigned i = 0, e = Input.size(); i != e; ++i) { - if (i) + + // Convert over the clobber constraints. + IsFirst = true; + ValueCount = 0; + for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + if (I->Type != InlineAsm::isClobber) + continue; // Ignore non-input constraints. + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { Out << ", "; - Out << "\"" << Input[i].first << "\"("; - writeOperand(Input[i].second); - Out << ")"; + IsFirst = false; + } + + Out << '\"' << C << '"'; } - if (Clobber.size()) - Out << "\n :" << Clobber.substr(1); + Out << ")"; } diff --git a/test/CodeGen/CBackend/2008-06-04-IndirectMem.ll b/test/CodeGen/CBackend/2008-06-04-IndirectMem.ll new file mode 100644 index 0000000..a2c1046 --- /dev/null +++ b/test/CodeGen/CBackend/2008-06-04-IndirectMem.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llc -march=c | grep {"m"(llvm_cbe_newcw))} +; PR2407 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" +target triple = "i386-pc-linux-gnu" + +define void @foo() { + %newcw = alloca i16 ; <i16*> [#uses=2] + call void asm sideeffect "fldcw $0", "*m,~{dirflag},~{fpsr},~{flags}"( i16* +%newcw ) nounwind + ret void +} |