18 #include "llvm/Support/ScopedPrinter.h" 21 using namespace clang;
22 using namespace CodeGen;
33 enum { DstIdx = 0, SrcIdx = 1 };
34 const char *ValNameStr[2] = {
"dst",
"src"};
36 template <
class Derived>
struct StructVisitor {
39 template <
class... Ts>
47 asDerived().visit(FT, FD, CurStructOffset, Args...);
50 asDerived().flushTrivialFields(Args...);
53 template <
class... Ts>
void visitTrivial(Ts... Args) {}
55 template <
class... Ts>
void visitCXXDestructor(Ts... Args) {
56 llvm_unreachable(
"field of a C++ struct type is not expected");
59 template <
class... Ts>
void flushTrivialFields(Ts... Args) {}
61 uint64_t getFieldOffsetInBits(
const FieldDecl *FD) {
71 Derived &asDerived() {
return static_cast<Derived &
>(*this); }
77 template <
class Derived,
bool IsMove>
78 struct CopyStructVisitor : StructVisitor<Derived>,
80 using StructVisitor<Derived>::asDerived;
83 CopyStructVisitor(
ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
85 template <
class... Ts>
89 asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
92 template <
class... Ts>
96 if (
const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
98 CurStructOffset, std::forward<Ts>(Args)...);
102 Super::visitWithKind(PCK, FT, FD, CurStructOffset,
103 std::forward<Ts>(Args)...);
106 template <
class... Ts>
117 uint64_t FStartInBits = asDerived().getFieldOffsetInBits(FD);
118 uint64_t FEndInBits = FStartInBits + FieldSize;
119 uint64_t RoundedFEnd = llvm::alignTo(FEndInBits, Ctx.getCharWidth());
123 Start = CurStructOffset + Ctx.toCharUnitsFromBits(FStartInBits);
124 End = CurStructOffset + Ctx.toCharUnitsFromBits(RoundedFEnd);
150 template <
class Derived>
struct GenFuncNameBase {
164 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
171 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
177 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
179 asDerived().visitStructFields(QT, FieldOffset);
182 template <
class FieldKind>
183 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
188 return asDerived().visitTrivial(
QualType(AT, 0), FD, CurStructOffset);
190 asDerived().flushTrivialFields();
191 CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
197 appendStr(
"_AB" + llvm::to_string(FieldOffset.
getQuantity()) +
"s" +
199 llvm::to_string(NumElts));
201 asDerived().visitWithKind(FK, EltTy,
nullptr, FieldOffset);
205 void appendStr(StringRef Str) { Name += Str; }
213 Derived &asDerived() {
return static_cast<Derived &
>(*this); }
218 template <
class Derived>
219 struct GenUnaryFuncName : StructVisitor<Derived>, GenFuncNameBase<Derived> {
221 : StructVisitor<Derived>(Ctx) {
222 this->appendStr(Prefix);
223 this->appendStr(llvm::to_string(DstAlignment.
getQuantity()));
230 return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty));
233 template <
bool IsMove>
234 struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
235 GenFuncNameBase<GenBinaryFuncName<IsMove>> {
237 GenBinaryFuncName(StringRef Prefix,
CharUnits DstAlignment,
239 : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>(Ctx) {
240 this->appendStr(Prefix);
241 this->appendStr(llvm::to_string(DstAlignment.
getQuantity()));
242 this->appendStr(
"_" + llvm::to_string(SrcAlignment.
getQuantity()));
245 void flushTrivialFields() {
246 if (this->Start == this->
End)
249 this->appendStr(
"_t" + llvm::to_string(this->Start.getQuantity()) +
"w" +
250 llvm::to_string((this->
End - this->Start).getQuantity()));
259 uint64_t OffsetInBits =
260 this->Ctx.
toBits(CurStructOffset) + this->getFieldOffsetInBits(FD);
261 this->appendStr(
"_tv" + llvm::to_string(OffsetInBits) +
"w" +
266 struct GenDefaultInitializeFuncName
267 : GenUnaryFuncName<GenDefaultInitializeFuncName>,
271 : GenUnaryFuncName<GenDefaultInitializeFuncName>(
"__default_constructor_",
272 DstAlignment, Ctx) {}
275 if (
const auto *AT = getContext().getAsArrayType(FT)) {
280 Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
284 struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
287 GenDestructorFuncName(
const char *Prefix,
CharUnits DstAlignment,
289 : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment, Ctx) {}
292 if (
const auto *AT = getContext().getAsArrayType(FT)) {
297 Super::visitWithKind(DK, FT, FD, CurStructOffset);
309 for (
unsigned I = 0; I < N; ++I)
314 for (
auto &
P : Params)
322 template <
class Derived>
struct GenFuncBase {
325 std::array<Address, N> Addrs) {
326 this->asDerived().callSpecialFunction(
330 template <
class FieldKind,
size_t N>
331 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
333 std::array<Address, N> Addrs) {
336 return asDerived().visitTrivial(
QualType(AT, 0), FD, CurStructOffset,
339 asDerived().flushTrivialFields(Addrs);
345 std::array<Address, N> StartAddrs = Addrs;
346 for (
unsigned I = 0; I < N; ++I)
347 StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStructOffset, FD);
348 Address DstAddr = StartAddrs[DstIdx];
352 llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
354 CGF.
Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
360 llvm::BasicBlock *PreheaderBB = CGF.
Builder.GetInsertBlock();
365 llvm::PHINode *PHIs[N];
367 for (
unsigned I = 0; I < N; ++I) {
369 PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB);
379 CGF.
Builder.CreateICmpEQ(PHIs[DstIdx], DstArrayEnd,
"done");
380 CGF.
Builder.CreateCondBr(Done, ExitBB, LoopBB);
386 std::array<Address, N> NewAddrs = Addrs;
388 for (
unsigned I = 0; I < N; ++I)
390 PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
396 LoopBB = CGF.
Builder.GetInsertBlock();
398 for (
unsigned I = 0; I < N; ++I) {
401 NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize);
402 PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB);
406 CGF.
Builder.CreateBr(HeaderBB);
412 assert(Addr.
isValid() &&
"invalid address");
415 Addr = CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrTy);
416 Addr = CGF->Builder.CreateConstInBoundsGEP(Addr, Offset.
getQuantity());
417 return CGF->Builder.CreateBitCast(Addr, CGF->CGM.Int8PtrPtrTy);
422 return getAddrWithOffset(Addr, StructFieldOffset +
428 getFunction(StringRef FuncName,
QualType QT, std::array<Address, N> Addrs,
431 if (llvm::Function *F = CGM.
getModule().getFunction(FuncName)) {
432 bool WrongType =
false;
433 if (!F->getReturnType()->isVoidTy())
436 for (
const llvm::Argument &Arg : F->args())
442 std::string FuncName = F->getName();
444 CGM.
Error(Loc,
"special function " + FuncName +
445 " for non-trivial C struct has incorrect type");
454 llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
457 FuncName, &CGM.getModule());
459 CGM.SetLLVMFunctionAttributes(
GlobalDecl(), FI, F);
460 CGM.SetLLVMFunctionAttributesForDefinition(
nullptr, F);
468 CGF->StartFunction(FD, Ctx.
VoidTy, F, FI, Args);
470 for (
unsigned I = 0; I < N; ++I) {
471 llvm::Value *
V = CGF->Builder.CreateLoad(CGF->GetAddrOfLocalVar(Args[I]));
472 Addrs[I] =
Address(V, Alignments[I]);
476 CGF->FinishFunction();
481 void callFunc(StringRef FuncName,
QualType QT, std::array<Address, N> Addrs,
483 std::array<CharUnits, N> Alignments;
486 for (
unsigned I = 0; I < N; ++I) {
487 Alignments[I] = Addrs[I].getAlignment();
493 if (llvm::Function *F =
494 getFunction(FuncName, QT, Addrs, Alignments, CallerCGF.
CGM))
498 Derived &asDerived() {
return static_cast<Derived &
>(*this); }
505 template <
class Derived,
bool IsMove>
506 struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
507 GenFuncBase<Derived> {
508 GenBinaryFunc(
ASTContext &Ctx) : CopyStructVisitor<Derived, IsMove>(Ctx) {}
510 void flushTrivialFields(std::array<Address, 2> Addrs) {
516 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], this->Start);
517 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], this->Start);
522 llvm::ConstantInt::get(this->CGF->SizeTy, Size.
getQuantity());
524 this->CGF->Builder.CreateElementBitCast(DstAddr, this->CGF->Int8Ty);
526 this->CGF->Builder.CreateElementBitCast(SrcAddr, this->CGF->Int8Ty);
527 this->CGF->Builder.CreateMemCpy(DstAddr, SrcAddr, SizeVal,
false);
530 this->CGF->getLLVMContext(),
531 Size.
getQuantity() * this->CGF->getContext().getCharWidth());
532 DstAddr = this->CGF->Builder.CreateElementBitCast(DstAddr, Ty);
533 SrcAddr = this->CGF->Builder.CreateElementBitCast(SrcAddr, Ty);
534 llvm::Value *SrcVal = this->CGF->Builder.CreateLoad(SrcAddr,
false);
535 this->CGF->Builder.CreateStore(SrcVal, DstAddr,
false);
541 template <
class... Ts>
543 std::array<Address, 2> Addrs) {
547 llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
548 Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
549 LValue DstBase = this->CGF->MakeAddrLValue(
550 this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
551 DstLV = this->CGF->EmitLValueForField(DstBase, FD);
552 Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
553 LValue SrcBase = this->CGF->MakeAddrLValue(
554 this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
555 SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
557 llvm::PointerType *Ty = this->CGF->ConvertType(FT)->getPointerTo();
558 Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
559 Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
560 DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
561 SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
564 this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
569 struct GenDestructor : StructVisitor<GenDestructor>,
570 GenFuncBase<GenDestructor>,
573 GenDestructor(
ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
577 std::array<Address, 1> Addrs) {
578 if (
const auto *AT = getContext().getAsArrayType(FT)) {
583 Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
587 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
588 CGF->destroyARCStrongImprecise(
589 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
593 std::array<Address, 1> Addrs) {
595 *CGF, getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
599 std::array<Address, 1> Addrs) {
600 CGF->callCStructDestructor(
601 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
605 struct GenDefaultInitialize
606 : StructVisitor<GenDefaultInitialize>,
607 GenFuncBase<GenDefaultInitialize>,
610 typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
613 : StructVisitor<GenDefaultInitialize>(Ctx) {}
617 std::array<Address, 1> Addrs) {
618 if (
const auto *AT = getContext().getAsArrayType(FT)) {
624 Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
628 CharUnits CurStructOffset, std::array<Address, 1> Addrs) {
629 CGF->EmitNullInitialization(
630 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
634 std::array<Address, 1> Addrs) {
635 CGF->EmitNullInitialization(
636 getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD), QT);
639 template <
class FieldKind,
size_t... Is>
640 void visitArray(FieldKind FK,
const ArrayType *AT,
bool IsVolatile,
642 std::array<Address, 1> Addrs) {
644 return visitTrivial(
QualType(AT, 0), FD, CurStructOffset, Addrs);
651 GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStructOffset, Addrs);
655 llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.
getQuantity());
656 Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
657 Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
658 CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
663 std::array<Address, 1> Addrs) {
664 CGF->callCStructDefaultConstructor(
665 CGF->MakeAddrLValue(getAddrWithOffset(Addrs[DstIdx], Offset), FT));
669 struct GenCopyConstructor : GenBinaryFunc<GenCopyConstructor, false> {
671 : GenBinaryFunc<GenCopyConstructor, false>(Ctx) {}
674 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
675 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
676 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
680 CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
true);
684 std::array<Address, 2> Addrs) {
685 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
686 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
687 CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
691 std::array<Address, 2> Addrs) {
692 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
693 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
694 CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
695 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
699 struct GenMoveConstructor : GenBinaryFunc<GenMoveConstructor, true> {
701 : GenBinaryFunc<GenMoveConstructor, true>(Ctx) {}
704 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
705 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
706 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
707 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
711 CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
716 std::array<Address, 2> Addrs) {
717 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
718 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
719 CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
723 std::array<Address, 2> Addrs) {
724 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
725 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
726 CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
727 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
731 struct GenCopyAssignment : GenBinaryFunc<GenCopyAssignment, false> {
733 : GenBinaryFunc<GenCopyAssignment, false>(Ctx) {}
736 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
737 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
738 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
741 CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
746 std::array<Address, 2> Addrs) {
747 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
748 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
749 CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
753 std::array<Address, 2> Addrs) {
754 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
755 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
756 CGF->callCStructCopyAssignmentOperator(
757 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
758 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
762 struct GenMoveAssignment : GenBinaryFunc<GenMoveAssignment, true> {
764 : GenBinaryFunc<GenMoveAssignment, true>(Ctx) {}
767 CharUnits CurStructOffset, std::array<Address, 2> Addrs) {
768 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
769 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
770 LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT);
774 LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT);
777 CGF->EmitStoreOfScalar(SrcVal, DstLV);
782 std::array<Address, 2> Addrs) {
783 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStructOffset, FD);
784 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStructOffset, FD);
785 CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
789 std::array<Address, 2> Addrs) {
790 Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], Offset);
791 Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], Offset);
792 CGF->callCStructMoveAssignmentOperator(
793 CGF->MakeAddrLValue(Addrs[DstIdx], FT),
794 CGF->MakeAddrLValue(Addrs[SrcIdx], FT));
808 GenDefaultInitialize Gen(getContext());
810 Builder.CreateBitCast(Dst.
getAddress(*
this), CGM.Int8PtrPtrTy);
814 Gen.visit(QT,
nullptr,
CharUnits::Zero(), std::array<Address, 1>({{DstPtr}}));
817 template <
class G,
size_t N>
820 std::array<Address, N> Addrs) {
822 for (
unsigned I = 0; I < N; ++I)
825 Gen.callFunc(FuncName, QT, Addrs, CGF);
839 template <
class G,
size_t N>
840 static llvm::Function *
847 return Gen.getFunction(FuncName, QT, createNullAddressArray<N>(), Alignments,
856 GenDefaultInitializeFuncName GenName(DstPtr.
getAlignment(), getContext());
857 std::string FuncName = GenName.getName(QT, IsVolatile);
859 IsVolatile, *
this, std::array<Address, 1>({{DstPtr}}));
864 GenBinaryFuncName<false> GenName(
"", Alignment, Alignment, Ctx);
865 return GenName.getName(QT, IsVolatile);
872 GenDestructorFuncName GenName(
"", Alignment, Ctx);
873 return GenName.getName(QT, IsVolatile);
880 GenDestructorFuncName GenName(
"__destructor_", DstPtr.
getAlignment(),
882 std::string FuncName = GenName.getName(QT, IsVolatile);
884 *
this, std::array<Address, 1>({{DstPtr}}));
891 GenBinaryFuncName<false> GenName(
"__copy_constructor_", DstPtr.
getAlignment(),
892 SrcPtr.getAlignment(), getContext());
893 std::string FuncName = GenName.getName(QT, IsVolatile);
896 std::array<Address, 2>({{DstPtr, SrcPtr}}));
905 GenBinaryFuncName<false> GenName(
"__copy_assignment_", DstPtr.
getAlignment(),
906 SrcPtr.getAlignment(), getContext());
907 std::string FuncName = GenName.getName(QT, IsVolatile);
909 *
this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
916 GenBinaryFuncName<true> GenName(
"__move_constructor_", DstPtr.
getAlignment(),
917 SrcPtr.getAlignment(), getContext());
918 std::string FuncName = GenName.getName(QT, IsVolatile);
921 std::array<Address, 2>({{DstPtr, SrcPtr}}));
930 GenBinaryFuncName<true> GenName(
"__move_assignment_", DstPtr.
getAlignment(),
931 SrcPtr.getAlignment(), getContext());
932 std::string FuncName = GenName.getName(QT, IsVolatile);
934 *
this, std::array<Address, 2>({{DstPtr, SrcPtr}}));
940 GenDefaultInitializeFuncName GenName(DstAlignment, Ctx);
941 std::string FuncName = GenName.getName(QT, IsVolatile);
943 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
950 GenBinaryFuncName<false> GenName(
"__copy_constructor_", DstAlignment,
952 std::string FuncName = GenName.getName(QT, IsVolatile);
954 GenCopyConstructor(Ctx), FuncName, QT, IsVolatile,
955 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
962 GenBinaryFuncName<true> GenName(
"__move_constructor_", DstAlignment,
964 std::string FuncName = GenName.getName(QT, IsVolatile);
966 GenMoveConstructor(Ctx), FuncName, QT, IsVolatile,
967 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
974 GenBinaryFuncName<false> GenName(
"__copy_assignment_", DstAlignment,
976 std::string FuncName = GenName.getName(QT, IsVolatile);
978 GenCopyAssignment(Ctx), FuncName, QT, IsVolatile,
979 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
986 GenBinaryFuncName<true> GenName(
"__move_assignment_", DstAlignment,
988 std::string FuncName = GenName.getName(QT, IsVolatile);
990 GenMoveAssignment(Ctx), FuncName, QT, IsVolatile,
991 std::array<CharUnits, 2>({{DstAlignment, SrcAlignment}}), CGM);
997 GenDestructorFuncName GenName(
"__destructor_", DstAlignment, Ctx);
998 std::string FuncName = GenName.getName(QT, IsVolatile);
1000 std::array<CharUnits, 1>({{DstAlignment}}), CGM);
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
llvm::PointerType * Int8PtrPtrTy
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
Represents a function declaration or definition.
Other implicit parameter.
A (possibly-)qualified type.
bool isBlockPointerType() const
CodeGenTypes & getTypes()
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
const Type * getTypeForDecl() const
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...
The base class of the type hierarchy.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=CSK_unspecified, Expr *TrailingRequiresClause=nullptr)
QualType getElementType() const
Objects with "hidden" visibility are not seen by the dynamic linker.
const T * getAs() const
Member-template getAs<specific type>'.
llvm::Value * getPointer() const
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
Represents a struct/union/class.
static llvm::Function * getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, std::array< CharUnits, N > Alignments, CodeGenModule &CGM)
One of these records is kept for each identifier that is lexed.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
Represents a member of a struct/union/class.
static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, ASTContext &Ctx)
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
bool isBitField() const
Determines whether this field is a bitfield.
void defaultInitNonTrivialCStructVar(LValue Dst)
CharUnits - This is an opaque type for sizes expressed in character units.
void callCStructDefaultConstructor(LValue Dst)
CharUnits getAlignment() const
Return the alignment of this pointer.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
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...
unsigned getBitWidthValue(const ASTContext &Ctx) const
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void callCStructMoveConstructor(LValue Dst, LValue Src)
PrimitiveDefaultInitializeKind
static std::string getNonTrivialCopyConstructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
ASTContext & getContext() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
void callCStructMoveAssignmentOperator(LValue Dst, LValue Src)
Address getAddress(CodeGenFunction &CGF) const
const T * castAs() const
Member-template castAs<specific type>.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
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, generating it if necessary.
ASTContext & getContext() const
GlobalDecl - represents a global declaration.
void callCStructCopyAssignmentOperator(LValue Dst, LValue Src)
The l-value was considered opaque, so the alignment was determined from a type.
Address CreateBitCast(Address Addr, llvm::Type *Ty, const llvm::Twine &Name="")
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static std::array< Address, N > createNullAddressArray()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
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...
static void callSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, CodeGenFunction &CGF, std::array< Address, N > Addrs)
FunctionArgList - Type for representing both the decl and type of parameters to a function...
QualType withVolatile() const
CGFunctionInfo - Class to encapsulate the information about a function definition.
This class organizes the cross-function state that is used while generating LLVM code.
Dataflow Directional Tag Classes.
void callCStructDestructor(LValue Dst)
llvm::Function * getNonTrivialCStructDefaultConstructor(CodeGenModule &GCM, CharUnits DstAlignment, bool IsVolatile, QualType QT)
Returns the default constructor for a C struct with non-trivially copyable fields, generating it if necessary.
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, generating it if necessary.
llvm::Module & getModule() const
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::PointerType * Int8PtrTy
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
static Destroyer destroyNonTrivialCStruct
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
void callCStructCopyConstructor(LValue Dst, LValue Src)
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
TranslationUnitDecl * getTranslationUnitDecl() const
static std::string getNonTrivialDestructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)
static llvm::Constant * getNullForVariable(Address addr)
Given the address of a variable of pointer type, find the correct null to store into it...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
LValue - This represents an lvalue references.
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::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
Represents the canonical version of C arrays with a specified constant size.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr *> VL, ArrayRef< Expr *> PL, ArrayRef< Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.