summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/Compiler.cpp')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp211
1 files changed, 112 insertions, 99 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index e3235d34e230..a21358338250 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -62,7 +62,7 @@ public:
OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,
bool NewInitializing, bool NewToLValue)
: Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
- OldInitializing(Ctx->Initializing), OldToLValue(NewToLValue) {
+ OldInitializing(Ctx->Initializing), OldToLValue(Ctx->ToLValue) {
Ctx->DiscardResult = NewDiscardResult;
Ctx->Initializing = NewInitializing;
Ctx->ToLValue = NewToLValue;
@@ -559,8 +559,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
// Possibly diagnose casts to enum types if the target type does not
// have a fixed size.
if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
- const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
- const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ const auto *ED = CE->getType()->castAsEnumDecl();
if (!ED->isFixed()) {
if (!this->emitCheckEnumValue(*FromT, ED, CE))
return false;
@@ -943,7 +942,7 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
if (!Result)
return false;
if (DiscardResult)
- return this->emitPop(*T, BO);
+ return this->emitPopBool(BO);
if (T != PT_Bool)
return this->emitCast(PT_Bool, *T, BO);
return true;
@@ -1377,14 +1376,20 @@ bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
template <class Emitter>
bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
+ const Expr *LHS = E->getLHS();
+ const Expr *RHS = E->getRHS();
assert(!E->isCommaOp() &&
"Comma op should be handled in VisitBinaryOperator");
assert(E->getType()->isVectorType());
- assert(E->getLHS()->getType()->isVectorType());
- assert(E->getRHS()->getType()->isVectorType());
+ assert(LHS->getType()->isVectorType());
+ assert(RHS->getType()->isVectorType());
+
+ // We can only handle vectors with primitive element types.
+ if (!canClassify(LHS->getType()->castAs<VectorType>()->getElementType()))
+ return false;
// Prepare storage for result.
- if (!Initializing && !E->isCompoundAssignmentOp()) {
+ if (!Initializing && !E->isCompoundAssignmentOp() && !E->isAssignmentOp()) {
UnsignedOrNone LocalIndex = allocateTemporary(E);
if (!LocalIndex)
return false;
@@ -1392,8 +1397,6 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
return false;
}
- const Expr *LHS = E->getLHS();
- const Expr *RHS = E->getRHS();
const auto *VecTy = E->getType()->getAs<VectorType>();
auto Op = E->isCompoundAssignmentOp()
? BinaryOperator::getOpForCompoundAssignment(E->getOpcode())
@@ -1403,6 +1406,21 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
PrimType RHSElemT = this->classifyVectorElementType(RHS->getType());
PrimType ResultElemT = this->classifyVectorElementType(E->getType());
+ if (E->getOpcode() == BO_Assign) {
+ assert(Ctx.getASTContext().hasSameUnqualifiedType(
+ LHS->getType()->castAs<VectorType>()->getElementType(),
+ RHS->getType()->castAs<VectorType>()->getElementType()));
+ if (!this->visit(LHS))
+ return false;
+ if (!this->visit(RHS))
+ return false;
+ if (!this->emitCopyArray(ElemT, 0, 0, VecTy->getNumElements(), E))
+ return false;
+ if (DiscardResult)
+ return this->emitPopPtr(E);
+ return true;
+ }
+
// Evaluate LHS and save value to LHSOffset.
unsigned LHSOffset =
this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
@@ -2248,7 +2266,9 @@ bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
assert(VAT);
if (VAT->getElementType()->isArrayType()) {
std::optional<APSInt> Res =
- VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx);
+ VAT->getSizeExpr()
+ ? VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx)
+ : std::nullopt;
if (Res) {
if (DiscardResult)
return true;
@@ -2892,25 +2912,20 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
OptPrimType SubExprT = classify(SubExpr);
bool IsStatic = E->getStorageDuration() == SD_Static;
if (IsStatic) {
- std::optional<unsigned> GlobalIndex = P.createGlobal(E);
+
+ UnsignedOrNone GlobalIndex = P.createGlobal(E);
if (!GlobalIndex)
return false;
const LifetimeExtendedTemporaryDecl *TempDecl =
E->getLifetimeExtendedTemporaryDecl();
- if (IsStatic)
- assert(TempDecl);
+ assert(TempDecl);
if (SubExprT) {
if (!this->visit(SubExpr))
return false;
- if (IsStatic) {
- if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
- return false;
- } else {
- if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E))
- return false;
- }
+ if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
+ return false;
return this->emitGetPtrGlobal(*GlobalIndex, E);
}
@@ -2921,9 +2936,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
return false;
if (!this->visitInitializer(SubExpr))
return false;
- if (IsStatic)
- return this->emitInitGlobalTempComp(TempDecl, E);
- return true;
+ return this->emitInitGlobalTempComp(TempDecl, E);
}
// For everyhing else, use local variables.
@@ -2989,7 +3002,7 @@ bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
if (T && !E->isLValue())
return this->delegate(Init);
- std::optional<unsigned> GlobalIndex = P.createGlobal(E);
+ UnsignedOrNone GlobalIndex = P.createGlobal(E);
if (!GlobalIndex)
return false;
@@ -3333,7 +3346,7 @@ bool Compiler<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);
- std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(UGCD);
+ UnsignedOrNone GlobalIndex = P.getOrCreateGlobal(UGCD);
if (!GlobalIndex)
return false;
@@ -3856,7 +3869,7 @@ bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
if (!RD->isCompleteDefinition())
return this->emitDummyPtr(GuidDecl, E);
- std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(GuidDecl);
+ UnsignedOrNone GlobalIndex = P.getOrCreateGlobal(GuidDecl);
if (!GlobalIndex)
return false;
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
@@ -3879,6 +3892,8 @@ bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
assert(classifyPrim(E->getType()) == PT_Bool);
+ if (E->isValueDependent())
+ return false;
if (DiscardResult)
return true;
return this->emitConstBool(E->isSatisfied(), E);
@@ -4169,6 +4184,31 @@ template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
return this->Visit(E);
}
+static const Expr *stripCheckedDerivedToBaseCasts(const Expr *E) {
+ if (const auto *PE = dyn_cast<ParenExpr>(E))
+ return stripCheckedDerivedToBaseCasts(PE->getSubExpr());
+
+ if (const auto *CE = dyn_cast<CastExpr>(E);
+ CE &&
+ (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
+ return stripCheckedDerivedToBaseCasts(CE->getSubExpr());
+
+ return E;
+}
+
+static const Expr *stripDerivedToBaseCasts(const Expr *E) {
+ if (const auto *PE = dyn_cast<ParenExpr>(E))
+ return stripDerivedToBaseCasts(PE->getSubExpr());
+
+ if (const auto *CE = dyn_cast<CastExpr>(E);
+ CE && (CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase ||
+ CE->getCastKind() == CK_NoOp))
+ return stripDerivedToBaseCasts(CE->getSubExpr());
+
+ return E;
+}
+
template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
if (E->getType().isNull())
return false;
@@ -4177,9 +4217,8 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
return this->discard(E);
// Create local variable to hold the return value.
- if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
- !canClassify(E->getType())) {
- UnsignedOrNone LocalIndex = allocateLocal(E);
+ if (!E->isGLValue() && !canClassify(E->getType())) {
+ UnsignedOrNone LocalIndex = allocateLocal(stripDerivedToBaseCasts(E));
if (!LocalIndex)
return false;
@@ -4608,8 +4647,8 @@ UnsignedOrNone Compiler<Emitter>::allocateTemporary(const Expr *E) {
template <class Emitter>
const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {
if (const PointerType *PT = dyn_cast<PointerType>(Ty))
- return PT->getPointeeType()->getAs<RecordType>();
- return Ty->getAs<RecordType>();
+ return PT->getPointeeType()->getAsCanonical<RecordType>();
+ return Ty->getAsCanonical<RecordType>();
}
template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {
@@ -4822,7 +4861,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
DeclScope<Emitter> LocalScope(this, VD);
// We've already seen and initialized this global.
- if (std::optional<unsigned> GlobalIndex = P.getGlobal(VD)) {
+ if (UnsignedOrNone GlobalIndex = P.getGlobal(VD)) {
if (P.getPtrGlobal(*GlobalIndex).isInitialized())
return checkDecl();
@@ -4831,7 +4870,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
return Init && checkDecl() && initGlobal(*GlobalIndex);
}
- std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
+ UnsignedOrNone GlobalIndex = P.createGlobal(VD, Init);
if (!GlobalIndex)
return false;
@@ -5057,18 +5096,6 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
return true;
}
-static const Expr *stripDerivedToBaseCasts(const Expr *E) {
- if (const auto *PE = dyn_cast<ParenExpr>(E))
- return stripDerivedToBaseCasts(PE->getSubExpr());
-
- if (const auto *CE = dyn_cast<CastExpr>(E);
- CE &&
- (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
- return stripDerivedToBaseCasts(CE->getSubExpr());
-
- return E;
-}
-
template <class Emitter>
bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
const FunctionDecl *FuncDecl = E->getDirectCallee();
@@ -5173,7 +5200,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
const auto *InstancePtr = MC->getImplicitObjectArgument();
if (isa_and_nonnull<CXXDestructorDecl>(CompilingFunction) ||
isa_and_nonnull<CXXConstructorDecl>(CompilingFunction)) {
- const auto *Stripped = stripDerivedToBaseCasts(InstancePtr);
+ const auto *Stripped = stripCheckedDerivedToBaseCasts(InstancePtr);
if (isa<CXXThisExpr>(Stripped)) {
FuncDecl =
cast<CXXMethodDecl>(FuncDecl)->getCorrespondingMethodInClass(
@@ -5228,6 +5255,12 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
const Function *Func = getFunction(FuncDecl);
if (!Func)
return false;
+
+ // In error cases, the function may be called with fewer arguments than
+ // parameters.
+ if (E->getNumArgs() < Func->getNumWrittenParams())
+ return false;
+
assert(HasRVO == Func->hasRVO());
bool HasQualifier = false;
@@ -6244,26 +6277,21 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
// First, destroy all fields.
for (const Record::Field &Field : llvm::reverse(R->fields())) {
const Descriptor *D = Field.Desc;
- if (!D->isPrimitive() && !D->isPrimitiveArray()) {
- if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
- return false;
- if (!this->emitDestruction(D, SourceInfo{}))
- return false;
- if (!this->emitPopPtr(SourceInfo{}))
- return false;
- }
+ if (D->hasTrivialDtor())
+ continue;
+ if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
+ return false;
+ if (!this->emitDestructionPop(D, SourceInfo{}))
+ return false;
}
}
for (const Record::Base &Base : llvm::reverse(R->bases())) {
- if (Base.R->isAnonymousUnion())
+ if (Base.R->hasTrivialDtor())
continue;
-
if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
return false;
- if (!this->emitRecordDestruction(Base.R, {}))
- return false;
- if (!this->emitPopPtr(SourceInfo{}))
+ if (!this->emitRecordDestructionPop(Base.R, {}))
return false;
}
@@ -6775,7 +6803,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
return F && this->emitGetFnPtr(F, E);
}
if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {
- if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) {
+ if (UnsignedOrNone Index = P.getOrCreateGlobal(D)) {
if (!this->emitGetPtrGlobal(*Index, E))
return false;
if (OptPrimType T = classify(E->getType())) {
@@ -7160,71 +7188,56 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
-bool Compiler<Emitter>::emitRecordDestruction(const Record *R, SourceInfo Loc) {
+bool Compiler<Emitter>::emitRecordDestructionPop(const Record *R,
+ SourceInfo Loc) {
assert(R);
- assert(!R->isAnonymousUnion());
+ assert(!R->hasTrivialDtor());
const CXXDestructorDecl *Dtor = R->getDestructor();
- if (!Dtor || Dtor->isTrivial())
- return true;
-
assert(Dtor);
const Function *DtorFunc = getFunction(Dtor);
if (!DtorFunc)
return false;
assert(DtorFunc->hasThisPointer());
assert(DtorFunc->getNumParams() == 1);
- if (!this->emitDupPtr(Loc))
- return false;
return this->emitCall(DtorFunc, 0, Loc);
}
/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
-bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
- SourceInfo Loc) {
+bool Compiler<Emitter>::emitDestructionPop(const Descriptor *Desc,
+ SourceInfo Loc) {
assert(Desc);
- assert(!Desc->isPrimitive());
- assert(!Desc->isPrimitiveArray());
+ assert(!Desc->hasTrivialDtor());
// Arrays.
if (Desc->isArray()) {
const Descriptor *ElemDesc = Desc->ElemDesc;
assert(ElemDesc);
- // Don't need to do anything for these.
- if (ElemDesc->isPrimitiveArray())
- return true;
+ unsigned N = Desc->getNumElems();
+ if (N == 0)
+ return this->emitPopPtr(Loc);
- // If this is an array of record types, check if we need
- // to call the element destructors at all. If not, try
- // to save the work.
- if (const Record *ElemRecord = ElemDesc->ElemRecord) {
- if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
- !Dtor || Dtor->isTrivial())
- return true;
- }
-
- if (unsigned N = Desc->getNumElems()) {
- for (ssize_t I = N - 1; I >= 0; --I) {
- if (!this->emitConstUint64(I, Loc))
- return false;
- if (!this->emitArrayElemPtrUint64(Loc))
- return false;
- if (!this->emitDestruction(ElemDesc, Loc))
- return false;
- if (!this->emitPopPtr(Loc))
- return false;
- }
+ for (ssize_t I = N - 1; I >= 1; --I) {
+ if (!this->emitConstUint64(I, Loc))
+ return false;
+ if (!this->emitArrayElemPtrUint64(Loc))
+ return false;
+ if (!this->emitDestructionPop(ElemDesc, Loc))
+ return false;
}
- return true;
+ // Last iteration, removes the instance pointer from the stack.
+ if (!this->emitConstUint64(0, Loc))
+ return false;
+ if (!this->emitArrayElemPtrPopUint64(Loc))
+ return false;
+ return this->emitDestructionPop(ElemDesc, Loc);
}
assert(Desc->ElemRecord);
- if (Desc->ElemRecord->isAnonymousUnion())
- return true;
-
- return this->emitRecordDestruction(Desc->ElemRecord, Loc);
+ assert(!Desc->ElemRecord->hasTrivialDtor());
+ return this->emitRecordDestructionPop(Desc->ElemRecord, Loc);
}
/// Create a dummy pointer for the given decl (or expr) and