/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps) { // Yes hardcoded 'm' symbol. Just because it also has been hardcoded in // SelectionDAGISel (callee for this method). assert(ConstraintCode == 'm' && "Unexpected asm memory constraint"); //MachineFunction& MF = CurDAG->getMachineFunction(); MachineRegisterInfo &RI = MF->getRegInfo(); const TargetLowering* TL = MF->getTarget().getTargetLowering(); const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op); // If address operand is of PTRDISPREGS class, all is OK, then. if (RegNode && RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) { OutOps.push_back(Op); return false; } if (Op->getOpcode() == ISD::FrameIndex) { SDValue Base, Disp; if (SelectAddr(Op.getNode(), Op, Base, Disp)) { OutOps.push_back(Base); OutOps.push_back(Disp); return false; } return true; } // If Op is add reg, imm and // reg is either virtual register or register of PTRDISPREGSRegClass if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) { SDValue CopyFromRegOp = Op->getOperand(0); SDValue ImmOp = Op->getOperand(1); ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp); unsigned Reg; bool CanHandleRegImmOpt = true; CanHandleRegImmOpt &= ImmNode != 0; CanHandleRegImmOpt &= ImmNode->getAPIntValue().getZExtValue() < 64; if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) { RegisterSDNode *RegNode = cast<RegisterSDNode>(CopyFromRegOp->getOperand(1)); Reg = RegNode->getReg(); CanHandleRegImmOpt &= (TargetRegisterInfo::isVirtualRegister(Reg) || AVR::PTRDISPREGSRegClass.contains(Reg)); } else { CanHandleRegImmOpt = false; } if (CanHandleRegImmOpt) { // If we detect proper case - correct virtual register class // if needed and go to another inlineasm operand. SDValue Base, Disp; if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) { SDLoc dl(CopyFromRegOp); unsigned VReg = RI.createVirtualRegister( &AVR::PTRDISPREGSRegClass); SDValue CopyToReg = CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp); SDValue NewCopyFromRegOp = CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL->getPointerTy()); Base = NewCopyFromRegOp; } else { Base = CopyFromRegOp; } if (ImmNode->getValueType(0) != MVT::i8) { Disp = CurDAG->getTargetConstant( ImmNode->getAPIntValue().getZExtValue(), MVT::i8); } else { Disp = ImmOp; } OutOps.push_back(Base); OutOps.push_back(Disp); return false; } } // More generic case. // Create chain that puts Op into pointer register // and return that register. SDLoc dl(Op); unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass); SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op); SDValue CopyFromReg = CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL->getPointerTy()); OutOps.push_back(CopyFromReg); return false; }
bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) { assert((ConstraintCode == InlineAsm::Constraint_m || ConstraintCode == InlineAsm::Constraint_Q) && "Unexpected asm memory constraint"); MachineRegisterInfo &RI = MF->getRegInfo(); const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>(); const TargetLowering &TL = *STI.getTargetLowering(); SDLoc dl(Op); auto DL = CurDAG->getDataLayout(); const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op); // If address operand is of PTRDISPREGS class, all is OK, then. if (RegNode && RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) { OutOps.push_back(Op); return false; } if (Op->getOpcode() == ISD::FrameIndex) { SDValue Base, Disp; if (SelectAddr(Op.getNode(), Op, Base, Disp)) { OutOps.push_back(Base); OutOps.push_back(Disp); return false; } return true; } // If Op is add 'register, immediate' and // register is either virtual register or register of PTRDISPREGSRegClass if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) { SDValue CopyFromRegOp = Op->getOperand(0); SDValue ImmOp = Op->getOperand(1); ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp); unsigned Reg; bool CanHandleRegImmOpt = true; CanHandleRegImmOpt &= ImmNode != 0; CanHandleRegImmOpt &= ImmNode->getAPIntValue().getZExtValue() < 64; if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) { RegisterSDNode *RegNode = cast<RegisterSDNode>(CopyFromRegOp->getOperand(1)); Reg = RegNode->getReg(); CanHandleRegImmOpt &= (TargetRegisterInfo::isVirtualRegister(Reg) || AVR::PTRDISPREGSRegClass.contains(Reg)); } else { CanHandleRegImmOpt = false; } // If we detect proper case - correct virtual register class // if needed and go to another inlineasm operand. if (CanHandleRegImmOpt) { SDValue Base, Disp; if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) { SDLoc dl(CopyFromRegOp); unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass); SDValue CopyToReg = CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp); SDValue NewCopyFromRegOp = CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL)); Base = NewCopyFromRegOp; } else { Base = CopyFromRegOp; } if (ImmNode->getValueType(0) != MVT::i8) { Disp = CurDAG->getTargetConstant(ImmNode->getAPIntValue().getZExtValue(), dl, MVT::i8); } else { Disp = ImmOp; } OutOps.push_back(Base); OutOps.push_back(Disp); return false; } } // More generic case. // Create chain that puts Op into pointer register // and return that register. unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass); SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op); SDValue CopyFromReg = CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL)); OutOps.push_back(CopyFromReg); return false; }