The attached patch implements code generation of byval arguments on the callee. For now only the case were the struct is in the stack is handle correctly.
With the patch, the function --------------------------------------------------- %struct.s = type { i64, i64, i64 } define i64 @f(%struct.s* byval %a) { entry: %tmp2 = getelementptr %struct.s* %a, i32 0, i32 0] %tmp3 = load i64* %tmp2 ret i64 %tmp3 } ------------------------ Correctly compiles to f: movq 8(%rsp), %rax ret There is still a lot to implement and debug, but I would like to know any comments one might have. Cheers, -- Rafael Avila de Espindola Google Ireland Ltd. Gordon House Barrow Street Dublin 4 Ireland Registered in Dublin, Ireland Registration Number: 368047
Index: include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- include/llvm/CodeGen/SelectionDAGNodes.h (revision 40777) +++ include/llvm/CodeGen/SelectionDAGNodes.h (working copy) @@ -68,6 +68,10 @@ ByValOffs = 4, Nest = 1<<5, ///< Parameter is nested function static chain NestOffs = 5, + ByValAlign = 0xF << 6, //< The alignment of the struct + ByValAlignOffs = 6, + ByValSize = 0x1ffff << 10, //< The size of the struct + ByValSizeOffs = 10, OrigAlignment = 0x1F<<27, OrigAlignmentOffs = 27 }; @@ -200,6 +204,10 @@ /// Bit 0 - signness /// Bit 1 - 'inreg' attribute /// Bit 2 - 'sret' attribute + /// Bit 4 - 'byval' attribute + /// Bit 5 - 'nest' attribute + /// Bit 6-9 - alignment of byval structures + /// Bit 10-26 - size of byval structures /// Bits 31:27 - argument ABI alignment in the first argument piece and /// alignment '1' in other argument pieces. CALL, Index: include/llvm/CodeGen/CallingConvLower.h =================================================================== --- include/llvm/CodeGen/CallingConvLower.h (revision 40777) +++ include/llvm/CodeGen/CallingConvLower.h (working copy) @@ -190,6 +190,10 @@ StackOffset += Size; return Result; } + + void HandleStruct(unsigned ValNo, MVT::ValueType ValVT, + MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo, + unsigned ArgFlags); private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); Index: utils/TableGen/CallingConvEmitter.cpp =================================================================== --- utils/TableGen/CallingConvEmitter.cpp (revision 40777) +++ utils/TableGen/CallingConvEmitter.cpp (working copy) @@ -130,7 +130,9 @@ << IndentStr << "else\n" << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; } else if (Action->isSubClassOf("CCStructAssign")) { - O << "assert(0 && \"Not Implemented\");\n"; + O << IndentStr << + "State.HandleStruct(ValNo, ValVT, LocVT, LocInfo, ArgFlags);\n"; + O << IndentStr << "return false;\n"; } else { Action->dump(); throw "Unknown CCAction!"; Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (revision 40777) +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (working copy) @@ -3848,8 +3848,15 @@ Flags |= ISD::ParamFlags::InReg; if (Attrs && Attrs->paramHasAttr(j, ParamAttr::StructRet)) Flags |= ISD::ParamFlags::StructReturn; - if (Attrs && Attrs->paramHasAttr(j, ParamAttr::ByVal)) + if (Attrs && Attrs->paramHasAttr(j, ParamAttr::ByVal)) { Flags |= ISD::ParamFlags::ByVal; + const PointerType *Ty = cast<PointerType>(I->getType()); + const StructType *STy = cast<StructType>(Ty->getElementType()); + unsigned StructAlign = Log2_32(getTargetData()->getABITypeAlignment(STy)); + unsigned StructSize = getTargetData()->getTypeSize(STy); + Flags |= (StructAlign << ISD::ParamFlags::ByValAlignOffs); + Flags |= (StructSize << ISD::ParamFlags::ByValSizeOffs); + } if (Attrs && Attrs->paramHasAttr(j, ParamAttr::Nest)) Flags |= ISD::ParamFlags::Nest; Flags |= (OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs); Index: lib/CodeGen/SelectionDAG/CallingConvLower.cpp =================================================================== --- lib/CodeGen/SelectionDAG/CallingConvLower.cpp (revision 40777) +++ lib/CodeGen/SelectionDAG/CallingConvLower.cpp (working copy) @@ -28,7 +28,18 @@ UsedRegs.resize(MRI.getNumRegs()); } +void CCState::HandleStruct(unsigned ValNo, MVT::ValueType ValVT, + MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo, + unsigned ArgFlags) { + unsigned Align = 1 << ((ArgFlags & ISD::ParamFlags::ByValAlign) >> + ISD::ParamFlags::ByValAlignOffs); + unsigned Size = (ArgFlags & ISD::ParamFlags::ByValSize) >> + ISD::ParamFlags::ByValSizeOffs; + unsigned Offset = AllocateStack(Size, Align); + addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); +} + /// MarkAllocated - Mark a register and all of its aliases as allocated. void CCState::MarkAllocated(unsigned Reg) { UsedRegs[Reg/32] |= 1 << (Reg&31); @@ -99,4 +110,3 @@ } } } - Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp (revision 40777) +++ lib/Target/X86/X86ISelLowering.cpp (working copy) @@ -1245,7 +1245,12 @@ int FI = MFI->CreateFixedObject(MVT::getSizeInBits(VA.getValVT())/8, VA.getLocMemOffset()); SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy()); - ArgValues.push_back(DAG.getLoad(VA.getValVT(), Root, FIN, NULL, 0)); + + unsigned Flags = cast<ConstantSDNode>(Op.getOperand(3 + i))->getValue(); + if (Flags & ISD::ParamFlags::ByVal) + ArgValues.push_back(FIN); + else + ArgValues.push_back(DAG.getLoad(VA.getValVT(), Root, FIN, NULL, 0)); } }
_______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits