17275da0fSAkira Hatanaka //===--- CGNonTrivialStruct.cpp - Emit Special Functions for C Structs ----===//
27275da0fSAkira Hatanaka //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67275da0fSAkira Hatanaka //
77275da0fSAkira Hatanaka //===----------------------------------------------------------------------===//
87275da0fSAkira Hatanaka //
97275da0fSAkira Hatanaka // This file defines functions to generate various special functions for C
107275da0fSAkira Hatanaka // structs.
117275da0fSAkira Hatanaka //
127275da0fSAkira Hatanaka //===----------------------------------------------------------------------===//
137275da0fSAkira Hatanaka
147275da0fSAkira Hatanaka #include "CodeGenFunction.h"
157275da0fSAkira Hatanaka #include "CodeGenModule.h"
1652a84e75SAkira Hatanaka #include "clang/AST/NonTrivialTypeVisitor.h"
17827aeb46SJohn McCall #include "clang/CodeGen/CodeGenABITypes.h"
187275da0fSAkira Hatanaka #include "llvm/Support/ScopedPrinter.h"
197275da0fSAkira Hatanaka #include <array>
207275da0fSAkira Hatanaka
217275da0fSAkira Hatanaka using namespace clang;
227275da0fSAkira Hatanaka using namespace CodeGen;
237275da0fSAkira Hatanaka
247275da0fSAkira Hatanaka // Return the size of a field in number of bits.
getFieldSize(const FieldDecl * FD,QualType FT,ASTContext & Ctx)257c55265cSAkira Hatanaka static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
267c55265cSAkira Hatanaka ASTContext &Ctx) {
277c55265cSAkira Hatanaka if (FD && FD->isBitField())
287275da0fSAkira Hatanaka return FD->getBitWidthValue(Ctx);
297c55265cSAkira Hatanaka return Ctx.getTypeSize(FT);
307275da0fSAkira Hatanaka }
317275da0fSAkira Hatanaka
327275da0fSAkira Hatanaka namespace {
337275da0fSAkira Hatanaka enum { DstIdx = 0, SrcIdx = 1 };
347275da0fSAkira Hatanaka const char *ValNameStr[2] = {"dst", "src"};
357275da0fSAkira Hatanaka
367275da0fSAkira Hatanaka template <class Derived> struct StructVisitor {
StructVisitor__anon25af64e30111::StructVisitor377275da0fSAkira Hatanaka StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
387275da0fSAkira Hatanaka
397275da0fSAkira Hatanaka template <class... Ts>
visitStructFields__anon25af64e30111::StructVisitor407275da0fSAkira Hatanaka void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
417275da0fSAkira Hatanaka const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
427275da0fSAkira Hatanaka
437275da0fSAkira Hatanaka // Iterate over the fields of the struct.
447275da0fSAkira Hatanaka for (const FieldDecl *FD : RD->fields()) {
457275da0fSAkira Hatanaka QualType FT = FD->getType();
467275da0fSAkira Hatanaka FT = QT.isVolatileQualified() ? FT.withVolatile() : FT;
477275da0fSAkira Hatanaka asDerived().visit(FT, FD, CurStructOffset, Args...);
487275da0fSAkira Hatanaka }
497275da0fSAkira Hatanaka
507275da0fSAkira Hatanaka asDerived().flushTrivialFields(Args...);
517275da0fSAkira Hatanaka }
527275da0fSAkira Hatanaka
visitTrivial__anon25af64e30111::StructVisitor537275da0fSAkira Hatanaka template <class... Ts> void visitTrivial(Ts... Args) {}
547275da0fSAkira Hatanaka
visitCXXDestructor__anon25af64e30111::StructVisitor557275da0fSAkira Hatanaka template <class... Ts> void visitCXXDestructor(Ts... Args) {
567275da0fSAkira Hatanaka llvm_unreachable("field of a C++ struct type is not expected");
577275da0fSAkira Hatanaka }
587275da0fSAkira Hatanaka
flushTrivialFields__anon25af64e30111::StructVisitor597275da0fSAkira Hatanaka template <class... Ts> void flushTrivialFields(Ts... Args) {}
607275da0fSAkira Hatanaka
getFieldOffsetInBits__anon25af64e30111::StructVisitor617275da0fSAkira Hatanaka uint64_t getFieldOffsetInBits(const FieldDecl *FD) {
627275da0fSAkira Hatanaka return FD ? Ctx.getASTRecordLayout(FD->getParent())
637275da0fSAkira Hatanaka .getFieldOffset(FD->getFieldIndex())
647275da0fSAkira Hatanaka : 0;
657275da0fSAkira Hatanaka }
667275da0fSAkira Hatanaka
getFieldOffset__anon25af64e30111::StructVisitor677275da0fSAkira Hatanaka CharUnits getFieldOffset(const FieldDecl *FD) {
687275da0fSAkira Hatanaka return Ctx.toCharUnitsFromBits(getFieldOffsetInBits(FD));
697275da0fSAkira Hatanaka }
707275da0fSAkira Hatanaka
asDerived__anon25af64e30111::StructVisitor717275da0fSAkira Hatanaka Derived &asDerived() { return static_cast<Derived &>(*this); }
727275da0fSAkira Hatanaka
getContext__anon25af64e30111::StructVisitor737275da0fSAkira Hatanaka ASTContext &getContext() { return Ctx; }
747275da0fSAkira Hatanaka ASTContext &Ctx;
757275da0fSAkira Hatanaka };
767275da0fSAkira Hatanaka
777275da0fSAkira Hatanaka template <class Derived, bool IsMove>
787275da0fSAkira Hatanaka struct CopyStructVisitor : StructVisitor<Derived>,
797275da0fSAkira Hatanaka CopiedTypeVisitor<Derived, IsMove> {
807275da0fSAkira Hatanaka using StructVisitor<Derived>::asDerived;
8152a84e75SAkira Hatanaka using Super = CopiedTypeVisitor<Derived, IsMove>;
827275da0fSAkira Hatanaka
CopyStructVisitor__anon25af64e30111::CopyStructVisitor837275da0fSAkira Hatanaka CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
847275da0fSAkira Hatanaka
857275da0fSAkira Hatanaka template <class... Ts>
preVisit__anon25af64e30111::CopyStructVisitor867275da0fSAkira Hatanaka void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
87801cc327SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
887275da0fSAkira Hatanaka if (PCK)
897275da0fSAkira Hatanaka asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
907275da0fSAkira Hatanaka }
917275da0fSAkira Hatanaka
927275da0fSAkira Hatanaka template <class... Ts>
visitWithKind__anon25af64e30111::CopyStructVisitor9352a84e75SAkira Hatanaka void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
94801cc327SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset,
9552a84e75SAkira Hatanaka Ts &&... Args) {
9652a84e75SAkira Hatanaka if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
9752a84e75SAkira Hatanaka asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
98801cc327SAkira Hatanaka CurStructOffset, std::forward<Ts>(Args)...);
9952a84e75SAkira Hatanaka return;
10052a84e75SAkira Hatanaka }
10152a84e75SAkira Hatanaka
102801cc327SAkira Hatanaka Super::visitWithKind(PCK, FT, FD, CurStructOffset,
10352a84e75SAkira Hatanaka std::forward<Ts>(Args)...);
10452a84e75SAkira Hatanaka }
10552a84e75SAkira Hatanaka
10652a84e75SAkira Hatanaka template <class... Ts>
visitTrivial__anon25af64e30111::CopyStructVisitor1077275da0fSAkira Hatanaka void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
1087275da0fSAkira Hatanaka Ts... Args) {
1097275da0fSAkira Hatanaka assert(!FT.isVolatileQualified() && "volatile field not expected");
1107275da0fSAkira Hatanaka ASTContext &Ctx = asDerived().getContext();
1117c55265cSAkira Hatanaka uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
1127275da0fSAkira Hatanaka
1137275da0fSAkira Hatanaka // Ignore zero-sized fields.
1147275da0fSAkira Hatanaka if (FieldSize == 0)
1157275da0fSAkira Hatanaka return;
1167275da0fSAkira Hatanaka
1177275da0fSAkira Hatanaka uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
1187275da0fSAkira Hatanaka uint64_t FEndInBits = FStartInBits + FieldSize;
1197275da0fSAkira Hatanaka uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
1207275da0fSAkira Hatanaka
1217275da0fSAkira Hatanaka // Set Start if this is the first field of a sequence of trivial fields.
1227275da0fSAkira Hatanaka if (Start == End)
1237275da0fSAkira Hatanaka Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
1247275da0fSAkira Hatanaka End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
1257275da0fSAkira Hatanaka }
1267275da0fSAkira Hatanaka
1277275da0fSAkira Hatanaka CharUnits Start = CharUnits::Zero(), End = CharUnits::Zero();
1287275da0fSAkira Hatanaka };
1297275da0fSAkira Hatanaka
1307275da0fSAkira Hatanaka // This function creates the mangled name of a special function of a non-trivial
1317275da0fSAkira Hatanaka // C struct. Since there is no ODR in C, the function is mangled based on the
1327275da0fSAkira Hatanaka // struct contents and not the name. The mangled name has the following
1337275da0fSAkira Hatanaka // structure:
1347275da0fSAkira Hatanaka //
1357275da0fSAkira Hatanaka // <function-name> ::= <prefix> <alignment-info> "_" <struct-field-info>
1367275da0fSAkira Hatanaka // <prefix> ::= "__destructor_" | "__default_constructor_" |
1377275da0fSAkira Hatanaka // "__copy_constructor_" | "__move_constructor_" |
1387275da0fSAkira Hatanaka // "__copy_assignment_" | "__move_assignment_"
1397275da0fSAkira Hatanaka // <alignment-info> ::= <dst-alignment> ["_" <src-alignment>]
1407275da0fSAkira Hatanaka // <struct-field-info> ::= <field-info>+
1417275da0fSAkira Hatanaka // <field-info> ::= <struct-or-scalar-field-info> | <array-field-info>
142155e26f0SShoaib Meenai // <struct-or-scalar-field-info> ::= "_S" <struct-field-info> |
143155e26f0SShoaib Meenai // <strong-field-info> | <trivial-field-info>
1447275da0fSAkira Hatanaka // <array-field-info> ::= "_AB" <array-offset> "s" <element-size> "n"
1457275da0fSAkira Hatanaka // <num-elements> <innermost-element-info> "_AE"
1467275da0fSAkira Hatanaka // <innermost-element-info> ::= <struct-or-scalar-field-info>
1477275da0fSAkira Hatanaka // <strong-field-info> ::= "_s" ["b"] ["v"] <field-offset>
1487275da0fSAkira Hatanaka // <trivial-field-info> ::= "_t" ["v"] <field-offset> "_" <field-size>
1497275da0fSAkira Hatanaka
1507275da0fSAkira Hatanaka template <class Derived> struct GenFuncNameBase {
getVolatileOffsetStr__anon25af64e30111::GenFuncNameBase1517275da0fSAkira Hatanaka std::string getVolatileOffsetStr(bool IsVolatile, CharUnits Offset) {
1527275da0fSAkira Hatanaka std::string S;
1537275da0fSAkira Hatanaka if (IsVolatile)
1547275da0fSAkira Hatanaka S = "v";
1557275da0fSAkira Hatanaka S += llvm::to_string(Offset.getQuantity());
1567275da0fSAkira Hatanaka return S;
1577275da0fSAkira Hatanaka }
1587275da0fSAkira Hatanaka
visitARCStrong__anon25af64e30111::GenFuncNameBase1597275da0fSAkira Hatanaka void visitARCStrong(QualType FT, const FieldDecl *FD,
1607275da0fSAkira Hatanaka CharUnits CurStructOffset) {
1617275da0fSAkira Hatanaka appendStr("_s");
1627275da0fSAkira Hatanaka if (FT->isBlockPointerType())
1637275da0fSAkira Hatanaka appendStr("b");
1647275da0fSAkira Hatanaka CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1657275da0fSAkira Hatanaka appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
1667275da0fSAkira Hatanaka }
1677275da0fSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenFuncNameBase168d791e92bSAkira Hatanaka void visitARCWeak(QualType FT, const FieldDecl *FD,
169d791e92bSAkira Hatanaka CharUnits CurStructOffset) {
170d791e92bSAkira Hatanaka appendStr("_w");
171d791e92bSAkira Hatanaka CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
172d791e92bSAkira Hatanaka appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
173d791e92bSAkira Hatanaka }
174d791e92bSAkira Hatanaka
visitStruct__anon25af64e30111::GenFuncNameBase1757275da0fSAkira Hatanaka void visitStruct(QualType QT, const FieldDecl *FD,
1767275da0fSAkira Hatanaka CharUnits CurStructOffset) {
1777275da0fSAkira Hatanaka CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
178155e26f0SShoaib Meenai appendStr("_S");
1797275da0fSAkira Hatanaka asDerived().visitStructFields(QT, FieldOffset);
1807275da0fSAkira Hatanaka }
1817275da0fSAkira Hatanaka
1827275da0fSAkira Hatanaka template <class FieldKind>
visitArray__anon25af64e30111::GenFuncNameBase18352a84e75SAkira Hatanaka void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
18452a84e75SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset) {
1857275da0fSAkira Hatanaka // String for non-volatile trivial fields is emitted when
1867275da0fSAkira Hatanaka // flushTrivialFields is called.
1877275da0fSAkira Hatanaka if (!FK)
18852a84e75SAkira Hatanaka return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
1897275da0fSAkira Hatanaka
1909d343077SAkira Hatanaka asDerived().flushTrivialFields();
1917275da0fSAkira Hatanaka CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
1927275da0fSAkira Hatanaka ASTContext &Ctx = asDerived().getContext();
19352a84e75SAkira Hatanaka const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
19452a84e75SAkira Hatanaka unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
19552a84e75SAkira Hatanaka QualType EltTy = Ctx.getBaseElementType(CAT);
1967275da0fSAkira Hatanaka CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
1977275da0fSAkira Hatanaka appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
1987275da0fSAkira Hatanaka llvm::to_string(EltSize.getQuantity()) + "n" +
1997275da0fSAkira Hatanaka llvm::to_string(NumElts));
20052a84e75SAkira Hatanaka EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
20152a84e75SAkira Hatanaka asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
2027275da0fSAkira Hatanaka appendStr("_AE");
2037275da0fSAkira Hatanaka }
2047275da0fSAkira Hatanaka
appendStr__anon25af64e30111::GenFuncNameBase2057275da0fSAkira Hatanaka void appendStr(StringRef Str) { Name += Str; }
2067275da0fSAkira Hatanaka
getName__anon25af64e30111::GenFuncNameBase2077275da0fSAkira Hatanaka std::string getName(QualType QT, bool IsVolatile) {
2087275da0fSAkira Hatanaka QT = IsVolatile ? QT.withVolatile() : QT;
2097275da0fSAkira Hatanaka asDerived().visitStructFields(QT, CharUnits::Zero());
2107275da0fSAkira Hatanaka return Name;
2117275da0fSAkira Hatanaka }
2127275da0fSAkira Hatanaka
asDerived__anon25af64e30111::GenFuncNameBase2137275da0fSAkira Hatanaka Derived &asDerived() { return static_cast<Derived &>(*this); }
2147275da0fSAkira Hatanaka
2157275da0fSAkira Hatanaka std::string Name;
2167275da0fSAkira Hatanaka };
2177275da0fSAkira Hatanaka
2187275da0fSAkira Hatanaka template <class Derived>
2197275da0fSAkira Hatanaka struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
GenUnaryFuncName__anon25af64e30111::GenUnaryFuncName2207275da0fSAkira Hatanaka GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
2217275da0fSAkira Hatanaka : StructVisitor<Derived>(Ctx) {
2227275da0fSAkira Hatanaka this->appendStr(Prefix);
2237275da0fSAkira Hatanaka this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
2247275da0fSAkira Hatanaka }
2257275da0fSAkira Hatanaka };
2267275da0fSAkira Hatanaka
2277275da0fSAkira Hatanaka // Helper function to create a null constant.
getNullForVariable(Address Addr)2287275da0fSAkira Hatanaka static llvm::Constant *getNullForVariable(Address Addr) {
2297275da0fSAkira Hatanaka llvm::Type *Ty = Addr.getElementType();
2307275da0fSAkira Hatanaka return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
2317275da0fSAkira Hatanaka }
2327275da0fSAkira Hatanaka
2337275da0fSAkira Hatanaka template <bool IsMove>
2347275da0fSAkira Hatanaka struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
2357275da0fSAkira Hatanaka GenFuncNameBase<GenBinaryFuncName<IsMove>> {
2367275da0fSAkira Hatanaka
GenBinaryFuncName__anon25af64e30111::GenBinaryFuncName2377275da0fSAkira Hatanaka GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
2387275da0fSAkira Hatanaka CharUnits SrcAlignment, ASTContext &Ctx)
2397275da0fSAkira Hatanaka : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
2407275da0fSAkira Hatanaka this->appendStr(Prefix);
2417275da0fSAkira Hatanaka this->appendStr(llvm::to_string(DstAlignment.getQuantity()));
2427275da0fSAkira Hatanaka this->appendStr("_" + llvm::to_string(SrcAlignment.getQuantity()));
2437275da0fSAkira Hatanaka }
2447275da0fSAkira Hatanaka
flushTrivialFields__anon25af64e30111::GenBinaryFuncName2457275da0fSAkira Hatanaka void flushTrivialFields() {
2467275da0fSAkira Hatanaka if (this->Start == this->End)
2477275da0fSAkira Hatanaka return;
2487275da0fSAkira Hatanaka
2497275da0fSAkira Hatanaka this->appendStr("_t" + llvm::to_string(this->Start.getQuantity()) + "w" +
2507275da0fSAkira Hatanaka llvm::to_string((this->End - this->Start).getQuantity()));
2517275da0fSAkira Hatanaka
2527275da0fSAkira Hatanaka this->Start = this->End = CharUnits::Zero();
2537275da0fSAkira Hatanaka }
2547275da0fSAkira Hatanaka
visitVolatileTrivial__anon25af64e30111::GenBinaryFuncName2557275da0fSAkira Hatanaka void visitVolatileTrivial(QualType FT, const FieldDecl *FD,
256801cc327SAkira Hatanaka CharUnits CurStructOffset) {
257d33c7de8SErik Pilkington // Zero-length bit-fields don't need to be copied/assigned.
258d33c7de8SErik Pilkington if (FD && FD->isZeroLengthBitField(this->Ctx))
259d33c7de8SErik Pilkington return;
260d33c7de8SErik Pilkington
2617275da0fSAkira Hatanaka // Because volatile fields can be bit-fields and are individually copied,
2627275da0fSAkira Hatanaka // their offset and width are in bits.
2637275da0fSAkira Hatanaka uint64_t OffsetInBits =
264801cc327SAkira Hatanaka this->Ctx.toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
2657275da0fSAkira Hatanaka this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
2667c55265cSAkira Hatanaka llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
2677275da0fSAkira Hatanaka }
2687275da0fSAkira Hatanaka };
2697275da0fSAkira Hatanaka
2707275da0fSAkira Hatanaka struct GenDefaultInitializeFuncName
2717275da0fSAkira Hatanaka : GenUnaryFuncName<GenDefaultInitializeFuncName>,
2727275da0fSAkira Hatanaka DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
27352a84e75SAkira Hatanaka using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
GenDefaultInitializeFuncName__anon25af64e30111::GenDefaultInitializeFuncName2747275da0fSAkira Hatanaka GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
2757275da0fSAkira Hatanaka : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
2767275da0fSAkira Hatanaka DstAlignment, Ctx) {}
visitWithKind__anon25af64e30111::GenDefaultInitializeFuncName27752a84e75SAkira Hatanaka void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
27852a84e75SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset) {
27952a84e75SAkira Hatanaka if (const auto *AT = getContext().getAsArrayType(FT)) {
28052a84e75SAkira Hatanaka visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
28152a84e75SAkira Hatanaka return;
28252a84e75SAkira Hatanaka }
28352a84e75SAkira Hatanaka
28452a84e75SAkira Hatanaka Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
28552a84e75SAkira Hatanaka }
2867275da0fSAkira Hatanaka };
2877275da0fSAkira Hatanaka
2887275da0fSAkira Hatanaka struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
2897275da0fSAkira Hatanaka DestructedTypeVisitor<GenDestructorFuncName> {
29052a84e75SAkira Hatanaka using Super = DestructedTypeVisitor<GenDestructorFuncName>;
GenDestructorFuncName__anon25af64e30111::GenDestructorFuncName2919978da36SAkira Hatanaka GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
2929978da36SAkira Hatanaka ASTContext &Ctx)
293801cc327SAkira Hatanaka : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
visitWithKind__anon25af64e30111::GenDestructorFuncName29452a84e75SAkira Hatanaka void visitWithKind(QualType::DestructionKind DK, QualType FT,
29552a84e75SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset) {
29652a84e75SAkira Hatanaka if (const auto *AT = getContext().getAsArrayType(FT)) {
29752a84e75SAkira Hatanaka visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
29852a84e75SAkira Hatanaka return;
29952a84e75SAkira Hatanaka }
30052a84e75SAkira Hatanaka
30152a84e75SAkira Hatanaka Super::visitWithKind(DK, FT, FD, CurStructOffset);
30252a84e75SAkira Hatanaka }
3037275da0fSAkira Hatanaka };
3047275da0fSAkira Hatanaka
3057275da0fSAkira Hatanaka // Helper function that creates CGFunctionInfo for an N-ary special function.
3067275da0fSAkira Hatanaka template <size_t N>
getFunctionInfo(CodeGenModule & CGM,FunctionArgList & Args)3077275da0fSAkira Hatanaka static const CGFunctionInfo &getFunctionInfo(CodeGenModule &CGM,
3087275da0fSAkira Hatanaka FunctionArgList &Args) {
3097275da0fSAkira Hatanaka ASTContext &Ctx = CGM.getContext();
3107275da0fSAkira Hatanaka llvm::SmallVector<ImplicitParamDecl *, N> Params;
3117275da0fSAkira Hatanaka QualType ParamTy = Ctx.getPointerType(Ctx.VoidPtrTy);
3127275da0fSAkira Hatanaka
3137275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I)
3147275da0fSAkira Hatanaka Params.push_back(ImplicitParamDecl::Create(
3157275da0fSAkira Hatanaka Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(ValNameStr[I]), ParamTy,
3167275da0fSAkira Hatanaka ImplicitParamDecl::Other));
3177275da0fSAkira Hatanaka
318*5d2ce766SBenjamin Kramer llvm::append_range(Args, Params);
3197275da0fSAkira Hatanaka
3207275da0fSAkira Hatanaka return CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
3217275da0fSAkira Hatanaka }
3227275da0fSAkira Hatanaka
3232cfb0273SAkira Hatanaka template <size_t N, size_t... Ints>
getParamAddrs(std::index_sequence<Ints...> IntSeq,std::array<CharUnits,N> Alignments,FunctionArgList Args,CodeGenFunction * CGF)3242cfb0273SAkira Hatanaka static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
3252cfb0273SAkira Hatanaka std::array<CharUnits, N> Alignments,
3262cfb0273SAkira Hatanaka FunctionArgList Args,
3272cfb0273SAkira Hatanaka CodeGenFunction *CGF) {
328aa4ea0eeSAkira Hatanaka return std::array<Address, N>{
329aa4ea0eeSAkira Hatanaka {Address(CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[Ints])),
330aa4ea0eeSAkira Hatanaka CGF->VoidPtrTy, Alignments[Ints])...}};
3312cfb0273SAkira Hatanaka }
3322cfb0273SAkira Hatanaka
3337275da0fSAkira Hatanaka // Template classes that are used as bases for classes that emit special
3347275da0fSAkira Hatanaka // functions.
3357275da0fSAkira Hatanaka template <class Derived> struct GenFuncBase {
3367275da0fSAkira Hatanaka template <size_t N>
visitStruct__anon25af64e30111::GenFuncBase337801cc327SAkira Hatanaka void visitStruct(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
3387275da0fSAkira Hatanaka std::array<Address, N> Addrs) {
3397275da0fSAkira Hatanaka this->asDerived().callSpecialFunction(
340801cc327SAkira Hatanaka FT, CurStructOffset + asDerived().getFieldOffset(FD), Addrs);
3417275da0fSAkira Hatanaka }
3427275da0fSAkira Hatanaka
3437275da0fSAkira Hatanaka template <class FieldKind, size_t N>
visitArray__anon25af64e30111::GenFuncBase34452a84e75SAkira Hatanaka void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
345801cc327SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset,
34652a84e75SAkira Hatanaka std::array<Address, N> Addrs) {
3477275da0fSAkira Hatanaka // Non-volatile trivial fields are copied when flushTrivialFields is called.
3487275da0fSAkira Hatanaka if (!FK)
349801cc327SAkira Hatanaka return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
35052a84e75SAkira Hatanaka Addrs);
3517275da0fSAkira Hatanaka
3529d343077SAkira Hatanaka asDerived().flushTrivialFields(Addrs);
3537275da0fSAkira Hatanaka CodeGenFunction &CGF = *this->CGF;
3547275da0fSAkira Hatanaka ASTContext &Ctx = CGF.getContext();
3557275da0fSAkira Hatanaka
3567275da0fSAkira Hatanaka // Compute the end address.
3577275da0fSAkira Hatanaka QualType BaseEltQT;
3587275da0fSAkira Hatanaka std::array<Address, N> StartAddrs = Addrs;
3597275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I)
360801cc327SAkira Hatanaka StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
3617275da0fSAkira Hatanaka Address DstAddr = StartAddrs[DstIdx];
36252a84e75SAkira Hatanaka llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
3637275da0fSAkira Hatanaka unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
3647275da0fSAkira Hatanaka llvm::Value *BaseEltSizeVal =
3657275da0fSAkira Hatanaka llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
3667275da0fSAkira Hatanaka llvm::Value *SizeInBytes =
3677275da0fSAkira Hatanaka CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
368481de0edSNikita Popov Address BC = CGF.Builder.CreateElementBitCast(DstAddr, CGF.CGM.Int8Ty);
3697275da0fSAkira Hatanaka llvm::Value *DstArrayEnd =
37042eb658fSNikita Popov CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
371481de0edSNikita Popov DstArrayEnd = CGF.Builder.CreateBitCast(
372481de0edSNikita Popov DstArrayEnd, CGF.CGM.Int8PtrPtrTy, "dstarray.end");
3737275da0fSAkira Hatanaka llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
3747275da0fSAkira Hatanaka
3757275da0fSAkira Hatanaka // Create the header block and insert the phi instructions.
3767275da0fSAkira Hatanaka llvm::BasicBlock *HeaderBB = CGF.createBasicBlock("loop.header");
3777275da0fSAkira Hatanaka CGF.EmitBlock(HeaderBB);
3787275da0fSAkira Hatanaka llvm::PHINode *PHIs[N];
3797275da0fSAkira Hatanaka
3807275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I) {
3817275da0fSAkira Hatanaka PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur");
3827275da0fSAkira Hatanaka PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
3837275da0fSAkira Hatanaka }
3847275da0fSAkira Hatanaka
3857275da0fSAkira Hatanaka // Create the exit and loop body blocks.
3867275da0fSAkira Hatanaka llvm::BasicBlock *ExitBB = CGF.createBasicBlock("loop.exit");
3877275da0fSAkira Hatanaka llvm::BasicBlock *LoopBB = CGF.createBasicBlock("loop.body");
3887275da0fSAkira Hatanaka
3897275da0fSAkira Hatanaka // Emit the comparison and conditional branch instruction that jumps to
3907275da0fSAkira Hatanaka // either the exit or the loop body.
3917275da0fSAkira Hatanaka llvm::Value *Done =
3927275da0fSAkira Hatanaka CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd, "done");
3937275da0fSAkira Hatanaka CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
3947275da0fSAkira Hatanaka
3957275da0fSAkira Hatanaka // Visit the element of the array in the loop body.
3967275da0fSAkira Hatanaka CGF.EmitBlock(LoopBB);
39752a84e75SAkira Hatanaka QualType EltQT = AT->getElementType();
3987275da0fSAkira Hatanaka CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
3997275da0fSAkira Hatanaka std::array<Address, N> NewAddrs = Addrs;
4007275da0fSAkira Hatanaka
4017275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I)
40250650766SNikita Popov NewAddrs[I] =
40350650766SNikita Popov Address(PHIs[I], CGF.Int8PtrTy,
40450650766SNikita Popov StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
4057275da0fSAkira Hatanaka
40652a84e75SAkira Hatanaka EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
40752a84e75SAkira Hatanaka this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
40852a84e75SAkira Hatanaka NewAddrs);
4097275da0fSAkira Hatanaka
4107275da0fSAkira Hatanaka LoopBB = CGF.Builder.GetInsertBlock();
4117275da0fSAkira Hatanaka
4127275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I) {
4137275da0fSAkira Hatanaka // Instrs to update the destination and source addresses.
4147275da0fSAkira Hatanaka // Update phi instructions.
4157275da0fSAkira Hatanaka NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
4167275da0fSAkira Hatanaka PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
4177275da0fSAkira Hatanaka }
4187275da0fSAkira Hatanaka
4197275da0fSAkira Hatanaka // Insert an unconditional branch to the header block.
4207275da0fSAkira Hatanaka CGF.Builder.CreateBr(HeaderBB);
4217275da0fSAkira Hatanaka CGF.EmitBlock(ExitBB);
4227275da0fSAkira Hatanaka }
4237275da0fSAkira Hatanaka
4247275da0fSAkira Hatanaka /// Return an address with the specified offset from the passed address.
getAddrWithOffset__anon25af64e30111::GenFuncBase4257275da0fSAkira Hatanaka Address getAddrWithOffset(Address Addr, CharUnits Offset) {
4267275da0fSAkira Hatanaka assert(Addr.isValid() && "invalid address");
4277275da0fSAkira Hatanaka if (Offset.getQuantity() == 0)
4287275da0fSAkira Hatanaka return Addr;
429481de0edSNikita Popov Addr = CGF->Builder.CreateElementBitCast(Addr, CGF->CGM.Int8Ty);
430751fe286SJames Y Knight Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.getQuantity());
431481de0edSNikita Popov return CGF->Builder.CreateElementBitCast(Addr, CGF->CGM.Int8PtrTy);
4327275da0fSAkira Hatanaka }
4337275da0fSAkira Hatanaka
getAddrWithOffset__anon25af64e30111::GenFuncBase4347275da0fSAkira Hatanaka Address getAddrWithOffset(Address Addr, CharUnits StructFieldOffset,
4357275da0fSAkira Hatanaka const FieldDecl *FD) {
4367275da0fSAkira Hatanaka return getAddrWithOffset(Addr, StructFieldOffset +
4377275da0fSAkira Hatanaka asDerived().getFieldOffset(FD));
4387275da0fSAkira Hatanaka }
4397275da0fSAkira Hatanaka
4407275da0fSAkira Hatanaka template <size_t N>
getFunction__anon25af64e30111::GenFuncBase4412cfb0273SAkira Hatanaka llvm::Function *getFunction(StringRef FuncName, QualType QT,
4422cfb0273SAkira Hatanaka std::array<CharUnits, N> Alignments,
4432cfb0273SAkira Hatanaka CodeGenModule &CGM) {
4447275da0fSAkira Hatanaka // If the special function already exists in the module, return it.
4457275da0fSAkira Hatanaka if (llvm::Function *F = CGM.getModule().getFunction(FuncName)) {
4467275da0fSAkira Hatanaka bool WrongType = false;
4477275da0fSAkira Hatanaka if (!F->getReturnType()->isVoidTy())
4487275da0fSAkira Hatanaka WrongType = true;
4497275da0fSAkira Hatanaka else {
4507275da0fSAkira Hatanaka for (const llvm::Argument &Arg : F->args())
4517275da0fSAkira Hatanaka if (Arg.getType() != CGM.Int8PtrPtrTy)
4527275da0fSAkira Hatanaka WrongType = true;
4537275da0fSAkira Hatanaka }
4547275da0fSAkira Hatanaka
4557275da0fSAkira Hatanaka if (WrongType) {
456adcd0268SBenjamin Kramer std::string FuncName = std::string(F->getName());
4577275da0fSAkira Hatanaka SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
4587275da0fSAkira Hatanaka CGM.Error(Loc, "special function " + FuncName +
4597275da0fSAkira Hatanaka " for non-trivial C struct has incorrect type");
4607275da0fSAkira Hatanaka return nullptr;
4617275da0fSAkira Hatanaka }
4627275da0fSAkira Hatanaka return F;
4637275da0fSAkira Hatanaka }
4647275da0fSAkira Hatanaka
4657275da0fSAkira Hatanaka ASTContext &Ctx = CGM.getContext();
4667275da0fSAkira Hatanaka FunctionArgList Args;
4677275da0fSAkira Hatanaka const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
4687275da0fSAkira Hatanaka llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
4697275da0fSAkira Hatanaka llvm::Function *F =
4707275da0fSAkira Hatanaka llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
4717275da0fSAkira Hatanaka FuncName, &CGM.getModule());
4727275da0fSAkira Hatanaka F->setVisibility(llvm::GlobalValue::HiddenVisibility);
473a624cec5SRoman Lebedev CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
4747275da0fSAkira Hatanaka CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
4757275da0fSAkira Hatanaka CodeGenFunction NewCGF(CGM);
4767275da0fSAkira Hatanaka setCGF(&NewCGF);
4778d21d547SAkira Hatanaka CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
4788d21d547SAkira Hatanaka auto AL = ApplyDebugLocation::CreateArtificial(*CGF);
4792cfb0273SAkira Hatanaka std::array<Address, N> Addrs =
4802cfb0273SAkira Hatanaka getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
4817275da0fSAkira Hatanaka asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
4827275da0fSAkira Hatanaka CGF->FinishFunction();
4837275da0fSAkira Hatanaka return F;
4847275da0fSAkira Hatanaka }
4857275da0fSAkira Hatanaka
4867275da0fSAkira Hatanaka template <size_t N>
callFunc__anon25af64e30111::GenFuncBase4877275da0fSAkira Hatanaka void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
4887275da0fSAkira Hatanaka CodeGenFunction &CallerCGF) {
4897275da0fSAkira Hatanaka std::array<CharUnits, N> Alignments;
4907275da0fSAkira Hatanaka llvm::Value *Ptrs[N];
4917275da0fSAkira Hatanaka
4927275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I) {
4937275da0fSAkira Hatanaka Alignments[I] = Addrs[I].getAlignment();
494481de0edSNikita Popov Ptrs[I] = CallerCGF.Builder.CreateElementBitCast(
495481de0edSNikita Popov Addrs[I], CallerCGF.CGM.Int8PtrTy).getPointer();
4967275da0fSAkira Hatanaka }
4977275da0fSAkira Hatanaka
4987275da0fSAkira Hatanaka if (llvm::Function *F =
4992cfb0273SAkira Hatanaka getFunction(FuncName, QT, Alignments, CallerCGF.CGM))
5007275da0fSAkira Hatanaka CallerCGF.EmitNounwindRuntimeCall(F, Ptrs);
5017275da0fSAkira Hatanaka }
5027275da0fSAkira Hatanaka
asDerived__anon25af64e30111::GenFuncBase5037275da0fSAkira Hatanaka Derived &asDerived() { return static_cast<Derived &>(*this); }
5047275da0fSAkira Hatanaka
setCGF__anon25af64e30111::GenFuncBase5057275da0fSAkira Hatanaka void setCGF(CodeGenFunction *F) { CGF = F; }
5067275da0fSAkira Hatanaka
5077275da0fSAkira Hatanaka CodeGenFunction *CGF = nullptr;
5087275da0fSAkira Hatanaka };
5097275da0fSAkira Hatanaka
5107275da0fSAkira Hatanaka template <class Derived, bool IsMove>
5117275da0fSAkira Hatanaka struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
5127275da0fSAkira Hatanaka GenFuncBase<Derived> {
GenBinaryFunc__anon25af64e30111::GenBinaryFunc5137275da0fSAkira Hatanaka GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
5147275da0fSAkira Hatanaka
flushTrivialFields__anon25af64e30111::GenBinaryFunc5157275da0fSAkira Hatanaka void flushTrivialFields(std::array<Address, 2> Addrs) {
5167275da0fSAkira Hatanaka CharUnits Size = this->End - this->Start;
5177275da0fSAkira Hatanaka
5187275da0fSAkira Hatanaka if (Size.getQuantity() == 0)
5197275da0fSAkira Hatanaka return;
5207275da0fSAkira Hatanaka
5217275da0fSAkira Hatanaka Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
5227275da0fSAkira Hatanaka Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
5237275da0fSAkira Hatanaka
5247275da0fSAkira Hatanaka // Emit memcpy.
5257275da0fSAkira Hatanaka if (Size.getQuantity() >= 16 || !llvm::isPowerOf2_32(Size.getQuantity())) {
5267275da0fSAkira Hatanaka llvm::Value *SizeVal =
5277275da0fSAkira Hatanaka llvm::ConstantInt::get(this->CGF->SizeTy, Size.getQuantity());
5287275da0fSAkira Hatanaka DstAddr =
5297275da0fSAkira Hatanaka this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
5307275da0fSAkira Hatanaka SrcAddr =
5317275da0fSAkira Hatanaka this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
5327275da0fSAkira Hatanaka this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal, false);
5337275da0fSAkira Hatanaka } else {
5347275da0fSAkira Hatanaka llvm::Type *Ty = llvm::Type::getIntNTy(
5357275da0fSAkira Hatanaka this->CGF->getLLVMContext(),
5367275da0fSAkira Hatanaka Size.getQuantity() * this->CGF->getContext().getCharWidth());
5377275da0fSAkira Hatanaka DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
5387275da0fSAkira Hatanaka SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
5397275da0fSAkira Hatanaka llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr, false);
5407275da0fSAkira Hatanaka this->CGF->Builder.CreateStore(SrcVal, DstAddr, false);
5417275da0fSAkira Hatanaka }
5427275da0fSAkira Hatanaka
5437275da0fSAkira Hatanaka this->Start = this->End = CharUnits::Zero();
5447275da0fSAkira Hatanaka }
5457275da0fSAkira Hatanaka
5467275da0fSAkira Hatanaka template <class... Ts>
visitVolatileTrivial__anon25af64e30111::GenBinaryFunc5477275da0fSAkira Hatanaka void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
5487275da0fSAkira Hatanaka std::array<Address, 2> Addrs) {
5497c55265cSAkira Hatanaka LValue DstLV, SrcLV;
5507c55265cSAkira Hatanaka if (FD) {
551d33c7de8SErik Pilkington // No need to copy zero-length bit-fields.
552d33c7de8SErik Pilkington if (FD->isZeroLengthBitField(this->CGF->getContext()))
553d33c7de8SErik Pilkington return;
554d33c7de8SErik Pilkington
5557275da0fSAkira Hatanaka QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
556481de0edSNikita Popov llvm::Type *Ty = this->CGF->ConvertType(RT);
5577275da0fSAkira Hatanaka Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
5587275da0fSAkira Hatanaka LValue DstBase = this->CGF->MakeAddrLValue(
559481de0edSNikita Popov this->CGF->Builder.CreateElementBitCast(DstAddr, Ty), FT);
5607c55265cSAkira Hatanaka DstLV = this->CGF->EmitLValueForField(DstBase, FD);
5617275da0fSAkira Hatanaka Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
5627275da0fSAkira Hatanaka LValue SrcBase = this->CGF->MakeAddrLValue(
563481de0edSNikita Popov this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty), FT);
5647c55265cSAkira Hatanaka SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
5657c55265cSAkira Hatanaka } else {
566481de0edSNikita Popov llvm::Type *Ty = this->CGF->ConvertTypeForMem(FT);
567481de0edSNikita Popov Address DstAddr =
568481de0edSNikita Popov this->CGF->Builder.CreateElementBitCast(Addrs[DstIdx], Ty);
569481de0edSNikita Popov Address SrcAddr =
570481de0edSNikita Popov this->CGF->Builder.CreateElementBitCast(Addrs[SrcIdx], Ty);
5717c55265cSAkira Hatanaka DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
5727c55265cSAkira Hatanaka SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
5737c55265cSAkira Hatanaka }
5747275da0fSAkira Hatanaka RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
5757275da0fSAkira Hatanaka this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
5767275da0fSAkira Hatanaka }
5777275da0fSAkira Hatanaka };
5787275da0fSAkira Hatanaka
5797275da0fSAkira Hatanaka // These classes that emit the special functions for a non-trivial struct.
5807275da0fSAkira Hatanaka struct GenDestructor : StructVisitor<GenDestructor>,
5817275da0fSAkira Hatanaka GenFuncBase<GenDestructor>,
5827275da0fSAkira Hatanaka DestructedTypeVisitor<GenDestructor> {
58352a84e75SAkira Hatanaka using Super = DestructedTypeVisitor<GenDestructor>;
GenDestructor__anon25af64e30111::GenDestructor5847275da0fSAkira Hatanaka GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
58552a84e75SAkira Hatanaka
visitWithKind__anon25af64e30111::GenDestructor58652a84e75SAkira Hatanaka void visitWithKind(QualType::DestructionKind DK, QualType FT,
58752a84e75SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset,
58852a84e75SAkira Hatanaka std::array<Address, 1> Addrs) {
58952a84e75SAkira Hatanaka if (const auto *AT = getContext().getAsArrayType(FT)) {
59052a84e75SAkira Hatanaka visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
59152a84e75SAkira Hatanaka return;
59252a84e75SAkira Hatanaka }
59352a84e75SAkira Hatanaka
59452a84e75SAkira Hatanaka Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
59552a84e75SAkira Hatanaka }
59652a84e75SAkira Hatanaka
visitARCStrong__anon25af64e30111::GenDestructor5977275da0fSAkira Hatanaka void visitARCStrong(QualType QT, const FieldDecl *FD,
598801cc327SAkira Hatanaka CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
5997275da0fSAkira Hatanaka CGF->destroyARCStrongImprecise(
600801cc327SAkira Hatanaka *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6017275da0fSAkira Hatanaka }
6027275da0fSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenDestructor603801cc327SAkira Hatanaka void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
604d791e92bSAkira Hatanaka std::array<Address, 1> Addrs) {
605d791e92bSAkira Hatanaka CGF->destroyARCWeak(
606801cc327SAkira Hatanaka *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
607d791e92bSAkira Hatanaka }
608d791e92bSAkira Hatanaka
callSpecialFunction__anon25af64e30111::GenDestructor6097275da0fSAkira Hatanaka void callSpecialFunction(QualType FT, CharUnits Offset,
6107275da0fSAkira Hatanaka std::array<Address, 1> Addrs) {
6117275da0fSAkira Hatanaka CGF->callCStructDestructor(
6127275da0fSAkira Hatanaka CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6137275da0fSAkira Hatanaka }
6147275da0fSAkira Hatanaka };
6157275da0fSAkira Hatanaka
6167275da0fSAkira Hatanaka struct GenDefaultInitialize
6177275da0fSAkira Hatanaka : StructVisitor<GenDefaultInitialize>,
6187275da0fSAkira Hatanaka GenFuncBase<GenDefaultInitialize>,
6197275da0fSAkira Hatanaka DefaultInitializedTypeVisitor<GenDefaultInitialize> {
62052a84e75SAkira Hatanaka using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
6217275da0fSAkira Hatanaka typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
62252a84e75SAkira Hatanaka
GenDefaultInitialize__anon25af64e30111::GenDefaultInitialize6237275da0fSAkira Hatanaka GenDefaultInitialize(ASTContext &Ctx)
6247275da0fSAkira Hatanaka : StructVisitor<GenDefaultInitialize>(Ctx) {}
6257275da0fSAkira Hatanaka
visitWithKind__anon25af64e30111::GenDefaultInitialize62652a84e75SAkira Hatanaka void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
62752a84e75SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset,
62852a84e75SAkira Hatanaka std::array<Address, 1> Addrs) {
62952a84e75SAkira Hatanaka if (const auto *AT = getContext().getAsArrayType(FT)) {
63052a84e75SAkira Hatanaka visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
63152a84e75SAkira Hatanaka Addrs);
63252a84e75SAkira Hatanaka return;
63352a84e75SAkira Hatanaka }
63452a84e75SAkira Hatanaka
63552a84e75SAkira Hatanaka Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
63652a84e75SAkira Hatanaka }
63752a84e75SAkira Hatanaka
visitARCStrong__anon25af64e30111::GenDefaultInitialize6387275da0fSAkira Hatanaka void visitARCStrong(QualType QT, const FieldDecl *FD,
639801cc327SAkira Hatanaka CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
6407275da0fSAkira Hatanaka CGF->EmitNullInitialization(
641801cc327SAkira Hatanaka getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
6427275da0fSAkira Hatanaka }
6437275da0fSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenDefaultInitialize644801cc327SAkira Hatanaka void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
645d791e92bSAkira Hatanaka std::array<Address, 1> Addrs) {
646d791e92bSAkira Hatanaka CGF->EmitNullInitialization(
647801cc327SAkira Hatanaka getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
648d791e92bSAkira Hatanaka }
649d791e92bSAkira Hatanaka
6507275da0fSAkira Hatanaka template <class FieldKind, size_t... Is>
visitArray__anon25af64e30111::GenDefaultInitialize65152a84e75SAkira Hatanaka void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
652801cc327SAkira Hatanaka const FieldDecl *FD, CharUnits CurStructOffset,
65352a84e75SAkira Hatanaka std::array<Address, 1> Addrs) {
6547275da0fSAkira Hatanaka if (!FK)
655801cc327SAkira Hatanaka return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
6567275da0fSAkira Hatanaka
6577275da0fSAkira Hatanaka ASTContext &Ctx = getContext();
65852a84e75SAkira Hatanaka CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
65952a84e75SAkira Hatanaka QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
6607275da0fSAkira Hatanaka
6617275da0fSAkira Hatanaka if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
662801cc327SAkira Hatanaka GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
6637275da0fSAkira Hatanaka return;
6647275da0fSAkira Hatanaka }
6657275da0fSAkira Hatanaka
6667275da0fSAkira Hatanaka llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
667801cc327SAkira Hatanaka Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
6687275da0fSAkira Hatanaka Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
6697275da0fSAkira Hatanaka CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
67052a84e75SAkira Hatanaka IsVolatile);
6717275da0fSAkira Hatanaka }
6727275da0fSAkira Hatanaka
callSpecialFunction__anon25af64e30111::GenDefaultInitialize6737275da0fSAkira Hatanaka void callSpecialFunction(QualType FT, CharUnits Offset,
6747275da0fSAkira Hatanaka std::array<Address, 1> Addrs) {
6757275da0fSAkira Hatanaka CGF->callCStructDefaultConstructor(
6767275da0fSAkira Hatanaka CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
6777275da0fSAkira Hatanaka }
6787275da0fSAkira Hatanaka };
6797275da0fSAkira Hatanaka
6807275da0fSAkira Hatanaka struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
GenCopyConstructor__anon25af64e30111::GenCopyConstructor6817275da0fSAkira Hatanaka GenCopyConstructor(ASTContext &Ctx)
6827275da0fSAkira Hatanaka : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
6837275da0fSAkira Hatanaka
visitARCStrong__anon25af64e30111::GenCopyConstructor6847275da0fSAkira Hatanaka void visitARCStrong(QualType QT, const FieldDecl *FD,
685801cc327SAkira Hatanaka CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
686801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
687801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
6887275da0fSAkira Hatanaka llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
6897275da0fSAkira Hatanaka Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
6907275da0fSAkira Hatanaka llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
6917275da0fSAkira Hatanaka CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
6927275da0fSAkira Hatanaka }
693d791e92bSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenCopyConstructor694801cc327SAkira Hatanaka void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
695d791e92bSAkira Hatanaka std::array<Address, 2> Addrs) {
696801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
697801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
698d791e92bSAkira Hatanaka CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
699d791e92bSAkira Hatanaka }
700d791e92bSAkira Hatanaka
callSpecialFunction__anon25af64e30111::GenCopyConstructor7017275da0fSAkira Hatanaka void callSpecialFunction(QualType FT, CharUnits Offset,
7027275da0fSAkira Hatanaka std::array<Address, 2> Addrs) {
7038b8d3623SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7048b8d3623SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7057275da0fSAkira Hatanaka CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7067275da0fSAkira Hatanaka CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7077275da0fSAkira Hatanaka }
7087275da0fSAkira Hatanaka };
7097275da0fSAkira Hatanaka
7107275da0fSAkira Hatanaka struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
GenMoveConstructor__anon25af64e30111::GenMoveConstructor7117275da0fSAkira Hatanaka GenMoveConstructor(ASTContext &Ctx)
7127275da0fSAkira Hatanaka : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
7137275da0fSAkira Hatanaka
visitARCStrong__anon25af64e30111::GenMoveConstructor7147275da0fSAkira Hatanaka void visitARCStrong(QualType QT, const FieldDecl *FD,
715801cc327SAkira Hatanaka CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
716801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
717801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7187275da0fSAkira Hatanaka LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7197275da0fSAkira Hatanaka llvm::Value *SrcVal =
7207275da0fSAkira Hatanaka CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
721f139ae3dSAkira Hatanaka CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7227275da0fSAkira Hatanaka CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
7237275da0fSAkira Hatanaka /* isInitialization */ true);
7247275da0fSAkira Hatanaka }
725d791e92bSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenMoveConstructor726801cc327SAkira Hatanaka void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
727d791e92bSAkira Hatanaka std::array<Address, 2> Addrs) {
728801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
729801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
730d791e92bSAkira Hatanaka CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
731d791e92bSAkira Hatanaka }
732d791e92bSAkira Hatanaka
callSpecialFunction__anon25af64e30111::GenMoveConstructor7337275da0fSAkira Hatanaka void callSpecialFunction(QualType FT, CharUnits Offset,
7347275da0fSAkira Hatanaka std::array<Address, 2> Addrs) {
7358b8d3623SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7368b8d3623SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7377275da0fSAkira Hatanaka CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7387275da0fSAkira Hatanaka CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7397275da0fSAkira Hatanaka }
7407275da0fSAkira Hatanaka };
7417275da0fSAkira Hatanaka
7427275da0fSAkira Hatanaka struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
GenCopyAssignment__anon25af64e30111::GenCopyAssignment7437275da0fSAkira Hatanaka GenCopyAssignment(ASTContext &Ctx)
7447275da0fSAkira Hatanaka : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
7457275da0fSAkira Hatanaka
visitARCStrong__anon25af64e30111::GenCopyAssignment7467275da0fSAkira Hatanaka void visitARCStrong(QualType QT, const FieldDecl *FD,
747801cc327SAkira Hatanaka CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
748801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
749801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7507275da0fSAkira Hatanaka llvm::Value *SrcVal = CGF->EmitLoadOfScalar(
7517275da0fSAkira Hatanaka Addrs[SrcIdx], QT.isVolatileQualified(), QT, SourceLocation());
7527275da0fSAkira Hatanaka CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
7537275da0fSAkira Hatanaka false);
7547275da0fSAkira Hatanaka }
755d791e92bSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenCopyAssignment756801cc327SAkira Hatanaka void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
757d791e92bSAkira Hatanaka std::array<Address, 2> Addrs) {
758801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
759801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
760d791e92bSAkira Hatanaka CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
761d791e92bSAkira Hatanaka }
762d791e92bSAkira Hatanaka
callSpecialFunction__anon25af64e30111::GenCopyAssignment7637275da0fSAkira Hatanaka void callSpecialFunction(QualType FT, CharUnits Offset,
7647275da0fSAkira Hatanaka std::array<Address, 2> Addrs) {
7658b8d3623SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
7668b8d3623SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
7677275da0fSAkira Hatanaka CGF->callCStructCopyAssignmentOperator(
7687275da0fSAkira Hatanaka CGF->MakeAddrLValue(Addrs[DstIdx], FT),
7697275da0fSAkira Hatanaka CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
7707275da0fSAkira Hatanaka }
7717275da0fSAkira Hatanaka };
7727275da0fSAkira Hatanaka
7737275da0fSAkira Hatanaka struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
GenMoveAssignment__anon25af64e30111::GenMoveAssignment7747275da0fSAkira Hatanaka GenMoveAssignment(ASTContext &Ctx)
7757275da0fSAkira Hatanaka : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
7767275da0fSAkira Hatanaka
visitARCStrong__anon25af64e30111::GenMoveAssignment7777275da0fSAkira Hatanaka void visitARCStrong(QualType QT, const FieldDecl *FD,
778801cc327SAkira Hatanaka CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
779801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
780801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
7817275da0fSAkira Hatanaka LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
7827275da0fSAkira Hatanaka llvm::Value *SrcVal =
7837275da0fSAkira Hatanaka CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal();
784f139ae3dSAkira Hatanaka CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV);
7857275da0fSAkira Hatanaka LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
7867275da0fSAkira Hatanaka llvm::Value *DstVal =
7877275da0fSAkira Hatanaka CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
7887275da0fSAkira Hatanaka CGF->EmitStoreOfScalar(SrcVal, DstLV);
7897275da0fSAkira Hatanaka CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
7907275da0fSAkira Hatanaka }
7917275da0fSAkira Hatanaka
visitARCWeak__anon25af64e30111::GenMoveAssignment792801cc327SAkira Hatanaka void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStructOffset,
793d791e92bSAkira Hatanaka std::array<Address, 2> Addrs) {
794801cc327SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
795801cc327SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
796d791e92bSAkira Hatanaka CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
797d791e92bSAkira Hatanaka }
798d791e92bSAkira Hatanaka
callSpecialFunction__anon25af64e30111::GenMoveAssignment7997275da0fSAkira Hatanaka void callSpecialFunction(QualType FT, CharUnits Offset,
8007275da0fSAkira Hatanaka std::array<Address, 2> Addrs) {
8018b8d3623SAkira Hatanaka Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
8028b8d3623SAkira Hatanaka Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
8037275da0fSAkira Hatanaka CGF->callCStructMoveAssignmentOperator(
8047275da0fSAkira Hatanaka CGF->MakeAddrLValue(Addrs[DstIdx], FT),
8057275da0fSAkira Hatanaka CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
8067275da0fSAkira Hatanaka }
8077275da0fSAkira Hatanaka };
8087275da0fSAkira Hatanaka
8097275da0fSAkira Hatanaka } // namespace
8107275da0fSAkira Hatanaka
destroyNonTrivialCStruct(CodeGenFunction & CGF,Address Addr,QualType Type)8117275da0fSAkira Hatanaka void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF,
8127275da0fSAkira Hatanaka Address Addr, QualType Type) {
8137275da0fSAkira Hatanaka CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Type));
8147275da0fSAkira Hatanaka }
8157275da0fSAkira Hatanaka
8167275da0fSAkira Hatanaka // Default-initialize a variable that is a non-trivial struct or an array of
8177275da0fSAkira Hatanaka // such structure.
defaultInitNonTrivialCStructVar(LValue Dst)8187275da0fSAkira Hatanaka void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) {
8197275da0fSAkira Hatanaka GenDefaultInitialize Gen(getContext());
820f139ae3dSAkira Hatanaka Address DstPtr =
821481de0edSNikita Popov Builder.CreateElementBitCast(Dst.getAddress(*this), CGM.Int8PtrTy);
8227275da0fSAkira Hatanaka Gen.setCGF(this);
8237275da0fSAkira Hatanaka QualType QT = Dst.getType();
8247275da0fSAkira Hatanaka QT = Dst.isVolatile() ? QT.withVolatile() : QT;
8257275da0fSAkira Hatanaka Gen.visit(QT, nullptr, CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
8267275da0fSAkira Hatanaka }
8277275da0fSAkira Hatanaka
8287275da0fSAkira Hatanaka template <class G, size_t N>
callSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,CodeGenFunction & CGF,std::array<Address,N> Addrs)8297275da0fSAkira Hatanaka static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT,
8307275da0fSAkira Hatanaka bool IsVolatile, CodeGenFunction &CGF,
8317275da0fSAkira Hatanaka std::array<Address, N> Addrs) {
832ea1db31dSVedant Kumar auto SetArtificialLoc = ApplyDebugLocation::CreateArtificial(CGF);
8337275da0fSAkira Hatanaka for (unsigned I = 0; I < N; ++I)
834481de0edSNikita Popov Addrs[I] = CGF.Builder.CreateElementBitCast(Addrs[I], CGF.CGM.Int8PtrTy);
8357275da0fSAkira Hatanaka QT = IsVolatile ? QT.withVolatile() : QT;
8367275da0fSAkira Hatanaka Gen.callFunc(FuncName, QT, Addrs, CGF);
8377275da0fSAkira Hatanaka }
8387275da0fSAkira Hatanaka
839827aeb46SJohn McCall template <class G, size_t N>
840827aeb46SJohn McCall static llvm::Function *
getSpecialFunction(G && Gen,StringRef FuncName,QualType QT,bool IsVolatile,std::array<CharUnits,N> Alignments,CodeGenModule & CGM)841827aeb46SJohn McCall getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile,
842827aeb46SJohn McCall std::array<CharUnits, N> Alignments, CodeGenModule &CGM) {
843827aeb46SJohn McCall QT = IsVolatile ? QT.withVolatile() : QT;
844827aeb46SJohn McCall // The following call requires an array of addresses as arguments, but doesn't
845827aeb46SJohn McCall // actually use them (it overwrites them with the addresses of the arguments
846827aeb46SJohn McCall // of the created function).
8472cfb0273SAkira Hatanaka return Gen.getFunction(FuncName, QT, Alignments, CGM);
848827aeb46SJohn McCall }
849827aeb46SJohn McCall
8507275da0fSAkira Hatanaka // Functions to emit calls to the special functions of a non-trivial C struct.
callCStructDefaultConstructor(LValue Dst)8517275da0fSAkira Hatanaka void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
8527275da0fSAkira Hatanaka bool IsVolatile = Dst.isVolatile();
853f139ae3dSAkira Hatanaka Address DstPtr = Dst.getAddress(*this);
8547275da0fSAkira Hatanaka QualType QT = Dst.getType();
8557275da0fSAkira Hatanaka GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext());
8567275da0fSAkira Hatanaka std::string FuncName = GenName.getName(QT, IsVolatile);
8577275da0fSAkira Hatanaka callSpecialFunction(GenDefaultInitialize(getContext()), FuncName, QT,
8587275da0fSAkira Hatanaka IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
8597275da0fSAkira Hatanaka }
8607275da0fSAkira Hatanaka
getNonTrivialCopyConstructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)861801cc327SAkira Hatanaka std::string CodeGenFunction::getNonTrivialCopyConstructorStr(
862801cc327SAkira Hatanaka QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx) {
8639978da36SAkira Hatanaka GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
8649978da36SAkira Hatanaka return GenName.getName(QT, IsVolatile);
8659978da36SAkira Hatanaka }
8669978da36SAkira Hatanaka
getNonTrivialDestructorStr(QualType QT,CharUnits Alignment,bool IsVolatile,ASTContext & Ctx)867801cc327SAkira Hatanaka std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT,
868801cc327SAkira Hatanaka CharUnits Alignment,
869801cc327SAkira Hatanaka bool IsVolatile,
870801cc327SAkira Hatanaka ASTContext &Ctx) {
8719978da36SAkira Hatanaka GenDestructorFuncName GenName("", Alignment, Ctx);
8729978da36SAkira Hatanaka return GenName.getName(QT, IsVolatile);
8739978da36SAkira Hatanaka }
8749978da36SAkira Hatanaka
callCStructDestructor(LValue Dst)8757275da0fSAkira Hatanaka void CodeGenFunction::callCStructDestructor(LValue Dst) {
8767275da0fSAkira Hatanaka bool IsVolatile = Dst.isVolatile();
877f139ae3dSAkira Hatanaka Address DstPtr = Dst.getAddress(*this);
8787275da0fSAkira Hatanaka QualType QT = Dst.getType();
8799978da36SAkira Hatanaka GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
8809978da36SAkira Hatanaka getContext());
8817275da0fSAkira Hatanaka std::string FuncName = GenName.getName(QT, IsVolatile);
8827275da0fSAkira Hatanaka callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
8837275da0fSAkira Hatanaka *this, std::array<Address, 1>({{DstPtr}}));
8847275da0fSAkira Hatanaka }
8857275da0fSAkira Hatanaka
callCStructCopyConstructor(LValue Dst,LValue Src)8867275da0fSAkira Hatanaka void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) {
8877275da0fSAkira Hatanaka bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
888f139ae3dSAkira Hatanaka Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
8897275da0fSAkira Hatanaka QualType QT = Dst.getType();
8907275da0fSAkira Hatanaka GenBinaryFuncName<false> GenName("__copy_constructor_", DstPtr.getAlignment(),
8917275da0fSAkira Hatanaka SrcPtr.getAlignment(), getContext());
8927275da0fSAkira Hatanaka std::string FuncName = GenName.getName(QT, IsVolatile);
8937275da0fSAkira Hatanaka callSpecialFunction(GenCopyConstructor(getContext()), FuncName, QT,
8947275da0fSAkira Hatanaka IsVolatile, *this,
8957275da0fSAkira Hatanaka std::array<Address, 2>({{DstPtr, SrcPtr}}));
8967275da0fSAkira Hatanaka }
8977275da0fSAkira Hatanaka
callCStructCopyAssignmentOperator(LValue Dst,LValue Src)8987275da0fSAkira Hatanaka void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src
8997275da0fSAkira Hatanaka
9007275da0fSAkira Hatanaka ) {
9017275da0fSAkira Hatanaka bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
902f139ae3dSAkira Hatanaka Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9037275da0fSAkira Hatanaka QualType QT = Dst.getType();
9047275da0fSAkira Hatanaka GenBinaryFuncName<false> GenName("__copy_assignment_", DstPtr.getAlignment(),
9057275da0fSAkira Hatanaka SrcPtr.getAlignment(), getContext());
9067275da0fSAkira Hatanaka std::string FuncName = GenName.getName(QT, IsVolatile);
9077275da0fSAkira Hatanaka callSpecialFunction(GenCopyAssignment(getContext()), FuncName, QT, IsVolatile,
9087275da0fSAkira Hatanaka *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9097275da0fSAkira Hatanaka }
9107275da0fSAkira Hatanaka
callCStructMoveConstructor(LValue Dst,LValue Src)9117275da0fSAkira Hatanaka void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) {
9127275da0fSAkira Hatanaka bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
913f139ae3dSAkira Hatanaka Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9147275da0fSAkira Hatanaka QualType QT = Dst.getType();
9157275da0fSAkira Hatanaka GenBinaryFuncName<true> GenName("__move_constructor_", DstPtr.getAlignment(),
9167275da0fSAkira Hatanaka SrcPtr.getAlignment(), getContext());
9177275da0fSAkira Hatanaka std::string FuncName = GenName.getName(QT, IsVolatile);
9187275da0fSAkira Hatanaka callSpecialFunction(GenMoveConstructor(getContext()), FuncName, QT,
9197275da0fSAkira Hatanaka IsVolatile, *this,
9207275da0fSAkira Hatanaka std::array<Address, 2>({{DstPtr, SrcPtr}}));
9217275da0fSAkira Hatanaka }
9227275da0fSAkira Hatanaka
callCStructMoveAssignmentOperator(LValue Dst,LValue Src)9237275da0fSAkira Hatanaka void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src
9247275da0fSAkira Hatanaka
9257275da0fSAkira Hatanaka ) {
9267275da0fSAkira Hatanaka bool IsVolatile = Dst.isVolatile() || Src.isVolatile();
927f139ae3dSAkira Hatanaka Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this);
9287275da0fSAkira Hatanaka QualType QT = Dst.getType();
9297275da0fSAkira Hatanaka GenBinaryFuncName<true> GenName("__move_assignment_", DstPtr.getAlignment(),
9307275da0fSAkira Hatanaka SrcPtr.getAlignment(), getContext());
9317275da0fSAkira Hatanaka std::string FuncName = GenName.getName(QT, IsVolatile);
9327275da0fSAkira Hatanaka callSpecialFunction(GenMoveAssignment(getContext()), FuncName, QT, IsVolatile,
9337275da0fSAkira Hatanaka *this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
9347275da0fSAkira Hatanaka }
935827aeb46SJohn McCall
getNonTrivialCStructDefaultConstructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)936827aeb46SJohn McCall llvm::Function *clang::CodeGen::getNonTrivialCStructDefaultConstructor(
937827aeb46SJohn McCall CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
938827aeb46SJohn McCall ASTContext &Ctx = CGM.getContext();
939827aeb46SJohn McCall GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
940827aeb46SJohn McCall std::string FuncName = GenName.getName(QT, IsVolatile);
941827aeb46SJohn McCall return getSpecialFunction(GenDefaultInitialize(Ctx), FuncName, QT, IsVolatile,
942827aeb46SJohn McCall std::array<CharUnits, 1>({{DstAlignment}}), CGM);
943827aeb46SJohn McCall }
944827aeb46SJohn McCall
getNonTrivialCStructCopyConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)945827aeb46SJohn McCall llvm::Function *clang::CodeGen::getNonTrivialCStructCopyConstructor(
946827aeb46SJohn McCall CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
947827aeb46SJohn McCall bool IsVolatile, QualType QT) {
948827aeb46SJohn McCall ASTContext &Ctx = CGM.getContext();
949827aeb46SJohn McCall GenBinaryFuncName<false> GenName("__copy_constructor_", DstAlignment,
950827aeb46SJohn McCall SrcAlignment, Ctx);
951827aeb46SJohn McCall std::string FuncName = GenName.getName(QT, IsVolatile);
952827aeb46SJohn McCall return getSpecialFunction(
953827aeb46SJohn McCall GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
954827aeb46SJohn McCall std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
955827aeb46SJohn McCall }
956827aeb46SJohn McCall
getNonTrivialCStructMoveConstructor(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)957827aeb46SJohn McCall llvm::Function *clang::CodeGen::getNonTrivialCStructMoveConstructor(
958827aeb46SJohn McCall CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
959827aeb46SJohn McCall bool IsVolatile, QualType QT) {
960827aeb46SJohn McCall ASTContext &Ctx = CGM.getContext();
961827aeb46SJohn McCall GenBinaryFuncName<true> GenName("__move_constructor_", DstAlignment,
962827aeb46SJohn McCall SrcAlignment, Ctx);
963827aeb46SJohn McCall std::string FuncName = GenName.getName(QT, IsVolatile);
964827aeb46SJohn McCall return getSpecialFunction(
965827aeb46SJohn McCall GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
966827aeb46SJohn McCall std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
967827aeb46SJohn McCall }
968827aeb46SJohn McCall
getNonTrivialCStructCopyAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)969827aeb46SJohn McCall llvm::Function *clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
970827aeb46SJohn McCall CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
971827aeb46SJohn McCall bool IsVolatile, QualType QT) {
972827aeb46SJohn McCall ASTContext &Ctx = CGM.getContext();
973827aeb46SJohn McCall GenBinaryFuncName<false> GenName("__copy_assignment_", DstAlignment,
974827aeb46SJohn McCall SrcAlignment, Ctx);
975827aeb46SJohn McCall std::string FuncName = GenName.getName(QT, IsVolatile);
976827aeb46SJohn McCall return getSpecialFunction(
977827aeb46SJohn McCall GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
978827aeb46SJohn McCall std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
979827aeb46SJohn McCall }
980827aeb46SJohn McCall
getNonTrivialCStructMoveAssignmentOperator(CodeGenModule & CGM,CharUnits DstAlignment,CharUnits SrcAlignment,bool IsVolatile,QualType QT)981827aeb46SJohn McCall llvm::Function *clang::CodeGen::getNonTrivialCStructMoveAssignmentOperator(
982827aeb46SJohn McCall CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment,
983827aeb46SJohn McCall bool IsVolatile, QualType QT) {
984827aeb46SJohn McCall ASTContext &Ctx = CGM.getContext();
985827aeb46SJohn McCall GenBinaryFuncName<true> GenName("__move_assignment_", DstAlignment,
986827aeb46SJohn McCall SrcAlignment, Ctx);
987827aeb46SJohn McCall std::string FuncName = GenName.getName(QT, IsVolatile);
988827aeb46SJohn McCall return getSpecialFunction(
989827aeb46SJohn McCall GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
990827aeb46SJohn McCall std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
991827aeb46SJohn McCall }
992827aeb46SJohn McCall
getNonTrivialCStructDestructor(CodeGenModule & CGM,CharUnits DstAlignment,bool IsVolatile,QualType QT)993827aeb46SJohn McCall llvm::Function *clang::CodeGen::getNonTrivialCStructDestructor(
994827aeb46SJohn McCall CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT) {
995827aeb46SJohn McCall ASTContext &Ctx = CGM.getContext();
996827aeb46SJohn McCall GenDestructorFuncName GenName("__destructor_", DstAlignment, Ctx);
997827aeb46SJohn McCall std::string FuncName = GenName.getName(QT, IsVolatile);
998827aeb46SJohn McCall return getSpecialFunction(GenDestructor(Ctx), FuncName, QT, IsVolatile,
999827aeb46SJohn McCall std::array<CharUnits, 1>({{DstAlignment}}), CGM);
1000827aeb46SJohn McCall }
1001