summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTanya Lattner <tonic@nondot.org>2008-06-04 20:21:59 +0000
committerTanya Lattner <tonic@nondot.org>2008-06-04 20:21:59 +0000
commitb666e3edcb3dd78da6eea9f3b3de0e0fae0f3762 (patch)
tree079384517c028a59ee3ec8483f2f2564f5d1e2ae
parent99b648afaf162cca02fd9ba728715c96ee7725d2 (diff)
downloadllvm-b666e3edcb3dd78da6eea9f3b3de0e0fae0f3762.tar.gz
Merge from mainline to fix PR2407.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_23@51962 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/CBackend/CBackend.cpp128
-rw-r--r--test/CodeGen/CBackend/2008-06-04-IndirectMem.ll12
2 files changed, 95 insertions, 45 deletions
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 84d9206da75f..92fc40bcc6fc 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -2936,10 +2936,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)
@@ -2951,61 +2947,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 000000000000..a2c10469bd7f
--- /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
+}