首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么是LLVM中的getOpcode?

什么是LLVM中的getOpcode?
EN

Stack Overflow用户
提问于 2018-02-21 04:52:11
回答 2查看 1.5K关注 0票数 1

在LLVM代码生成器部分的MCInstrDescMachineInstr类中,函数getOpcode()返回什么?我不能联系到机器的实际操作码。

例如,对于x86中的RET指令,getOpcode()函数返回2515。但是,x86中的实际操作码是C3 (十进制的195)。

这是什么关系?

EN

回答 2

Stack Overflow用户

发布于 2018-02-26 02:54:12

MCInstrDescMachineInstr上的getOpcode()成员函数返回枚举值,该枚举值标识指令表示X86InstrInfo.td中的哪个操作码。在其他后端中,编号对应于该后端的instr信息,通常是一个名为[BACKEND]InstrInfo.td的文件。

您可以在许多X86后端传递中找到使用这种方法的示例,例如X86ExpandPseudo.cpp中处理尾部调用返回的代码。

代码语言:javascript
运行
复制
switch (MI.getOpcode()) {
default:
  return false;
case X86::TCRETURNdi:
case X86::TCRETURNdicc:
case X86::TCRETURNri:
case X86::TCRETURNmi:
case X86::TCRETURNdi64:
case X86::TCRETURNdi64cc:
case X86::TCRETURNri64:
case X86::TCRETURNmi64: {
  /* ... */
}
/* ... */
}
票数 2
EN

Stack Overflow用户

发布于 2021-06-27 09:29:56

最近,我一直在为同样的问题而苦苦挣扎,最终得到了答案。你的问题已经有很长一段时间了,但我写这篇文章是为了如果有人仍然感到困惑。

正如你所说的,getOpcode()函数返回机器指令的枚举,而这些并不是@dtolnay所说的保存在{BackendArchName}InstrInfo.td中的。这些枚举将是在LLVM库构建后生成的,它与真实的十进制操作码编号无关,而且由于不同的llvm版本或后端库中的自定义更改,操作码的十进制枚举表示可能会发生变化。这听起来很合理,因为它不会阻止自定义,您可以在后端添加或删除操作码,并且在构建库后,操作码的枚举会动态更改和生成。如果这些枚举在构建之前一直保存在库中的某个地方,例如,你可能不能为目标添加新的操作码,或者很难更改像这样的小细节。

因此,在构建之后,您可以在以下文件夹中找到具有以下操作码表示的文件:

{your-llvm-directory}/{your-llvm-build-directory}/lib/Target/{which-backend-target}

.inc文件包含操作码的枚举:

{which-backend-target}GenInstrInfo.inc

例如,在我的pc中为riscv目标构建之后,我可以在以下位置找到枚举:

~/llvm/llvm-project/build/lib/Target/RISCV/RISCVGenInstrInfo.inc

这些枚举的一部分:

代码语言:javascript
运行
复制
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|*                                                                            *|
|* Target Instruction Enum Values and Descriptors                             *|
|*                                                                            *|
|* Automatically generated file, do not edit!                                 *|
|*                                                                            *|
\*===----------------------------------------------------------------------===*/

#ifdef GET_INSTRINFO_ENUM
#undef GET_INSTRINFO_ENUM
namespace llvm {

namespace RISCV {
  enum {

// ........................................

    AND = 323,
    ANDI    = 324,
    ANDN    = 325,
    AUIPC   = 326,
    BDEP    = 327,
    BDEPW   = 328,
    BEQ = 329,
    BEXT    = 330,
    BEXTW   = 331,
    BFP = 332,
    BFPW    = 333,
    BGE = 334,
    BGEU    = 335,
    BLT = 336,
    BLTU    = 337,
    BMATFLIP    = 338,
    BMATOR  = 339,
    BMATXOR = 340,
    BNE = 341,
    CLMUL   = 342,
    CLMULH  = 343,
    CLMULHW = 344,
    CLMULR  = 345,
    CLMULRW = 346,
    CLMULW  = 347,
    CLZ = 348,
    CLZW    = 349,
    CMIX    = 350,
    CMOV    = 351,
    CRC32B  = 352,

// ........................................

    CRC32H  = 358,
    CRC32W  = 359,
    CSRRC   = 360,
    CSRRCI  = 361,
    CSRRS   = 362,
    CSRRSI  = 363,
    CSRRW   = 364,
    CSRRWI  = 365,
    CTZ = 366,
    CTZW    = 367,
    C_ADD   = 368,
    C_ADDI  = 369,
    C_ADDI16SP  = 370,
    C_ADDI4SPN  = 371,
    C_ADDIW = 372,
    C_ADDI_HINT_IMM_ZERO    = 373,
    C_ADDI_HINT_X0  = 374,
    C_ADDI_NOP  = 375,
// ........................................

  };

} // end namespace RISCV
} // end namespace llvm

我刚刚给出了一个RISCV的例子,对于X86这样的其他目标也是一样的过程。在您的示例中,RET2515应该在X86GenInstrInfo.inc文件中作为枚举号,如下所示。

因为这些枚举是在构建之后生成的,所以在任何未构建的llvm library中都找不到它们是很正常的,比如在github中。

额外信息:

由于枚举编号可能因场景不同而不同,因此在使用LLVM时,不应将它们用作编号,而应使用枚举名称调用它们。例如:

代码语言:javascript
运行
复制
#include "RISCV.h" //You should include backend header for using enums.
#include "llvm/MC/MCInst.h"

//Some code here ... 

if(MI->getOpcode() == RISCV::ADD){  // MI is machine instruction for example const MCInst *MI

//Some code here...

}

//Some code here...

在上面的代码中,正如你所看到的,无论什么数字都会返回getOpcode函数,因为我可以用从(RISCV header->RISCV namespace->RISCV Opcode Enum Name)派生的名称来控制它。但是,如果您想要直接获取返回的枚举号的名称,可以使用getOpcodeName函数,例如:

代码语言:javascript
运行
复制
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/ADT/StringRef.h" //for llvm string variable

//Some code here ... 

StringRef opcodeName = IP.getOpcodeName(MI->getOpcode()); // IP is instruction printer for example MCInstPrinter &IP

//Some code here ... 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48894012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档