Hello, Everyone. Attached patch will enable llvm-gcc to use sret & inreg attributes.
-- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University.
diff -r 19e687420e52 gcc/config/i386/cygming.h --- a/gcc/config/i386/cygming.h Sun Jan 28 02:52:06 2007 +0300 +++ b/gcc/config/i386/cygming.h Sun Jan 28 17:55:48 2007 +0300 @@ -429,6 +429,8 @@ extern int i386_pe_dllimport_p (tree); #endif /* APPLE LOCAL begin LLVM */ +#ifdef ENABLE_LLVM + /* LLVM specific stuff for supporting dllimport & dllexport linkage output */ #define TARGET_ADJUST_LLVM_LINKAGE(GV, decl) \ @@ -439,18 +441,11 @@ extern int i386_pe_dllimport_p (tree); (GV)->setLinkage(GlobalValue::DLLExportLinkage); \ } \ } - -/* LLVM specific stuff for supporting calling convention output */ - -#define TARGET_ADJUST_LLVM_CC(CC, type) \ - { \ - tree type_attributes = TYPE_ATTRIBUTES (type); \ - if (lookup_attribute ("stdcall", type_attributes)) { \ - CC = CallingConv::X86_StdCall; \ - } else if (lookup_attribute("fastcall", type_attributes)) { \ - CC = CallingConv::X86_FastCall; \ - } \ - } \ - + +/* Add general target specific stuff */ +#include "llvm-i386-target.h" + /* APPLE LOCAL end LLVM */ + +#endif diff -r 19e687420e52 gcc/config/i386/darwin.h --- a/gcc/config/i386/darwin.h Sun Jan 28 02:52:06 2007 +0300 +++ b/gcc/config/i386/darwin.h Sun Jan 28 17:57:02 2007 +0300 @@ -343,3 +343,13 @@ extern void ix86_darwin_init_expanders ( #undef TARGET_DEEP_BRANCH_PREDICTION #define TARGET_DEEP_BRANCH_PREDICTION ((m_PPRO | m_K6 | m_ATHLON_K8 | m_PENT4) & TUNEMASK) /* APPLE LOCAL end 4106131 */ + +/* APPLE LOCAL begin LLVM */ +#ifdef ENABLE_LLVM + +/* Add general target specific stuff */ +#include "llvm-i386-target.h" + +/* APPLE LOCAL end LLVM */ + +#endif diff -r 19e687420e52 gcc/config/i386/linux.h --- a/gcc/config/i386/linux.h Sun Jan 28 02:52:06 2007 +0300 +++ b/gcc/config/i386/linux.h Sun Jan 28 17:57:05 2007 +0300 @@ -190,11 +190,15 @@ Boston, MA 02111-1307, USA. */ #ifdef ENABLE_LLVM /* Yes, we're supporting PIC codegen for X86-Linux-ELF target! */ - #define LLVM_SET_TARGET_OPTIONS(argvec) \ if (flag_pic) \ argvec.push_back ("--relocation-model=pic"); \ else \ argvec.push_back ("--relocation-model=static"); -#endif + +/* Add general target specific stuff */ +#include "llvm-i386-target.h" + /* APPLE LOCAL end LLVM */ + +#endif diff -r 19e687420e52 gcc/llvm-abi.h --- a/gcc/llvm-abi.h Sun Jan 28 02:52:06 2007 +0300 +++ b/gcc/llvm-abi.h Fri Jan 26 11:31:36 2007 +0300 @@ -47,6 +47,8 @@ extern "C" { /// DefaultABIClient - This is a simple implementation of the ABI client /// interface that can be subclassed. struct DefaultABIClient { + bool isStructReturn() { return false; } + /// HandleScalarResult - This callback is invoked if the function returns a /// simple scalar result value. void HandleScalarResult(const Type *RetTy) {} @@ -136,6 +138,8 @@ protected: Client &C; public: DefaultABI(Client &c) : C(c) {} + + bool isStructReturn() const { return C.isStructReturn(); } /// HandleReturnType - This is invoked by the target-independent code for the /// return type. It potentially breaks down the argument and invokes methods diff -r 19e687420e52 gcc/llvm-convert.cpp --- a/gcc/llvm-convert.cpp Sun Jan 28 02:52:06 2007 +0300 +++ b/gcc/llvm-convert.cpp Sun Jan 28 02:53:45 2007 +0300 @@ -1876,6 +1876,7 @@ namespace { tree CallExpression; std::vector<Value*> &CallOperands; CallingConv::ID &CallingConvention; + bool isStructRet; BasicBlock *CurBB; Value *DestLoc; std::vector<Value*> LocStack; @@ -1886,6 +1887,7 @@ namespace { : CallExpression(exp), CallOperands(ops), CallingConvention(cc), CurBB(bb), DestLoc(destloc) { CallingConvention = CallingConv::C; + isStructRet = false; #ifdef TARGET_ADJUST_LLVM_CC tree ftype; if (tree fdecl = get_callee_fndecl(exp)) { @@ -1931,8 +1933,8 @@ namespace { /// function. void HandleAggregateShadowArgument(const PointerType *PtrArgTy, bool RetPtr) { - // Make sure this call is marked as csret calling convention. - CallingConvention = CallingConv::CSRet; + // Make sure this call is marked as 'struct return'. + isStructRet = true; // If the front-end has already made the argument explicit, don't do it // again. diff -r 19e687420e52 gcc/llvm-types.cpp --- a/gcc/llvm-types.cpp Sun Jan 28 02:52:06 2007 +0300 +++ b/gcc/llvm-types.cpp Fri Jan 26 23:32:03 2007 +0300 @@ -468,13 +468,17 @@ namespace { const Type *&RetTy; std::vector<const Type*> &ArgTypes; unsigned &CallingConv; + bool isStructRet; bool KNRPromotion; public: FunctionTypeConversion(const Type *&retty, std::vector<const Type*> &AT, unsigned &CC, bool KNR) : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) { CallingConv = CallingConv::C; - } + isStructRet = false; + } + + bool isStructReturn() const { return isStructRet; } /// HandleScalarResult - This callback is invoked if the function returns a /// simple scalar result value. @@ -502,8 +506,8 @@ namespace { // In any case, there is a dummy shadow argument though! ArgTypes.push_back(PtrArgTy); - // Also, switch the calling convention to C Struct Return. - CallingConv = CallingConv::CSRet; + // Also, switch the to C Struct Return. + isStructRet = true; } void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) { @@ -584,36 +588,68 @@ const FunctionType *TypeConverter::Conve // the function will be correctly sign or zero extended to 32-bits by // the LLVM code gen. FunctionType::ParamAttrsList ParamAttrs; - if (CallingConv == CallingConv::C || CallingConv == CallingConv::CSRet) { + unsigned RAttributes = FunctionType::NoAttributeSet; + if (CallingConv == CallingConv::C) { tree ResultTy = TREE_TYPE(type); if (TREE_CODE(ResultTy) == BOOLEAN_TYPE) { if (TREE_INT_CST_LOW(TYPE_SIZE(ResultTy)) < INT_TYPE_SIZE) - ParamAttrs.push_back(FunctionType::ZExtAttribute); - } else if (TREE_CODE(ResultTy) == INTEGER_TYPE && - TREE_INT_CST_LOW(TYPE_SIZE(ResultTy)) < INT_TYPE_SIZE) - if (TYPE_UNSIGNED(ResultTy)) - ParamAttrs.push_back(FunctionType::ZExtAttribute); - else - ParamAttrs.push_back(FunctionType::SExtAttribute); - else - ParamAttrs.push_back(FunctionType::NoAttributeSet); - tree Args = TYPE_ARG_TYPES(type); - unsigned Idx = 1; - for (; Args && TREE_VALUE(Args) != void_type_node; Args = TREE_CHAIN(Args)){ - tree Ty = TREE_VALUE(Args); + RAttributes |= FunctionType::ZExtAttribute; + } else { + if (TREE_CODE(ResultTy) == INTEGER_TYPE && + TREE_INT_CST_LOW(TYPE_SIZE(ResultTy)) < INT_TYPE_SIZE) + if (TYPE_UNSIGNED(ResultTy)) + RAttributes |= FunctionType::ZExtAttribute; + else + RAttributes |= FunctionType::SExtAttribute; + } + } + ParamAttrs.push_back(FunctionType::ParameterAttributes(RAttributes)); + + unsigned Idx = 1; + bool isFirstArg = true; + + int lparam = 0; +#ifdef LLVM_TARGET_ENABLE_REGPARM + LLVM_TARGET_INIT_REGPARM(lparam, type); +#endif // LLVM_TARGET_ENABLE_REGPARM + + for (tree Args = TYPE_ARG_TYPES(type); + Args && TREE_VALUE(Args) != void_type_node; + Args = TREE_CHAIN(Args)) { + unsigned Attributes = FunctionType::NoAttributeSet; + tree Ty = TREE_VALUE(Args); + + if (CallingConv == CallingConv::C) { if (TREE_CODE(Ty) == BOOLEAN_TYPE) { if (TREE_INT_CST_LOW(TYPE_SIZE(Ty)) < INT_TYPE_SIZE) - ParamAttrs.push_back(FunctionType::ZExtAttribute); + Attributes |= FunctionType::ZExtAttribute; } else if (TREE_CODE(Ty) == INTEGER_TYPE && - TREE_INT_CST_LOW(TYPE_SIZE(Ty)) < INT_TYPE_SIZE) + TREE_INT_CST_LOW(TYPE_SIZE(Ty)) < INT_TYPE_SIZE) { if (TYPE_UNSIGNED(Ty)) - ParamAttrs.push_back(FunctionType::ZExtAttribute); - else - ParamAttrs.push_back(FunctionType::SExtAttribute); - else - ParamAttrs.push_back(FunctionType::NoAttributeSet); - Idx++; - } + Attributes |= FunctionType::ZExtAttribute; + else + Attributes |= FunctionType::SExtAttribute; + } + } + + // Handle struct return + if (isFirstArg) { + if (ABIConverter.isStructReturn()) { + Attributes |= FunctionType::StructRetAttribute; + //printf("Struct return!\n"); + } + isFirstArg = false; + } + +#ifdef LLVM_TARGET_ENABLE_REGPARM + if (TREE_CODE(Ty) == INTEGER_TYPE || TREE_CODE(Ty) == POINTER_TYPE) + LLVM_ADJUST_REGPARM_ATTRIBUTE(Attributes, TREE_INT_CST_LOW(TYPE_SIZE(Ty)), + isVarArg, lparam); +#endif // LLVM_TARGET_ENABLE_REGPARM + + Idx++; + + ParamAttrs.push_back(FunctionType::ParameterAttributes(Attributes)); } return FunctionType::get(RetTy, ArgTypes, isVarArg, ParamAttrs); } --- /dev/null 2000-10-22 01:01:00.000000000 +0400 +++ a/gcc/config/i386/llvm-i386-target.h 2007-01-28 17:54:06.349945062 +0300 @@ -0,0 +1,61 @@ +/* APPLE LOCAL begin LLVM (ENTIRE FILE!) */ +/* Some target-specific hooks for gcc->llvm conversion +Copyright (C) 2007 Free Software Foundation, Inc. +Contributed by Anton Korobeynikov ([EMAIL PROTECTED]) + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +/* LLVM specific stuff for supporting calling convention output */ +#define TARGET_ADJUST_LLVM_CC(CC, type) \ + { \ + tree type_attributes = TYPE_ATTRIBUTES (type); \ + if (lookup_attribute ("stdcall", type_attributes)) { \ + CC = CallingConv::X86_StdCall; \ + } else if (lookup_attribute("fastcall", type_attributes)) { \ + CC = CallingConv::X86_FastCall; \ + } \ + } \ + +/* LLVM specific stuff for converting gcc's `regparm` attribute to LLVM's + `inreg` parameter attribute */ +#define LLVM_TARGET_ENABLE_REGPARM + +#define LLVM_TARGET_INIT_REGPARM(local_regparm, type) \ + { \ + tree attr; \ + local_regparm = ix86_regparm; \ + attr = lookup_attribute ("regparm", \ + TYPE_ATTRIBUTES (type)); \ + if (attr) { \ + local_regparm = TREE_INT_CST_LOW (TREE_VALUE \ + (TREE_VALUE (attr))); \ + } \ + } + +#define LLVM_ADJUST_REGPARM_ATTRIBUTE(Attribute, Size, \ + isVarArg, local_regparm) \ + { \ + if (!isVarArg && !TARGET_64BIT) { \ + int words = (Size + BITS_PER_WORD - 1) / BITS_PER_WORD; \ + local_regparm -= words; \ + if (local_regparm>=0) { \ + Attribute |= FunctionType::InRegAttribute; \ + } else \ + local_regparm = 0; \ + } \ + }
_______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits