/// 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
// 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.
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);
/// 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
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,
/// 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.
}
};
+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 {
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)
for (unsigned i = 0; i != NumArgs; ++i) {
MVT::ValueType ArgVT = TheArgs->getValueType(i);
- SDOperand FlagOp = TheArgs->getOperand(3+i);
- ISD::ParamFlags::ParamFlagsTy ArgFlags =
- cast<ConstantSDNode>(FlagOp)->getValue();
+ ISD::ArgFlagsTy ArgFlags =
+ cast<ARG_FLAGSSDNode>(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";
// 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<ConstantSDNode>(TheRet->getOperand(i*2+2))->getValue(), *this)){
+ ISD::ArgFlagsTy ArgFlags =
+ cast<ARG_FLAGSSDNode>(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();
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<ConstantSDNode>(FlagOp)->getValue();
+ ISD::ArgFlagsTy ArgFlags =
+ cast<ARG_FLAGSSDNode>(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";
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();
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!");
// 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<ARG_FLAGSSDNode>(N)->getArgFlags().getRawBits());
+ break;
case ISD::TargetConstant:
case ISD::Constant:
ID.Add(cast<ConstantSDNode>(N)->getAPIntValue());
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);
void RegisterSDNode::ANCHOR() {}
void ExternalSymbolSDNode::ANCHOR() {}
void CondCodeSDNode::ANCHOR() {}
+void ARG_FLAGSSDNode::ANCHOR() {}
void VTSDNode::ANCHOR() {}
void LoadSDNode::ANCHOR() {}
void StoreSDNode::ANCHOR() {}
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";
}
}
+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 << ": ";
cerr << "<" << M->MO.getValue() << ":" << M->MO.getOffset() << ">";
else
cerr << "<null:" << M->MO.getOffset() << ">";
+ } else if (const ARG_FLAGSSDNode *N = dyn_cast<ARG_FLAGSSDNode>(this)) {
+ cerr << N->getArgFlags().getArgFlagsString();
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) {
cerr << ":" << MVT::getValueTypeString(N->getVT());
} else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(this)) {
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,
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<PointerType>(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);
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));
}
}
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<PointerType>(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);
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));
}
}
Op += "<" + M->MO.getValue()->getName() + ":" + itostr(M->MO.getOffset()) + ">";
else
Op += "<null:" + itostr(M->MO.getOffset()) + ">";
+ } else if (const ARG_FLAGSSDNode *N = dyn_cast<ARG_FLAGSSDNode>(Node)) {
+ Op = Op + " AF=" + N->getArgFlags().getArgFlagsString();
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
Op = Op + " VT=" + MVT::getValueTypeString(N->getVT());
} else if (const StringSDNode *N = dyn_cast<StringSDNode>(Node)) {
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;
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<ARG_FLAGSSDNode>(Op.getOperand(5+2*i+1))->getArgFlags();
HowToPassArgument(ObjectVT, NumGPRs, NumBytes, ObjGPRs, ObjSize,
GPRPad, StackPad, Flags);
NumBytes += ObjSize + StackPad;
std::vector<SDOperand> 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<ARG_FLAGSSDNode>(Op.getOperand(5+2*i+1))->getArgFlags();
MVT::ValueType ArgVT = Arg.getValueType();
unsigned ObjSize;
unsigned ObjGPRs;
unsigned GPRPad;
unsigned StackPad;
- ISD::ParamFlags::ParamFlagsTy Flags = Op.getConstantOperandVal(ArgNo + 3);
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo + 3))->getArgFlags();
HowToPassArgument(ObjectVT, NumGPRs, ArgOffset, ObjGPRs,
ObjSize, GPRPad, StackPad, Flags);
NumGPRs += GPRPad;
++ArgNo) {
MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
- ISD::ParamFlags::ParamFlagsTy Flags =
- cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
- unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(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;
//
// 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<SDOperand, 8> MemOps;
MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
unsigned ArgSize = ObjSize;
- ISD::ParamFlags::ParamFlagsTy Flags =
- cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
- unsigned AlignFlag = ISD::ParamFlags::One
- << ISD::ParamFlags::OrigAlignmentOffs;
- unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo+3))->getArgFlags();
// See if next argument requires stack alignment in ELF
- bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) &&
- (cast<ConstantSDNode>(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);
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));
/// 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);
NumBytes = ((NumBytes+15)/16)*16;
}
}
- ISD::ParamFlags::ParamFlagsTy Flags =
- cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(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;
}
for (unsigned i = 0; i != NumOps; ++i) {
bool inMem = false;
SDOperand Arg = Op.getOperand(5+2*i);
- ISD::ParamFlags::ParamFlagsTy Flags =
- cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
- unsigned AlignFlag = ISD::ParamFlags::One <<
- ISD::ParamFlags::OrigAlignmentOffs;
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(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<ConstantSDNode>(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.
// 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.
/// CCIfByVal - If the current argument has ByVal parameter attribute, apply
/// Action A.
-class CCIfByVal<CCAction A> : CCIf<"ArgFlags & ISD::ParamFlags::ByVal", A> {
+class CCIfByVal<CCAction A> : CCIf<"ArgFlags.isByVal()", A> {
}
/// CCIfCC - Match of the current calling convention is 'CC'.
/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply
/// the specified action.
-class CCIfInReg<CCAction A> : CCIf<"ArgFlags & ISD::ParamFlags::InReg", A> {}
+class CCIfInReg<CCAction A> : CCIf<"ArgFlags.isInReg()", A> {}
/// CCIfNest - If this argument is marked with the 'nest' attribute, apply
/// the specified action.
-class CCIfNest<CCAction A> : CCIf<"ArgFlags & ISD::ParamFlags::Nest", A> {}
+class CCIfNest<CCAction A> : CCIf<"ArgFlags.isNest()", A> {}
/// CCIfNotVarArg - If the current function is not vararg - apply the action
class CCIfNotVarArg<CCAction A> : CCIf<"!State.isVarArg()", A> {}
unsigned NumOps = (Op.getNumOperands() - 5) / 2;
if (!NumOps)
return false;
-
- ConstantSDNode *Flags = cast<ConstantSDNode>(Op.getOperand(6));
- return Flags->getValue() & ISD::ParamFlags::StructReturn;
+
+ return cast<ARG_FLAGSSDNode>(Op.getOperand(6))->getArgFlags().isSRet();
}
/// ArgsAreStructReturn - Determines whether a FORMAL_ARGUMENTS node uses struct
unsigned NumArgs = Op.Val->getNumValues() - 1;
if (!NumArgs)
return false;
-
- ConstantSDNode *Flags = cast<ConstantSDNode>(Op.getOperand(3));
- return Flags->getValue() & ISD::ParamFlags::StructReturn;
+
+ return cast<ARG_FLAGSSDNode>(Op.getOperand(3))->getArgFlags().isSRet();
}
/// IsCalleePop - Determines whether a CALL or FORMAL_ARGUMENTS node requires the
/// 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);
}
unsigned CC,
SDOperand Root, unsigned i) {
// Create the nodes corresponding to a load from this parameter slot.
- ISD::ParamFlags::ParamFlagsTy Flags =
- cast<ConstantSDNode>(Op.getOperand(3 + i))->getValue();
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(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.
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);
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<ConstantSDNode>(FlagsOp)->getValue();
- if (Flags & ISD::ParamFlags::ByVal) {
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(Op.getOperand(6+2*VA.getValNo()))->getArgFlags();
+ if (Flags.isByVal()) {
return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG);
}
return DAG.getStore(Chain, Arg, PtrOff,
assert(VA.isMemLoc());
SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
- ISD::ParamFlags::ParamFlagsTy Flags =
- cast<ConstantSDNode>(FlagsOp)->getValue();
+ ISD::ArgFlagsTy Flags =
+ cast<ARG_FLAGSSDNode>(FlagsOp)->getArgFlags();
// Create frame index.
int32_t Offset = VA.getLocMemOffset()+FPDiff;
uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8;
}
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));
<< 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.
<< 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";
} 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";