clang——CFG构成与生成(一)

CFGElement CFGBlock的最基本元素

enum Kind {
    // main kind
    Statement,
    Initializer,
    NewAllocator,
    // dtor kind
    AutomaticObjectDtor,
    DeleteDtor,
    BaseDtor,
    MemberDtor,
    TemporaryDtor,
    DTOR_BEGIN = AutomaticObjectDtor,
    DTOR_END = TemporaryDtor
  };

代表具体每一条语句,Terminator除外

CFGElement每种kind都有一个相应的子类,如

class CFGStmt : public CFGElement {
public:
  CFGStmt(Stmt *S) : CFGElement(Statement, S) {}

  const Stmt *getStmt() const {
    return static_cast<const Stmt *>(Data1.getPointer());
  }

private:
  friend class CFGElement;
  CFGStmt() {}
  static bool isKind(const CFGElement &E) {
    return E.getKind() == Statement;
  }
};

CFGStmt代表普通的语句

/// CFGInitializer - Represents C++ base or member initializer from
/// constructor's initialization list.
class CFGInitializer : public CFGElement {
public:
  CFGInitializer(CXXCtorInitializer *initializer)
      : CFGElement(Initializer, initializer) {}

  CXXCtorInitializer* getInitializer() const {
    return static_cast(Data1.getPointer());
  }

private:
  friend class CFGElement;
  CFGInitializer() {}
  static bool isKind(const CFGElement &E) {
    return E.getKind() == Initializer;
  }
};

CFGInitializer表示构造函数的初始化列表

/// CFGNewAllocator - Represents C++ allocator call.
class CFGNewAllocator : public CFGElement {
public:
  explicit CFGNewAllocator(const CXXNewExpr *S)
    : CFGElement(NewAllocator, S) {}

  // Get the new expression.
  const CXXNewExpr *getAllocatorExpr() const {
    return static_cast(Data1.getPointer());
  }

private:
  friend class CFGElement;
  CFGNewAllocator() {}
  static bool isKind(const CFGElement &elem) {
    return elem.getKind() == NewAllocator;
  }
};

CFGNewAllocator顾名思义,表示内存分配的new表达式

/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
protected:
  CFGImplicitDtor() {}
  CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr)
    : CFGElement(kind, data1, data2) {
    assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
  }

public:
  const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const;
  bool isNoReturn(ASTContext &astContext) const;

private:
  friend class CFGElement;
  static bool isKind(const CFGElement &E) {
    Kind kind = E.getKind();
    return kind >= DTOR_BEGIN && kind <= DTOR_END;
  }
};

CFGImplicitDtor,前面的kind枚举值中并没有出现ImplicitDtor这个kind。其实ImplicitDtor表示的是一类语句,即编译器隐式调用地对象析构函数,比如对象的作用域结束、调用delete表达式,都会隐式地调用到析构函数。虽然没有单独作为一个kind,但是之后的AutomaticObjectDtor等kind的子类都继承于CFGImplicitDtor,也就是说从AutomaticObjectDtor开始,表示的都是更加精确的析构方式。

继承关系

clang——CFG构成与生成(一)_第1张图片

CFGTerminator CFGBlock的终结语句

class CFGTerminator {
  llvm::PointerIntPair1> Data;
public:
  CFGTerminator() {}
  CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
      : Data(S, TemporaryDtorsBranch) {}

  Stmt *getStmt() { return Data.getPointer(); }
  const Stmt *getStmt() const { return Data.getPointer(); }

  bool isTemporaryDtorsBranch() const { return Data.getInt(); }

  operator Stmt *() { return getStmt(); }
  operator const Stmt *() const { return getStmt(); }

  Stmt *operator->() { return getStmt(); }
  const Stmt *operator->() const { return getStmt(); }

  Stmt &operator*() { return *getStmt(); }
  const Stmt &operator*() const { return *getStmt(); }

  explicit operator bool() const { return getStmt(); }
};

CFGBlock CFG中独立的基本块

完整的Block由三部分组成

1、声明/表达式的集合;

2、一个Terminator;

3、前驱列表和后继列表。

声明和表达式的集合由一个ElementList类型的对象表示

  /// Stmts - The set of statements in the basic block.
  ElementList Elements;

ElementList声明在CFGBlock内部

  class ElementList {
    typedef BumpVector<CFGElement> ImplTy;
    ImplTy Impl;
  public:
    ElementList(BumpVectorContext &C) : Impl(C, 4) {}

    typedef std::reverse_iterator<ImplTy::iterator>       iterator;
    typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
    typedef ImplTy::iterator                              reverse_iterator;
    typedef ImplTy::const_iterator                       const_reverse_iterator;
    typedef ImplTy::const_reference                       const_reference;

    void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }

    ...

   CFGElement operator[](size_t i) const  {
     assert(i < Impl.size());
     return Impl[Impl.size() - 1 - i];
   }

    size_t size() const { return Impl.size(); }
    bool empty() const { return Impl.empty(); }
  };

Terminator由一个CFGTerminator类型的变量表示

  /// Terminator - The terminator for a basic block that
  ///  indicates the type of control-flow that occurs between a block
  ///  and its successors.
  CFGTerminator Terminator;
/// CFGTerminator - Represents CFGBlock terminator statement.
///
/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
/// in control flow of destructors of temporaries. In this case terminator
/// statement is the same statement that branches control flow in evaluation
/// of matching full expression.
class CFGTerminator {
  llvm::PointerIntPair1> Data;
public:
  CFGTerminator() {}
  CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
      : Data(S, TemporaryDtorsBranch) {}

  Stmt *getStmt() { return Data.getPointer(); }
  const Stmt *getStmt() const { return Data.getPointer(); }

  bool isTemporaryDtorsBranch() const { return Data.getInt(); }

  operator Stmt *() { return getStmt(); }
  operator const Stmt *() const { return getStmt(); }

  Stmt *operator->() { return getStmt(); }
  const Stmt *operator->() const { return getStmt(); }

  Stmt &operator*() { return *getStmt(); }
  const Stmt &operator*() const { return *getStmt(); }

  explicit operator bool() const { return getStmt(); }
};

CFGTerminator的构造如上所示。

前驱和后继的保存由两个AdjacentBlock的vector保存

/// Predecessors/Successors - Keep track of the predecessor / successor
  /// CFG blocks.
  typedef BumpVector AdjacentBlocks;
  AdjacentBlocks Preds;
  AdjacentBlocks Succs;

AdjacentBlock表示一个潜在相邻的CFGBlock,并判断它是否可达

class AdjacentBlock {
    enum Kind {
      AB_Normal,
      AB_Unreachable,
      AB_Alternate
    };

    CFGBlock *ReachableBlock;
    llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock;

  public:
    /// Construct an AdjacentBlock with a possibly unreachable block.
    AdjacentBlock(CFGBlock *B, bool IsReachable);

    /// Construct an AdjacentBlock with a reachable block and an alternate
    /// unreachable block.
    AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);

    ...  
  };

CFGBlock还有诸如BlockID等等属性,还有一个CFG对象作为它的parent。

CFG对象可以看做是CFGBlock的集合。至少有一个Entry和Exit的CFGBlock,此外还有一个保存CFGBlock的vector

  CFGBlock *Entry;
  CFGBlock *Exit;
  ...
  CFGBlockListTy Blocks;

此外,CFG还有比如针对try statements的vector

  /// C++ 'try' statements are modeled with an indirect dispatch block.
  /// This is the collection of such blocks present in the CFG.
  std::vector<const CFGBlock *> TryDispatchBlocks;

等等其他属性

其中一个比较重要的函数是

CFGBlock *CFG::createBlock() {
  bool first_block = begin() == end();

  // Create the block.
  CFGBlock *Mem = getAllocator().Allocate();
  new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this);
  Blocks.push_back(Mem, BlkBVC);

  // If this is the first block, set it as the Entry and Exit.
  if (first_block)
    Entry = Exit = &back();

  // Return the block.
  return &back();
}

负责生成一个新的CFGBlock。这里所用的new经过重载,提前分配好内存空间

CFGBlock *Mem = getAllocator().Allocate();

然后直接对这块内存通过new调用构造函数

new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this);

也就是所谓的placement new

你可能感兴趣的:(clang)