;
36using namespaceCodeGen;
43classConstExprEmitter;
46llvm::Type *Ty = CGM.
CharTy;
48Ty = llvm::ArrayType::get(Ty, PadSize.
getQuantity());
50 returnllvm::Constant::getNullValue(Ty);
52 returnllvm::UndefValue::get(Ty);
55structConstantAggregateBuilderUtils {
58ConstantAggregateBuilderUtils(
CodeGenModule&CGM) : CGM(CGM) {}
60 CharUnitsgetAlignment(
constllvm::Constant *
C)
const{
69 CharUnitsgetSize(
constllvm::Constant *
C)
const{
70 returngetSize(
C->getType());
73llvm::Constant *getPadding(
CharUnitsPadSize)
const{
74return ::getPadding(CGM, PadSize);
77llvm::Constant *getZeroes(
CharUnitsZeroSize)
const{
79 returnllvm::ConstantAggregateZero::get(Ty);
85classConstantAggregateBuilder :
privateConstantAggregateBuilderUtils {
104 boolNaturalLayout =
true;
106 boolsplit(
size_tIndex,
CharUnitsHint);
107std::optional<size_t> splitAt(
CharUnitsPos);
113 boolNaturalLayout, llvm::Type *DesiredTy,
114 boolAllowOversized);
118: ConstantAggregateBuilderUtils(CGM) {}
125 booladd(llvm::Constant *
C,
CharUnitsOffset,
boolAllowOverwrite);
128 booladdBits(llvm::APInt Bits, uint64_t OffsetInBits,
boolAllowOverwrite);
132 voidcondense(
CharUnitsOffset, llvm::Type *DesiredTy);
139llvm::Constant *build(llvm::Type *DesiredTy,
boolAllowOversized)
const{
141NaturalLayout, DesiredTy, AllowOversized);
145template<
typenameContainer,
typename Range= std::initializer_list<
146 typenameContainer::value_type>>
147static voidreplace(Container &
C,
size_tBeginOff,
size_tEndOff,
RangeVals) {
148assert(BeginOff <= EndOff &&
"invalid replacement range");
149llvm::replace(
C,
C.begin() + BeginOff,
C.begin() + EndOff, Vals);
152boolConstantAggregateBuilder::add(llvm::Constant *
C,
CharUnitsOffset,
153 boolAllowOverwrite) {
155 if(Offset >= Size) {
158 if(AlignedSize > Offset || Offset.alignTo(Align) != Offset)
159NaturalLayout =
false;
160 else if(AlignedSize < Offset) {
161Elems.push_back(getPadding(Offset - Size));
162Offsets.push_back(Size);
164Elems.push_back(
C);
165Offsets.push_back(Offset);
166 Size= Offset + getSize(
C);
171std::optional<size_t> FirstElemToReplace = splitAt(Offset);
172 if(!FirstElemToReplace)
176std::optional<size_t> LastElemToReplace = splitAt(Offset + CSize);
177 if(!LastElemToReplace)
180assert((FirstElemToReplace == LastElemToReplace || AllowOverwrite) &&
181 "unexpectedly overwriting field");
183replace(Elems, *FirstElemToReplace, *LastElemToReplace, {
C});
184replace(Offsets, *FirstElemToReplace, *LastElemToReplace, {Offset});
185 Size= std::max(Size, Offset + CSize);
186NaturalLayout =
false;
190boolConstantAggregateBuilder::addBits(llvm::APInt Bits, uint64_t OffsetInBits,
191 boolAllowOverwrite) {
197 unsignedOffsetWithinChar = OffsetInBits % CharWidth;
205 unsignedWantedBits =
206std::min((uint64_t)Bits.getBitWidth(), CharWidth - OffsetWithinChar);
210llvm::APInt BitsThisChar = Bits;
211 if(BitsThisChar.getBitWidth() < CharWidth)
212BitsThisChar = BitsThisChar.zext(CharWidth);
216 int Shift= Bits.getBitWidth() - CharWidth + OffsetWithinChar;
218BitsThisChar.lshrInPlace(Shift);
220BitsThisChar = BitsThisChar.shl(-Shift);
222BitsThisChar = BitsThisChar.shl(OffsetWithinChar);
224 if(BitsThisChar.getBitWidth() > CharWidth)
225BitsThisChar = BitsThisChar.trunc(CharWidth);
227 if(WantedBits == CharWidth) {
230OffsetInChars, AllowOverwrite);
235std::optional<size_t> FirstElemToUpdate = splitAt(OffsetInChars);
236 if(!FirstElemToUpdate)
238std::optional<size_t> LastElemToUpdate =
240 if(!LastElemToUpdate)
242assert(*LastElemToUpdate - *FirstElemToUpdate < 2 &&
243 "should have at most one element covering one byte");
246llvm::APInt UpdateMask(CharWidth, 0);
248UpdateMask.setBits(CharWidth - OffsetWithinChar - WantedBits,
249CharWidth - OffsetWithinChar);
251UpdateMask.setBits(OffsetWithinChar, OffsetWithinChar + WantedBits);
252BitsThisChar &= UpdateMask;
254 if(*FirstElemToUpdate == *LastElemToUpdate ||
255Elems[*FirstElemToUpdate]->isNullValue() ||
256isa<llvm::UndefValue>(Elems[*FirstElemToUpdate])) {
259OffsetInChars,
true);
261llvm::Constant *&ToUpdate = Elems[*FirstElemToUpdate];
264 auto*CI = dyn_cast<llvm::ConstantInt>(ToUpdate);
269assert(CI->getBitWidth() == CharWidth &&
"splitAt failed");
270assert((!(CI->getValue() & UpdateMask) || AllowOverwrite) &&
271 "unexpectedly overwriting bitfield");
272BitsThisChar |= (CI->getValue() & ~UpdateMask);
273ToUpdate = llvm::ConstantInt::get(CGM.
getLLVMContext(), BitsThisChar);
278 if(WantedBits == Bits.getBitWidth())
283Bits.lshrInPlace(WantedBits);
284Bits = Bits.trunc(Bits.getBitWidth() - WantedBits);
287OffsetWithinChar = 0;
297std::optional<size_t> ConstantAggregateBuilder::splitAt(
CharUnitsPos) {
299 returnOffsets.size();
302 autoFirstAfterPos = llvm::upper_bound(Offsets, Pos);
303 if(FirstAfterPos == Offsets.begin())
307 size_tLastAtOrBeforePosIndex = FirstAfterPos - Offsets.begin() - 1;
308 if(Offsets[LastAtOrBeforePosIndex] == Pos)
309 returnLastAtOrBeforePosIndex;
312 if(Offsets[LastAtOrBeforePosIndex] +
313getSize(Elems[LastAtOrBeforePosIndex]) <= Pos)
314 returnLastAtOrBeforePosIndex + 1;
317 if(!split(LastAtOrBeforePosIndex, Pos))
325boolConstantAggregateBuilder::split(
size_tIndex,
CharUnitsHint) {
326NaturalLayout =
false;
327llvm::Constant *
C= Elems[Index];
330 if(
auto*CA = dyn_cast<llvm::ConstantAggregate>(
C)) {
333replace(Elems, Index, Index + 1,
334llvm::map_range(llvm::seq(0u, CA->getNumOperands()),
335[&](
unsignedOp) { return CA->getOperand(Op); }));
336 if(isa<llvm::ArrayType>(CA->getType()) ||
337isa<llvm::VectorType>(CA->getType())) {
340llvm::GetElementPtrInst::getTypeAtIndex(CA->getType(), (uint64_t)0);
343Offsets, Index, Index + 1,
344llvm::map_range(llvm::seq(0u, CA->getNumOperands()),
345[&](
unsignedOp) { return Offset + Op * ElemSize; }));
348 auto*ST = cast<llvm::StructType>(CA->getType());
349 constllvm::StructLayout *Layout =
351replace(Offsets, Index, Index + 1,
353llvm::seq(0u, CA->getNumOperands()), [&](
unsignedOp) {
354return Offset + CharUnits::fromQuantity(
355Layout->getElementOffset(Op));
361 if(
auto*CDS = dyn_cast<llvm::ConstantDataSequential>(
C)) {
365 CharUnitsElemSize = getSize(CDS->getElementType());
366replace(Elems, Index, Index + 1,
367llvm::map_range(llvm::seq(0u, CDS->getNumElements()),
368[&](
unsignedElem) {
369return CDS->getElementAsConstant(Elem);
371replace(Offsets, Index, Index + 1,
373llvm::seq(0u, CDS->getNumElements()),
374[&](
unsignedElem) { return Offset + Elem * ElemSize; }));
378 if(isa<llvm::ConstantAggregateZero>(
C)) {
381assert(Hint > Offset && Hint < Offset + ElemSize &&
"nothing to split");
382replace(Elems, Index, Index + 1,
383{getZeroes(Hint - Offset), getZeroes(Offset + ElemSize - Hint)});
384replace(Offsets, Index, Index + 1, {Offset, Hint});
388 if(isa<llvm::UndefValue>(
C)) {
390replace(Elems, Index, Index + 1, {});
391replace(Offsets, Index, Index + 1, {});
402staticllvm::Constant *
403EmitArrayConstant(
CodeGenModule&CGM, llvm::ArrayType *DesiredType,
404llvm::Type *CommonElementType, uint64_t ArrayBound,
406llvm::Constant *Filler);
408llvm::Constant *ConstantAggregateBuilder::buildFrom(
411 boolNaturalLayout, llvm::Type *DesiredTy,
boolAllowOversized) {
412ConstantAggregateBuilderUtils Utils(CGM);
415 returnllvm::UndefValue::get(DesiredTy);
417 autoOffset = [&](
size_tI) {
returnOffsets[I] - StartOffset; };
421 if(llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(DesiredTy)) {
422assert(!AllowOversized &&
"oversized array emission not supported");
424 boolCanEmitArray =
true;
425llvm::Type *CommonType = Elems[0]->getType();
426llvm::Constant *Filler = llvm::Constant::getNullValue(CommonType);
427 CharUnitsElemSize = Utils.getSize(ATy->getElementType());
429 for(
size_tI = 0; I != Elems.size(); ++I) {
431 if(Elems[I]->isNullValue())
435 if(Elems[I]->getType() != CommonType ||
436Offset(I) % ElemSize != 0) {
437CanEmitArray =
false;
440ArrayElements.resize(Offset(I) / ElemSize + 1, Filler);
441ArrayElements.back() = Elems[I];
445 returnEmitArrayConstant(CGM, ATy, CommonType, ATy->getNumElements(),
446ArrayElements, Filler);
455 CharUnitsDesiredSize = Utils.getSize(DesiredTy);
456 if(Size > DesiredSize) {
457assert(AllowOversized &&
"Elems are oversized");
463 for(llvm::Constant *
C: Elems)
464Align = std::max(Align, Utils.getAlignment(
C));
469 boolPacked =
false;
472 if(DesiredSize < AlignedSize || DesiredSize.
alignTo(Align) != DesiredSize) {
474NaturalLayout =
false;
476}
else if(DesiredSize > AlignedSize) {
479UnpackedElemStorage.assign(Elems.begin(), Elems.end());
480UnpackedElemStorage.push_back(Utils.getPadding(DesiredSize - Size));
481UnpackedElems = UnpackedElemStorage;
488 if(!NaturalLayout) {
490 for(
size_tI = 0; I != Elems.size(); ++I) {
491 CharUnitsAlign = Utils.getAlignment(Elems[I]);
494assert(DesiredOffset >= SizeSoFar &&
"elements out of order");
496 if(DesiredOffset != NaturalOffset)
498 if(DesiredOffset != SizeSoFar)
499PackedElems.push_back(Utils.getPadding(DesiredOffset - SizeSoFar));
500PackedElems.push_back(Elems[I]);
501SizeSoFar = DesiredOffset + Utils.getSize(Elems[I]);
506assert(SizeSoFar <= DesiredSize &&
507 "requested size is too small for contents");
508 if(SizeSoFar < DesiredSize)
509PackedElems.push_back(Utils.getPadding(DesiredSize - SizeSoFar));
513llvm::StructType *STy = llvm::ConstantStruct::getTypeForElements(
514CGM.
getLLVMContext(), Packed ? PackedElems : UnpackedElems, Packed);
518 if(llvm::StructType *DesiredSTy = dyn_cast<llvm::StructType>(DesiredTy)) {
519 if(DesiredSTy->isLayoutIdentical(STy))
523 returnllvm::ConstantStruct::get(STy, Packed ? PackedElems : UnpackedElems);
526voidConstantAggregateBuilder::condense(
CharUnitsOffset,
527llvm::Type *DesiredTy) {
530std::optional<size_t> FirstElemToReplace = splitAt(Offset);
531 if(!FirstElemToReplace)
533 size_t First= *FirstElemToReplace;
535std::optional<size_t> LastElemToReplace = splitAt(Offset + Size);
536 if(!LastElemToReplace)
538 size_t Last= *LastElemToReplace;
544 if(Length == 1 && Offsets[
First] == Offset &&
545getSize(Elems[
First]) == Size) {
548 auto*STy = dyn_cast<llvm::StructType>(DesiredTy);
549 if(STy && STy->getNumElements() == 1 &&
550STy->getElementType(0) == Elems[
First]->getType())
551Elems[
First] = llvm::ConstantStruct::get(STy, Elems[
First]);
555llvm::Constant *Replacement = buildFrom(
557 ArrayRef(Offsets).slice(
First, Length), Offset, getSize(DesiredTy),
558 false, DesiredTy,
false);
559replace(Elems,
First,
Last, {Replacement});
560replace(Offsets,
First,
Last, {Offset});
567classConstStructBuilder {
570ConstantAggregateBuilder &Builder;
580ConstantAggregateBuilder &Const,
CharUnitsOffset,
585ConstantAggregateBuilder &Builder,
CharUnitsStartOffset)
587StartOffset(StartOffset) {}
589 boolAppendField(
const FieldDecl*Field, uint64_t FieldOffset,
590llvm::Constant *InitExpr,
boolAllowOverwrite =
false);
592 boolAppendBytes(
CharUnitsFieldOffsetInChars, llvm::Constant *InitCst,
593 boolAllowOverwrite =
false);
595 boolAppendBitField(
const FieldDecl*Field, uint64_t FieldOffset,
596llvm::Constant *InitExpr,
boolAllowOverwrite =
false);
598 boolBuild(
const InitListExpr*ILE,
boolAllowOverwrite);
601 boolDoZeroInitPadding(
const ASTRecordLayout&Layout,
unsignedFieldNo,
602 const FieldDecl&Field,
boolAllowOverwrite,
603 CharUnits&SizeSoFar,
bool&ZeroFieldSize);
604 boolDoZeroInitPadding(
const ASTRecordLayout&Layout,
boolAllowOverwrite,
609boolConstStructBuilder::AppendField(
610 const FieldDecl*Field, uint64_t FieldOffset, llvm::Constant *InitCst,
611 boolAllowOverwrite) {
616 returnAppendBytes(FieldOffsetInChars, InitCst, AllowOverwrite);
619boolConstStructBuilder::AppendBytes(
CharUnitsFieldOffsetInChars,
620llvm::Constant *InitCst,
621 boolAllowOverwrite) {
622 returnBuilder.add(InitCst, StartOffset + FieldOffsetInChars, AllowOverwrite);
625boolConstStructBuilder::AppendBitField(
const FieldDecl*Field,
626uint64_t FieldOffset, llvm::Constant *
C,
627 boolAllowOverwrite) {
629llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(
C);
635llvm::Type *LoadType =
637llvm::Constant *FoldedConstant = llvm::ConstantFoldLoadFromConst(
639CI = dyn_cast_if_present<llvm::ConstantInt>(FoldedConstant);
647llvm::APInt FieldValue = CI->getValue();
653 if(Info.
Size> FieldValue.getBitWidth())
654FieldValue = FieldValue.zext(Info.
Size);
657 if(Info.
Size< FieldValue.getBitWidth())
658FieldValue = FieldValue.trunc(Info.
Size);
660 returnBuilder.addBits(FieldValue,
666ConstantAggregateBuilder &Const,
670 returnConstStructBuilder::UpdateStruct(
Emitter, Const, Offset, Updater);
672 autoCAT =
Emitter.CGM.getContext().getAsConstantArrayType(
Type);
675 QualTypeElemType = CAT->getElementType();
676 CharUnitsElemSize =
Emitter.CGM.getContext().getTypeSizeInChars(ElemType);
677llvm::Type *ElemTy =
Emitter.CGM.getTypes().ConvertTypeForMem(ElemType);
679llvm::Constant *FillC =
nullptr;
681 if(!isa<NoInitExpr>(Filler)) {
682FillC =
Emitter.tryEmitAbstractForMemory(Filler, ElemType);
688 unsignedNumElementsToUpdate =
689FillC ? CAT->getZExtSize() : Updater->
getNumInits();
690 for(
unsignedI = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) {
692 if(I < Updater->getNumInits())
695 if(!
Init&& FillC) {
696 if(!
Const.add(FillC, Offset,
true))
698}
else if(!
Init|| isa<NoInitExpr>(
Init)) {
700}
else if(
const auto*ChildILE = dyn_cast<InitListExpr>(
Init)) {
701 if(!EmitDesignatedInitUpdater(
Emitter, Const, Offset, ElemType,
705 Const.condense(Offset, ElemTy);
707llvm::Constant *Val =
Emitter.tryEmitPrivateForMemory(
Init, ElemType);
708 if(!
Const.add(Val, Offset,
true))
716boolConstStructBuilder::Build(
const InitListExpr*ILE,
boolAllowOverwrite) {
720 unsignedFieldNo = -1;
721 unsignedElementNo = 0;
726 if(
auto*CXXRD = dyn_cast<CXXRecordDecl>(RD))
727 if(CXXRD->getNumBases())
731 boolZeroFieldSize =
false;
743 if(
Field->isUnnamedBitField())
749 if(ElementNo < ILE->getNumInits())
751 if(isa_and_nonnull<NoInitExpr>(
Init)) {
752 if(ZeroInitPadding &&
753!DoZeroInitPadding(Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
767 if(ZeroInitPadding &&
768!DoZeroInitPadding(Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
775 if(AllowOverwrite &&
776(
Field->getType()->isArrayType() ||
Field->getType()->isRecordType())) {
777 if(
auto*SubILE = dyn_cast<InitListExpr>(
Init)) {
780 if(!EmitDesignatedInitUpdater(
Emitter, Builder, StartOffset + Offset,
781 Field->getType(), SubILE))
785Builder.condense(StartOffset + Offset,
791llvm::Constant *EltInit =
797 if(ZeroInitPadding && ZeroFieldSize)
801 if(!
Field->isBitField()) {
803 if(!AppendField(Field, Layout.
getFieldOffset(FieldNo), EltInit,
808 if(
Field->hasAttr<NoUniqueAddressAttr>())
809AllowOverwrite =
true;
812 if(!AppendBitField(Field, Layout.
getFieldOffset(FieldNo), EltInit,
818 if(ZeroInitPadding && !DoZeroInitPadding(Layout, AllowOverwrite, SizeSoFar))
827:
Decl(
Decl), Offset(Offset), Index(Index) {
834 bool operator<(
constBaseInfo &O)
const{
returnOffset < O.Offset; }
844 if(
const CXXRecordDecl*CD = dyn_cast<CXXRecordDecl>(RD)) {
847llvm::Constant *VTableAddressPoint =
851VTableAddressPoint =
Emitter.tryEmitConstantSignedPointer(
852VTableAddressPoint, *Authentication);
853 if(!VTableAddressPoint)
856 if(!AppendBytes(Offset, VTableAddressPoint))
863Bases.reserve(CD->getNumBases());
866BaseEnd = CD->bases_end();
Base!= BaseEnd; ++
Base, ++BaseNo) {
867assert(!
Base->isVirtual() &&
"should not have virtual bases here");
870Bases.push_back(BaseInfo(BD, BaseOffset, BaseNo));
872llvm::stable_sort(Bases);
874 for(
unsignedI = 0, N = Bases.size(); I != N; ++I) {
875BaseInfo &
Base= Bases[I];
879VTableClass, Offset +
Base.Offset);
883 unsignedFieldNo = 0;
886 boolZeroFieldSize =
false;
889 boolAllowOverwrite =
false;
891FieldEnd = RD->
field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
897 if(
Field->isUnnamedBitField() ||
904llvm::Constant *EltInit =
905 Emitter.tryEmitPrivateForMemory(FieldValue,
Field->getType());
909 if(ZeroInitPadding) {
910 if(!DoZeroInitPadding(Layout, FieldNo, **Field, AllowOverwrite,
911SizeSoFar, ZeroFieldSize))
918 if(!
Field->isBitField()) {
920 if(!AppendField(*Field, Layout.
getFieldOffset(FieldNo) + OffsetBits,
921EltInit, AllowOverwrite))
925 if(
Field->hasAttr<NoUniqueAddressAttr>())
926AllowOverwrite =
true;
929 if(!AppendBitField(*Field, Layout.
getFieldOffset(FieldNo) + OffsetBits,
930EltInit, AllowOverwrite))
934 if(ZeroInitPadding && !DoZeroInitPadding(Layout, AllowOverwrite, SizeSoFar))
940boolConstStructBuilder::DoZeroInitPadding(
942 boolAllowOverwrite,
CharUnits&SizeSoFar,
bool&ZeroFieldSize) {
945 if(SizeSoFar < StartOffset)
946 if(!AppendBytes(SizeSoFar, getPadding(CGM, StartOffset - SizeSoFar),
950 if(!
Field.isBitField()) {
952SizeSoFar = StartOffset + FieldSize;
953ZeroFieldSize = FieldSize.
isZero();
963ZeroFieldSize = Info.
Size== 0;
968boolConstStructBuilder::DoZeroInitPadding(
const ASTRecordLayout&Layout,
972 if(SizeSoFar < TotalSize)
973 if(!AppendBytes(SizeSoFar, getPadding(CGM, TotalSize - SizeSoFar),
976SizeSoFar = TotalSize;
980llvm::Constant *ConstStructBuilder::Finalize(
QualType Type) {
993 if(!Builder.Build(ILE,
false))
996 returnBuilder.Finalize(ValTy);
1010 returnBuilder.Finalize(ValTy);
1014ConstantAggregateBuilder &Const,
1017 returnConstStructBuilder(
Emitter, Const, Offset)
1018.Build(Updater,
true);
1030 if(llvm::GlobalVariable *Addr =
1038assert(!
E->isFileScope() &&
1039 "file-scope compound literal did not have constant initializer!");
1043 autoGV =
newllvm::GlobalVariable(
1046llvm::GlobalValue::InternalLinkage,
C,
".compoundliteral",
nullptr,
1047llvm::GlobalVariable::NotThreadLocal,
1055staticllvm::Constant *
1056EmitArrayConstant(
CodeGenModule&CGM, llvm::ArrayType *DesiredType,
1057llvm::Type *CommonElementType, uint64_t ArrayBound,
1059llvm::Constant *Filler) {
1061 uint64_tNonzeroLength = ArrayBound;
1062 if(Elements.size() < NonzeroLength && Filler->isNullValue())
1063NonzeroLength = Elements.size();
1064 if(NonzeroLength == Elements.size()) {
1065 while(NonzeroLength > 0 && Elements[NonzeroLength - 1]->isNullValue())
1069 if(NonzeroLength == 0)
1070 returnllvm::ConstantAggregateZero::get(DesiredType);
1073 uint64_tTrailingZeroes = ArrayBound - NonzeroLength;
1074 if(TrailingZeroes >= 8) {
1075assert(Elements.size() >= NonzeroLength &&
1076 "missing initializer for non-zero element");
1080 if(CommonElementType && NonzeroLength >= 8) {
1081llvm::Constant *Initial = llvm::ConstantArray::get(
1082llvm::ArrayType::get(CommonElementType, NonzeroLength),
1083 ArrayRef(Elements).take_front(NonzeroLength));
1085Elements[0] = Initial;
1087Elements.resize(NonzeroLength + 1);
1091CommonElementType ? CommonElementType : DesiredType->getElementType();
1092FillerType = llvm::ArrayType::get(FillerType, TrailingZeroes);
1093Elements.back() = llvm::ConstantAggregateZero::get(FillerType);
1094CommonElementType =
nullptr;
1095}
else if(Elements.size() != ArrayBound) {
1097Elements.resize(ArrayBound, Filler);
1098 if(Filler->getType() != CommonElementType)
1099CommonElementType =
nullptr;
1103 if(CommonElementType)
1104 returnllvm::ConstantArray::get(
1105llvm::ArrayType::get(CommonElementType, ArrayBound), Elements);
1109Types.reserve(Elements.size());
1110 for(llvm::Constant *Elt : Elements)
1111Types.push_back(Elt->getType());
1112llvm::StructType *SType =
1114 returnllvm::ConstantStruct::get(SType, Elements);
1123classConstExprEmitter
1127llvm::LLVMContext &VMContext;
1130: CGM(emitter.CGM),
Emitter(emitter), VMContext(CGM.getLLVMContext()) {
1137llvm::Constant *VisitStmt(
const Stmt*S,
QualType T) {
return nullptr; }
1140 if(llvm::Constant *Result =
Emitter.tryEmitConstantExpr(CE))
1157 return Visit(
GE->getResultExpr(),
T);
1166 return Visit(
E->getInitializer(),
T);
1169llvm::Constant *ProduceIntToIntCast(
const Expr*
E,
QualTypeDestType) {
1173 if(llvm::Constant *
C=
Visit(
E, FromType))
1174 if(
auto*CI = dyn_cast<llvm::ConstantInt>(
C)) {
1177 if(DstWidth == SrcWidth)
1180? CI->getValue().sextOrTrunc(DstWidth)
1181: CI->getValue().zextOrTrunc(DstWidth);
1188 if(
const auto*ECE = dyn_cast<ExplicitCastExpr>(
E))
1190 const Expr*subExpr =
E->getSubExpr();
1192 switch(
E->getCastKind()) {
1196 "Destination type is not union type!");
1198 autofield =
E->getTargetUnionField();
1200 auto C=
Emitter.tryEmitPrivateForMemory(subExpr, field->getType());
1201 if(!
C)
return nullptr;
1203 autodestTy = ConvertType(destType);
1204 if(
C->getType() == destTy)
return C;
1210Elts.push_back(
C);
1211Types.push_back(
C->getType());
1212 unsignedCurSize = CGM.
getDataLayout().getTypeAllocSize(
C->getType());
1213 unsignedTotalSize = CGM.
getDataLayout().getTypeAllocSize(destTy);
1215assert(CurSize <= TotalSize &&
"Union size mismatch!");
1216 if(
unsignedNumPadBytes = TotalSize - CurSize) {
1217llvm::Constant *Padding =
1219Elts.push_back(Padding);
1220Types.push_back(Padding->getType());
1223llvm::StructType *STy = llvm::StructType::get(VMContext, Types,
false);
1224 returnllvm::ConstantStruct::get(STy, Elts);
1227 caseCK_AddressSpaceConversion: {
1229 if(!
C)
return nullptr;
1232llvm::Type *destTy = ConvertType(
E->
getType());
1237 caseCK_LValueToRValue: {
1242 if(
const auto*
E=
1243dyn_cast<CompoundLiteralExpr>(subExpr->
IgnoreParens()))
1244 return Visit(
E->getInitializer(), destType);
1248 caseCK_AtomicToNonAtomic:
1249 caseCK_NonAtomicToAtomic:
1251 caseCK_ConstructorConversion:
1252 return Visit(subExpr, destType);
1254 caseCK_ArrayToPointerDecay:
1255 if(
const auto*S = dyn_cast<StringLiteral>(subExpr))
1258 caseCK_NullToPointer:
1259 if(
Visit(subExpr, destType))
1263 caseCK_IntToOCLSampler:
1264llvm_unreachable(
"global sampler variables are not generated");
1266 caseCK_IntegralCast:
1267 returnProduceIntToIntCast(subExpr, destType);
1269 caseCK_Dependent: llvm_unreachable(
"saw dependent cast!");
1271 caseCK_BuiltinFnToFnPtr:
1272llvm_unreachable(
"builtin functions are handled elsewhere");
1274 caseCK_ReinterpretMemberPointer:
1275 caseCK_DerivedToBaseMemberPointer:
1276 caseCK_BaseToDerivedMemberPointer: {
1278 if(!
C)
return nullptr;
1283 caseCK_ObjCObjectLValueCast:
1284 caseCK_ARCProduceObject:
1285 caseCK_ARCConsumeObject:
1286 caseCK_ARCReclaimReturnedObject:
1287 caseCK_ARCExtendBlockObject:
1288 caseCK_CopyAndAutoreleaseBlockObject:
1296 caseCK_LValueBitCast:
1297 caseCK_LValueToRValueBitCast:
1298 caseCK_NullToMemberPointer:
1299 caseCK_UserDefinedConversion:
1300 caseCK_CPointerToObjCPointerCast:
1301 caseCK_BlockPointerToObjCPointerCast:
1302 caseCK_AnyPointerToBlockPointerCast:
1303 caseCK_FunctionToPointerDecay:
1304 caseCK_BaseToDerived:
1305 caseCK_DerivedToBase:
1306 caseCK_UncheckedDerivedToBase:
1307 caseCK_MemberPointerToBoolean:
1308 caseCK_VectorSplat:
1309 caseCK_FloatingRealToComplex:
1310 caseCK_FloatingComplexToReal:
1311 caseCK_FloatingComplexToBoolean:
1312 caseCK_FloatingComplexCast:
1313 caseCK_FloatingComplexToIntegralComplex:
1314 caseCK_IntegralRealToComplex:
1315 caseCK_IntegralComplexToReal:
1316 caseCK_IntegralComplexToBoolean:
1317 caseCK_IntegralComplexCast:
1318 caseCK_IntegralComplexToFloatingComplex:
1319 caseCK_PointerToIntegral:
1320 caseCK_PointerToBoolean:
1321 caseCK_BooleanToSignedIntegral:
1322 caseCK_IntegralToPointer:
1323 caseCK_IntegralToBoolean:
1324 caseCK_IntegralToFloating:
1325 caseCK_FloatingToIntegral:
1326 caseCK_FloatingToBoolean:
1327 caseCK_FloatingCast:
1328 caseCK_FloatingToFixedPoint:
1329 caseCK_FixedPointToFloating:
1330 caseCK_FixedPointCast:
1331 caseCK_FixedPointToBoolean:
1332 caseCK_FixedPointToIntegral:
1333 caseCK_IntegralToFixedPoint:
1334 caseCK_ZeroToOCLOpaqueType:
1336 caseCK_HLSLVectorTruncation:
1337 caseCK_HLSLArrayRValue:
1340llvm_unreachable(
"Invalid CastKind");
1351 return Visit(
E->getSubExpr(),
T);
1362llvm::APFloat Result =
1364llvm::RoundingMode RM =
1366 if(RM == llvm::RoundingMode::Dynamic)
1367RM = llvm::RoundingMode::NearestTiesToEven;
1368Result.convertFromAPInt(
Value,
Value.isSigned(), RM);
1377assert(CAT &&
"can't emit array init for non-constant-bound array");
1379 const uint64_tNumElements = CAT->getZExtSize();
1380 for(
const auto*
Init: ILE->
inits()) {
1381 if(
const auto*Embed =
1382dyn_cast<EmbedExpr>(
Init->IgnoreParenImpCasts())) {
1383NumInitElements += Embed->getDataElementCount() - 1;
1384 if(NumInitElements > NumElements) {
1385NumInitElements = NumElements;
1393 uint64_tNumInitableElts = std::min<uint64_t>(NumInitElements, NumElements);
1395 QualTypeEltType = CAT->getElementType();
1398llvm::Constant *fillC =
nullptr;
1400fillC =
Emitter.tryEmitAbstractForMemory(filler, EltType);
1407 if(fillC && fillC->isNullValue())
1408Elts.reserve(NumInitableElts + 1);
1410Elts.reserve(NumElements);
1412llvm::Type *CommonElementType =
nullptr;
1413 autoEmit = [&](
const Expr*
Init,
unsignedArrayIndex) {
1414llvm::Constant *
C=
nullptr;
1418 if(ArrayIndex == 0)
1419CommonElementType =
C->getType();
1420 else if(
C->getType() != CommonElementType)
1421CommonElementType =
nullptr;
1422Elts.push_back(
C);
1426 unsignedArrayIndex = 0;
1427 QualTypeDestTy = CAT->getElementType();
1428 for(
unsignedi = 0; i < ILE->
getNumInits(); ++i) {
1430 if(
auto*EmbedS = dyn_cast<EmbedExpr>(
Init->IgnoreParenImpCasts())) {
1434llvm::Constant *
C;
1435 for(
unsignedI = EmbedS->getStartingElementPos(),
1436N = EmbedS->getDataElementCount();
1437I != EmbedS->getStartingElementPos() + N; ++I) {
1442 C=
Emitter.tryEmitPrivateForMemory(
1443withDestType(CGM.
getContext(),
Init, EmbedS->getType(), DestTy,
1449Elts.push_back(
C);
1452 if((ArrayIndex - EmbedS->getDataElementCount()) == 0)
1453CommonElementType =
C->getType();
1454 else if(
C->getType() != CommonElementType)
1455CommonElementType =
nullptr;
1457 if(!Emit(
Init, ArrayIndex))
1463llvm::ArrayType *Desired =
1465 returnEmitArrayConstant(CGM, Desired, CommonElementType, NumElements, Elts,
1469llvm::Constant *EmitRecordInitialization(
const InitListExpr*ILE,
1471 returnConstStructBuilder::BuildStruct(
Emitter, ILE,
T);
1484 returnEmitArrayInitialization(ILE,
T);
1487 returnEmitRecordInitialization(ILE,
T);
1495 auto C=
Visit(
E->getBase(), destType);
1499ConstantAggregateBuilder
Const(CGM);
1507 boolHasFlexibleArray =
false;
1509HasFlexibleArray = RT->getDecl()->hasFlexibleArrayMember();
1510 return Const.build(ValTy, HasFlexibleArray);
1515 if(!
E->getConstructor()->isTrivial())
1519 if(
E->getNumArgs()) {
1520assert(
E->getNumArgs() == 1 &&
"trivial ctor with > 1 argument");
1521assert(
E->getConstructor()->isCopyOrMoveConstructor() &&
1522 "trivial ctor has argument but isn't a copy/move ctor");
1524 const Expr*Arg =
E->getArg(0);
1526 "argument to copy ctor is of wrong type");
1530 if(
const auto*MTE = dyn_cast<MaterializeTemporaryExpr>(Arg))
1531 return Visit(MTE->getSubExpr(), Ty);
1551assert(CAT &&
"String data not of constant array type!");
1556 returnllvm::ConstantDataArray::getString(VMContext, Str,
false);
1560 return Visit(
E->getSubExpr(),
T);
1564 if(llvm::Constant *
C=
Visit(
U->getSubExpr(),
T))
1565 if(
auto*CI = dyn_cast<llvm::ConstantInt>(
C))
1566 returnllvm::ConstantInt::get(CGM.
getLLVMContext(), -CI->getValue());
1571 return Visit(
E->getSelectedExpr(),
T);
1582llvm::Constant *ConstantEmitter::validateAndPopAbstract(llvm::Constant *
C,
1583AbstractState saved) {
1584Abstract = saved.OldValue;
1586assert(saved.OldPlaceholdersSize == PlaceholderAddresses.size() &&
1587 "created a placeholder while doing an abstract emission?");
1596 autostate = pushAbstract();
1598 returnvalidateAndPopAbstract(
C, state);
1603 autostate = pushAbstract();
1605 returnvalidateAndPopAbstract(
C, state);
1610 autostate = pushAbstract();
1612 returnvalidateAndPopAbstract(
C, state);
1628 autostate = pushAbstract();
1630 C= validateAndPopAbstract(
C, state);
1633 "internal error: could not emit constant value \"abstractly\"");
1642 boolEnablePtrAuthFunctionTypeDiscrimination) {
1643 autostate = pushAbstract();
1645 tryEmitPrivate(value, destType, EnablePtrAuthFunctionTypeDiscrimination);
1646 C= validateAndPopAbstract(
C, state);
1649 "internal error: could not emit constant value \"abstractly\"");
1656initializeNonAbstract(
D.getType().getAddressSpace());
1663initializeNonAbstract(destAddrSpace);
1670initializeNonAbstract(destAddrSpace);
1672assert(
C&&
"couldn't emit constant value non-abstractly?");
1677assert(!Abstract &&
"cannot get current address for abstract constant");
1684llvm::GlobalValue::PrivateLinkage,
1688llvm::GlobalVariable::NotThreadLocal,
1691PlaceholderAddresses.push_back(std::make_pair(
nullptr, global));
1697llvm::GlobalValue *placeholder) {
1698assert(!PlaceholderAddresses.empty());
1699assert(PlaceholderAddresses.back().first ==
nullptr);
1700assert(PlaceholderAddresses.back().second == placeholder);
1701PlaceholderAddresses.back().first = signal;
1705 structReplacePlaceholders {
1709llvm::Constant *
Base;
1710llvm::Type *BaseValueTy =
nullptr;
1713llvm::DenseMap<llvm::Constant*, llvm::GlobalVariable*> PlaceholderAddresses;
1716llvm::DenseMap<llvm::GlobalVariable*, llvm::Constant*> Locations;
1724ReplacePlaceholders(
CodeGenModule&CGM, llvm::Constant *base,
1725 ArrayRef<std::pair<llvm::Constant*,
1726llvm::GlobalVariable*>> addresses)
1727: CGM(CGM),
Base(base),
1728PlaceholderAddresses(addresses.begin(), addresses.end()) {
1731 voidreplaceInInitializer(llvm::Constant *init) {
1733BaseValueTy = init->getType();
1736Indices.push_back(0);
1737IndexValues.push_back(
nullptr);
1740findLocations(init);
1743assert(IndexValues.size() == Indices.size() &&
"mismatch");
1744assert(Indices.size() == 1 &&
"didn't pop all indices");
1747assert(Locations.size() == PlaceholderAddresses.size() &&
1748 "missed a placeholder?");
1754 for(
auto&entry : Locations) {
1755assert(entry.first->getName() ==
""&&
"not a placeholder!");
1756entry.first->replaceAllUsesWith(entry.second);
1757entry.first->eraseFromParent();
1762 voidfindLocations(llvm::Constant *init) {
1764 if(
autoagg = dyn_cast<llvm::ConstantAggregate>(init)) {
1765 for(
unsignedi = 0, e = agg->getNumOperands(); i != e; ++i) {
1766Indices.push_back(i);
1767IndexValues.push_back(
nullptr);
1769findLocations(agg->getOperand(i));
1771IndexValues.pop_back();
1779 autoit = PlaceholderAddresses.find(init);
1780 if(it != PlaceholderAddresses.end()) {
1781setLocation(it->second);
1786 if(
auto expr= dyn_cast<llvm::ConstantExpr>(init)) {
1787init =
expr->getOperand(0);
1794 voidsetLocation(llvm::GlobalVariable *placeholder) {
1795assert(!Locations.contains(placeholder) &&
1796 "already found location for placeholder!");
1801assert(Indices.size() == IndexValues.size());
1802 for(
size_ti = Indices.size() - 1; i !=
size_t(-1); --i) {
1803 if(IndexValues[i]) {
1805 for(
size_tj = 0; j != i + 1; ++j) {
1806assert(IndexValues[j] &&
1807isa<llvm::ConstantInt>(IndexValues[j]) &&
1808cast<llvm::ConstantInt>(IndexValues[j])->getZExtValue()
1815IndexValues[i] = llvm::ConstantInt::get(CGM.
Int32Ty, Indices[i]);
1818llvm::Constant *location = llvm::ConstantExpr::getInBoundsGetElementPtr(
1819BaseValueTy,
Base, IndexValues);
1821Locations.insert({placeholder, location});
1827assert(InitializedNonAbstract &&
1828 "finalizing emitter that was used for abstract emission?");
1829assert(!Finalized &&
"finalizing emitter multiple times");
1830assert(global->getInitializer());
1835 if(!PlaceholderAddresses.empty()) {
1836ReplacePlaceholders(
CGM, global, PlaceholderAddresses)
1837.replaceInInitializer(global->getInitializer());
1838PlaceholderAddresses.clear();
1843assert((!InitializedNonAbstract || Finalized || Failed) &&
1844 "not finalized after being initialized for non-abstract emission");
1845assert(PlaceholderAddresses.empty() &&
"unhandled placeholders");
1851 type.getQualifiers());
1860 if(!
D.hasLocalStorage()) {
1864dyn_cast_or_null<CXXConstructExpr>(
D.getInit())) {
1870InConstantContext =
D.hasConstantInitialization();
1873 const Expr*
E=
D.getInit();
1874assert(
E&&
"No initializer to emit");
1878 if(llvm::Constant *
C= ConstExprEmitter(*this).Visit(
E, nonMemoryDestType))
1884 if(
APValue*value =
D.evaluateValue())
1927assert(Schema &&
"applying trivial ptrauth schema");
1930 returnUnsignedPointer;
1932 unsignedKey = Schema.
getKey();
1935llvm::GlobalValue *StorageAddress =
nullptr;
1944llvm::ConstantInt *Discriminator =
1948UnsignedPointer, Key, StorageAddress, Discriminator);
1953 returnSignedPointer;
1957llvm::Constant *
C,
1961 QualTypedestValueType = AT->getValueType();
1966 if(innerSize == outerSize)
1969assert(innerSize < outerSize &&
"emitted over-large constant for atomic");
1970llvm::Constant *elts[] = {
1972llvm::ConstantAggregateZero::get(
1973llvm::ArrayType::get(
CGM.
Int8Ty, (outerSize - innerSize) / 8))
1975 returnllvm::ConstantStruct::getAnon(elts);
1979 if(
C->getType()->isIntegerTy(1) && !destType->
isBitIntType()) {
1981llvm::Constant *Res = llvm::ConstantFoldCastOperand(
1983assert(Res &&
"Constant folding must succeed");
1988ConstantAggregateBuilder Builder(
CGM);
1992 auto*CI = cast<llvm::ConstantInt>(
C);
1993llvm::Constant *Res = llvm::ConstantFoldCastOperand(
1995: llvm::Instruction::ZExt,
2001llvm::APInt
Value= cast<llvm::ConstantInt>(Res)->getValue();
2002Builder.addBits(
Value,
0,
false);
2003 returnBuilder.build(DesiredTy,
false);
2013assert(!destType->
isVoidType() &&
"can't emit a void constant");
2016 if(llvm::Constant *
C= ConstExprEmitter(*this).Visit(
E, destType))
2041structConstantLValue {
2042llvm::Constant *
Value;
2043 boolHasOffsetApplied;
2045ConstantLValue(llvm::Constant *value,
2046 boolhasOffsetApplied =
false)
2047:
Value(value), HasOffsetApplied(hasOffsetApplied) {}
2050: ConstantLValue(address.getPointer()) {}
2054classConstantLValueEmitter :
public ConstStmtVisitor<ConstantLValueEmitter,
2060 boolEnablePtrAuthFunctionTypeDiscrimination;
2068 boolEnablePtrAuthFunctionTypeDiscrimination =
true)
2069: CGM(emitter.CGM),
Emitter(emitter),
Value(value), DestType(destType),
2070EnablePtrAuthFunctionTypeDiscrimination(
2071EnablePtrAuthFunctionTypeDiscrimination) {}
2073llvm::Constant *tryEmit();
2076llvm::Constant *tryEmitAbsolute(llvm::Type *destTy);
2079ConstantLValue VisitStmt(
const Stmt*S) {
return nullptr; }
2088ConstantLValue VisitCallExpr(
const CallExpr*
E);
2089ConstantLValue VisitBlockExpr(
const BlockExpr*
E);
2091ConstantLValue VisitMaterializeTemporaryExpr(
2094ConstantLValue emitPointerAuthSignConstant(
const CallExpr*
E);
2095llvm::Constant *emitPointerAuthPointer(
const Expr*
E);
2096 unsignedemitPointerAuthKey(
const Expr*
E);
2097std::pair<llvm::Constant *, llvm::ConstantInt *>
2098emitPointerAuthDiscriminator(
const Expr*
E);
2100 boolhasNonZeroOffset()
const{
2101 return!
Value.getLValueOffset().isZero();
2105llvm::Constant *getOffset() {
2106 returnllvm::ConstantInt::get(CGM.
Int64Ty,
2107 Value.getLValueOffset().getQuantity());
2111llvm::Constant *applyOffset(llvm::Constant *
C) {
2112 if(!hasNonZeroOffset())
2115 returnllvm::ConstantExpr::getGetElementPtr(CGM.
Int8Ty,
C, getOffset());
2121llvm::Constant *ConstantLValueEmitter::tryEmit() {
2132assert(isa<llvm::IntegerType>(destTy) || isa<llvm::PointerType>(destTy));
2137 returntryEmitAbsolute(destTy);
2141ConstantLValue result = tryEmitBase(base);
2144llvm::Constant *value = result.Value;
2145 if(!value)
return nullptr;
2148 if(!result.HasOffsetApplied) {
2149value = applyOffset(value);
2154 if(isa<llvm::PointerType>(destTy))
2155 returnllvm::ConstantExpr::getPointerCast(value, destTy);
2157 returnllvm::ConstantExpr::getPtrToInt(value, destTy);
2163ConstantLValueEmitter::tryEmitAbsolute(llvm::Type *destTy) {
2165 autodestPtrTy = cast<llvm::PointerType>(destTy);
2166 if(
Value.isNullPointer()) {
2174 autointptrTy = CGM.
getDataLayout().getIntPtrType(destPtrTy);
2175llvm::Constant *
C;
2176 C= llvm::ConstantFoldIntegerCast(getOffset(), intptrTy,
false,
2178assert(
C&&
"Must have folded, as Offset is a ConstantInt");
2179 C= llvm::ConstantExpr::getIntToPtr(
C, destPtrTy);
2194 autoPtrAuthSign = [&](llvm::Constant *
C) {
2197 if(EnablePtrAuthFunctionTypeDiscrimination)
2201 if(hasNonZeroOffset())
2202 returnConstantLValue(
nullptr);
2204 C= applyOffset(
C);
2206 C, AuthInfo.
getKey(),
nullptr,
2208 returnConstantLValue(
C,
true);
2211 returnConstantLValue(
C);
2214 if(
const auto*FD = dyn_cast<FunctionDecl>(
D))
2217 if(
const auto*VD = dyn_cast<VarDecl>(
D)) {
2219 if(!VD->hasLocalStorage()) {
2220 if(VD->isFileVarDecl() || VD->hasExternalStorage())
2223 if(VD->isLocalVarDecl()) {
2230 if(
const auto*GD = dyn_cast<MSGuidDecl>(
D))
2233 if(
const auto*GCD = dyn_cast<UnnamedGlobalConstantDecl>(
D))
2236 if(
const auto*TPO = dyn_cast<TemplateParamObjectDecl>(
D))
2247 returnVisit(base.
get<
const Expr*>());
2251ConstantLValueEmitter::VisitConstantExpr(
const ConstantExpr*
E) {
2254 returnVisit(
E->getSubExpr());
2260CompoundLiteralEmitter.setInConstantContext(
Emitter.isInConstantContext());
2261 returntryEmitGlobalCompoundLiteral(CompoundLiteralEmitter,
E);
2265ConstantLValueEmitter::VisitStringLiteral(
const StringLiteral*
E) {
2270ConstantLValueEmitter::VisitObjCEncodeExpr(
const ObjCEncodeExpr*
E) {
2287ConstantLValueEmitter::VisitObjCBoxedExpr(
const ObjCBoxedExpr*
E) {
2288assert(
E->isExpressibleAsConstantInitializer() &&
2289 "this boxed expression can't be emitted as a compile-time constant");
2295ConstantLValueEmitter::VisitPredefinedExpr(
const PredefinedExpr*
E) {
2300ConstantLValueEmitter::VisitAddrLabelExpr(
const AddrLabelExpr*
E) {
2301assert(
Emitter.CGF &&
"Invalid address of label expression outside function");
2302llvm::Constant *Ptr =
Emitter.CGF->GetAddrOfLabel(
E->getLabel());
2307ConstantLValueEmitter::VisitCallExpr(
const CallExpr*
E) {
2308 unsignedbuiltin =
E->getBuiltinCallee();
2309 if(builtin == Builtin::BI__builtin_function_start)
2313 if(builtin == Builtin::BI__builtin_ptrauth_sign_constant)
2314 returnemitPointerAuthSignConstant(
E);
2316 if(builtin != Builtin::BI__builtin___CFStringMakeConstantString &&
2317builtin != Builtin::BI__builtin___NSStringMakeConstantString)
2321 if(builtin == Builtin::BI__builtin___NSStringMakeConstantString) {
2330ConstantLValueEmitter::emitPointerAuthSignConstant(
const CallExpr*
E) {
2331llvm::Constant *UnsignedPointer = emitPointerAuthPointer(
E->getArg(0));
2332 unsignedKey = emitPointerAuthKey(
E->getArg(1));
2333 auto[StorageAddress, OtherDiscriminator] =
2334emitPointerAuthDiscriminator(
E->getArg(2));
2337UnsignedPointer, Key, StorageAddress, OtherDiscriminator);
2338 returnSignedPointer;
2341llvm::Constant *ConstantLValueEmitter::emitPointerAuthPointer(
const Expr*
E) {
2348assert(
Result.Val.isLValue());
2349 if(isa<FunctionDecl>(
Result.Val.getLValueBase().get<
const ValueDecl*>()))
2350assert(
Result.Val.getLValueOffset().isZero());
2355unsignedConstantLValueEmitter::emitPointerAuthKey(
const Expr*
E) {
2359std::pair<llvm::Constant *, llvm::ConstantInt *>
2360ConstantLValueEmitter::emitPointerAuthDiscriminator(
const Expr*
E) {
2363 if(
const auto*
Call= dyn_cast<CallExpr>(
E)) {
2364 if(
Call->getBuiltinCallee() ==
2365Builtin::BI__builtin_ptrauth_blend_discriminator) {
2367 Call->getArg(0),
Call->getArg(0)->getType());
2368 auto*Extra = cast<llvm::ConstantInt>(
ConstantEmitter(CGM).emitAbstract(
2369 Call->getArg(1),
Call->getArg(1)->getType()));
2375 if(
Result->getType()->isPointerTy())
2376 return{
Result,
nullptr};
2377 return{
nullptr, cast<llvm::ConstantInt>(
Result)};
2381ConstantLValueEmitter::VisitBlockExpr(
const BlockExpr*
E) {
2382StringRef functionName;
2384functionName = CGF->CurFn->getName();
2386functionName =
"global";
2392ConstantLValueEmitter::VisitCXXTypeidExpr(
const CXXTypeidExpr*
E) {
2394 if(
E->isTypeOperand())
2402ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
2404assert(
E->getStorageDuration() ==
SD_Static);
2411 boolEnablePtrAuthFunctionTypeDiscrimination) {
2418 returnConstantLValueEmitter(*
this,
Value, DestType,
2419EnablePtrAuthFunctionTypeDiscrimination)
2425 Value.getFixedPoint().getValue());
2430 Value.getComplexIntReal());
2432 Value.getComplexIntImag());
2435llvm::StructType *STy =
2436llvm::StructType::get(
Complex[0]->getType(),
Complex[1]->getType());
2437 returnllvm::ConstantStruct::get(STy,
Complex);
2440 constllvm::APFloat &
Init=
Value.getFloat();
2441 if(&
Init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
2445 Init.bitcastToAPInt());
2453 Value.getComplexFloatReal());
2455 Value.getComplexFloatImag());
2458llvm::StructType *STy =
2459llvm::StructType::get(
Complex[0]->getType(),
Complex[1]->getType());
2460 returnllvm::ConstantStruct::get(STy,
Complex);
2463 unsignedNumElts =
Value.getVectorLength();
2466 for(
unsignedI = 0; I != NumElts; ++I) {
2476llvm_unreachable(
"unsupported vector element type");
2478 returnllvm::ConstantVector::get(Inits);
2485 if(!LHS || !RHS)
return nullptr;
2489LHS = llvm::ConstantExpr::getPtrToInt(LHS,
CGM.
IntPtrTy);
2490RHS = llvm::ConstantExpr::getPtrToInt(RHS,
CGM.
IntPtrTy);
2491llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
2496 returnllvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
2500 returnConstStructBuilder::BuildStruct(*
this,
Value, DestType);
2503 unsignedNumElements =
Value.getArraySize();
2504 unsignedNumInitElts =
Value.getArrayInitializedElts();
2507llvm::Constant *Filler =
nullptr;
2508 if(
Value.hasArrayFiller()) {
2517 if(Filler && Filler->isNullValue())
2518Elts.reserve(NumInitElts + 1);
2520Elts.reserve(NumElements);
2522llvm::Type *CommonElementType =
nullptr;
2523 for(
unsignedI = 0; I < NumInitElts; ++I) {
2526 if(!
C)
return nullptr;
2529CommonElementType =
C->getType();
2530 else if(
C->getType() != CommonElementType)
2531CommonElementType =
nullptr;
2532Elts.push_back(
C);
2535llvm::ArrayType *Desired =
2540Desired = llvm::ArrayType::get(Desired->getElementType(), Elts.size());
2542 returnEmitArrayConstant(
CGM, Desired, CommonElementType, NumElements, Elts,
2548llvm_unreachable(
"Unknown APValue kind");
2553 returnEmittedCompoundLiterals.lookup(
E);
2558 bool Ok= EmittedCompoundLiterals.insert(std::make_pair(CLE, GV)).second;
2560assert(
Ok&&
"CLE has already been emitted!");
2565assert(
E->isFileScope() &&
"not a file-scope compound literal expr");
2567 returntryEmitGlobalCompoundLiteral(emitter,
E);
2587llvm::Type *baseType,
2592 boolasCompleteObject) {
2594llvm::StructType *structure =
2598 unsignednumElements = structure->getNumElements();
2599std::vector<llvm::Constant *> elements(numElements);
2601 autoCXXR = dyn_cast<CXXRecordDecl>(record);
2604 for(
const auto&I : CXXR->bases()) {
2605 if(I.isVirtual()) {
2623llvm::Type *baseType = structure->getElementType(fieldIndex);
2629 for(
const auto*Field : record->
fields()) {
2632 if(!Field->isBitField() &&
2640 if(Field->getIdentifier())
2642 if(
const auto*FieldRD = Field->getType()->getAsRecordDecl())
2643 if(FieldRD->findFirstNamedDataMember())
2649 if(CXXR && asCompleteObject) {
2650 for(
const auto&I : CXXR->vbases()) {
2661 if(elements[fieldIndex])
continue;
2663llvm::Type *baseType = structure->getElementType(fieldIndex);
2669 for(
unsignedi = 0; i != numElements; ++i) {
2671elements[i] = llvm::Constant::getNullValue(structure->getElementType(i));
2674 returnllvm::ConstantStruct::get(structure, elements);
2679llvm::Type *baseType,
2685 returnllvm::Constant::getNullValue(baseType);
2699cast<llvm::PointerType>(
getTypes().ConvertTypeForMem(
T)),
T);
2701 if(
getTypes().isZeroInitializable(
T))
2702 returnllvm::Constant::getNullValue(
getTypes().ConvertTypeForMem(
T));
2705llvm::ArrayType *ATy =
2706cast<llvm::ArrayType>(
getTypes().ConvertTypeForMem(
T));
2710llvm::Constant *Element =
2714 returnllvm::ConstantArray::get(ATy, Array);
2718return ::EmitNullConstant(*
this, RT->getDecl(),
true);
2721 "Should only see pointers to data members here!");
2728return ::EmitNullConstant(*
this,
Record,
false);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)
static llvm::Constant * EmitNullConstant(CodeGenModule &CGM, const RecordDecl *record, bool asCompleteObject)
static ConstantLValue emitConstantObjCStringLiteral(const StringLiteral *S, QualType T, CodeGenModule &CGM)
static llvm::Constant * EmitNullConstantForBase(CodeGenModule &CGM, llvm::Type *baseType, const CXXRecordDecl *base)
Emit the null constant for a base subobject.
llvm::MachO::Record Record
llvm::APInt getValue() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
APValue & getStructField(unsigned i)
const FieldDecl * getUnionField() const
APValue & getUnionValue()
bool isIndeterminate() const
@ Indeterminate
This object has an indeterminate value (C++ [basic.indet]).
@ None
There is no such object (it's outside its lifetime).
APValue & getStructBase(unsigned i)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
const LangOptions & getLangOpts() const
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
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.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
unsigned getTargetAddressSpace(LangAS AS) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
AddrLabelExpr - The GNU address of label extension, representing &&label.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a base class of a C++ class.
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
A use of a default initializer in a constructor or in aggregate initialization.
Expr * getExpr()
Get the initialization expression that will be used.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
virtual llvm::Constant * EmitNullMemberPointer(const MemberPointerType *MPT)
Create a null member pointer of the given type.
virtual llvm::Constant * EmitMemberPointer(const APValue &MP, QualType MPT)
Create a member pointer for the given member pointer constant.
virtual llvm::Constant * getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0
Get the address point of the vtable for the given base subobject.
virtual llvm::Constant * EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset)
Create a member pointer for the given field.
virtual llvm::Value * EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src)
Perform a derived-to-base, base-to-derived, or bitcast member pointer conversion.
virtual llvm::Constant * EmitMemberFunctionPointer(const CXXMethodDecl *MD)
Create a member pointer for the given method.
virtual ConstantAddress GenerateConstantString(const StringLiteral *)=0
Generate a constant string object.
llvm::Value * getDiscriminator() const
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const
Return the BitFieldInfo that corresponds to the field FD.
bool isZeroInitializableAsBase() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer when considered as a bas...
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
This class organizes the cross-function state that is used while generating LLVM code.
ConstantAddress GetAddrOfMSGuidDecl(const MSGuidDecl *GD)
Get the address of a GUID.
void EmitExplicitCastExprType(const ExplicitCastExpr *E, CodeGenFunction *CGF=nullptr)
Emit type info if type of an expression is a variably modified type.
llvm::Module & getModule() const
ConstantAddress GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E)
Returns a pointer to a constant global variable for the given file-scope compound literal expression.
llvm::Constant * EmitNullConstantForBase(const CXXRecordDecl *Record)
Return a null constant appropriate for zero-initializing a base class with the given type.
llvm::Constant * getRawFunctionPointer(GlobalDecl GD, llvm::Type *Ty=nullptr)
Return a function pointer for a reference to the given function.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
llvm::Constant * getNullPointer(llvm::PointerType *T, QualType QT)
Get target specific null pointer.
llvm::Constant * GetAddrOfGlobalBlock(const BlockExpr *BE, StringRef Name)
Gets the address of a block which requires no captures.
CodeGenTypes & getTypes()
llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD)
Returns LLVM linkage for a declarator.
llvm::Constant * getMemberPointerConstant(const UnaryOperator *e)
const llvm::DataLayout & getDataLayout() const
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
CGCXXABI & getCXXABI() const
ConstantAddress GetWeakRefReference(const ValueDecl *VD)
Get a reference to the target of VD.
CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T)
Return the abstract pointer authentication schema for a pointer to the given function type.
llvm::Constant * GetFunctionStart(const ValueDecl *Decl)
llvm::GlobalVariable * getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *E)
If it's been emitted already, returns the GlobalVariable corresponding to a compound literal.
std::optional< PointerAuthQualifier > getVTablePointerAuthentication(const CXXRecordDecl *thisClass)
llvm::Constant * getOrCreateStaticVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage)
ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal)
Return a pointer to a constant CFString object for the given string.
ConstantAddress GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef Name=".str")
Return a pointer to a constant array for the given string literal.
ASTContext & getContext() const
ConstantAddress GetAddrOfTemplateParamObject(const TemplateParamObjectDecl *TPO)
Get the address of a template parameter object.
ConstantAddress GetAddrOfUnnamedGlobalConstantDecl(const UnnamedGlobalConstantDecl *GCD)
Get the address of a UnnamedGlobalConstant.
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *CLE, llvm::GlobalVariable *GV)
Notes that CLE's GlobalVariable is GV.
const TargetCodeGenInfo & getTargetCodeGenInfo()
llvm::Constant * GetConstantArrayFromStringLiteral(const StringLiteral *E)
Return a constant array for the given string.
llvm::LLVMContext & getLLVMContext()
bool shouldZeroInitPadding() const
CGObjCRuntime & getObjCRuntime()
Return a reference to the configured Objective-C runtime.
ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E, const Expr *Inner)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Sign a constant pointer using the given scheme, producing a constant with the same IR type.
ConstantAddress GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *)
Return a pointer to a constant array for the given ObjCEncodeExpr node.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::Type * convertTypeForLoadStore(QualType T, llvm::Type *LLVMTy=nullptr)
Given that T is a scalar type, return the IR type that should be used for load and store operations.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
bool typeRequiresSplitIntoByteArray(QualType ASTTy, llvm::Type *LLVMTy=nullptr)
Check whether the given type needs to be laid out in memory using an opaque byte-array type because i...
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
llvm::Constant * getPointer() const
llvm::Constant * tryEmitPrivateForMemory(const Expr *E, QualType T)
llvm::Constant * tryEmitForInitializer(const VarDecl &D)
Try to emit the initiaizer of the given declaration as an abstract constant.
llvm::Constant * tryEmitPrivateForVarInit(const VarDecl &D)
llvm::Constant * tryEmitPrivate(const Expr *E, QualType T)
void finalize(llvm::GlobalVariable *global)
llvm::Constant * tryEmitAbstractForInitializer(const VarDecl &D)
Try to emit the initializer of the given declaration as an abstract constant.
llvm::Constant * emitAbstract(const Expr *E, QualType T)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
llvm::GlobalValue * getCurrentAddrPrivate()
Get the address of the current location.
llvm::Constant * tryEmitConstantExpr(const ConstantExpr *CE)
llvm::Constant * emitForMemory(llvm::Constant *C, QualType T)
llvm::Constant * emitNullForMemory(QualType T)
llvm::Constant * tryEmitAbstract(const Expr *E, QualType T)
Try to emit the result of the given expression as an abstract constant.
void registerCurrentAddrPrivate(llvm::Constant *signal, llvm::GlobalValue *placeholder)
Register a 'signal' value with the emitter to inform it where to resolve a placeholder.
llvm::Constant * emitForInitializer(const APValue &value, LangAS destAddrSpace, QualType destType)
llvm::Constant * tryEmitAbstractForMemory(const Expr *E, QualType T)
bool isAbstract() const
Is the current emission context abstract?
llvm::Constant * tryEmitConstantSignedPointer(llvm::Constant *Ptr, PointerAuthQualifier Auth)
Try to emit a constant signed pointer, given a raw pointer and the destination ptrauth qualifier.
Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy, bool IsNonNull=false) const
virtual llvm::Constant * getNullPointer(const CodeGen::CodeGenModule &CGM, llvm::PointerType *T, QualType QT) const
Get target specific null pointer.
CompoundLiteralExpr - [C99 6.5.2.5].
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Represents the canonical version of C arrays with a specified constant size.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
APValue getAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
bool hasAPValueResult() const
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
Decl - This represents one declaration (or definition), e.g.
Decl * getMostRecentDecl()
Retrieve the most recent declaration that declares the same entity as this declaration (which may be ...
Represents an expression â generally a full-expression â that introduces cleanups to be run at the en...
This represents one expression.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsLValue - Evaluate an expression to see if we can fold it to an lvalue with link time known ...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
const ValueDecl * getAsBuiltinConstantDeclRef(const ASTContext &Context) const
If this expression is an unambiguous reference to a single declaration, in the style of __builtin_fun...
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
const Expr * getSubExpr() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Represents a C11 generic selection.
Represents an implicitly-generated value initialization of an object of a given type.
Describes an C or C++ initializer list.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
unsigned getNumInits() const
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits()
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
A pointer to member type per C++ 8.3.3 - Pointers to members.
ObjCBoxedExpr - used for generalized expression boxing.
ObjCEncodeExpr, used for @encode in Objective-C.
ObjCStringLiteral, used for Objective-C string literals i.e.
ParenExpr - This represents a parenthesized expression, e.g.
const Expr * getSubExpr() const
Pointer-authentication qualifiers.
bool isAddressDiscriminated() const
unsigned getExtraDiscriminator() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
[C99 6.4.2.2] - A predefined identifier such as func.
A (possibly-)qualified type.
LangAS getAddressSpace() const
Return the address space of this type.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Represents a struct/union/class.
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
field_iterator field_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Encodes a location in the source.
StmtVisitorBase - This class implements a simple visitor for Stmt subclasses.
RetTy Visit(PTR(Stmt) S, ParamTys... P)
Stmt - This represents one statement.
StringLiteral - This represents a string literal expression, e.g.
uint32_t getCodeUnit(size_t i) const
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Expr * getReplacement() const
virtual bool useFP16ConversionIntrinsics() const
Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used to convert to and from __fp...
Symbolic representation of typeid(T) for some type T.
The base class of the type hierarchy.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isIncompleteArrayType() const
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isMemberDataPointerType() const
bool isBitIntType() const
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
Represents a GCC generic vector type.
QualType getElementType() const
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
uint32_t Literal
Literals are represented as positive integers.
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
bool GE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ Finalize
'finalize' clause, allowed on 'exit data' directive.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ SD_Static
Static storage duration.
@ Result
The result type of a method or function.
LangAS
Defines the address space values used by the address space qualifier of QualType.
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
@ Success
Template argument deduction was successful.
Structure with information about how a bitfield should be accessed.
unsigned Size
The total size of the bit-field, in bits.
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * CharTy
char
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
EvalResult is a struct with detailed info about an evaluated expression.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4