diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AsmParser/Lexer.l | 3 | ||||
-rw-r--r-- | lib/AsmParser/Lexer.l.cvs | 3 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 12 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y.cvs | 12 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 40 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 1 | ||||
-rw-r--r-- | lib/Target/CBackend/CBackend.cpp | 28 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 6 | ||||
-rw-r--r-- | lib/Target/X86/X86AsmPrinter.cpp | 4 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 1096 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.h | 22 | ||||
-rw-r--r-- | lib/Target/X86/X86Subtarget.cpp | 1 | ||||
-rw-r--r-- | lib/Transforms/IPO/DeadArgumentElimination.cpp | 7 | ||||
-rw-r--r-- | lib/Transforms/IPO/ExtractFunction.cpp | 29 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 3 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 4 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 10 |
18 files changed, 470 insertions, 817 deletions
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) - ObjXMMRegs = 1; - else - ObjSize = 16; - break; + if (AllowVectors) { + if (NumXMMRegs < 4) + ObjXMMRegs = 1; + else + ObjSize = 16; + break; + } else + assert(0 && "Unhandled argument type [vector]!"); } } -SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) { +SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG, + bool isStdCall) { unsigned NumArgs = Op.Val->getNumValues() - 1; MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); SDOperand Root = Op.getOperand(0); std::vector<SDOperand> ArgValues; + bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; // Add DAG nodes to load the arguments... On entry to a function on the X86, // the stack frame looks like this: @@ -484,57 +531,115 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) // [ESP + 8] -- second argument, if first argument is <= 4 bytes in size // ... // - unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot - unsigned NumXMMRegs = 0; // XMM regs used for parameter passing. + unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot + unsigned NumSRetBytes= 0; // How much bytes on stack used for struct return + unsigned NumXMMRegs = 0; // XMM regs used for parameter passing. + unsigned NumIntRegs = 0; // Integer regs used for parameter passing + static const unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3 }; + static const unsigned GPRArgRegs[][3] = { + { X86::AL, X86::DL, X86::CL }, + { X86::AX, X86::DX, X86::CX }, + { X86::EAX, X86::EDX, X86::ECX } + }; + static const TargetRegisterClass* GPRClasses[3] = { + X86::GR8RegisterClass, X86::GR16RegisterClass, X86::GR32RegisterClass + }; + + // Handle regparm attribute + std::vector<bool> ArgInRegs(NumArgs, false); + std::vector<bool> SRetArgs(NumArgs, false); + if (!isVarArg) { + for (unsigned i = 0; i<NumArgs; ++i) { + unsigned Flags = cast<ConstantSDNode>(Op.getOperand(3+i))->getValue(); + ArgInRegs[i] = (Flags >> 1) & 1; + SRetArgs[i] = (Flags >> 2) & 1; + } + } + for (unsigned i = 0; i < NumArgs; ++i) { MVT::ValueType ObjectVT = Op.getValue(i).getValueType(); unsigned ArgIncrement = 4; unsigned ObjSize = 0; unsigned ObjXMMRegs = 0; - HowToPassCCCArgument(ObjectVT, NumXMMRegs, ObjSize, ObjXMMRegs); + unsigned ObjIntRegs = 0; + unsigned Reg = 0; + SDOperand ArgValue; + + HowToPassCallArgument(ObjectVT, + ArgInRegs[i], + NumIntRegs, NumXMMRegs, 3, + ObjSize, ObjIntRegs, ObjXMMRegs, + !isStdCall); + if (ObjSize > 4) ArgIncrement = ObjSize; - SDOperand ArgValue; - if (ObjXMMRegs) { - // Passed in a XMM register. - unsigned Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], - X86::VR128RegisterClass); - ArgValue= DAG.getCopyFromReg(Root, Reg, ObjectVT); - ArgValues.push_back(ArgValue); + if (ObjIntRegs || ObjXMMRegs) { + switch (ObjectVT) { + default: assert(0 && "Unhandled argument type!"); + case MVT::i8: + case MVT::i16: + case MVT::i32: { + unsigned RegToUse = GPRArgRegs[ObjectVT-MVT::i8][NumIntRegs]; + Reg = AddLiveIn(MF, RegToUse, GPRClasses[ObjectVT-MVT::i8]); + ArgValue = DAG.getCopyFromReg(Root, Reg, ObjectVT); + break; + } + case MVT::v16i8: + case MVT::v8i16: + case MVT::v4i32: + case MVT::v2i64: + case MVT::v4f32: + case MVT::v2f64: + assert(!isStdCall && "Unhandled argument type!"); + Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], X86::VR128RegisterClass); + ArgValue = DAG.getCopyFromReg(Root, Reg, ObjectVT); + break; + } + NumIntRegs += ObjIntRegs; NumXMMRegs += ObjXMMRegs; - } else { + } + if (ObjSize) { // XMM arguments have to be aligned on 16-byte boundary. if (ObjSize == 16) ArgOffset = ((ArgOffset + 15) / 16) * 16; - // Create the frame index object for this incoming parameter... + // Create the SelectionDAG nodes corresponding to a load from this + // parameter. int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy()); ArgValue = DAG.getLoad(Op.Val->getValueType(i), Root, FIN, NULL, 0); - ArgValues.push_back(ArgValue); - ArgOffset += ArgIncrement; // Move on to the next argument... + + ArgOffset += ArgIncrement; // Move on to the next argument. + if (SRetArgs[i]) + NumSRetBytes += ArgIncrement; } + + ArgValues.push_back(ArgValue); } ArgValues.push_back(Root); // If the function takes variable number of arguments, make a frame index for // the start of the first vararg value... for expansion of llvm.va_start. - bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; if (isVarArg) VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset); + + if (isStdCall && !isVarArg) { + BytesToPopOnReturn = ArgOffset; // Callee pops everything.. + BytesCallerReserves = 0; + } else { + BytesToPopOnReturn = NumSRetBytes; // Callee pops hidden struct pointer. + BytesCallerReserves = ArgOffset; + } + RegSaveFrameIndex = 0xAAAAAAA; // X86-64 only. ReturnAddrIndex = 0; // No return address slot generated yet. - BytesToPopOnReturn = 0; // Callee pops nothing. - BytesCallerReserves = ArgOffset; - // If this is a struct return on, the callee pops the hidden struct - // pointer. This is common for Darwin/X86, Linux & Mingw32 targets. - if (MF.getFunction()->getCallingConv() == CallingConv::CSRet) - BytesToPopOnReturn = 4; + + MF.getInfo<X86FunctionInfo>()->setBytesToPopOnReturn(BytesToPopOnReturn); // Return the new list of results. std::vector<MVT::ValueType> RetVTs(Op.Val->value_begin(), @@ -542,52 +647,64 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) return DAG.getNode(ISD::MERGE_VALUES, RetVTs, &ArgValues[0],ArgValues.size()); } - -SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG) { +SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, + bool isStdCall) { SDOperand Chain = Op.getOperand(0); - unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue(); + bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0; SDOperand Callee = Op.getOperand(4); MVT::ValueType RetVT= Op.Val->getValueType(0); unsigned NumOps = (Op.getNumOperands() - 5) / 2; - // Keep track of the number of XMM regs passed so far. - unsigned NumXMMRegs = 0; static const unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3 }; + static const unsigned GPR32ArgRegs[] = { + X86::EAX, X86::EDX, X86::ECX + }; // Count how many bytes are to be pushed on the stack. - unsigned NumBytes = 0; + unsigned NumBytes = 0; + // Keep track of the number of integer regs passed so far. + unsigned NumIntRegs = 0; + // Keep track of t |