diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGBuilder.h | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 127 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 7 |
3 files changed, 136 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 489f3413d4b..baba30d5bf6 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H +#include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "Address.h" #include "CodeGenTypeCache.h" @@ -194,6 +195,12 @@ public: Addr.getPointer(), Index, Name), Addr.getAlignment().alignmentAtOffset(Offset)); } + Address CreateStructGEP(Address Addr, unsigned Index, + const llvm::StructLayout *Layout, + const llvm::Twine &Name = "") { + auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); + return CreateStructGEP(Addr, Index, Offset, Name); + } /// Given /// %addr = [n x T]* ... 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. diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 51949979ad9..1748cd2ba57 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -160,6 +160,10 @@ LLVM_DUMP_METHOD void ABIArgInfo::dump() const { case Expand: OS << "Expand"; break; + case CoerceAndExpand: + OS << "CoerceAndExpand Type="; + getCoerceAndExpandType()->print(OS); + break; } OS << ")\n"; } @@ -1570,6 +1574,7 @@ static bool isArgInAlloca(const ABIArgInfo &Info) { case ABIArgInfo::Direct: case ABIArgInfo::Extend: case ABIArgInfo::Expand: + case ABIArgInfo::CoerceAndExpand: if (Info.getInReg()) return false; return true; @@ -6829,6 +6834,7 @@ Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits Stride; switch (AI.getKind()) { case ABIArgInfo::Expand: + case ABIArgInfo::CoerceAndExpand: case ABIArgInfo::InAlloca: llvm_unreachable("Unsupported ABI kind for va_arg"); @@ -7059,6 +7065,7 @@ Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits ArgSize = CharUnits::Zero(); switch (AI.getKind()) { case ABIArgInfo::Expand: + case ABIArgInfo::CoerceAndExpand: case ABIArgInfo::InAlloca: llvm_unreachable("Unsupported ABI kind for va_arg"); case ABIArgInfo::Ignore: |