Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/InterpStack.cpp
213799 views
//===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "InterpStack.h"9#include "Boolean.h"10#include "FixedPoint.h"11#include "Floating.h"12#include "Integral.h"13#include "MemberPointer.h"14#include "Pointer.h"15#include <cassert>16#include <cstdlib>1718using namespace clang;19using namespace clang::interp;2021InterpStack::~InterpStack() {22if (Chunk && Chunk->Next)23std::free(Chunk->Next);24if (Chunk)25std::free(Chunk);26Chunk = nullptr;27StackSize = 0;28#ifndef NDEBUG29ItemTypes.clear();30#endif31}3233// We keep the last chunk around to reuse.34void InterpStack::clear() {35if (!Chunk)36return;3738if (Chunk->Next)39std::free(Chunk->Next);4041assert(Chunk);42StackSize = 0;43#ifndef NDEBUG44ItemTypes.clear();45#endif46}4748void InterpStack::clearTo(size_t NewSize) {49assert(NewSize <= size());50size_t ToShrink = size() - NewSize;51if (ToShrink == 0)52return;5354shrink(ToShrink);55assert(size() == NewSize);56}5758void *InterpStack::grow(size_t Size) {59assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");6061if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {62if (Chunk && Chunk->Next) {63Chunk = Chunk->Next;64} else {65StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk);66if (Chunk)67Chunk->Next = Next;68Chunk = Next;69}70}7172auto *Object = reinterpret_cast<void *>(Chunk->End);73Chunk->End += Size;74StackSize += Size;75return Object;76}7778void *InterpStack::peekData(size_t Size) const {79assert(Chunk && "Stack is empty!");8081StackChunk *Ptr = Chunk;82while (Size > Ptr->size()) {83Size -= Ptr->size();84Ptr = Ptr->Prev;85assert(Ptr && "Offset too large");86}8788return reinterpret_cast<void *>(Ptr->End - Size);89}9091void InterpStack::shrink(size_t Size) {92assert(Chunk && "Chunk is empty!");9394while (Size > Chunk->size()) {95Size -= Chunk->size();96if (Chunk->Next) {97std::free(Chunk->Next);98Chunk->Next = nullptr;99}100Chunk->End = Chunk->start();101Chunk = Chunk->Prev;102assert(Chunk && "Offset too large");103}104105Chunk->End -= Size;106StackSize -= Size;107108#ifndef NDEBUG109size_t TypesSize = 0;110for (PrimType T : ItemTypes)111TYPE_SWITCH(T, { TypesSize += aligned_size<T>(); });112113size_t StackSize = size();114while (TypesSize > StackSize) {115TYPE_SWITCH(ItemTypes.back(), {116TypesSize -= aligned_size<T>();117ItemTypes.pop_back();118});119}120assert(TypesSize == StackSize);121#endif122}123124void InterpStack::dump() const {125#ifndef NDEBUG126llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n';127if (ItemTypes.empty())128return;129130size_t Index = 0;131size_t Offset = 0;132133// The type of the item on the top of the stack is inserted to the back134// of the vector, so the iteration has to happen backwards.135for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) {136Offset += align(primSize(*TyIt));137138llvm::errs() << Index << '/' << Offset << ": ";139TYPE_SWITCH(*TyIt, {140const T &V = peek<T>(Offset);141llvm::errs() << V;142});143llvm::errs() << '\n';144145++Index;146}147#endif148}149150151