diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 350 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.h | 21 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 46 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 16 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 121 |
9 files changed, 503 insertions, 81 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c7290937a6f..7bf9082007c 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -28,7 +28,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" -#include "llvm/MC/SubtargetFeature.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Support/CallSite.h" #include "llvm/Transforms/Utils/Local.h" using namespace clang; @@ -226,6 +226,28 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D, return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo, required); } +/// Arrange a call to a C++ method, passing the given arguments. +const CGFunctionInfo & +CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, + const CXXConstructorDecl *D, + CXXCtorType CtorKind, + unsigned ExtraArgs) { + // FIXME: Kill copy. + SmallVector<CanQualType, 16> ArgTypes; + for (CallArgList::const_iterator i = args.begin(), e = args.end(); i != e; + ++i) + ArgTypes.push_back(Context.getCanonicalParamType(i->Ty)); + + CanQual<FunctionProtoType> FPT = GetFormalType(D); + RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs); + GlobalDecl GD(D, CtorKind); + CanQualType ResultType = + TheCXXABI.HasThisReturn(GD) ? ArgTypes.front() : Context.VoidTy; + + FunctionType::ExtInfo Info = FPT->getExtInfo(); + return arrangeLLVMFunctionInfo(ResultType, true, ArgTypes, Info, Required); +} + /// Arrange the argument and result information for a declaration, /// definition, or call to the given destructor variant. It so /// happens that all three cases produce the same information. @@ -505,6 +527,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, FI->Required = required; FI->HasRegParm = info.getHasRegParm(); FI->RegParm = info.getRegParm(); + FI->ArgStruct = 0; FI->NumArgs = argTypes.size(); FI->getArgsBuffer()[0].type = resultType; for (unsigned i = 0, e = argTypes.size(); i != e; ++i) @@ -916,6 +939,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { resultType = retAI.getCoerceToType(); break; + case ABIArgInfo::InAlloca: + resultType = llvm::Type::getVoidTy(getLLVMContext()); + break; + case ABIArgInfo::Indirect: { assert(!retAI.getIndirectAlign() && "Align unused on indirect return."); resultType = llvm::Type::getVoidTy(getLLVMContext()); @@ -948,6 +975,7 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { switch (argAI.getKind()) { case ABIArgInfo::Ignore: + case ABIArgInfo::InAlloca: break; case ABIArgInfo::Indirect: { @@ -978,6 +1006,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { } } + // Add the inalloca struct as the last parameter type. + if (llvm::StructType *ArgStruct = FI.getArgStruct()) + argTypes.push_back(ArgStruct->getPointerTo()); + bool Erased = FunctionsBeingProcessed.erase(&FI); (void)Erased; assert(Erased && "Not in set?"); @@ -1103,6 +1135,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: break; + case ABIArgInfo::InAlloca: { + // inalloca disables readnone and readonly + FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) + .removeAttribute(llvm::Attribute::ReadNone); + break; + } + case ABIArgInfo::Indirect: { llvm::AttrBuilder SRETAttrs; SRETAttrs.addAttribute(llvm::Attribute::StructRet); @@ -1187,6 +1226,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // Skip increment, no matching LLVM parameter. continue; + case ABIArgInfo::InAlloca: + // inalloca disables readnone and readonly. + FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) + .removeAttribute(llvm::Attribute::ReadNone); + // Skip increment, no matching LLVM parameter. + continue; + case ABIArgInfo::Expand: { SmallVector<llvm::Type*, 8> types; // FIXME: This is rather inefficient. Do we ever actually need to do @@ -1202,6 +1248,14 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, PAL.push_back(llvm::AttributeSet::get(getLLVMContext(), Index, Attrs)); ++Index; } + + // Add the inalloca attribute to the trailing inalloca parameter if present. + if (FI.usesInAlloca()) { + llvm::AttrBuilder Attrs; + Attrs.addAttribute(llvm::Attribute::InAlloca); + PAL.push_back(llvm::AttributeSet::get(getLLVMContext(), Index, Attrs)); + } + if (FuncAttrs.hasAttributes()) PAL.push_back(llvm:: AttributeSet::get(getLLVMContext(), @@ -1251,6 +1305,16 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Emit allocs for param decls. Give the LLVM Argument nodes names. llvm::Function::arg_iterator AI = Fn->arg_begin(); + // If we're using inalloca, all the memory arguments are GEPs off of the last + // parameter, which is a pointer to the complete memory area. + llvm::Value *ArgStruct = 0; + if (FI.usesInAlloca()) { + llvm::Function::arg_iterator EI = Fn->arg_end(); + --EI; + ArgStruct = EI; + assert(ArgStruct->getType() == FI.getArgStruct()->getPointerTo()); + } + // Name the struct return argument. if (CGM.ReturnTypeUsesSRet(FI)) { AI->setName("agg.result"); @@ -1260,12 +1324,18 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, ++AI; } + // Track if we received the parameter as a pointer (indirect, byval, or + // inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it + // into a local alloca for us. + enum ValOrPointer { HaveValue = 0, HavePointer = 1 }; + typedef llvm::PointerIntPair<llvm::Value *, 1, ValOrPointer> ValueAndIsPtr; + SmallVector<ValueAndIsPtr, 16> ArgVals; + ArgVals.reserve(Args.size()); + // Create a pointer value for every parameter declaration. This usually // entails copying one or more LLVM IR arguments into an alloca. Don't push // any cleanups or do anything that might unwind. We do that separately, so // we can push the cleanups in the correct order for the ABI. - SmallVector<llvm::Value *, 16> ArgVals; - ArgVals.reserve(Args.size()); assert(FI.arg_size() == Args.size() && "Mismatch between function signature & arguments."); unsigned ArgNo = 1; @@ -1284,6 +1354,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, ++AI; switch (ArgI.getKind()) { + case ABIArgInfo::InAlloca: { + llvm::Value *V = Builder.CreateStructGEP( + ArgStruct, ArgI.getInAllocaFieldIndex(), Arg->getName()); + ArgVals.push_back(ValueAndIsPtr(V, HavePointer)); + continue; // Don't increment AI! + } + case ABIArgInfo::Indirect: { llvm::Value *V = AI; @@ -1310,6 +1387,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, false); V = AlignedTemp; } + ArgVals.push_back(ValueAndIsPtr(V, HavePointer)); } else { // Load scalar value from indirect argument. CharUnits Alignment = getContext().getTypeAlignInChars(Ty); @@ -1318,8 +1396,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, if (isPromoted) V = emitArgumentDemotion(*this, Arg, V); + ArgVals.push_back(ValueAndIsPtr(V, HaveValue)); } - ArgVals.push_back(V); break; } @@ -1360,7 +1438,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, if (V->getType() != LTy) V = Builder.CreateBitCast(V, LTy); - ArgVals.push_back(V); + ArgVals.push_back(ValueAndIsPtr(V, HaveValue)); break; } @@ -1432,8 +1510,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty, Arg->getLocStart()); if (isPromoted) V = emitArgumentDemotion(*this, Arg, V); + ArgVals.push_back(ValueAndIsPtr(V, HaveValue)); + } else { + ArgVals.push_back(ValueAndIsPtr(V, HavePointer)); } - ArgVals.push_back(V); continue; // Skip ++AI increment, already done. } @@ -1446,7 +1526,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Alloca->setAlignment(Align.getQuantity()); LValue LV = MakeAddrLValue(Alloca, Ty, Align); llvm::Function::arg_iterator End = ExpandTypeFromArgs(Ty, LV, AI); - ArgVals.push_back(Alloca); + ArgVals.push_back(ValueAndIsPtr(Alloca, HavePointer)); // Name the arguments used in expansion and increment AI. unsigned Index = 0; @@ -1457,10 +1537,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: // Initialize the local variable appropriately. - if (!hasScalarEvaluationKind(Ty)) - ArgVals.push_back(CreateMemTemp(Ty)); - else - ArgVals.push_back(llvm::UndefValue::get(ConvertType(Arg->getType()))); + if (!hasScalarEvaluationKind(Ty)) { + ArgVals.push_back(ValueAndIsPtr(CreateMemTemp(Ty), HavePointer)); + } else { + llvm::Value *U = llvm::UndefValue::get(ConvertType(Arg->getType())); + ArgVals.push_back(ValueAndIsPtr(U, HaveValue)); + } // Skip increment, no matching LLVM parameter. continue; @@ -1468,14 +1550,19 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, ++AI; } + + if (FI.usesInAlloca()) + ++AI; assert(AI == Fn->arg_end() && "Argument mismatch!"); if (getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { for (int I = Args.size() - 1; I >= 0; --I) - EmitParmDecl(*Args[I], ArgVals[I], I + 1); + EmitParmDecl(*Args[I], ArgVals[I].getPointer(), ArgVals[I].getInt(), + I + 1); } else { for (unsigned I = 0, E = Args.size(); I != E; ++I) - EmitParmDecl(*Args[I], ArgVals[I], I + 1); + EmitParmDecl(*Args[I], ArgVals[I].getPointer(), ArgVals[I].getInt(), + I + 1); } } @@ -1689,6 +1776,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, const ABIArgInfo &RetAI = FI.getReturnInfo(); switch (RetAI.getKind()) { + case ABIArgInfo::InAlloca: + // Do nothing; aggregrates get evaluated directly into the destination. + break; + case ABIArgInfo::Indirect: { switch (getEvaluationKind(RetTy)) { case TEK_Complex: { @@ -1777,6 +1868,25 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, Ret->setDebugLoc(RetDbgLoc); } +static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) { + const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); + return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; +} + +static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF, QualType Ty) { + // FIXME: Generate IR in one pass, rather than going back and fixing up these + // placeholders. + llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty); + llvm::Value *Placeholder = + llvm::UndefValue::get(IRTy->getPointerTo()->getPointerTo()); + Placeholder = CGF.Builder.CreateLoad(Placeholder); + return AggValueSlot::forAddr(Placeholder, CharUnits::Zero(), + Ty.getQualifiers(), + AggValueSlot::IsNotDestructed, + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); +} + void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc) { @@ -1800,6 +1910,20 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, return args.add(RValue::get(Builder.CreateLoad(local)), type); } + if (isInAllocaArgument(CGM.getCXXABI(), type)) { + AggValueSlot Slot = createPlaceholderSlot(*this, type); + Slot.setExternallyDestructed(); + + // FIXME: Either emit a copy constructor call, or figure out how to do + // guaranteed tail calls with perfect forwarding in LLVM. + CGM.ErrorUnsupported(param, "non-trivial argument copy for thunk"); + EmitNullInitialization(Slot.getAddr(), type); + + RValue RV = Slot.asRValue(); + args.add(RV, type); + return; + } + args.add(convertTempToRValue(local, type, loc), type); } @@ -2031,6 +2155,34 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, args.add(RValue::get(finalArgument), CRE->getType()); } +void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) { + assert(!StackBase && !StackCleanup.isValid()); + + // Save the stack. + llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave); + StackBase = CGF.Builder.CreateCall(F, "inalloca.save"); + + // Control gets really tied up in landing pads, so we have to spill the + // stacksave to an alloca to avoid violating SSA form. + // TODO: This is dead if we never emit the cleanup. We should create the + // alloca and store lazily on the first cleanup emission. + StackBaseMem = CGF.CreateTempAlloca(CGF.Int8PtrTy, "inalloca.spmem"); + CGF.Builder.CreateStore(StackBase, StackBaseMem); + CGF.pushStackRestore(EHCleanup, StackBaseMem); + StackCleanup = CGF.EHStack.getInnermostEHScope(); + assert(StackCleanup.isValid()); +} + +void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const { + if (StackBase) { + CGF.DeactivateCleanupBlock(StackCleanup, StackBase); + llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore); + // We could load StackBase from StackBaseMem, but in the non-exceptional + // case we can skip it. + CGF.Builder.CreateCall(F, StackBase); + } +} + void CodeGenFunction::EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes, CallExpr::const_arg_iterator ArgBeg, @@ -2043,6 +2195,17 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args, // We *have* to evaluate arguments from right to left in the MS C++ ABI, // because arguments are destroyed left to right in the callee. if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { + // Insert a stack save if we're going to need any inalloca args. + bool HasInAllocaArgs = false; + for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end(); + I != E && !HasInAllocaArgs; ++I) + HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I); + if (HasInAllocaArgs) { + assert(getTarget().getTriple().getArch() == llvm::Triple::x86); + Args.allocateArgumentMemory(*this); + } + + // Evaluate each argument. size_t CallArgsStart = Args.size(); for (int I = ArgTypes.size() - 1; I >= 0; --I) { CallExpr::const_arg_iterator Arg = ArgBeg + I; @@ -2066,6 +2229,25 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args, } } +namespace { + +struct DestroyUnpassedArg : EHScopeStack::Cleanup { + DestroyUnpassedArg(llvm::Value *Addr, QualType Ty) + : Addr(Addr), Ty(Ty) {} + + llvm::Value *Addr; + QualType Ty; + + void Emit(CodeGenFunction &CGF, Flags flags) { + const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); + assert(!Dtor->isTrivial()); + CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false, + /*Delegating=*/false, Addr); + } +}; + +} + void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, QualType type) { if (const ObjCIndirectCopyRestoreExpr *CRE @@ -2088,23 +2270,25 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee. // However, we still have to push an EH-only cleanup in case we unwind before // we make it to the call. - if (HasAggregateEvalKind && - CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { + if (HasAggregateEvalKind && args.isUsingInAlloca()) { + assert(getTarget().getTriple().getArch() == llvm::Triple::x86); + AggValueSlot Slot = createPlaceholderSlot(*this, type); + Slot.setExternallyDestructed(); + EmitAggExpr(E, Slot); + RValue RV = Slot.asRValue(); + args.add(RV, type); + const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); - if (RD && RD->hasNonTrivialDestructor()) { - AggValueSlot Slot = CreateAggTemp(type, "agg.arg.tmp"); - Slot.setExternallyDestructed(); - EmitAggExpr(E, Slot); - RValue RV = Slot.asRValue(); - args.add(RV, type); - - pushDestroy(EHCleanup, RV.getAggregateAddr(), type, destroyCXXObject, - /*useEHCleanupForArray*/ true); + if (RD->hasNonTrivialDestructor()) { + // Create a no-op GEP between the placeholder and the cleanup so we can + // RAUW it successfully. It also serves as a marker of the first + // instruction where the cleanup is active. + pushFullExprCleanup<DestroyUnpassedArg>(EHCleanup, Slot.getAddr(), type); // This unreachable is a temporary marker which will be removed later. llvm::Instruction *IsActive = Builder.CreateUnreachable(); args.addArgCleanupDeactivation(EHStack.getInnermostEHScope(), IsActive); - return; } + return; } if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) && @@ -2314,6 +2498,20 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, } } +/// \brief Store a non-aggregate value to an address to initialize it. For +/// initialization, a non-atomic store will be used. +static void EmitInitStoreOfNonAggregate(CodeGenFunction &CGF, RValue Src, + LValue Dst) { + if (Src.isScalar()) + CGF.EmitStoreOfScalar(Src.getScalarVal(), Dst, /*init=*/true); + else + CGF.EmitStoreOfComplex(Src.getComplexVal(), Dst, /*init=*/true); +} + +void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old, + llvm::Value *New) { + DeferredReplacements.push_back(std::make_pair(Old, New)); +} RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *Callee, @@ -2335,14 +2533,32 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, cast<llvm::FunctionType>( cast<llvm::PointerType>(Callee->getType())->getElementType()); + // If we're using inalloca, insert the allocation after the stack save. + // FIXME: Do this earlier rather than hacking it in here! + llvm::Value *ArgMemory = 0; + if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { + llvm::AllocaInst *AI = new llvm::AllocaInst( + ArgStruct, "argmem", CallArgs.getStackBase()->getNextNode()); + AI->setUsedWithInAlloca(true); + assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); + ArgMemory = AI; + } + // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. - if (CGM.ReturnTypeUsesSRet(CallInfo)) { - llvm::Value *Value = ReturnValue.getValue(); - if (!Value) - Value = CreateMemTemp(RetTy); - Args.push_back(Value); - checkArgMatches(Value, IRArgNo, IRFuncTy); + llvm::Value *SRetPtr = 0; + if (CGM.ReturnTypeUsesSRet(CallInfo) || RetAI.isInAlloca()) { + SRetPtr = ReturnValue.getValue(); + if (!SRetPtr) + SRetPtr = CreateMemTemp(RetTy); + if (CGM.ReturnTypeUsesSRet(CallInfo)) { + Args.push_back(SRetPtr); + checkArgMatches(SRetPtr, IRArgNo, IRFuncTy); + } else { + llvm::Value *Addr = + Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); + Builder.CreateStore(SRetPtr, Addr); + } } assert(CallInfo.arg_size() == CallArgs.size() && @@ -2362,6 +2578,28 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } switch (ArgInfo.getKind()) { + case ABIArgInfo::InAlloca: { + assert(getTarget().getTriple().getArch() == llvm::Triple::x86); + if (RV.isAggregate()) { + // Replace the placeholder with the appropriate argument slot GEP. + llvm::Instruction *Placeholder = + cast<llvm::Instruction>(RV.getAggregateAddr()); + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(Placeholder); + llvm::Value *Addr = Builder.CreateStructGEP( + ArgMemory, ArgInfo.getInAllocaFieldIndex()); + Builder.restoreIP(IP); + deferPlaceholderReplacement(Placeholder, Addr); + } else { + // Store the RValue into the argument struct. + llvm::Value *Addr = + Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex()); + LValue argLV = MakeAddrLValue(Addr, I->Ty, TypeAlign); + EmitInitStoreOfNonAggregate(*this, RV, argLV); + } + break; // Don't increment IRArgNo! + } + case ABIArgInfo::Indirect: { if (RV.isScalar() || RV.isComplex()) { // Make a temporary alloca to pass the argument. @@ -2370,13 +2608,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI->setAlignment(ArgInfo.getIndirectAlign()); Args.push_back(AI); - LValue argLV = - MakeAddrLValue(Args.back(), I->Ty, TypeAlign); - - if (RV.isScalar()) - EmitStoreOfScalar(RV.getScalarVal(), argLV, /*init*/ true); - else - EmitStoreOfComplex(RV.getComplexVal(), argLV, /*init*/ true); + LValue argLV = MakeAddrLValue(Args.back(), I->Ty, TypeAlign); + EmitInitStoreOfNonAggregate(*this, RV, argLV); // Validate argument match. checkArgMatches(AI, IRArgNo, IRFuncTy); @@ -2449,11 +2682,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (RV.isScalar() || RV.isComplex()) { SrcPtr = CreateMemTemp(I->Ty, "coerce"); LValue SrcLV = MakeAddrLValue(SrcPtr, I->Ty, TypeAlign); - if (RV.isScalar()) { - EmitStoreOfScalar(RV.getScalarVal(), SrcLV, /*init*/ true); - } else { - EmitStoreOfComplex(RV.getComplexVal(), SrcLV, /*init*/ true); - } + EmitInitStoreOfNonAggregate(*this, RV, SrcLV); } else SrcPtr = RV.getAggregateAddr(); @@ -2519,6 +2748,34 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } + if (ArgMemory) { + llvm::Value *Arg = ArgMemory; + llvm::Type *LastParamTy = + IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1); + if (Arg->getType() != LastParamTy) { +#ifndef NDEBUG + // Assert that these structs have equivalent element types. + llvm::StructType *FullTy = CallInfo.getArgStruct(); + llvm::StructType *Prefix = cast<llvm::StructType>( + cast<llvm::PointerType>(LastParamTy)->getElementType()); + + // For variadic functions, the caller might supply a larger struct than + // the callee expects, and that's OK. + assert(Prefix->getNumElements() == FullTy->getNumElements() || + (CallInfo.isVariadic() && + Prefix->getNumElements() <= FullTy->getNumElements())); + + for (llvm::StructType::element_iterator PI = Prefix->element_begin(), + PE = Prefix->element_end(), + FI = FullTy->element_begin(); + PI != PE; ++PI, ++FI) + assert(*PI == *FI); +#endif + Arg = Builder.CreateBitCast(Arg, LastParamTy); + } + Args.push_back(Arg); + } + if (!CallArgs.getCleanupsToDeactivate().empty()) deactivateArgCleanupsBeforeCall(*this, CallArgs); @@ -2608,9 +2865,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (CallArgs.hasWritebacks()) emitWritebacks(*this, CallArgs); + // The stack cleanup for inalloca arguments has to run out of the normal + // lexical order, so deactivate it and run it manually here. + CallArgs.freeArgumentMemory(*this); + switch (RetAI.getKind()) { + case ABIArgInfo::InAlloca: case ABIArgInfo::Indirect: - return convertTempToRValue(Args[0], RetTy, SourceLocation()); + return convertTempToRValue(SRetPtr, RetTy, SourceLocation()); case ABIArgInfo::Ignore: // If we are ignoring an argument that had a result, make sure to diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 532cb59c62e..c51f06fdcd2 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -56,6 +56,8 @@ namespace CodeGen { class CallArgList : public SmallVector<CallArg, 16> { public: + CallArgList() : StackBase(0), StackBaseMem(0) {} + struct Writeback { /// The original argument. Note that the argument l-value /// is potentially null. @@ -113,6 +115,14 @@ namespace CodeGen { return CleanupsToDeactivate; } + void allocateArgumentMemory(CodeGenFunction &CGF); + llvm::Instruction *getStackBase() const { return StackBase; } + void freeArgumentMemory(CodeGenFunction &CGF) const; + + /// \brief Returns if we're using an inalloca struct to pass arguments in + /// memory. + bool isUsingInAlloca() const { return StackBase; } + private: SmallVector<Writeback, 1> Writebacks; @@ -120,6 +130,17 @@ namespace CodeGen { /// is used to cleanup objects that are owned by the callee once the call /// occurs. SmallVector<CallArgCleanup, 1> CleanupsToDeactivate; + + /// The stacksave call. It dominates all of the argument evaluation. + llvm::CallInst *StackBase; + + /// The alloca holding the stackbase. We need it to maintain SSA form. + llvm::AllocaInst *StackBaseMem; + + /// The iterator pointing to the stack restore cleanup. We manually run and + /// deactivate this cleanup after the call in the unexceptional case because + /// it doesn't run in the normal order. + EHScopeStack::stable_iterator StackCleanup; }; /// FunctionArgList - Type for representing both the decl and type diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 273fed52d5c..4c48afe0752 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1714,9 +1714,8 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // Emit the call. llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); - RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs); const CGFunctionInfo &Info = - CGM.getTypes().arrangeCXXMethodCall(Args, FPT, Required); + CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs); EmitCall(Info, Callee, ReturnValueSlot(), Args, D); } diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index e87be5f4148..cb48e84aacb 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -944,7 +944,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // Push a cleanup block and restore the stack there. // FIXME: in general circumstances, this should be an EH cleanup. - EHStack.pushCleanup<CallStackRestore>(NormalCleanup, Stack); + pushStackRestore(NormalCleanup, Stack); } llvm::Value *elementCount; @@ -1344,6 +1344,10 @@ void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr, destroyer, useEHCleanupForArray); } +void CodeGenFunction::pushStackRestore(CleanupKind Kind, llvm::Value *SPMem) { + EHStack.pushCleanup<CallStackRestore>(Kind, SPMem); +} + void CodeGenFunction::pushLifetimeExtendedDestroy( CleanupKind cleanupKind, llvm::Value *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { @@ -1603,7 +1607,7 @@ namespace { /// Emit an alloca (or GlobalValue depending on target) /// for the specified parameter and set up LocalDeclMap. void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, - unsigned ArgNo) { + bool ArgIsPointer, unsigned ArgNo) { // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) && "Invalid argument to EmitParmDecl"); @@ -1641,30 +1645,32 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, } llvm::Value *DeclPtr; - bool HasNonScalarEvalKind = !CodeGenFunction::hasScalarEvaluationKind(Ty); - // If this is an aggregate or variable sized value, reuse the input pointer. - if (HasNonScalarEvalKind || !Ty->isConstantSizeType()) { + bool DoStore = false; + bool IsScalar = hasScalarEvaluationKind(Ty); + CharUnits Align = getContext().getDeclAlign(&D); + // If we already have a pointer to the argument, reuse the input pointer. + if (ArgIsPointer) { + assert(isa<llvm::PointerType>(Arg->getType())); DeclPtr = Arg; // Push a destructor cleanup for this parameter if the ABI requires it. - if (HasNonScalarEvalKind && + if (!IsScalar && getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { - if (const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) { - if (RD->hasNonTrivialDestructor()) - pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty); - } + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (RD && RD->hasNonTrivialDestructor()) + pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty); } } else { // Otherwise, create a temporary to hold the value. llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty), D.getName() + ".addr"); - CharUnits Align = getContext().getDeclAlign(&D); Alloc->setAlignment(Align.getQuantity()); DeclPtr = Alloc; + DoStore = true; + } - bool doStore = true; - + LValue lv = MakeAddrLValue(DeclPtr, Ty, Align); + if (IsScalar) { Qualifiers qs = Ty.getQualifiers(); - LValue lv = MakeAddrLValue(DeclPtr, Ty, Align); if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) { // We honor __attribute__((ns_consumed)) for types with lifetime. // For __strong, it's handled by just skipping the initial retain; @@ -1693,7 +1699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, llvm::Value *Null = CGM.EmitNullConstant(D.getType()); EmitStoreOfScalar(Null, lv, /* isInitialization */ true); EmitARCStoreStrongCall(lv.getAddress(), Arg, true); - doStore = false; + DoStore = false; } else // Don't use objc_retainBlock for block pointers, because we @@ -1712,19 +1718,19 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, if (lt == Qualifiers::OCL_Weak) { EmitARCInitWeak(DeclPtr, Arg); - doStore = false; // The weak init is a store, no need to do two. + DoStore = false; // The weak init is a store, no need to do two. } } // Enter the cleanup scope. EmitAutoVarWithLifetime(*this, D, DeclPtr, lt); } - - // Store the initial value into the alloca. - if (doStore) - EmitStoreOfScalar(Arg, lv, /* isInitialization */ true); } + // Store the initial value into the alloca. + if (DoStore) + EmitStoreOfScalar(Arg, lv, /* isInitialization */ true); + llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); DMEntry = DeclPtr; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 572f5babd0a..7d451e8f6d0 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -276,6 +276,14 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { if (CGM.getCodeGenOpts().EmitDeclMetadata) EmitDeclMetadata(); + + for (SmallVectorImpl<std::pair<llvm::Instruction *, llvm::Value *> >::iterator + I = DeferredReplacements.begin(), + E = DeferredReplacements.end(); + I != E; ++I) { + I->first->replaceAllUsesWith(I->second); + I->first->eraseFromParent(); + } } /// ShouldInstrumentFunction - Return true if the current function should be @@ -592,6 +600,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, // Indirect aggregate return; emit returned value directly into sret slot. // This reduces code size, and affects correctness in C++. ReturnValue = CurFn->arg_begin(); + } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && + !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { + // Load the sret pointer from the argument struct and return into that. + unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex(); + llvm::Function::arg_iterator EI = CurFn->arg_end(); + --EI; + llvm::Value *Addr = Builder.CreateStructGEP(EI, Idx); + ReturnValue = Builder.CreateLoad(Addr, "agg.result"); } else { ReturnValue = CreateIRTemp(RetTy, "retval"); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 9f418ef434e..322f480c834 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1037,6 +1037,7 @@ public: void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); + void pushStackRestore(CleanupKind kind, llvm::Value *SPMem); void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); llvm::Function *generateDestroyHelper(llvm::Constant *addr, QualType type, @@ -1398,6 +1399,10 @@ public: AggValueSlot::IsNotAliased); } + /// CreateInAllocaTmp - Create a temporary memory object for the given + /// aggregate type. + AggValueSlot CreateInAllocaTmp(QualType T, const Twine &Name = "inalloca"); + /// Emit a cast to void* in the appropriate address space. llvm::Value *EmitCastToVoidPtr(llvm::Value *value); @@ -1785,7 +1790,8 @@ public: llvm::GlobalValue::LinkageTypes Linkage); /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl. - void EmitParmDecl(const VarDecl &D, llvm::Value *Arg, unsigned ArgNo); + void EmitParmDecl(const VarDecl &D, llvm::Value *Arg, bool ArgIsPointer, + unsigned ArgNo); /// protectFromPeepholes - Protect a value that we're intending to /// store to the side, but which will probably be used later, from @@ -2490,6 +2496,11 @@ private: llvm::MDNode *getRangeForLoadFromType(QualType Ty); void EmitReturnOfRValue(RValue RV, QualType Ty); + void deferPlaceholderReplacement(llvm::Instruction *Old, llvm::Value *New); + + llvm::SmallVector<std::pair<llvm::Instruction *, llvm::Value *>, 4> + DeferredReplacements; + /// ExpandTypeFromArgs - Reconstruct a structure of type \arg Ty /// from function arguments into \arg Dst. See ABIArgInfo::Expand. /// diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index d74f589a749..59e308995d0 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -188,6 +188,10 @@ public: const CGFunctionInfo &arrangeCXXConstructorDeclaration( const CXXConstructorDecl *D, CXXCtorType Type); + const CGFunctionInfo &arrangeCXXConstructorCall(const CallArgList &Args, + const CXXConstructorDecl *D, + CXXCtorType CtorKind, + unsigned ExtraArgs); const CGFunctionInfo &arrangeCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type); diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 875591d0df9..3433c8ca30c 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -45,8 +45,14 @@ public: } RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const { - if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialDestructor()) - return RAA_DirectInMemory; + if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialDestructor()) { + llvm::Triple::ArchType Arch = CGM.getTarget().getTriple().getArch(); + if (Arch == llvm::Triple::x86) + return RAA_DirectInMemory; + // On x64, pass non-trivial records indirectly. + // FIXME: Test other Windows architectures. + return RAA_Indirect; + } return RAA_Default; } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index bf968f34815..53747e3fcd1 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -114,6 +114,9 @@ void ABIArgInfo::dump() const { case Ignore: OS << "Ignore"; break; + case InAlloca: + OS << "InAlloca Offset=" << getInAllocaFieldIndex(); + break; case Indirect: OS << "Indirect Align=" << getIndirectAlign() << " ByVal=" << getIndirectByVal() @@ -532,6 +535,8 @@ struct CCState { unsigned CC; unsigned FreeRegs; + unsigned StackOffset; + bool UseInAlloca; }; /// X86_32ABIInfo - The X86-32 ABI information. @@ -570,6 +575,14 @@ class X86_32ABIInfo : public ABIInfo { ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; bool shouldUseInReg(QualType Ty, CCState &State, bool &NeedsPadding) const; + /// \brief Rewrite the function info so that all memory arguments use + /// inalloca. + void rewriteWithInAlloca(CGFunctionInfo &FI) const; + + void addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields, + unsigned &StackOffset, ABIArgInfo &Info, + QualType Type) const; + public: virtual void computeInfo(CGFunctionInfo &FI) const; @@ -831,15 +844,12 @@ ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal, unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign); if (StackAlign == 0) - return ABIArgInfo::getIndirect(4); + return ABIArgInfo::getIndirect(4, /*ByVal=*/true); // If the stack alignment is less than the type alignment, realign the // argument. - if (StackAlign < TypeAlign) - return ABIArgInfo::getIndirect(StackAlign, /*ByVal=*/true, - /*Realign=*/true); - - return ABIArgInfo::getIndirect(StackAlign); + bool Realign = TypeAlign > StackAlign; + return ABIArgInfo::getIndirect(StackAlign, /*ByVal=*/true, Realign); } X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const { @@ -897,17 +907,24 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, CCState &State, return true; } -ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State) const { +ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, + CCState &State) const { // FIXME: Set alignment on indirect arguments. if (isAggregateTypeForABI(Ty)) { if (const RecordType *RT = Ty->getAs<RecordType>()) { + // Check with the C++ ABI first. + CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); + if (RAA == CGCXXABI::RAA_Indirect) { + return getIndirectResult(Ty, false, State); + } else if (RAA == CGCXXABI::RAA_DirectInMemory) { + // The field index doesn't matter, we'll fix it up later. + return ABIArgInfo::getInAlloca(/*FieldIndex=*/0); + } + + // Structs are always byval on win32, regardless of what they contain. if (IsWin32StructABI) return getIndirectResult(Ty, true, State); - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI())) - return getIndirectResult(Ty, RAA == CGCXXABI::RAA_DirectInMemory, - State); - // Structures with flexible arrays are always indirect. if (RT->getDecl()->hasFlexibleArrayMember()) return getIndirectResult(Ty, true, State); @@ -994,9 +1011,87 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const { FI.getReturnInfo().isIndirect()) FI.setEffectiveCallingConvention(llvm::CallingConv::X86_CDeclMethod); + bool UsedInAlloca = false; for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); - it != ie; ++it) + it != ie; ++it) { it->info = classifyArgumentType(it->type, State); + UsedInAlloca |= (it->info.getKind() == ABIArgInfo::InAlloca); + } + + // If we needed to use inalloca for any argument, do a second pass and rewrite + // all the memory arguments to use inalloca. + if (UsedInAlloca) + rewriteWithInAlloca(FI); +} + +void +X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields, + unsigned &StackOffset, + ABIArgInfo &Info, QualType Type) const { + // Insert padding bytes to respect alignment. For x86_32, each argument is 4 + // byte aligned. + unsigned Align = 4U; + if (Info.getKind() == ABIArgInfo::Indirect && Info.getIndirectByVal()) + Align = std::max(Align, Info.getIndirectAlign()); + if (StackOffset & (Align - 1)) { + unsigned OldOffset = StackOffset; + StackOffset = llvm::RoundUpToAlignment(StackOffset, Align); + unsigned NumBytes = StackOffset - OldOffset; + assert(NumBytes); + llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext()); + Ty = llvm::ArrayType::get(Ty, NumBytes); + FrameFields.push_back(Ty); + } + + Info = ABIArgInfo::getInAlloca(FrameFields.size()); + FrameFields.push_back(CGT.ConvertTypeForMem(Type)); + StackOffset += getContext().getTypeSizeInChars(Type).getQuantity(); +} + +void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI) const { + assert(IsWin32StructABI && "inalloca only supported on win32"); + + // Build a packed struct type for all of the arguments in memory. + SmallVector<llvm::Type *, 6> FrameFields; + + unsigned StackOffset = 0; + + // Put the sret parameter into the inalloca struct if it's in memory. + ABIArgInfo &Ret = FI.getReturnInfo(); + if (Ret.isIndirect() && !Ret.getInReg()) { + CanQualType PtrTy = getContext().getPointerType(FI.getReturnType()); + addFieldToArgStruct(FrameFields, StackOffset, Ret, PtrTy); + } + + // Skip the 'this' parameter in ecx. + CGFunctionInfo::arg_iterator I = FI.arg_begin(), E = FI.arg_end(); + if (FI.getCallingConvention() == llvm::CallingConv::X86_ThisCall) + ++I; + + // Put arguments passed in memory into the struct. + for (; I != E; ++I) { + + // Leave ignored and inreg arguments alone. + switch (I->info.getKind()) { + case ABIArgInfo::Indirect: + assert(I->info.getIndirectByVal()); + break; + case ABIArgInfo::Ignore: + continue; + case ABIArgInfo::Direct: + case ABIArgInfo::Extend: + if (I->info.getInReg()) + continue; + break; + default: + break; + } + + addFieldToArgStruct(FrameFields, StackOffset, I->info, I->type); + } + + FI.setArgStruct(llvm::StructType::get(getVMContext(), FrameFields, + /*isPacked=*/true)); } llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, @@ -5413,6 +5508,7 @@ llvm::Value *SparcV9ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, switch (AI.getKind()) { case ABIArgInfo::Expand: + case ABIArgInfo::InAlloca: llvm_unreachable("Unsupported ABI kind for va_arg"); case ABIArgInfo::Extend: @@ -5499,6 +5595,7 @@ llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, uint64_t ArgSize = 0; switch (AI.getKind()) { case ABIArgInfo::Expand: + case ABIArgInfo::InAlloca: llvm_unreachable("Unsupported ABI kind for va_arg"); case ABIArgInfo::Ignore: Val = llvm::UndefValue::get(ArgPtrTy); |