diff options
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp new file mode 100644 index 00000000000..932a5c5da8b --- /dev/null +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -0,0 +1,615 @@ +//===--- CGExpr.cpp - Emit LLVM Code from Expressions ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Expr nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Support/MathExtras.h" +using namespace clang; +using namespace CodeGen; + +//===--------------------------------------------------------------------===// +// Miscellaneous Helper Methods +//===--------------------------------------------------------------------===// + +/// CreateTempAlloca - This creates a alloca and inserts it into the entry +/// block. +llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty, + const char *Name) { + return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt); +} + +/// EvaluateExprAsBool - Perform the usual unary conversions on the specified +/// expression and compare the result against zero, returning an Int1Ty value. +llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { + QualType BoolTy = getContext().BoolTy; + if (!E->getType()->isComplexType()) + return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy); + + return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(),BoolTy); +} + +/// EmitAnyExpr - Emit code to compute the specified expression which can have +/// any type. The result is returned as an RValue struct. If this is an +/// aggregate expression, the aggloc/agglocvolatile arguments indicate where +/// the result should be returned. +RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, + bool isAggLocVolatile) { + if (!hasAggregateLLVMType(E->getType())) + return RValue::get(EmitScalarExpr(E)); + else if (E->getType()->isComplexType()) + return RValue::getComplex(EmitComplexExpr(E)); + + EmitAggExpr(E, AggLoc, isAggLocVolatile); + return RValue::getAggregate(AggLoc); +} + + +//===----------------------------------------------------------------------===// +// LValue Expression Emission +//===----------------------------------------------------------------------===// + +/// EmitLValue - Emit code to compute a designator that specifies the location +/// of the expression. +/// +/// This can return one of two things: a simple address or a bitfield +/// reference. In either case, the LLVM Value* in the LValue structure is +/// guaranteed to be an LLVM pointer type. +/// +/// If this returns a bitfield reference, nothing about the pointee type of +/// the LLVM value is known: For example, it may not be a pointer to an +/// integer. +/// +/// If this returns a normal address, and if the lvalue's C type is fixed +/// size, this method guarantees that the returned pointer type will point to +/// an LLVM type of the same size of the lvalue's type. If the lvalue has a +/// variable length type, this is not possible. +/// +LValue CodeGenFunction::EmitLValue(const Expr *E) { + switch (E->getStmtClass()) { + default: { + WarnUnsupported(E, "l-value expression"); + llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); + return LValue::MakeAddr(llvm::UndefValue::get(Ty)); + } + + case Expr::CallExprClass: return EmitCallExprLValue(cast<CallExpr>(E)); + case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E)); + case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); + case Expr::PreDefinedExprClass: + return EmitPreDefinedLValue(cast<PreDefinedExpr>(E)); + case Expr::StringLiteralClass: + return EmitStringLiteralLValue(cast<StringLiteral>(E)); + + case Expr::UnaryOperatorClass: + return EmitUnaryOpLValue(cast<UnaryOperator>(E)); + case Expr::ArraySubscriptExprClass: + return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); + case Expr::OCUVectorElementExprClass: + return EmitOCUVectorElementExpr(cast<OCUVectorElementExpr>(E)); + case Expr::MemberExprClass: return EmitMemberExpr(cast<MemberExpr>(E)); + } +} + +/// EmitLoadOfLValue - Given an expression that represents a value lvalue, +/// this method emits the address of the lvalue, then loads the result as an +/// rvalue, returning the rvalue. +RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { + if (LV.isSimple()) { + llvm::Value *Ptr = LV.getAddress(); + const llvm::Type *EltTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + + // Simple scalar l-value. + if (EltTy->isFirstClassType()) { + llvm::Value *V = Builder.CreateLoad(Ptr, "tmp"); + + // Bool can have different representation in memory than in registers. + if (ExprType->isBooleanType()) { + if (V->getType() != llvm::Type::Int1Ty) + V = Builder.CreateTrunc(V, llvm::Type::Int1Ty, "tobool"); + } + + return RValue::get(V); + } + + assert(ExprType->isFunctionType() && "Unknown scalar value"); + return RValue::get(Ptr); + } + + if (LV.isVectorElt()) { + llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), "tmp"); + return RValue::get(Builder.CreateExtractElement(Vec, LV.getVectorIdx(), + "vecext")); + } + + // If this is a reference to a subset of the elements of a vector, either + // shuffle the input or extract/insert them as appropriate. + if (LV.isOCUVectorElt()) + return EmitLoadOfOCUElementLValue(LV, ExprType); + + if (LV.isBitfield()) + return EmitLoadOfBitfieldLValue(LV, ExprType); + + assert(0 && "Unknown LValue type!"); + //an invalid RValue, but the assert will + //ensure that this point is never reached + return RValue(); +} + +RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, + QualType ExprType) { + llvm::Value *Ptr = LV.getBitfieldAddr(); + const llvm::Type *EltTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + unsigned EltTySize = EltTy->getPrimitiveSizeInBits(); + unsigned short BitfieldSize = LV.getBitfieldSize(); + unsigned short EndBit = LV.getBitfieldStartBit() + BitfieldSize; + + llvm::Value *V = Builder.CreateLoad(Ptr, "tmp"); + + llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - EndBit); + V = Builder.CreateShl(V, ShAmt, "tmp"); + + ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - BitfieldSize); + V = LV.isBitfieldSigned() ? + Builder.CreateAShr(V, ShAmt, "tmp") : + Builder.CreateLShr(V, ShAmt, "tmp"); + return RValue::get(V); +} + +// If this is a reference to a subset of the elements of a vector, either +// shuffle the input or extract/insert them as appropriate. +RValue CodeGenFunction::EmitLoadOfOCUElementLValue(LValue LV, + QualType ExprType) { + llvm::Value *Vec = Builder.CreateLoad(LV.getOCUVectorAddr(), "tmp"); + + unsigned EncFields = LV.getOCUVectorElts(); + + // If the result of the expression is a non-vector type, we must be + // extracting a single element. Just codegen as an extractelement. + const VectorType *ExprVT = ExprType->getAsVectorType(); + if (!ExprVT) { + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(0, EncFields); + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp")); + } + + // If the source and destination have the same number of elements, use a + // vector shuffle instead of insert/extracts. + unsigned NumResultElts = ExprVT->getNumElements(); + unsigned NumSourceElts = + cast<llvm::VectorType>(Vec->getType())->getNumElements(); + + if (NumResultElts == NumSourceElts) { + llvm::SmallVector<llvm::Constant*, 4> Mask; + for (unsigned i = 0; i != NumResultElts; ++i) { + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(i, EncFields); + Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx)); + } + + llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size()); + Vec = Builder.CreateShuffleVector(Vec, + llvm::UndefValue::get(Vec->getType()), + MaskV, "tmp"); + return RValue::get(Vec); + } + + // Start out with an undef of the result type. + llvm::Value *Result = llvm::UndefValue::get(ConvertType(ExprType)); + + // Extract/Insert each element of the result. + for (unsigned i = 0; i != NumResultElts; ++i) { + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(i, EncFields); + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + Elt = Builder.CreateExtractElement(Vec, Elt, "tmp"); + + llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Result = Builder.CreateInsertElement(Result, Elt, OutIdx, "tmp"); + } + + return RValue::get(Result); +} + + + +/// EmitStoreThroughLValue - Store the specified rvalue into the specified +/// lvalue, where both are guaranteed to the have the same type, and that type +/// is 'Ty'. +void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, + QualType Ty) { + if (!Dst.isSimple()) { + if (Dst.isVectorElt()) { + // Read/modify/write the vector, inserting the new element. + // FIXME: Volatility. + llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(), "tmp"); + Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(), + Dst.getVectorIdx(), "vecins"); + Builder.CreateStore(Vec, Dst.getVectorAddr()); + return; + } + + // If this is an update of elements of a vector, insert them as appropriate. + if (Dst.isOCUVectorElt()) + return EmitStoreThroughOCUComponentLValue(Src, Dst, Ty); + + if (Dst.isBitfield()) + return EmitStoreThroughBitfieldLValue(Src, Dst, Ty); + + assert(0 && "Unknown LValue type"); + } + + llvm::Value *DstAddr = Dst.getAddress(); + assert(Src.isScalar() && "Can't emit an agg store with this method"); + // FIXME: Handle volatility etc. + const llvm::Type *SrcTy = Src.getScalarVal()->getType(); + const llvm::PointerType *DstPtr = cast<llvm::PointerType>(DstAddr->getType()); + const llvm::Type *AddrTy = DstPtr->getElementType(); + unsigned AS = DstPtr->getAddressSpace(); + + if (AddrTy != SrcTy) + DstAddr = Builder.CreateBitCast(DstAddr, + llvm::PointerType::get(SrcTy, AS), + "storetmp"); + Builder.CreateStore(Src.getScalarVal(), DstAddr); +} + +void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, + QualType Ty) { + unsigned short StartBit = Dst.getBitfieldStartBit(); + unsigned short BitfieldSize = Dst.getBitfieldSize(); + llvm::Value *Ptr = Dst.getBitfieldAddr(); + const llvm::Type *EltTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + unsigned EltTySize = EltTy->getPrimitiveSizeInBits(); + + llvm::Value *NewVal = Src.getScalarVal(); + llvm::Value *OldVal = Builder.CreateLoad(Ptr, "tmp"); + + llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, StartBit); + NewVal = Builder.CreateShl(NewVal, ShAmt, "tmp"); + + llvm::Constant *Mask = llvm::ConstantInt::get( + llvm::APInt::getBitsSet(EltTySize, StartBit, + StartBit + BitfieldSize)); + + // Mask out any bits that shouldn't be set in the result. + NewVal = Builder.CreateAnd(NewVal, Mask, "tmp"); + + // Next, mask out the bits this bit-field should include from the old value. + Mask = llvm::ConstantExpr::getNot(Mask); + OldVal = Builder.CreateAnd(OldVal, Mask, "tmp"); + + // Finally, merge the two together and store it. + NewVal = Builder.CreateOr(OldVal, NewVal, "tmp"); + + Builder.CreateStore(NewVal, Ptr); +} + +void CodeGenFunction::EmitStoreThroughOCUComponentLValue(RValue Src, LValue Dst, + QualType Ty) { + // This access turns into a read/modify/write of the vector. Load the input + // value now. + llvm::Value *Vec = Builder.CreateLoad(Dst.getOCUVectorAddr(), "tmp"); + // FIXME: Volatility. + unsigned EncFields = Dst.getOCUVectorElts(); + + llvm::Value *SrcVal = Src.getScalarVal(); + + if (const VectorType *VTy = Ty->getAsVectorType()) { + unsigned NumSrcElts = VTy->getNumElements(); + + // Extract/Insert each element. + for (unsigned i = 0; i != NumSrcElts; ++i) { + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp"); + + unsigned Idx = OCUVectorElementExpr::getAccessedFieldNo(i, EncFields); + llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx); + Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp"); + } + } else { + // If the Src is a scalar (not a vector) it must be updating one element. + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(0, EncFields); + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp"); + } + + Builder.CreateStore(Vec, Dst.getOCUVectorAddr()); +} + + +LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { + const ValueDecl *D = E->getDecl(); + if (isa<BlockVarDecl>(D) || isa<ParmVarDecl>(D)) { + const VarDecl *VD = cast<VarDecl>(D); + if (VD->getStorageClass() == VarDecl::Extern) + return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false)); + else { + llvm::Value *V = LocalDeclMap[D]; + assert(V && "BlockVarDecl not entered in LocalDeclMap?"); + return LValue::MakeAddr(V); + } + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false)); + } else if (const FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) { + return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(FVD, false)); + } + assert(0 && "Unimp declref"); + //an invalid LValue, but the assert will + //ensure that this point is never reached. + return LValue(); +} + +LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { + // __extension__ doesn't affect lvalue-ness. + if (E->getOpcode() == UnaryOperator::Extension) + return EmitLValue(E->getSubExpr()); + + switch (E->getOpcode()) { + default: assert(0 && "Unknown unary operator lvalue!"); + case UnaryOperator::Deref: + return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr())); + case UnaryOperator::Real: + case UnaryOperator::Imag: + LValue LV = EmitLValue(E->getSubExpr()); + + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, + E->getOpcode() == UnaryOperator::Imag); + llvm::Value *Ops[] = {Zero, Idx}; + return LValue::MakeAddr(Builder.CreateGEP(LV.getAddress(), Ops, Ops+2, + "idx")); + } +} + +LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { + assert(!E->isWide() && "FIXME: Wide strings not supported yet!"); + const char *StrData = E->getStrData(); + unsigned Len = E->getByteLength(); + std::string StringLiteral(StrData, StrData+Len); + return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral)); +} + +LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) { + std::string FunctionName(CurFuncDecl->getName()); + std::string GlobalVarName; + + switch (E->getIdentType()) { + default: + assert(0 && "unknown pre-defined ident type"); + case PreDefinedExpr::Func: + GlobalVarName = "__func__."; + break; + case PreDefinedExpr::Function: + GlobalVarName = "__FUNCTION__."; + break; + case PreDefinedExpr::PrettyFunction: + // FIXME:: Demangle C++ method names + GlobalVarName = "__PRETTY_FUNCTION__."; + break; + } + + GlobalVarName += CurFuncDecl->getName(); + + // FIXME: Can cache/reuse these within the module. + llvm::Constant *C=llvm::ConstantArray::get(FunctionName); + + // Create a global variable for this. + C = new llvm::GlobalVariable(C->getType(), true, + llvm::GlobalValue::InternalLinkage, + C, GlobalVarName, CurFn->getParent()); + return LValue::MakeAddr(C); +} + +LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { + // The index must always be an integer, which is not an aggregate. Emit it. + llvm::Value *Idx = EmitScalarExpr(E->getIdx()); + + // If the base is a vector type, then we are forming a vector element lvalue + // with this subscript. + if (E->getLHS()->getType()->isVectorType()) { + // Emit the vector as an lvalue to get its address. + LValue LHS = EmitLValue(E->getLHS()); + assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); + // FIXME: This should properly sign/zero/extend or truncate Idx to i32. + return LValue::MakeVectorElt(LHS.getAddress(), Idx); + } + + // The base must be a pointer, which is not an aggregate. Emit it. + llvm::Value *Base = EmitScalarExpr(E->getBase()); + + // Extend or truncate the index type to 32 or 64-bits. + QualType IdxTy = E->getIdx()->getType(); + bool IdxSigned = IdxTy->isSignedIntegerType(); + unsigned IdxBitwidth = cast<llvm::IntegerType>(Idx->getType())->getBitWidth(); + if (IdxBitwidth != LLVMPointerWidth) + Idx = Builder.CreateIntCast(Idx, llvm::IntegerType::get(LLVMPointerWidth), + IdxSigned, "idxprom"); + + // We know that the pointer points to a type of the correct size, unless the + // size is a VLA. + if (!E->getType()->isConstantSizeType()) + assert(0 && "VLA idx not implemented"); + return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx")); +} + +LValue CodeGenFunction:: +EmitOCUVectorElementExpr(const OCUVectorElementExpr *E) { + // Emit the base vector as an l-value. + LValue Base = EmitLValue(E->getBase()); + assert(Base.isSimple() && "Can only subscript lvalue vectors here!"); + + return LValue::MakeOCUVectorElt(Base.getAddress(), + E->getEncodedElementAccess()); +} + +LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { + bool isUnion = false; + Expr *BaseExpr = E->getBase(); + llvm::Value *BaseValue = NULL; + + // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. + if (E->isArrow()) { + BaseValue = EmitScalarExpr(BaseExpr); + const PointerType *PTy = + cast<PointerType>(BaseExpr->getType().getCanonicalType()); + if (PTy->getPointeeType()->isUnionType()) + isUnion = true; + } + else { + LValue BaseLV = EmitLValue(BaseExpr); + // FIXME: this isn't right for bitfields. + BaseValue = BaseLV.getAddress(); + if (BaseExpr->getType()->isUnionType()) + isUnion = true; + } + + FieldDecl *Field = E->getMemberDecl(); + return EmitLValueForField(BaseValue, Field, isUnion); +} + +LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, + FieldDecl* Field, + bool isUnion) +{ + llvm::Value *V; + unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); + + if (Field->isBitField()) { + const llvm::Type * FieldTy = ConvertType(Field->getType()); + const llvm::PointerType * BaseTy = + cast<llvm::PointerType>(BaseValue->getType()); + unsigned AS = BaseTy->getAddressSpace(); + BaseValue = Builder.CreateBitCast(BaseValue, + llvm::PointerType::get(FieldTy, AS), + "tmp"); + V = Builder.CreateGEP(BaseValue, + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx), + "tmp"); + } else { + llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty), + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) }; + V = Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp"); + } + // Match union field type. + if (isUnion) { + const llvm::Type * FieldTy = ConvertType(Field->getType()); + const llvm::PointerType * BaseTy = + cast<llvm::PointerType>(BaseValue->getType()); + if (FieldTy != BaseTy->getElementType()) { + unsigned AS = BaseTy->getAddressSpace(); + V = Builder.CreateBitCast(V, + llvm::PointerType::get(FieldTy, AS), + "tmp"); + } + } + + if (Field->isBitField()) { + CodeGenTypes::BitFieldInfo bitFieldInfo = + CGM.getTypes().getBitFieldInfo(Field); + return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size, + Field->getType()->isSignedIntegerType()); + } else + return LValue::MakeAddr(V); +} + +//===--------------------------------------------------------------------===// +// Expression Emission +//===--------------------------------------------------------------------===// + + +RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { + if (const ImplicitCastExpr *IcExpr = + dyn_cast<const ImplicitCastExpr>(E->getCallee())) + if (const DeclRefExpr *DRExpr = + dyn_cast<const DeclRefExpr>(IcExpr->getSubExpr())) + if (const FunctionDecl *FDecl = + dyn_cast<const FunctionDecl>(DRExpr->getDecl())) + if (unsigned builtinID = FDecl->getIdentifier()->getBuiltinID()) + return EmitBuiltinExpr(builtinID, E); + + llvm::Value *Callee = EmitScalarExpr(E->getCallee()); + return EmitCallExpr(Callee, E->getCallee()->getType(), + E->arg_begin(), E->getNumArgs()); +} + +RValue CodeGenFunction::EmitCallExpr(Expr *FnExpr, Expr *const *Args, + unsigned NumArgs) { + llvm::Value *Callee = EmitScalarExpr(FnExpr); + return EmitCallExpr(Callee, FnExpr->getType(), Args, NumArgs); +} + +LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { + // Can only get l-value for call expression returning aggregate type + RValue RV = EmitCallExpr(E); + return LValue::MakeAddr(RV.getAggregateAddr()); +} + +RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType, + Expr *const *ArgExprs, unsigned NumArgs) { + // The callee type will always be a pointer to function type, get the function + // type. + FnType = cast<PointerType>(FnType.getCanonicalType())->getPointeeType(); + QualType ResultType = cast<FunctionType>(FnType)->getResultType(); + + llvm::SmallVector<llvm::Value*, 16> Args; + + // Handle struct-return functions by passing a pointer to the location that + // we would like to return into. + if (hasAggregateLLVMType(ResultType)) { + // Create a temporary alloca to hold the result of the call. :( + Args.push_back(CreateTempAlloca(ConvertType(ResultType))); + // FIXME: set the stret attribute on the argument. + } + + for (unsigned i = 0, e = NumArgs; i != e; ++i) { + QualType ArgTy = ArgExprs[i]->getType(); + + if (!hasAggregateLLVMType(ArgTy)) { + // Scalar argument is passed by-value. + Args.push_back(EmitScalarExpr(ArgExprs[i])); + } else if (ArgTy->isComplexType()) { + // Make a temporary alloca to pass the argument. + llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy)); + EmitComplexExprIntoAddr(ArgExprs[i], DestMem, false); + Args.push_back(DestMem); + } else { + llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy)); + EmitAggExpr(ArgExprs[i], DestMem, false); + Args.push_back(DestMem); + } + } + + llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size()); + if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee)) + CI->setCallingConv(F->getCallingConv()); + if (CI->getType() != llvm::Type::VoidTy) + CI->setName("call"); + else if (ResultType->isComplexType()) + return RValue::getComplex(LoadComplexFromAddr(Args[0], false)); + else if (hasAggregateLLVMType(ResultType)) + // Struct return. + return RValue::getAggregate(Args[0]); + else { + // void return. + assert(ResultType->isVoidType() && "Should only have a void expr here"); + CI = 0; + } + + return RValue::get(CI); +} |