[llvm-commits] [llvm-gcc-4.2] r48778 - in /llvm-gcc-4.2/trunk/gcc: llvm-abi.h llvm-convert.cpp llvm-types.cpp
Duncan Sands
baldrick at free.fr
Tue Mar 25 10:02:29 PDT 2008
Author: baldrick
Date: Tue Mar 25 12:02:29 2008
New Revision: 48778
URL: http://llvm.org/viewvc/llvm-project?rev=48778&view=rev
Log:
Add infrastructure for returning scalar values
via a "shadow" sret argument, and let it handle
the vector-as-aggregate case. I changed some
names and cleaned up whitespace while there.
Modified:
llvm-gcc-4.2/trunk/gcc/llvm-abi.h
llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=48778&r1=48777&r2=48778&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Tue Mar 25 12:02:29 2008
@@ -49,27 +49,38 @@
/// DefaultABIClient - This is a simple implementation of the ABI client
/// interface that can be subclassed.
struct DefaultABIClient {
- bool isStructReturn() { return false; }
-
+ bool isShadowReturn() { return false; }
+
/// HandleScalarResult - This callback is invoked if the function returns a
- /// simple scalar result value.
+ /// simple scalar result value, which is of type RetTy.
void HandleScalarResult(const Type *RetTy) {}
/// HandleAggregateResultAsScalar - This callback is invoked if the function
/// returns an aggregate value by bit converting it to the specified scalar
/// type and returning that.
void HandleAggregateResultAsScalar(const Type *ScalarTy) {}
-
+
/// HandleAggregateShadowArgument - This callback is invoked if the function
- /// returns an aggregate value by using a "shadow" first parameter. If RetPtr
- /// is set to true, the pointer argument itself is returned from the function.
+ /// returns an aggregate value by using a "shadow" first parameter, which is
+ /// a pointer to the aggregate, of type PtrArgTy. If RetPtr is set to true,
+ /// the pointer argument itself is returned from the function.
void HandleAggregateShadowArgument(const PointerType *PtrArgTy, bool RetPtr){}
-
-
+
+ /// HandleScalarShadowArgument - This callback is invoked if the function
+ /// returns a scalar value by using a "shadow" first parameter, which is a
+ /// pointer to the scalar, of type PtrArgTy. If RetPtr is set to true,
+ /// the pointer argument itself is returned from the function.
+ void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {}
+
+
/// HandleScalarArgument - This is the primary callback that specifies an LLVM
/// argument to pass.
void HandleScalarArgument(const llvm::Type *LLVMTy, tree argTreeType) {}
-
+
+ /// HandleByValArgument - This callback is invoked if the aggregate function
+ /// argument is passed by value.
+ void HandleByValArgument(const llvm::Type *LLVMTy, tree type) {}
+
/// EnterField - Called when we're about the enter the field of a struct
/// or union. FieldNo is the number of the element we are entering in the
/// LLVM Struct, StructTy is the LLVM type of the struct we are entering.
@@ -229,7 +240,7 @@
public:
DefaultABI(Client &c) : C(c) {}
- bool isStructReturn() const { return C.isStructReturn(); }
+ bool isShadowReturn() const { return C.isShadowReturn(); }
/// HandleReturnType - This is invoked by the target-independent code for the
/// return type. It potentially breaks down the argument and invokes methods
@@ -245,7 +256,7 @@
if (ScalarType)
C.HandleAggregateResultAsScalar(ConvertType(ScalarType));
else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin))
- C.HandleAggregateShadowArgument(PointerType::getUnqual(Ty), false);
+ C.HandleScalarShadowArgument(PointerType::getUnqual(Ty), false);
else
C.HandleScalarResult(Ty);
} else if (Ty->isFirstClassType() || Ty == Type::VoidTy) {
Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=48778&r1=48777&r2=48778&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Tue Mar 25 12:02:29 2008
@@ -459,7 +459,15 @@
}
++AI;
}
-
+
+ void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+ assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() &&
+ "No explicit return value?");
+ AI->setName("scalar.result");
+ SET_DECL_LLVM(DECL_RESULT(FunctionDecl), AI);
+ ++AI;
+ }
+
void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
Value *ArgVal = AI;
if (ArgVal->getType() != LLVMTy) {
@@ -2255,24 +2263,8 @@
// parameter for the chain.
Callee = BitCastToType(Callee, PointerType::getUnqual(Ty));
- Value *Result;
- if (TREE_CODE(TREE_TYPE(exp))==VECTOR_TYPE &&
- LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(TREE_TYPE(exp),
- fndecl ? DECL_BUILT_IN(fndecl) : false)) {
- // Vectors are first class types, so we need to return a value,
- // but this one is to be passed using sret. Pass in a DestLoc, if
- // there isn't one already, and return a Load from it as the value.
- if (!DestLoc) {
- MemRef NewLoc = CreateTempLoc(ConvertType(TREE_TYPE(exp)));
- DestLoc = &NewLoc;
- }
- EmitCallOf(Callee, exp, DestLoc, PAL);
- LoadInst *LI = Builder.CreateLoad(DestLoc->Ptr, false, "tmp");
- Result = LI;
- } else {
- //EmitCall(exp, DestLoc);
- Result = EmitCallOf(Callee, exp, DestLoc, PAL);
- }
+ //EmitCall(exp, DestLoc);
+ Value *Result = EmitCallOf(Callee, exp, DestLoc, PAL);
// If the function has the volatile bit set, then it is a "noreturn" function.
// Output an unreachable instruction right after the function to prevent LLVM
@@ -2295,14 +2287,15 @@
CallingConv::ID &CallingConvention;
LLVMBuilder &Builder;
const MemRef *DestLoc;
- MemRef BufLoc;
+ MemRef RetBuf;
std::vector<Value*> LocStack;
+ bool isShadowRet;
FunctionCallArgumentConversion(tree exp, SmallVector<Value*, 16> &ops,
CallingConv::ID &cc,
LLVMBuilder &b, const MemRef *destloc)
: CallExpression(exp), CallOperands(ops), CallingConvention(cc),
- Builder(b), DestLoc(destloc) {
+ Builder(b), DestLoc(destloc), isShadowRet(false) {
CallingConvention = CallingConv::C;
#ifdef TARGET_ADJUST_LLVM_CC
tree ftype;
@@ -2328,15 +2321,24 @@
LocStack.clear();
}
- // CopyOutResult - If the (aggregate) return result was redirected to a
- // buffer, copy it to the final destination.
- void CopyOutResult(tree result_type) {
- if (BufLoc.Ptr && DestLoc) {
- // A buffer was used for the aggregate return result. Copy it out now.
- assert(ConvertType(result_type) ==
- cast<PointerType>(BufLoc.Ptr->getType())->getElementType() &&
+ bool isShadowReturn() { return isShadowRet; }
+
+ // EmitShadowResult - If the return result was redirected to a buffer,
+ // emit it now.
+ Value *EmitShadowResult(tree type, const MemRef *DestLoc) {
+ if (!RetBuf.Ptr)
+ return 0;
+
+ if (DestLoc) {
+ // Copy out the aggregate return value now.
+ assert(ConvertType(type) ==
+ cast<PointerType>(RetBuf.Ptr->getType())->getElementType() &&
"Inconsistent result types!");
- TheTreeToLLVM->EmitAggregateCopy(*DestLoc, BufLoc, result_type);
+ TheTreeToLLVM->EmitAggregateCopy(*DestLoc, RetBuf, type);
+ return 0;
+ } else {
+ // Read out the scalar return value now.
+ return Builder.CreateLoad(RetBuf.Ptr, "result");
}
}
@@ -2377,9 +2379,24 @@
// Letting the call write directly to the final destination may not be
// safe (eg: if DestLoc aliases a parameter) and is not required - pass
// a buffer and copy it to DestLoc after the call.
- BufLoc = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
- CallOperands.push_back(BufLoc.Ptr);
+ RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
+ CallOperands.push_back(RetBuf.Ptr);
}
+
+ // Note the use of a shadow argument.
+ isShadowRet = true;
+ }
+
+ void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+ assert(DestLoc == 0 &&
+ "Call returns a scalar but caller expects aggregate!");
+ // Create a buffer to hold the result. The result will be loaded out of
+ // it after the call.
+ RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
+ CallOperands.push_back(RetBuf.Ptr);
+
+ // Note the use of a shadow argument.
+ isShadowRet = true;
}
void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
@@ -2558,13 +2575,14 @@
EmitBlock(NextBlock);
}
- Client.CopyOutResult(TREE_TYPE(exp));
+ if (Client.isShadowReturn())
+ return Client.EmitShadowResult(TREE_TYPE(exp), DestLoc);
if (Call->getType() == Type::VoidTy)
return 0;
-
+
Call->setName("tmp");
-
+
// If the caller expects an aggregate, we have a situation where the ABI for
// the current target specifies that the aggregate be returned in scalar
// registers even though it is an aggregate. We must bitconvert the scalar
Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=48778&r1=48777&r2=48778&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Tue Mar 25 12:02:29 2008
@@ -929,48 +929,61 @@
PATypeHolder &RetTy;
std::vector<PATypeHolder> &ArgTypes;
unsigned &CallingConv;
- bool isStructRet;
+ bool isShadowRet;
bool KNRPromotion;
public:
FunctionTypeConversion(PATypeHolder &retty, std::vector<PATypeHolder> &AT,
unsigned &CC, bool KNR)
: RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) {
CallingConv = CallingConv::C;
- isStructRet = false;
+ isShadowRet = false;
}
- bool isStructReturn() const { return isStructRet; }
-
+ bool isShadowReturn() const { return isShadowRet; }
+
/// HandleScalarResult - This callback is invoked if the function returns a
/// simple scalar result value.
void HandleScalarResult(const Type *RetTy) {
this->RetTy = RetTy;
}
-
+
/// HandleAggregateResultAsScalar - This callback is invoked if the function
/// returns an aggregate value by bit converting it to the specified scalar
/// type and returning that.
void HandleAggregateResultAsScalar(const Type *ScalarTy) {
RetTy = ScalarTy;
}
-
+
+ /// HandleShadowArgument - Handle an aggregate or scalar shadow argument.
+ void HandleShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+ // This function either returns void or the shadow argument,
+ // depending on the target.
+ RetTy = RetPtr ? PtrArgTy : Type::VoidTy;
+
+ // In any case, there is a dummy shadow argument though!
+ ArgTypes.push_back(PtrArgTy);
+
+ // Also, note the use of a shadow argument.
+ isShadowRet = true;
+ }
+
/// HandleAggregateShadowArgument - This callback is invoked if the function
- /// returns an aggregate value by using a "shadow" first parameter. If
- /// RetPtr is set to true, the pointer argument itself is returned from
- /// the function.
+ /// returns an aggregate value by using a "shadow" first parameter, which is
+ /// a pointer to the aggregate, of type PtrArgTy. If RetPtr is set to true,
+ /// the pointer argument itself is returned from the function.
void HandleAggregateShadowArgument(const PointerType *PtrArgTy,
bool RetPtr) {
- // If this function returns a structure by value, it either returns void
- // or the shadow argument, depending on the target.
- this->RetTy = RetPtr ? PtrArgTy : Type::VoidTy;
-
- // In any case, there is a dummy shadow argument though!
- ArgTypes.push_back(PtrArgTy);
-
- // Also, switch the to C Struct Return.
- isStructRet = true;
+ HandleShadowArgument(PtrArgTy, RetPtr);
}
-
+
+ /// HandleScalarShadowArgument - This callback is invoked if the function
+ /// returns a scalar value by using a "shadow" first parameter, which is a
+ /// pointer to the scalar, of type PtrArgTy. If RetPtr is set to true,
+ /// the pointer argument itself is returned from the function.
+ void HandleScalarShadowArgument(const PointerType *PtrArgTy, bool RetPtr) {
+ HandleShadowArgument(PtrArgTy, RetPtr);
+ }
+
void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
if (KNRPromotion) {
if (LLVMTy == Type::FloatTy)
@@ -1032,12 +1045,12 @@
if (RAttributes != ParamAttr::None)
Attrs.push_back(ParamAttrsWithIndex::get(0, RAttributes));
- // If this is a struct-return function, the dest loc is passed in as a
- // pointer. Mark that pointer as structret and noalias.
- if (ABIConverter.isStructReturn())
+ // If this function returns via a shadow argument, the dest loc is passed
+ // in as a pointer. Mark that pointer as struct-ret and noalias.
+ if (ABIConverter.isShadowReturn())
Attrs.push_back(ParamAttrsWithIndex::get(ArgTys.size(),
ParamAttr::StructRet | ParamAttr::NoAlias));
-
+
if (static_chain) {
// Pass the static chain as the first parameter.
ABIConverter.HandleArgument(TREE_TYPE(static_chain));
@@ -1113,7 +1126,7 @@
// Since they write the return value through a pointer,
// 'sret' functions cannot be 'readnone' or 'readonly'.
- if (ABIConverter.isStructReturn())
+ if (ABIConverter.isShadowReturn())
RAttributes &= ~(ParamAttr::ReadNone|ParamAttr::ReadOnly);
// Demote 'readnone' nested functions to 'readonly' since
@@ -1128,13 +1141,13 @@
if (RAttributes != ParamAttr::None)
Attrs.push_back(ParamAttrsWithIndex::get(0, RAttributes));
-
- // If this is a struct-return function, the dest loc is passed in as a
- // pointer. Mark that pointer as structret, and noalias.
- if (ABIConverter.isStructReturn())
+
+ // If this function returns via a shadow argument, the dest loc is passed
+ // in as a pointer. Mark that pointer as struct-ret and noalias.
+ if (ABIConverter.isShadowReturn())
Attrs.push_back(ParamAttrsWithIndex::get(ArgTypes.size(),
ParamAttr::StructRet | ParamAttr::NoAlias));
-
+
if (static_chain) {
// Pass the static chain as the first parameter.
ABIConverter.HandleArgument(TREE_TYPE(static_chain));
More information about the llvm-commits
mailing list