[llvm-commits] [llvm-gcc-4.2] r49038 - in /llvm-gcc-4.2/trunk/gcc: llvm-abi.h llvm-convert.cpp llvm-types.cpp
Duncan Sands
baldrick at free.fr
Tue Apr 1 10:05:40 PDT 2008
Author: baldrick
Date: Tue Apr 1 12:05:39 2008
New Revision: 49038
URL: http://llvm.org/viewvc/llvm-project?rev=49038&view=rev
Log:
Rework call-argument handling so that it is
entirely driven by the ABI. That way there
is no longer any need for logic about vectors
and by-invisible-reference parameters to be
duplicated in EmitCallOf.
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=49038&r1=49037&r2=49038&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Tue Apr 1 12:05:39 2008
@@ -73,9 +73,13 @@
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) {}
+ /// HandleScalarArgument - This is the primary callback that specifies an
+ /// LLVM argument to pass. It is only used for first class types.
+ void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {}
+
+ /// HandleByInvisibleReferenceArgument - This callback is invoked if a pointer
+ /// (of type PtrTy) to the argument is passed rather than the argument itself.
+ void HandleByInvisibleReferenceArgument(const llvm::Type *PtrTy, tree type) {}
/// HandleByValArgument - This callback is invoked if the aggregate function
/// argument is passed by value.
@@ -331,7 +335,7 @@
// not include variable sized fields here.
std::vector<const Type*> Elts;
if (isPassedByInvisibleReference(type)) { // variable size -> by-ref.
- C.HandleScalarArgument(PointerType::getUnqual(Ty), type);
+ C.HandleByInvisibleReferenceArgument(PointerType::getUnqual(Ty), type);
} else if (Ty->getTypeID()==Type::VectorTyID) {
if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
PassInIntegerRegisters(type, Ty);
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=49038&r1=49037&r2=49038&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Tue Apr 1 12:05:39 2008
@@ -2282,40 +2282,66 @@
/// definition for this target to figure out how to pass arguments into the
/// stack/regs for a function call.
struct FunctionCallArgumentConversion : public DefaultABIClient {
- tree CallExpression;
SmallVector<Value*, 16> &CallOperands;
- CallingConv::ID &CallingConvention;
- LLVMBuilder &Builder;
+ SmallVector<Value*, 2> LocStack;
+ const FunctionType *FTy;
const MemRef *DestLoc;
+ bool useReturnSlot;
+ LLVMBuilder &Builder;
+ Value *TheValue;
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), isShadowRet(false) {
- CallingConvention = CallingConv::C;
-#ifdef TARGET_ADJUST_LLVM_CC
- tree ftype;
- if (tree fdecl = get_callee_fndecl(exp)) {
- ftype = TREE_TYPE(fdecl);
- } else {
- ftype = TREE_TYPE(TREE_OPERAND(exp,0));
+ FunctionCallArgumentConversion(SmallVector<Value*, 16> &ops,
+ const FunctionType *FnTy,
+ const MemRef *destloc,
+ bool ReturnSlotOpt,
+ LLVMBuilder &b)
+ : CallOperands(ops), FTy(FnTy), DestLoc(destloc),
+ useReturnSlot(ReturnSlotOpt), Builder(b), isShadowRet(false) { }
+
+ // Push the address of an argument.
+ void pushAddress(Value *Loc) {
+ assert(Loc && "Invalid location!");
+ LocStack.push_back(Loc);
+ }
+
+ // Push the value of an argument.
+ void pushValue(Value *V) {
+ assert(LocStack.empty() && "Value only allowed at top level!");
+ LocStack.push_back(NULL);
+ TheValue = V;
+ }
- // If it's call to pointer, we look for the function type.
- if (TREE_CODE(ftype) == POINTER_TYPE)
- ftype = TREE_TYPE(ftype);
+ // Get the address of the current location.
+ Value *getAddress(void) {
+ assert(!LocStack.empty());
+ Value *&Loc = LocStack.back();
+ if (!Loc) {
+ // A value. Store to a temporary, and return the temporary's address.
+ // Any future access to this argument will reuse the same address.
+ Loc = TheTreeToLLVM->CreateTemporary(TheValue->getType());
+ Builder.CreateStore(TheValue, Loc);
}
-
- TARGET_ADJUST_LLVM_CC(CallingConvention, ftype);
-#endif
+ return Loc;
}
-
- void setLocation(Value *Loc) {
- LocStack.push_back(Loc);
+
+ // Get the value of the current location (of type Ty).
+ Value *getValue(const Type *Ty) {
+ assert(!LocStack.empty());
+ Value *Loc = LocStack.back();
+ if (Loc) {
+ // An address. Convert to the right type and load the value out.
+ if (Loc->getType() != PointerType::getUnqual(Ty))
+ Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(Ty), "tmp");
+ return Builder.CreateLoad(Loc, "val");
+ } else {
+ // A value - just return it.
+ assert(TheValue->getType() == Ty && "Value not of expected type!");
+ return TheValue;
+ }
}
+
void clear() {
assert(LocStack.size() == 1 && "Imbalance!");
LocStack.clear();
@@ -2349,7 +2375,7 @@
assert(DestLoc == 0 &&
"Call returns a scalar but caller expects aggregate!");
}
-
+
/// HandleAggregateResultAsScalar - This callback is invoked if the function
/// returns an aggregate value by bit converting it to the specified scalar
/// type and returning that.
@@ -2371,7 +2397,7 @@
// The result is unused, but still needs to be stored somewhere.
Value *Buf = TheTreeToLLVM->CreateTemporary(PtrArgTy->getElementType());
CallOperands.push_back(Buf);
- } else if (CALL_EXPR_RETURN_SLOT_OPT(CallExpression)) {
+ } else if (useReturnSlot) {
// Letting the call write directly to the final destination is safe and
// may be required. Do not use a buffer.
CallOperands.push_back(DestLoc->Ptr);
@@ -2387,6 +2413,10 @@
isShadowRet = true;
}
+ /// 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) {
assert(DestLoc == 0 &&
"Call returns a scalar but caller expects aggregate!");
@@ -2399,36 +2429,54 @@
isShadowRet = true;
}
+ /// HandleScalarArgument - This is the primary callback that specifies an
+ /// LLVM argument to pass. It is only used for first class types.
void HandleScalarArgument(const llvm::Type *LLVMTy, tree type) {
- assert(!LocStack.empty());
- Value *Loc = LocStack.back();
- if (cast<PointerType>(Loc->getType())->getElementType() != LLVMTy)
- // This always deals with pointer types so BitCast is appropriate
- Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(LLVMTy), "tmp");
-
- CallOperands.push_back(Builder.CreateLoad(Loc, "tmp"));
+ Value *Loc = getValue(LLVMTy);
+
+ // Perform any implicit type conversions.
+ if (CallOperands.size() < FTy->getNumParams()) {
+ const Type *CalledTy = FTy->getParamType(CallOperands.size());
+ if (Loc->getType() != CalledTy) {
+ assert(type && "Inconsistent parameter types?");
+ bool isSigned = !TYPE_UNSIGNED(type);
+ Loc = TheTreeToLLVM->CastToAnyType(Loc, isSigned, CalledTy, false);
+ }
+ }
+
+ CallOperands.push_back(Loc);
}
-
+
+ /// HandleByInvisibleReferenceArgument - This callback is invoked if a pointer
+ /// (of type PtrTy) to the argument is passed rather than the argument itself.
+ void HandleByInvisibleReferenceArgument(const llvm::Type *PtrTy, tree type){
+ Value *Loc = getAddress();
+ if (Loc->getType() != PtrTy)
+ Loc = Builder.CreateBitCast(Loc, PtrTy, "tmp");
+ CallOperands.push_back(Loc);
+ }
+
/// HandleByValArgument - This callback is invoked if the aggregate function
/// argument is passed by value. It is lowered to a parameter passed by
/// reference with an additional parameter attribute "ByVal".
void HandleByValArgument(const llvm::Type *LLVMTy, tree type) {
- assert(!LocStack.empty());
- Value *Loc = LocStack.back();
+ Value *Loc = getAddress();
assert(PointerType::getUnqual(LLVMTy) == Loc->getType());
CallOperands.push_back(Loc);
}
+ /// 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.
void EnterField(unsigned FieldNo, const llvm::Type *StructTy) {
- Value *Loc = LocStack.back();
- if (cast<PointerType>(Loc->getType())->getElementType() != StructTy)
- // This always deals with pointer types so BitCast is appropriate
- Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(StructTy),
+ Value *Loc = getAddress();
+ if (Loc->getType() != PointerType::getUnqual(StructTy))
+ Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(StructTy),
"tmp");
-
- LocStack.push_back(Builder.CreateStructGEP(Loc, FieldNo, "tmp"));
+ pushAddress(Builder.CreateStructGEP(Loc, FieldNo, "elt"));
}
void ExitField() {
+ assert(!LocStack.empty());
LocStack.pop_back();
}
};
@@ -2445,6 +2493,7 @@
if (PAL.isEmpty() && isa<Function>(Callee))
PAL = cast<Function>(Callee)->getParamAttrs();
+ // Work out whether to use an invoke or an ordinary call.
if (!tree_could_throw_p(exp))
// This call does not throw - mark it 'nounwind'.
PAL = PAL.addAttr(0, ParamAttr::NoUnwind);
@@ -2474,15 +2523,26 @@
}
}
+ tree fndecl = get_callee_fndecl(exp);
+ tree fntype = fndecl ?
+ TREE_TYPE(fndecl) : TREE_TYPE (TREE_TYPE(TREE_OPERAND (exp, 0)));
+
+ // Determine the calling convention.
+ CallingConv::ID CallingConvention = CallingConv::C;
+#ifdef TARGET_ADJUST_LLVM_CC
+ TARGET_ADJUST_LLVM_CC(CallingConvention, fntype);
+#endif
+
SmallVector<Value*, 16> CallOperands;
- CallingConv::ID CallingConvention;
- FunctionCallArgumentConversion Client(exp, CallOperands, CallingConvention,
- Builder, DestLoc);
+ const PointerType *PFTy = cast<PointerType>(Callee->getType());
+ const FunctionType *FTy = cast<FunctionType>(PFTy->getElementType());
+ FunctionCallArgumentConversion Client(CallOperands, FTy, DestLoc,
+ CALL_EXPR_RETURN_SLOT_OPT(exp),
+ Builder);
TheLLVMABI<FunctionCallArgumentConversion> ABIConverter(Client);
// Handle the result, including struct returns.
- tree fndecl = get_callee_fndecl(exp);
- ABIConverter.HandleReturnType(TREE_TYPE(exp),
+ ABIConverter.HandleReturnType(TREE_TYPE(exp),
fndecl ? DECL_BUILT_IN(fndecl) : false);
// Pass the static chain, if any, as the first parameter.
@@ -2490,52 +2550,26 @@
CallOperands.push_back(Emit(TREE_OPERAND(exp, 2), 0));
// Loop over the arguments, expanding them and adding them to the op list.
- const PointerType *PFTy = cast<PointerType>(Callee->getType());
- const FunctionType *FTy = cast<FunctionType>(PFTy->getElementType());
for (tree arg = TREE_OPERAND(exp, 1); arg; arg = TREE_CHAIN(arg)) {
- const Type *ActualArgTy = ConvertType(TREE_TYPE(TREE_VALUE(arg)));
- const Type *ArgTy = ActualArgTy;
- if (CallOperands.size() < FTy->getNumParams())
- ArgTy = FTy->getParamType(CallOperands.size());
-
- // If we are implicitly passing the address of this argument instead of
- // passing it by value, handle this first.
- if (isPassedByInvisibleReference(TREE_TYPE(TREE_VALUE(arg)))) {
- // Get the address of the parameter passed in.
- LValue ArgVal = EmitLV(TREE_VALUE(arg));
- assert(!ArgVal.isBitfield() && "Bitfields shouldn't be invisible refs!");
- Value *Ptr = ArgVal.Ptr;
-
- if (CallOperands.size() >= FTy->getNumParams())
- ArgTy = PointerType::getUnqual(ArgTy);
- CallOperands.push_back(BitCastToType(Ptr, ArgTy));
- } else if (ActualArgTy->isFirstClassType()) {
- Value *V = Emit(TREE_VALUE(arg), 0);
- if (TREE_CODE(TREE_TYPE(TREE_VALUE(arg)))==VECTOR_TYPE &&
- LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(TREE_TYPE(TREE_VALUE(arg)))) {
- // Passed as integer registers. We need a stack object, not a value.
- MemRef NewLoc = CreateTempLoc(ConvertType(TREE_TYPE(TREE_VALUE(arg))));
- StoreInst *St = Builder.CreateStore(V, NewLoc.Ptr, false);
- Client.setLocation(NewLoc.Ptr);
- ParameterAttributes Attributes = ParamAttr::None;
- ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), &Attributes);
- if (Attributes != ParamAttr::None)
- PAL = PAL.addAttr(CallOperands.size(), Attributes);
- } else {
- bool isSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_VALUE(arg)));
- CallOperands.push_back(CastToAnyType(V, isSigned, ArgTy, false));
- }
+ const Type *ArgTy = ConvertType(TREE_TYPE(TREE_VALUE(arg)));
+
+ // Push the argument.
+ if (ArgTy->isFirstClassType()) {
+ // A scalar - push the value.
+ Client.pushValue(Emit(TREE_VALUE(arg), 0));
} else {
- // If this is an aggregate value passed by-value, use the current ABI to
- // determine how the parameters are passed.
- LValue LV = EmitLV(TREE_VALUE(arg));
- assert(!LV.isBitfield() && "Bitfields are first-class types!");
- Client.setLocation(LV.Ptr);
- ParameterAttributes Attributes = ParamAttr::None;
- ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), &Attributes);
- if (Attributes != ParamAttr::None)
- PAL = PAL.addAttr(CallOperands.size(), Attributes);
+ // An aggregate - push the address.
+ LValue ArgVal = EmitLV(TREE_VALUE(arg));
+ assert(!ArgVal.isBitfield() && "Bitfields are first-class types!");
+ Client.pushAddress(ArgVal.Ptr);
}
+
+ ParameterAttributes Attributes = ParamAttr::None;
+ ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), &Attributes);
+ if (Attributes != ParamAttr::None)
+ PAL = PAL.addAttr(CallOperands.size(), Attributes);
+
+ Client.clear();
}
// Compile stuff like:
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=49038&r1=49037&r2=49038&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Tue Apr 1 12:05:39 2008
@@ -995,6 +995,12 @@
ArgTypes.push_back(LLVMTy);
}
+ /// HandleByInvisibleReferenceArgument - This callback is invoked if a pointer
+ /// (of type PtrTy) to the argument is passed rather than the argument itself.
+ void HandleByInvisibleReferenceArgument(const llvm::Type *PtrTy, tree type) {
+ ArgTypes.push_back(PtrTy);
+ }
+
/// HandleByValArgument - This callback is invoked if the aggregate function
/// argument is passed by value. It is lowered to a parameter passed by
/// reference with an additional parameter attribute "ByVal".
More information about the llvm-commits
mailing list