aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp125
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h2
-rw-r--r--clang/lib/AST/ByteCode/Disasm.cpp2
-rw-r--r--clang/lib/AST/ByteCode/DynamicAllocator.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Interp.h25
-rw-r--r--clang/lib/AST/ByteCode/InterpBlock.cpp43
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp28
-rw-r--r--clang/lib/AST/ByteCode/InterpStack.h2
-rw-r--r--clang/lib/AST/ByteCode/InterpState.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td1
-rw-r--r--clang/lib/AST/ByteCode/Pointer.cpp30
-rw-r--r--clang/lib/AST/ByteCode/Pointer.h21
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp6
-rw-r--r--clang/lib/AST/ByteCode/Program.h3
15 files changed, 168 insertions, 126 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 07efd6f8..d0ddb2e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -25,34 +25,6 @@ using APSInt = llvm::APSInt;
namespace clang {
namespace interp {
-static bool refersToUnion(const Expr *E) {
- for (;;) {
- if (const auto *ME = dyn_cast<MemberExpr>(E)) {
- if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
- FD && FD->getParent()->isUnion())
- return true;
- E = ME->getBase();
- continue;
- }
-
- if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
- E = ASE->getBase()->IgnoreImplicit();
- continue;
- }
-
- if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
- ICE && (ICE->getCastKind() == CK_NoOp ||
- ICE->getCastKind() == CK_DerivedToBase ||
- ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
- E = ICE->getSubExpr();
- continue;
- }
-
- break;
- }
- return false;
-}
-
static std::optional<bool> getBoolValue(const Expr *E) {
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
CE && CE->hasAPValueResult() &&
@@ -1050,7 +1022,8 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
if (classifyPrim(E) != PT_Ptr)
return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
return true;
- } else if (Op == BO_Sub) {
+ }
+ if (Op == BO_Sub) {
if (!this->emitSubOffset(OffsetType, E))
return false;
@@ -3731,7 +3704,7 @@ bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {
return true;
const Function *Func = nullptr;
- if (auto F = Ctx.getOrCreateObjCBlock(E))
+ if (const Function *F = Ctx.getOrCreateObjCBlock(E))
Func = F;
if (!Func)
@@ -4316,7 +4289,8 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
return false;
}
return true;
- } else if (ElemType->isRecordType()) {
+ }
+ if (ElemType->isRecordType()) {
const Record *R = getRecord(ElemType);
for (size_t I = 0; I != NumElems; ++I) {
@@ -4330,7 +4304,8 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
return false;
}
return true;
- } else if (ElemType->isArrayType()) {
+ }
+ if (ElemType->isArrayType()) {
for (size_t I = 0; I != NumElems; ++I) {
if (!this->emitConstUint32(I, E))
return false;
@@ -4802,11 +4777,10 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
if (!this->visit(Init))
return false;
return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
- } else {
+ }
if (!this->visit(Init))
return false;
return this->emitSetLocal(*VarT, Offset, VD);
- }
}
} else {
if (std::optional<unsigned> Offset = this->allocateLocal(
@@ -4833,7 +4807,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
assert(!DiscardResult);
if (Val.isInt())
return this->emitConst(Val.getInt(), ValType, E);
- else if (Val.isFloat()) {
+ if (Val.isFloat()) {
APFloat F = Val.getFloat();
return this->emitFloat(F, E);
}
@@ -4844,9 +4818,8 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
APValue::LValueBase Base = Val.getLValueBase();
if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
return this->visit(BaseExpr);
- else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
+ if (const auto *VD = Base.dyn_cast<const ValueDecl *>())
return this->visitDeclRef(VD, E);
- }
} else if (Val.isMemberPointer()) {
if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
return this->emitGetMemberPtr(MemberDecl, E);
@@ -4882,7 +4855,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
}
}
return true;
- } else if (Val.isUnion()) {
+ }
+ if (Val.isUnion()) {
const FieldDecl *UnionField = Val.getUnionField();
const Record *R = this->getRecord(UnionField->getParent());
assert(R);
@@ -4892,7 +4866,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
if (!this->visitAPValue(F, T, E))
return false;
return this->emitInitField(T, RF->Offset, E);
- } else if (Val.isArray()) {
+ }
+ if (Val.isArray()) {
const auto *ArrType = T->getAsArrayTypeUnsafe();
QualType ElemType = ArrType->getElementType();
for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
@@ -5009,12 +4984,10 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
// Calls to replaceable operator new/operator delete.
if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
- if (FuncDecl->getDeclName().isAnyOperatorNew()) {
+ if (FuncDecl->getDeclName().isAnyOperatorNew())
return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);
- } else {
- assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
- return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
- }
+ assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
+ return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
}
// Explicit calls to trivial destructors
@@ -5401,6 +5374,53 @@ bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
return true;
}
+static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
+ assert(FD);
+ assert(FD->getParent()->isUnion());
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(FD->getParent());
+ return !CXXRD || CXXRD->hasTrivialDefaultConstructor();
+}
+
+template <class Emitter> bool Compiler<Emitter>::refersToUnion(const Expr *E) {
+ for (;;) {
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ FD && FD->getParent()->isUnion() && hasTrivialDefaultCtorParent(FD))
+ return true;
+ E = ME->getBase();
+ continue;
+ }
+
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+ E = ASE->getBase()->IgnoreImplicit();
+ continue;
+ }
+
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
+ ICE && (ICE->getCastKind() == CK_NoOp ||
+ ICE->getCastKind() == CK_DerivedToBase ||
+ ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
+ E = ICE->getSubExpr();
+ continue;
+ }
+
+ if (const auto *This = dyn_cast<CXXThisExpr>(E)) {
+ const auto *ThisRecord =
+ This->getType()->getPointeeType()->getAsRecordDecl();
+ if (!ThisRecord->isUnion())
+ return false;
+ // Otherwise, always activate if we're in the ctor.
+ if (const auto *Ctor =
+ dyn_cast_if_present<CXXConstructorDecl>(CompilingFunction))
+ return Ctor->getParent() == ThisRecord;
+ return false;
+ }
+
+ break;
+ }
+ return false;
+}
+
template <class Emitter>
bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
bool EvaluateConditionDecl) {
@@ -5436,7 +5456,9 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
return false;
this->emitCleanup();
return this->emitRet(*ReturnType, RS);
- } else if (RE->getType()->isVoidType()) {
+ }
+
+ if (RE->getType()->isVoidType()) {
if (!this->visit(RE))
return false;
} else {
@@ -5481,7 +5503,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {
if (*BoolValue)
return visitChildStmt(IS->getThen());
- else if (const Stmt *Else = IS->getElse())
+ if (const Stmt *Else = IS->getElse())
return visitChildStmt(Else);
return true;
}
@@ -5933,16 +5955,15 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
return false;
if (OptPrimType T = this->classify(InitExpr)) {
+ if (Activate && !this->emitActivateThisField(FieldOffset, InitExpr))
+ return false;
+
if (!this->visit(InitExpr))
return false;
bool BitField = F->isBitField();
- if (BitField && Activate)
- return this->emitInitThisBitFieldActivate(*T, F, FieldOffset, InitExpr);
if (BitField)
return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
- if (Activate)
- return this->emitInitThisFieldActivate(*T, FieldOffset, InitExpr);
return this->emitInitThisField(*T, FieldOffset, InitExpr);
}
// Non-primitive case. Get a pointer to the field-to-initialize
@@ -5974,7 +5995,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
if (!this->emitThis(Ctor))
return false;
- auto PVD = Ctor->getParamDecl(0);
+ const ParmVarDecl *PVD = Ctor->getParamDecl(0);
ParamOffset PO = this->Params[PVD]; // Must exist.
if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))
@@ -6135,7 +6156,7 @@ bool Compiler<Emitter>::compileUnionAssignmentOperator(
if (!this->emitThis(MD))
return false;
- auto PVD = MD->getParamDecl(0);
+ const ParmVarDecl *PVD = MD->getParamDecl(0);
ParamOffset PO = this->Params[PVD]; // Must exist.
if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 5032693..3a26342 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -401,6 +401,8 @@ private:
bool checkLiteralType(const Expr *E);
bool maybeEmitDeferredVarInit(const VarDecl *VD);
+ bool refersToUnion(const Expr *E);
+
protected:
/// Variable to storage mapping.
llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index 74399d1..5049a65 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -531,7 +531,7 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
Desc->dump(OS);
OS << ")\n";
unsigned NPointers = 0;
- for (const Pointer *P = Pointers; P; P = P->Next) {
+ for (const Pointer *P = Pointers; P; P = P->asBlockPointer().Next) {
++NPointers;
}
OS << " EvalID: " << EvalID << '\n';
diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
index 4f0f511..169250c 100644
--- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp
+++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
@@ -27,7 +27,7 @@ void DynamicAllocator::cleanup() {
B->invokeDtor();
if (B->hasPointers()) {
while (B->Pointers) {
- Pointer *Next = B->Pointers->Next;
+ Pointer *Next = B->Pointers->asBlockPointer().Next;
B->Pointers->PointeeStorage.BS.Pointee = nullptr;
B->Pointers = Next;
}
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 5463aec..224d65c 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -845,7 +845,7 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return true;
}
-bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
+static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index b42c766..2602ed7 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -481,13 +481,11 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
Floating RA = S.allocFloat(A.getSemantics());
RA.copy(ResR);
Result.elem<Floating>(0) = RA; // Floating(ResR);
- Result.atIndex(0).initialize();
Floating RI = S.allocFloat(A.getSemantics());
RI.copy(ResI);
Result.elem<Floating>(1) = RI; // Floating(ResI);
- Result.atIndex(1).initialize();
- Result.initialize();
+ Result.initializeAllElements();
} else {
// Integer element type.
const T &LHSR = LHS.elem<T>(0);
@@ -505,7 +503,6 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
return false;
if (T::sub(A, B, Bits, &Result.elem<T>(0)))
return false;
- Result.atIndex(0).initialize();
// imag(Result) = (real(LHS) * imag(RHS)) + (imag(LHS) * real(RHS))
if (T::mul(LHSR, RHSI, Bits, &A))
@@ -514,8 +511,8 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
return false;
if (T::add(A, B, Bits, &Result.elem<T>(1)))
return false;
- Result.atIndex(1).initialize();
Result.initialize();
+ Result.initializeAllElements();
}
return true;
@@ -541,14 +538,12 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
Floating RA = S.allocFloat(A.getSemantics());
RA.copy(ResR);
Result.elem<Floating>(0) = RA; // Floating(ResR);
- Result.atIndex(0).initialize();
Floating RI = S.allocFloat(A.getSemantics());
RI.copy(ResI);
Result.elem<Floating>(1) = RI; // Floating(ResI);
- Result.atIndex(1).initialize();
- Result.initialize();
+ Result.initializeAllElements();
} else {
// Integer element type.
const T &LHSR = LHS.elem<T>(0);
@@ -590,7 +585,6 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
return false;
if (T::div(ResultR, Den, Bits, &ResultR))
return false;
- Result.atIndex(0).initialize();
// imag(Result) = ((imag(LHS) * real(RHS)) - (real(LHS) * imag(RHS))) / Den
if (T::mul(LHSI, RHSR, Bits, &A) || T::mul(LHSR, RHSI, Bits, &B))
@@ -599,8 +593,7 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
return false;
if (T::div(ResultI, Den, Bits, &ResultI))
return false;
- Result.atIndex(1).initialize();
- Result.initialize();
+ Result.initializeAllElements();
}
return true;
@@ -1983,6 +1976,16 @@ static inline bool Activate(InterpState &S, CodePtr OpPC) {
return true;
}
+static inline bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
+ if (S.checkingPotentialConstantExpression())
+ return false;
+
+ const Pointer &Ptr = S.Current->getThis();
+ assert(Ptr.atField(I).canBeInitialized());
+ Ptr.atField(I).activate();
+ return true;
+}
+
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreActivate(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp
index f603078..963b54e 100644
--- a/clang/lib/AST/ByteCode/InterpBlock.cpp
+++ b/clang/lib/AST/ByteCode/InterpBlock.cpp
@@ -27,9 +27,9 @@ void Block::addPointer(Pointer *P) {
assert(!hasPointer(P));
#endif
if (Pointers)
- Pointers->Prev = P;
- P->Next = Pointers;
- P->Prev = nullptr;
+ Pointers->PointeeStorage.BS.Prev = P;
+ P->PointeeStorage.BS.Next = Pointers;
+ P->PointeeStorage.BS.Prev = nullptr;
Pointers = P;
#ifndef NDEBUG
assert(hasPointer(P));
@@ -48,13 +48,15 @@ void Block::removePointer(Pointer *P) {
assert(hasPointer(P));
#endif
+ BlockPointer &BP = P->PointeeStorage.BS;
+
if (Pointers == P)
- Pointers = P->Next;
+ Pointers = BP.Next;
- if (P->Prev)
- P->Prev->Next = P->Next;
- if (P->Next)
- P->Next->Prev = P->Prev;
+ if (BP.Prev)
+ BP.Prev->PointeeStorage.BS.Next = BP.Next;
+ if (BP.Next)
+ BP.Next->PointeeStorage.BS.Prev = BP.Prev;
P->PointeeStorage.BS.Pointee = nullptr;
#ifndef NDEBUG
assert(!hasPointer(P));
@@ -68,7 +70,9 @@ void Block::cleanup() {
void Block::replacePointer(Pointer *Old, Pointer *New) {
assert(Old);
+ assert(Old->isBlockPointer());
assert(New);
+ assert(New->isBlockPointer());
assert(Old != New);
if (IsStatic) {
assert(!Pointers);
@@ -78,17 +82,20 @@ void Block::replacePointer(Pointer *Old, Pointer *New) {
assert(hasPointer(Old));
#endif
- if (Old->Prev)
- Old->Prev->Next = New;
- if (Old->Next)
- Old->Next->Prev = New;
- New->Prev = Old->Prev;
- New->Next = Old->Next;
+ BlockPointer &OldBP = Old->PointeeStorage.BS;
+ BlockPointer &NewBP = New->PointeeStorage.BS;
+
+ if (OldBP.Prev)
+ OldBP.Prev->PointeeStorage.BS.Next = New;
+ if (OldBP.Next)
+ OldBP.Next->PointeeStorage.BS.Prev = New;
+ NewBP.Prev = OldBP.Prev;
+ NewBP.Next = OldBP.Next;
if (Pointers == Old)
Pointers = New;
- Old->PointeeStorage.BS.Pointee = nullptr;
- New->PointeeStorage.BS.Pointee = this;
+ OldBP.Pointee = nullptr;
+ NewBP.Pointee = this;
#ifndef NDEBUG
assert(!hasPointer(Old));
assert(hasPointer(New));
@@ -97,7 +104,7 @@ void Block::replacePointer(Pointer *Old, Pointer *New) {
#ifndef NDEBUG
bool Block::hasPointer(const Pointer *P) const {
- for (const Pointer *C = Pointers; C; C = C->Next) {
+ for (const Pointer *C = Pointers; C; C = C->asBlockPointer().Next) {
if (C == P)
return true;
}
@@ -120,7 +127,7 @@ DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
// Transfer pointers.
B.Pointers = Blk->Pointers;
- for (Pointer *P = Blk->Pointers; P; P = P->Next)
+ for (Pointer *P = Blk->Pointers; P; P = P->asBlockPointer().Next)
P->PointeeStorage.BS.Pointee = &B;
Blk->Pointers = nullptr;
}
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 19d4c0c..f908d02 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -240,9 +240,9 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
T CB = PB.deref<T>();
if (CA > CB)
return returnResult(1);
- else if (CA < CB)
+ if (CA < CB)
return returnResult(-1);
- else if (CA.isZero() || CB.isZero())
+ if (CA.isZero() || CB.isZero())
return returnResult(0);
});
continue;
@@ -253,7 +253,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
if (CA > CB)
return returnResult(1);
- else if (CA < CB)
+ if (CA < CB)
return returnResult(-1);
if (CA == 0 || CB == 0)
return returnResult(0);
@@ -1048,7 +1048,7 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
PtrArg = ICE->getSubExpr();
}
- if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {
+ if (const auto *PtrTy = PtrArg->getType()->getAs<PointerType>()) {
QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isIncompleteType() &&
S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
@@ -1099,10 +1099,8 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
Pointer &Result = S.Stk.peek<Pointer>();
Result.elem<Floating>(0) = Arg1;
- Result.atIndex(0).initialize();
Result.elem<Floating>(1) = Arg2;
- Result.atIndex(1).initialize();
- Result.initialize();
+ Result.initializeAllElements();
return true;
}
@@ -1728,9 +1726,9 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
Dst.elem<T>(I) =
T::from(Arg.elem<T>(I).toAPSInt().reverseBits().getZExtValue());
}
- Dst.atIndex(I).initialize();
});
}
+ Dst.initializeAllElements();
return true;
}
@@ -1967,7 +1965,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
if (A < B) {
pushInteger(S, -1, Call->getType());
return true;
- } else if (A > B) {
+ }
+ if (A > B) {
pushInteger(S, 1, Call->getType());
return true;
}
@@ -1979,7 +1978,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
if (A < B) {
pushInteger(S, -1, Call->getType());
return true;
- } else if (A > B) {
+ }
+ if (A > B) {
pushInteger(S, 1, Call->getType());
return true;
}
@@ -2312,12 +2312,10 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC,
llvm_unreachable("Wrong builtin ID");
}
- INT_TYPE_SWITCH_NO_BOOL(ElemT, {
- const Pointer &E = Dst.atIndex(I);
- E.deref<T>() = static_cast<T>(Result);
- E.initialize();
- });
+ INT_TYPE_SWITCH_NO_BOOL(ElemT,
+ { Dst.elem<T>(I) = static_cast<T>(Result); });
}
+ Dst.initializeAllElements();
return true;
}
diff --git a/clang/lib/AST/ByteCode/InterpStack.h b/clang/lib/AST/ByteCode/InterpStack.h
index 0b76f1d..580494e 100644
--- a/clang/lib/AST/ByteCode/InterpStack.h
+++ b/clang/lib/AST/ByteCode/InterpStack.h
@@ -14,11 +14,9 @@
#define LLVM_CLANG_AST_INTERP_INTERPSTACK_H
#include "FixedPoint.h"
-#include "FunctionPointer.h"
#include "IntegralAP.h"
#include "MemberPointer.h"
#include "PrimType.h"
-#include <memory>
#include <vector>
namespace clang {
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp
index 7848f29..3010847 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -52,7 +52,7 @@ void InterpState::cleanup() {
// As a last resort, make sure all pointers still pointing to a dead block
// don't point to it anymore.
for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) {
- for (Pointer *P = DB->B.Pointers; P; P = P->Next) {
+ for (Pointer *P = DB->B.Pointers; P; P = P->asBlockPointer().Next) {
P->PointeeStorage.BS.Pointee = nullptr;
}
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 80703ad..abfed77 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -510,6 +510,7 @@ def StoreBitFieldActivate : StoreBitFieldOpcode {}
def StoreBitFieldActivatePop : StoreBitFieldOpcode {}
def Activate : Opcode {}
+def ActivateThisField : Opcode { let Args = [ArgUint32]; }
// [Pointer, Value] -> []
def Init : StoreOpcode {}
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 4019b74..dec2088 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -16,6 +16,7 @@
#include "MemberPointer.h"
#include "PrimType.h"
#include "Record.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -41,7 +42,7 @@ Pointer::Pointer(Block *Pointee, unsigned Base, uint64_t Offset)
: Offset(Offset), StorageKind(Storage::Block) {
assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
- PointeeStorage.BS = {Pointee, Base};
+ PointeeStorage.BS = {Pointee, Base, nullptr, nullptr};
if (Pointee)
Pointee->addPointer(this);
@@ -66,14 +67,14 @@ Pointer::~Pointer() {
}
}
-void Pointer::operator=(const Pointer &P) {
+Pointer &Pointer::operator=(const Pointer &P) {
// If the current storage type is Block, we need to remove
// this pointer from the block.
if (isBlockPointer()) {
if (P.isBlockPointer() && this->block() == P.block()) {
Offset = P.Offset;
PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
- return;
+ return *this;
}
if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -88,7 +89,6 @@ void Pointer::operator=(const Pointer &P) {
if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
- PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee;
if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);
@@ -101,16 +101,17 @@ void Pointer::operator=(const Pointer &P) {
} else {
assert(false && "Unhandled storage kind");
}
+ return *this;
}
-void Pointer::operator=(Pointer &&P) {
+Pointer &Pointer::operator=(Pointer &&P) {
// If the current storage type is Block, we need to remove
// this pointer from the block.
if (isBlockPointer()) {
if (P.isBlockPointer() && this->block() == P.block()) {
Offset = P.Offset;
PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
- return;
+ return *this;
}
if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -125,7 +126,6 @@ void Pointer::operator=(Pointer &&P) {
if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
- PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee;
if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);
@@ -138,6 +138,7 @@ void Pointer::operator=(Pointer &&P) {
} else {
assert(false && "Unhandled storage kind");
}
+ return *this;
}
APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
@@ -492,6 +493,19 @@ void Pointer::initialize() const {
getInlineDesc()->IsInitialized = true;
}
+void Pointer::initializeAllElements() const {
+ assert(getFieldDesc()->isPrimitiveArray());
+ assert(isArrayRoot());
+
+ InitMapPtr &IM = getInitMap();
+ if (!IM) {
+ IM = std::make_pair(true, nullptr);
+ } else {
+ IM->first = true;
+ IM->second.reset();
+ }
+}
+
void Pointer::activate() const {
// Field has its bit in an inline descriptor.
assert(PointeeStorage.BS.Base != 0 &&
@@ -603,7 +617,7 @@ bool Pointer::pointsToStringLiteral() const {
return false;
const Expr *E = block()->getDescriptor()->asExpr();
- return E && isa<StringLiteral>(E);
+ return isa_and_nonnull<StringLiteral>(E);
}
std::optional<std::pair<Pointer, Pointer>>
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index d17eba5..5bafc5b 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -39,6 +39,10 @@ struct BlockPointer {
Block *Pointee;
/// Start of the current subfield.
unsigned Base;
+ /// Previous link in the pointer chain.
+ Pointer *Prev;
+ /// Next link in the pointer chain.
+ Pointer *Next;
};
struct IntPointer {
@@ -120,8 +124,8 @@ public:
Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
~Pointer();
- void operator=(const Pointer &P);
- void operator=(Pointer &&P);
+ Pointer &operator=(const Pointer &P);
+ Pointer &operator=(Pointer &&P);
/// Equality operators are just for tests.
bool operator==(const Pointer &P) const {
@@ -725,6 +729,10 @@ public:
/// Initializes a field.
void initialize() const;
+ /// Initialize all elements of a primitive array at once. This can be
+ /// used in situations where we *know* we have initialized *all* elements
+ /// of a primtive array.
+ void initializeAllElements() const;
/// Activats a field.
void activate() const;
/// Deactivates an entire strurcutre.
@@ -761,7 +769,7 @@ public:
if (Offset < Other.Offset)
return ComparisonCategoryResult::Less;
- else if (Offset > Other.Offset)
+ if (Offset > Other.Offset)
return ComparisonCategoryResult::Greater;
return ComparisonCategoryResult::Equal;
@@ -828,15 +836,10 @@ private:
/// Offset into the storage.
uint64_t Offset = 0;
- /// Previous link in the pointer chain.
- Pointer *Prev = nullptr;
- /// Next link in the pointer chain.
- Pointer *Next = nullptr;
-
Storage StorageKind = Storage::Int;
union {
- BlockPointer BS;
IntPointer Int;
+ BlockPointer BS;
FunctionPointer Fn;
TypeidPointer Typeid;
} PointeeStorage;
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 7002724..2421ec4 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -418,7 +418,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
}
return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary,
IsMutable);
- } else {
+ }
// Arrays of composites. In this case, the array is a list of pointers,
// followed by the actual elements.
const Descriptor *ElemDesc = createDescriptor(
@@ -430,7 +430,6 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
return {};
return allocateDescriptor(D, Ty, ElemDesc, MDSize, NumElems, IsConst,
IsTemporary, IsMutable);
- }
}
// Array of unknown bounds - cannot be accessed and pointer arithmetic
@@ -440,14 +439,13 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
if (OptPrimType T = Ctx.classify(ElemTy)) {
return allocateDescriptor(D, *T, MDSize, IsConst, IsTemporary,
Descriptor::UnknownSize{});
- } else {
+ }
const Descriptor *Desc = createDescriptor(
D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary);
if (!Desc)
return nullptr;
return allocateDescriptor(D, Desc, MDSize, IsTemporary,
Descriptor::UnknownSize{});
- }
}
}
diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h
index 5d9c422..207ceef 100644
--- a/clang/lib/AST/ByteCode/Program.h
+++ b/clang/lib/AST/ByteCode/Program.h
@@ -19,10 +19,7 @@
#include "Record.h"
#include "Source.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
-#include <map>
#include <vector>
namespace clang {