diff options
Diffstat (limited to 'clang/lib/CodeGen/CGNonTrivialStruct.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGNonTrivialStruct.cpp | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index d5f378c52232..d134be83a9dc 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -254,6 +254,10 @@ struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>, void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset) { + // Zero-length bit-fields don't need to be copied/assigned. + if (FD && FD->isZeroLengthBitField(this->Ctx)) + return; + // Because volatile fields can be bit-fields and are individually copied, // their offset and width are in bits. uint64_t OffsetInBits = @@ -317,6 +321,16 @@ static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM, return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); } +template <size_t N, size_t... Ints> +static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq, + std::array<CharUnits, N> Alignments, + FunctionArgList Args, + CodeGenFunction *CGF) { + return std::array<Address, N>{{ + Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])), + Alignments[Ints])...}}; +} + // Template classes that are used as bases for classes that emit special // functions. template <class Derived> struct GenFuncBase { @@ -424,9 +438,9 @@ template <class Derived> struct GenFuncBase { } template <size_t N> - llvm::Function * - getFunction(StringRef FuncName, QualType QT, std::array<Address, N> Addrs, - std::array<CharUnits, N> Alignments, CodeGenModule &CGM) { + llvm::Function *getFunction(StringRef FuncName, QualType QT, + std::array<CharUnits, N> Alignments, + CodeGenModule &CGM) { // If the special function already exists in the module, return it. if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) { bool WrongType = false; @@ -439,7 +453,7 @@ template <class Derived> struct GenFuncBase { } if (WrongType) { - std::string FuncName = F->getName(); + std::string FuncName = std::string(F->getName()); SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation(); CGM.Error(Loc, "special function " + FuncName + " for non-trivial C struct has incorrect type"); @@ -466,12 +480,8 @@ template <class Derived> struct GenFuncBase { CodeGenFunction NewCGF(CGM); setCGF(&NewCGF); CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args); - - for (unsigned I = 0; I < N; ++I) { - llvm::Value *V = CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[I])); - Addrs[I] = Address(V, Alignments[I]); - } - + std::array<Address, N> Addrs = + getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF); asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs); CGF->FinishFunction(); return F; @@ -491,7 +501,7 @@ template <class Derived> struct GenFuncBase { } if (llvm::Function *F = - getFunction(FuncName, QT, Addrs, Alignments, CallerCGF.CGM)) + getFunction(FuncName, QT, Alignments, CallerCGF.CGM)) CallerCGF.EmitNounwindRuntimeCall(F, Ptrs); } @@ -543,6 +553,10 @@ struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>, std::array<Address, 2> Addrs) { LValue DstLV, SrcLV; if (FD) { + // No need to copy zero-length bit-fields. + if (FD->isZeroLengthBitField(this->CGF->getContext())) + return; + QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo(); Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset); @@ -825,17 +839,6 @@ static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, Gen.callFunc(FuncName, QT, Addrs, CGF); } -template <size_t N> static std::array<Address, N> createNullAddressArray(); - -template <> std::array<Address, 1> createNullAddressArray() { - return std::array<Address, 1>({{Address(nullptr, CharUnits::Zero())}}); -} - -template <> std::array<Address, 2> createNullAddressArray() { - return std::array<Address, 2>({{Address(nullptr, CharUnits::Zero()), - Address(nullptr, CharUnits::Zero())}}); -} - template <class G, size_t N> static llvm::Function * getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, @@ -844,8 +847,7 @@ getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, // The following call requires an array of addresses as arguments, but doesn't // actually use them (it overwrites them with the addresses of the arguments // of the created function). - return Gen.getFunction(FuncName, QT, createNullAddressArray<N>(), Alignments, - CGM); + return Gen.getFunction(FuncName, QT, Alignments, CGM); } // Functions to emit calls to the special functions of a non-trivial C struct. |