mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
split register class handling from explicit physreg handling.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26308 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
16d597a20d
commit
1efa40f6a4
@ -481,6 +481,7 @@ public:
|
||||
//
|
||||
|
||||
enum ConstraintType {
|
||||
C_Register, // Constraint represents a single register.
|
||||
C_RegisterClass, // Constraint represents one or more registers.
|
||||
C_Other, // Something else.
|
||||
C_Unknown // Unsupported constraint.
|
||||
@ -491,13 +492,22 @@ public:
|
||||
/// constraint it is for this target.
|
||||
virtual ConstraintType getConstraintType(char ConstraintLetter) const;
|
||||
|
||||
/// getRegForInlineAsmConstraint - Given a constraint letter or register
|
||||
/// name (e.g. "r" or "edx"), return a list of registers that can be used to
|
||||
/// satisfy the constraint. This should only be used for physregs and
|
||||
/// C_RegisterClass constraints.
|
||||
|
||||
/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"),
|
||||
/// return a list of registers that can be used to satisfy the constraint.
|
||||
/// This should only be used for C_RegisterClass constraints.
|
||||
virtual std::vector<unsigned>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
|
||||
/// getRegForInlineAsmConstraint - Given a physical register constraint (e.g.
|
||||
/// {edx}), return the register number and the register class for the
|
||||
/// register. This should only be used for C_Register constraints. On error,
|
||||
/// this returns a register number of 0.
|
||||
virtual std::pair<unsigned, const TargetRegisterClass*>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
|
||||
|
||||
/// isOperandValidForConstraint - Return true if the specified SDOperand is
|
||||
/// valid for the specified target constraint letter.
|
||||
|
@ -1187,6 +1187,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||
bool hasSideEffects = IA->hasSideEffects();
|
||||
|
||||
std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
|
||||
std::vector<MVT::ValueType> ConstraintVTs;
|
||||
|
||||
/// AsmNodeOperands - A list of pairs. The first element is a register, the
|
||||
/// second is a bitfield where bit #0 is set if it is a use and bit #1 is set
|
||||
@ -1203,14 +1204,43 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||
// could let the LLVM RA do its thing, but we currently don't. Do a prepass
|
||||
// over the constraints, collecting fixed registers that we know we can't use.
|
||||
std::set<unsigned> OutputRegs, InputRegs;
|
||||
unsigned OpNum = 1;
|
||||
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
|
||||
assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
|
||||
std::string &ConstraintCode = Constraints[i].Codes[0];
|
||||
|
||||
std::vector<unsigned> Regs =
|
||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, MVT::Other);
|
||||
if (Regs.size() != 1) continue; // Not assigned a fixed reg.
|
||||
unsigned TheReg = Regs[0];
|
||||
MVT::ValueType OpVT;
|
||||
|
||||
// Compute the value type for each operand and add it to ConstraintVTs.
|
||||
switch (Constraints[i].Type) {
|
||||
case InlineAsm::isOutput:
|
||||
if (!Constraints[i].isIndirectOutput) {
|
||||
assert(I.getType() != Type::VoidTy && "Bad inline asm!");
|
||||
OpVT = TLI.getValueType(I.getType());
|
||||
} else {
|
||||
Value *CallOperand = I.getOperand(OpNum);
|
||||
const Type *OpTy = CallOperand->getType();
|
||||
OpVT = TLI.getValueType(cast<PointerType>(OpTy)->getElementType());
|
||||
OpNum++; // Consumes a call operand.
|
||||
}
|
||||
break;
|
||||
case InlineAsm::isInput:
|
||||
OpVT = TLI.getValueType(I.getOperand(OpNum)->getType());
|
||||
OpNum++; // Consumes a call operand.
|
||||
break;
|
||||
case InlineAsm::isClobber:
|
||||
OpVT = MVT::Other;
|
||||
break;
|
||||
}
|
||||
|
||||
ConstraintVTs.push_back(OpVT);
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass*> Reg =
|
||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, OpVT);
|
||||
if (Reg.first == 0) continue; // Not assigned a fixed reg.
|
||||
unsigned TheReg = Reg.first;
|
||||
|
||||
// FIXME: Handle expanded physreg refs!
|
||||
|
||||
switch (Constraints[i].Type) {
|
||||
case InlineAsm::isOutput:
|
||||
@ -1221,15 +1251,15 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
|
||||
InputRegs.insert(TheReg);
|
||||
break;
|
||||
case InlineAsm::isInput:
|
||||
// We can't assign any other input to this register.
|
||||
InputRegs.insert(TheReg);
|
||||
break;
|
||||
case InlineAsm::isClobber:
|
||||
// Clobbered regs cannot be used as inputs or outputs.
|
||||
InputRegs.insert(TheReg);
|
||||
OutputRegs.insert(TheReg);
|
||||
break;
|
||||
case InlineAsm::isInput:
|
||||
// We can't assign any other input to this register.
|
||||
InputRegs.insert(TheReg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1238,28 +1268,32 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||
unsigned RetValReg = 0;
|
||||
std::vector<std::pair<unsigned, Value*> > IndirectStoresToEmit;
|
||||
bool FoundOutputConstraint = false;
|
||||
unsigned OpNum = 1;
|
||||
OpNum = 1;
|
||||
|
||||
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
|
||||
assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
|
||||
std::string &ConstraintCode = Constraints[i].Codes[0];
|
||||
Value *CallOperand = I.getOperand(OpNum);
|
||||
MVT::ValueType CallOpVT = TLI.getValueType(CallOperand->getType());
|
||||
|
||||
switch (Constraints[i].Type) {
|
||||
case InlineAsm::isOutput: {
|
||||
// Copy the output from the appropriate register.
|
||||
std::vector<unsigned> Regs =
|
||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, CallOpVT);
|
||||
|
||||
// Find a regsister that we can use.
|
||||
// Copy the output from the appropriate register. Find a regsister that
|
||||
// we can use.
|
||||
|
||||
// Check to see if this is a physreg reference.
|
||||
std::pair<unsigned, const TargetRegisterClass*> PhysReg =
|
||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, ConstraintVTs[i]);
|
||||
unsigned DestReg;
|
||||
if (Regs.size() == 1)
|
||||
DestReg = Regs[0];
|
||||
if (PhysReg.first)
|
||||
DestReg = PhysReg.first;
|
||||
else {
|
||||
bool UsesInputRegister = false;
|
||||
std::vector<unsigned> Regs =
|
||||
TLI.getRegClassForInlineAsmConstraint(ConstraintCode,
|
||||
ConstraintVTs[i]);
|
||||
|
||||
// If this is an early-clobber output, or if there is an input
|
||||
// constraint that matches this, we need to reserve the input register
|
||||
// so no other inputs allocate to it.
|
||||
bool UsesInputRegister = false;
|
||||
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
|
||||
UsesInputRegister = true;
|
||||
DestReg = GetAvailableRegister(true, UsesInputRegister,
|
||||
@ -1276,24 +1310,21 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||
assert(I.getType() != Type::VoidTy && "Bad inline asm!");
|
||||
|
||||
RetValReg = DestReg;
|
||||
OpTy = I.getType();
|
||||
} else {
|
||||
Value *CallOperand = I.getOperand(OpNum);
|
||||
IndirectStoresToEmit.push_back(std::make_pair(DestReg, CallOperand));
|
||||
OpTy = CallOperand->getType();
|
||||
OpTy = cast<PointerType>(OpTy)->getElementType();
|
||||
OpNum++; // Consumes a call operand.
|
||||
}
|
||||
|
||||
// Add information to the INLINEASM node to know that this register is
|
||||
// set.
|
||||
AsmNodeOperands.push_back(DAG.getRegister(DestReg,
|
||||
TLI.getValueType(OpTy)));
|
||||
AsmNodeOperands.push_back(DAG.getRegister(DestReg, ConstraintVTs[i]));
|
||||
AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
|
||||
|
||||
break;
|
||||
}
|
||||
case InlineAsm::isInput: {
|
||||
const Type *OpTy = CallOperand->getType();
|
||||
Value *CallOperand = I.getOperand(OpNum);
|
||||
OpNum++; // Consumes a call operand.
|
||||
|
||||
unsigned SrcReg;
|
||||
@ -1306,33 +1337,45 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||
// just use its register.
|
||||
unsigned OperandNo = atoi(ConstraintCode.c_str());
|
||||
SrcReg = cast<RegisterSDNode>(AsmNodeOperands[OperandNo*2+2])->getReg();
|
||||
ResOp = DAG.getRegister(SrcReg, CallOpVT);
|
||||
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
||||
ResOpType = 1;
|
||||
|
||||
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
||||
Flag = Chain.getValue(1);
|
||||
} else {
|
||||
TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
|
||||
TargetLowering::ConstraintType CTy = TargetLowering::C_Register;
|
||||
if (ConstraintCode.size() == 1) // not a physreg name.
|
||||
CTy = TLI.getConstraintType(ConstraintCode[0]);
|
||||
|
||||
switch (CTy) {
|
||||
default: assert(0 && "Unknown constraint type! FAIL!");
|
||||
case TargetLowering::C_Register: {
|
||||
std::pair<unsigned, const TargetRegisterClass*> PhysReg =
|
||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, ConstraintVTs[i]);
|
||||
// FIXME: should be match fail.
|
||||
assert(PhysReg.first && "Unknown physical register name!");
|
||||
SrcReg = PhysReg.first;
|
||||
|
||||
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
||||
Flag = Chain.getValue(1);
|
||||
|
||||
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
||||
ResOpType = 1;
|
||||
break;
|
||||
}
|
||||
case TargetLowering::C_RegisterClass: {
|
||||
// Copy the input into the appropriate register.
|
||||
std::vector<unsigned> Regs =
|
||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, CallOpVT);
|
||||
if (Regs.size() == 1)
|
||||
SrcReg = Regs[0];
|
||||
else
|
||||
SrcReg = GetAvailableRegister(false, true, Regs,
|
||||
OutputRegs, InputRegs);
|
||||
TLI.getRegClassForInlineAsmConstraint(ConstraintCode,
|
||||
ConstraintVTs[i]);
|
||||
SrcReg = GetAvailableRegister(false, true, Regs,
|
||||
OutputRegs, InputRegs);
|
||||
// FIXME: should be match fail.
|
||||
assert(SrcReg && "Wasn't able to allocate register!");
|
||||
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
||||
Flag = Chain.getValue(1);
|
||||
|
||||
ResOp = DAG.getRegister(SrcReg, CallOpVT);
|
||||
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
||||
ResOpType = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -745,24 +745,34 @@ bool TargetLowering::isOperandValidForConstraint(SDOperand Op,
|
||||
|
||||
|
||||
std::vector<unsigned> TargetLowering::
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const {
|
||||
return std::vector<unsigned>();
|
||||
}
|
||||
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass*> TargetLowering::
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const {
|
||||
// Not a physreg, must not be a register reference or something.
|
||||
if (Constraint[0] != '{') return std::vector<unsigned>();
|
||||
if (Constraint[0] != '{')
|
||||
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
|
||||
assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?");
|
||||
|
||||
// Remove the braces from around the name.
|
||||
std::string RegName(Constraint.begin()+1, Constraint.end()-1);
|
||||
|
||||
// Scan to see if this constraint is a register name.
|
||||
|
||||
// Figure out which register class contains this reg.
|
||||
const MRegisterInfo *RI = TM.getRegisterInfo();
|
||||
for (unsigned i = 1, e = RI->getNumRegs(); i != e; ++i) {
|
||||
if (const char *Name = RI->get(i).Name)
|
||||
if (StringsEqualNoCase(RegName, Name))
|
||||
return std::vector<unsigned>(1, i);
|
||||
for (MRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
|
||||
E = RI->regclass_end(); RCI != E; ++RCI) {
|
||||
const TargetRegisterClass *RC = *RCI;
|
||||
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
|
||||
I != E; ++I) {
|
||||
if (StringsEqualNoCase(RegName, RI->get(*I).Name)) {
|
||||
return std::make_pair(*I, RC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown physreg.
|
||||
return std::vector<unsigned>();
|
||||
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
|
||||
}
|
||||
|
||||
|
@ -999,8 +999,8 @@ PPCTargetLowering::getConstraintType(char ConstraintLetter) const {
|
||||
|
||||
|
||||
std::vector<unsigned> PPCTargetLowering::
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const {
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const {
|
||||
if (Constraint.size() == 1) {
|
||||
switch (Constraint[0]) { // GCC RS6000 Constraint Letters
|
||||
default: break; // Unknown constriant letter
|
||||
@ -1051,8 +1051,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle explicit register names.
|
||||
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
|
||||
return std::vector<unsigned>();
|
||||
}
|
||||
|
||||
// isOperandValidForConstraint
|
||||
|
@ -99,8 +99,8 @@ namespace llvm {
|
||||
|
||||
ConstraintType getConstraintType(char ConstraintLetter) const;
|
||||
std::vector<unsigned>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
bool isOperandValidForConstraint(SDOperand Op, char ConstraintLetter);
|
||||
};
|
||||
}
|
||||
|
@ -1961,8 +1961,8 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
|
||||
}
|
||||
|
||||
std::vector<unsigned> X86TargetLowering::
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const {
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const {
|
||||
if (Constraint.size() == 1) {
|
||||
// FIXME: not handling fp-stack yet!
|
||||
// FIXME: not handling MMX registers yet ('y' constraint).
|
||||
@ -1993,6 +1993,5 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle explicit register names.
|
||||
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
|
||||
return std::vector<unsigned>();
|
||||
}
|
||||
|
@ -224,8 +224,8 @@ namespace llvm {
|
||||
SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG);
|
||||
|
||||
std::vector<unsigned>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT::ValueType VT) const;
|
||||
private:
|
||||
// C Calling Convention implementation.
|
||||
std::vector<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG);
|
||||
|
Loading…
Reference in New Issue
Block a user