diff options
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 127 |
1 files changed, 122 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 090a123ffe1..19f8c7cfd24 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1357,11 +1357,13 @@ void ClangToLLVMArgMapping::construct(const ASTContext &Context, // ignore and inalloca doesn't have matching LLVM parameters. IRArgs.NumberOfArgs = 0; break; - case ABIArgInfo::Expand: { + case ABIArgInfo::CoerceAndExpand: + IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size(); + break; + case ABIArgInfo::Expand: IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context); break; } - } if (IRArgs.NumberOfArgs > 0) { IRArgs.FirstArgIndex = IRArgNo; @@ -1460,6 +1462,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { case ABIArgInfo::Ignore: resultType = llvm::Type::getVoidTy(getLLVMContext()); break; + + case ABIArgInfo::CoerceAndExpand: + resultType = retAI.getUnpaddedCoerceAndExpandType(); + break; } ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true); @@ -1527,6 +1533,15 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { break; } + case ABIArgInfo::CoerceAndExpand: { + auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; + for (auto EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) { + *ArgTypesIter++ = EltTy; + } + assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); + break; + } + case ABIArgInfo::Expand: auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; getExpandedTypes(it->type, ArgTypesIter); @@ -1768,6 +1783,9 @@ void CodeGenModule::ConstructAttributeList( break; } + case ABIArgInfo::CoerceAndExpand: + break; + case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } @@ -1875,7 +1893,8 @@ void CodeGenModule::ConstructAttributeList( } case ABIArgInfo::Ignore: case ABIArgInfo::Expand: - continue; + case ABIArgInfo::CoerceAndExpand: + break; case ABIArgInfo::InAlloca: // inalloca disables readnone and readonly. @@ -2248,6 +2267,29 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, break; } + case ABIArgInfo::CoerceAndExpand: { + // Reconstruct into a temporary. + Address alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg)); + ArgVals.push_back(ParamValue::forIndirect(alloca)); + + auto coercionType = ArgI.getCoerceAndExpandType(); + alloca = Builder.CreateElementBitCast(alloca, coercionType); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + unsigned argIndex = FirstIRArg; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) + continue; + + auto eltAddr = Builder.CreateStructGEP(alloca, i, layout); + auto elt = FnArgs[argIndex++]; + Builder.CreateStore(elt, eltAddr); + } + assert(argIndex == FirstIRArg + NumIRArgs); + break; + } + case ABIArgInfo::Expand: { // If this structure was expanded into multiple arguments then // we need to create a temporary and reconstruct it from the @@ -2638,6 +2680,40 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: break; + case ABIArgInfo::CoerceAndExpand: { + auto coercionType = RetAI.getCoerceAndExpandType(); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + // Load all of the coerced elements out into results. + llvm::SmallVector<llvm::Value*, 4> results; + Address addr = Builder.CreateElementBitCast(ReturnValue, coercionType); + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + auto coercedEltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType)) + continue; + + auto eltAddr = Builder.CreateStructGEP(addr, i, layout); + auto elt = Builder.CreateLoad(eltAddr); + results.push_back(elt); + } + + // If we have one result, it's the single direct result type. + if (results.size() == 1) { + RV = results[0]; + + // Otherwise, we need to make a first-class aggregate. + } else { + // Construct a return type that lacks padding elements. + llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType(); + + RV = llvm::UndefValue::get(returnType); + for (unsigned i = 0, e = results.size(); i != e; ++i) { + RV = Builder.CreateInsertValue(RV, results[i], i); + } + } + break; + } + case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } @@ -3377,7 +3453,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); size_t UnusedReturnSize = 0; - if (RetAI.isIndirect() || RetAI.isInAlloca()) { + if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { SRetPtr = ReturnValue.getValue(); } else { @@ -3391,7 +3467,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } if (IRFunctionArgs.hasSRetArg()) { IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); - } else { + } else if (RetAI.isInAlloca()) { Address Addr = createInAllocaStructGEP(RetAI.getInAllocaFieldIndex()); Builder.CreateStore(SRetPtr.getPointer(), Addr); } @@ -3571,6 +3647,29 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, break; } + case ABIArgInfo::CoerceAndExpand: { + assert(RV.isAggregate() && + "CoerceAndExpand does not support non-aggregate types yet"); + + auto coercionType = ArgInfo.getCoerceAndExpandType(); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + Address addr = RV.getAggregateAddress(); + addr = Builder.CreateElementBitCast(addr, coercionType); + + unsigned IRArgPos = FirstIRArg; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; + Address eltAddr = Builder.CreateStructGEP(addr, i, layout); + llvm::Value *elt = Builder.CreateLoad(eltAddr); + IRCallArgs[IRArgPos++] = elt; + } + assert(IRArgPos == FirstIRArg + NumIRArgs); + + break; + } + case ABIArgInfo::Expand: unsigned IRArgPos = FirstIRArg; ExpandTypeToArgs(I->Ty, RV, IRFuncTy, IRCallArgs, IRArgPos); @@ -3770,6 +3869,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return ret; } + case ABIArgInfo::CoerceAndExpand: { + auto coercionType = RetAI.getCoerceAndExpandType(); + auto layout = CGM.getDataLayout().getStructLayout(coercionType); + + Address addr = SRetPtr; + addr = Builder.CreateElementBitCast(addr, coercionType); + + unsigned unpaddedIndex = 0; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; + Address eltAddr = Builder.CreateStructGEP(addr, i, layout); + llvm::Value *elt = Builder.CreateExtractValue(CI, unpaddedIndex++); + Builder.CreateStore(elt, eltAddr); + } + break; + } + case ABIArgInfo::Ignore: // If we are ignoring an argument that had a result, make sure to // construct the appropriate return value for our caller. |