Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -365,7 +365,7 @@ const Expr *Index = E->getIdx(); PrimType IndexT = classifyPrim(Index->getType()); - // Take pointer of LHS, add offset from RHS, narrow result. + // Take pointer of LHS, add offset from RHS. // What's left on the stack after this is a pointer. if (!this->visit(Base)) return false; @@ -373,10 +373,7 @@ if (!this->visit(Index)) return false; - if (!this->emitAddOffset(IndexT, E)) - return false; - - if (!this->emitNarrowPtr(E)) + if (!this->emitArrayElemPtrPop(IndexT, E)) return false; if (DiscardResult) @@ -1115,16 +1112,11 @@ return false; } else { // Advance the pointer currently on the stack to the given - // dimension and narrow(). - if (!this->emitDupPtr(Init)) - return false; + // dimension. if (!this->emitConstUint32(ElementIndex, Init)) return false; - if (!this->emitAddOffsetUint32(Init)) + if (!this->emitArrayElemPtrUint32(Init)) return false; - if (!this->emitNarrowPtr(Init)) - return false; - if (!visitInitializer(Init)) return false; if (!this->emitPopPtr(Init)) @@ -1150,31 +1142,22 @@ for (size_t I = 0; I != Size; ++I) { ArrayIndexScope IndexScope(this, I); - if (!this->emitDupPtr(SubExpr)) // LHS - return false; - if (ElemT) { if (!this->visit(SubExpr)) return false; if (!this->emitInitElem(*ElemT, I, Initializer)) return false; } else { - // Narrow to our array element and recurse into visitInitializer() + // Get to our array element and recurse into visitInitializer() if (!this->emitConstUint64(I, SubExpr)) return false; - - if (!this->emitAddOffsetUint64(SubExpr)) - return false; - - if (!this->emitNarrowPtr(SubExpr)) + if (!this->emitArrayElemPtrUint64(SubExpr)) return false; - if (!visitInitializer(SubExpr)) return false; + if (!this->emitPopPtr(Initializer)) + return false; } - - if (!this->emitPopPtr(Initializer)) - return false; } return true; } else if (const auto *IVIE = dyn_cast(Initializer)) { @@ -1210,13 +1193,9 @@ // FIXME(perf): We're calling the constructor once per array element here, // in the old intepreter we had a special-case for trivial constructors. for (size_t I = 0; I != NumElems; ++I) { - if (!this->emitDupPtr(Initializer)) - return false; if (!this->emitConstUint64(I, Initializer)) return false; - if (!this->emitAddOffsetUint64(Initializer)) - return false; - if (!this->emitNarrowPtr(Initializer)) + if (!this->emitArrayElemPtrUint64(Initializer)) return false; // Constructor arguments. Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1369,6 +1369,36 @@ return true; } +// 1) Pops an integral value from the stack +// 2) Peeks a pointer +// 3) Pushes a new pointer that's a narrowed array +// element of the peeked pointer with the value +// from 1) added as offset. +// +// This leaves the original pointer on the stack and pushes a new one +// with the offset applied and narrowed. +template ::T> +inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.peek(); + + if (!OffsetHelper(S, OpPC, Offset, Ptr)) + return false; + + return NarrowPtr(S, OpPC); +} + +template ::T> +inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.pop(); + + if (!OffsetHelper(S, OpPC, Offset, Ptr)) + return false; + + return NarrowPtr(S, OpPC); +} + inline bool CheckGlobalCtor(InterpState &S, CodePtr &PC) { const Pointer &Obj = S.Stk.peek(); return CheckCtorCall(S, PC, Obj); Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -300,6 +300,9 @@ def NarrowPtr : Opcode; // [Pointer] -> [Pointer] def ExpandPtr : Opcode; +// [Pointer, Offset] -> [Pointer] +def ArrayElemPtr : AluOpcode; +def ArrayElemPtrPop : AluOpcode; //===----------------------------------------------------------------------===// // Direct field accessors