想做程序員需要學什么黑帽seo技術(shù)
llvm后端之td定義指令信息
- 引言
- 1 定義指令
- 2 定義Operand
- 3 定義SDNode
- 4 PatFrags
- 4.1 ImmLeaf
- 4.2 PatLeaf
- 5 ComplexPattern
- 6 謂詞條件
- 7 理解dag
引言
llvm后端通過td定義指令信息,并通過dag匹配將IR節(jié)點轉(zhuǎn)換為平臺相關(guān)的指令。
1 定義指令
td通過class Instruction來定義指令,其各個字段意義如下:
- OutOperandList:輸出dag節(jié)點列表;
- InOperandList:輸入操作數(shù)節(jié)點列表;
- AsmString:用于在“.s”文件中的匯編顯示;
- Pattern:用于指令選擇匹配的dag列表;
- Predicates:用于在指令選擇階段是否啟用的條件判斷;
- Uses:指令引用的寄存器列表;
- Defs:指令改寫的寄存器列表;
- Size:指令編碼成二進制的長度,為0表示可變長度;
- CodeSize:
- Itinerary:按步驟方式的調(diào)度模式;
- SchedRW:按資源使用的調(diào)度模式;
- Constraints:約束條件,例如有些指令源寄存器與目的寄存器筆下相同,則$src = $dst;
- TSFlags:
注:還有一個隱含的字段field bits Inst,該字段表示指令轉(zhuǎn)換為二進制時bit位。例如RISCV里面為field bits<32> Inst。
2 定義Operand
Operand用于定義操作,相關(guān)字段如下:
- Type:操作數(shù)類型,例如i8、i16、i32等;
- PrintMethod:在class XXXInstPrinter中用于打印該操作數(shù)的成員函數(shù),參數(shù)分別為const MCInst *MI、unsigned Op、raw_ostream &O。需要cpp實現(xiàn);
- EncoderMethod:在class XXXMCCodeEmitter中用于編碼該操作數(shù)的成員函數(shù),參數(shù)分別為const MCInst &MI、unsigned OpNo、SmallVectorImpl &Fixups、const MCSubtargetInfo &STI,返回值為unsigned,表示錯誤編號。需要cpp實現(xiàn);
- DecoderMethod:在class XXXDisassembler中用于解碼該操作數(shù)的成員函數(shù),參數(shù)分別為MCInst &Inst、uint64_t Imm、int64_t Address、const void *Decoder,返回值為DecodeStatus;
- hasCompleteDecoder:
- OperandType:操作數(shù)類型字符串,包括MCInstrDesc.h中定義的enum OperandType中,有些target會進行自定義。
- OperandNamespace:操作數(shù)類型定義所在的namespace。默認為MCOI,即定義在MCInstrDesc.h中;
- MIOperandInfo:子操作數(shù)片段。例如地址可能有基地址、偏移、scale等組成,為了可讀性將其合并定義為addr;
- MCOperandPredicate:在XXXAsmParser和XXXAsmPrinter發(fā)射該操作數(shù)有效的匹配前置條件的代碼片段。代碼片段可訪問const MCOperand &MCOp;
- ParserMatchClass:用于匯編解析的方法集合,類型為AsmOperandClass。
class AsmOperandClass用于生成匯編解析代碼,其各個字段如下:
- Name:操作數(shù)類型名稱;
- SuperClasses:操作數(shù)分類所屬父類列表;
- PredicateMethod:表示class XXXOperand的成員函數(shù)名稱,該成員函數(shù)用于判斷是否為該類型的操作數(shù),不定義則為bool is%Name%() const;
- RenderMethod:表示class XXXOperand的成員函數(shù)名稱,該成員函數(shù)用于將該操作數(shù)添加到MCInst中,不定義則為void add%Name%Operands(MCInst &Inst, unsigned N) const;
- ParserMethod:表示class XXXAsmParser的成員函數(shù)名稱,用于解析該匯編操作數(shù)。函數(shù)原型為( OperandMatchResultTy )(OperandVector &Operands);
- DiagnosticType:當XXXAsmParser解析失敗時,觸發(fā)的錯誤打印;
- DiagnosticString:當該操作數(shù)被賦值一個非法值時,觸發(fā)的錯誤打印;
- IsOptional:為1表示為可選參數(shù),為0為必須參數(shù);
- DefaultMethod:表示class XXXAsmParser的成員函數(shù)名稱,當IsOptional時,該成員函數(shù)用于創(chuàng)建默認的該操作數(shù),不定義則為std::unique_ptr< XXXOperand > default%Name%Operands() const;
3 定義SDNode
SDNode用于定義一個dag節(jié)點,它分別有如下重要參數(shù):
- opcode:SDNode的節(jié)點枚舉;
- typeprof:用于描述節(jié)點特性的SDTypeProfile類型;
- props:節(jié)點屬性列表,定義在SDNodeProperties.td文件中,對應源碼enum SDNP。例如滿足交換律、滿足結(jié)合律、有邊界影響;
- sdclass:節(jié)點對應C++類型名稱;
SDTypeProfile用于描述節(jié)點的特性,各個參數(shù)如下:
- numresults:節(jié)點輸出值數(shù)量;
- numoperands:節(jié)點輸入操作數(shù)數(shù)量;
- constraints:節(jié)點輸出/入的約束;
注:SDTypeConstraint用于描述節(jié)點的輸入輸出約束。例如SDTCisInt<2>表示第0個輸出/入為int,假設節(jié)點numresults為1,numoperands為2,序號從0到2,前面一個為輸出、后面兩個為輸入。
4 PatFrags
例如store節(jié)點包括unindexed store、normal store、trunc store等,怎么分別定義這些SDNode呢?這時PatFrags就派上用場,其主要的參數(shù)如下:
- ops與frags:它表示將frags中的任何片段之一匹配成ops片段;
- pred:啟動該匹配的前置條件代碼,輸出布爾變量。該代碼片段生成于XXXGenDAGISel.inc中,代碼片段除了可以訪問class XXXDAGToDAGISel,還可以訪問一個臨時變量SDNode *N;
- xform:對節(jié)點的轉(zhuǎn)換代碼片段,類型為SDNodeXForm。默認為NOOP_SDNodeXForm,即不轉(zhuǎn)換。
注:通常frags只有一項,因此td模板定義了PatFrag來表示這種情況。
class SDNodeXForm用于對節(jié)點的轉(zhuǎn)換操作,例如在PatFrags匹配結(jié)束,輸出的SDNode可以做一次轉(zhuǎn)換、或者做封裝、甚至替換。核心字段如下:
- opc:可轉(zhuǎn)換的節(jié)點,類型為SDNode。
- xformFunction:轉(zhuǎn)換代碼片段,代碼片段除了可以訪問class XXXDAGToDAGISel,還可以訪問一個臨時變量SDNode *N;
4.1 ImmLeaf
ImmLeaf表示將一個常數(shù)葉子重新匹配、或者說重定義為一個新的節(jié)點,也就是立即數(shù)節(jié)點。用于取立即數(shù)操作。立即數(shù)節(jié)點是沒有子節(jié)點可繼續(xù)展開,所以在PatFrag中斷ops參數(shù)由一個空的ops表示。其主要兩個參數(shù):
- vt:表示節(jié)點的輸出類型,例如i8、i16、i32等;
- pred:表示可匹配的先決條件,為一段輸出布爾的代碼。代碼片段除了可以訪問class XXXDAGToDAGISel,還可以訪問一個臨時變量 Imm
4.2 PatLeaf
PatLeaf表示將一個無操作數(shù)節(jié)點重新匹配、或者說重定義為一個新的節(jié)點名稱,PatLeaf是PatFrag子類。由于葉子節(jié)點沒有子節(jié)點可繼續(xù)展開,所以在PatFrag中斷ops參數(shù)由一個空的ops表示。例如x86中如下定義:
... ...
def i32immSExt8 : ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
... ...
def i32immSExt8_su : PatLeaf<(i32immSExt8), [{return !shouldAvoidImmediateInstFormsForSize(N);
}]>;
... ...
注:與PatFrag類似,pred字段的代碼片段除了可以訪問class XXXDAGToDAGISel,還可以訪問一個臨時變量SDNode *N。
5 ComplexPattern
ComplexPattern可用于從節(jié)點中提前操作數(shù)。例如地址有基地址、偏移、scale等組成,這時ComplexPattern派上用場。其各個字段意義如下:
- Ty:被提取、或者說匹配的節(jié)點類型;
- NumOperands:需要提前的子操作數(shù)個數(shù);
- SelectFunc:表示class XXXDAGToDAGISel中用于提取操作的成員函數(shù)名稱;
- RootNodes:表示該提取操作在哪些根節(jié)點下有效。為空則沒有限制;
- Properties:表示被提取節(jié)點(而非根節(jié)點)的屬性;
例如X86中,有如下定義:
def addr : ComplexPattern<iPTR, 5, "selectAddr", [], [SDNPWantParent]>;
則X86DAGToDAGISel類中有如下函數(shù)實現(xiàn):
//Parent - ComplexPattern中定義了SDNPWantParent屬性;
//N - 被提取節(jié)點,類型為iPTR;
//后面的導出參數(shù)對應ComplexPattern中定義的5個需要提前的子操作數(shù)
bool X86DAGToDAGISel::selectAddr(SDNode *Parent, SDValue N, SDValue &Base,SDValue &Scale, SDValue &Index,SDValue &Disp, SDValue &Segment) {
6 謂詞條件
謂詞條件表示匹配或定義有效的前置條件。除了前面各個record中表示謂詞的字段。還有一種定義謂詞的通用方式,就是def的record多重繼承class Requires< list < Predicate > preds >。其中Predicate定義的謂詞一般訪問Subtarget實現(xiàn)返回條件布爾值。