summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGNonTrivialStruct.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGNonTrivialStruct.cpp')
-rw-r--r--clang/lib/CodeGen/CGNonTrivialStruct.cpp50
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.