SDOperand AlphaTargetLowering::CustomPromoteOperation(SDOperand Op, SelectionDAG &DAG) { assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::VAARG && "Unknown node to custom promote!"); // The code in LowerOperation already handles i32 vaarg return LowerOperation(Op, DAG); }
/// LowerOperation - Provide custom lowering hooks for some operations. /// SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Wasn't expecting to be able to lower this!"); case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsBase, VarArgsOffset); case ISD::RET: return LowerRET(Op,DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SINT_TO_FP: { assert(MVT::i64 == Op.getOperand(0).getValueType() && "Unhandled SINT_TO_FP type in custom expander!"); SDOperand LD; bool isDouble = MVT::f64 == Op.getValueType(); LD = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0)); SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, isDouble?MVT::f64:MVT::f32, LD); return FP; } case ISD::FP_TO_SINT: { bool isDouble = MVT::f64 == Op.getOperand(0).getValueType(); SDOperand src = Op.getOperand(0); if (!isDouble) //Promote src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, src); src = DAG.getNode(AlphaISD::CVTTQ_, MVT::f64, src); return DAG.getNode(ISD::BIT_CONVERT, MVT::i64, src); } case ISD::ConstantPool: { ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); Constant *C = CP->getConstVal(); SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, CPI, DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, CPI, Hi); return Lo; } case ISD::GlobalAddress: { GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); GlobalValue *GV = GSDN->getGlobal(); SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset()); // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) { if (GV->hasInternalLinkage()) { SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, GA, DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, GA, Hi); return Lo; } else return DAG.getNode(AlphaISD::RelLit, MVT::i64, GA, DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); } case ISD::ExternalSymbol: { return DAG.getNode(AlphaISD::RelLit, MVT::i64, DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op) ->getSymbol(), MVT::i64), DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); } case ISD::UREM: case ISD::SREM: //Expand only on constant case if (Op.getOperand(1).getOpcode() == ISD::Constant) { MVT::ValueType VT = Op.Val->getValueType(0); SDOperand Tmp1 = Op.Val->getOpcode() == ISD::UREM ? BuildUDIV(Op.Val, DAG, NULL) : BuildSDIV(Op.Val, DAG, NULL); Tmp1 = DAG.getNode(ISD::MUL, VT, Tmp1, Op.getOperand(1)); Tmp1 = DAG.getNode(ISD::SUB, VT, Op.getOperand(0), Tmp1); return Tmp1; } //fall through case ISD::SDIV: case ISD::UDIV: if (MVT::isInteger(Op.getValueType())) { if (Op.getOperand(1).getOpcode() == ISD::Constant) return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.Val, DAG, NULL) : BuildUDIV(Op.Val, DAG, NULL); const char* opstr = 0; switch (Op.getOpcode()) { case ISD::UREM: opstr = "__remqu"; break; case ISD::SREM: opstr = "__remq"; break; case ISD::UDIV: opstr = "__divqu"; break; case ISD::SDIV: opstr = "__divq"; break; } SDOperand Tmp1 = Op.getOperand(0), Tmp2 = Op.getOperand(1), Addr = DAG.getExternalSymbol(opstr, MVT::i64); return DAG.getNode(AlphaISD::DivCall, MVT::i64, Addr, Tmp1, Tmp2); } break; case ISD::VAARG: { SDOperand Chain = Op.getOperand(0); SDOperand VAListP = Op.getOperand(1); SrcValueSDNode *VAListS = cast<SrcValueSDNode>(Op.getOperand(2)); SDOperand Base = DAG.getLoad(MVT::i64, Chain, VAListP, VAListS->getValue(), VAListS->getOffset()); SDOperand Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); SDOperand Offset = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Base.getValue(1), Tmp, NULL, 0, MVT::i32); SDOperand DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset); if (MVT::isFloatingPoint(Op.getValueType())) { //if fp && Offset < 6*8, then subtract 6*8 from DataPtr SDOperand FPDataPtr = DAG.getNode(ISD::SUB, MVT::i64, DataPtr, DAG.getConstant(8*6, MVT::i64)); SDOperand CC = DAG.getSetCC(MVT::i64, Offset, DAG.getConstant(8*6, MVT::i64), ISD::SETLT); DataPtr = DAG.getNode(ISD::SELECT, MVT::i64, CC, FPDataPtr, DataPtr); } SDOperand NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset, DAG.getConstant(8, MVT::i64)); SDOperand Update = DAG.getTruncStore(Offset.getValue(1), NewOffset, Tmp, NULL, 0, MVT::i32); SDOperand Result; if (Op.getValueType() == MVT::i32) Result = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Update, DataPtr, NULL, 0, MVT::i32); else Result = DAG.getLoad(Op.getValueType(), Update, DataPtr, NULL, 0); return Result; } case ISD::VACOPY: { SDOperand Chain = Op.getOperand(0); SDOperand DestP = Op.getOperand(1); SDOperand SrcP = Op.getOperand(2); SrcValueSDNode *DestS = cast<SrcValueSDNode>(Op.getOperand(3)); SrcValueSDNode *SrcS = cast<SrcValueSDNode>(Op.getOperand(4)); SDOperand Val = DAG.getLoad(getPointerTy(), Chain, SrcP, SrcS->getValue(), SrcS->getOffset()); SDOperand Result = DAG.getStore(Val.getValue(1), Val, DestP, DestS->getValue(), DestS->getOffset()); SDOperand NP = DAG.getNode(ISD::ADD, MVT::i64, SrcP, DAG.getConstant(8, MVT::i64)); Val = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Result, NP, NULL,0, MVT::i32); SDOperand NPD = DAG.getNode(ISD::ADD, MVT::i64, DestP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(Val.getValue(1), Val, NPD, NULL, 0, MVT::i32); } case ISD::VASTART: { SDOperand Chain = Op.getOperand(0); SDOperand VAListP = Op.getOperand(1); SrcValueSDNode *VAListS = cast<SrcValueSDNode>(Op.getOperand(2)); // vastart stores the address of the VarArgsBase and VarArgsOffset SDOperand FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); SDOperand S1 = DAG.getStore(Chain, FR, VAListP, VAListS->getValue(), VAListS->getOffset()); SDOperand SA2 = DAG.getNode(ISD::ADD, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(S1, DAG.getConstant(VarArgsOffset, MVT::i64), SA2, NULL, 0, MVT::i32); } case ISD::RETURNADDR: return DAG.getNode(AlphaISD::GlobalRetAddr, MVT::i64); //FIXME: implement case ISD::FRAMEADDR: break; } return SDOperand(); }
SDOperand IA64TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Should not custom lower this!"); case ISD::GlobalTLSAddress: assert(0 && "TLS not implemented for IA64."); case ISD::RET: { SDOperand AR_PFSVal, Copy; switch(Op.getNumOperands()) { default: assert(0 && "Do not know how to return this many arguments!"); abort(); case 1: AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64); AR_PFSVal = DAG.getCopyToReg(AR_PFSVal.getValue(1), IA64::AR_PFS, AR_PFSVal); return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, AR_PFSVal); case 3: { // Copy the result into the output register & restore ar.pfs MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); unsigned ArgReg = MVT::isInteger(ArgVT) ? IA64::r8 : IA64::F8; AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64); Copy = DAG.getCopyToReg(AR_PFSVal.getValue(1), ArgReg, Op.getOperand(1), SDOperand()); AR_PFSVal = DAG.getCopyToReg(Copy.getValue(0), IA64::AR_PFS, AR_PFSVal, Copy.getValue(1)); return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, AR_PFSVal, AR_PFSVal.getValue(1)); } } return SDOperand(); } case ISD::VAARG: { MVT::ValueType VT = getPointerTy(); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); SDOperand VAList = DAG.getLoad(VT, Op.getOperand(0), Op.getOperand(1), SV, 0); // Increment the pointer, VAList, to the next vaarg SDOperand VAIncr = DAG.getNode(ISD::ADD, VT, VAList, DAG.getConstant(MVT::getSizeInBits(VT)/8, VT)); // Store the incremented VAList to the legalized pointer VAIncr = DAG.getStore(VAList.getValue(1), VAIncr, Op.getOperand(1), SV, 0); // Load the actual argument out of the pointer VAList return DAG.getLoad(Op.getValueType(), VAIncr, VAList, NULL, 0); } case ISD::VASTART: { // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0); } // Frame & Return address. Currently unimplemented case ISD::RETURNADDR: break; case ISD::FRAMEADDR: break; } return SDOperand(); }