mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 15:17:25 +00:00
Rewrite a bunch of the CBE's inline asm code, giving it the
ability to handle indirect input operands. This fixes PR2407. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51952 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -2956,10 +2956,6 @@ static std::string gccifyAsm(std::string asmstr) {
|
|||||||
void CWriter::visitInlineAsm(CallInst &CI) {
|
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, std::pair<Value*, int> > > Output;
|
|
||||||
std::string Clobber;
|
|
||||||
unsigned ValueCount = 0;
|
|
||||||
|
|
||||||
std::vector<std::pair<Value*, int> > ResultVals;
|
std::vector<std::pair<Value*, int> > ResultVals;
|
||||||
if (CI.getType() == Type::VoidTy)
|
if (CI.getType() == Type::VoidTy)
|
||||||
@@ -2971,61 +2967,103 @@ void CWriter::visitInlineAsm(CallInst &CI) {
|
|||||||
ResultVals.push_back(std::make_pair(&CI, -1));
|
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(),
|
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");
|
assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
|
||||||
std::string C = InterpretASMConstraint(*I);
|
std::string C = InterpretASMConstraint(*I);
|
||||||
if (C.empty()) continue;
|
if (C.empty()) continue;
|
||||||
|
|
||||||
switch (I->Type) {
|
if (!IsFirst) {
|
||||||
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.
|
|
||||||
}
|
|
||||||
++ValueCount; // Consumes an argument.
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
Out << ", ";
|
Out << ", ";
|
||||||
Out << "\"" << Output[i].first << "\"("
|
IsFirst = false;
|
||||||
<< GetValueName(Output[i].second.first);
|
}
|
||||||
if (Output[i].second.second != -1)
|
|
||||||
Out << ".field" << Output[i].second.second; // Multiple retvals.
|
// 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 << ")";
|
Out << ")";
|
||||||
|
++ValueCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convert over all the input constraints.
|
||||||
Out << "\n :";
|
Out << "\n :";
|
||||||
for (unsigned i = 0, e = Input.size(); i != e; ++i) {
|
IsFirst = true;
|
||||||
if (i)
|
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 << ", ";
|
||||||
Out << "\"" << Input[i].first << "\"(";
|
IsFirst = false;
|
||||||
writeOperand(Input[i].second);
|
}
|
||||||
|
|
||||||
|
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 << ")";
|
||||||
}
|
}
|
||||||
if (Clobber.size())
|
|
||||||
Out << "\n :" << Clobber.substr(1);
|
// 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 << ", ";
|
||||||
|
IsFirst = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Out << '\"' << C << '"';
|
||||||
|
}
|
||||||
|
|
||||||
Out << ")";
|
Out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
test/CodeGen/CBackend/2008-06-04-IndirectMem.ll
Normal file
12
test/CodeGen/CBackend/2008-06-04-IndirectMem.ll
Normal file
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user