/src/llvm-project/clang/lib/CodeGen/CGNonTrivialStruct.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file defines functions to generate various special functions for C |
10 | | // structs. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "CodeGenFunction.h" |
15 | | #include "CodeGenModule.h" |
16 | | #include "clang/AST/NonTrivialTypeVisitor.h" |
17 | | #include "clang/CodeGen/CodeGenABITypes.h" |
18 | | #include "llvm/Support/ScopedPrinter.h" |
19 | | #include <array> |
20 | | |
21 | | using namespace clang; |
22 | | using namespace CodeGen; |
23 | | |
24 | | // Return the size of a field in number of bits. |
25 | | static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, |
26 | 0 | ASTContext &Ctx) { |
27 | 0 | if (FD && FD->isBitField()) |
28 | 0 | return FD->getBitWidthValue(Ctx); |
29 | 0 | return Ctx.getTypeSize(FT); |
30 | 0 | } |
31 | | |
32 | | namespace { |
33 | | enum { DstIdx = 0, SrcIdx = 1 }; |
34 | | const char *ValNameStr[2] = {"dst", "src"}; |
35 | | |
36 | | template <class Derived> struct StructVisitor { |
37 | 0 | StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {} Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyConstructor>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyAssignment>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveConstructor>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveAssignment>::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<false> >::StructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<true> >::StructVisitor(clang::ASTContext&) |
38 | | |
39 | | template <class... Ts> |
40 | 0 | void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) { |
41 | 0 | const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); |
42 | | |
43 | | // Iterate over the fields of the struct. |
44 | 0 | for (const FieldDecl *FD : RD->fields()) { |
45 | 0 | QualType FT = FD->getType(); |
46 | 0 | FT = QT.isVolatileQualified() ? FT.withVolatile() : FT; |
47 | 0 | asDerived().visit(FT, FD, CurStructOffset, Args...); |
48 | 0 | } |
49 | |
|
50 | 0 | asDerived().flushTrivialFields(Args...); |
51 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::visitStructFields<>(clang::QualType, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::visitStructFields<std::__1::array<clang::CodeGen::Address, 1ul> >(clang::QualType, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<false> >::visitStructFields<>(clang::QualType, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::visitStructFields<>(clang::QualType, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::visitStructFields<std::__1::array<clang::CodeGen::Address, 1ul> >(clang::QualType, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyConstructor>::visitStructFields<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyAssignment>::visitStructFields<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<true> >::visitStructFields<>(clang::QualType, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveConstructor>::visitStructFields<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveAssignment>::visitStructFields<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) |
52 | | |
53 | 0 | template <class... Ts> void visitTrivial(Ts... Args) {} Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::visitTrivial<clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::visitTrivial<clang::QualType, clang::FieldDecl const*, clang::CharUnits>(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::visitTrivial<clang::QualType, clang::FieldDecl const*, clang::CharUnits>(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::visitTrivial<clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) |
54 | | |
55 | 0 | template <class... Ts> void visitCXXDestructor(Ts... Args) { |
56 | 0 | llvm_unreachable("field of a C++ struct type is not expected"); |
57 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::visitCXXDestructor<clang::QualType, clang::FieldDecl const*, clang::CharUnits>(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::visitCXXDestructor<clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) |
58 | | |
59 | 0 | template <class... Ts> void flushTrivialFields(Ts... Args) {} Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::flushTrivialFields<std::__1::array<clang::CodeGen::Address, 1ul> >(std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::flushTrivialFields<>() Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::flushTrivialFields<>() Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::flushTrivialFields<std::__1::array<clang::CodeGen::Address, 1ul> >(std::__1::array<clang::CodeGen::Address, 1ul>) |
60 | | |
61 | 0 | uint64_t getFieldOffsetInBits(const FieldDecl *FD) { |
62 | 0 | return FD ? Ctx.getASTRecordLayout(FD->getParent()) |
63 | 0 | .getFieldOffset(FD->getFieldIndex()) |
64 | 0 | : 0; |
65 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<false> >::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyConstructor>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyAssignment>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<true> >::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveConstructor>::getFieldOffsetInBits(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveAssignment>::getFieldOffsetInBits(clang::FieldDecl const*) |
66 | | |
67 | 0 | CharUnits getFieldOffset(const FieldDecl *FD) { |
68 | 0 | return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD)); |
69 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<false> >::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyConstructor>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyAssignment>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<true> >::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveConstructor>::getFieldOffset(clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveAssignment>::getFieldOffset(clang::FieldDecl const*) |
70 | | |
71 | 0 | Derived &asDerived() { return static_cast<Derived &>(*this); } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<false> >::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyConstructor>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyAssignment>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<true> >::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveConstructor>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveAssignment>::asDerived() |
72 | | |
73 | 0 | ASTContext &getContext() { return Ctx; } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitialize>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDefaultInitializeFuncName>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<false> >::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructorFuncName>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenDestructor>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyConstructor>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenCopyAssignment>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenBinaryFuncName<true> >::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveConstructor>::getContext() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::StructVisitor<(anonymous namespace)::GenMoveAssignment>::getContext() |
74 | | ASTContext &Ctx; |
75 | | }; |
76 | | |
77 | | template <class Derived, bool IsMove> |
78 | | struct CopyStructVisitor : StructVisitor<Derived>, |
79 | | CopiedTypeVisitor<Derived, IsMove> { |
80 | | using StructVisitor<Derived>::asDerived; |
81 | | using Super = CopiedTypeVisitor<Derived, IsMove>; |
82 | | |
83 | 0 | CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {} Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyConstructor, false>::CopyStructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyAssignment, false>::CopyStructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveConstructor, true>::CopyStructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveAssignment, true>::CopyStructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<false>, false>::CopyStructVisitor(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<true>, true>::CopyStructVisitor(clang::ASTContext&) |
84 | | |
85 | | template <class... Ts> |
86 | | void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT, |
87 | 0 | const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) { |
88 | 0 | if (PCK) |
89 | 0 | asDerived().flushTrivialFields(std::forward<Ts>(Args)...); |
90 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<false>, false>::preVisit<>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyConstructor, false>::preVisit<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyAssignment, false>::preVisit<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<true>, true>::preVisit<>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveConstructor, true>::preVisit<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveAssignment, true>::preVisit<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) |
91 | | |
92 | | template <class... Ts> |
93 | | void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, |
94 | | const FieldDecl *FD, CharUnits CurStructOffset, |
95 | 0 | Ts &&... Args) { |
96 | 0 | if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) { |
97 | 0 | asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD, |
98 | 0 | CurStructOffset, std::forward<Ts>(Args)...); |
99 | 0 | return; |
100 | 0 | } |
101 | | |
102 | 0 | Super::visitWithKind(PCK, FT, FD, CurStructOffset, |
103 | 0 | std::forward<Ts>(Args)...); |
104 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<false>, false>::visitWithKind<>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyConstructor, false>::visitWithKind<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyAssignment, false>::visitWithKind<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<true>, true>::visitWithKind<>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveConstructor, true>::visitWithKind<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveAssignment, true>::visitWithKind<std::__1::array<clang::CodeGen::Address, 2ul>&>(clang::QualType::PrimitiveCopyKind, clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>&) |
105 | | |
106 | | template <class... Ts> |
107 | | void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset, |
108 | 0 | Ts... Args) { |
109 | 0 | assert(!FT.isVolatileQualified() && "volatile field not expected"); |
110 | 0 | ASTContext &Ctx = asDerived().getContext(); |
111 | 0 | uint64_t FieldSize = getFieldSize(FD, FT, Ctx); |
112 | | |
113 | | // Ignore zero-sized fields. |
114 | 0 | if (FieldSize == 0) |
115 | 0 | return; |
116 | | |
117 | 0 | uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD); |
118 | 0 | uint64_t FEndInBits = FStartInBits + FieldSize; |
119 | 0 | uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth()); |
120 | | |
121 | | // Set Start if this is the first field of a sequence of trivial fields. |
122 | 0 | if (Start == End) |
123 | 0 | Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits); |
124 | 0 | End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd); |
125 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<false>, false>::visitTrivial<>(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyConstructor, false>::visitTrivial<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenCopyAssignment, false>::visitTrivial<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenBinaryFuncName<true>, true>::visitTrivial<>(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveConstructor, true>::visitTrivial<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::CopyStructVisitor<(anonymous namespace)::GenMoveAssignment, true>::visitTrivial<std::__1::array<clang::CodeGen::Address, 2ul> >(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) |
126 | | |
127 | | CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero(); |
128 | | }; |
129 | | |
130 | | // This function creates the mangled name of a special function of a non-trivial |
131 | | // C struct. Since there is no ODR in C, the function is mangled based on the |
132 | | // struct contents and not the name. The mangled name has the following |
133 | | // structure: |
134 | | // |
135 | | // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info> |
136 | | // <prefix> ::= "__destructor_" | "__default_constructor_" | |
137 | | // "__copy_constructor_" | "__move_constructor_" | |
138 | | // "__copy_assignment_" | "__move_assignment_" |
139 | | // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>] |
140 | | // <struct-field-info> ::= <field-info>+ |
141 | | // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info> |
142 | | // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> | |
143 | | // <strong-field-info> | <trivial-field-info> |
144 | | // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n" |
145 | | // <num-elements> <innermost-element-info> "_AE" |
146 | | // <innermost-element-info> ::= <struct-or-scalar-field-info> |
147 | | // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset> |
148 | | // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size> |
149 | | |
150 | | template <class Derived> struct GenFuncNameBase { |
151 | 0 | std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) { |
152 | 0 | std::string S; |
153 | 0 | if (IsVolatile) |
154 | 0 | S = "v"; |
155 | 0 | S += llvm::to_string(Offset.getQuantity()); |
156 | 0 | return S; |
157 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::getVolatileOffsetStr(bool, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::getVolatileOffsetStr(bool, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::getVolatileOffsetStr(bool, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::getVolatileOffsetStr(bool, clang::CharUnits) |
158 | | |
159 | | void visitARCStrong(QualType FT, const FieldDecl *FD, |
160 | 0 | CharUnits CurStructOffset) { |
161 | 0 | appendStr("_s"); |
162 | 0 | if (FT->isBlockPointerType()) |
163 | 0 | appendStr("b"); |
164 | 0 | CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); |
165 | 0 | appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset)); |
166 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::visitARCStrong(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::visitARCStrong(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::visitARCStrong(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::visitARCStrong(clang::QualType, clang::FieldDecl const*, clang::CharUnits) |
167 | | |
168 | | void visitARCWeak(QualType FT, const FieldDecl *FD, |
169 | 0 | CharUnits CurStructOffset) { |
170 | 0 | appendStr("_w"); |
171 | 0 | CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); |
172 | 0 | appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset)); |
173 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::visitARCWeak(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::visitARCWeak(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::visitARCWeak(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::visitARCWeak(clang::QualType, clang::FieldDecl const*, clang::CharUnits) |
174 | | |
175 | | void visitStruct(QualType QT, const FieldDecl *FD, |
176 | 0 | CharUnits CurStructOffset) { |
177 | 0 | CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); |
178 | 0 | appendStr("_S"); |
179 | 0 | asDerived().visitStructFields(QT, FieldOffset); |
180 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::visitStruct(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::visitStruct(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::visitStruct(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::visitStruct(clang::QualType, clang::FieldDecl const*, clang::CharUnits) |
181 | | |
182 | | template <class FieldKind> |
183 | | void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, |
184 | 0 | const FieldDecl *FD, CharUnits CurStructOffset) { |
185 | | // String for non-volatile trivial fields is emitted when |
186 | | // flushTrivialFields is called. |
187 | 0 | if (!FK) |
188 | 0 | return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset); |
189 | | |
190 | 0 | asDerived().flushTrivialFields(); |
191 | 0 | CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD); |
192 | 0 | ASTContext &Ctx = asDerived().getContext(); |
193 | 0 | const ConstantArrayType *CAT = cast<ConstantArrayType>(AT); |
194 | 0 | unsigned NumElts = Ctx.getConstantArrayElementCount(CAT); |
195 | 0 | QualType EltTy = Ctx.getBaseElementType(CAT); |
196 | 0 | CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy); |
197 | 0 | appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" + |
198 | 0 | llvm::to_string(EltSize.getQuantity()) + "n" + |
199 | 0 | llvm::to_string(NumElts)); |
200 | 0 | EltTy = IsVolatile ? EltTy.withVolatile() : EltTy; |
201 | 0 | asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset); |
202 | 0 | appendStr("_AE"); |
203 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::visitArray<clang::QualType::PrimitiveDefaultInitializeKind>(clang::QualType::PrimitiveDefaultInitializeKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::visitArray<clang::QualType::PrimitiveCopyKind>(clang::QualType::PrimitiveCopyKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::visitArray<clang::QualType::DestructionKind>(clang::QualType::DestructionKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::visitArray<clang::QualType::PrimitiveCopyKind>(clang::QualType::PrimitiveCopyKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits) |
204 | | |
205 | 0 | void appendStr(StringRef Str) { Name += Str; } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::appendStr(llvm::StringRef) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::appendStr(llvm::StringRef) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::appendStr(llvm::StringRef) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::appendStr(llvm::StringRef) |
206 | | |
207 | 0 | std::string getName(QualType QT, bool IsVolatile) { |
208 | 0 | QT = IsVolatile ? QT.withVolatile() : QT; |
209 | 0 | asDerived().visitStructFields(QT, CharUnits::Zero()); |
210 | 0 | return Name; |
211 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::getName(clang::QualType, bool) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::getName(clang::QualType, bool) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::getName(clang::QualType, bool) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::getName(clang::QualType, bool) |
212 | | |
213 | 0 | Derived &asDerived() { return static_cast<Derived &>(*this); } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDefaultInitializeFuncName>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<false> >::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenDestructorFuncName>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncNameBase<(anonymous namespace)::GenBinaryFuncName<true> >::asDerived() |
214 | | |
215 | | std::string Name; |
216 | | }; |
217 | | |
218 | | template <class Derived> |
219 | | struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> { |
220 | | GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx) |
221 | 0 | : StructVisitor<Derived>(Ctx) { |
222 | 0 | this->appendStr(Prefix); |
223 | 0 | this->appendStr(llvm::to_string(DstAlignment.getQuantity())); |
224 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenUnaryFuncName<(anonymous namespace)::GenDefaultInitializeFuncName>::GenUnaryFuncName(llvm::StringRef, clang::CharUnits, clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenUnaryFuncName<(anonymous namespace)::GenDestructorFuncName>::GenUnaryFuncName(llvm::StringRef, clang::CharUnits, clang::ASTContext&) |
225 | | }; |
226 | | |
227 | | // Helper function to create a null constant. |
228 | 0 | static llvm::Constant *getNullForVariable(Address Addr) { |
229 | 0 | llvm::Type *Ty = Addr.getElementType(); |
230 | 0 | return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty)); |
231 | 0 | } |
232 | | |
233 | | template <bool IsMove> |
234 | | struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>, |
235 | | GenFuncNameBase<GenBinaryFuncName<IsMove>> { |
236 | | |
237 | | GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment, |
238 | | CharUnits SrcAlignment, ASTContext &Ctx) |
239 | 0 | : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) { |
240 | 0 | this->appendStr(Prefix); |
241 | 0 | this->appendStr(llvm::to_string(DstAlignment.getQuantity())); |
242 | 0 | this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity())); |
243 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFuncName<false>::GenBinaryFuncName(llvm::StringRef, clang::CharUnits, clang::CharUnits, clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFuncName<true>::GenBinaryFuncName(llvm::StringRef, clang::CharUnits, clang::CharUnits, clang::ASTContext&) |
244 | | |
245 | 0 | void flushTrivialFields() { |
246 | 0 | if (this->Start == this->End) |
247 | 0 | return; |
248 | | |
249 | 0 | this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" + |
250 | 0 | llvm::to_string((this->End - this->Start).getQuantity())); |
251 | |
|
252 | 0 | this->Start = this->End = CharUnits::Zero(); |
253 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFuncName<false>::flushTrivialFields() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFuncName<true>::flushTrivialFields() |
254 | | |
255 | | void visitVolatileTrivial(QualType FT, const FieldDecl *FD, |
256 | 0 | CharUnits CurStructOffset) { |
257 | | // Zero-length bit-fields don't need to be copied/assigned. |
258 | 0 | if (FD && FD->isZeroLengthBitField(this->Ctx)) |
259 | 0 | return; |
260 | | |
261 | | // Because volatile fields can be bit-fields and are individually copied, |
262 | | // their offset and width are in bits. |
263 | 0 | uint64_t OffsetInBits = |
264 | 0 | this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD); |
265 | 0 | this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" + |
266 | 0 | llvm::to_string(getFieldSize(FD, FT, this->Ctx))); |
267 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFuncName<false>::visitVolatileTrivial(clang::QualType, clang::FieldDecl const*, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFuncName<true>::visitVolatileTrivial(clang::QualType, clang::FieldDecl const*, clang::CharUnits) |
268 | | }; |
269 | | |
270 | | struct GenDefaultInitializeFuncName |
271 | | : GenUnaryFuncName<GenDefaultInitializeFuncName>, |
272 | | DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> { |
273 | | using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>; |
274 | | GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx) |
275 | | : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_", |
276 | 0 | DstAlignment, Ctx) {} |
277 | | void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, |
278 | 0 | const FieldDecl *FD, CharUnits CurStructOffset) { |
279 | 0 | if (const auto *AT = getContext().getAsArrayType(FT)) { |
280 | 0 | visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset); |
281 | 0 | return; |
282 | 0 | } |
283 | | |
284 | 0 | Super::visitWithKind(PDIK, FT, FD, CurStructOffset); |
285 | 0 | } |
286 | | }; |
287 | | |
288 | | struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>, |
289 | | DestructedTypeVisitor<GenDestructorFuncName> { |
290 | | using Super = DestructedTypeVisitor<GenDestructorFuncName>; |
291 | | GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment, |
292 | | ASTContext &Ctx) |
293 | 0 | : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {} |
294 | | void visitWithKind(QualType::DestructionKind DK, QualType FT, |
295 | 0 | const FieldDecl *FD, CharUnits CurStructOffset) { |
296 | 0 | if (const auto *AT = getContext().getAsArrayType(FT)) { |
297 | 0 | visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset); |
298 | 0 | return; |
299 | 0 | } |
300 | | |
301 | 0 | Super::visitWithKind(DK, FT, FD, CurStructOffset); |
302 | 0 | } |
303 | | }; |
304 | | |
305 | | // Helper function that creates CGFunctionInfo for an N-ary special function. |
306 | | template <size_t N> |
307 | | static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM, |
308 | 0 | FunctionArgList &Args) { |
309 | 0 | ASTContext &Ctx = CGM.getContext(); |
310 | 0 | llvm::SmallVector<ImplicitParamDecl *, N> Params; |
311 | 0 | QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy); |
312 | |
|
313 | 0 | for (unsigned I = 0; I < N; ++I) |
314 | 0 | Params.push_back(ImplicitParamDecl::Create( |
315 | 0 | Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy, |
316 | 0 | ImplicitParamKind::Other)); |
317 | |
|
318 | 0 | llvm::append_range(Args, Params); |
319 | |
|
320 | 0 | return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args); |
321 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:clang::CodeGen::CGFunctionInfo const& (anonymous namespace)::getFunctionInfo<1ul>(clang::CodeGen::CodeGenModule&, clang::CodeGen::FunctionArgList&) Unexecuted instantiation: CGNonTrivialStruct.cpp:clang::CodeGen::CGFunctionInfo const& (anonymous namespace)::getFunctionInfo<2ul>(clang::CodeGen::CodeGenModule&, clang::CodeGen::FunctionArgList&) |
322 | | |
323 | | template <size_t N, size_t... Ints> |
324 | | static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq, |
325 | | std::array<CharUnits, N> Alignments, |
326 | | const FunctionArgList &Args, |
327 | 0 | CodeGenFunction *CGF) { |
328 | 0 | return std::array<Address, N>{ |
329 | 0 | {Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])), |
330 | 0 | CGF->VoidPtrTy, Alignments[Ints], KnownNonNull)...}}; |
331 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:std::__1::array<clang::CodeGen::Address, 1ul> (anonymous namespace)::getParamAddrs<1ul, 0ul>(std::__1::integer_sequence<unsigned long, 0ul>, std::__1::array<clang::CharUnits, 1ul>, clang::CodeGen::FunctionArgList const&, clang::CodeGen::CodeGenFunction*) Unexecuted instantiation: CGNonTrivialStruct.cpp:std::__1::array<clang::CodeGen::Address, 2ul> (anonymous namespace)::getParamAddrs<2ul, 0ul, 1ul>(std::__1::integer_sequence<unsigned long, 0ul, 1ul>, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::FunctionArgList const&, clang::CodeGen::CodeGenFunction*) |
332 | | |
333 | | // Template classes that are used as bases for classes that emit special |
334 | | // functions. |
335 | | template <class Derived> struct GenFuncBase { |
336 | | template <size_t N> |
337 | | void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset, |
338 | 0 | std::array<Address, N> Addrs) { |
339 | 0 | this->asDerived().callSpecialFunction( |
340 | 0 | FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs); |
341 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::visitStruct<1ul>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::visitStruct<1ul>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::visitStruct<2ul>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::visitStruct<2ul>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::visitStruct<2ul>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::visitStruct<2ul>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) |
342 | | |
343 | | template <class FieldKind, size_t N> |
344 | | void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, |
345 | | const FieldDecl *FD, CharUnits CurStructOffset, |
346 | 0 | std::array<Address, N> Addrs) { |
347 | | // Non-volatile trivial fields are copied when flushTrivialFields is called. |
348 | 0 | if (!FK) |
349 | 0 | return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset, |
350 | 0 | Addrs); |
351 | | |
352 | 0 | asDerived().flushTrivialFields(Addrs); |
353 | 0 | CodeGenFunction &CGF = *this->CGF; |
354 | 0 | ASTContext &Ctx = CGF.getContext(); |
355 | | |
356 | | // Compute the end address. |
357 | 0 | QualType BaseEltQT; |
358 | 0 | std::array<Address, N> StartAddrs = Addrs; |
359 | 0 | for (unsigned I = 0; I < N; ++I) |
360 | 0 | StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD); |
361 | 0 | Address DstAddr = StartAddrs[DstIdx]; |
362 | 0 | llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr); |
363 | 0 | unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity(); |
364 | 0 | llvm::Value *BaseEltSizeVal = |
365 | 0 | llvm::ConstantInt::get(NumElts->getType(), BaseEltSize); |
366 | 0 | llvm::Value *SizeInBytes = |
367 | 0 | CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); |
368 | 0 | llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP( |
369 | 0 | CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes); |
370 | 0 | llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); |
371 | | |
372 | | // Create the header block and insert the phi instructions. |
373 | 0 | llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header"); |
374 | 0 | CGF.EmitBlock(HeaderBB); |
375 | 0 | llvm::PHINode *PHIs[N]; |
376 | |
|
377 | 0 | for (unsigned I = 0; I < N; ++I) { |
378 | 0 | PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); |
379 | 0 | PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); |
380 | 0 | } |
381 | | |
382 | | // Create the exit and loop body blocks. |
383 | 0 | llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit"); |
384 | 0 | llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body"); |
385 | | |
386 | | // Emit the comparison and conditional branch instruction that jumps to |
387 | | // either the exit or the loop body. |
388 | 0 | llvm::Value *Done = |
389 | 0 | CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done"); |
390 | 0 | CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB); |
391 | | |
392 | | // Visit the element of the array in the loop body. |
393 | 0 | CGF.EmitBlock(LoopBB); |
394 | 0 | QualType EltQT = AT->getElementType(); |
395 | 0 | CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT); |
396 | 0 | std::array<Address, N> NewAddrs = Addrs; |
397 | |
|
398 | 0 | for (unsigned I = 0; I < N; ++I) |
399 | 0 | NewAddrs[I] = |
400 | 0 | Address(PHIs[I], CGF.Int8PtrTy, |
401 | 0 | StartAddrs[I].getAlignment().alignmentAtOffset(EltSize)); |
402 | |
|
403 | 0 | EltQT = IsVolatile ? EltQT.withVolatile() : EltQT; |
404 | 0 | this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(), |
405 | 0 | NewAddrs); |
406 | |
|
407 | 0 | LoopBB = CGF.Builder.GetInsertBlock(); |
408 | |
|
409 | 0 | for (unsigned I = 0; I < N; ++I) { |
410 | | // Instrs to update the destination and source addresses. |
411 | | // Update phi instructions. |
412 | 0 | NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); |
413 | 0 | PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); |
414 | 0 | } |
415 | | |
416 | | // Insert an unconditional branch to the header block. |
417 | 0 | CGF.Builder.CreateBr(HeaderBB); |
418 | 0 | CGF.EmitBlock(ExitBB); |
419 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::visitArray<clang::QualType::PrimitiveDefaultInitializeKind, 1ul>(clang::QualType::PrimitiveDefaultInitializeKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::visitArray<clang::QualType::DestructionKind, 1ul>(clang::QualType::DestructionKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::visitArray<clang::QualType::PrimitiveCopyKind, 2ul>(clang::QualType::PrimitiveCopyKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::visitArray<clang::QualType::PrimitiveCopyKind, 2ul>(clang::QualType::PrimitiveCopyKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::visitArray<clang::QualType::PrimitiveCopyKind, 2ul>(clang::QualType::PrimitiveCopyKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::visitArray<clang::QualType::PrimitiveCopyKind, 2ul>(clang::QualType::PrimitiveCopyKind, clang::ArrayType const*, bool, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) |
420 | | |
421 | | /// Return an address with the specified offset from the passed address. |
422 | 0 | Address getAddrWithOffset(Address Addr, CharUnits Offset) { |
423 | 0 | assert(Addr.isValid() && "invalid address"); |
424 | 0 | if (Offset.getQuantity() == 0) |
425 | 0 | return Addr; |
426 | 0 | Addr = Addr.withElementType(CGF->CGM.Int8Ty); |
427 | 0 | Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity()); |
428 | 0 | return Addr.withElementType(CGF->CGM.Int8PtrTy); |
429 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits) |
430 | | |
431 | | Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset, |
432 | 0 | const FieldDecl *FD) { |
433 | 0 | return getAddrWithOffset(Addr, StructFieldOffset + |
434 | 0 | asDerived().getFieldOffset(FD)); |
435 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits, clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits, clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits, clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits, clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits, clang::FieldDecl const*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::getAddrWithOffset(clang::CodeGen::Address, clang::CharUnits, clang::FieldDecl const*) |
436 | | |
437 | | template <size_t N> |
438 | | llvm::Function *getFunction(StringRef FuncName, QualType QT, |
439 | | std::array<CharUnits, N> Alignments, |
440 | 0 | CodeGenModule &CGM) { |
441 | | // If the special function already exists in the module, return it. |
442 | 0 | if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) { |
443 | 0 | bool WrongType = false; |
444 | 0 | if (!F->getReturnType()->isVoidTy()) |
445 | 0 | WrongType = true; |
446 | 0 | else { |
447 | 0 | for (const llvm::Argument &Arg : F->args()) |
448 | 0 | if (Arg.getType() != CGM.Int8PtrPtrTy) |
449 | 0 | WrongType = true; |
450 | 0 | } |
451 | |
|
452 | 0 | if (WrongType) { |
453 | 0 | std::string FuncName = std::string(F->getName()); |
454 | 0 | SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation(); |
455 | 0 | CGM.Error(Loc, "special function " + FuncName + |
456 | 0 | " for non-trivial C struct has incorrect type"); |
457 | 0 | return nullptr; |
458 | 0 | } |
459 | 0 | return F; |
460 | 0 | } |
461 | | |
462 | 0 | ASTContext &Ctx = CGM.getContext(); |
463 | 0 | FunctionArgList Args; |
464 | 0 | const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args); |
465 | 0 | llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI); |
466 | 0 | llvm::Function *F = |
467 | 0 | llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, |
468 | 0 | FuncName, &CGM.getModule()); |
469 | 0 | F->setVisibility(llvm::GlobalValue::HiddenVisibility); |
470 | 0 | CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false); |
471 | 0 | CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); |
472 | 0 | CodeGenFunction NewCGF(CGM); |
473 | 0 | setCGF(&NewCGF); |
474 | 0 | CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args); |
475 | 0 | auto AL = ApplyDebugLocation::CreateArtificial(*CGF); |
476 | 0 | std::array<Address, N> Addrs = |
477 | 0 | getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF); |
478 | 0 | asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs); |
479 | 0 | CGF->FinishFunction(); |
480 | 0 | return F; |
481 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::getFunction<1ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CharUnits, 1ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::getFunction<1ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CharUnits, 1ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::getFunction<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::getFunction<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::getFunction<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::getFunction<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) |
482 | | |
483 | | template <size_t N> |
484 | | void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs, |
485 | 0 | CodeGenFunction &CallerCGF) { |
486 | 0 | std::array<CharUnits, N> Alignments; |
487 | 0 | llvm::Value *Ptrs[N]; |
488 | |
|
489 | 0 | for (unsigned I = 0; I < N; ++I) { |
490 | 0 | Alignments[I] = Addrs[I].getAlignment(); |
491 | 0 | Ptrs[I] = Addrs[I].getPointer(); |
492 | 0 | } |
493 | |
|
494 | 0 | if (llvm::Function *F = |
495 | 0 | getFunction(FuncName, QT, Alignments, CallerCGF.CGM)) |
496 | 0 | CallerCGF.EmitNounwindRuntimeCall(F, Ptrs); |
497 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::callFunc<1ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CodeGen::Address, 1ul>, clang::CodeGen::CodeGenFunction&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::callFunc<1ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CodeGen::Address, 1ul>, clang::CodeGen::CodeGenFunction&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::callFunc<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CodeGen::Address, 2ul>, clang::CodeGen::CodeGenFunction&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::callFunc<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CodeGen::Address, 2ul>, clang::CodeGen::CodeGenFunction&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::callFunc<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CodeGen::Address, 2ul>, clang::CodeGen::CodeGenFunction&) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::callFunc<2ul>(llvm::StringRef, clang::QualType, std::__1::array<clang::CodeGen::Address, 2ul>, clang::CodeGen::CodeGenFunction&) |
498 | | |
499 | 0 | Derived &asDerived() { return static_cast<Derived &>(*this); } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::asDerived() Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::asDerived() |
500 | | |
501 | 0 | void setCGF(CodeGenFunction *F) { CGF = F; } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDefaultInitialize>::setCGF(clang::CodeGen::CodeGenFunction*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenDestructor>::setCGF(clang::CodeGen::CodeGenFunction*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyConstructor>::setCGF(clang::CodeGen::CodeGenFunction*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenCopyAssignment>::setCGF(clang::CodeGen::CodeGenFunction*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveConstructor>::setCGF(clang::CodeGen::CodeGenFunction*) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenFuncBase<(anonymous namespace)::GenMoveAssignment>::setCGF(clang::CodeGen::CodeGenFunction*) |
502 | | |
503 | | CodeGenFunction *CGF = nullptr; |
504 | | }; |
505 | | |
506 | | template <class Derived, bool IsMove> |
507 | | struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>, |
508 | | GenFuncBase<Derived> { |
509 | 0 | GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {} Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenCopyConstructor, false>::GenBinaryFunc(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenCopyAssignment, false>::GenBinaryFunc(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenMoveConstructor, true>::GenBinaryFunc(clang::ASTContext&) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenMoveAssignment, true>::GenBinaryFunc(clang::ASTContext&) |
510 | | |
511 | 0 | void flushTrivialFields(std::array<Address, 2> Addrs) { |
512 | 0 | CharUnits Size = this->End - this->Start; |
513 | |
|
514 | 0 | if (Size.getQuantity() == 0) |
515 | 0 | return; |
516 | | |
517 | 0 | Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start); |
518 | 0 | Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start); |
519 | | |
520 | | // Emit memcpy. |
521 | 0 | if (Size.getQuantity() >= 16 || |
522 | 0 | !llvm::has_single_bit<uint32_t>(Size.getQuantity())) { |
523 | 0 | llvm::Value *SizeVal = |
524 | 0 | llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity()); |
525 | 0 | DstAddr = DstAddr.withElementType(this->CGF->Int8Ty); |
526 | 0 | SrcAddr = SrcAddr.withElementType(this->CGF->Int8Ty); |
527 | 0 | this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false); |
528 | 0 | } else { |
529 | 0 | llvm::Type *Ty = llvm::Type::getIntNTy( |
530 | 0 | this->CGF->getLLVMContext(), |
531 | 0 | Size.getQuantity() * this->CGF->getContext().getCharWidth()); |
532 | 0 | DstAddr = DstAddr.withElementType(Ty); |
533 | 0 | SrcAddr = SrcAddr.withElementType(Ty); |
534 | 0 | llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false); |
535 | 0 | this->CGF->Builder.CreateStore(SrcVal, DstAddr, false); |
536 | 0 | } |
537 | |
|
538 | 0 | this->Start = this->End = CharUnits::Zero(); |
539 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenCopyConstructor, false>::flushTrivialFields(std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenCopyAssignment, false>::flushTrivialFields(std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenMoveConstructor, true>::flushTrivialFields(std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:(anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenMoveAssignment, true>::flushTrivialFields(std::__1::array<clang::CodeGen::Address, 2ul>) |
540 | | |
541 | | template <class... Ts> |
542 | | void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset, |
543 | 0 | std::array<Address, 2> Addrs) { |
544 | 0 | LValue DstLV, SrcLV; |
545 | 0 | if (FD) { |
546 | | // No need to copy zero-length bit-fields. |
547 | 0 | if (FD->isZeroLengthBitField(this->CGF->getContext())) |
548 | 0 | return; |
549 | | |
550 | 0 | QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); |
551 | 0 | llvm::Type *Ty = this->CGF->ConvertType(RT); |
552 | 0 | Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset); |
553 | 0 | LValue DstBase = |
554 | 0 | this->CGF->MakeAddrLValue(DstAddr.withElementType(Ty), FT); |
555 | 0 | DstLV = this->CGF->EmitLValueForField(DstBase, FD); |
556 | 0 | Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset); |
557 | 0 | LValue SrcBase = |
558 | 0 | this->CGF->MakeAddrLValue(SrcAddr.withElementType(Ty), FT); |
559 | 0 | SrcLV = this->CGF->EmitLValueForField(SrcBase, FD); |
560 | 0 | } else { |
561 | 0 | llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT); |
562 | 0 | Address DstAddr = Addrs[DstIdx].withElementType(Ty); |
563 | 0 | Address SrcAddr = Addrs[SrcIdx].withElementType(Ty); |
564 | 0 | DstLV = this->CGF->MakeAddrLValue(DstAddr, FT); |
565 | 0 | SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT); |
566 | 0 | } |
567 | 0 | RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation()); |
568 | 0 | this->CGF->EmitStoreThroughLValue(SrcVal, DstLV); |
569 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenCopyConstructor, false>::visitVolatileTrivial<>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenCopyAssignment, false>::visitVolatileTrivial<>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenMoveConstructor, true>::visitVolatileTrivial<>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void (anonymous namespace)::GenBinaryFunc<(anonymous namespace)::GenMoveAssignment, true>::visitVolatileTrivial<>(clang::QualType, clang::FieldDecl const*, clang::CharUnits, std::__1::array<clang::CodeGen::Address, 2ul>) |
570 | | }; |
571 | | |
572 | | // These classes that emit the special functions for a non-trivial struct. |
573 | | struct GenDestructor : StructVisitor<GenDestructor>, |
574 | | GenFuncBase<GenDestructor>, |
575 | | DestructedTypeVisitor<GenDestructor> { |
576 | | using Super = DestructedTypeVisitor<GenDestructor>; |
577 | 0 | GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {} |
578 | | |
579 | | void visitWithKind(QualType::DestructionKind DK, QualType FT, |
580 | | const FieldDecl *FD, CharUnits CurStructOffset, |
581 | 0 | std::array<Address, 1> Addrs) { |
582 | 0 | if (const auto *AT = getContext().getAsArrayType(FT)) { |
583 | 0 | visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs); |
584 | 0 | return; |
585 | 0 | } |
586 | | |
587 | 0 | Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs); |
588 | 0 | } |
589 | | |
590 | | void visitARCStrong(QualType QT, const FieldDecl *FD, |
591 | 0 | CharUnits CurStructOffset, std::array<Address, 1> Addrs) { |
592 | 0 | CGF->destroyARCStrongImprecise( |
593 | 0 | *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); |
594 | 0 | } |
595 | | |
596 | | void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, |
597 | 0 | std::array<Address, 1> Addrs) { |
598 | 0 | CGF->destroyARCWeak( |
599 | 0 | *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); |
600 | 0 | } |
601 | | |
602 | | void callSpecialFunction(QualType FT, CharUnits Offset, |
603 | 0 | std::array<Address, 1> Addrs) { |
604 | 0 | CGF->callCStructDestructor( |
605 | 0 | CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT)); |
606 | 0 | } |
607 | | }; |
608 | | |
609 | | struct GenDefaultInitialize |
610 | | : StructVisitor<GenDefaultInitialize>, |
611 | | GenFuncBase<GenDefaultInitialize>, |
612 | | DefaultInitializedTypeVisitor<GenDefaultInitialize> { |
613 | | using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>; |
614 | | typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy; |
615 | | |
616 | | GenDefaultInitialize(ASTContext &Ctx) |
617 | 0 | : StructVisitor<GenDefaultInitialize>(Ctx) {} |
618 | | |
619 | | void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, |
620 | | const FieldDecl *FD, CharUnits CurStructOffset, |
621 | 0 | std::array<Address, 1> Addrs) { |
622 | 0 | if (const auto *AT = getContext().getAsArrayType(FT)) { |
623 | 0 | visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset, |
624 | 0 | Addrs); |
625 | 0 | return; |
626 | 0 | } |
627 | | |
628 | 0 | Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs); |
629 | 0 | } |
630 | | |
631 | | void visitARCStrong(QualType QT, const FieldDecl *FD, |
632 | 0 | CharUnits CurStructOffset, std::array<Address, 1> Addrs) { |
633 | 0 | CGF->EmitNullInitialization( |
634 | 0 | getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); |
635 | 0 | } |
636 | | |
637 | | void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, |
638 | 0 | std::array<Address, 1> Addrs) { |
639 | 0 | CGF->EmitNullInitialization( |
640 | 0 | getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT); |
641 | 0 | } |
642 | | |
643 | | template <class FieldKind, size_t... Is> |
644 | | void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile, |
645 | | const FieldDecl *FD, CharUnits CurStructOffset, |
646 | 0 | std::array<Address, 1> Addrs) { |
647 | 0 | if (!FK) |
648 | 0 | return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs); |
649 | | |
650 | 0 | ASTContext &Ctx = getContext(); |
651 | 0 | CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0)); |
652 | 0 | QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0)); |
653 | |
|
654 | 0 | if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) { |
655 | 0 | GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs); |
656 | 0 | return; |
657 | 0 | } |
658 | | |
659 | 0 | llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity()); |
660 | 0 | Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
661 | 0 | Address Loc = DstAddr.withElementType(CGF->Int8Ty); |
662 | 0 | CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal, |
663 | 0 | IsVolatile); |
664 | 0 | } |
665 | | |
666 | | void callSpecialFunction(QualType FT, CharUnits Offset, |
667 | 0 | std::array<Address, 1> Addrs) { |
668 | 0 | CGF->callCStructDefaultConstructor( |
669 | 0 | CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT)); |
670 | 0 | } |
671 | | }; |
672 | | |
673 | | struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> { |
674 | | GenCopyConstructor(ASTContext &Ctx) |
675 | 0 | : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {} |
676 | | |
677 | | void visitARCStrong(QualType QT, const FieldDecl *FD, |
678 | 0 | CharUnits CurStructOffset, std::array<Address, 2> Addrs) { |
679 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
680 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
681 | 0 | llvm::Value *SrcVal = CGF->EmitLoadOfScalar( |
682 | 0 | Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation()); |
683 | 0 | llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal); |
684 | 0 | CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true); |
685 | 0 | } |
686 | | |
687 | | void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, |
688 | 0 | std::array<Address, 2> Addrs) { |
689 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
690 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
691 | 0 | CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]); |
692 | 0 | } |
693 | | |
694 | | void callSpecialFunction(QualType FT, CharUnits Offset, |
695 | 0 | std::array<Address, 2> Addrs) { |
696 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); |
697 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); |
698 | 0 | CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT), |
699 | 0 | CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); |
700 | 0 | } |
701 | | }; |
702 | | |
703 | | struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> { |
704 | | GenMoveConstructor(ASTContext &Ctx) |
705 | 0 | : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {} |
706 | | |
707 | | void visitARCStrong(QualType QT, const FieldDecl *FD, |
708 | 0 | CharUnits CurStructOffset, std::array<Address, 2> Addrs) { |
709 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
710 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
711 | 0 | LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); |
712 | 0 | llvm::Value *SrcVal = |
713 | 0 | CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); |
714 | 0 | CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV); |
715 | 0 | CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT), |
716 | 0 | /* isInitialization */ true); |
717 | 0 | } |
718 | | |
719 | | void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, |
720 | 0 | std::array<Address, 2> Addrs) { |
721 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
722 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
723 | 0 | CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]); |
724 | 0 | } |
725 | | |
726 | | void callSpecialFunction(QualType FT, CharUnits Offset, |
727 | 0 | std::array<Address, 2> Addrs) { |
728 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); |
729 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); |
730 | 0 | CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT), |
731 | 0 | CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); |
732 | 0 | } |
733 | | }; |
734 | | |
735 | | struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> { |
736 | | GenCopyAssignment(ASTContext &Ctx) |
737 | 0 | : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {} |
738 | | |
739 | | void visitARCStrong(QualType QT, const FieldDecl *FD, |
740 | 0 | CharUnits CurStructOffset, std::array<Address, 2> Addrs) { |
741 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
742 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
743 | 0 | llvm::Value *SrcVal = CGF->EmitLoadOfScalar( |
744 | 0 | Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation()); |
745 | 0 | CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal, |
746 | 0 | false); |
747 | 0 | } |
748 | | |
749 | | void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, |
750 | 0 | std::array<Address, 2> Addrs) { |
751 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
752 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
753 | 0 | CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); |
754 | 0 | } |
755 | | |
756 | | void callSpecialFunction(QualType FT, CharUnits Offset, |
757 | 0 | std::array<Address, 2> Addrs) { |
758 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); |
759 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); |
760 | 0 | CGF->callCStructCopyAssignmentOperator( |
761 | 0 | CGF->MakeAddrLValue(Addrs[DstIdx], FT), |
762 | 0 | CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); |
763 | 0 | } |
764 | | }; |
765 | | |
766 | | struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> { |
767 | | GenMoveAssignment(ASTContext &Ctx) |
768 | 0 | : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {} |
769 | | |
770 | | void visitARCStrong(QualType QT, const FieldDecl *FD, |
771 | 0 | CharUnits CurStructOffset, std::array<Address, 2> Addrs) { |
772 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
773 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
774 | 0 | LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); |
775 | 0 | llvm::Value *SrcVal = |
776 | 0 | CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); |
777 | 0 | CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV); |
778 | 0 | LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT); |
779 | 0 | llvm::Value *DstVal = |
780 | 0 | CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); |
781 | 0 | CGF->EmitStoreOfScalar(SrcVal, DstLV); |
782 | 0 | CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime); |
783 | 0 | } |
784 | | |
785 | | void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset, |
786 | 0 | std::array<Address, 2> Addrs) { |
787 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD); |
788 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD); |
789 | 0 | CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]); |
790 | 0 | } |
791 | | |
792 | | void callSpecialFunction(QualType FT, CharUnits Offset, |
793 | 0 | std::array<Address, 2> Addrs) { |
794 | 0 | Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset); |
795 | 0 | Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset); |
796 | 0 | CGF->callCStructMoveAssignmentOperator( |
797 | 0 | CGF->MakeAddrLValue(Addrs[DstIdx], FT), |
798 | 0 | CGF->MakeAddrLValue(Addrs[SrcIdx], FT)); |
799 | 0 | } |
800 | | }; |
801 | | |
802 | | } // namespace |
803 | | |
804 | | void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF, |
805 | 0 | Address Addr, QualType Type) { |
806 | 0 | CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type)); |
807 | 0 | } |
808 | | |
809 | | // Default-initialize a variable that is a non-trivial struct or an array of |
810 | | // such structure. |
811 | 0 | void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) { |
812 | 0 | GenDefaultInitialize Gen(getContext()); |
813 | 0 | Address DstPtr = Dst.getAddress(*this).withElementType(CGM.Int8PtrTy); |
814 | 0 | Gen.setCGF(this); |
815 | 0 | QualType QT = Dst.getType(); |
816 | 0 | QT = Dst.isVolatile() ? QT.withVolatile() : QT; |
817 | 0 | Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}})); |
818 | 0 | } |
819 | | |
820 | | template <class G, size_t N> |
821 | | static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, |
822 | | bool IsVolatile, CodeGenFunction &CGF, |
823 | 0 | std::array<Address, N> Addrs) { |
824 | 0 | auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF); |
825 | 0 | for (unsigned I = 0; I < N; ++I) |
826 | 0 | Addrs[I] = Addrs[I].withElementType(CGF.CGM.Int8PtrTy); |
827 | 0 | QT = IsVolatile ? QT.withVolatile() : QT; |
828 | 0 | Gen.callFunc(FuncName, QT, Addrs, CGF); |
829 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:void callSpecialFunction<(anonymous namespace)::GenDefaultInitialize, 1ul>((anonymous namespace)::GenDefaultInitialize&&, llvm::StringRef, clang::QualType, bool, clang::CodeGen::CodeGenFunction&, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void callSpecialFunction<(anonymous namespace)::GenDestructor, 1ul>((anonymous namespace)::GenDestructor&&, llvm::StringRef, clang::QualType, bool, clang::CodeGen::CodeGenFunction&, std::__1::array<clang::CodeGen::Address, 1ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void callSpecialFunction<(anonymous namespace)::GenCopyConstructor, 2ul>((anonymous namespace)::GenCopyConstructor&&, llvm::StringRef, clang::QualType, bool, clang::CodeGen::CodeGenFunction&, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void callSpecialFunction<(anonymous namespace)::GenCopyAssignment, 2ul>((anonymous namespace)::GenCopyAssignment&&, llvm::StringRef, clang::QualType, bool, clang::CodeGen::CodeGenFunction&, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void callSpecialFunction<(anonymous namespace)::GenMoveConstructor, 2ul>((anonymous namespace)::GenMoveConstructor&&, llvm::StringRef, clang::QualType, bool, clang::CodeGen::CodeGenFunction&, std::__1::array<clang::CodeGen::Address, 2ul>) Unexecuted instantiation: CGNonTrivialStruct.cpp:void callSpecialFunction<(anonymous namespace)::GenMoveAssignment, 2ul>((anonymous namespace)::GenMoveAssignment&&, llvm::StringRef, clang::QualType, bool, clang::CodeGen::CodeGenFunction&, std::__1::array<clang::CodeGen::Address, 2ul>) |
830 | | |
831 | | template <class G, size_t N> |
832 | | static llvm::Function * |
833 | | getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, |
834 | 0 | std::array<CharUnits, N> Alignments, CodeGenModule &CGM) { |
835 | 0 | QT = IsVolatile ? QT.withVolatile() : QT; |
836 | | // The following call requires an array of addresses as arguments, but doesn't |
837 | | // actually use them (it overwrites them with the addresses of the arguments |
838 | | // of the created function). |
839 | 0 | return Gen.getFunction(FuncName, QT, Alignments, CGM); |
840 | 0 | } Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* getSpecialFunction<(anonymous namespace)::GenDefaultInitialize, 1ul>((anonymous namespace)::GenDefaultInitialize&&, llvm::StringRef, clang::QualType, bool, std::__1::array<clang::CharUnits, 1ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* getSpecialFunction<(anonymous namespace)::GenCopyConstructor, 2ul>((anonymous namespace)::GenCopyConstructor&&, llvm::StringRef, clang::QualType, bool, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* getSpecialFunction<(anonymous namespace)::GenMoveConstructor, 2ul>((anonymous namespace)::GenMoveConstructor&&, llvm::StringRef, clang::QualType, bool, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* getSpecialFunction<(anonymous namespace)::GenCopyAssignment, 2ul>((anonymous namespace)::GenCopyAssignment&&, llvm::StringRef, clang::QualType, bool, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* getSpecialFunction<(anonymous namespace)::GenMoveAssignment, 2ul>((anonymous namespace)::GenMoveAssignment&&, llvm::StringRef, clang::QualType, bool, std::__1::array<clang::CharUnits, 2ul>, clang::CodeGen::CodeGenModule&) Unexecuted instantiation: CGNonTrivialStruct.cpp:llvm::Function* getSpecialFunction<(anonymous namespace)::GenDestructor, 1ul>((anonymous namespace)::GenDestructor&&, llvm::StringRef, clang::QualType, bool, std::__1::array<clang::CharUnits, 1ul>, clang::CodeGen::CodeGenModule&) |
841 | | |
842 | | // Functions to emit calls to the special functions of a non-trivial C struct. |
843 | 0 | void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) { |
844 | 0 | bool IsVolatile = Dst.isVolatile(); |
845 | 0 | Address DstPtr = Dst.getAddress(*this); |
846 | 0 | QualType QT = Dst.getType(); |
847 | 0 | GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext()); |
848 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
849 | 0 | callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT, |
850 | 0 | IsVolatile, *this, std::array<Address, 1>({{DstPtr}})); |
851 | 0 | } |
852 | | |
853 | | std::string CodeGenFunction::getNonTrivialCopyConstructorStr( |
854 | 0 | QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) { |
855 | 0 | GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx); |
856 | 0 | return GenName.getName(QT, IsVolatile); |
857 | 0 | } |
858 | | |
859 | | std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT, |
860 | | CharUnits Alignment, |
861 | | bool IsVolatile, |
862 | 0 | ASTContext &Ctx) { |
863 | 0 | GenDestructorFuncName GenName("", Alignment, Ctx); |
864 | 0 | return GenName.getName(QT, IsVolatile); |
865 | 0 | } |
866 | | |
867 | 0 | void CodeGenFunction::callCStructDestructor(LValue Dst) { |
868 | 0 | bool IsVolatile = Dst.isVolatile(); |
869 | 0 | Address DstPtr = Dst.getAddress(*this); |
870 | 0 | QualType QT = Dst.getType(); |
871 | 0 | GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(), |
872 | 0 | getContext()); |
873 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
874 | 0 | callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile, |
875 | 0 | *this, std::array<Address, 1>({{DstPtr}})); |
876 | 0 | } |
877 | | |
878 | 0 | void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) { |
879 | 0 | bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); |
880 | 0 | Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); |
881 | 0 | QualType QT = Dst.getType(); |
882 | 0 | GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(), |
883 | 0 | SrcPtr.getAlignment(), getContext()); |
884 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
885 | 0 | callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT, |
886 | 0 | IsVolatile, *this, |
887 | 0 | std::array<Address, 2>({{DstPtr, SrcPtr}})); |
888 | 0 | } |
889 | | |
890 | | void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src |
891 | | |
892 | 0 | ) { |
893 | 0 | bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); |
894 | 0 | Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); |
895 | 0 | QualType QT = Dst.getType(); |
896 | 0 | GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(), |
897 | 0 | SrcPtr.getAlignment(), getContext()); |
898 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
899 | 0 | callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile, |
900 | 0 | *this, std::array<Address, 2>({{DstPtr, SrcPtr}})); |
901 | 0 | } |
902 | | |
903 | 0 | void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) { |
904 | 0 | bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); |
905 | 0 | Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); |
906 | 0 | QualType QT = Dst.getType(); |
907 | 0 | GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(), |
908 | 0 | SrcPtr.getAlignment(), getContext()); |
909 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
910 | 0 | callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT, |
911 | 0 | IsVolatile, *this, |
912 | 0 | std::array<Address, 2>({{DstPtr, SrcPtr}})); |
913 | 0 | } |
914 | | |
915 | | void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src |
916 | | |
917 | 0 | ) { |
918 | 0 | bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); |
919 | 0 | Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); |
920 | 0 | QualType QT = Dst.getType(); |
921 | 0 | GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(), |
922 | 0 | SrcPtr.getAlignment(), getContext()); |
923 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
924 | 0 | callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile, |
925 | 0 | *this, std::array<Address, 2>({{DstPtr, SrcPtr}})); |
926 | 0 | } |
927 | | |
928 | | llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor( |
929 | 0 | CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) { |
930 | 0 | ASTContext &Ctx = CGM.getContext(); |
931 | 0 | GenDefaultInitializeFuncName GenName(DstAlignment, Ctx); |
932 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
933 | 0 | return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile, |
934 | 0 | std::array<CharUnits, 1>({{DstAlignment}}), CGM); |
935 | 0 | } |
936 | | |
937 | | llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor( |
938 | | CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, |
939 | 0 | bool IsVolatile, QualType QT) { |
940 | 0 | ASTContext &Ctx = CGM.getContext(); |
941 | 0 | GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment, |
942 | 0 | SrcAlignment, Ctx); |
943 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
944 | 0 | return getSpecialFunction( |
945 | 0 | GenCopyConstructor(Ctx), FuncName, QT, IsVolatile, |
946 | 0 | std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); |
947 | 0 | } |
948 | | |
949 | | llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor( |
950 | | CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, |
951 | 0 | bool IsVolatile, QualType QT) { |
952 | 0 | ASTContext &Ctx = CGM.getContext(); |
953 | 0 | GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment, |
954 | 0 | SrcAlignment, Ctx); |
955 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
956 | 0 | return getSpecialFunction( |
957 | 0 | GenMoveConstructor(Ctx), FuncName, QT, IsVolatile, |
958 | 0 | std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); |
959 | 0 | } |
960 | | |
961 | | llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator( |
962 | | CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, |
963 | 0 | bool IsVolatile, QualType QT) { |
964 | 0 | ASTContext &Ctx = CGM.getContext(); |
965 | 0 | GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment, |
966 | 0 | SrcAlignment, Ctx); |
967 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
968 | 0 | return getSpecialFunction( |
969 | 0 | GenCopyAssignment(Ctx), FuncName, QT, IsVolatile, |
970 | 0 | std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); |
971 | 0 | } |
972 | | |
973 | | llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator( |
974 | | CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, |
975 | 0 | bool IsVolatile, QualType QT) { |
976 | 0 | ASTContext &Ctx = CGM.getContext(); |
977 | 0 | GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment, |
978 | 0 | SrcAlignment, Ctx); |
979 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
980 | 0 | return getSpecialFunction( |
981 | 0 | GenMoveAssignment(Ctx), FuncName, QT, IsVolatile, |
982 | 0 | std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM); |
983 | 0 | } |
984 | | |
985 | | llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor( |
986 | 0 | CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) { |
987 | 0 | ASTContext &Ctx = CGM.getContext(); |
988 | 0 | GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx); |
989 | 0 | std::string FuncName = GenName.getName(QT, IsVolatile); |
990 | 0 | return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile, |
991 | 0 | std::array<CharUnits, 1>({{DstAlignment}}), CGM); |
992 | 0 | } |