19#include "llvm/Support/ScopedPrinter.h"
34enum { DstIdx = 0, SrcIdx = 1 };
35const char *ValNameStr[2] = {
"dst",
"src"};
37template <
class Derived>
struct StructVisitor {
38 StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
40 template <
class... Ts>
41 void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
45 for (
const FieldDecl *FD : RD->fields()) {
46 QualType FT = FD->getType();
48 asDerived().visit(FT, FD, CurStructOffset, Args...);
51 asDerived().flushTrivialFields(Args...);
54 template <
class... Ts>
void visitTrivial(Ts... Args) {}
56 template <
class... Ts>
void visitCXXDestructor(Ts... Args) {
57 llvm_unreachable(
"field of a C++ struct type is not expected");
60 template <
class... Ts>
void flushTrivialFields(Ts... Args) {}
63 return FD ? Ctx.getASTRecordLayout(FD->
getParent())
72 Derived &asDerived() {
return static_cast<Derived &
>(*this); }
74 ASTContext &getContext() {
return Ctx; }
78template <
class Derived,
bool IsMove>
79struct CopyStructVisitor : StructVisitor<Derived>,
81 using StructVisitor<Derived>::asDerived;
82 using Super = CopiedTypeVisitor<Derived, IsMove>;
84 CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
86 template <
class... Ts>
88 const FieldDecl *FD, CharUnits CurStructOffset, Ts &&... Args) {
90 asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
93 template <
class... Ts>
95 const FieldDecl *FD, CharUnits CurStructOffset,
97 if (
const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
99 CurStructOffset, std::forward<Ts>(Args)...);
104 std::forward<Ts>(Args)...);
107 template <
class... Ts>
108 void visitTrivial(QualType FT,
const FieldDecl *FD, CharUnits CurStructOffset,
111 ASTContext &Ctx = asDerived().getContext();
118 uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
119 uint64_t FEndInBits = FStartInBits + FieldSize;
151template <
class Derived>
struct GenFuncNameBase {
152 std::string getVolatileOffsetStr(
bool IsVolatile, CharUnits Offset) {
160 void visitARCStrong(QualType FT,
const FieldDecl *FD,
161 CharUnits CurStructOffset) {
165 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
169 void visitARCWeak(QualType FT,
const FieldDecl *FD,
170 CharUnits CurStructOffset) {
172 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
176 void visitStruct(QualType QT,
const FieldDecl *FD,
177 CharUnits CurStructOffset) {
178 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
180 asDerived().visitStructFields(QT, FieldOffset);
183 template <
class FieldKind>
184 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
185 const FieldDecl *FD, CharUnits CurStructOffset) {
189 return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
191 asDerived().flushTrivialFields();
192 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
193 ASTContext &Ctx = asDerived().getContext();
198 appendStr(
"_AB" + llvm::to_string(FieldOffset.
getQuantity()) +
"s" +
200 llvm::to_string(NumElts));
202 asDerived().visitWithKind(FK, EltTy,
nullptr, FieldOffset);
206 void appendStr(StringRef Str) { Name += Str; }
208 std::string
getName(QualType QT,
bool IsVolatile) {
214 Derived &asDerived() {
return static_cast<Derived &
>(*this); }
219template <
class Derived>
220struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
221 GenUnaryFuncName(StringRef Prefix, CharUnits DstAlignment, ASTContext &Ctx)
222 : StructVisitor<Derived>(Ctx) {
223 this->appendStr(Prefix);
224 this->appendStr(llvm::to_string(DstAlignment.
getQuantity()));
230 llvm::Type *Ty =
Addr.getElementType();
234template <
bool IsMove>
235struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
236 GenFuncNameBase<GenBinaryFuncName<IsMove>> {
238 GenBinaryFuncName(StringRef Prefix, CharUnits DstAlignment,
239 CharUnits SrcAlignment, ASTContext &Ctx)
240 : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
241 this->appendStr(Prefix);
242 this->appendStr(llvm::to_string(DstAlignment.
getQuantity()));
243 this->appendStr(
"_" + llvm::to_string(SrcAlignment.
getQuantity()));
246 void flushTrivialFields() {
247 if (this->Start == this->End)
250 this->appendStr(
"_t" + llvm::to_string(this->Start.getQuantity()) +
"w" +
251 llvm::to_string((this->End - this->Start).getQuantity()));
256 void visitVolatileTrivial(QualType FT,
const FieldDecl *FD,
257 CharUnits CurStructOffset) {
266 this->appendStr(
"_tv" + llvm::to_string(OffsetInBits) +
"w" +
270 void visitPtrAuth(QualType FT,
const FieldDecl *FD,
271 CharUnits CurStructOffset) {
272 this->appendStr(
"_pa");
274 this->appendStr(llvm::to_string(PtrAuth.
getKey()) +
"_");
277 this->appendStr(
"anv_");
278 CharUnits FieldOffset = CurStructOffset + this->
getFieldOffset(FD);
279 this->appendStr(llvm::to_string(FieldOffset.
getQuantity()));
283struct GenDefaultInitializeFuncName
284 : GenUnaryFuncName<GenDefaultInitializeFuncName>,
286 using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
287 GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
288 : GenUnaryFuncName<GenDefaultInitializeFuncName>(
"__default_constructor_",
289 DstAlignment, Ctx) {}
291 const FieldDecl *FD, CharUnits CurStructOffset) {
292 if (
const auto *AT = getContext().getAsArrayType(FT)) {
301struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
303 using Super = DestructedTypeVisitor<GenDestructorFuncName>;
304 GenDestructorFuncName(
const char *Prefix, CharUnits DstAlignment,
306 : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
308 const FieldDecl *FD, CharUnits CurStructOffset) {
309 if (
const auto *AT = getContext().getAsArrayType(FT)) {
326 for (
unsigned I = 0; I < N; ++I)
331 llvm::append_range(Args, Params);
336template <
size_t N,
size_t... Ints>
337static std::array<Address, N> getParamAddrs(std::index_sequence<Ints...> IntSeq,
338 std::array<CharUnits, N> Alignments,
341 return std::array<Address, N>{
348template <
class Derived>
struct GenFuncBase {
350 void visitStruct(QualType FT,
const FieldDecl *FD, CharUnits CurStructOffset,
351 std::array<Address, N> Addrs) {
352 this->asDerived().callSpecialFunction(
356 template <
class FieldKind,
size_t N>
357 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
358 const FieldDecl *FD, CharUnits CurStructOffset,
359 std::array<Address, N> Addrs) {
362 return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset,
365 asDerived().flushTrivialFields(Addrs);
366 CodeGenFunction &CGF = *this->CGF;
367 ASTContext &Ctx = CGF.getContext();
371 std::array<Address, N> StartAddrs = Addrs;
372 for (
unsigned I = 0; I < N; ++I)
373 StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
374 Address DstAddr = StartAddrs[DstIdx];
375 llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
377 llvm::Value *BaseEltSizeVal =
378 llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
379 llvm::Value *SizeInBytes =
380 CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
381 llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP(
383 llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
386 llvm::BasicBlock *HeaderBB = CGF.createBasicBlock(
"loop.header");
387 CGF.EmitBlock(HeaderBB);
388 llvm::PHINode *PHIs[N];
390 for (
unsigned I = 0; I < N; ++I) {
391 PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2,
"addr.cur");
392 PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB);
396 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"loop.exit");
397 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"loop.body");
402 CGF.Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd,
"done");
403 CGF.Builder.CreateCondBr(Done, ExitBB, LoopBB);
406 CGF.EmitBlock(LoopBB);
409 std::array<Address, N> NewAddrs = Addrs;
411 for (
unsigned I = 0; I < N; ++I)
413 Address(PHIs[I], CGF.Int8PtrTy,
414 StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
420 LoopBB = CGF.Builder.GetInsertBlock();
422 for (
unsigned I = 0; I < N; ++I) {
425 NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
426 PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB);
430 CGF.Builder.CreateBr(HeaderBB);
431 CGF.EmitBlock(ExitBB);
435 Address getAddrWithOffset(Address
Addr, CharUnits Offset) {
436 assert(
Addr.isValid() &&
"invalid address");
439 Addr =
Addr.withElementType(CGF->CGM.Int8Ty);
441 return Addr.withElementType(CGF->CGM.Int8PtrTy);
444 Address getAddrWithOffset(Address
Addr, CharUnits StructFieldOffset,
445 const FieldDecl *FD) {
446 return getAddrWithOffset(
Addr, StructFieldOffset +
451 llvm::Function *getFunction(StringRef FuncName, QualType QT,
452 std::array<CharUnits, N> Alignments,
453 CodeGenModule &CGM) {
455 if (llvm::Function *F = CGM.
getModule().getFunction(FuncName)) {
456 bool WrongType =
false;
457 if (!F->getReturnType()->isVoidTy())
460 for (
const llvm::Argument &Arg : F->args())
466 std::string FuncName = std::string(F->getName());
467 SourceLocation Loc = QT->
castAs<RecordType>()->getDecl()->getLocation();
468 CGM.
Error(Loc,
"special function " + FuncName +
469 " for non-trivial C struct has incorrect type");
476 FunctionArgList Args;
477 const CGFunctionInfo &FI = getFunctionInfo<N>(CGM, Args);
480 llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
482 F->setVisibility(llvm::GlobalValue::HiddenVisibility);
485 CodeGenFunction NewCGF(CGM);
487 CGF->StartFunction(GlobalDecl(), Ctx.
VoidTy, F, FI, Args);
489 std::array<Address, N> Addrs =
490 getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
492 CGF->FinishFunction();
497 void callFunc(StringRef FuncName, QualType QT, std::array<Address, N> Addrs,
498 CodeGenFunction &CallerCGF) {
499 std::array<CharUnits, N> Alignments;
500 llvm::Value *Ptrs[N];
502 for (
unsigned I = 0; I < N; ++I) {
503 Alignments[I] = Addrs[I].getAlignment();
504 Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF);
507 if (llvm::Function *F =
508 getFunction(FuncName, QT, Alignments, CallerCGF.
CGM))
512 Derived &asDerived() {
return static_cast<Derived &
>(*this); }
514 void setCGF(CodeGenFunction *F) { CGF = F; }
516 CodeGenFunction *CGF =
nullptr;
519template <
class Derived,
bool IsMove>
520struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
521 GenFuncBase<Derived> {
522 GenBinaryFunc(ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
524 void flushTrivialFields(std::array<Address, 2> Addrs) {
525 CharUnits
Size = this->End - this->Start;
527 if (
Size.getQuantity() == 0)
530 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
531 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
534 if (
Size.getQuantity() >= 16 ||
535 !llvm::has_single_bit<uint32_t>(
Size.getQuantity())) {
536 llvm::Value *SizeVal =
537 llvm::ConstantInt::get(this->CGF->
SizeTy,
Size.getQuantity());
542 llvm::Type *Ty = llvm::Type::getIntNTy(
544 Size.getQuantity() * this->CGF->getContext().getCharWidth());
554 template <
class... Ts>
555 void visitVolatileTrivial(QualType FT,
const FieldDecl *FD, CharUnits Offset,
556 std::array<Address, 2> Addrs) {
566 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
570 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
576 Address DstAddr = Addrs[DstIdx].withElementType(Ty);
577 Address SrcAddr = Addrs[SrcIdx].withElementType(Ty);
584 void visitPtrAuth(QualType FT,
const FieldDecl *FD, CharUnits CurStackOffset,
585 std::array<Address, 2> Addrs) {
587 Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
588 Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
594struct GenDestructor : StructVisitor<GenDestructor>,
595 GenFuncBase<GenDestructor>,
597 using Super = DestructedTypeVisitor<GenDestructor>;
598 GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
601 const FieldDecl *FD, CharUnits CurStructOffset,
602 std::array<Address, 1> Addrs) {
603 if (
const auto *AT = getContext().getAsArrayType(FT)) {
611 void visitARCStrong(QualType QT,
const FieldDecl *FD,
612 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
614 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
617 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
618 std::array<Address, 1> Addrs) {
620 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
624 std::array<Address, 1> Addrs) {
626 CGF->
MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
630struct GenDefaultInitialize
631 : StructVisitor<GenDefaultInitialize>,
632 GenFuncBase<GenDefaultInitialize>,
634 using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
635 typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
637 GenDefaultInitialize(ASTContext &Ctx)
638 : StructVisitor<GenDefaultInitialize>(Ctx) {}
641 const FieldDecl *FD, CharUnits CurStructOffset,
642 std::array<Address, 1> Addrs) {
643 if (
const auto *AT = getContext().getAsArrayType(FT)) {
652 void visitARCStrong(QualType QT,
const FieldDecl *FD,
653 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
655 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
658 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
659 std::array<Address, 1> Addrs) {
661 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
664 template <
class FieldKind,
size_t... Is>
665 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
666 const FieldDecl *FD, CharUnits CurStructOffset,
667 std::array<Address, 1> Addrs) {
669 return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
671 ASTContext &Ctx = getContext();
677 GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
681 llvm::Constant *SizeVal = CGF->
Builder.getInt64(
Size.getQuantity());
682 Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
689 std::array<Address, 1> Addrs) {
691 CGF->
MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
695struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
696 GenCopyConstructor(ASTContext &Ctx)
697 : GenBinaryFunc<GenCopyConstructor,
false>(Ctx) {}
699 void visitARCStrong(QualType QT,
const FieldDecl *FD,
700 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
701 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
702 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
709 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
710 std::array<Address, 2> Addrs) {
711 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
712 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
717 std::array<Address, 2> Addrs) {
718 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
719 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
725struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
726 GenMoveConstructor(ASTContext &Ctx)
727 : GenBinaryFunc<GenMoveConstructor,
true>(Ctx) {}
729 void visitARCStrong(QualType QT,
const FieldDecl *FD,
730 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
731 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
732 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
734 llvm::Value *SrcVal =
741 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
742 std::array<Address, 2> Addrs) {
743 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
744 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
749 std::array<Address, 2> Addrs) {
750 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
751 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
757struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
758 GenCopyAssignment(ASTContext &Ctx)
759 : GenBinaryFunc<GenCopyAssignment,
false>(Ctx) {}
761 void visitARCStrong(QualType QT,
const FieldDecl *FD,
762 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
763 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
764 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
771 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
772 std::array<Address, 2> Addrs) {
773 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
774 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
779 std::array<Address, 2> Addrs) {
780 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
781 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
788struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
789 GenMoveAssignment(ASTContext &Ctx)
790 : GenBinaryFunc<GenMoveAssignment,
true>(Ctx) {}
792 void visitARCStrong(QualType QT,
const FieldDecl *FD,
793 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
794 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
795 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
797 llvm::Value *SrcVal =
801 llvm::Value *DstVal =
807 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
808 std::array<Address, 2> Addrs) {
809 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
810 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
815 std::array<Address, 2> Addrs) {
816 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
817 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
839 Gen.visit(QT,
nullptr,
CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
842template <
class G,
size_t N>
845 std::array<Address, N> Addrs) {
847 for (
unsigned I = 0; I < N; ++I)
850 Gen.callFunc(FuncName, QT, Addrs, CGF);
853template <
class G,
size_t N>
854static llvm::Function *
861 return Gen.getFunction(FuncName, QT, Alignments, CGM);
870 std::string FuncName = GenName.getName(QT, IsVolatile);
872 IsVolatile, *
this, std::array<Address, 1>({{DstPtr}}));
877 GenBinaryFuncName<false> GenName(
"", Alignment, Alignment, Ctx);
878 return GenName.getName(QT, IsVolatile);
885 GenDestructorFuncName GenName(
"", Alignment, Ctx);
886 return GenName.getName(QT, IsVolatile);
893 GenDestructorFuncName GenName(
"__destructor_", DstPtr.
getAlignment(),
895 std::string FuncName = GenName.getName(QT, IsVolatile);
897 *
this, std::array<Address, 1>({{DstPtr}}));
904 GenBinaryFuncName<false> GenName(
"__copy_constructor_", DstPtr.
getAlignment(),
906 std::string FuncName = GenName.getName(QT, IsVolatile);
909 std::array<Address, 2>({{DstPtr, SrcPtr}}));
918 GenBinaryFuncName<false> GenName(
"__copy_assignment_", DstPtr.
getAlignment(),
920 std::string FuncName = GenName.getName(QT, IsVolatile);
922 *
this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
929 GenBinaryFuncName<true> GenName(
"__move_constructor_", DstPtr.
getAlignment(),
931 std::string FuncName = GenName.getName(QT, IsVolatile);
934 std::array<Address, 2>({{DstPtr, SrcPtr}}));
943 GenBinaryFuncName<true> GenName(
"__move_assignment_", DstPtr.
getAlignment(),
945 std::string FuncName = GenName.getName(QT, IsVolatile);
947 *
this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
953 GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
954 std::string FuncName = GenName.getName(QT, IsVolatile);
956 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
963 GenBinaryFuncName<false> GenName(
"__copy_constructor_", DstAlignment,
965 std::string FuncName = GenName.getName(QT, IsVolatile);
967 GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
968 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
975 GenBinaryFuncName<true> GenName(
"__move_constructor_", DstAlignment,
977 std::string FuncName = GenName.getName(QT, IsVolatile);
979 GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
980 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
987 GenBinaryFuncName<false> GenName(
"__copy_assignment_", DstAlignment,
989 std::string FuncName = GenName.getName(QT, IsVolatile);
991 GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
992 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
999 GenBinaryFuncName<true> GenName(
"__move_assignment_", DstAlignment,
1001 std::string FuncName = GenName.getName(QT, IsVolatile);
1003 GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
1004 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1010 GenDestructorFuncName GenName(
"__destructor_", DstAlignment, Ctx);
1011 std::string FuncName = GenName.getName(QT, IsVolatile);
1013 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
static bool getFieldOffsetInBits(CodeGenFunction &CGF, const RecordDecl *RD, const FieldDecl *Field, int64_t &Offset)
The offset of a field from the beginning of the record.
static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, ASTContext &Ctx)
static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, CodeGenFunction &CGF, std::array< Address, N > Addrs)
static llvm::Function * getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, std::array< CharUnits, N > Alignments, CodeGenModule &CGM)
static llvm::Constant * getNullForVariable(Address addr)
Given the address of a variable of pointer type, find the correct null to store into it.
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
QualType getElementType() const
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::CallInst * CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
CGFunctionInfo - Class to encapsulate the information about a function definition.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitARCMoveWeak(Address dst, Address src)
void @objc_moveWeak(i8** dest, i8** src) Disregards the current value in dest.
static Destroyer destroyNonTrivialCStruct
void callCStructMoveConstructor(LValue Dst, LValue Src)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::Type * ConvertType(QualType T)
static Destroyer destroyARCWeak
void callCStructDestructor(LValue Dst)
llvm::Value * EmitARCRetain(QualType type, llvm::Value *value)
Produce the code to do a retain.
llvm::Value * EmitARCStoreStrong(LValue lvalue, llvm::Value *value, bool resultIgnored)
Store into a strong object.
static std::string getNonTrivialDestructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise)
Release the given object.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
void defaultInitNonTrivialCStructVar(LValue Dst)
void callCStructDefaultConstructor(LValue Dst)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void callCStructCopyAssignmentOperator(LValue Dst, LValue Src)
static Destroyer destroyARCStrongImprecise
void callCStructCopyConstructor(LValue Dst, LValue Src)
void EmitPointerAuthCopy(PointerAuthQualifier Qualifier, QualType Type, Address DestField, Address SrcField)
void callCStructMoveAssignmentOperator(LValue Dst, LValue Src)
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
llvm::Type * ConvertTypeForMem(QualType T)
static std::string getNonTrivialCopyConstructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
llvm::LLVMContext & getLLVMContext()
void EmitARCCopyWeak(Address dst, Address src)
void @objc_copyWeak(i8** dest, i8** src) Disregards the current value in dest.
void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
CodeGenTypes & getTypes()
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
ASTContext & getContext() const
void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)
Set the LLVM function attributes (sext, zext, etc).
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)
Set the LLVM function attributes which only apply to a function definition.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
Address getAddress() const
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isZeroLengthBitField() const
Is this a zero-length bit-field?
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
bool authenticatesNullValues() const
PointerAuthQualifier withoutKeyNone() const
unsigned getExtraDiscriminator() const
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
PointerAuthQualifier getPointerAuth() const
PrimitiveDefaultInitializeKind
QualType withVolatile() const
Encodes a location in the source.
The base class of the type hierarchy.
bool isBlockPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
RecordDecl * castAsRecordDecl() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
llvm::Function * getNonTrivialCStructCopyConstructor(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Returns the copy constructor for a C struct with non-trivially copyable fields, generating it if nece...
llvm::Function * getNonTrivialCStructMoveConstructor(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Returns the move constructor for a C struct with non-trivially copyable fields, generating it if nece...
llvm::Function * getNonTrivialCStructCopyAssignmentOperator(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Returns the copy assignment operator for a C struct with non-trivially copyable fields,...
llvm::Function * getNonTrivialCStructMoveAssignmentOperator(CodeGenModule &CGM, CharUnits DstAlignment, CharUnits SrcAlignment, bool IsVolatile, QualType QT)
Return the move assignment operator for a C struct with non-trivially copyable fields,...
llvm::Function * getNonTrivialCStructDestructor(CodeGenModule &CGM, CharUnits DstAlignment, bool IsVolatile, QualType QT)
Returns the destructor for a C struct with non-trivially copyable fields, generating it if necessary.
llvm::Function * getNonTrivialCStructDefaultConstructor(CodeGenModule &GCM, CharUnits DstAlignment, bool IsVolatile, QualType QT)
Returns the default constructor for a C struct with non-trivially copyable fields,...
StringRef getName(const HeaderType T)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.
llvm::PointerType * VoidPtrTy
llvm::PointerType * Int8PtrPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * SizeTy
llvm::PointerType * Int8PtrTy
RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, Ts &&... Args)
void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT, Ts &&... Args)
void visitWithKind(QualType::DestructionKind DK, QualType FT, Ts &&... Args)