diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 34e20903fa7..2f83eaaa3cd 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -98,7 +98,7 @@ public: /// reflect the change. typedef bool CCAssignFn(unsigned ValNo, MVT::ValueType ValVT, MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo, - ISD::ParamFlags::ParamFlagsTy ArgFlags, CCState &State); + ISD::ArgFlagsTy ArgFlags, CCState &State); /// CCState - This class holds information needed while lowering arguments and @@ -197,8 +197,7 @@ public: // parameter attribute. void HandleByVal(unsigned ValNo, MVT::ValueType ValVT, MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo, - int MinSize, int MinAlign, - ISD::ParamFlags::ParamFlagsTy ArgFlags); + int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); private: /// MarkAllocated - Mark a register and all of its aliases as allocated. diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 6e395a5b7fd..28535d12737 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -219,6 +219,7 @@ public: SDOperand getBasicBlock(MachineBasicBlock *MBB); SDOperand getExternalSymbol(const char *Sym, MVT::ValueType VT); SDOperand getTargetExternalSymbol(const char *Sym, MVT::ValueType VT); + SDOperand getArgFlags(ISD::ArgFlagsTy Flags); SDOperand getValueType(MVT::ValueType); SDOperand getRegister(unsigned Reg, MVT::ValueType VT); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 4f2574efc1e..3b718b605a8 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -56,31 +56,6 @@ struct SDVTList { /// SelectionDAG node types and value types. /// namespace ISD { - namespace ParamFlags { - typedef uint64_t ParamFlagsTy; - - const ParamFlagsTy NoFlagSet = 0ULL; - const ParamFlagsTy ZExt = 1ULL<<0; ///< Zero extended - const ParamFlagsTy ZExtOffs = 0; - const ParamFlagsTy SExt = 1ULL<<1; ///< Sign extended - const ParamFlagsTy SExtOffs = 1; - const ParamFlagsTy InReg = 1ULL<<2; ///< Passed in register - const ParamFlagsTy InRegOffs = 2; - const ParamFlagsTy StructReturn = 1ULL<<3; ///< Hidden struct-ret ptr - const ParamFlagsTy StructReturnOffs = 3; - const ParamFlagsTy ByVal = 1ULL<<4; ///< Struct passed by value - const ParamFlagsTy ByValOffs = 4; - const ParamFlagsTy Nest = 1ULL<<5; ///< Nested fn static chain - const ParamFlagsTy NestOffs = 5; - const ParamFlagsTy ByValAlign = 0xFULL << 6; //< Struct alignment - const ParamFlagsTy ByValAlignOffs = 6; - const ParamFlagsTy OrigAlignment = 0x1FULL<<27; - const ParamFlagsTy OrigAlignmentOffs = 27; - const ParamFlagsTy ByValSize = 0xffffffffULL << 32; //< Struct size - const ParamFlagsTy ByValSizeOffs = 32; - - const ParamFlagsTy One = 1LL; //< 1 of this type, for shifts - } //===--------------------------------------------------------------------===// /// ISD::NodeType enum - This enum defines all of the operators valid in a @@ -107,7 +82,7 @@ namespace ISD { AssertSext, AssertZext, // Various leaf nodes. - STRING, BasicBlock, VALUETYPE, CONDCODE, Register, + STRING, BasicBlock, VALUETYPE, ARG_FLAGS, CONDCODE, Register, Constant, ConstantFP, GlobalAddress, GlobalTLSAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol, @@ -659,7 +634,7 @@ namespace ISD { /// computed and is available in the base pointer. The offset /// operand is always undefined. In addition to producing a /// chain, an unindexed load produces one value (result of the - /// load); an unindexed store does not produces a value. + /// load); an unindexed store does not produce a value. /// /// PRE_INC Similar to the unindexed mode where the effective address is /// PRE_DEC the value of the base pointer add / subtract the offset. @@ -1584,6 +1559,102 @@ public: } }; +namespace ISD { + struct ArgFlagsTy { + private: + static const uint64_t NoFlagSet = 0ULL; + static const uint64_t ZExt = 1ULL<<0; ///< Zero extended + static const uint64_t ZExtOffs = 0; + static const uint64_t SExt = 1ULL<<1; ///< Sign extended + static const uint64_t SExtOffs = 1; + static const uint64_t InReg = 1ULL<<2; ///< Passed in register + static const uint64_t InRegOffs = 2; + static const uint64_t SRet = 1ULL<<3; ///< Hidden struct-ret ptr + static const uint64_t SRetOffs = 3; + static const uint64_t ByVal = 1ULL<<4; ///< Struct passed by value + static const uint64_t ByValOffs = 4; + static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain + static const uint64_t NestOffs = 5; + static const uint64_t ByValAlign = 0xFULL << 6; //< Struct alignment + static const uint64_t ByValAlignOffs = 6; + static const uint64_t OrigAlign = 0x1FULL<<27; + static const uint64_t OrigAlignOffs = 27; + static const uint64_t ByValSize = 0xffffffffULL << 32; //< Struct size + static const uint64_t ByValSizeOffs = 32; + + static const uint64_t One = 1ULL; //< 1 of this type, for shifts + + uint64_t Flags; + public: + ArgFlagsTy() : Flags(0) { } + + bool isZExt() const { return Flags & ZExt; } + void setZExt() { Flags |= One << ZExtOffs; } + + bool isSExt() const { return Flags & SExt; } + void setSExt() { Flags |= One << SExtOffs; } + + bool isInReg() const { return Flags & InReg; } + void setInReg() { Flags |= One << InRegOffs; } + + bool isSRet() const { return Flags & SRet; } + void setSRet() { Flags |= One << SRetOffs; } + + bool isByVal() const { return Flags & ByVal; } + void setByVal() { Flags |= One << ByValOffs; } + + bool isNest() const { return Flags & Nest; } + void setNest() { Flags |= One << NestOffs; } + + unsigned getByValAlign() const { + return (One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2; + } + void setByValAlign(unsigned A) { + Flags = (Flags & ~ByValAlign) | + (uint64_t(Log2_32(A) + 1) << ByValAlignOffs); + } + + unsigned getOrigAlign() const { + return (One << ((Flags & OrigAlign) >> OrigAlignOffs)) / 2; + } + void setOrigAlign(unsigned A) { + Flags = (Flags & ~OrigAlign) | + (uint64_t(Log2_32(A) + 1) << OrigAlignOffs); + } + + unsigned getByValSize() const { + return (Flags & ByValSize) >> ByValSizeOffs; + } + void setByValSize(unsigned S) { + Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs); + } + + /// getArgFlagsString - Returns the flags as a string, eg: "zext align:4". + std::string getArgFlagsString(); + + /// getRawBits - Represent the flags as a bunch of bits. + uint64_t getRawBits() const { return Flags; } + }; +} + +/// ARG_FLAGSSDNode - Leaf node holding parameter flags. +class ARG_FLAGSSDNode : public SDNode { + ISD::ArgFlagsTy TheFlags; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + explicit ARG_FLAGSSDNode(ISD::ArgFlagsTy Flags) + : SDNode(ISD::ARG_FLAGS, getSDVTList(MVT::Other)), TheFlags(Flags) { + } +public: + ISD::ArgFlagsTy getArgFlags() const { return TheFlags; } + + static bool classof(const ARG_FLAGSSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ARG_FLAGS; + } +}; + /// VTSDNode - This class is used to represent MVT::ValueType's, which are used /// to parameterize some operations. class VTSDNode : public SDNode { diff --git a/lib/CodeGen/SelectionDAG/CallingConvLower.cpp b/lib/CodeGen/SelectionDAG/CallingConvLower.cpp index 6b9b31b548f..667870d4521 100644 --- a/lib/CodeGen/SelectionDAG/CallingConvLower.cpp +++ b/lib/CodeGen/SelectionDAG/CallingConvLower.cpp @@ -35,11 +35,9 @@ CCState::CCState(unsigned CC, bool isVarArg, const TargetMachine &tm, void CCState::HandleByVal(unsigned ValNo, MVT::ValueType ValVT, MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo, int MinSize, int MinAlign, - ISD::ParamFlags::ParamFlagsTy ArgFlags) { - unsigned Align = 1 << ((ArgFlags & ISD::ParamFlags::ByValAlign) >> - ISD::ParamFlags::ByValAlignOffs); - unsigned Size = (ArgFlags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; + ISD::ArgFlagsTy ArgFlags) { + unsigned Align = ArgFlags.getByValAlign(); + unsigned Size = ArgFlags.getByValSize(); if (MinSize > (int)Size) Size = MinSize; if (MinAlign > (int)Align) @@ -65,9 +63,8 @@ void CCState::AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn) { for (unsigned i = 0; i != NumArgs; ++i) { MVT::ValueType ArgVT = TheArgs->getValueType(i); - SDOperand FlagOp = TheArgs->getOperand(3+i); - ISD::ParamFlags::ParamFlagsTy ArgFlags = - cast(FlagOp)->getValue(); + ISD::ArgFlagsTy ArgFlags = + cast(TheArgs->getOperand(3+i))->getArgFlags(); if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { cerr << "Formal argument #" << i << " has unhandled type " << MVT::getValueTypeString(ArgVT) << "\n"; @@ -82,8 +79,9 @@ void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) { // Determine which register each value should be copied into. for (unsigned i = 0, e = TheRet->getNumOperands() / 2; i != e; ++i) { MVT::ValueType VT = TheRet->getOperand(i*2+1).getValueType(); - if (Fn(i, VT, VT, CCValAssign::Full, - cast(TheRet->getOperand(i*2+2))->getValue(), *this)){ + ISD::ArgFlagsTy ArgFlags = + cast(TheRet->getOperand(i*2+2))->getArgFlags(); + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)){ cerr << "Return operand #" << i << " has unhandled type " << MVT::getValueTypeString(VT) << "\n"; abort(); @@ -98,9 +96,8 @@ void CCState::AnalyzeCallOperands(SDNode *TheCall, CCAssignFn Fn) { unsigned NumOps = (TheCall->getNumOperands() - 5) / 2; for (unsigned i = 0; i != NumOps; ++i) { MVT::ValueType ArgVT = TheCall->getOperand(5+2*i).getValueType(); - SDOperand FlagOp = TheCall->getOperand(5+2*i+1); - ISD::ParamFlags::ParamFlagsTy ArgFlags = - cast(FlagOp)->getValue(); + ISD::ArgFlagsTy ArgFlags = + cast(TheCall->getOperand(5+2*i+1))->getArgFlags(); if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { cerr << "Call operand #" << i << " has unhandled type " << MVT::getValueTypeString(ArgVT) << "\n"; @@ -114,7 +111,7 @@ void CCState::AnalyzeCallOperands(SDNode *TheCall, CCAssignFn Fn) { void CCState::AnalyzeCallResult(SDNode *TheCall, CCAssignFn Fn) { for (unsigned i = 0, e = TheCall->getNumValues() - 1; i != e; ++i) { MVT::ValueType VT = TheCall->getValueType(i); - if (Fn(i, VT, VT, CCValAssign::Full, 0, *this)) { + if (Fn(i, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) { cerr << "Call result #" << i << " has unhandled type " << MVT::getValueTypeString(VT) << "\n"; abort(); diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 56ac37590bc..d318cb43724 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -808,6 +808,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::MEMOPERAND: case ISD::STRING: case ISD::CONDCODE: + case ISD::ARG_FLAGS: // Primitives must all be legal. assert(TLI.isOperationLegal(Node->getOpcode(), Node->getValueType(0)) && "This must be legal!"); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3cd731073c0..9331e8b7ee9 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -355,6 +355,9 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, SDNode *N) { // Handle SDNode leafs with special info. switch (N->getOpcode()) { default: break; // Normal nodes don't need extra info. + case ISD::ARG_FLAGS: + ID.AddInteger(cast(N)->getArgFlags().getRawBits()); + break; case ISD::TargetConstant: case ISD::Constant: ID.Add(cast(N)->getAPIntValue()); @@ -923,6 +926,19 @@ SDOperand SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) { return SDOperand(N, 0); } +SDOperand SelectionDAG::getArgFlags(ISD::ArgFlagsTy Flags) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::ARG_FLAGS, getVTList(MVT::Other), 0, 0); + ID.AddInteger(Flags.getRawBits()); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDOperand(E, 0); + SDNode *N = new ARG_FLAGSSDNode(Flags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDOperand(N, 0); +} + SDOperand SelectionDAG::getValueType(MVT::ValueType VT) { if (!MVT::isExtendedVT(VT) && (unsigned)VT >= ValueTypeNodes.size()) ValueTypeNodes.resize(VT+1); @@ -3584,6 +3600,7 @@ void MemOperandSDNode::ANCHOR() {} void RegisterSDNode::ANCHOR() {} void ExternalSymbolSDNode::ANCHOR() {} void CondCodeSDNode::ANCHOR() {} +void ARG_FLAGSSDNode::ANCHOR() {} void VTSDNode::ANCHOR() {} void LoadSDNode::ANCHOR() {} void StoreSDNode::ANCHOR() {} @@ -3831,6 +3848,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::STRING: return "String"; case ISD::BasicBlock: return "BasicBlock"; + case ISD::ARG_FLAGS: return "ArgFlags"; case ISD::VALUETYPE: return "ValueType"; case ISD::Register: return "Register"; @@ -4043,6 +4061,30 @@ const char *SDNode::getIndexedModeName(ISD::MemIndexedMode AM) { } } +std::string ISD::ArgFlagsTy::getArgFlagsString() { + std::string S = "< "; + + if (isZExt()) + S += "zext "; + if (isSExt()) + S += "sext "; + if (isInReg()) + S += "inreg "; + if (isSRet()) + S += "sret "; + if (isByVal()) + S += "byval "; + if (isNest()) + S += "nest "; + if (getByValAlign()) + S += "byval-align:" + utostr(getByValAlign()) + " "; + if (getOrigAlign()) + S += "orig-align:" + utostr(getOrigAlign()) + " "; + if (getByValSize()) + S += "byval-size:" + utostr(getByValSize()) + " "; + return S + ">"; +} + void SDNode::dump() const { dump(0); } void SDNode::dump(const SelectionDAG *G) const { cerr << (void*)this << ": "; @@ -4138,6 +4180,8 @@ void SDNode::dump(const SelectionDAG *G) const { cerr << "<" << M->MO.getValue() << ":" << M->MO.getOffset() << ">"; else cerr << "MO.getOffset() << ">"; + } else if (const ARG_FLAGSSDNode *N = dyn_cast(this)) { + cerr << N->getArgFlags().getArgFlagsString(); } else if (const VTSDNode *N = dyn_cast(this)) { cerr << ":" << MVT::getValueTypeString(N->getVT()); } else if (const LoadSDNode *LD = dyn_cast(this)) { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 1e249d0386f..d9d58fa037c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1064,7 +1064,7 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) { for (unsigned i = 0; i < NumParts; ++i) { NewValues.push_back(Parts[i]); - NewValues.push_back(DAG.getConstant(false, MVT::i32)); + NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy())); } } DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, @@ -4065,39 +4065,34 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I, ++j) { MVT::ValueType VT = getValueType(I->getType()); - ISD::ParamFlags::ParamFlagsTy Flags = ISD::ParamFlags::NoFlagSet; + ISD::ArgFlagsTy Flags; unsigned OriginalAlignment = getTargetData()->getABITypeAlignment(I->getType()); - // FIXME: Distinguish between a formal with no [sz]ext attribute from one - // that is zero extended! if (F.paramHasAttr(j, ParamAttr::ZExt)) - Flags &= ~(ISD::ParamFlags::SExt); + Flags.setZExt(); if (F.paramHasAttr(j, ParamAttr::SExt)) - Flags |= ISD::ParamFlags::SExt; + Flags.setSExt(); if (F.paramHasAttr(j, ParamAttr::InReg)) - Flags |= ISD::ParamFlags::InReg; + Flags.setInReg(); if (F.paramHasAttr(j, ParamAttr::StructRet)) - Flags |= ISD::ParamFlags::StructReturn; + Flags.setSRet(); if (F.paramHasAttr(j, ParamAttr::ByVal)) { - Flags |= ISD::ParamFlags::ByVal; + Flags.setByVal(); const PointerType *Ty = cast(I->getType()); const Type *ElementTy = Ty->getElementType(); - unsigned FrameAlign = Log2_32(getByValTypeAlignment(ElementTy)); + unsigned FrameAlign = getByValTypeAlignment(ElementTy); unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy); // For ByVal, alignment should be passed from FE. BE will guess if // this info is not there but there are cases it cannot get right. if (F.getParamAlignment(j)) - FrameAlign = Log2_32(F.getParamAlignment(j)); - Flags |= ((ISD::ParamFlags::ParamFlagsTy)FrameAlign - << ISD::ParamFlags::ByValAlignOffs); - Flags |= ((ISD::ParamFlags::ParamFlagsTy)FrameSize - << ISD::ParamFlags::ByValSizeOffs); + FrameAlign = F.getParamAlignment(j); + Flags.setByValAlign(FrameAlign); + Flags.setByValSize(FrameSize); } if (F.paramHasAttr(j, ParamAttr::Nest)) - Flags |= ISD::ParamFlags::Nest; - Flags |= ((ISD::ParamFlags::ParamFlagsTy)OriginalAlignment - << ISD::ParamFlags::OrigAlignmentOffs); + Flags.setNest(); + Flags.setOrigAlign(OriginalAlignment); MVT::ValueType RegisterVT = getRegisterType(VT); unsigned NumRegs = getNumRegisters(VT); @@ -4105,9 +4100,8 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { RetVals.push_back(RegisterVT); // if it isn't first piece, alignment must be 1 if (i > 0) - Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) | - (ISD::ParamFlags::One << ISD::ParamFlags::OrigAlignmentOffs); - Ops.push_back(DAG.getConstant(Flags, MVT::i64)); + Flags.setOrigAlign(1); + Ops.push_back(DAG.getArgFlags(Flags)); } } @@ -4183,37 +4177,34 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, for (unsigned i = 0, e = Args.size(); i != e; ++i) { MVT::ValueType VT = getValueType(Args[i].Ty); SDOperand Op = Args[i].Node; - ISD::ParamFlags::ParamFlagsTy Flags = ISD::ParamFlags::NoFlagSet; + ISD::ArgFlagsTy Flags; unsigned OriginalAlignment = getTargetData()->getABITypeAlignment(Args[i].Ty); - - if (Args[i].isSExt) - Flags |= ISD::ParamFlags::SExt; + if (Args[i].isZExt) - Flags |= ISD::ParamFlags::ZExt; + Flags.setZExt(); + if (Args[i].isSExt) + Flags.setSExt(); if (Args[i].isInReg) - Flags |= ISD::ParamFlags::InReg; + Flags.setInReg(); if (Args[i].isSRet) - Flags |= ISD::ParamFlags::StructReturn; + Flags.setSRet(); if (Args[i].isByVal) { - Flags |= ISD::ParamFlags::ByVal; + Flags.setByVal(); const PointerType *Ty = cast(Args[i].Ty); const Type *ElementTy = Ty->getElementType(); - unsigned FrameAlign = Log2_32(getByValTypeAlignment(ElementTy)); + unsigned FrameAlign = getByValTypeAlignment(ElementTy); unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy); // For ByVal, alignment should come from FE. BE will guess if this // info is not there but there are cases it cannot get right. if (Args[i].Alignment) - FrameAlign = Log2_32(Args[i].Alignment); - Flags |= ((ISD::ParamFlags::ParamFlagsTy)FrameAlign - << ISD::ParamFlags::ByValAlignOffs); - Flags |= ((ISD::ParamFlags::ParamFlagsTy)FrameSize - << ISD::ParamFlags::ByValSizeOffs); + FrameAlign = Args[i].Alignment; + Flags.setByValAlign(FrameAlign); + Flags.setByValSize(FrameSize); } if (Args[i].isNest) - Flags |= ISD::ParamFlags::Nest; - Flags |= ((ISD::ParamFlags::ParamFlagsTy)OriginalAlignment) - << ISD::ParamFlags::OrigAlignmentOffs; + Flags.setNest(); + Flags.setOrigAlign(OriginalAlignment); MVT::ValueType PartVT = getRegisterType(VT); unsigned NumParts = getNumRegisters(VT); @@ -4229,13 +4220,12 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, for (unsigned i = 0; i != NumParts; ++i) { // if it isn't first piece, alignment must be 1 - ISD::ParamFlags::ParamFlagsTy MyFlags = Flags; + ISD::ArgFlagsTy MyFlags = Flags; if (i != 0) - MyFlags = (MyFlags & (~ISD::ParamFlags::OrigAlignment)) | - (ISD::ParamFlags::One << ISD::ParamFlags::OrigAlignmentOffs); + MyFlags.setOrigAlign(1); Ops.push_back(Parts[i]); - Ops.push_back(DAG.getConstant(MyFlags, MVT::i64)); + Ops.push_back(DAG.getArgFlags(MyFlags)); } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp index b316d417a97..ad58aa06165 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp @@ -151,6 +151,8 @@ std::string DOTGraphTraits::getNodeLabel(const SDNode *Node, Op += "<" + M->MO.getValue()->getName() + ":" + itostr(M->MO.getOffset()) + ">"; else Op += "MO.getOffset()) + ">"; + } else if (const ARG_FLAGSSDNode *N = dyn_cast(Node)) { + Op = Op + " AF=" + N->getArgFlags().getArgFlagsString(); } else if (const VTSDNode *N = dyn_cast(Node)) { Op = Op + " VT=" + MVT::getValueTypeString(N->getVT()); } else if (const StringSDNode *N = dyn_cast(Node)) { diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 0326ecf43e4..421a03fca00 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -367,13 +367,12 @@ static void HowToPassArgument(MVT::ValueType ObjectVT, unsigned NumGPRs, unsigned StackOffset, unsigned &NeededGPRs, unsigned &NeededStackSize, unsigned &GPRPad, - unsigned &StackPad, ISD::ParamFlags::ParamFlagsTy Flags) { + unsigned &StackPad, ISD::ArgFlagsTy Flags) { NeededStackSize = 0; NeededGPRs = 0; StackPad = 0; GPRPad = 0; - unsigned align = ((Flags & ISD::ParamFlags::OrigAlignment) - >> ISD::ParamFlags::OrigAlignmentOffs); + unsigned align = Flags.getOrigAlign(); GPRPad = NumGPRs % ((align + 3)/4); StackPad = StackOffset % align; unsigned firstGPR = NumGPRs + GPRPad; @@ -422,7 +421,8 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { unsigned StackPad; unsigned GPRPad; MVT::ValueType ObjectVT = Op.getOperand(5+2*i).getValueType(); - ISD::ParamFlags::ParamFlagsTy Flags = Op.getConstantOperandVal(5+2*i+1); + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(5+2*i+1))->getArgFlags(); HowToPassArgument(ObjectVT, NumGPRs, NumBytes, ObjGPRs, ObjSize, GPRPad, StackPad, Flags); NumBytes += ObjSize + StackPad; @@ -445,7 +445,8 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { std::vector MemOpChains; for (unsigned i = 0; i != NumOps; ++i) { SDOperand Arg = Op.getOperand(5+2*i); - ISD::ParamFlags::ParamFlagsTy Flags = Op.getConstantOperandVal(5+2*i+1); + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(5+2*i+1))->getArgFlags(); MVT::ValueType ArgVT = Arg.getValueType(); unsigned ObjSize; @@ -924,7 +925,8 @@ static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG, unsigned ObjGPRs; unsigned GPRPad; unsigned StackPad; - ISD::ParamFlags::ParamFlagsTy Flags = Op.getConstantOperandVal(ArgNo + 3); + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(ArgNo + 3))->getArgFlags(); HowToPassArgument(ObjectVT, NumGPRs, ArgOffset, ObjGPRs, ObjSize, GPRPad, StackPad, Flags); NumGPRs += GPRPad; diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index d8f7400c2ae..5a3a51f21c4 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1366,14 +1366,12 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, ++ArgNo) { MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; - ISD::ParamFlags::ParamFlagsTy Flags = - cast(Op.getOperand(ArgNo+3))->getValue(); - unsigned isByVal = Flags & ISD::ParamFlags::ByVal; + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(ArgNo+3))->getArgFlags(); - if (isByVal) { + if (Flags.isByVal()) { // ObjSize is the true size, ArgSize rounded up to multiple of regs. - ObjSize = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; + ObjSize = Flags.getByValSize(); unsigned ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; VecArgOffset += ArgSize; @@ -1410,7 +1408,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, // // In the ELF 32 ABI, GPRs and stack are double word align: an argument // represented with two words (long long or double) must be copied to an - // even GPR_idx value or to an even ArgOffset value. + // even GPR_idx value or to an even ArgOffset value. TODO: implement this. SmallVector MemOps; @@ -1420,25 +1418,19 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; unsigned ArgSize = ObjSize; - ISD::ParamFlags::ParamFlagsTy Flags = - cast(Op.getOperand(ArgNo+3))->getValue(); - unsigned AlignFlag = ISD::ParamFlags::One - << ISD::ParamFlags::OrigAlignmentOffs; - unsigned isByVal = Flags & ISD::ParamFlags::ByVal; + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(ArgNo+3))->getArgFlags(); // See if next argument requires stack alignment in ELF - bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) && - (cast(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) && - (!(Flags & AlignFlag))); + bool Expand = false; // TODO: implement this. unsigned CurArgOffset = ArgOffset; // FIXME alignment for ELF may not be right // FIXME the codegen can be much improved in some cases. // We do not have to keep everything in memory. - if (isByVal) { + if (Flags.isByVal()) { // ObjSize is the true size, ArgSize rounded up to multiple of registers. - ObjSize = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; + ObjSize = Flags.getByValSize(); ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; // Double word align in ELF if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2); @@ -1521,10 +1513,10 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, if (ObjectVT == MVT::i32) { // PPC64 passes i8, i16, and i32 values in i64 registers. Promote // value to MVT::i64 and then truncate to the correct register size. - if (Flags & ISD::ParamFlags::SExt) + if (Flags.isSExt()) ArgVal = DAG.getNode(ISD::AssertSext, MVT::i64, ArgVal, DAG.getValueType(ObjectVT)); - else if (Flags & ISD::ParamFlags::ZExt) + else if (Flags.isZExt()) ArgVal = DAG.getNode(ISD::AssertZext, MVT::i64, ArgVal, DAG.getValueType(ObjectVT)); @@ -1736,11 +1728,9 @@ static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) { /// does not fit in registers. static SDOperand CreateCopyOfByValArgument(SDOperand Src, SDOperand Dst, SDOperand Chain, - ISD::ParamFlags::ParamFlagsTy Flags, - SelectionDAG &DAG, unsigned Size) { - unsigned Align = ISD::ParamFlags::One << - ((Flags & ISD::ParamFlags::ByValAlign) >> ISD::ParamFlags::ByValAlignOffs); - SDOperand AlignNode = DAG.getConstant(Align, MVT::i32); + ISD::ArgFlagsTy Flags, SelectionDAG &DAG, + unsigned Size) { + SDOperand AlignNode = DAG.getConstant(Flags.getByValAlign(), MVT::i32); SDOperand SizeNode = DAG.getConstant(Size, MVT::i32); SDOperand AlwaysInline = DAG.getConstant(0, MVT::i32); return DAG.getMemcpy(Chain, Dst, Src, SizeNode, AlignNode, AlwaysInline); @@ -1792,12 +1782,11 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, NumBytes = ((NumBytes+15)/16)*16; } } - ISD::ParamFlags::ParamFlagsTy Flags = - cast(Op.getOperand(5+2*i+1))->getValue(); + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(5+2*i+1))->getArgFlags(); unsigned ArgSize =MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8; - if (Flags & ISD::ParamFlags::ByVal) - ArgSize = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; + if (Flags.isByVal()) + ArgSize = Flags.getByValSize(); ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; NumBytes += ArgSize; } @@ -1862,15 +1851,10 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, for (unsigned i = 0; i != NumOps; ++i) { bool inMem = false; SDOperand Arg = Op.getOperand(5+2*i); - ISD::ParamFlags::ParamFlagsTy Flags = - cast(Op.getOperand(5+2*i+1))->getValue(); - unsigned AlignFlag = ISD::ParamFlags::One << - ISD::ParamFlags::OrigAlignmentOffs; + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(5+2*i+1))->getArgFlags(); // See if next argument requires stack alignment in ELF - unsigned next = 5+2*(i+1)+1; - bool Expand = (Arg.getValueType() == MVT::f64) || ((i + 1 < NumOps) && - (cast(Op.getOperand(next))->getValue() & AlignFlag) && - (!(Flags & AlignFlag))); + bool Expand = false; // TODO: implement this. // PtrOff will be used to store the current argument to the stack if a // register cannot be found for it. @@ -1887,15 +1871,15 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, // On PPC64, promote integers to 64-bit values. if (isPPC64 && Arg.getValueType() == MVT::i32) { - unsigned ExtOp = (Flags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + // FIXME: Should this use ANY_EXTEND if neither sext nor zext? + unsigned ExtOp = Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; Arg = DAG.getNode(ExtOp, MVT::i64, Arg); } // FIXME Elf untested, what are alignment rules? // FIXME memcpy is used way more than necessary. Correctness first. - if (Flags & ISD::ParamFlags::ByVal) { - unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; + if (Flags.isByVal()) { + unsigned Size = Flags.getByValSize(); if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2); if (Size==1 || Size==2) { // Very small objects are passed right-justified. diff --git a/lib/Target/TargetCallingConv.td b/lib/Target/TargetCallingConv.td index a3b84f4b6f0..05d505a88d3 100644 --- a/lib/Target/TargetCallingConv.td +++ b/lib/Target/TargetCallingConv.td @@ -34,7 +34,7 @@ class CCIf : CCPredicateAction { /// CCIfByVal - If the current argument has ByVal parameter attribute, apply /// Action A. -class CCIfByVal : CCIf<"ArgFlags & ISD::ParamFlags::ByVal", A> { +class CCIfByVal : CCIf<"ArgFlags.isByVal()", A> { } /// CCIfCC - Match of the current calling convention is 'CC'. @@ -43,11 +43,11 @@ class CCIfCC /// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply /// the specified action. -class CCIfInReg : CCIf<"ArgFlags & ISD::ParamFlags::InReg", A> {} +class CCIfInReg : CCIf<"ArgFlags.isInReg()", A> {} /// CCIfNest - If this argument is marked with the 'nest' attribute, apply /// the specified action. -class CCIfNest : CCIf<"ArgFlags & ISD::ParamFlags::Nest", A> {} +class CCIfNest : CCIf<"ArgFlags.isNest()", A> {} /// CCIfNotVarArg - If the current function is not vararg - apply the action class CCIfNotVarArg : CCIf<"!State.isVarArg()", A> {} diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1cbf5ee1ff9..9d22fbeaaad 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -969,9 +969,8 @@ static bool CallIsStructReturn(SDOperand Op) { unsigned NumOps = (Op.getNumOperands() - 5) / 2; if (!NumOps) return false; - - ConstantSDNode *Flags = cast(Op.getOperand(6)); - return Flags->getValue() & ISD::ParamFlags::StructReturn; + + return cast(Op.getOperand(6))->getArgFlags().isSRet(); } /// ArgsAreStructReturn - Determines whether a FORMAL_ARGUMENTS node uses struct @@ -980,9 +979,8 @@ static bool ArgsAreStructReturn(SDOperand Op) { unsigned NumArgs = Op.Val->getNumValues() - 1; if (!NumArgs) return false; - - ConstantSDNode *Flags = cast(Op.getOperand(3)); - return Flags->getValue() & ISD::ParamFlags::StructReturn; + + return cast(Op.getOperand(3))->getArgFlags().isSRet(); } /// IsCalleePop - Determines whether a CALL or FORMAL_ARGUMENTS node requires the @@ -1110,14 +1108,9 @@ CopyTailCallClobberedArgumentsToVRegs(SDOperand Chain, /// parameter. static SDOperand CreateCopyOfByValArgument(SDOperand Src, SDOperand Dst, SDOperand Chain, - ISD::ParamFlags::ParamFlagsTy Flags, - SelectionDAG &DAG) { - unsigned Align = ISD::ParamFlags::One << - ((Flags & ISD::ParamFlags::ByValAlign) >> ISD::ParamFlags::ByValAlignOffs); - unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; - SDOperand AlignNode = DAG.getConstant(Align, MVT::i32); - SDOperand SizeNode = DAG.getConstant(Size, MVT::i32); + ISD::ArgFlagsTy Flags, SelectionDAG &DAG) { + SDOperand AlignNode = DAG.getConstant(Flags.getByValAlign(), MVT::i32); + SDOperand SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); SDOperand AlwaysInline = DAG.getConstant(1, MVT::i32); return DAG.getMemcpy(Chain, Dst, Src, SizeNode, AlignNode, AlwaysInline); } @@ -1128,11 +1121,10 @@ SDOperand X86TargetLowering::LowerMemArgument(SDOperand Op, SelectionDAG &DAG, unsigned CC, SDOperand Root, unsigned i) { // Create the nodes corresponding to a load from this parameter slot. - ISD::ParamFlags::ParamFlagsTy Flags = - cast(Op.getOperand(3 + i))->getValue(); + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(3 + i))->getArgFlags(); bool AlwaysUseMutable = (CC==CallingConv::Fast) && PerformTailCallOpt; - bool isByVal = Flags & ISD::ParamFlags::ByVal; - bool isImmutable = !AlwaysUseMutable && !isByVal; + bool isImmutable = !AlwaysUseMutable && !Flags.isByVal(); // FIXME: For now, all byval parameter objects are marked mutable. This can be // changed with more analysis. @@ -1141,7 +1133,7 @@ SDOperand X86TargetLowering::LowerMemArgument(SDOperand Op, SelectionDAG &DAG, int FI = MFI->CreateFixedObject(MVT::getSizeInBits(VA.getValVT())/8, VA.getLocMemOffset(), isImmutable); SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy()); - if (isByVal) + if (Flags.isByVal()) return FIN; return DAG.getLoad(VA.getValVT(), Root, FIN, PseudoSourceValue::getFixedStack(), FI); @@ -1346,10 +1338,9 @@ X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG, unsigned LocMemOffset = VA.getLocMemOffset(); SDOperand PtrOff = DAG.getIntPtrConstant(LocMemOffset); PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff); - SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo()); - ISD::ParamFlags::ParamFlagsTy Flags = - cast(FlagsOp)->getValue(); - if (Flags & ISD::ParamFlags::ByVal) { + ISD::ArgFlagsTy Flags = + cast(Op.getOperand(6+2*VA.getValNo()))->getArgFlags(); + if (Flags.isByVal()) { return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG); } return DAG.getStore(Chain, Arg, PtrOff, @@ -1536,8 +1527,8 @@ SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { assert(VA.isMemLoc()); SDOperand Arg = Op.getOperand(5+2*VA.getValNo()); SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo()); - ISD::ParamFlags::ParamFlagsTy Flags = - cast(FlagsOp)->getValue(); + ISD::ArgFlagsTy Flags = + cast(FlagsOp)->getArgFlags(); // Create frame index. int32_t Offset = VA.getLocMemOffset()+FPDiff; uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8; @@ -1554,8 +1545,8 @@ SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { } assert(IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)==false || (Found==true && "No corresponding Argument was found")); - - if (Flags & ISD::ParamFlags::ByVal) { + + if (Flags.isByVal()) { // Copy relative to framepointer. MemOpChains2.push_back(CreateCopyOfByValArgument(Arg, FIN, Chain, Flags, DAG)); diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 48f7cb33e6e..192bba5ee31 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -30,7 +30,7 @@ void CallingConvEmitter::run(std::ostream &O) { << std::string(CCs[i]->getName().size()+13, ' ') << "MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo,\n" << std::string(CCs[i]->getName().size()+13, ' ') - << "ISD::ParamFlags::ParamFlagsTy ArgFlags, CCState &State);\n"; + << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; } // Emit each calling convention description in full. @@ -48,7 +48,7 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, std::ostream &O) { << std::string(CC->getName().size()+13, ' ') << "MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo,\n" << std::string(CC->getName().size()+13, ' ') - << "ISD::ParamFlags::ParamFlagsTy ArgFlags, CCState &State) {\n"; + << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; // Emit all of the actions, in order. for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) { O << "\n"; @@ -134,9 +134,9 @@ void CallingConvEmitter::EmitAction(Record *Action, } else if (Action->isSubClassOf("CCPromoteToType")) { Record *DestTy = Action->getValueAsDef("DestTy"); O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; - O << IndentStr << "if (ArgFlags & ISD::ParamFlags::SExt)\n" + O << IndentStr << "if (ArgFlags.isSExt())\n" << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n" - << IndentStr << "else if (ArgFlags & ISD::ParamFlags::ZExt)\n" + << IndentStr << "else if (ArgFlags.isZExt())\n" << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n" << IndentStr << "else\n" << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";