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,
bool IsCtor>
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) {
569 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
573 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
579 Address DstAddr = Addrs[DstIdx].withElementType(Ty);
580 Address SrcAddr = Addrs[SrcIdx].withElementType(Ty);
604 void visitPtrAuth(QualType FT,
const FieldDecl *FD, CharUnits CurStackOffset,
605 std::array<Address, 2> Addrs) {
607 Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
608 Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
614struct GenDestructor : StructVisitor<GenDestructor>,
615 GenFuncBase<GenDestructor>,
617 using Super = DestructedTypeVisitor<GenDestructor>;
618 GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
621 const FieldDecl *FD, CharUnits CurStructOffset,
622 std::array<Address, 1> Addrs) {
623 if (
const auto *AT = getContext().getAsArrayType(FT)) {
631 void visitARCStrong(QualType QT,
const FieldDecl *FD,
632 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
634 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
637 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
638 std::array<Address, 1> Addrs) {
640 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
644 std::array<Address, 1> Addrs) {
646 CGF->
MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
650struct GenDefaultInitialize
651 : StructVisitor<GenDefaultInitialize>,
652 GenFuncBase<GenDefaultInitialize>,
654 using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
655 typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
657 GenDefaultInitialize(ASTContext &Ctx)
658 : StructVisitor<GenDefaultInitialize>(Ctx) {}
661 const FieldDecl *FD, CharUnits CurStructOffset,
662 std::array<Address, 1> Addrs) {
663 if (
const auto *AT = getContext().getAsArrayType(FT)) {
672 void visitARCStrong(QualType QT,
const FieldDecl *FD,
673 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
675 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
678 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
679 std::array<Address, 1> Addrs) {
681 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
684 template <
class FieldKind,
size_t... Is>
685 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
686 const FieldDecl *FD, CharUnits CurStructOffset,
687 std::array<Address, 1> Addrs) {
689 return visitTrivial(QualType(AT, 0), FD, CurStructOffset, Addrs);
691 ASTContext &Ctx = getContext();
697 GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
701 llvm::Constant *SizeVal = CGF->
Builder.getInt64(
Size.getQuantity());
702 Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
709 std::array<Address, 1> Addrs) {
711 CGF->
MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
715struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false, true> {
716 GenCopyConstructor(ASTContext &Ctx)
717 : GenBinaryFunc<GenCopyConstructor,
false,
true>(Ctx) {}
719 void visitARCStrong(QualType QT,
const FieldDecl *FD,
720 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
721 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
722 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
729 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
730 std::array<Address, 2> Addrs) {
731 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
732 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
737 std::array<Address, 2> Addrs) {
738 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
739 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
745struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true, true> {
746 GenMoveConstructor(ASTContext &Ctx)
747 : GenBinaryFunc<GenMoveConstructor,
true,
true>(Ctx) {}
749 void visitARCStrong(QualType QT,
const FieldDecl *FD,
750 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
751 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
752 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
754 llvm::Value *SrcVal =
761 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
762 std::array<Address, 2> Addrs) {
763 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
764 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
769 std::array<Address, 2> Addrs) {
770 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
771 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
777struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false, false> {
778 GenCopyAssignment(ASTContext &Ctx)
779 : GenBinaryFunc<GenCopyAssignment,
false,
false>(Ctx) {}
781 void visitARCStrong(QualType QT,
const FieldDecl *FD,
782 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
783 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
784 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
791 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
792 std::array<Address, 2> Addrs) {
793 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
794 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
799 std::array<Address, 2> Addrs) {
800 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
801 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
808struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true, false> {
809 GenMoveAssignment(ASTContext &Ctx)
810 : GenBinaryFunc<GenMoveAssignment,
true,
false>(Ctx) {}
812 void visitARCStrong(QualType QT,
const FieldDecl *FD,
813 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
814 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
815 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
817 llvm::Value *SrcVal =
821 llvm::Value *DstVal =
827 void visitARCWeak(QualType QT,
const FieldDecl *FD, CharUnits CurStructOffset,
828 std::array<Address, 2> Addrs) {
829 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
830 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
835 std::array<Address, 2> Addrs) {
836 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
837 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
859 Gen.visit(QT,
nullptr,
CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
862template <
class G,
size_t N>
865 std::array<Address, N> Addrs) {
867 for (
unsigned I = 0; I < N; ++I)
870 Gen.callFunc(FuncName, QT, Addrs, CGF);
873template <
class G,
size_t N>
874static llvm::Function *
881 return Gen.getFunction(FuncName, QT, Alignments, CGM);
890 std::string FuncName = GenName.getName(QT, IsVolatile);
892 IsVolatile, *
this, std::array<Address, 1>({{DstPtr}}));
897 GenBinaryFuncName<false> GenName(
"", Alignment, Alignment, Ctx);
898 return GenName.getName(QT, IsVolatile);
905 GenDestructorFuncName GenName(
"", Alignment, Ctx);
906 return GenName.getName(QT, IsVolatile);
913 GenDestructorFuncName GenName(
"__destructor_", DstPtr.
getAlignment(),
915 std::string FuncName = GenName.getName(QT, IsVolatile);
917 *
this, std::array<Address, 1>({{DstPtr}}));
924 GenBinaryFuncName<false> GenName(
"__copy_constructor_", DstPtr.
getAlignment(),
926 std::string FuncName = GenName.getName(QT, IsVolatile);
929 std::array<Address, 2>({{DstPtr, SrcPtr}}));
938 GenBinaryFuncName<false> GenName(
"__copy_assignment_", DstPtr.
getAlignment(),
940 std::string FuncName = GenName.getName(QT, IsVolatile);
942 *
this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
949 GenBinaryFuncName<true> GenName(
"__move_constructor_", DstPtr.
getAlignment(),
951 std::string FuncName = GenName.getName(QT, IsVolatile);
954 std::array<Address, 2>({{DstPtr, SrcPtr}}));
963 GenBinaryFuncName<true> GenName(
"__move_assignment_", DstPtr.
getAlignment(),
965 std::string FuncName = GenName.getName(QT, IsVolatile);
967 *
this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
973 GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
974 std::string FuncName = GenName.getName(QT, IsVolatile);
976 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
983 GenBinaryFuncName<false> GenName(
"__copy_constructor_", DstAlignment,
985 std::string FuncName = GenName.getName(QT, IsVolatile);
987 GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
988 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
995 GenBinaryFuncName<true> GenName(
"__move_constructor_", DstAlignment,
997 std::string FuncName = GenName.getName(QT, IsVolatile);
999 GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
1000 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1007 GenBinaryFuncName<false> GenName(
"__copy_assignment_", DstAlignment,
1009 std::string FuncName = GenName.getName(QT, IsVolatile);
1011 GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
1012 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1019 GenBinaryFuncName<true> GenName(
"__move_assignment_", DstAlignment,
1021 std::string FuncName = GenName.getName(QT, IsVolatile);
1023 GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
1024 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
1030 GenDestructorFuncName GenName(
"__destructor_", DstAlignment, Ctx);
1031 std::string FuncName = GenName.getName(QT, IsVolatile);
1033 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.
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
QualType getElementType() const
This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
static CharUnits 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 AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
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.
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
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 EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
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)
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
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.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex 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, const 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)
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
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)