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