forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- InterpBlock.h - Allocated blocks for the interpreter -*- C++ ----*-===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// Defines the classes describing allocated blocks.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H
 | 
						|
#define LLVM_CLANG_AST_INTERP_BLOCK_H
 | 
						|
 | 
						|
#include "Descriptor.h"
 | 
						|
#include "clang/AST/Decl.h"
 | 
						|
#include "clang/AST/DeclCXX.h"
 | 
						|
#include "clang/AST/Expr.h"
 | 
						|
#include "clang/AST/ComparisonCategories.h"
 | 
						|
#include "llvm/ADT/PointerUnion.h"
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
 | 
						|
namespace clang {
 | 
						|
namespace interp {
 | 
						|
class Block;
 | 
						|
class DeadBlock;
 | 
						|
class Context;
 | 
						|
class InterpState;
 | 
						|
class Pointer;
 | 
						|
class Function;
 | 
						|
enum PrimType : unsigned;
 | 
						|
 | 
						|
/// A memory block, either on the stack or in the heap.
 | 
						|
///
 | 
						|
/// The storage described by the block immediately follows it in memory.
 | 
						|
class Block {
 | 
						|
public:
 | 
						|
  // Creates a new block.
 | 
						|
  Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc,
 | 
						|
        bool IsStatic = false, bool IsExtern = false)
 | 
						|
      : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {}
 | 
						|
 | 
						|
  Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
 | 
						|
      : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern),
 | 
						|
        Desc(Desc) {}
 | 
						|
 | 
						|
  /// Returns the block's descriptor.
 | 
						|
  Descriptor *getDescriptor() const { return Desc; }
 | 
						|
  /// Checks if the block has any live pointers.
 | 
						|
  bool hasPointers() const { return Pointers; }
 | 
						|
  /// Checks if the block is extern.
 | 
						|
  bool isExtern() const { return IsExtern; }
 | 
						|
  /// Checks if the block has static storage duration.
 | 
						|
  bool isStatic() const { return IsStatic; }
 | 
						|
  /// Checks if the block is temporary.
 | 
						|
  bool isTemporary() const { return Desc->IsTemporary; }
 | 
						|
  /// Returns the size of the block.
 | 
						|
  InterpSize getSize() const { return Desc->getAllocSize(); }
 | 
						|
  /// Returns the declaration ID.
 | 
						|
  llvm::Optional<unsigned> getDeclID() const { return DeclID; }
 | 
						|
 | 
						|
  /// Returns a pointer to the stored data.
 | 
						|
  char *data() { return reinterpret_cast<char *>(this + 1); }
 | 
						|
 | 
						|
  /// Returns a view over the data.
 | 
						|
  template <typename T>
 | 
						|
  T &deref() { return *reinterpret_cast<T *>(data()); }
 | 
						|
 | 
						|
  /// Invokes the constructor.
 | 
						|
  void invokeCtor() {
 | 
						|
    std::memset(data(), 0, getSize());
 | 
						|
    if (Desc->CtorFn)
 | 
						|
      Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
 | 
						|
                   /*isActive=*/true, Desc);
 | 
						|
  }
 | 
						|
 | 
						|
protected:
 | 
						|
  friend class Pointer;
 | 
						|
  friend class DeadBlock;
 | 
						|
  friend class InterpState;
 | 
						|
 | 
						|
  Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
 | 
						|
    : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
 | 
						|
 | 
						|
  // Deletes a dead block at the end of its lifetime.
 | 
						|
  void cleanup();
 | 
						|
 | 
						|
  // Pointer chain management.
 | 
						|
  void addPointer(Pointer *P);
 | 
						|
  void removePointer(Pointer *P);
 | 
						|
  void movePointer(Pointer *From, Pointer *To);
 | 
						|
 | 
						|
  /// Start of the chain of pointers.
 | 
						|
  Pointer *Pointers = nullptr;
 | 
						|
  /// Unique identifier of the declaration.
 | 
						|
  llvm::Optional<unsigned> DeclID;
 | 
						|
  /// Flag indicating if the block has static storage duration.
 | 
						|
  bool IsStatic = false;
 | 
						|
  /// Flag indicating if the block is an extern.
 | 
						|
  bool IsExtern = false;
 | 
						|
  /// Flag indicating if the pointer is dead.
 | 
						|
  bool IsDead = false;
 | 
						|
  /// Pointer to the stack slot descriptor.
 | 
						|
  Descriptor *Desc;
 | 
						|
};
 | 
						|
 | 
						|
/// Descriptor for a dead block.
 | 
						|
///
 | 
						|
/// Dead blocks are chained in a double-linked list to deallocate them
 | 
						|
/// whenever pointers become dead.
 | 
						|
class DeadBlock {
 | 
						|
public:
 | 
						|
  /// Copies the block.
 | 
						|
  DeadBlock(DeadBlock *&Root, Block *Blk);
 | 
						|
 | 
						|
  /// Returns a pointer to the stored data.
 | 
						|
  char *data() { return B.data(); }
 | 
						|
 | 
						|
private:
 | 
						|
  friend class Block;
 | 
						|
  friend class InterpState;
 | 
						|
 | 
						|
  void free();
 | 
						|
 | 
						|
  /// Root pointer of the list.
 | 
						|
  DeadBlock *&Root;
 | 
						|
  /// Previous block in the list.
 | 
						|
  DeadBlock *Prev;
 | 
						|
  /// Next block in the list.
 | 
						|
  DeadBlock *Next;
 | 
						|
 | 
						|
  /// Actual block storing data and tracking pointers.
 | 
						|
  Block B;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace interp
 | 
						|
} // namespace clang
 | 
						|
 | 
						|
#endif
 |