diff options
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.cpp | 34 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.h | 1 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Disasm.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/DynamicAllocator.cpp | 21 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Interp.h | 40 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/InterpBlock.cpp | 43 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/InterpBuiltin.cpp | 14 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/InterpState.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Opcodes.td | 4 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Pointer.cpp | 17 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Pointer.h | 15 |
11 files changed, 116 insertions, 77 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index d0ddb2e..8b9e5e0 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -106,25 +106,14 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const { return true; } -/// Scope managing label targets. -template <class Emitter> class LabelScope { -public: - virtual ~LabelScope() {} - -protected: - LabelScope(Compiler<Emitter> *Ctx) : Ctx(Ctx) {} - /// Compiler instance. - Compiler<Emitter> *Ctx; -}; - /// Sets the context for break/continue statements. -template <class Emitter> class LoopScope final : public LabelScope<Emitter> { +template <class Emitter> class LoopScope final { public: using LabelTy = typename Compiler<Emitter>::LabelTy; using OptLabelTy = typename Compiler<Emitter>::OptLabelTy; LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel) - : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), + : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel), OldContinueLabel(Ctx->ContinueLabel), OldBreakVarScope(Ctx->BreakVarScope), OldContinueVarScope(Ctx->ContinueVarScope) { @@ -142,6 +131,7 @@ public: } private: + Compiler<Emitter> *Ctx; OptLabelTy OldBreakLabel; OptLabelTy OldContinueLabel; VariableScope<Emitter> *OldBreakVarScope; @@ -149,7 +139,7 @@ private: }; // Sets the context for a switch scope, mapping labels. -template <class Emitter> class SwitchScope final : public LabelScope<Emitter> { +template <class Emitter> class SwitchScope final { public: using LabelTy = typename Compiler<Emitter>::LabelTy; using OptLabelTy = typename Compiler<Emitter>::OptLabelTy; @@ -157,7 +147,7 @@ public: SwitchScope(Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel, OptLabelTy DefaultLabel) - : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), + : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel), OldDefaultLabel(this->Ctx->DefaultLabel), OldCaseLabels(std::move(this->Ctx->CaseLabels)), OldLabelVarScope(Ctx->BreakVarScope) { @@ -175,6 +165,7 @@ public: } private: + Compiler<Emitter> *Ctx; OptLabelTy OldBreakLabel; OptLabelTy OldDefaultLabel; CaseMap OldCaseLabels; @@ -457,13 +448,17 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { assert(isPtrType(*FromT)); assert(isPtrType(*ToT)); if (FromT == ToT) { - if (CE->getType()->isVoidPointerType()) + if (CE->getType()->isVoidPointerType() && + !SubExprTy->isFunctionPointerType()) { return this->delegate(SubExpr); + } if (!this->visit(SubExpr)) return false; - if (CE->getType()->isFunctionPointerType()) - return true; + if (CE->getType()->isFunctionPointerType() || + SubExprTy->isFunctionPointerType()) { + return this->emitFnPtrCast(CE); + } if (FromT == PT_Ptr) return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE); return true; @@ -1763,6 +1758,9 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, if (Inits.size() == 1 && E->getType() == Inits[0]->getType()) return this->delegate(Inits[0]); + if (!R) + return false; + auto initPrimitiveField = [=](const Record::Field *FieldToInit, const Expr *Init, PrimType T, bool Activate = false) -> bool { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 3a26342..16f108f 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -21,7 +21,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/TargetInfo.h" namespace clang { class QualType; 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..9b8b664 100644 --- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp +++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp @@ -13,6 +13,25 @@ using namespace clang; using namespace clang::interp; +// FIXME: There is a peculiar problem with the way we track pointers +// to blocks and the way we allocate dynamic memory. +// +// When we have code like this: +// while (true) { +// char *buffer = new char[1024]; +// delete[] buffer; +// } +// +// We have a local variable 'buffer' pointing to the heap allocated memory. +// When deallocating the memory via delete[], that local variable still +// points to the memory, which means we will create a DeadBlock for it and move +// it over to that block, essentially duplicating the allocation. Moving +// the data is also slow. +// +// However, when we actually try to access the allocation after it has been +// freed, we need the block to still exist (alive or dead) so we can tell +// that it's a dynamic allocation. + DynamicAllocator::~DynamicAllocator() { cleanup(); } void DynamicAllocator::cleanup() { @@ -27,7 +46,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.h b/clang/lib/AST/ByteCode/Interp.h index 9012442..9a325ab 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -25,7 +25,6 @@ #include "InterpStack.h" #include "InterpState.h" #include "MemberPointer.h" -#include "Opcode.h" #include "PrimType.h" #include "Program.h" #include "State.h" @@ -481,13 +480,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 +502,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 +510,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 +537,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 +584,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 +592,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; @@ -1138,8 +1130,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) { S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end) << LHS.toDiagnosticString(S.getASTContext()); return false; - } else if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() && - LHS.getOffset() == 0) { + } + if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() && + LHS.getOffset() == 0) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end) << RHS.toDiagnosticString(S.getASTContext()); @@ -1157,8 +1150,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_literal_comparison); return false; - } else if (const auto *CE = dyn_cast<CallExpr>(E); - CE && IsOpaqueConstantCall(CE)) { + } + if (const auto *CE = dyn_cast<CallExpr>(E); + CE && IsOpaqueConstantCall(CE)) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_opaque_call_comparison) << P.toDiagnosticString(S.getASTContext()); @@ -2688,6 +2682,14 @@ static inline bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC) { return true; } +static inline bool FnPtrCast(InterpState &S, CodePtr OpPC) { + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret + << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + return true; +} + static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) { const auto &Ptr = S.Stk.peek<Pointer>(); @@ -3273,7 +3275,8 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, S.CCEDiag(Loc, diag::note_constexpr_invalid_cast) << static_cast<unsigned>(Kind) << S.Current->getRange(OpPC); return !Fatal; - } else if (Kind == CastKind::Volatile) { + } + if (Kind == CastKind::Volatile) { if (!S.checkingPotentialConstantExpression()) { const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC)); if (S.getLangOpts().CPlusPlus) @@ -3284,7 +3287,8 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, } return false; - } else if (Kind == CastKind::Dynamic) { + } + if (Kind == CastKind::Dynamic) { assert(!S.getLangOpts().CPlusPlus20); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast) << diag::ConstexprInvalidCastKind::Dynamic; 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 3ece7054..f908d02 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -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; } @@ -2314,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/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 abfed77..95a4433 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -412,7 +412,7 @@ def CheckDecl : Opcode { def CheckEnumValue : Opcode { let Args = [ArgEnumDecl]; - let Types = [FixedSizeIntegralTypeClass]; + let Types = [IntegralTypeClass]; let HasGroup = 1; } @@ -735,6 +735,8 @@ def PtrPtrCast : Opcode { } +def FnPtrCast : Opcode; + def DecayPtr : Opcode { let Types = [PtrTypeClass, PtrTypeClass]; let HasGroup = 1; diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 9341bc1..dec2088 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -42,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); @@ -89,7 +89,6 @@ Pointer &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); @@ -127,7 +126,6 @@ Pointer &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); @@ -495,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 && diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index 059f176..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 { @@ -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. @@ -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; |