aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp715
1 files changed, 510 insertions, 205 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
index 47e41261e095..f22321f0e738 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
@@ -25,10 +26,12 @@
#include "clang/Basic/Builtins.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
+#include <optional>
using namespace clang;
using namespace CodeGen;
@@ -46,7 +49,7 @@ struct ConstantAggregateBuilderUtils {
CharUnits getAlignment(const llvm::Constant *C) const {
return CharUnits::fromQuantity(
- CGM.getDataLayout().getABITypeAlignment(C->getType()));
+ CGM.getDataLayout().getABITypeAlign(C->getType()));
}
CharUnits getSize(llvm::Type *Ty) const {
@@ -94,7 +97,7 @@ class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
bool NaturalLayout = true;
bool split(size_t Index, CharUnits Hint);
- Optional<size_t> splitAt(CharUnits Pos);
+ std::optional<size_t> splitAt(CharUnits Pos);
static llvm::Constant *buildFrom(CodeGenModule &CGM,
ArrayRef<llvm::Constant *> Elems,
@@ -158,12 +161,12 @@ bool ConstantAggregateBuilder::add(llvm::Constant *C, CharUnits Offset,
}
// Uncommon case: constant overlaps what we've already created.
- llvm::Optional<size_t> FirstElemToReplace = splitAt(Offset);
+ std::optional<size_t> FirstElemToReplace = splitAt(Offset);
if (!FirstElemToReplace)
return false;
CharUnits CSize = getSize(C);
- llvm::Optional<size_t> LastElemToReplace = splitAt(Offset + CSize);
+ std::optional<size_t> LastElemToReplace = splitAt(Offset + CSize);
if (!LastElemToReplace)
return false;
@@ -222,10 +225,10 @@ bool ConstantAggregateBuilder::addBits(llvm::APInt Bits, uint64_t OffsetInBits,
// Partial byte: update the existing integer if there is one. If we
// can't split out a 1-CharUnit range to update, then we can't add
// these bits and fail the entire constant emission.
- llvm::Optional<size_t> FirstElemToUpdate = splitAt(OffsetInChars);
+ std::optional<size_t> FirstElemToUpdate = splitAt(OffsetInChars);
if (!FirstElemToUpdate)
return false;
- llvm::Optional<size_t> LastElemToUpdate =
+ std::optional<size_t> LastElemToUpdate =
splitAt(OffsetInChars + CharUnits::One());
if (!LastElemToUpdate)
return false;
@@ -283,8 +286,8 @@ bool ConstantAggregateBuilder::addBits(llvm::APInt Bits, uint64_t OffsetInBits,
/// Returns a position within Elems and Offsets such that all elements
/// before the returned index end before Pos and all elements at or after
/// the returned index begin at or after Pos. Splits elements as necessary
-/// to ensure this. Returns None if we find something we can't split.
-Optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits Pos) {
+/// to ensure this. Returns std::nullopt if we find something we can't split.
+std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits Pos) {
if (Pos >= Size)
return Offsets.size();
@@ -305,7 +308,7 @@ Optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits Pos) {
// Try to decompose it into smaller constants.
if (!split(LastAtOrBeforePosIndex, Pos))
- return None;
+ return std::nullopt;
}
}
@@ -391,7 +394,7 @@ bool ConstantAggregateBuilder::split(size_t Index, CharUnits Hint) {
static llvm::Constant *
EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
- llvm::Type *CommonElementType, unsigned ArrayBound,
+ llvm::Type *CommonElementType, uint64_t ArrayBound,
SmallVectorImpl<llvm::Constant *> &Elements,
llvm::Constant *Filler);
@@ -439,22 +442,33 @@ llvm::Constant *ConstantAggregateBuilder::buildFrom(
// Can't emit as an array, carry on to emit as a struct.
}
+ // The size of the constant we plan to generate. This is usually just
+ // the size of the initialized type, but in AllowOversized mode (i.e.
+ // flexible array init), it can be larger.
CharUnits DesiredSize = Utils.getSize(DesiredTy);
+ if (Size > DesiredSize) {
+ assert(AllowOversized && "Elems are oversized");
+ DesiredSize = Size;
+ }
+
+ // The natural alignment of an unpacked LLVM struct with the given elements.
CharUnits Align = CharUnits::One();
for (llvm::Constant *C : Elems)
Align = std::max(Align, Utils.getAlignment(C));
+
+ // The natural size of an unpacked LLVM struct with the given elements.
CharUnits AlignedSize = Size.alignTo(Align);
bool Packed = false;
ArrayRef<llvm::Constant*> UnpackedElems = Elems;
llvm::SmallVector<llvm::Constant*, 32> UnpackedElemStorage;
- if ((DesiredSize < AlignedSize && !AllowOversized) ||
- DesiredSize.alignTo(Align) != DesiredSize) {
- // The natural layout would be the wrong size; force use of a packed layout.
+ if (DesiredSize < AlignedSize || DesiredSize.alignTo(Align) != DesiredSize) {
+ // The natural layout would be too big; force use of a packed layout.
NaturalLayout = false;
Packed = true;
} else if (DesiredSize > AlignedSize) {
- // The constant would be too small. Add padding to fix it.
+ // The natural layout would be too small. Add padding to fix it. (This
+ // is ignored if we choose a packed layout.)
UnpackedElemStorage.assign(Elems.begin(), Elems.end());
UnpackedElemStorage.push_back(Utils.getPadding(DesiredSize - Size));
UnpackedElems = UnpackedElemStorage;
@@ -482,7 +496,7 @@ llvm::Constant *ConstantAggregateBuilder::buildFrom(
// If we're using the packed layout, pad it out to the desired size if
// necessary.
if (Packed) {
- assert((SizeSoFar <= DesiredSize || AllowOversized) &&
+ assert(SizeSoFar <= DesiredSize &&
"requested size is too small for contents");
if (SizeSoFar < DesiredSize)
PackedElems.push_back(Utils.getPadding(DesiredSize - SizeSoFar));
@@ -506,12 +520,12 @@ void ConstantAggregateBuilder::condense(CharUnits Offset,
llvm::Type *DesiredTy) {
CharUnits Size = getSize(DesiredTy);
- llvm::Optional<size_t> FirstElemToReplace = splitAt(Offset);
+ std::optional<size_t> FirstElemToReplace = splitAt(Offset);
if (!FirstElemToReplace)
return;
size_t First = *FirstElemToReplace;
- llvm::Optional<size_t> LastElemToReplace = splitAt(Offset + Size);
+ std::optional<size_t> LastElemToReplace = splitAt(Offset + Size);
if (!LastElemToReplace)
return;
size_t Last = *LastElemToReplace;
@@ -532,8 +546,8 @@ void ConstantAggregateBuilder::condense(CharUnits Offset,
}
llvm::Constant *Replacement = buildFrom(
- CGM, makeArrayRef(Elems).slice(First, Length),
- makeArrayRef(Offsets).slice(First, Length), Offset, getSize(DesiredTy),
+ CGM, ArrayRef(Elems).slice(First, Length),
+ ArrayRef(Offsets).slice(First, Length), Offset, getSize(DesiredTy),
/*known to have natural layout=*/false, DesiredTy, false);
replace(Elems, First, Last, {Replacement});
replace(Offsets, First, Last, {Offset});
@@ -551,12 +565,13 @@ class ConstStructBuilder {
public:
static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
- InitListExpr *ILE, QualType StructTy);
+ const InitListExpr *ILE,
+ QualType StructTy);
static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
const APValue &Value, QualType ValTy);
static bool UpdateStruct(ConstantEmitter &Emitter,
ConstantAggregateBuilder &Const, CharUnits Offset,
- InitListExpr *Updater);
+ const InitListExpr *Updater);
private:
ConstStructBuilder(ConstantEmitter &Emitter,
@@ -571,9 +586,9 @@ private:
bool AllowOverwrite = false);
bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
- llvm::ConstantInt *InitExpr, bool AllowOverwrite = false);
+ llvm::Constant *InitExpr, bool AllowOverwrite = false);
- bool Build(InitListExpr *ILE, bool AllowOverwrite);
+ bool Build(const InitListExpr *ILE, bool AllowOverwrite);
bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
llvm::Constant *Finalize(QualType Ty);
@@ -595,9 +610,25 @@ bool ConstStructBuilder::AppendBytes(CharUnits FieldOffsetInChars,
return Builder.add(InitCst, StartOffset + FieldOffsetInChars, AllowOverwrite);
}
-bool ConstStructBuilder::AppendBitField(
- const FieldDecl *Field, uint64_t FieldOffset, llvm::ConstantInt *CI,
- bool AllowOverwrite) {
+bool ConstStructBuilder::AppendBitField(const FieldDecl *Field,
+ uint64_t FieldOffset, llvm::Constant *C,
+ bool AllowOverwrite) {
+
+ llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C);
+ if (!CI) {
+ // Constants for long _BitInt types are sometimes split into individual
+ // bytes. Try to fold these back into an integer constant. If that doesn't
+ // work out, then we are trying to initialize a bitfield with a non-trivial
+ // constant, this must require run-time code.
+ llvm::Type *LoadType =
+ CGM.getTypes().convertTypeForLoadStore(Field->getType(), C->getType());
+ llvm::Constant *FoldedConstant = llvm::ConstantFoldLoadFromConst(
+ C, LoadType, llvm::APInt::getZero(32), CGM.getDataLayout());
+ CI = dyn_cast_if_present<llvm::ConstantInt>(FoldedConstant);
+ if (!CI)
+ return false;
+ }
+
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field);
@@ -622,7 +653,7 @@ bool ConstStructBuilder::AppendBitField(
static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
ConstantAggregateBuilder &Const,
CharUnits Offset, QualType Type,
- InitListExpr *Updater) {
+ const InitListExpr *Updater) {
if (Type->isRecordType())
return ConstStructBuilder::UpdateStruct(Emitter, Const, Offset, Updater);
@@ -634,7 +665,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
llvm::Type *ElemTy = Emitter.CGM.getTypes().ConvertTypeForMem(ElemType);
llvm::Constant *FillC = nullptr;
- if (Expr *Filler = Updater->getArrayFiller()) {
+ if (const Expr *Filler = Updater->getArrayFiller()) {
if (!isa<NoInitExpr>(Filler)) {
FillC = Emitter.tryEmitAbstractForMemory(Filler, ElemType);
if (!FillC)
@@ -643,9 +674,9 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
}
unsigned NumElementsToUpdate =
- FillC ? CAT->getSize().getZExtValue() : Updater->getNumInits();
+ FillC ? CAT->getZExtSize() : Updater->getNumInits();
for (unsigned I = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) {
- Expr *Init = nullptr;
+ const Expr *Init = nullptr;
if (I < Updater->getNumInits())
Init = Updater->getInit(I);
@@ -654,7 +685,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
return false;
} else if (!Init || isa<NoInitExpr>(Init)) {
continue;
- } else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init)) {
+ } else if (const auto *ChildILE = dyn_cast<InitListExpr>(Init)) {
if (!EmitDesignatedInitUpdater(Emitter, Const, Offset, ElemType,
ChildILE))
return false;
@@ -670,7 +701,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
return true;
}
-bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) {
+bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
RecordDecl *RD = ILE->getType()->castAs<RecordType>()->getDecl();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
@@ -692,18 +723,26 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) {
!declaresSameEntity(ILE->getInitializedFieldInUnion(), Field))
continue;
- // Don't emit anonymous bitfields or zero-sized fields.
- if (Field->isUnnamedBitfield() || Field->isZeroSize(CGM.getContext()))
+ // Don't emit anonymous bitfields.
+ if (Field->isUnnamedBitField())
continue;
// Get the initializer. A struct can include fields without initializers,
// we just use explicit null values for them.
- Expr *Init = nullptr;
+ const Expr *Init = nullptr;
if (ElementNo < ILE->getNumInits())
Init = ILE->getInit(ElementNo++);
- if (Init && isa<NoInitExpr>(Init))
+ if (isa_and_nonnull<NoInitExpr>(Init))
continue;
+ // Zero-sized fields are not emitted, but their initializers may still
+ // prevent emission of this struct as a constant.
+ if (isEmptyFieldForLayout(CGM.getContext(), Field)) {
+ if (Init->HasSideEffects(CGM.getContext()))
+ return false;
+ continue;
+ }
+
// When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
// represents additional overwriting of our current constant value, and not
// a new constant to emit independently.
@@ -740,15 +779,9 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) {
AllowOverwrite = true;
} else {
// Otherwise we have a bitfield.
- if (auto *CI = dyn_cast<llvm::ConstantInt>(EltInit)) {
- if (!AppendBitField(Field, Layout.getFieldOffset(FieldNo), CI,
- AllowOverwrite))
- return false;
- } else {
- // We are trying to initialize a bitfield with a non-trivial constant,
- // this must require run-time code.
+ if (!AppendBitField(Field, Layout.getFieldOffset(FieldNo), EltInit,
+ AllowOverwrite))
return false;
- }
}
}
@@ -779,8 +812,14 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
// Add a vtable pointer, if we need one and it hasn't already been added.
if (Layout.hasOwnVFPtr()) {
llvm::Constant *VTableAddressPoint =
- CGM.getCXXABI().getVTableAddressPointForConstExpr(
- BaseSubobject(CD, Offset), VTableClass);
+ CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset),
+ VTableClass);
+ if (auto Authentication = CGM.getVTablePointerAuthentication(CD)) {
+ VTableAddressPoint = Emitter.tryEmitConstantSignedPointer(
+ VTableAddressPoint, *Authentication);
+ if (!VTableAddressPoint)
+ return false;
+ }
if (!AppendBytes(Offset, VTableAddressPoint))
return false;
}
@@ -819,7 +858,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
continue;
// Don't emit anonymous bitfields or zero-sized fields.
- if (Field->isUnnamedBitfield() || Field->isZeroSize(CGM.getContext()))
+ if (Field->isUnnamedBitField() ||
+ isEmptyFieldForLayout(CGM.getContext(), *Field))
continue;
// Emit the value of the initializer.
@@ -842,7 +882,7 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
} else {
// Otherwise we have a bitfield.
if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits,
- cast<llvm::ConstantInt>(EltInit), AllowOverwrite))
+ EltInit, AllowOverwrite))
return false;
}
}
@@ -851,13 +891,14 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
}
llvm::Constant *ConstStructBuilder::Finalize(QualType Type) {
+ Type = Type.getNonReferenceType();
RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
llvm::Type *ValTy = CGM.getTypes().ConvertType(Type);
return Builder.build(ValTy, RD->hasFlexibleArrayMember());
}
llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
- InitListExpr *ILE,
+ const InitListExpr *ILE,
QualType ValTy) {
ConstantAggregateBuilder Const(Emitter.CGM);
ConstStructBuilder Builder(Emitter, Const, CharUnits::Zero());
@@ -884,7 +925,8 @@ llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
bool ConstStructBuilder::UpdateStruct(ConstantEmitter &Emitter,
ConstantAggregateBuilder &Const,
- CharUnits Offset, InitListExpr *Updater) {
+ CharUnits Offset,
+ const InitListExpr *Updater) {
return ConstStructBuilder(Emitter, Const, Offset)
.Build(Updater, /*AllowOverwrite*/ true);
}
@@ -893,17 +935,16 @@ bool ConstStructBuilder::UpdateStruct(ConstantEmitter &Emitter,
// ConstExprEmitter
//===----------------------------------------------------------------------===//
-static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM,
- CodeGenFunction *CGF,
- const CompoundLiteralExpr *E) {
+static ConstantAddress
+tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter,
+ const CompoundLiteralExpr *E) {
+ CodeGenModule &CGM = emitter.CGM;
CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
if (llvm::GlobalVariable *Addr =
CGM.getAddrOfConstantCompoundLiteralIfEmitted(E))
- return ConstantAddress(Addr, Align);
+ return ConstantAddress(Addr, Addr->getValueType(), Align);
LangAS addressSpace = E->getType().getAddressSpace();
-
- ConstantEmitter emitter(CGM, CGF);
llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(),
addressSpace, E->getType());
if (!C) {
@@ -912,25 +953,25 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM,
return ConstantAddress::invalid();
}
- auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
- CGM.isTypeConstant(E->getType(), true),
- llvm::GlobalValue::InternalLinkage,
- C, ".compoundliteral", nullptr,
- llvm::GlobalVariable::NotThreadLocal,
- CGM.getContext().getTargetAddressSpace(addressSpace));
+ auto GV = new llvm::GlobalVariable(
+ CGM.getModule(), C->getType(),
+ E->getType().isConstantStorage(CGM.getContext(), true, false),
+ llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", nullptr,
+ llvm::GlobalVariable::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(addressSpace));
emitter.finalize(GV);
GV->setAlignment(Align.getAsAlign());
CGM.setAddrOfConstantCompoundLiteral(E, GV);
- return ConstantAddress(GV, Align);
+ return ConstantAddress(GV, GV->getValueType(), Align);
}
static llvm::Constant *
EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
- llvm::Type *CommonElementType, unsigned ArrayBound,
+ llvm::Type *CommonElementType, uint64_t ArrayBound,
SmallVectorImpl<llvm::Constant *> &Elements,
llvm::Constant *Filler) {
// Figure out how long the initial prefix of non-zero elements is.
- unsigned NonzeroLength = ArrayBound;
+ uint64_t NonzeroLength = ArrayBound;
if (Elements.size() < NonzeroLength && Filler->isNullValue())
NonzeroLength = Elements.size();
if (NonzeroLength == Elements.size()) {
@@ -942,7 +983,7 @@ EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
return llvm::ConstantAggregateZero::get(DesiredType);
// Add a zeroinitializer array filler if we have lots of trailing zeroes.
- unsigned TrailingZeroes = ArrayBound - NonzeroLength;
+ uint64_t TrailingZeroes = ArrayBound - NonzeroLength;
if (TrailingZeroes >= 8) {
assert(Elements.size() >= NonzeroLength &&
"missing initializer for non-zero element");
@@ -952,7 +993,7 @@ EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
if (CommonElementType && NonzeroLength >= 8) {
llvm::Constant *Initial = llvm::ConstantArray::get(
llvm::ArrayType::get(CommonElementType, NonzeroLength),
- makeArrayRef(Elements).take_front(NonzeroLength));
+ ArrayRef(Elements).take_front(NonzeroLength));
Elements.resize(2);
Elements[0] = Initial;
} else {
@@ -992,8 +1033,8 @@ EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
//
// Constant folding is currently missing support for a few features supported
// here: CK_ToUnion, CK_ReinterpretMemberPointer, and DesignatedInitUpdateExpr.
-class ConstExprEmitter :
- public StmtVisitor<ConstExprEmitter, llvm::Constant*, QualType> {
+class ConstExprEmitter
+ : public ConstStmtVisitor<ConstExprEmitter, llvm::Constant *, QualType> {
CodeGenModule &CGM;
ConstantEmitter &Emitter;
llvm::LLVMContext &VMContext;
@@ -1006,43 +1047,60 @@ public:
// Visitor Methods
//===--------------------------------------------------------------------===//
- llvm::Constant *VisitStmt(Stmt *S, QualType T) {
- return nullptr;
- }
+ llvm::Constant *VisitStmt(const Stmt *S, QualType T) { return nullptr; }
- llvm::Constant *VisitConstantExpr(ConstantExpr *CE, QualType T) {
+ llvm::Constant *VisitConstantExpr(const ConstantExpr *CE, QualType T) {
if (llvm::Constant *Result = Emitter.tryEmitConstantExpr(CE))
return Result;
return Visit(CE->getSubExpr(), T);
}
- llvm::Constant *VisitParenExpr(ParenExpr *PE, QualType T) {
+ llvm::Constant *VisitParenExpr(const ParenExpr *PE, QualType T) {
return Visit(PE->getSubExpr(), T);
}
llvm::Constant *
- VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE,
+ VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *PE,
QualType T) {
return Visit(PE->getReplacement(), T);
}
- llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE,
+ llvm::Constant *VisitGenericSelectionExpr(const GenericSelectionExpr *GE,
QualType T) {
return Visit(GE->getResultExpr(), T);
}
- llvm::Constant *VisitChooseExpr(ChooseExpr *CE, QualType T) {
+ llvm::Constant *VisitChooseExpr(const ChooseExpr *CE, QualType T) {
return Visit(CE->getChosenSubExpr(), T);
}
- llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E, QualType T) {
+ llvm::Constant *VisitCompoundLiteralExpr(const CompoundLiteralExpr *E,
+ QualType T) {
return Visit(E->getInitializer(), T);
}
- llvm::Constant *VisitCastExpr(CastExpr *E, QualType destType) {
+ llvm::Constant *ProduceIntToIntCast(const Expr *E, QualType DestType) {
+ QualType FromType = E->getType();
+ // See also HandleIntToIntCast in ExprConstant.cpp
+ if (FromType->isIntegerType())
+ if (llvm::Constant *C = Visit(E, FromType))
+ if (auto *CI = dyn_cast<llvm::ConstantInt>(C)) {
+ unsigned SrcWidth = CGM.getContext().getIntWidth(FromType);
+ unsigned DstWidth = CGM.getContext().getIntWidth(DestType);
+ if (DstWidth == SrcWidth)
+ return CI;
+ llvm::APInt A = FromType->isSignedIntegerType()
+ ? CI->getValue().sextOrTrunc(DstWidth)
+ : CI->getValue().zextOrTrunc(DstWidth);
+ return llvm::ConstantInt::get(CGM.getLLVMContext(), A);
+ }
+ return nullptr;
+ }
+
+ llvm::Constant *VisitCastExpr(const CastExpr *E, QualType destType) {
if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
CGM.EmitExplicitCastExprType(ECE, Emitter.CGF);
- Expr *subExpr = E->getSubExpr();
+ const Expr *subExpr = E->getSubExpr();
switch (E->getCastKind()) {
case CK_ToUnion: {
@@ -1091,16 +1149,38 @@ public:
destAS, destTy);
}
- case CK_LValueToRValue:
+ case CK_LValueToRValue: {
+ // We don't really support doing lvalue-to-rvalue conversions here; any
+ // interesting conversions should be done in Evaluate(). But as a
+ // special case, allow compound literals to support the gcc extension
+ // allowing "struct x {int x;} x = (struct x) {};".
+ if (const auto *E =
+ dyn_cast<CompoundLiteralExpr>(subExpr->IgnoreParens()))
+ return Visit(E->getInitializer(), destType);
+ return nullptr;
+ }
+
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
case CK_NoOp:
case CK_ConstructorConversion:
return Visit(subExpr, destType);
+ case CK_ArrayToPointerDecay:
+ if (const auto *S = dyn_cast<StringLiteral>(subExpr))
+ return CGM.GetAddrOfConstantStringFromLiteral(S).getPointer();
+ return nullptr;
+ case CK_NullToPointer:
+ if (Visit(subExpr, destType))
+ return CGM.EmitNullConstant(destType);
+ return nullptr;
+
case CK_IntToOCLSampler:
llvm_unreachable("global sampler variables are not generated");
+ case CK_IntegralCast:
+ return ProduceIntToIntCast(subExpr, destType);
+
case CK_Dependent: llvm_unreachable("saw dependent cast!");
case CK_BuiltinFnToFnPtr:
@@ -1135,7 +1215,6 @@ public:
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
- case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_BaseToDerived:
case CK_DerivedToBase:
@@ -1154,8 +1233,6 @@ public:
case CK_IntegralComplexToFloatingComplex:
case CK_PointerToIntegral:
case CK_PointerToBoolean:
- case CK_NullToPointer:
- case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToPointer:
case CK_IntegralToBoolean:
@@ -1171,64 +1248,131 @@ public:
case CK_IntegralToFixedPoint:
case CK_ZeroToOCLOpaqueType:
case CK_MatrixCast:
+ case CK_HLSLVectorTruncation:
+ case CK_HLSLArrayRValue:
return nullptr;
}
llvm_unreachable("Invalid CastKind");
}
- llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE, QualType T) {
+ llvm::Constant *VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *DIE,
+ QualType T) {
// No need for a DefaultInitExprScope: we don't handle 'this' in a
// constant expression.
return Visit(DIE->getExpr(), T);
}
- llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E, QualType T) {
+ llvm::Constant *VisitExprWithCleanups(const ExprWithCleanups *E, QualType T) {
return Visit(E->getSubExpr(), T);
}
- llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E,
- QualType T) {
- return Visit(E->getSubExpr(), T);
+ llvm::Constant *VisitIntegerLiteral(const IntegerLiteral *I, QualType T) {
+ return llvm::ConstantInt::get(CGM.getLLVMContext(), I->getValue());
+ }
+
+ static APValue withDestType(ASTContext &Ctx, const Expr *E, QualType SrcType,
+ QualType DestType, const llvm::APSInt &Value) {
+ if (!Ctx.hasSameType(SrcType, DestType)) {
+ if (DestType->isFloatingType()) {
+ llvm::APFloat Result =
+ llvm::APFloat(Ctx.getFloatTypeSemantics(DestType), 1);
+ llvm::RoundingMode RM =
+ E->getFPFeaturesInEffect(Ctx.getLangOpts()).getRoundingMode();
+ if (RM == llvm::RoundingMode::Dynamic)
+ RM = llvm::RoundingMode::NearestTiesToEven;
+ Result.convertFromAPInt(Value, Value.isSigned(), RM);
+ return APValue(Result);
+ }
+ }
+ return APValue(Value);
}
- llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) {
+ llvm::Constant *EmitArrayInitialization(const InitListExpr *ILE, QualType T) {
auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType());
assert(CAT && "can't emit array init for non-constant-bound array");
- unsigned NumInitElements = ILE->getNumInits();
- unsigned NumElements = CAT->getSize().getZExtValue();
+ uint64_t NumInitElements = ILE->getNumInits();
+ const uint64_t NumElements = CAT->getZExtSize();
+ for (const auto *Init : ILE->inits()) {
+ if (const auto *Embed =
+ dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {
+ NumInitElements += Embed->getDataElementCount() - 1;
+ if (NumInitElements > NumElements) {
+ NumInitElements = NumElements;
+ break;
+ }
+ }
+ }
// Initialising an array requires us to automatically
// initialise any elements that have not been initialised explicitly
- unsigned NumInitableElts = std::min(NumInitElements, NumElements);
+ uint64_t NumInitableElts = std::min<uint64_t>(NumInitElements, NumElements);
QualType EltType = CAT->getElementType();
// Initialize remaining array elements.
llvm::Constant *fillC = nullptr;
- if (Expr *filler = ILE->getArrayFiller()) {
+ if (const Expr *filler = ILE->getArrayFiller()) {
fillC = Emitter.tryEmitAbstractForMemory(filler, EltType);
if (!fillC)
return nullptr;
}
// Copy initializer elements.
- SmallVector<llvm::Constant*, 16> Elts;
+ SmallVector<llvm::Constant *, 16> Elts;
if (fillC && fillC->isNullValue())
Elts.reserve(NumInitableElts + 1);
else
Elts.reserve(NumElements);
llvm::Type *CommonElementType = nullptr;
- for (unsigned i = 0; i < NumInitableElts; ++i) {
- Expr *Init = ILE->getInit(i);
- llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType);
+ auto Emit = [&](const Expr *Init, unsigned ArrayIndex) {
+ llvm::Constant *C = nullptr;
+ C = Emitter.tryEmitPrivateForMemory(Init, EltType);
if (!C)
- return nullptr;
- if (i == 0)
+ return false;
+ if (ArrayIndex == 0)
CommonElementType = C->getType();
else if (C->getType() != CommonElementType)
CommonElementType = nullptr;
Elts.push_back(C);
+ return true;
+ };
+
+ unsigned ArrayIndex = 0;
+ QualType DestTy = CAT->getElementType();
+ for (unsigned i = 0; i < ILE->getNumInits(); ++i) {
+ const Expr *Init = ILE->getInit(i);
+ if (auto *EmbedS = dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {
+ StringLiteral *SL = EmbedS->getDataStringLiteral();
+ llvm::APSInt Value(CGM.getContext().getTypeSize(DestTy),
+ DestTy->isUnsignedIntegerType());
+ llvm::Constant *C;
+ for (unsigned I = EmbedS->getStartingElementPos(),
+ N = EmbedS->getDataElementCount();
+ I != EmbedS->getStartingElementPos() + N; ++I) {
+ Value = SL->getCodeUnit(I);
+ if (DestTy->isIntegerType()) {
+ C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value);
+ } else {
+ C = Emitter.tryEmitPrivateForMemory(
+ withDestType(CGM.getContext(), Init, EmbedS->getType(), DestTy,
+ Value),
+ EltType);
+ }
+ if (!C)
+ return nullptr;
+ Elts.push_back(C);
+ ArrayIndex++;
+ }
+ if ((ArrayIndex - EmbedS->getDataElementCount()) == 0)
+ CommonElementType = C->getType();
+ else if (C->getType() != CommonElementType)
+ CommonElementType = nullptr;
+ } else {
+ if (!Emit(Init, ArrayIndex))
+ return nullptr;
+ ArrayIndex++;
+ }
}
llvm::ArrayType *Desired =
@@ -1237,16 +1381,17 @@ public:
fillC);
}
- llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) {
+ llvm::Constant *EmitRecordInitialization(const InitListExpr *ILE,
+ QualType T) {
return ConstStructBuilder::BuildStruct(Emitter, ILE, T);
}
- llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E,
+ llvm::Constant *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E,
QualType T) {
return CGM.EmitNullConstant(T);
}
- llvm::Constant *VisitInitListExpr(InitListExpr *ILE, QualType T) {
+ llvm::Constant *VisitInitListExpr(const InitListExpr *ILE, QualType T) {
if (ILE->isTransparent())
return Visit(ILE->getInit(0), T);
@@ -1259,8 +1404,9 @@ public:
return nullptr;
}
- llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E,
- QualType destType) {
+ llvm::Constant *
+ VisitDesignatedInitUpdateExpr(const DesignatedInitUpdateExpr *E,
+ QualType destType) {
auto C = Visit(E->getBase(), destType);
if (!C)
return nullptr;
@@ -1274,12 +1420,13 @@ public:
llvm::Type *ValTy = CGM.getTypes().ConvertType(destType);
bool HasFlexibleArray = false;
- if (auto *RT = destType->getAs<RecordType>())
+ if (const auto *RT = destType->getAs<RecordType>())
HasFlexibleArray = RT->getDecl()->hasFlexibleArrayMember();
return Const.build(ValTy, HasFlexibleArray);
}
- llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E, QualType Ty) {
+ llvm::Constant *VisitCXXConstructExpr(const CXXConstructExpr *E,
+ QualType Ty) {
if (!E->getConstructor()->isTrivial())
return nullptr;
@@ -1289,32 +1436,38 @@ public:
assert(E->getConstructor()->isCopyOrMoveConstructor() &&
"trivial ctor has argument but isn't a copy/move ctor");
- Expr *Arg = E->getArg(0);
+ const Expr *Arg = E->getArg(0);
assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) &&
"argument to copy ctor is of wrong type");
- return Visit(Arg, Ty);
+ // Look through the temporary; it's just converting the value to an
+ // lvalue to pass it to the constructor.
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Arg))
+ return Visit(MTE->getSubExpr(), Ty);
+ // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
+ return nullptr;
}
return CGM.EmitNullConstant(Ty);
}
- llvm::Constant *VisitStringLiteral(StringLiteral *E, QualType T) {
+ llvm::Constant *VisitStringLiteral(const StringLiteral *E, QualType T) {
// This is a string literal initializing an array in an initializer.
return CGM.GetConstantArrayFromStringLiteral(E);
}
- llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E, QualType T) {
+ llvm::Constant *VisitObjCEncodeExpr(const ObjCEncodeExpr *E, QualType T) {
// This must be an @encode initializing an array in a static initializer.
// Don't emit it as the address of the string, emit the string data itself
// as an inline array.
std::string Str;
CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
const ConstantArrayType *CAT = CGM.getContext().getAsConstantArrayType(T);
+ assert(CAT && "String data not of constant array type!");
// Resize the string to the right size, adding zeros at the end, or
// truncating as needed.
- Str.resize(CAT->getSize().getZExtValue(), '\0');
+ Str.resize(CAT->getZExtSize(), '\0');
return llvm::ConstantDataArray::getString(VMContext, Str, false);
}
@@ -1322,6 +1475,17 @@ public:
return Visit(E->getSubExpr(), T);
}
+ llvm::Constant *VisitUnaryMinus(const UnaryOperator *U, QualType T) {
+ if (llvm::Constant *C = Visit(U->getSubExpr(), T))
+ if (auto *CI = dyn_cast<llvm::ConstantInt>(C))
+ return llvm::ConstantInt::get(CGM.getLLVMContext(), -CI->getValue());
+ return nullptr;
+ }
+
+ llvm::Constant *VisitPackIndexingExpr(const PackIndexingExpr *E, QualType T) {
+ return Visit(E->getSelectedExpr(), T);
+ }
+
// Utility methods
llvm::Type *ConvertType(QualType T) {
return CGM.getTypes().ConvertType(T);
@@ -1366,15 +1530,12 @@ ConstantEmitter::tryEmitAbstract(const APValue &value, QualType destType) {
llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
if (!CE->hasAPValueResult())
return nullptr;
- const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
- QualType RetType;
- if (auto *Call = dyn_cast<CallExpr>(Inner))
- RetType = Call->getCallReturnType(CGF->getContext());
- else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
- RetType = Ctor->getType();
- llvm::Constant *Res =
- emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
- return Res;
+
+ QualType RetType = CE->getType();
+ if (CE->isGLValue())
+ RetType = CGM.getContext().getLValueReferenceType(RetType);
+
+ return emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
}
llvm::Constant *
@@ -1392,9 +1553,11 @@ ConstantEmitter::emitAbstract(const Expr *E, QualType destType) {
llvm::Constant *
ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value,
- QualType destType) {
+ QualType destType,
+ bool EnablePtrAuthFunctionTypeDiscrimination) {
auto state = pushAbstract();
- auto C = tryEmitPrivate(value, destType);
+ auto C =
+ tryEmitPrivate(value, destType, EnablePtrAuthFunctionTypeDiscrimination);
C = validateAndPopAbstract(C, state);
if (!C) {
CGM.Error(loc,
@@ -1504,7 +1667,7 @@ namespace {
// messing around with llvm::Constant structures, which never itself
// does anything that should be visible in compiler output.
for (auto &entry : Locations) {
- assert(entry.first->getParent() == nullptr && "not a placeholder!");
+ assert(entry.first->getName() == "" && "not a placeholder!");
entry.first->replaceAllUsesWith(entry.second);
entry.first->eraseFromParent();
}
@@ -1544,7 +1707,7 @@ namespace {
}
void setLocation(llvm::GlobalVariable *placeholder) {
- assert(Locations.find(placeholder) == Locations.end() &&
+ assert(!Locations.contains(placeholder) &&
"already found location for placeholder!");
// Lazily fill in IndexValues with the values from Indices.
@@ -1567,13 +1730,8 @@ namespace {
IndexValues[i] = llvm::ConstantInt::get(CGM.Int32Ty, Indices[i]);
}
- // Form a GEP and then bitcast to the placeholder type so that the
- // replacement will succeed.
- llvm::Constant *location =
- llvm::ConstantExpr::getInBoundsGetElementPtr(BaseValueTy,
- Base, IndexValues);
- location = llvm::ConstantExpr::getBitCast(location,
- placeholder->getType());
+ llvm::Constant *location = llvm::ConstantExpr::getInBoundsGetElementPtr(
+ BaseValueTy, Base, IndexValues);
Locations.insert({placeholder, location});
}
@@ -1623,33 +1781,25 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
if (CD->isTrivial() && CD->isDefaultConstructor())
return CGM.EmitNullConstant(D.getType());
}
- InConstantContext = true;
}
+ InConstantContext = D.hasConstantInitialization();
QualType destType = D.getType();
+ const Expr *E = D.getInit();
+ assert(E && "No initializer to emit");
+
+ if (!destType->isReferenceType()) {
+ QualType nonMemoryDestType = getNonMemoryType(CGM, destType);
+ if (llvm::Constant *C = ConstExprEmitter(*this).Visit(E, nonMemoryDestType))
+ return emitForMemory(C, destType);
+ }
// Try to emit the initializer. Note that this can allow some things that
// are not allowed by tryEmitPrivateForMemory alone.
- if (auto value = D.evaluateValue()) {
+ if (APValue *value = D.evaluateValue())
return tryEmitPrivateForMemory(*value, destType);
- }
-
- // FIXME: Implement C++11 [basic.start.init]p2: if the initializer of a
- // reference is a constant expression, and the reference binds to a temporary,
- // then constant initialization is performed. ConstExprEmitter will
- // incorrectly emit a prvalue constant in this case, and the calling code
- // interprets that as the (pointer) value of the reference, rather than the
- // desired value of the referee.
- if (destType->isReferenceType())
- return nullptr;
- const Expr *E = D.getInit();
- assert(E && "No initializer to emit");
-
- auto nonMemoryDestType = getNonMemoryType(CGM, destType);
- auto C =
- ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), nonMemoryDestType);
- return (C ? emitForMemory(C, destType) : nullptr);
+ return nullptr;
}
llvm::Constant *
@@ -1681,6 +1831,43 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,
return (C ? emitForMemory(C, destType) : nullptr);
}
+/// Try to emit a constant signed pointer, given a raw pointer and the
+/// destination ptrauth qualifier.
+///
+/// This can fail if the qualifier needs address discrimination and the
+/// emitter is in an abstract mode.
+llvm::Constant *
+ConstantEmitter::tryEmitConstantSignedPointer(llvm::Constant *UnsignedPointer,
+ PointerAuthQualifier Schema) {
+ assert(Schema && "applying trivial ptrauth schema");
+
+ if (Schema.hasKeyNone())
+ return UnsignedPointer;
+
+ unsigned Key = Schema.getKey();
+
+ // Create an address placeholder if we're using address discrimination.
+ llvm::GlobalValue *StorageAddress = nullptr;
+ if (Schema.isAddressDiscriminated()) {
+ // We can't do this if the emitter is in an abstract state.
+ if (isAbstract())
+ return nullptr;
+
+ StorageAddress = getCurrentAddrPrivate();
+ }
+
+ llvm::ConstantInt *Discriminator =
+ llvm::ConstantInt::get(CGM.IntPtrTy, Schema.getExtraDiscriminator());
+
+ llvm::Constant *SignedPointer = CGM.getConstantSignedPointer(
+ UnsignedPointer, Key, StorageAddress, Discriminator);
+
+ if (Schema.isAddressDiscriminated())
+ registerCurrentAddrPrivate(SignedPointer, StorageAddress);
+
+ return SignedPointer;
+}
+
llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
llvm::Constant *C,
QualType destType) {
@@ -1704,9 +1891,33 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
}
// Zero-extend bool.
- if (C->getType()->isIntegerTy(1)) {
+ if (C->getType()->isIntegerTy(1) && !destType->isBitIntType()) {
llvm::Type *boolTy = CGM.getTypes().ConvertTypeForMem(destType);
- return llvm::ConstantExpr::getZExt(C, boolTy);
+ llvm::Constant *Res = llvm::ConstantFoldCastOperand(
+ llvm::Instruction::ZExt, C, boolTy, CGM.getDataLayout());
+ assert(Res && "Constant folding must succeed");
+ return Res;
+ }
+
+ if (destType->isBitIntType()) {
+ ConstantAggregateBuilder Builder(CGM);
+ llvm::Type *LoadStoreTy = CGM.getTypes().convertTypeForLoadStore(destType);
+ // ptrtoint/inttoptr should not involve _BitInt in constant expressions, so
+ // casting to ConstantInt is safe here.
+ auto *CI = cast<llvm::ConstantInt>(C);
+ llvm::Constant *Res = llvm::ConstantFoldCastOperand(
+ destType->isSignedIntegerOrEnumerationType() ? llvm::Instruction::SExt
+ : llvm::Instruction::ZExt,
+ CI, LoadStoreTy, CGM.getDataLayout());
+ if (CGM.getTypes().typeRequiresSplitIntoByteArray(destType, C->getType())) {
+ // Long _BitInt has array of bytes as in-memory type.
+ // So, split constant into individual bytes.
+ llvm::Type *DesiredTy = CGM.getTypes().ConvertTypeForMem(destType);
+ llvm::APInt Value = cast<llvm::ConstantInt>(Res)->getValue();
+ Builder.addBits(Value, /*OffsetInBits=*/0, /*AllowOverwrite=*/false);
+ return Builder.build(DesiredTy, /*AllowOversized*/ false);
+ }
+ return Res;
}
return C;
@@ -1714,6 +1925,12 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
QualType destType) {
+ assert(!destType->isVoidType() && "can't emit a void constant");
+
+ if (!destType->isReferenceType())
+ if (llvm::Constant *C = ConstExprEmitter(*this).Visit(E, destType))
+ return C;
+
Expr::EvalResult Result;
bool Success = false;
@@ -1723,13 +1940,10 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
else
Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext);
- llvm::Constant *C;
if (Success && !Result.HasSideEffects)
- C = tryEmitPrivate(Result.Val, destType);
- else
- C = ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), destType);
+ return tryEmitPrivate(Result.Val, destType);
- return C;
+ return nullptr;
}
llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT) {
@@ -1758,14 +1972,18 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
ConstantEmitter &Emitter;
const APValue &Value;
QualType DestType;
+ bool EnablePtrAuthFunctionTypeDiscrimination;
// Befriend StmtVisitorBase so that we don't have to expose Visit*.
friend StmtVisitorBase;
public:
ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
- QualType destType)
- : CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType) {}
+ QualType destType,
+ bool EnablePtrAuthFunctionTypeDiscrimination = true)
+ : CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType),
+ EnablePtrAuthFunctionTypeDiscrimination(
+ EnablePtrAuthFunctionTypeDiscrimination) {}
llvm::Constant *tryEmit();
@@ -1788,6 +2006,12 @@ private:
ConstantLValue VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *E);
+ ConstantLValue emitPointerAuthSignConstant(const CallExpr *E);
+ llvm::Constant *emitPointerAuthPointer(const Expr *E);
+ unsigned emitPointerAuthKey(const Expr *E);
+ std::pair<llvm::Constant *, llvm::ConstantInt *>
+ emitPointerAuthDiscriminator(const Expr *E);
+
bool hasNonZeroOffset() const {
return !Value.getLValueOffset().isZero();
}
@@ -1803,13 +2027,7 @@ private:
if (!hasNonZeroOffset())
return C;
- llvm::Type *origPtrTy = C->getType();
- unsigned AS = origPtrTy->getPointerAddressSpace();
- llvm::Type *charPtrTy = CGM.Int8Ty->getPointerTo(AS);
- C = llvm::ConstantExpr::getBitCast(C, charPtrTy);
- C = llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, C, getOffset());
- C = llvm::ConstantExpr::getPointerCast(C, origPtrTy);
- return C;
+ return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, C, getOffset());
}
};
@@ -1870,8 +2088,9 @@ ConstantLValueEmitter::tryEmitAbsolute(llvm::Type *destTy) {
// FIXME: signedness depends on the original integer type.
auto intptrTy = CGM.getDataLayout().getIntPtrType(destPtrTy);
llvm::Constant *C;
- C = llvm::ConstantExpr::getIntegerCast(getOffset(), intptrTy,
- /*isSigned*/ false);
+ C = llvm::ConstantFoldIntegerCast(getOffset(), intptrTy, /*isSigned*/ false,
+ CGM.getDataLayout());
+ assert(C && "Must have folded, as Offset is a ConstantInt");
C = llvm::ConstantExpr::getIntToPtr(C, destPtrTy);
return C;
}
@@ -1887,10 +2106,30 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
if (D->hasAttr<WeakRefAttr>())
return CGM.GetWeakRefReference(D).getPointer();
- if (auto FD = dyn_cast<FunctionDecl>(D))
- return CGM.GetAddrOfFunction(FD);
+ auto PtrAuthSign = [&](llvm::Constant *C) {
+ CGPointerAuthInfo AuthInfo;
+
+ if (EnablePtrAuthFunctionTypeDiscrimination)
+ AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
- if (auto VD = dyn_cast<VarDecl>(D)) {
+ if (AuthInfo) {
+ if (hasNonZeroOffset())
+ return ConstantLValue(nullptr);
+
+ C = applyOffset(C);
+ C = CGM.getConstantSignedPointer(
+ C, AuthInfo.getKey(), nullptr,
+ cast_or_null<llvm::ConstantInt>(AuthInfo.getDiscriminator()));
+ return ConstantLValue(C, /*applied offset*/ true);
+ }
+
+ return ConstantLValue(C);
+ };
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return PtrAuthSign(CGM.getRawFunctionPointer(FD));
+
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
// We can never refer to a variable with local storage.
if (!VD->hasLocalStorage()) {
if (VD->isFileVarDecl() || VD->hasExternalStorage())
@@ -1898,30 +2137,26 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
if (VD->isLocalVarDecl()) {
return CGM.getOrCreateStaticVarDecl(
- *VD, CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false));
+ *VD, CGM.getLLVMLinkageVarDefinition(VD));
}
}
}
- if (auto *GD = dyn_cast<MSGuidDecl>(D))
+ if (const auto *GD = dyn_cast<MSGuidDecl>(D))
return CGM.GetAddrOfMSGuidDecl(GD);
- if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(D))
+ if (const auto *GCD = dyn_cast<UnnamedGlobalConstantDecl>(D))
+ return CGM.GetAddrOfUnnamedGlobalConstantDecl(GCD);
+
+ if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D))
return CGM.GetAddrOfTemplateParamObject(TPO);
return nullptr;
}
// Handle typeid(T).
- if (TypeInfoLValue TI = base.dyn_cast<TypeInfoLValue>()) {
- llvm::Type *StdTypeInfoPtrTy =
- CGM.getTypes().ConvertType(base.getTypeInfoType())->getPointerTo();
- llvm::Constant *TypeInfo =
- CGM.GetAddrOfRTTIDescriptor(QualType(TI.getType(), 0));
- if (TypeInfo->getType() != StdTypeInfoPtrTy)
- TypeInfo = llvm::ConstantExpr::getBitCast(TypeInfo, StdTypeInfoPtrTy);
- return TypeInfo;
- }
+ if (TypeInfoLValue TI = base.dyn_cast<TypeInfoLValue>())
+ return CGM.GetAddrOfRTTIDescriptor(QualType(TI.getType(), 0));
// Otherwise, it must be an expression.
return Visit(base.get<const Expr*>());
@@ -1936,7 +2171,9 @@ ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) {
ConstantLValue
ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
- return tryEmitGlobalCompoundLiteral(CGM, Emitter.CGF, E);
+ ConstantEmitter CompoundLiteralEmitter(CGM, Emitter.CGF);
+ CompoundLiteralEmitter.setInConstantContext(Emitter.isInConstantContext());
+ return tryEmitGlobalCompoundLiteral(CompoundLiteralEmitter, E);
}
ConstantLValue
@@ -1953,7 +2190,7 @@ static ConstantLValue emitConstantObjCStringLiteral(const StringLiteral *S,
QualType T,
CodeGenModule &CGM) {
auto C = CGM.getObjCRuntime().GenerateConstantString(S);
- return C.getElementBitCast(CGM.getTypes().ConvertTypeForMem(T));
+ return C.withElementType(CGM.getTypes().ConvertTypeForMem(T));
}
ConstantLValue
@@ -1965,7 +2202,7 @@ ConstantLValue
ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
assert(E->isExpressibleAsConstantInitializer() &&
"this boxed expression can't be emitted as a compile-time constant");
- auto *SL = cast<StringLiteral>(E->getSubExpr()->IgnoreParenCasts());
+ const auto *SL = cast<StringLiteral>(E->getSubExpr()->IgnoreParenCasts());
return emitConstantObjCStringLiteral(SL, E->getType(), CGM);
}
@@ -1978,28 +2215,84 @@ ConstantLValue
ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *E) {
assert(Emitter.CGF && "Invalid address of label expression outside function");
llvm::Constant *Ptr = Emitter.CGF->GetAddrOfLabel(E->getLabel());
- Ptr = llvm::ConstantExpr::getBitCast(Ptr,
- CGM.getTypes().ConvertType(E->getType()));
return Ptr;
}
ConstantLValue
ConstantLValueEmitter::VisitCallExpr(const CallExpr *E) {
unsigned builtin = E->getBuiltinCallee();
+ if (builtin == Builtin::BI__builtin_function_start)
+ return CGM.GetFunctionStart(
+ E->getArg(0)->getAsBuiltinConstantDeclRef(CGM.getContext()));
+
+ if (builtin == Builtin::BI__builtin_ptrauth_sign_constant)
+ return emitPointerAuthSignConstant(E);
+
if (builtin != Builtin::BI__builtin___CFStringMakeConstantString &&
builtin != Builtin::BI__builtin___NSStringMakeConstantString)
return nullptr;
- auto literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts());
+ const auto *Literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts());
if (builtin == Builtin::BI__builtin___NSStringMakeConstantString) {
- return CGM.getObjCRuntime().GenerateConstantString(literal);
+ return CGM.getObjCRuntime().GenerateConstantString(Literal);
} else {
// FIXME: need to deal with UCN conversion issues.
- return CGM.GetAddrOfConstantCFString(literal);
+ return CGM.GetAddrOfConstantCFString(Literal);
}
}
ConstantLValue
+ConstantLValueEmitter::emitPointerAuthSignConstant(const CallExpr *E) {
+ llvm::Constant *UnsignedPointer = emitPointerAuthPointer(E->getArg(0));
+ unsigned Key = emitPointerAuthKey(E->getArg(1));
+ auto [StorageAddress, OtherDiscriminator] =
+ emitPointerAuthDiscriminator(E->getArg(2));
+
+ llvm::Constant *SignedPointer = CGM.getConstantSignedPointer(
+ UnsignedPointer, Key, StorageAddress, OtherDiscriminator);
+ return SignedPointer;
+}
+
+llvm::Constant *ConstantLValueEmitter::emitPointerAuthPointer(const Expr *E) {
+ Expr::EvalResult Result;
+ bool Succeeded = E->EvaluateAsRValue(Result, CGM.getContext());
+ assert(Succeeded);
+ (void)Succeeded;
+
+ // The assertions here are all checked by Sema.
+ assert(Result.Val.isLValue());
+ if (isa<FunctionDecl>(Result.Val.getLValueBase().get<const ValueDecl *>()))
+ assert(Result.Val.getLValueOffset().isZero());
+ return ConstantEmitter(CGM, Emitter.CGF)
+ .emitAbstract(E->getExprLoc(), Result.Val, E->getType(), false);
+}
+
+unsigned ConstantLValueEmitter::emitPointerAuthKey(const Expr *E) {
+ return E->EvaluateKnownConstInt(CGM.getContext()).getZExtValue();
+}
+
+std::pair<llvm::Constant *, llvm::ConstantInt *>
+ConstantLValueEmitter::emitPointerAuthDiscriminator(const Expr *E) {
+ E = E->IgnoreParens();
+
+ if (const auto *Call = dyn_cast<CallExpr>(E)) {
+ if (Call->getBuiltinCallee() ==
+ Builtin::BI__builtin_ptrauth_blend_discriminator) {
+ llvm::Constant *Pointer = ConstantEmitter(CGM).emitAbstract(
+ Call->getArg(0), Call->getArg(0)->getType());
+ auto *Extra = cast<llvm::ConstantInt>(ConstantEmitter(CGM).emitAbstract(
+ Call->getArg(1), Call->getArg(1)->getType()));
+ return {Pointer, Extra};
+ }
+ }
+
+ llvm::Constant *Result = ConstantEmitter(CGM).emitAbstract(E, E->getType());
+ if (Result->getType()->isPointerTy())
+ return {Result, nullptr};
+ return {nullptr, cast<llvm::ConstantInt>(Result)};
+}
+
+ConstantLValue
ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *E) {
StringRef functionName;
if (auto CGF = Emitter.CGF)
@@ -2024,22 +2317,22 @@ ConstantLValue
ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *E) {
assert(E->getStorageDuration() == SD_Static);
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- const Expr *Inner =
- E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+ const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
return CGM.GetAddrOfGlobalTemporary(E, Inner);
}
-llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
- QualType DestType) {
+llvm::Constant *
+ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
+ bool EnablePtrAuthFunctionTypeDiscrimination) {
switch (Value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
// Out-of-lifetime and indeterminate values can be modeled as 'undef'.
return llvm::UndefValue::get(CGM.getTypes().ConvertType(DestType));
case APValue::LValue:
- return ConstantLValueEmitter(*this, Value, DestType).tryEmit();
+ return ConstantLValueEmitter(*this, Value, DestType,
+ EnablePtrAuthFunctionTypeDiscrimination)
+ .tryEmit();
case APValue::Int:
return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
case APValue::FixedPoint:
@@ -2091,6 +2384,9 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
Inits[I] = llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt());
else if (Elt.isFloat())
Inits[I] = llvm::ConstantFP::get(CGM.getLLVMContext(), Elt.getFloat());
+ else if (Elt.isIndeterminate())
+ Inits[I] = llvm::UndefValue::get(CGM.getTypes().ConvertType(
+ DestType->castAs<VectorType>()->getElementType()));
else
llvm_unreachable("unsupported vector element type");
}
@@ -2153,6 +2449,11 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
llvm::ArrayType *Desired =
cast<llvm::ArrayType>(CGM.getTypes().ConvertType(DestType));
+
+ // Fix the type of incomplete arrays if the initializer isn't empty.
+ if (DestType->isIncompleteArrayType() && !Elts.empty())
+ Desired = llvm::ArrayType::get(Desired->getElementType(), Elts.size());
+
return EmitArrayConstant(CGM, Desired, CommonElementType, NumElements, Elts,
Filler);
}
@@ -2177,7 +2478,8 @@ void CodeGenModule::setAddrOfConstantCompoundLiteral(
ConstantAddress
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
assert(E->isFileScope() && "not a file-scope compound literal expr");
- return tryEmitGlobalCompoundLiteral(*this, nullptr, E);
+ ConstantEmitter emitter(*this);
+ return tryEmitGlobalCompoundLiteral(emitter, E);
}
llvm::Constant *
@@ -2225,8 +2527,10 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
// Ignore empty bases.
- if (base->isEmpty() ||
- CGM.getContext().getASTRecordLayout(base).getNonVirtualSize()
+ if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) ||
+ CGM.getContext()
+ .getASTRecordLayout(base)
+ .getNonVirtualSize()
.isZero())
continue;
@@ -2240,7 +2544,8 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
for (const auto *Field : record->fields()) {
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
// will fill in later.)
- if (!Field->isBitField() && !Field->isZeroSize(CGM.getContext())) {
+ if (!Field->isBitField() &&
+ !isEmptyFieldForLayout(CGM.getContext(), Field)) {
unsigned fieldIndex = layout.getLLVMFieldNo(Field);
elements[fieldIndex] = CGM.EmitNullConstant(Field->getType());
}
@@ -2262,7 +2567,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
// Ignore empty bases.
- if (base->isEmpty())
+ if (isEmptyRecordForLayout(CGM.getContext(), I.getType()))
continue;
unsigned fieldIndex = layout.getVirtualBaseIndex(base);
@@ -2319,7 +2624,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
llvm::Constant *Element =
ConstantEmitter::emitNullForMemory(*this, ElementTy);
- unsigned NumElements = CAT->getSize().getZExtValue();
+ unsigned NumElements = CAT->getZExtSize();
SmallVector<llvm::Constant *, 8> Array(NumElements, Element);
return llvm::ConstantArray::get(ATy, Array);
}