llvm源码父类的设计方式以及其他设计方式

本文介绍了LLVM源码中类的设计技巧,包括使用枚举节省内存、通过Kind值判断子类及数据获取,以及静态成员类的管理。此外,还讨论了LLVM如何通过FoldingSetNodeID进行哈希计算,以及利用模板来识别子类类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

llvm源码类的设计方式有些地方还是很精妙的,下面这个类有很多枚举类型,这个类真实的数据也就是Data1和Data2,Data1和Data2除了保存了两个指针之外还隐藏了一个枚举变量,这样做节省了内存,能这样做的原因是llvm::PointerIntPair<void *, 2> 里面的void*的地址值是个对齐的地址,也就是说void*的值至少是4的倍数或者4以上的数字,但是这个数字肯定是2的幂。另外void*也有另外一个精妙的地方,比如某个子类继承了CFGElement,那么要判断父类指针是那个子类,只需要根据它的Kind值判断,例如它的Kind值是Statement,那么就能找到那个子类,如果我们要取出其中的数据,比如我们知道数据在Data1里面,就可以取出其中的数据,不同子类的数据类型不一样,这个时候我们可以在各个子类里面定义一个函数比如叫 getData1()   对于A子类可能返回int*,对于B子类可能返回double*。总体来说我们从一个父类指针通过Kind找到子类,再转化为子类指针,最后获取数据。因为数据都保持在父类里,所以直接从父类转换为子类也没问题,不过需要用到引用  son s; father&f=son;   f=value_father; 这样子类就从某个父类获取了数据。

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


protected:
  // The int bits are used to mark the kind.
  llvm::PointerIntPair<void *, 2> Data1;
  llvm::PointerIntPair<void *, 2> Data2;


  CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr)
    : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
      Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {

    assert(getKind() == kind);
  }

}

llvm另外一个比较高明的设计是对于某种有静态成员类的设计。例如

class a{

  public:

    int a;

    static int index;

}

比如有个map<int*,map<>(不一定是map,可以是其他对象)>

int*可以采用 static int index;的地址,那么我们就可以很好的管理a类对象


LLVM对类取哈希值的方式也比较特殊,对于一个类来说,其成员一般是整数,指针,字符串或者是某个子类,但是其子类的成员的类型和父类差不多

比如我们要对一个类求其哈希值,

     遍历其成员

           如果成员是个普通类型(整数,指针,字符串),则直接添加到Bits(Bits是FoldingSetNodeID 类的成员,这个类主要用来求哈希值)里面

           如果成员是个类则进入到子类里面,遍历子类的成员,也把它们添加到Bits


最终通过FoldingSetNodeID 的成员Bits生成一个哈希值

//===--------------------------------------------------------------------===//
/// FoldingSetNodeID - This class is used to gather all the unique data bits of
/// a node.  When all the bits are gathered this class is used to produce a
/// hash value for the node.
///
class FoldingSetNodeID {
  /// Bits - Vector of all the data bits that make the node unique.
  /// Use a SmallVector to avoid a heap allocation in the common case.
  SmallVector<unsigned, 32> Bits;


public:
  FoldingSetNodeID() = default;


  FoldingSetNodeID(FoldingSetNodeIDRef Ref)
    : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}


  /// Add* - Add various data types to Bit data.
  ///
  void AddPointer(const void *Ptr);
  void AddInteger(signed I);
  void AddInteger(unsigned I);
  void AddInteger(long I);
  void AddInteger(unsigned long I);
  void AddInteger(long long I);
  void AddInteger(unsigned long long I);
  void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
  void AddString(StringRef String);
  void AddNodeID(const FoldingSetNodeID &ID);

}

另外一种比较有意思的设计是,就是通过模板可以知道子类的类型

template <typename DERIVED>
class ClusterAnalysis  {

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值