llvmIR转为SDNode

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

学习LLVM得第1章


一、与架构无关的SDNode的Opcode

LLVMIR--->SDNode的过程中会涉及Opcode的转换,这里的Opcode是与架构无关的,即所有架构通用。

/source/llvm/include/llvm/IR/ Instruction.h
/source/llvm/include/llvm/IR/ Instruction.def //定义Opcode

//Instruction.h
class Instruction : public User,
                    public ilist_node_with_parent<Instruction, BasicBlock> {
  // Exported enumerations.
  enum TermOps {       // These terminate basic blocks
#define  FIRST_TERM_INST(N)             TermOpsBegin = N,
#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N,
#define   LAST_TERM_INST(N)             TermOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };

  enum UnaryOps {
#define  FIRST_UNARY_INST(N)             UnaryOpsBegin = N,
#define HANDLE_UNARY_INST(N, OPC, CLASS) OPC = N,
#define   LAST_UNARY_INST(N)             UnaryOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };
  enum BinaryOps {
#define  FIRST_BINARY_INST(N)             BinaryOpsBegin = N,
#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N,
#define   LAST_BINARY_INST(N)             BinaryOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };

  enum MemoryOps {
#define  FIRST_MEMORY_INST(N)             MemoryOpsBegin = N,
#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N,
#define   LAST_MEMORY_INST(N)             MemoryOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };

  enum CastOps {
#define  FIRST_CAST_INST(N)             CastOpsBegin = N,
#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N,
#define   LAST_CAST_INST(N)             CastOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };

  enum FuncletPadOps {
#define  FIRST_FUNCLETPAD_INST(N)             FuncletPadOpsBegin = N,
#define HANDLE_FUNCLETPAD_INST(N, OPC, CLASS) OPC = N,
#define   LAST_FUNCLETPAD_INST(N)             FuncletPadOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };

  enum OtherOps {
#define  FIRST_OTHER_INST(N)             OtherOpsBegin = N,
#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N,
#define   LAST_OTHER_INST(N)             OtherOpsEnd = N+1
#include "llvm/IR/Instruction.def"
  };
}

上文将Instruction的Opcode定义为7种类型。

Instruction类继承自User,所以指令的ID号有区别。这里引入了InstructionVal

Enum values starting at InstructionVal are used for Instructions;
用于界定

ID号大于InstructionVal的才会被认为是指令。
指令的ID号请查看文件/source/llvm/include/llvm/IR/ Instruction.def

 FIRST_TERM_INST  ( 1)
HANDLE_TERM_INST  ( 1, Ret           , ReturnInst)
HANDLE_TERM_INST  ( 2, Br            , BranchInst)
HANDLE_TERM_INST  ( 3, Switch        , SwitchInst)
HANDLE_TERM_INST  ( 4, IndirectBr    , IndirectBrInst)
HANDLE_TERM_INST  ( 5, Invoke        , InvokeInst)
HANDLE_TERM_INST  ( 6, Resume        , ResumeInst)
HANDLE_TERM_INST  ( 7, Unreachable   , UnreachableInst)
HANDLE_TERM_INST  ( 8, CleanupRet    , CleanupReturnInst)
HANDLE_TERM_INST  ( 9, CatchRet      , CatchReturnInst)
HANDLE_TERM_INST  (10, CatchSwitch   , CatchSwitchInst)
HANDLE_TERM_INST  (11, CallBr        , CallBrInst) // A call-site terminator
  LAST_TERM_INST  (11)

上问可知Ret指令的ID,即OpCode是1

1. 与架构相关的MachineNode的Opcode

SDNode--->MahineNode的过程中会涉及Opcode的转换,架构Opcode相关的内容如下产生。

../build/bin/llvm-tblgen \
  /[source]/llvm/lib/Target/RISCV/RISCV.td \
  --gen-instr-info \
  -I /[source]/llvm/include/ \
  -I /[source]/lib/Target/RISCV/
 #source请改为源码的地址
 #本例子对的RISCV架构,其他架构请更换

输出与特定架构相关的文件。「这里涉及LLVM中的tblgen以及模块化概念,对于新架构添加和修改很重要。本文重点不在于此,有机会再做讲解。」

也可以在build目录中的build/lib/Target/AArch64相关Instruction.inc文件中找到上述生成内容。

2.读入数据

LLVMIR

代码如下(示例):

class Instruction : public User,
                    public ilist_node_with_parent<Instruction, BasicBlock> {
  BasicBlock *Parent;
  DebugLoc DbgLoc;                         // 'dbg' Metadata cache.

  /// Relative order of this instruction in its parent basic block. Used for
  /// O(1) local dominance checks between instructions.
  mutable unsigned Order = 0;
    /// Returns a member of one of the enums like Instruction::Add.
  unsigned getOpcode() const { return getValueID() - InstructionVal; }

  const char *getOpcodeName() const { return getOpcodeName(getOpcode()); }
    /// Set the debug location information for this instruction.
  void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }

  /// Return the debug location for this node as a DebugLoc.
  const DebugLoc &getDebugLoc() const { return DbgLoc; }

unsigned getOpcode() const { return getValueID() - InstructionVal; } 中getValueID()是class Value的成员。

SelectionDAGBuilder

class SelectionDAGBuilder {
  /// The current instruction being visited.
  const Instruction *CurInst = nullptr;
  DenseMap<const Value*, SDValue> NodeMap;

Value SDValue

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值