diff options
24 files changed, 502 insertions, 838 deletions
diff --git a/include/llvm/CallingConv.h b/include/llvm/CallingConv.h index e6ffd281e6..4bacb1d954 100644 --- a/include/llvm/CallingConv.h +++ b/include/llvm/CallingConv.h @@ -30,14 +30,6 @@ namespace CallingConv { /// certain amounts of prototype mismatch. C = 0, - /// CSRet - C Struct Return calling convention. This convention requires - /// that the function return void and take a pointer as the first argument - /// of the struct. This is used by targets which need to distinguish - /// between C functions returning a structure, and C functions taking a - /// structure pointer as the first argument to the function. - CSRet = 1, - - // Generic LLVM calling conventions. None of these calling conventions // support varargs calls, and all assume that the caller and callee // prototype exactly match. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index faa0e35da0..11c6ad6c53 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -133,20 +133,25 @@ namespace ISD { // UNDEF - An undefined node UNDEF, - /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG) - This node represents the formal - /// arguments for a function. CC# is a Constant value indicating the - /// calling convention of the function, and ISVARARG is a flag that - /// indicates whether the function is varargs or not. This node has one - /// result value for each incoming argument, plus one for the output chain. - /// It must be custom legalized. + /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node + /// represents the formal arguments for a function. CC# is a Constant value + /// indicating the calling convention of the function, and ISVARARG is a + /// flag that indicates whether the function is varargs or not. This node + /// has one result value for each incoming argument, plus one for the output + /// chain. It must be custom legalized. See description of CALL node for + /// FLAG argument contents explanation. /// FORMAL_ARGUMENTS, /// RV1, RV2...RVn, CHAIN = CALL(CHAIN, CC#, ISVARARG, ISTAILCALL, CALLEE, - /// ARG0, SIGN0, ARG1, SIGN1, ... ARGn, SIGNn) + /// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn) /// This node represents a fully general function call, before the legalizer - /// runs. This has one result value for each argument / signness pair, plus - /// a chain result. It must be custom legalized. + /// runs. This has one result value for each argument / flag pair, plus + /// a chain result. It must be custom legalized. Flag argument indicates + /// misc. argument attributes. Currently: + /// Bit 0 - signness + /// Bit 1 - 'inreg' attribute + /// Bit 2 - 'sret' attribute CALL, // EXTRACT_ELEMENT - This is used to get the first or second (determined by diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index c1e3a98a04..06f3a98807 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -134,7 +134,9 @@ public: NoAttributeSet = 0, ///< No attribute value has been set ZExtAttribute = 1, ///< zero extended before/after call SExtAttribute = 1 << 1, ///< sign extended before/after call - NoReturnAttribute = 1 << 2 ///< mark the function as not returning + NoReturnAttribute = 1 << 2, ///< mark the function as not returning + InRegAttribute = 1 << 3, ///< force argument to be passed in register + StructRetAttribute= 1 << 4 ///< hidden pointer to structure to return }; typedef std::vector<ParameterAttributes> ParamAttrsList; private: @@ -176,6 +178,10 @@ public: /// unsigned getNumParams() const { return unsigned(ContainedTys.size()-1); } + bool isStructReturn() const { + return (getNumParams() && paramHasAttr(1, StructRetAttribute)); + } + /// The parameter attributes for the \p ith parameter are returned. The 0th /// parameter refers to the return type of the function. /// @returns The ParameterAttributes for the \p ith parameter. diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 34bc3ad7ee..49d6624f8e 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -730,6 +730,8 @@ public: SDOperand Node; const Type* Ty; bool isSigned; + bool isInReg; + bool isSRet; }; typedef std::vector<ArgListEntry> ArgListTy; virtual std::pair<SDOperand, SDOperand> diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 44ffa473e4..b24857e967 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -82,7 +82,8 @@ ModulePass *createGlobalDCEPass(); /// the specified function. Otherwise, it deletes as much of the module as /// possible, except for the function specified. /// -ModulePass *createFunctionExtractionPass(Function *F, bool deleteFn = false); +ModulePass *createFunctionExtractionPass(Function *F, bool deleteFn = false, + bool relinkCallees = false); //===----------------------------------------------------------------------===// diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index e688868802..96eedff5d5 100644 --- a/lib/AsmParser/Lexer.l +++ b/lib/AsmParser/Lexer.l @@ -227,7 +227,6 @@ sideeffect { return SIDEEFFECT; } cc { return CC_TOK; } ccc { return CCC_TOK; } -csretcc { return CSRETCC_TOK; } fastcc { return FASTCC_TOK; } coldcc { return COLDCC_TOK; } x86_stdcallcc { return X86_STDCALLCC_TOK; } @@ -287,6 +286,8 @@ call { RET_TOK(OtherOpVal, Call, CALL); } trunc { RET_TOK(CastOpVal, Trunc, TRUNC); } zext { RET_TOK(CastOpVal, ZExt, ZEXT); } sext { RET_TOK(CastOpVal, SExt, SEXT); } +inreg { return INREG; } +sret { return SRET; } fptrunc { RET_TOK(CastOpVal, FPTrunc, FPTRUNC); } fpext { RET_TOK(CastOpVal, FPExt, FPEXT); } uitofp { RET_TOK(CastOpVal, UIToFP, UITOFP); } diff --git a/lib/AsmParser/Lexer.l.cvs b/lib/AsmParser/Lexer.l.cvs index e688868802..96eedff5d5 100644 --- a/lib/AsmParser/Lexer.l.cvs +++ b/lib/AsmParser/Lexer.l.cvs @@ -227,7 +227,6 @@ sideeffect { return SIDEEFFECT; } cc { return CC_TOK; } ccc { return CCC_TOK; } -csretcc { return CSRETCC_TOK; } fastcc { return FASTCC_TOK; } coldcc { return COLDCC_TOK; } x86_stdcallcc { return X86_STDCALLCC_TOK; } @@ -287,6 +286,8 @@ call { RET_TOK(OtherOpVal, Call, CALL); } trunc { RET_TOK(CastOpVal, Trunc, TRUNC); } zext { RET_TOK(CastOpVal, ZExt, ZEXT); } sext { RET_TOK(CastOpVal, SExt, SEXT); } +inreg { return INREG; } +sret { return SRET; } fptrunc { RET_TOK(CastOpVal, FPTrunc, FPTRUNC); } fpext { RET_TOK(CastOpVal, FPExt, FPEXT); } uitofp { RET_TOK(CastOpVal, UIToFP, UITOFP); } diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 03832e7c9f..a5c4b67cb3 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -984,8 +984,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token DLLIMPORT DLLEXPORT EXTERN_WEAK %token OPAQUE EXTERNAL TARGET TRIPLE ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT -%token CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK -%token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK +%token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK %token DATALAYOUT %type <UIntVal> OptCallingConv %type <ParamAttrs> OptParamAttrs ParamAttr @@ -1017,7 +1016,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR // Function Attributes -%token NORETURN +%token NORETURN INREG SRET // Visibility Styles %token DEFAULT HIDDEN @@ -1119,7 +1118,6 @@ FunctionDefineLinkage OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CCC_TOK { $$ = CallingConv::C; } | - CSRETCC_TOK { $$ = CallingConv::CSRet; } | FASTCC_TOK { $$ = CallingConv::Fast; } | COLDCC_TOK { $$ = CallingConv::Cold; } | X86_STDCALLCC_TOK { $$ = CallingConv::X86_StdCall; } | @@ -1131,8 +1129,10 @@ OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CHECK_FOR_ERROR }; -ParamAttr : ZEXT { $$ = FunctionType::ZExtAttribute; } - | SEXT { $$ = FunctionType::SExtAttribute; } +ParamAttr : ZEXT { $$ = FunctionType::ZExtAttribute; } + | SEXT { $$ = FunctionType::SExtAttribute; } + | INREG { $$ = FunctionType::InRegAttribute; } + | SRET { $$ = FunctionType::StructRetAttribute; } ; OptParamAttrs : /* empty */ { $$ = FunctionType::NoAttributeSet; } diff --git a/lib/AsmParser/llvmAsmParser.y.cvs b/lib/AsmParser/llvmAsmParser.y.cvs index 03832e7c9f..a5c4b67cb3 100644 --- a/lib/AsmParser/llvmAsmParser.y.cvs +++ b/lib/AsmParser/llvmAsmParser.y.cvs @@ -984,8 +984,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token DLLIMPORT DLLEXPORT EXTERN_WEAK %token OPAQUE EXTERNAL TARGET TRIPLE ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT -%token CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK -%token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK +%token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK %token DATALAYOUT %type <UIntVal> OptCallingConv %type <ParamAttrs> OptParamAttrs ParamAttr @@ -1017,7 +1016,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR // Function Attributes -%token NORETURN +%token NORETURN INREG SRET // Visibility Styles %token DEFAULT HIDDEN @@ -1119,7 +1118,6 @@ FunctionDefineLinkage OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CCC_TOK { $$ = CallingConv::C; } | - CSRETCC_TOK { $$ = CallingConv::CSRet; } | FASTCC_TOK { $$ = CallingConv::Fast; } | COLDCC_TOK { $$ = CallingConv::Cold; } | X86_STDCALLCC_TOK { $$ = CallingConv::X86_StdCall; } | @@ -1131,8 +1129,10 @@ OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CHECK_FOR_ERROR }; -ParamAttr : ZEXT { $$ = FunctionType::ZExtAttribute; } - | SEXT { $$ = FunctionType::SExtAttribute; } +ParamAttr : ZEXT { $$ = FunctionType::ZExtAttribute; } + | SEXT { $$ = FunctionType::SExtAttribute; } + | INREG { $$ = FunctionType::InRegAttribute; } + | SRET { $$ = FunctionType::StructRetAttribute; } ; OptParamAttrs : /* empty */ { $$ = FunctionType::NoAttributeSet; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 5f5f0d360f..84754ce9af 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2168,6 +2168,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { const char *FnName = 0; if (Node->getOpcode() == ISD::MEMSET) { Entry.Node = Tmp2; Entry.isSigned = false; Entry.Ty = IntPtrTy; + Entry.isInReg = false; Args.push_back(Entry); // Extend the (previously legalized) ubyte argument to be an int value // for the call. @@ -2176,6 +2177,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { else Tmp3 = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Tmp3); Entry.Node = Tmp3; Entry.Ty = Type::Int32Ty; Entry.isSigned = true; + Entry.isInReg = false; Args.push_back(Entry); Entry.Node = Tmp4; Entry.Ty = IntPtrTy; Entry.isSigned = false; Args.push_back(Entry); @@ -2183,7 +2185,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { FnName = "memset"; } else if (Node->getOpcode() == ISD::MEMCPY || Node->getOpcode() == ISD::MEMMOVE) { - Entry.Ty = IntPtrTy; Entry.isSigned = false; + Entry.Ty = IntPtrTy; Entry.isSigned = false; Entry.isInReg = false; Entry.Node = Tmp2; Args.push_back(Entry); Entry.Node = Tmp3; Args.push_back(Entry); Entry.Node = Tmp4; Args.push_back(Entry); @@ -4124,7 +4126,7 @@ SDOperand SelectionDAGLegalize::ExpandLibCall(const char *Name, SDNode *Node, MVT::ValueType ArgVT = Node->getOperand(i).getValueType(); const Type *ArgTy = MVT::getTypeForValueType(ArgVT); Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; - Entry.isSigned = isSigned; + Entry.isSigned = isSigned; Entry.isInReg = false; Args.push_back(Entry); } SDOperand Callee = DAG.getExternalSymbol(Name, TLI.getPointerTy()); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 12c5d8e18d..c1d70006c1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2167,6 +2167,8 @@ void SelectionDAGLowering::visitCall(CallInst &I) { SDOperand ArgNode = getValue(Arg); Entry.Node = ArgNode; Entry.Ty = Arg->getType(); Entry.isSigned = FTy->paramHasAttr(i, FunctionType::SExtAttribute); + Entry.isInReg = FTy->paramHasAttr(i, FunctionType::InRegAttribute); + Entry.isSRet = FTy->paramHasAttr(i, FunctionType::StructRetAttribute); Args.push_back(Entry); } @@ -2761,6 +2763,8 @@ void SelectionDAGLowering::visitMalloc(MallocInst &I) { Entry.Node = Src; Entry.Ty = TLI.getTargetData()->getIntPtrType(); Entry.isSigned = false; + Entry.isInReg = false; + Entry.isSRet = false; Args.push_back(Entry); std::pair<SDOperand,SDOperand> Result = @@ -2777,6 +2781,8 @@ void SelectionDAGLowering::visitFree(FreeInst &I) { Entry.Node = getValue(I.getOperand(0)); Entry.Ty = TLI.getTargetData()->getIntPtrType(); Entry.isSigned = false; + Entry.isInReg = false; + Entry.isSRet = false; Args.push_back(Entry); MVT::ValueType IntPtr = TLI.getPointerTy(); std::pair<SDOperand,SDOperand> Result = @@ -2859,6 +2865,7 @@ static SDOperand ExpandScalarFormalArgs(MVT::ValueType VT, SDNode *Arg, /// integrated into SDISel. std::vector<SDOperand> TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { + const FunctionType *FTy = F.getFunctionType(); // Add CC# and isVararg as operands to the FORMAL_ARGUMENTS node. std::vector<SDOperand> Ops; Ops.push_back(DAG.getRoot()); @@ -2867,16 +2874,22 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { // Add one result value for each formal argument. std::vector<MVT::ValueType> RetVals; + unsigned j = 0; for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { MVT::ValueType VT = getValueType(I->getType()); + bool isInReg = FTy->paramHasAttr(++j, FunctionType::InRegAttribute); + bool isSRet = FTy->paramHasAttr(j, FunctionType::StructRetAttribute); + unsigned Flags = (isInReg << 1) | (isSRet << 2); switch (getTypeAction(VT)) { default: assert(0 && "Unknown type action!"); case Legal: RetVals.push_back(VT); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); break; case Promote: RetVals.push_back(getTypeToTransformTo(VT)); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); break; case Expand: if (VT != MVT::Vector) { @@ -2885,8 +2898,10 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { // integers it turns into. MVT::ValueType NVT = getTypeToExpandTo(VT); unsigned NumVals = getNumElements(VT); - for (unsigned i = 0; i != NumVals; ++i) + for (unsigned i = 0; i != NumVals; ++i) { RetVals.push_back(NVT); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); + } } else { // Otherwise, this is a vector type. We only support legal vectors // right now. @@ -2898,6 +2913,7 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { MVT::ValueType TVT = MVT::getVectorType(getValueType(EltTy), NumElems); if (TVT != MVT::Other && isTypeLegal(TVT)) { RetVals.push_back(TVT); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); } else { assert(0 && "Don't support illegal by-val vector arguments yet!"); } @@ -2917,7 +2933,6 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { // Set up the return result vector. Ops.clear(); - const FunctionType *FTy = F.getFunctionType(); unsigned i = 0; unsigned Idx = 1; for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; @@ -2984,13 +2999,13 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { /// ExpandScalarCallArgs - Recursively expand call argument node by /// bit_converting it or extract a pair of elements from the larger node. static void ExpandScalarCallArgs(MVT::ValueType VT, SDOperand Arg, - bool isSigned, + unsigned Flags, SmallVector<SDOperand, 32> &Ops, SelectionDAG &DAG, TargetLowering &TLI) { if (TLI.getTypeAction(VT) != TargetLowering::Expand) { Ops.push_back(Arg); - Ops.push_back(DAG.getConstant(isSigned, MVT::i32)); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); return; } @@ -2998,7 +3013,7 @@ static void ExpandScalarCallArgs(MVT::ValueType VT, SDOperand Arg, unsigned NumVals = MVT::getSizeInBits(VT) / MVT::getSizeInBits(EVT); if (NumVals == 1) { Arg = DAG.getNode(ISD::BIT_CONVERT, EVT, Arg); - ExpandScalarCallArgs(EVT, Arg, isSigned, Ops, DAG, TLI); + ExpandScalarCallArgs(EVT, Arg, Flags, Ops, DAG, TLI); } else if (NumVals == 2) { SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, EVT, Arg, DAG.getConstant(0, TLI.getPointerTy())); @@ -3006,8 +3021,8 @@ static void ExpandScalarCallArgs(MVT::ValueType VT, SDOperand Arg, DAG.getConstant(1, TLI.getPointerTy())); if (!TLI.isLittleEndian()) std::swap(Lo, Hi); - ExpandScalarCallArgs(EVT, Lo, isSigned, Ops, DAG, TLI); - ExpandScalarCallArgs(EVT, Hi, isSigned, Ops, DAG, TLI); + ExpandScalarCallArgs(EVT, Lo, Flags, Ops, DAG, TLI); + ExpandScalarCallArgs(EVT, Hi, Flags, Ops, DAG, TLI); } else { // Value scalarized into many values. Unimp for now. assert(0 && "Cannot expand i64 -> i16 yet!"); @@ -3036,11 +3051,14 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, MVT::ValueType VT = getValueType(Args[i].Ty); SDOperand Op = Args[i].Node; bool isSigned = Args[i].isSigned; + bool isInReg = Args[i].isInReg; + bool isSRet = Args[i].isSRet; + unsigned Flags = (isSRet << 2) | (isInReg << 1) | isSigned; switch (getTypeAction(VT)) { default: assert(0 && "Unknown type action!"); case Legal: Ops.push_back(Op); - Ops.push_back(DAG.getConstant(isSigned, MVT::i32)); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); break; case Promote: if (MVT::isInteger(VT)) { @@ -3051,14 +3069,14 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, Op = DAG.getNode(ISD::FP_EXTEND, getTypeToTransformTo(VT), Op); } Ops.push_back(Op); - Ops.push_back(DAG.getConstant(isSigned, MVT::i32)); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); break; case Expand: if (VT != MVT::Vector) { // If this is a large integer, it needs to be broken down into small // integers. Figure out what the source elt type is and how many small // integers it is. - ExpandScalarCallArgs(VT, Op, isSigned, Ops, DAG, *this); + ExpandScalarCallArgs(VT, Op, Flags, Ops, DAG, *this); } else { // Otherwise, this is a vector type. We only support legal vectors // right now. @@ -3073,7 +3091,7 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, // Insert a VBIT_CONVERT of the MVT::Vector type to the packed type. Op = DAG.getNode(ISD::VBIT_CONVERT, TVT, Op); Ops.push_back(Op); - Ops.push_back(DAG.getConstant(isSigned, MVT::i32)); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); } else { assert(0 && "Don't support illegal by-val vector call args yet!"); abort(); diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 594a48e788..e2268d212b 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -352,7 +352,6 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { SDOperand Chain = Op.getOperand(0); unsigned CallConv = cast<ConstantSDNode>(Op.getOperand(1))->getValue(); assert((CallConv == CallingConv::C || - CallConv == CallingConv::CSRet || CallConv == CallingConv::Fast) && "unknown calling convention"); SDOperand Callee = Op.getOperand(4); unsigned NumOps = (Op.getNumOperands() - 5) / 2; diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 9faba6bd81..0c808131b6 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1748,8 +1748,8 @@ void CWriter::printContainedStructs(const Type *Ty, } void CWriter::printFunctionSignature(const Function *F, bool Prototype) { - /// isCStructReturn - Should this function actually return a struct by-value? - bool isCStructReturn = F->getCallingConv() == CallingConv::CSRet; + /// isStructReturn - Should this function actually return a struct by-value? + bool isStructReturn = F->getFunctionType()->isStructReturn(); if (F->hasInternalLinkage()) Out << "static "; if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) "; @@ -1778,7 +1778,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { // If this is a struct-return function, don't print the hidden // struct-return argument. - if (isCStructReturn) { + if (isStructReturn) { assert(I != E && "Invalid struct return function!"); ++I; } @@ -1804,7 +1804,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { // If this is a struct-return function, don't print the hidden // struct-return argument. - if (isCStructReturn) { + if (isStructReturn) { assert(I != E && "Invalid struct return function!"); ++I; } @@ -1832,7 +1832,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { // Get the return tpe for the function. const Type *RetTy; - if (!isCStructReturn) + if (!isStructReturn) RetTy = F->getReturnType(); else { // If this is a struct-return function, print the struct-return type. @@ -1855,11 +1855,14 @@ static inline bool isFPIntBitCast(const Instruction &I) { } void CWriter::printFunction(Function &F) { + /// isStructReturn - Should this function actually return a struct by-value? + bool isStructReturn = F.getFunctionType()->isStructReturn(); + printFunctionSignature(&F, false); Out << " {\n"; // If this is a struct return function, handle the result with magic. - if (F.getCallingConv() == CallingConv::CSRet) { + if (isStructReturn) { const Type *StructTy = cast<PointerType>(F.arg_begin()->getType())->getElementType(); Out << " "; @@ -1977,7 +1980,10 @@ void CWriter::printBasicBlock(BasicBlock *BB) { // void CWriter::visitReturnInst(ReturnInst &I) { // If this is a struct return function, return the temporary struct. - if (I.getParent()->getParent()->getCallingConv() == CallingConv::CSRet) { + bool isStructReturn = I.getParent()->getParent()-> + getFunctionType()->isStructReturn(); + + if (isStructReturn) { Out << " return StructReturn;\n"; return; } @@ -2468,9 +2474,12 @@ void CWriter::visitCallInst(CallInst &I) { Value *Callee = I.getCalledValue(); + const PointerType *PTy = cast<PointerType>(Callee->getType()); + const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); + // If this is a call to a struct-return function, assign to the first // parameter instead of passing it to the call. - bool isStructRet = I.getCallingConv() == CallingConv::CSRet; + bool isStructRet = FTy->isStructReturn(); if (isStructRet) { Out << "*("; writeOperand(I.getOperand(1)); @@ -2478,9 +2487,6 @@ void CWriter::visitCallInst(CallInst &I) { } if (I.isTailCall()) Out << " /*tail*/ "; - - const PointerType *PTy = cast<PointerType>(Callee->getType()); - const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); if (!WroteCallee) { // If this is an indirect call to a struct return function, we need to cast diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 097ca91a30..041ff36af3 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1360,9 +1360,9 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // On PPC64, promote integers to 64-bit values. if (isPPC64 && Arg.getValueType() == MVT::i32) { - unsigned ExtOp = ISD::ZERO_EXTEND; - if (cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue()) - ExtOp = ISD::SIGN_EXTEND; + unsigned Flags = cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue(); + unsigned ExtOp = (Flags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + Arg = DAG.getNode(ExtOp, MVT::i64, Arg); } diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 5c28fac10c..ff85828c5a 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -71,6 +71,10 @@ void X86SharedAsmPrinter::decorateName(std::string &Name, unsigned CC = F->getCallingConv(); if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall) return; + + // Decorate names only when we're targeting Cygwin/Mingw32 targets + if (!Subtarget->isTargetCygMing()) + return; FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 9f9fb7248e..0dce6fd6ed 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -424,57 +424,104 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) } //===----------------------------------------------------------------------===// -// C Calling Convention implementation +// C & StdCall Calling Convention implementation //===----------------------------------------------------------------------===// +// StdCall calling convention seems to be standard for many Windows' API +// routines and around. It differs from C calling convention just a little: +// callee should clean up the stack, not caller. Symbols should be also +// decorated in some fancy way :) It doesn't support any vector arguments. /// AddLiveIn - This helper function adds the specified physical register to the /// MachineFunction as a live in value. It also creates a corresponding virtual /// register for it. static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, - TargetRegisterClass *RC) { + const TargetRegisterClass *RC) { assert(RC->contains(PReg) && "Not the correct regclass!"); unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC); MF.addLiveIn(PReg, VReg); return VReg; } -/// HowToPassCCCArgument - Returns how an formal argument of the specified type +/// HowToPassArgument - Returns how an formal argument of the specified type /// should be passed. If it is through stack, returns the size of the stack -/// slot; if it is through XMM register, returns the number of XMM registers -/// are needed. +/// slot; if it is through integer or XMM register, returns the number of +/// integer or XMM registers are needed. static void -HowToPassCCCArgument(MVT::ValueType ObjectVT, unsigned NumXMMRegs, - unsigned &ObjSize, unsigned &ObjXMMRegs) { +HowToPassCallArgument(MVT::ValueType ObjectVT, + bool ArgInReg, + unsigned NumIntRegs, unsigned NumXMMRegs, + unsigned MaxNumIntRegs, + unsigned &ObjSize, unsigned &ObjIntRegs, + unsigned &ObjXMMRegs, + bool AllowVectors = true) { + ObjSize = 0; + ObjIntRegs = 0; ObjXMMRegs = 0; + if (MaxNumIntRegs>3) { + // We don't have too much registers on ia32! :) + MaxNumIntRegs = 3; + } + switch (ObjectVT) { default: assert(0 && "Unhandled argument type!"); - case MVT::i8: ObjSize = 1; break; - case MVT::i16: ObjSize = 2; break; - case MVT::i32: ObjSize = 4; break; - case MVT::i64: ObjSize = 8; break; - case MVT::f32: ObjSize = 4; break; - case MVT::f64: ObjSize = 8; break; + case MVT::i8: + if (ArgInReg && (NumIntRegs < MaxNumIntRegs)) + ObjIntRegs = 1; + else + ObjSize = 1; + break; + case MVT::i16: + if (ArgInReg && (NumIntRegs < MaxNumIntRegs)) + ObjIntRegs = 1; + else + ObjSize = 2; + break; + case MVT::i32: + if (ArgInReg && (NumIntRegs < MaxNumIntRegs)) + ObjIntRegs = 1; + else + ObjSize = 4; + break; + case MVT::i64: + if (ArgInReg && (NumIntRegs+2 <= MaxNumIntRegs)) { + ObjIntRegs = 2; + } else if (ArgInReg && (NumIntRegs+1 <= MaxNumIntRegs)) { + ObjIntRegs = 1; + ObjSize = 4; + } else + ObjSize = 8; + case MVT::f32: + ObjSize = 4; + break; + case MVT::f64: + ObjSize = 8; + break; case MVT::v16i8: case MVT::v8i16: case MVT::v4i32: case MVT::v2i64: case MVT::v4f32: case MVT::v2f64: - if (NumXMMRegs < 4) - ObjXMM |