首页 > 其他分享 >TableGen:指令中嵌套操作数的OperandType

TableGen:指令中嵌套操作数的OperandType

时间:2023-01-01 04:44:05浏览次数:60  
标签:std 操作数 string OperandType 嵌套 TableGen operand Rec

TableGen:指令中嵌套操作数的OperandType

Consider, for example, ARM’s predicate operand:

例如,考虑ARM的谓词操作数:

def pred : PredicateOperand<OtherVT, (ops i32imm, i32imm),

                                     (ops (i32 14), (i32 zero_reg))> {

  let PrintMethod = "printPredicateOperand";

  let ParserMatchClass = CondCodeOperand;

  let DecoderMethod = "DecodePredicateOperand";

}

Or addrmode5

class AddrMode5 : MemOperand,

                  ComplexPattern<i32, 2, "SelectAddrMode5", []> {

  let EncoderMethod = "getAddrMode5OpValue";

  let DecoderMethod = "DecodeAddrMode5Operand";

  let ParserMatchClass = AddrMode5AsmOperand;

  let MIOperandInfo = (ops GPR:$base, i32imm);

}

 

def addrmode5 : AddrMode5 {

   let PrintMethod = "printAddrMode5Operand<false>";

}

例如,考虑ARM的谓词操作数:这些操作数在MIOperandInfo中有多个操作数组成整体。

These operands have multiple operands in MIOperandInfo composing the whole.

  • pred (i32imm, i32imm)
  • addrmode5 (GPR, i32imm)

“i32imm”被定义为OPERAND_IMMEDIATE类型,但InstrInfoEmitter::GetOperandInfo会为展平操作数列表(–gen instr info)中与i32immm关联的索引发出OPERAND_UNKNOWN类型。

这似乎是预期的行为。考虑上面的“pred” ,‘zero_reg’(寄存器)是默认值,但i32imm(立即数)是操作数类型。

‘i32imm’ is defined as type OPERAND_IMMEDIATE, but InstrInfoEmitter::GetOperandInfo emits the type OPERAND_UNKNOWN for the index associated with the i32imm in the flattened operand list (–gen-instr-info).

本希望机器代码验证器在指令中看到$noreg时标记一个错误,其中需要立即数,但因为操作数类型是UNKNOWN而不是immediate,所以跳过了该错误。

再深入一点,发现InstrInfoEmitter.cpp将每个子操作数的类型分配给包含操作数。

This seems to be expected behavior. Consider ‘pred’ above. ‘zero_reg’, a register, is a default value, but i32imm, an immediate, is the operand type. I would have expected the machine code verifier to flag an error when it saw $noreg in the instruction where an immediate is expected, but because the operand type is UNKNOWN instead of IMMEDIATE, the error is skipped.

Digging a bit deeper, I found that InstrInfoEmitter.cpp assigns the type of each sub-operand to the containing operand.

  1. Res += "|(1<<MCOI::OptionalDef)";
  2.  
  3.           
  4. // Branch target operands.  Check to see if the original unexpanded
  5. // operand was of type BranchTargetOperand.
  6. if (Op.Rec->isSubClassOf("BranchTargetOperand"))
  7.   Res += "|(1<<MCOI::BranchTarget)";
  8.  
  9.           
  10. // Fill in operand type.
  11. Res += ", ";
  12. assert(!Op.OperandType.empty() && "Invalid operand type.");
  13. Res += Op.OperandType;
  14.  
  15.           
  16. // Fill in constraint info.
  17. Res += ", ";
  18.  
  19.           
  20. const CGIOperandList::ConstraintInfo &Constraint =
  21.   Op.Constraints[j];
  22. if (Constraint.isNone())
  23.   Res += "0";
  24. else if (Constraint.isEarlyClobber())
  25.   Res += "MCOI_EARLY_CLOBBER";

参考文献链接

llvm/llvm-project/blob/4efcea95852abe6ed25ae9a2bf8c3a51a1157675/llvm/utils/TableGen/InstrInfoEmitter.cpp#L195

Is there an ambiguous situation that is being avoided by such a classification? Assigning ‘correct’ types all the time seems to be a non-starter, as both operands above start break in multiple places during normal machine code verification, such as when addrmode5’s first operand receives a constant pool entry rather than a register for its first operand.

My current experiment replicates some code from CGIOperandList which inspects a record to construct the operand namespace and type.

这种分类是否避免了模棱两可的情况?始终指定“正确”类型似乎不是一个开始,因为在正常的机器代码验证过程中,两个开头以上的操作数都会在多个位置中断,例如addrmode5的第一个操作数收到一个常量池条目,而不是第一个操作数的寄存器。

当前的实验复制了CGIOperandList中的一些代码,该代码检查记录以构造操作数名称空间和类型。

  1. PrintFatalError(R->getLoc(), "Illegal operand for the '" + R->getName() +
  2.                                    "' instruction!");
  3.  
  4.           
  5. Record *Rec = Arg->getDef();
  6. std::string PrintMethod = "printOperand";
  7. std::string EncoderMethod;
  8. std::string OperandType = "OPERAND_UNKNOWN";
  9. std::string OperandNamespace = "MCOI";
  10. unsigned NumOps = 1;
  11. DagInit *MIOpInfo = nullptr;
  12. if (Rec->isSubClassOf("RegisterOperand")) {
  13.   PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
  14.   OperandType = std::string(Rec->getValueAsString("OperandType"));
  15.   OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
  16.   EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod"));
  17. } else if (Rec->isSubClassOf("Operand")) {
  18.   PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
  19.   OperandType = std::string(Rec->getValueAsString("OperandType"));
  20.   OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
  21.   // If there is an explicit encoder method, use it.
  22.   EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod"));

参考文献链接

llvm/llvm-project/blob/4efcea95852abe6ed25ae9a2bf8c3a51a1157675/llvm/utils/TableGen/CodeGenInstruction.cpp#L86

参考文献链接

https://discourse.llvm.org/t/tablegen-operandtype-of-nested-operands-in-instructions/67099/1

标签:std,操作数,string,OperandType,嵌套,TableGen,operand,Rec
From: https://www.cnblogs.com/wujianming-110117/p/17017703.html

相关文章

  • VirtualBox嵌套使用虚拟机
    VirtualBoxsupportsAMD-V,but"EnableNestedVT-x/AMD-V"can'tbecheckedinSystem->Processor->ExtendedFeaturesCommandline:VBoxManage.exemodifyvm"vm......
  • 第三章《数组与循环》第6节:嵌套循环
    ​在Java语言中,允许循环当中再次出现循环。这种“循环套循环”的结构被称为嵌套循环。Java语言并没有限制循环嵌套的层数,所以循环可以实现无限层次的嵌套。此外,循环的嵌套也......
  • angularjs 嵌套循环 ng-repeat 超过30条不显示数据
    问题:ng-repeat嵌套使用的时候,内层循环的数组超过30条便不再显示数据。解决办法:加上“trackby$index”。例如:<trng-repeat="changeinInComeChange">......
  • GO 使用嵌套map应该多次分配空间
    GO使用嵌套map应该多次分配空间demopackagemainimport( "fmt")funcmain(){ //初始化一个map vartmpmap[int64]interface{} //tmp[1]="abc"//pan......
  • 多层嵌套的CSS 3D动画技术详解
    CSS动画是当前一种非常火爆的技术,我说的并不是一些简单的颜色变换或长短属性变换,我说的是3D变换技术;纯CSS实现的翻滚旋转立方体就是最典型的例子。网上能找到很多关于CSS动......
  • Go 快速入门指南 - 嵌套结构体
    概述Go支持将多个结构体通过嵌套的方式,组成一个大的结构体,降低了单个结构体复杂度,同时提高了结构体之间组合的灵活性。例子为了省略篇幅,本小节只使用 ​​字面量​​​ ......
  • 关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法
    今天在工作中写项目的时候,遇到了一个让我感到几乎无解的问题,在转换了思路后,想出了一个折中的解决方案,记录如下。其实,问题的场景,非常简单:就是需要查询出上图的数据,红框是......
  • 关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法
    今天在工作中写项目的时候,遇到了一个让我感到几乎无解的问题,在转换了思路后,想出了一个折中的解决方案,记录如下。其实,问题的场景,非常简单:就是需要查询出上图的数据,红框是......
  • 关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法
    今天在工作中写项目的时候,遇到了一个让我感到几乎无解的问题,在转换了思路后,想出了一个折中的解决方案,记录如下。其实,问题的场景,非常简单:就是需要查询出上图的数据,红框是......
  • T1408 矩阵嵌套(DAG 记忆化搜索)
    T1408矩阵嵌套​ 有n个矩阵,每个矩阵有长x和宽y。我们定义矩阵A可以嵌套在矩阵B中:A.x>B.x且A.y>B.y或者A.x>B.y且A.y>B.x。我们现在要找一个最长......