<s>
void
CSKYAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
MCFixupKind
Kind
=
Fixup
.
getKind
(
)
;
if
(
Kind
>=
FirstLiteralRelocationKind
)
return
;
MCContext
&
Ctx
=
Asm
.
getContext
(
)
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Kind
)
;
if
(
!
Value
)
return
;
Value
=
adjustFixupValue
(
Fixup
,
Value
,
Ctx
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
unsigned
NumBytes
=
alignTo
(
Info
.
TargetSize
+
Info
.
TargetOffset
,
8
)
/
8
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
bool
IsLittleEndian
=
(
Endian
==
support
::
little
)
;
if
(
IsLittleEndian
&&
(
NumBytes
==
4
)
)
{
Data
[
Offset
+
0
]
|=
uint8_t
(
(
Value
>>
16
)
&
0xff
)
;
Data
[
Offset
+
1
]
|=
uint8_t
(
(
Value
>>
24
)
&
0xff
)
;
Data
[
Offset
+
2
]
|=
uint8_t
(
Value
&
0xff
)
;
Data
[
Offset
+
3
]
|=
uint8_t
(
(
Value
>>
8
)
&
0xff
)
;
}
else
{
for
(
unsigned
I
=
0
;
I
!=
NumBytes
;
I
++
)
{
unsigned
Idx
=
IsLittleEndian
I
:
(
NumBytes
1
I
)
;
Data
[
Offset
+
Idx
]
|=
uint8_t
(
(
Value
>>
(
I
*
8
)
)
&
0xff
)
;
}
}
}
</s>

Apply the Value for given Fixup into the provided data fragment , at the offset specified by the fixup and following the fixup kind as appropriate .


Relax the instruction in the given fragment to the next wider instruction .


<s> bool CSKYAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count , const MCSubtargetInfo * STI ) const { if ( Count % 2 ) return false ; while ( Count >= 4 ) { OS . write ( "\xc4\x00\x48\x20" , 4 ) ; Count -= 4 ; } if ( Count ) OS . write ( "\x6c\x03" , 2 ) ; return true ; } </s>

Write an ( optimal ) nop sequence of Count bytes to the given output .


<s> void CSKYAsmBackend :: applyFixup ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target , MutableArrayRef < char > Data , uint64_t Value , bool IsResolved , const MCSubtargetInfo * STI ) const { return ; } </s>


<s> unsigned int getNumFixupKinds ( ) const override { return CSKY :: NumTargetFixupKinds ; } </s>

Get the number of target specific fixup kinds .


<s> bool CSKYAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count ) const { if ( Count % 2 ) return false ; while ( Count >= 4 ) { OS . write ( "\xc4\x00\x48\x20" , 4 ) ; Count -= 4 ; } if ( Count ) OS . write ( "\x6c\x03" , 2 ) ; return true ; } </s>


"Not all fixup kinds added to Infos array"


<s>
void
CSKYAsmBackend
::
relaxInstruction
(
MCInst
&
Inst
,
const
MCSubtargetInfo
&
STI
)
const
{
MCInst
Res
;
switch
(
Inst
.
getOpcode
(
)
)
{
default
:
LLVM_DEBUG
(
Inst
.
dump
(
)
)
;
llvm_unreachable
(
"Opcode not expected!"
)
;
case
CSKY
::
LRW16
:
Res
.
setOpcode
(
CSKY
::
LRW32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
BR16
:
Res
.
setOpcode
(
CSKY
::
BR32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
case
CSKY
::
JBSR32
:
Res
.
setOpcode
(
CSKY
::
JSRI32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
JBR32
:
Res
.
setOpcode
(
CSKY
::
JMPI32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
JBT32
:
case
CSKY
::
JBF32
:
Res
.
setOpcode
(
Inst
.
getOpcode
(
)
==
CSKY
::
JBT32
CSKY
::
JBT_E
:
CSKY
::
JBF_E
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
2
)
)
;
break
;
case
CSKY
::
JBR16
:
Res
.
setOpcode
(
CSKY
::
JBR32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
JBT16
:
case
CSKY
::
JBF16
:
unsigned
opcode
;
if
(
STI
.
getFeatureBits
(
)
[
CSKY
::
HasE2
]
)
opcode
=
Inst
.
getOpcode
(
)
==
CSKY
::
JBT16
CSKY
::
JBT32
:
CSKY
::
JBF32
;
else
opcode
=
Inst
.
getOpcode
(
)
==
CSKY
::
JBT16
CSKY
::
JBT_E
:
CSKY
::
JBF_E
;
Res
.
setOpcode
(
opcode
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
2
)
)
;
break
;
}
Inst
=
std
::
move
(
Res
)
;
}
</s>


<s>
void
CSKYAsmBackend
::
applyFixup
(
const
MCAssembler
&
Asm
,
const
MCFixup
&
Fixup
,
const
MCValue
&
Target
,
MutableArrayRef
<
char
>
Data
,
uint64_t
Value
,
bool
IsResolved
,
const
MCSubtargetInfo
*
STI
)
const
{
MCFixupKind
Kind
=
Fixup
.
getKind
(
)
;
if
(
Kind
>=
FirstLiteralRelocationKind
)
return
;
MCContext
&
Ctx
=
Asm
.
getContext
(
)
;
MCFixupKindInfo
Info
=
getFixupKindInfo
(
Kind
)
;
if
(
!
Value
)
return
;
Value
=
adjustFixupValue
(
Fixup
,
Value
,
Ctx
)
;
Value
<<=
Info
.
TargetOffset
;
unsigned
Offset
=
Fixup
.
getOffset
(
)
;
unsigned
NumBytes
=
alignTo
(
Info
.
TargetSize
+
Info
.
TargetOffset
,
8
)
/
8
;
assert
(
Offset
+
NumBytes
<=
Data
.
size
(
)
&&
"Invalid fixup offset!"
)
;
bool
IsLittleEndian
=
(
Endian
==
support
::
little
)
;
bool
IsInstFixup
=
(
Kind
>=
FirstTargetFixupKind
)
;
if
(
IsLittleEndian
&&
IsInstFixup
&&
(
NumBytes
==
4
)
)
{
Data
[
Offset
+
0
]
|=
uint8_t
(
(
Value
>>
16
)
&
0xff
)
;
Data
[
Offset
+
1
]
|=
uint8_t
(
(
Value
>>
24
)
&
0xff
)
;
Data
[
Offset
+
2
]
|=
uint8_t
(
Value
&
0xff
)
;
Data
[
Offset
+
3
]
|=
uint8_t
(
(
Value
>>
8
)
&
0xff
)
;
}
else
{
for
(
unsigned
I
=
0
;
I
!=
NumBytes
;
I
++
)
{
unsigned
Idx
=
IsLittleEndian
I
:
(
NumBytes
1
I
)
;
Data
[
Offset
+
Idx
]
|=
uint8_t
(
(
Value
>>
(
I
*
8
)
)
&
0xff
)
;
}
}
}
</s>


<s> bool CSKYAsmBackend :: fixupNeedsRelaxation ( const MCFixup & Fixup , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout ) const { return false ; } </s>

Simple predicate for targets where ! Resolved implies requiring relaxation .


<s> bool CSKYAsmBackend :: fixupNeedsRelaxationAdvanced ( const MCFixup & Fixup , bool Resolved , uint64_t Value , const MCRelaxableFragment * DF , const MCAsmLayout & Layout , const bool WasForced ) const { if ( ! Resolved && ! WasForced ) return true ; int64_t Offset = int64_t ( Value ) ; switch ( Fixup . getTargetKind ( ) ) { default : return false ; case CSKY :: fixup_csky_pcrel_imm10_scale2 : return ! isShiftedInt < 10 , 1 > ( Offset ) ; case CSKY :: fixup_csky_pcrel_imm16_scale2 : return ! isShiftedInt < 16 , 1 > ( Offset ) ; case CSKY :: fixup_csky_pcrel_imm26_scale2 : return ! isShiftedInt < 26 , 1 > ( Offset ) ; case CSKY :: fixup_csky_pcrel_uimm7_scale4 : return ! isShiftedUInt < 8 , 2 > ( Offset ) ; } } </s>

Target specific predicate for whether a given fixup requires the associated instruction to be relaxed .


<s> bool CSKYAsmBackend :: mayNeedRelaxation ( const MCInst & Inst , const MCSubtargetInfo & STI ) const { switch ( Inst . getOpcode ( ) ) { default : return false ; case CSKY :: JBR32 : case CSKY :: JBT32 : case CSKY :: JBF32 : case CSKY :: JBSR32 : if ( ! STI . getFeatureBits ( ) [ CSKY :: Has2E3 ] ) return false ; return true ; case CSKY :: JBR16 : case CSKY :: JBT16 : case CSKY :: JBF16 : case CSKY :: LRW16 : case CSKY :: BR16 : return true ; } } </s>

Check whether the given instruction may need relaxation .


<s>
void
CSKYAsmBackend
::
relaxInstruction
(
MCInst
&
Inst
,
const
MCSubtargetInfo
&
STI
)
const
{
MCInst
Res
;
switch
(
Inst
.
getOpcode
(
)
)
{
default
:
Inst
.
dump
(
)
;
llvm_unreachable
(
"Opcode not expected!"
)
;
case
CSKY
::
LRW16
:
Res
.
setOpcode
(
CSKY
::
LRW32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
BR16
:
Res
.
setOpcode
(
CSKY
::
BR32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
break
;
case
CSKY
::
JBSR32
:
Res
.
setOpcode
(
CSKY
::
JSRI32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
JBR32
:
Res
.
setOpcode
(
CSKY
::
JMPI32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
JBT32
:
case
CSKY
::
JBF32
:
Res
.
setOpcode
(
Inst
.
getOpcode
(
)
==
CSKY
::
JBT32
CSKY
::
JBT_E
:
CSKY
::
JBF_E
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
2
)
)
;
break
;
case
CSKY
::
JBR16
:
Res
.
setOpcode
(
CSKY
::
JBR32
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
break
;
case
CSKY
::
JBT16
:
case
CSKY
::
JBF16
:
unsigned
opcode
;
if
(
STI
.
getFeatureBits
(
)
[
CSKY
::
HasE2
]
)
opcode
=
Inst
.
getOpcode
(
)
==
CSKY
::
JBT16
CSKY
::
JBT32
:
CSKY
::
JBF32
;
else
opcode
=
Inst
.
getOpcode
(
)
==
CSKY
::
JBT16
CSKY
::
JBT_E
:
CSKY
::
JBF_E
;
Res
.
setOpcode
(
opcode
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
0
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
1
)
)
;
Res
.
addOperand
(
Inst
.
getOperand
(
2
)
)
;
break
;
}
Inst
=
std
::
move
(
Res
)
;
}
</s>


<s> bool CSKYAsmBackend :: shouldForceRelocation ( const MCAssembler & Asm , const MCFixup & Fixup , const MCValue & Target ) { if ( Fixup . getKind ( ) >= FirstLiteralRelocationKind ) return true ; switch ( Fixup . getTargetKind ( ) ) { default : break ; case CSKY :: fixup_csky_got32 : case CSKY :: fixup_csky_got_imm18_scale4 : case CSKY :: fixup_csky_gotoff : case CSKY :: fixup_csky_gotpc : case CSKY :: fixup_csky_plt32 : case CSKY :: fixup_csky_plt_imm18_scale4 : case CSKY :: fixup_csky_doffset_imm18 : case CSKY :: fixup_csky_doffset_imm18_scale2 : case CSKY :: fixup_csky_doffset_imm18_scale4 : return true ; } return false ; } </s>

Hook to check if a relocation is needed for some target specific reason .


<s> bool CSKYAsmBackend :: writeNopData ( raw_ostream & OS , uint64_t Count , const MCSubtargetInfo * STI ) const { OS . write_zeros ( Count ) ; return true ; } </s>


<s> bool CSKYAsmParser :: ParseDirective ( AsmToken DirectiveID ) { StringRef IDVal = DirectiveID . getString ( ) ; if ( IDVal == ".csky_attribute" ) return parseDirectiveAttribute ( ) ; return true ; } </s>

ParseDirective - Parse a target specific assembler directive This method is deprecated , use 'parseDirective ' instead .


<s> unsigned CSKYAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { CSKYOperand & Op = static_cast < CSKYOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; MCRegister Reg = Op . getReg ( ) ; if ( CSKYMCRegisterClasses [ CSKY :: FPR32RegClassID ] . contains ( Reg ) ) { if ( Kind == MCK_FPR64 || Kind == MCK_sFPR64_V ) { Op . Reg . RegNum = convertFPR32ToFPR64 ( Reg ) ; if ( Kind == MCK_sFPR64_V && ( Op . Reg . RegNum < CSKY :: F0_64 || Op . Reg . RegNum > CSKY :: F15_64 ) ) return Match_InvalidRegOutOfRange ; if ( Kind == MCK_FPR64 && ( Op . Reg . RegNum < CSKY :: F0_64 || Op . Reg . RegNum > CSKY :: F31_64 ) ) return Match_InvalidRegOutOfRange ; return Match_Success ; } } if ( CSKYMCRegisterClasses [ CSKY :: GPRRegClassID ] . contains ( Reg ) ) { if ( Kind == MCK_GPRPair ) { Op . Reg . RegNum = MRI -> getEncodingValue ( Reg ) + CSKY :: R0_R1 ; return Match_Success ; } } return Match_InvalidOperand ; } </s>

Allow a target to add special case operand matching for things that tblgen doesn't/ca n't handle effectively .


"Register sequence is not valid. 'r4-r7' expected"

Process a single instruction and collect debug info anchors .


<s> unsigned CSKYAsmParser :: validateTargetOperandClass ( MCParsedAsmOperand & AsmOp , unsigned Kind ) { CSKYOperand & Op = static_cast < CSKYOperand & > ( AsmOp ) ; if ( ! Op . isReg ( ) ) return Match_InvalidOperand ; MCRegister Reg = Op . getReg ( ) ; if ( CSKYMCRegisterClasses [ CSKY :: FPR32RegClassID ] . contains ( Reg ) ) { if ( Kind == MCK_FPR64 || Kind == MCK_sFPR64 ) { Op . Reg . RegNum = convertFPR32ToFPR64 ( Reg ) ; if ( Kind == MCK_sFPR64 && ( Op . Reg . RegNum < CSKY :: F0_64 || Op . Reg . RegNum > CSKY :: F15_64 ) ) return Match_InvalidRegOutOfRange ; if ( Kind == MCK_FPR64 && ( Op . Reg . RegNum < CSKY :: F0_64 || Op . Reg . RegNum > CSKY :: F31_64 ) ) return Match_InvalidRegOutOfRange ; return Match_Success ; } } if ( CSKYMCRegisterClasses [ CSKY :: GPRRegClassID ] . contains ( Reg ) ) { if ( Kind == MCK_GPRPair ) { Op . Reg . RegNum = MRI -> getEncodingValue ( Reg ) + CSKY :: R0_R1 ; return Match_Success ; } } return Match_InvalidOperand ; } </s>


<s>
void
print
(
raw_ostream
&
OS
)
const
override
{
switch
(
Kind
)
{
case
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
Register
:
OS
<<
"<register x"
<<
getReg
(
)
<<
">"
;
break
;
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
}
}
</s>

print - Print a debug representation of the operand to the given stream .


<s> OperandMatchResultTy CSKYAsmParser :: tryParseRegister ( unsigned & RegNo , SMLoc & StartLoc , SMLoc & EndLoc ) { const AsmToken & Tok = getParser ( ) . getTok ( ) ; StartLoc = Tok . getLoc ( ) ; EndLoc = Tok . getEndLoc ( ) ; StringRef Name = getLexer ( ) . getTok ( ) . getIdentifier ( ) ; if ( matchRegisterNameHelper ( ( MCRegister & ) RegNo , Name ) ) return MatchOperand_NoMatch ; getParser ( ) . Lex ( ) ; return MatchOperand_Success ; } </s>

tryParseRegister - parse one register if possible


<s>
void
addExpr
(
MCInst
&
Inst
,
const
MCExpr
*
Expr
)
const
{
assert
(
Expr
&&
"Expr shouldn't be null!"
)
;
if
(
auto
*
CE
=
dyn_cast
<
MCConstantExpr
>
(
Expr
)
)
Inst
.
addOperand
(
MCOperand
::
createImm
(
CE
->
getValue
(
)
)
)
;
else
Inst
.
addOperand
(
MCOperand
::
createExpr
(
Expr
)
)
;
}
</s>


<s> SMLoc getEndLoc ( ) const override { return EndLoc ; } </s>

getEndLoc - Get the location of the last token of this operand .


<s> SMLoc getLoc ( ) const { return getParser ( ) . getTok ( ) . getLoc ( ) ; } </s>

Get the source location of the point where the field was defined .


<s>
unsigned
getReg
(
)
const
override
{
assert
(
Kind
==
Register
&&
"Invalid type access!"
)
;
return
Reg
.
RegNum
;
}
</s>

Returns the register associated with this edge .


<s> SMLoc getStartLoc ( ) const override { return StartLoc ; } </s>

getStartLoc - Get the location of the first token of this operand .


<s> bool isImm ( ) const override { return Kind == Immediate ; } </s>


<s> bool isMem ( ) const override { return false ; } </s>


<s> bool isReg ( ) const override { return Kind == Register ; } </s>


<s> bool isToken ( ) const override { return Kind == Token ; } </s>


<s> bool CSKYAsmParser :: ParseDirective ( AsmToken DirectiveID ) { return true ; } </s>


<s>
bool
CSKYAsmParser
::
ParseInstruction
(
ParseInstructionInfo
&
Info
,
StringRef
Name
,
SMLoc
NameLoc
,
OperandVector
&
Operands
)
{
Operands
.
push_back
(
CSKYOperand
::
createToken
(
Name
,
NameLoc
)
)
;
if
(
getLexer
(
)
.
is
(
AsmToken
::
EndOfStatement
)
)
return
false
;
if
(
parseOperand
(
Operands
,
Name
)
)
return
true
;
while
(
getLexer
(
)
.
is
(
AsmToken
::
Comma
)
)
{
getLexer
(
)
.
Lex
(
)
;
if
(
parseOperand
(
Operands
,
Name
)
)
return
true
;
}
if
(
getLexer
(
)
.
isNot
(
AsmToken
::
EndOfStatement
)
)
{
SMLoc
Loc
=
getLexer
(
)
.
getLoc
(
)
;
getParser
(
)
.
eatToEndOfStatement
(
)
;
return
Error
(
Loc
,
"unexpected token"
)
;
}
getParser
(
)
.
Lex
(
)
;
return
false
;
}
</s>

ParseInstruction - Parse one assembly instruction .

CSKY
CSKY
CSKYOperand::createToken
"unexpected token"


<s>
void
print
(
raw_ostream
&
OS
)
const
override
{
auto
RegName
=
[
]
(
unsigned
Reg
)
{
if
(
Reg
)
return
CSKYInstPrinter
::
getRegisterName
(
Reg
)
;
else
return
"noreg"
;
}
;
switch
(
Kind
)
{
case
CPOP
:
OS
<<
*
getConstpoolOp
(
)
;
break
;
case
Immediate
:
OS
<<
*
getImm
(
)
;
break
;
case
KindTy
::
Register
:
OS
<<
"<register "
<<
RegName
(
getReg
(
)
)
<<
">"
;
break
;
case
RegisterSeq
:
OS
<<
"<register-seq "
;
OS
<<
RegName
(
getRegSeq
(
)
.
first
)
<<
"-"
<<
RegName
(
getRegSeq
(
)
.
second
)
<<
">"
;
break
;
case
RegisterList
:
OS
<<
"<register-list "
;
OS
<<
RegName
(
getRegList
(
)
.
List1From
)
<<
"-"
<<
RegName
(
getRegList
(
)
.
List1To
)
<<
","
;
OS
<<
RegName
(
getRegList
(
)
.
List2From
)
<<
"-"
<<
RegName
(
getRegList
(
)
.
List2To
)
<<
","
;
OS
<<
RegName
(
getRegList
(
)
.
List3From
)
<<
"-"
<<
RegName
(
getRegList
(
)
.
List3To
)
<<
","
;
OS
<<
RegName
(
getRegList
(
)
.
List4From
)
<<
"-"
<<
RegName
(
getRegList
(
)
.
List4To
)
;
break
;
case
Token
:
OS
<<
"'"
<<
getToken
(
)
<<
"'"
;
break
;
}
}
</s>


<s> OperandMatchResultTy CSKYAsmParser :: tryParseRegister ( unsigned & RegNo , SMLoc & StartLoc , SMLoc & EndLoc ) { const AsmToken & Tok = getParser ( ) . getTok ( ) ; StartLoc = Tok . getLoc ( ) ; EndLoc = Tok . getEndLoc ( ) ; StringRef Name = getLexer ( ) . getTok ( ) . getIdentifier ( ) ; if ( matchRegisterNameHelper ( getSTI ( ) , ( MCRegister & ) RegNo , Name ) ) return MatchOperand_NoMatch ; getParser ( ) . Lex ( ) ; return MatchOperand_Success ; } </s>


<s> void CSKYAsmPrinter :: emitEndOfAsmFile ( Module & M ) { CSKYTargetStreamer & CTS = static_cast < CSKYTargetStreamer & > ( * OutStreamer -> getTargetStreamer ( ) ) ; if ( TM . getTargetTriple ( ) . isOSBinFormatELF ( ) ) CTS . finishAttributeSection ( ) ; } </s>

This virtual method can be overridden by targets that want to emit something at the end of their file .


<s> void CSKYAsmPrinter :: emitFunctionBodyEnd ( ) { if ( ! InConstantPool ) return ; InConstantPool = false ; } </s>

Targets can override this to emit stuff after the last basic block in the function .


<s> void CSKYAsmPrinter :: emitInstruction ( const MachineInstr * MI ) { if ( emitPseudoExpansionLowering ( * OutStreamer , MI ) ) return ; if ( InConstantPool && MI -> getOpcode ( ) != CSKY :: CONSTPOOL_ENTRY ) { InConstantPool = false ; } if ( MI -> getOpcode ( ) == CSKY :: PseudoTLSLA32 ) return expandTLSLA ( MI ) ; if ( MI -> getOpcode ( ) == CSKY :: CONSTPOOL_ENTRY ) return emitCustomConstantPool ( MI ) ; MCInst TmpInst ; MCInstLowering . Lower ( MI , TmpInst ) ; EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>

Targets should implement this to emit instructions .


<s>
void
CSKYAsmPrinter
::
emitMachineConstantPoolValue
(
MachineConstantPoolValue
*
MCPV
)
{
int
Size
=
getDataLayout
(
)
.
getTypeAllocSize
(
MCPV
->
getType
(
)
)
;
CSKYConstantPoolValue
*
CCPV
=
static_cast
<
CSKYConstantPoolValue
*
>
(
MCPV
)
;
MCSymbol
*
MCSym
;
if
(
CCPV
->
isBlockAddress
(
)
)
{
const
BlockAddress
*
BA
=
cast
<
CSKYConstantPoolConstant
>
(
CCPV
)
->
getBlockAddress
(
)
;
MCSym
=
GetBlockAddressSymbol
(
BA
)
;
}
else
if
(
CCPV
->
isGlobalValue
(
)
)
{
const
GlobalValue
*
GV
=
cast
<
CSKYConstantPoolConstant
>
(
CCPV
)
->
getGV
(
)
;
MCSym
=
getSymbol
(
GV
)
;
}
else
if
(
CCPV
->
isMachineBasicBlock
(
)
)
{
const
MachineBasicBlock
*
MBB
=
cast
<
CSKYConstantPoolMBB
>
(
CCPV
)
->
getMBB
(
)
;
MCSym
=
MBB
->
getSymbol
(
)
;
}
else
if
(
CCPV
->
isJT
(
)
)
{
signed
JTI
=
cast
<
CSKYConstantPoolJT
>
(
CCPV
)
->
getJTI
(
)
;
MCSym
=
GetJTISymbol
(
JTI
)
;
}
else
{
assert
(
CCPV
->
isExtSymbol
(
)
&&
"unrecognized constant pool value"
)
;
StringRef
Sym
=
cast
<
CSKYConstantPoolSymbol
>
(
CCPV
)
->
getSymbol
(
)
;
MCSym
=
GetExternalSymbolSymbol
(
Sym
)
;
}
const
MCExpr
*
Expr
=
MCSymbolRefExpr
::
create
(
MCSym
,
MCSymbolRefExpr
::
VK_None
,
OutContext
)
;
if
(
CCPV
->
getPCAdjustment
(
)
)
{
MCSymbol
*
PCLabel
=
OutContext
.
getOrCreateSymbol
(
Twine
(
MAI
->
getPrivateGlobalPrefix
(
)
)
+
"PC"
+
Twine
(
getFunctionNumber
(
)
)
+
"_"
+
Twine
(
CCPV
->
getLabelID
(
)
)
)
;
const
MCExpr
*
PCRelExpr
=
MCSymbolRefExpr
::
create
(
PCLabel
,
OutContext
)
;
if
(
CCPV
->
mustAddCurrentAddress
(
)
)
{
MCSymbol
*
DotSym
=
OutContext
.
createTempSymbol
(
)
;
OutStreamer
->
emitLabel
(
DotSym
)
;
const
MCExpr
*
DotExpr
=
MCSymbolRefExpr
::
create
(
DotSym
,
OutContext
)
;
PCRelExpr
=
MCBinaryExpr
::
createSub
(
PCRelExpr
,
DotExpr
,
OutContext
)
;
}
Expr
=
MCBinaryExpr
::
createSub
(
Expr
,
PCRelExpr
,
OutContext
)
;
}
Expr
=
CSKYMCExpr
::
create
(
Expr
,
getModifierVariantKind
(
CCPV
->
getModifier
(
)
)
,
OutContext
)
;
OutStreamer
->
emitValue
(
Expr
,
Size
)
;
}
</s>

EmitMachineConstantPoolValue - Print a machine constantpool value to the .s file .

CSKY
CSKY
CSKY
CSKY
CSKY
CSKY
CSKY
CSKY
"unrecognized constant pool value"
CSKY
"PC"
"_"
CSKY


<s> void CSKYAsmPrinter :: emitStartOfAsmFile ( Module & M ) { if ( TM . getTargetTriple ( ) . isOSBinFormatELF ( ) ) emitAttributes ( ) ; } </s>

This virtual method can be overridden by targets that want to emit something at the start of their file .


<s>
bool
CSKYAsmPrinter
::
PrintAsmMemoryOperand
(
const
MachineInstr
*
MI
,
unsigned
OpNo
,
const
char
*
ExtraCode
,
raw_ostream
&
OS
)
{
if
(
!
ExtraCode
)
{
const
MachineOperand
&
MO
=
MI
->
getOperand
(
OpNo
)
;
if
(
!
MO
.
isReg
(
)
)
return
true
;
OS
<<
"("
<<
CSKYInstPrinter
::
getRegisterName
(
MO
.
getReg
(
)
)
<<
", 0)"
;
return
false
;
}
return
AsmPrinter
::
PrintAsmMemoryOperand
(
MI
,
OpNo
,
ExtraCode
,
OS
)
;
}
</s>

Print the specified operand of MI , an INLINEASM instruction , using the specified assembler variant as an address .


<s> bool CSKYAsmPrinter :: PrintAsmOperand ( const MachineInstr * MI , unsigned OpNo , const char * ExtraCode , raw_ostream & OS ) { if ( ! AsmPrinter :: PrintAsmOperand ( MI , OpNo , ExtraCode , OS ) ) return false ; const MachineOperand & MO = MI -> getOperand ( OpNo ) ; if ( ExtraCode && ExtraCode [ 0 ] ) { if ( ExtraCode [ 1 ] != 0 ) return true ; switch ( ExtraCode [ 0 ] ) { default : return true ; case 'R' : if ( MO . getType ( ) == MachineOperand :: MO_Register ) { OS << CSKYInstPrinter :: getRegisterName ( MO . getReg ( ) + 1 ) ; return false ; } } } switch ( MO . getType ( ) ) { case MachineOperand :: MO_Immediate : OS << MO . getImm ( ) ; return false ; case MachineOperand :: MO_Register : if ( MO . getReg ( ) == CSKY :: C ) return false ; OS << CSKYInstPrinter :: getRegisterName ( MO . getReg ( ) ) ; return false ; case MachineOperand :: MO_GlobalAddress : PrintSymbolOperand ( MO , OS ) ; return false ; case MachineOperand :: MO_BlockAddress : { MCSymbol * Sym = GetBlockAddressSymbol ( MO . getBlockAddress ( ) ) ; Sym -> print ( OS , MAI ) ; return false ; } default : break ; } return true ; } </s>

PrintAsmOperand - Print out an operand for an inline asm expression .


<s> bool CSKYAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { MCP = MF . getConstantPool ( ) ; TII = MF . getSubtarget ( ) . getInstrInfo ( ) ; MCSubtargetInfo & NewSTI = OutStreamer -> getContext ( ) . getSubtargetCopy ( * TM . getMCSubtargetInfo ( ) ) ; NewSTI . setFeatureBits ( MF . getSubtarget ( ) . getFeatureBits ( ) ) ; Subtarget = & NewSTI ; return AsmPrinter :: runOnMachineFunction ( MF ) ; } </s>

runOnMachineFunction - Emit the function body .


<s> bool CSKYAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { MCP = MF . getConstantPool ( ) ; Subtarget = & MF . getSubtarget < CSKYSubtarget > ( ) ; return AsmPrinter :: runOnMachineFunction ( MF ) ; } </s>


<s> void CSKYAsmPrinter :: emitInstruction ( const MachineInstr * MI ) { if ( emitPseudoExpansionLowering ( * OutStreamer , MI ) ) return ; MCInst TmpInst ; MCInstLowering . Lower ( MI , TmpInst ) ; EmitToStreamer ( * OutStreamer , TmpInst ) ; } </s>


<s>
StringRef
getPassName
(
)
const
override
{
return
"CSKY Assembly Printer"
;
}
</s>

getPassName - Return a nice clean name for a pass .


<s> bool CSKYAsmPrinter :: runOnMachineFunction ( MachineFunction & MF ) { Subtarget = & MF . getSubtarget < CSKYSubtarget > ( ) ; return AsmPrinter :: runOnMachineFunction ( MF ) ; } </s>


"Constant Island pass failed to converge!"

"Branch Fix Up pass failed to converge!"


<s> void getAnalysisUsage ( AnalysisUsage & AU ) const override { AU . addRequired < MachineDominatorTree > ( ) ; MachineFunctionPass :: getAnalysisUsage ( AU ) ; } </s>

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this .


"Didn't find MI in its own basic block?"

getOffsetOf - Return the current offset of the specified machine instruction from the start of the function .


<s>
StringRef
getPassName
(
)
const
override
{
return
"CSKY Constant Islands"
;
}
</s>


<s>
bool
CSKYConstantIslands
::
isBBInRange
(
MachineInstr
*
MI
,
MachineBasicBlock
*
DestBB
,
unsigned
MaxDisp
)
{
unsigned
BrOffset
=
getOffsetOf
(
MI
)
;
unsigned
DestOffset
=
BBInfo
[
DestBB
->
getNumber
(
)
]
.
Offset
;
LLVM_DEBUG
(
dbgs
(
)
<<
"Branch of destination "
<<
printMBBReference
(
*
DestBB
)
<<
" from "
<<
printMBBReference
(
*
MI
->
getParent
(
)
)
<<
" max delta="
<<
MaxDisp
<<
" from "
<<
getOffsetOf
(
MI
)
<<
" to "
<<
DestOffset
<<
" offset "
<<
int
(
DestOffset
BrOffset
)
<<
"\t"
<<
*
MI
)
;
if
(
BrOffset
<=
DestOffset
)
{
if
(
DestOffset
BrOffset
<=
MaxDisp
)
return
true
;
}
else
{
if
(
BrOffset
DestOffset
<=
MaxDisp
)
return
true
;
}
return
false
;
}
</s>

isBBInRange - Returns true if the distance between specific MI and specific BB can fit in MI 's displacement field .

CSKY
CSKY
"Branch of destination "
" from "
" max delta="
" from "
" to "
" offset "
"\t"


<s> unsigned postOffset ( ) const { return Offset + Size ; } </s>

Compute the offset immediately following this block .


<s> static bool classof ( const CSKYConstantPoolValue * ACPV ) { return ACPV -> isJT ( ) ; } </s>

Methods for support type inquiry through isa , cast , and dyn_cast :


<s> CSKYConstantPoolJT * CSKYConstantPoolJT :: Create ( Type * Ty , int JTI , unsigned PCAdj , CSKYCP :: CSKYCPModifier Modifier ) { return new CSKYConstantPoolJT ( Ty , JTI , PCAdj , Modifier , false ) ; } </s>

Construct a unary instruction , given the opcode and an operand .

CSKY CSKY CSKY CSKYCP::CSKYCPModifier CSKY


<s> bool equals ( const CSKYConstantPoolJT * A ) const { return JTI == A -> JTI && CSKYConstantPoolValue :: equals ( A ) ; } </s>

equals - Check for string equality , this is more efficient than compare ( ) when the relative ordering of inequal strings is n't needed .


<s> const MachineBasicBlock * getMBB ( ) const { return MBB ; } </s>

Return a reference to the basic block containing this bundle .


<s> StringRef getSymbol ( ) const { return S ; } </s>

Get the target address and flags for the named symbol .


<s> bool isBlockAddress ( ) const { return Kind == CSKYCP :: CPBlockAddress ; } </s>

isBlockAddress - Tests if this is a MO_BlockAddress operand .


<s> void CSKYConstantPoolJT :: print ( raw_ostream & O ) const { O << "JTI#" << JTI ; CSKYConstantPoolValue :: print ( O ) ; } </s>

print - Print a debug representation of the operand to the given stream .


<s>
DecodeStatus
CSKYDisassembler
::
getInstruction
(
MCInst
&
MI
,
uint64_t
&
Size
,
ArrayRef
<
uint8_t
>
Bytes
,
uint64_t
Address
,
raw_ostream
&
CS
)
const
{
uint32_t
Insn
;
DecodeStatus
Result
=
MCDisassembler
::
Fail
;
Insn
=
support
::
endian
::
read16le
(
Bytes
.
data
(
)
)
;
if
(
(
Insn
>>
14
)
==
0x3
)
{
if
(
Bytes
.
size
(
)
<
4
)
{
Size
=
0
;
return
MCDisassembler
::
Fail
;
}
Insn
=
(
Insn
<<
16
)
|
support
::
endian
::
read16le
(
&
Bytes
[
2
]
)
;
if
(
decodeFPUV3Instruction
(
MI
,
Insn
,
Address
,
this
,
STI
)
)
Result
=
MCDisassembler
::
Success
;
else
{
LLVM_DEBUG
(
dbgs
(
)
<<
"Trying CSKY 32-bit table :\n"
)
;
Result
=
decodeInstruction
(
DecoderTable32
,
MI
,
Insn
,
Address
,
this
,
STI
)
;
}
Size
=
4
;
}
else
{
if
(
Bytes
.
size
(
)
<
2
)
{
Size
=
0
;
return
MCDisassembler
::
Fail
;
}
LLVM_DEBUG
(
dbgs
(
)
<<
"Trying CSKY 16-bit table :\n"
)
;
Result
=
decodeInstruction
(
DecoderTable16
,
MI
,
Insn
,
Address
,
this
,
STI
)
;
Size
=
2
;
}
handleCROperand
(
MI
)
;
return
Result
;
}
</s>

Returns the disassembly of a single instruction .


<s> void reset ( ) override { MappingSymbolCounter = 0 ; State = EMS_None ; MCELFStreamer :: reset ( ) ; } </s>

Reset an existing scalar value for Def and a given Instance .


<s> void emitBytes ( StringRef Data ) override { EmitMappingSymbol ( "$d" ) ; MCELFStreamer :: emitBytes ( Data ) ; } </s>

Emit the bytes in Data into the output .


<s> void emitFill ( const MCExpr & NumBytes , uint64_t FillValue , SMLoc Loc ) override { EmitMappingSymbol ( "$d" ) ; MCObjectStreamer :: emitFill ( NumBytes , FillValue , Loc ) ; } </s>

Emit Size bytes worth of the value specified by FillValue .


<s> void emitInstruction ( const MCInst & Inst , const MCSubtargetInfo & STI ) override { EmitMappingSymbol ( "$t" ) ; MCELFStreamer :: emitInstruction ( Inst , STI ) ; } </s>

Targets should implement this to emit instructions .


<s> void emitValueImpl ( const MCExpr * Value , unsigned Size , SMLoc Loc ) override { EmitMappingSymbol ( "$d" ) ; MCELFStreamer :: emitValueImpl ( Value , Size , Loc ) ; } </s>

Overriding these functions allows us to dismiss all labels that are candidates for marking as microMIPS when .word/.long/.4byte etc directives are emitted .


<s> MCELFStreamer & CSKYTargetELFStreamer :: getStreamer ( ) { return static_cast < MCELFStreamer & > ( Streamer ) ; } </s>

Return the output streamer for the assembler .


<s> void reset ( ) { MappingSymbolCounter = 0 ; State = EMS_None ; MCELFStreamer :: reset ( ) ; } </s>


<s> bool assignCalleeSavedSpillSlots ( MachineFunction & MF , const TargetRegisterInfo * TRI , std :: vector < CalleeSavedInfo > & CSI ) const override { std :: reverse ( CSI . begin ( ) , CSI . end ( ) ) ; return false ; } </s>

This function will assign callee saved gprs to volatile vector registers for prologue spills when applicable .


<s> void CSKYFrameLowering :: determineFrameLayout ( MachineFunction & MF ) const { MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const CSKYRegisterInfo * RI = STI . getRegisterInfo ( ) ; uint64_t FrameSize = MFI . getStackSize ( ) ; Align StackAlign = getStackAlign ( ) ; if ( RI -> hasStackRealignment ( MF ) ) { Align MaxStackAlign = std :: max ( StackAlign , MFI . getMaxAlign ( ) ) ; FrameSize += ( MaxStackAlign . value ( ) - StackAlign . value ( ) ) ; StackAlign = MaxStackAlign ; } uint64_t MaxCallSize = alignTo ( MFI . getMaxCallFrameSize ( ) , StackAlign ) ; MFI . setMaxCallFrameSize ( MaxCallSize ) ; FrameSize = alignTo ( FrameSize , StackAlign ) ; MFI . setStackSize ( FrameSize ) ; } </s>

Determine the frame layout but do not update the machine function .


<s> MachineBasicBlock :: iterator CSKYFrameLowering :: eliminateCallFramePseudoInstr ( MachineFunction & MF , MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI ) const { Register SPReg = CSKY :: R14 ; DebugLoc DL = MI -> getDebugLoc ( ) ; if ( ! hasReservedCallFrame ( MF ) ) { int64_t Amount = MI -> getOperand ( 0 ) . getImm ( ) ; if ( Amount != 0 ) { Amount = alignSPAdjust ( Amount ) ; if ( MI -> getOpcode ( ) == CSKY :: ADJCALLSTACKDOWN ) Amount = - Amount ; adjustReg ( MBB , MI , DL , SPReg , SPReg , Amount , MachineInstr :: NoFlags ) ; } } return MBB . erase ( MI ) ; } </s>

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy pseudo instructions ( but only if the Target is using them ) .


<s> void CSKYFrameLowering :: emitEpilogue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { CSKYMachineFunctionInfo * CFI = MF . getInfo < CSKYMachineFunctionInfo > ( ) ; MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; Register FPReg = getFPReg ( STI ) ; Register SPReg = CSKY :: R14 ; MachineBasicBlock :: iterator MBBI = MBB . end ( ) ; DebugLoc DL ; if ( ! MBB . empty ( ) ) { MBBI = MBB . getFirstTerminator ( ) ; if ( MBBI == MBB . end ( ) ) MBBI = MBB . getLastNonDebugInstr ( ) ; DL = MBBI -> getDebugLoc ( ) ; if ( ! MBBI -> isTerminator ( ) ) MBBI = std :: next ( MBBI ) ; } const auto & CSI = MFI . getCalleeSavedInfo ( ) ; uint64_t StackSize = MFI . getStackSize ( ) ; uint64_t ActualSize = CFI -> getCalleeSaveAreaSize ( ) + CFI -> getVarArgsSaveSize ( ) ; auto LastFrameDestroy = MBBI ; if ( ! CSI . empty ( ) ) LastFrameDestroy = std :: prev ( MBBI , CSI . size ( ) ) ; if ( hasFP ( MF ) ) { const CSKYInstrInfo * TII = STI . getInstrInfo ( ) ; BuildMI ( MBB , LastFrameDestroy , DL , TII -> get ( TargetOpcode :: COPY ) , SPReg ) . addReg ( FPReg ) . setMIFlag ( MachineInstr :: NoFlags ) ; } else { adjustReg ( MBB , LastFrameDestroy , DL , SPReg , SPReg , ( StackSize - ActualSize ) , MachineInstr :: FrameDestroy ) ; } adjustReg ( MBB , MBBI , DL , SPReg , SPReg , ActualSize , MachineInstr :: FrameDestroy ) ; } </s>


<s> StackOffset CSKYFrameLowering :: getFrameIndexReference ( const MachineFunction & MF , int FI , Register & FrameReg ) const { const CSKYMachineFunctionInfo * CFI = MF . getInfo < CSKYMachineFunctionInfo > ( ) ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; const TargetRegisterInfo * RI = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const auto & CSI = MFI . getCalleeSavedInfo ( ) ; int MinCSFI = 0 ; int MaxCSFI = - 1 ; int Offset = MFI . getObjectOffset ( FI ) + MFI . getOffsetAdjustment ( ) ; if ( CSI . size ( ) ) { MinCSFI = CSI [ 0 ] . getFrameIdx ( ) ; MaxCSFI = CSI [ CSI . size ( ) - 1 ] . getFrameIdx ( ) ; } if ( FI >= MinCSFI && FI <= MaxCSFI ) { FrameReg = CSKY :: R14 ; Offset += CFI -> getVarArgsSaveSize ( ) + CFI -> getCalleeSaveAreaSize ( ) ; } else if ( RI -> hasStackRealignment ( MF ) ) { assert ( hasFP ( MF ) ) ; if ( ! MFI . isFixedObjectIndex ( FI ) ) { FrameReg = hasBP ( MF ) ? getBPReg ( STI ) : CSKY :: R14 ; Offset += MFI . getStackSize ( ) ; } else { FrameReg = getFPReg ( STI ) ; Offset += CFI -> getVarArgsSaveSize ( ) + CFI -> getCalleeSaveAreaSize ( ) ; } } else { if ( MFI . isFixedObjectIndex ( FI ) && hasFP ( MF ) ) { FrameReg = getFPReg ( STI ) ; Offset += CFI -> getVarArgsSaveSize ( ) + CFI -> getCalleeSaveAreaSize ( ) ; } else { FrameReg = hasBP ( MF ) ? getBPReg ( STI ) : CSKY :: R14 ; Offset += MFI . getStackSize ( ) ; } } return StackOffset :: getFixed ( Offset ) ; } </s>

getFrameIndexReference - This method should return the base register and offset used to reference a frame index location .


<s> bool CSKYFrameLowering :: hasReservedCallFrame ( const MachineFunction & MF ) const { return ! MF . getFrameInfo ( ) . hasVarSizedObjects ( ) ; } </s>

hasReservedCallFrame - Under normal circumstances , when a frame pointer is not required , we reserve argument space for call sites in the function immediately on entry to the current function .


"loadRegFromStackSlot didn't insert any code!"

restoreCalleeSavedRegisters - Issues instruction ( s ) to restore all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of load instructions via loadRegToStackSlot ( ) .


<s> bool CSKYFrameLowering :: spillCalleeSavedRegisters ( MachineBasicBlock & MBB , MachineBasicBlock :: iterator MI , ArrayRef < CalleeSavedInfo > CSI , const TargetRegisterInfo * TRI ) const { if ( CSI . empty ( ) ) return true ; MachineFunction * MF = MBB . getParent ( ) ; const TargetInstrInfo & TII = * MF -> getSubtarget ( ) . getInstrInfo ( ) ; DebugLoc DL ; if ( MI != MBB . end ( ) && ! MI -> isDebugInstr ( ) ) DL = MI -> getDebugLoc ( ) ; for ( auto & CS : CSI ) { Register Reg = CS . getReg ( ) ; const TargetRegisterClass * RC = TRI -> getMinimalPhysRegClass ( Reg ) ; TII . storeRegToStackSlot ( MBB , MI , Reg , true , CS . getFrameIdx ( ) , RC , TRI ) ; } return true ; } </s>

spillCalleeSavedRegisters - Issues instruction ( s ) to spill all callee saved registers and returns true if it is n't possible / profitable to do so by issuing a series of store instructions via storeRegToStackSlot ( ) .


<s> void CSKYFrameLowering :: emitEpilogue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { } </s>


<s> void CSKYFrameLowering :: emitPrologue ( MachineFunction & MF , MachineBasicBlock & MBB ) const { } </s>

emitProlog/emitEpilog - These methods insert prolog and epilog code into the function .


<s> bool CSKYFrameLowering :: hasFP ( const MachineFunction & MF ) const { const TargetRegisterInfo * RegInfo = MF . getSubtarget ( ) . getRegisterInfo ( ) ; const MachineFrameInfo & MFI = MF . getFrameInfo ( ) ; return MF . getTarget ( ) . Options . DisableFramePointerElim ( MF ) || RegInfo -> hasStackRealignment ( MF ) || MFI . hasVarSizedObjects ( ) || MFI . isFrameAddressTaken ( ) ; } </s>

hasFP - Return true if the specified function should have a dedicated frame pointer register .


<s> bool CSKYInstPrinter :: applyTargetSpecificCLOption ( StringRef Opt ) { if ( Opt == "no-aliases" ) { NoAliases = true ; return true ; } if ( Opt == "numeric" ) { ArchRegNames = true ; return true ; } if ( Opt == "debug" ) { DebugFlag = true ; return true ; } if ( Opt == "abi-names" ) { ABIRegNames = true ; return true ; } return false ; } </s>

Customize the printer according to a command line option .

CSKY CSKY "no-aliases" "numeric" "debug" "abi-names"


<s> void CSKYInstPrinter :: printRegName ( raw_ostream & O , unsigned RegNo ) const { if ( PrintBranchImmAsAddress ) O << getRegisterName ( RegNo , ABIRegNames ? CSKY :: ABIRegAltName : CSKY :: NoRegAltName ) ; else O << getRegisterName ( RegNo ) ; } </s>

CSKY CSKY CSKY::ABIRegAltName CSKY::NoRegAltName


<s> bool CSKYInstPrinter :: applyTargetSpecificCLOption ( StringRef Opt ) { if ( Opt == "no-aliases" ) { NoAliases = true ; return true ; } if ( Opt == "numeric" ) { ArchRegNames = true ; return true ; } return false ; } </s>


<s> void CSKYInstPrinter :: printInst ( const MCInst * MI , uint64_t Address , StringRef Annot , const MCSubtargetInfo & STI , raw_ostream & O ) { const MCInst * NewMI = MI ; if ( NoAliases || ! printAliasInstr ( NewMI , Address , STI , O ) ) printInstruction ( NewMI , Address , STI , O ) ; printAnnotation ( O , Annot ) ; } </s>

Print the specified MCInst to the specified raw_ostream .


<s> void CSKYInstPrinter :: printRegName ( raw_ostream & O , unsigned RegNo ) const { O << getRegisterName ( RegNo ) ; } </s>


<s> bool CSKYInstrInfo :: analyzeBranch ( MachineBasicBlock & MBB , MachineBasicBlock * & TBB , MachineBasicBlock * & FBB , SmallVectorImpl < MachineOperand > & Cond , bool AllowModify ) const { TBB = FBB = nullptr ; Cond . clear ( ) ; MachineBasicBlock :: iterator I = MBB . getLastNonDebugInstr ( ) ; if ( I == MBB . end ( ) || ! isUnpredicatedTerminator ( * I ) ) return false ; MachineBasicBlock :: iterator FirstUncondOrIndirectBr = MBB . end ( ) ; int NumTerminators = 0 ; for ( auto J = I . getReverse ( ) ; J != MBB . rend ( ) && isUnpredicatedTerminator ( * J ) ; J ++ ) { NumTerminators ++ ; if ( J -> getDesc ( ) . isUnconditionalBranch ( ) || J -> getDesc ( ) . isIndirectBranch ( ) ) { FirstUncondOrIndirectBr = J . getReverse ( ) ; } } if ( AllowModify && FirstUncondOrIndirectBr != MBB . end ( ) ) { while ( std :: next ( FirstUncondOrIndirectBr ) != MBB . end ( ) ) { std :: next ( FirstUncondOrIndirectBr ) -> eraseFromParent ( ) ; NumTerminators -- ; } I = FirstUncondOrIndirectBr ; } if ( I -> getDesc ( ) . isIndirectBranch ( ) ) return true ; if ( NumTerminators > 2 ) return true ; if ( NumTerminators == 1 && I -> getDesc ( ) . isUnconditionalBranch ( ) ) { TBB = getBranchDestBlock ( * I ) ; return false ; } if ( NumTerminators == 1 && I -> getDesc ( ) . isConditionalBranch ( ) ) { parseCondBranch ( * I , TBB , Cond ) ; return false ; } if ( NumTerminators == 2 && std :: prev ( I ) -> getDesc ( ) . isConditionalBranch ( ) && I -> getDesc ( ) . isUnconditionalBranch ( ) ) { parseCondBranch ( * std :: prev ( I ) , TBB , Cond ) ; FBB = getBranchDestBlock ( * I ) ; return false ; } return true ; } </s>

analyzeBranch - Analyze the branching code at the end of MBB , returning true if it can not be understood ( e.g .


<s> Register CSKYInstrInfo :: getGlobalBaseReg ( MachineFunction & MF ) const { CSKYMachineFunctionInfo * CFI = MF . getInfo < CSKYMachineFunctionInfo > ( ) ; MachineConstantPool * MCP = MF . getConstantPool ( ) ; MachineRegisterInfo & MRI = MF . getRegInfo ( ) ; Register GlobalBaseReg = CFI -> getGlobalBaseReg ( ) ; if ( GlobalBaseReg != 0 ) return GlobalBaseReg ; MachineBasicBlock & FirstMBB = MF . front ( ) ; MachineBasicBlock :: iterator MBBI = FirstMBB . begin ( ) ; DebugLoc DL ; CSKYConstantPoolValue * CPV = CSKYConstantPoolSymbol :: Create ( Type :: getInt32Ty ( MF . getFunction ( ) . getContext ( ) ) , "_GLOBAL_OFFSET_TABLE_" , 0 , CSKYCP :: ADDR ) ; unsigned CPI = MCP -> getConstantPoolIndex ( CPV , Align ( 4 ) ) ; MachineMemOperand * MO = MF . getMachineMemOperand ( MachinePointerInfo :: getConstantPool ( MF ) , MachineMemOperand :: MOLoad , 4 , Align ( 4 ) ) ; BuildMI ( FirstMBB , MBBI , DL , get ( CSKY :: LRW32 ) , CSKY :: R28 ) . addConstantPoolIndex ( CPI ) . addMemOperand ( MO ) ; GlobalBaseReg = MRI . createVirtualRegister ( & CSKY :: GPRRegClass ) ; BuildMI ( FirstMBB , MBBI , DL , get ( TargetOpcode :: COPY ) , GlobalBaseReg ) . addReg ( CSKY :: R28 ) ; CFI -> setGlobalBaseReg ( GlobalBaseReg ) ; return GlobalBaseReg ; } </s>

getGlobalBaseReg - Return a virtual register initialized with the the global base register value .


<s> unsigned CSKYInstrInfo :: getInstSizeInBytes ( const MachineInstr & MI ) const { switch ( MI . getOpcode ( ) ) { default : return MI . getDesc ( ) . getSize ( ) ; case CSKY :: CONSTPOOL_ENTRY : return MI . getOperand ( 2 ) . getImm ( ) ; case CSKY :: SPILL_CARRY : case CSKY :: RESTORE_CARRY : case CSKY :: PseudoTLSLA32 : return 8 ; case TargetOpcode :: INLINEASM_BR : case TargetOpcode :: INLINEASM : { const MachineFunction * MF = MI . getParent ( ) -> getParent ( ) ; const char * AsmStr = MI . getOperand ( 0 ) . getSymbolName ( ) ; return getInlineAsmLength ( AsmStr , * MF -> getTarget ( ) . getMCAsmInfo ( ) ) ; } } } </s>

Returns the size in bytes of the specified MachineInstr , or ~0U when this function is not implemented by a target .


<s>
static
unsigned
getOppositeBranchOpc
(
unsigned
Opcode
)
{
switch
(
Opcode
)
{
default
:
llvm_unreachable
(
"Unknown conditional branch!"
)
;
case
CSKY
::
BT32
:
return
CSKY
::
BF32
;
case
CSKY
::
BT16
:
return
CSKY
::
BF16
;
case
CSKY
::
BF32
:
return
CSKY
::
BT32
;
case
CSKY
::
BF16
:
return
CSKY
::
BT16
;
case
CSKY
::
BHZ32
:
return
CSKY
::
BLSZ32
;
case
CSKY
::
BHSZ32
:
return
CSKY
::
BLZ32
;
case
CSKY
::
BLZ32
:
return
CSKY
::
BHSZ32
;
case
CSKY
::
BLSZ32
:
return
CSKY
::
BHZ32
;
case
CSKY
::
BNEZ32
:
return
CSKY
::
BEZ32
;
case
CSKY
::
BEZ32
:
return
CSKY
::
BNEZ32
;
}
}
</s>

getOppositeBranchOpc - Return the inverse of the specified opcode , e.g .


"insertBranch must not be told to insert a fallthrough"

"CSKY branch conditions have two components!"

Insert branch code into the end of the specified MachineBasicBlock .


<s> unsigned CSKYInstrInfo :: isLoadFromStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : return 0 ; case CSKY :: LD16B : case CSKY :: LD16H : case CSKY :: LD16W : case CSKY :: LD32B : case CSKY :: LD32BS : case CSKY :: LD32H : case CSKY :: LD32HS : case CSKY :: LD32W : case CSKY :: FLD_S : case CSKY :: FLD_D : case CSKY :: f2FLD_S : case CSKY :: f2FLD_D : case CSKY :: RESTORE_CARRY : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>

isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot , return the virtual or physical register number of the destination along with the FrameIndex of the loaded stack slot .


<s> unsigned CSKYInstrInfo :: isStoreToStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : return 0 ; case CSKY :: ST16B : case CSKY :: ST16H : case CSKY :: ST16W : case CSKY :: ST32B : case CSKY :: ST32H : case CSKY :: ST32W : case CSKY :: FST_S : case CSKY :: FST_D : case CSKY :: f2FST_S : case CSKY :: f2FST_D : case CSKY :: SPILL_CARRY : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>

isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot , return the virtual or physical register number of the source reg along with the FrameIndex of the loaded stack slot .


<s>
void
CSKYInstrInfo
::
loadRegFromStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
Register
DestReg
,
int
FI
,
const
TargetRegisterClass
*
RC
,
const
TargetRegisterInfo
*
TRI
)
const
{
DebugLoc
DL
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
CSKYMachineFunctionInfo
*
CFI
=
MF
.
getInfo
<
CSKYMachineFunctionInfo
>
(
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
unsigned
Opcode
=
0
;
if
(
CSKY
::
GPRRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
LD32W
;
}
else
if
(
CSKY
::
CARRYRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
RESTORE_CARRY
;
CFI
->
setSpillsCR
(
)
;
}
else
if
(
v2sf
&&
CSKY
::
sFPR32RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
FLD_S
;
else
if
(
v2df
&&
CSKY
::
sFPR64RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
FLD_D
;
else
if
(
v3sf
&&
CSKY
::
FPR32RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
f2FLD_S
;
else
if
(
v3df
&&
CSKY
::
FPR64RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
f2FLD_D
;
else
{
llvm_unreachable
(
"Unknown RegisterClass"
)
;
}
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
MachinePointerInfo
::
getFixedStack
(
MF
,
FI
)
,
MachineMemOperand
::
MOLoad
,
MFI
.
getObjectSize
(
FI
)
,
MFI
.
getObjectAlign
(
FI
)
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
Opcode
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
;
}
</s>

Load the specified register of the given register class from the specified stack frame index .


<s> unsigned CSKYInstrInfo :: removeBranch ( MachineBasicBlock & MBB , int * BytesRemoved ) const { if ( BytesRemoved ) * BytesRemoved = 0 ; MachineBasicBlock :: iterator I = MBB . getLastNonDebugInstr ( ) ; if ( I == MBB . end ( ) ) return 0 ; if ( ! I -> getDesc ( ) . isUnconditionalBranch ( ) && ! I -> getDesc ( ) . isConditionalBranch ( ) ) return 0 ; if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I -> eraseFromParent ( ) ; I = MBB . end ( ) ; if ( I == MBB . begin ( ) ) return 1 ; -- I ; if ( ! I -> getDesc ( ) . isConditionalBranch ( ) ) return 1 ; if ( BytesRemoved ) * BytesRemoved += getInstSizeInBytes ( * I ) ; I -> eraseFromParent ( ) ; return 2 ; } </s>

Remove the branching code at the end of the specific MBB .


<s>
bool
CSKYInstrInfo
::
reverseBranchCondition
(
SmallVectorImpl
<
MachineOperand
>
&
Cond
)
const
{
assert
(
(
Cond
.
size
(
)
==
2
)
&&
"Invalid branch condition!"
)
;
Cond
[
0
]
.
setImm
(
getOppositeBranchOpc
(
Cond
[
0
]
.
getImm
(
)
)
)
;
return
false
;
}
</s>

Reverses the branch condition of the specified condition list , returning false on success and true if it can not be reversed .


<s>
void
CSKYInstrInfo
::
storeRegToStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
Register
SrcReg
,
bool
IsKill
,
int
FI
,
const
TargetRegisterClass
*
RC
,
const
TargetRegisterInfo
*
TRI
)
const
{
DebugLoc
DL
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
CSKYMachineFunctionInfo
*
CFI
=
MF
.
getInfo
<
CSKYMachineFunctionInfo
>
(
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
unsigned
Opcode
=
0
;
if
(
CSKY
::
GPRRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
ST32W
;
}
else
if
(
CSKY
::
CARRYRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
SPILL_CARRY
;
CFI
->
setSpillsCR
(
)
;
}
else
if
(
v2sf
&&
CSKY
::
sFPR32RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
FST_S
;
else
if
(
v2df
&&
CSKY
::
sFPR64RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
FST_D
;
else
if
(
v3sf
&&
CSKY
::
FPR32RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
f2FST_S
;
else
if
(
v3df
&&
CSKY
::
FPR64RegClass
.
hasSubClassEq
(
RC
)
)
Opcode
=
CSKY
::
f2FST_D
;
else
{
llvm_unreachable
(
"Unknown RegisterClass"
)
;
}
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
MachinePointerInfo
::
getFixedStack
(
MF
,
FI
)
,
MachineMemOperand
::
MOStore
,
MFI
.
getObjectSize
(
FI
)
,
MFI
.
getObjectAlign
(
FI
)
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
Opcode
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
IsKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
;
}
</s>

Store the specified register of the given register class to the specified stack frame index .


<s>
void
CSKYInstrInfo
::
copyPhysReg
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
const
DebugLoc
&
DL
,
MCRegister
DestReg
,
MCRegister
SrcReg
,
bool
KillSrc
)
const
{
MachineRegisterInfo
&
MRI
=
MBB
.
getParent
(
)
->
getRegInfo
(
)
;
if
(
CSKY
::
GPRRegClass
.
contains
(
SrcReg
)
&&
CSKY
::
CARRYRegClass
.
contains
(
DestReg
)
)
{
if
(
STI
.
hasE2
(
)
)
{
BuildMI
(
MBB
,
I
,
DL
,
get
(
CSKY
::
BTSTI32
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addImm
(
0
)
;
}
else
{
assert
(
SrcReg
<
CSKY
::
R8
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
CSKY
::
BTSTI16
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
.
addImm
(
0
)
;
}
return
;
}
if
(
CSKY
::
CARRYRegClass
.
contains
(
SrcReg
)
&&
CSKY
::
GPRRegClass
.
contains
(
DestReg
)
)
{
if
(
STI
.
hasE2
(
)
)
{
BuildMI
(
MBB
,
I
,
DL
,
get
(
CSKY
::
MVC32
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
else
{
assert
(
DestReg
<
CSKY
::
R16
)
;
assert
(
DestReg
<
CSKY
::
R8
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
CSKY
::
MOVI16
)
,
DestReg
)
.
addImm
(
0
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
CSKY
::
ADDC16
)
)
.
addReg
(
DestReg
,
RegState
::
Define
)
.
addReg
(
SrcReg
,
RegState
::
Define
)
.
addReg
(
DestReg
,
getKillRegState
(
true
)
)
.
addReg
(
DestReg
,
getKillRegState
(
true
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
true
)
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
CSKY
::
BTSTI16
)
)
.
addReg
(
SrcReg
,
RegState
::
Define
|
getDeadRegState
(
KillSrc
)
)
.
addReg
(
DestReg
)
.
addImm
(
0
)
;
}
return
;
}
unsigned
Opcode
=
0
;
if
(
CSKY
::
GPRRegClass
.
contains
(
DestReg
,
SrcReg
)
)
Opcode
=
CSKY
::
MOV32
;
else
{
LLVM_DEBUG
(
dbgs
(
)
<<
"src = "
<<
SrcReg
<<
", dst = "
<<
DestReg
)
;
LLVM_DEBUG
(
I
->
dump
(
)
)
;
llvm_unreachable
(
"Unknown RegisterClass"
)
;
}
BuildMI
(
MBB
,
I
,
DL
,
get
(
Opcode
)
,
DestReg
)
.
addReg
(
SrcReg
,
getKillRegState
(
KillSrc
)
)
;
}
</s>


<s> unsigned CSKYInstrInfo :: isLoadFromStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : return 0 ; case CSKY :: LD16B : case CSKY :: LD16H : case CSKY :: LD16W : case CSKY :: LD32B : case CSKY :: LD32BS : case CSKY :: LD32H : case CSKY :: LD32HS : case CSKY :: LD32W : case CSKY :: RESTORE_CARRY : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>


<s> unsigned CSKYInstrInfo :: isStoreToStackSlot ( const MachineInstr & MI , int & FrameIndex ) const { switch ( MI . getOpcode ( ) ) { default : return 0 ; case CSKY :: ST16B : case CSKY :: ST16H : case CSKY :: ST16W : case CSKY :: ST32B : case CSKY :: ST32H : case CSKY :: ST32W : case CSKY :: SPILL_CARRY : break ; } if ( MI . getOperand ( 1 ) . isFI ( ) && MI . getOperand ( 2 ) . isImm ( ) && MI . getOperand ( 2 ) . getImm ( ) == 0 ) { FrameIndex = MI . getOperand ( 1 ) . getIndex ( ) ; return MI . getOperand ( 0 ) . getReg ( ) ; } return 0 ; } </s>


<s>
void
CSKYInstrInfo
::
loadRegFromStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
Register
DestReg
,
int
FI
,
const
TargetRegisterClass
*
RC
,
const
TargetRegisterInfo
*
TRI
)
const
{
DebugLoc
DL
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
CSKYMachineFunctionInfo
*
CFI
=
MF
.
getInfo
<
CSKYMachineFunctionInfo
>
(
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
unsigned
Opcode
=
0
;
if
(
CSKY
::
GPRRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
LD32W
;
}
else
if
(
CSKY
::
CARRYRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
RESTORE_CARRY
;
CFI
->
setSpillsCR
(
)
;
}
else
{
llvm_unreachable
(
"Unknown RegisterClass"
)
;
}
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
MachinePointerInfo
::
getFixedStack
(
MF
,
FI
)
,
MachineMemOperand
::
MOLoad
,
MFI
.
getObjectSize
(
FI
)
,
MFI
.
getObjectAlign
(
FI
)
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
Opcode
)
,
DestReg
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
;
}
</s>


<s>
void
CSKYInstrInfo
::
storeRegToStackSlot
(
MachineBasicBlock
&
MBB
,
MachineBasicBlock
::
iterator
I
,
Register
SrcReg
,
bool
IsKill
,
int
FI
,
const
TargetRegisterClass
*
RC
,
const
TargetRegisterInfo
*
TRI
)
const
{
DebugLoc
DL
;
if
(
I
!=
MBB
.
end
(
)
)
DL
=
I
->
getDebugLoc
(
)
;
MachineFunction
&
MF
=
*
MBB
.
getParent
(
)
;
CSKYMachineFunctionInfo
*
CFI
=
MF
.
getInfo
<
CSKYMachineFunctionInfo
>
(
)
;
MachineFrameInfo
&
MFI
=
MF
.
getFrameInfo
(
)
;
unsigned
Opcode
=
0
;
if
(
CSKY
::
GPRRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
ST32W
;
}
else
if
(
CSKY
::
CARRYRegClass
.
hasSubClassEq
(
RC
)
)
{
Opcode
=
CSKY
::
SPILL_CARRY
;
CFI
->
setSpillsCR
(
)
;
}
else
{
llvm_unreachable
(
"Unknown RegisterClass"
)
;
}
MachineMemOperand
*
MMO
=
MF
.
getMachineMemOperand
(
MachinePointerInfo
::
getFixedStack
(
MF
,
FI
)
,
MachineMemOperand
::
MOStore
,
MFI
.
getObjectSize
(
FI
)
,
MFI
.
getObjectAlign
(
FI
)
)
;
BuildMI
(
MBB
,
I
,
DL
,
get
(
Opcode
)
)
.
addReg
(
SrcReg
,
getKillRegState
(
IsKill
)
)
.
addFrameIndex
(
FI
)
.
addImm
(
0
)
.
addMemOperand
(
MMO
)
;
}
</s>


<s>
void
CSKYDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
SDLoc
Dl
(
N
)
;
unsigned
Opcode
=
N
->
getOpcode
(
)
;
bool
IsSelected
=
false
;
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
ADDCARRY
:
IsSelected
=
selectAddCarry
(
N
)
;
break
;
case
ISD
::
SUBCARRY
:
IsSelected
=
selectSubCarry
(
N
)
;
break
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
{
Register
GP
=
Subtarget
->
getInstrInfo
(
)
->
getGlobalBaseReg
(
*
MF
)
;
ReplaceNode
(
N
,
CurDAG
->
getRegister
(
GP
,
N
->
getValueType
(
0
)
)
.
getNode
(
)
)
;
IsSelected
=
true
;
break
;
}
case
ISD
::
FrameIndex
:
{
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
0
,
Dl
,
MVT
::
i32
)
;
int
FI
=
cast
<
FrameIndexSDNode
>
(
N
)
->
getIndex
(
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
MVT
::
i32
)
;
ReplaceNode
(
N
,
CurDAG
->
getMachineNode
(
Subtarget
->
hasE2
(
)
CSKY
::
ADDI32
:
CSKY
::
ADDI16XZ
,
Dl
,
MVT
::
i32
,
TFI
,
Imm
)
)
;
IsSelected
=
true
;
break
;
}
}
if
(
IsSelected
)
return
;
SelectCode
(
N
)
;
}
</s>

Main hook for targets to transform nodes into machine nodes .


<s>
void
CSKYDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
SDLoc
Dl
(
N
)
;
unsigned
Opcode
=
N
->
getOpcode
(
)
;
bool
IsSelected
=
false
;
switch
(
Opcode
)
{
default
:
break
;
}
if
(
IsSelected
)
return
;
SelectCode
(
N
)
;
}
</s>


<s>
void
CSKYDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
SDLoc
Dl
(
N
)
;
unsigned
Opcode
=
N
->
getOpcode
(
)
;
bool
IsSelected
=
false
;
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
ADDCARRY
:
IsSelected
=
selectAddCarry
(
N
)
;
break
;
case
ISD
::
SUBCARRY
:
IsSelected
=
selectSubCarry
(
N
)
;
break
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
{
Register
GP
=
Subtarget
->
getInstrInfo
(
)
->
getGlobalBaseReg
(
*
MF
)
;
ReplaceNode
(
N
,
CurDAG
->
getRegister
(
GP
,
N
->
getValueType
(
0
)
)
.
getNode
(
)
)
;
IsSelected
=
true
;
break
;
}
case
ISD
::
FrameIndex
:
{
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
0
,
Dl
,
MVT
::
i32
)
;
int
FI
=
cast
<
FrameIndexSDNode
>
(
N
)
->
getIndex
(
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
MVT
::
i32
)
;
ReplaceNode
(
N
,
CurDAG
->
getMachineNode
(
Subtarget
->
hasE2
(
)
CSKY
::
ADDI32
:
CSKY
::
ADDI16XZ
,
Dl
,
MVT
::
i32
,
TFI
,
Imm
)
)
;
IsSelected
=
true
;
break
;
}
case
CSKYISD
::
BITCAST_TO_LOHI
:
IsSelected
=
selectBITCAST_TO_LOHI
(
N
)
;
break
;
case
ISD
::
INLINEASM
:
case
ISD
::
INLINEASM_BR
:
IsSelected
=
selectInlineAsm
(
N
)
;
break
;
}
if
(
IsSelected
)
return
;
SelectCode
(
N
)
;
}
</s>


<s>
void
CSKYDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
SDLoc
Dl
(
N
)
;
unsigned
Opcode
=
N
->
getOpcode
(
)
;
bool
IsSelected
=
false
;
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
ADDCARRY
:
IsSelected
=
selectAddCarry
(
N
)
;
break
;
case
ISD
::
SUBCARRY
:
IsSelected
=
selectSubCarry
(
N
)
;
break
;
}
if
(
IsSelected
)
return
;
SelectCode
(
N
)
;
}
</s>

CSKY
CSKY
"== "
"\n"
1
ISD::ADDCARRY
ISD::SUBCARRY


"CSKY DAG->DAG Pattern Instruction Selection"

getPassName - Return a nice clean name for a pass .


<s> bool runOnMachineFunction ( MachineFunction & MF ) override { Subtarget = & MF . getSubtarget < CSKYSubtarget > ( ) ; SelectionDAGISel :: runOnMachineFunction ( MF ) ; return true ; } </s>

runOnMachineFunction - Emit the function body .


<s>
void
CSKYDAGToDAGISel
::
Select
(
SDNode
*
N
)
{
if
(
N
->
isMachineOpcode
(
)
)
{
LLVM_DEBUG
(
dbgs
(
)
<<
"== "
;
N
->
dump
(
CurDAG
)
;
dbgs
(
)
<<
"\n"
)
;
N
->
setNodeId
(
1
)
;
return
;
}
SDLoc
Dl
(
N
)
;
unsigned
Opcode
=
N
->
getOpcode
(
)
;
bool
IsSelected
=
false
;
switch
(
Opcode
)
{
default
:
break
;
case
ISD
::
ADDCARRY
:
IsSelected
=
selectAddCarry
(
N
)
;
break
;
case
ISD
::
SUBCARRY
:
IsSelected
=
selectSubCarry
(
N
)
;
break
;
case
ISD
::
GLOBAL_OFFSET_TABLE
:
{
Register
GP
=
Subtarget
->
getInstrInfo
(
)
->
getGlobalBaseReg
(
*
MF
)
;
ReplaceNode
(
N
,
CurDAG
->
getRegister
(
GP
,
N
->
getValueType
(
0
)
)
.
getNode
(
)
)
;
IsSelected
=
true
;
break
;
}
case
ISD
::
FrameIndex
:
{
SDValue
Imm
=
CurDAG
->
getTargetConstant
(
0
,
Dl
,
MVT
::
i32
)
;
int
FI
=
cast
<
FrameIndexSDNode
>
(
N
)
->
getIndex
(
)
;
SDValue
TFI
=
CurDAG
->
getTargetFrameIndex
(
FI
,
MVT
::
i32
)
;
ReplaceNode
(
N
,
CurDAG
->
getMachineNode
(
Subtarget
->
hasE2
(
)
CSKY
::
ADDI32
:
CSKY
::
ADDI16XZ
,
Dl
,
MVT
::
i32
,
TFI
,
Imm
)
)
;
IsSelected
=
true
;
break
;
}
case
ISD
::
INLINEASM
:
case
ISD
::
INLINEASM_BR
:
IsSelected
=
selectInlineAsm
(
N
)
;
break
;
}
if
(
IsSelected
)
return
;
SelectCode
(
N
)
;
}
</s>


<s> bool CSKYDAGToDAGISel :: SelectInlineAsmMemoryOperand ( const SDValue & Op , unsigned ConstraintID , std :: vector < SDValue > & OutOps ) { switch ( ConstraintID ) { case InlineAsm :: Constraint_m : OutOps . push_back ( Op ) ; return false ; default : break ; } return true ; } </s>

SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode , according to the specified constraint .


<s> SDValue getAddr ( NodeTy * N , SelectionDAG & DAG , bool IsLocal = true ) const { SDLoc DL ( N ) ; EVT Ty = getPointerTy ( DAG . getDataLayout ( ) ) ; unsigned Flag = CSKYII :: MO_None ; bool IsPIC = isPositionIndependent ( ) ; if ( IsPIC ) Flag = IsLocal ? CSKYII :: MO_GOTOFF : IsCall ? CSKYII :: MO_PLT32 : CSKYII :: MO_GOT32 ; SDValue TCPV = getTargetConstantPoolValue ( N , Ty , DAG , Flag ) ; SDValue TV = getTargetNode ( N , DL , Ty , DAG , Flag ) ; SDValue Addr = DAG . getNode ( CSKYISD :: LOAD_ADDR , DL , Ty , { TV , TCPV } ) ; if ( ! IsPIC ) return Addr ; SDValue Result = DAG . getNode ( ISD :: ADD , DL , Ty , { DAG . getGLOBAL_OFFSET_TABLE ( Ty ) , Addr } ) ; if ( IsLocal ) return Result ; return DAG . getLoad ( Ty , DL , DAG . getEntryNode ( ) , Result , MachinePointerInfo :: getGOT ( DAG . getMachineFunction ( ) ) ) ; } </s>

Return the address accessed by this recipe .


<s>
const
char
*
CSKYTargetLowering
::
getTargetNodeName
(
unsigned
Opcode
)
const
{
switch
(
Opcode
)
{
default
:
llvm_unreachable
(
"unknown CSKYISD node"
)
;
case
CSKYISD
::
NIE
:
return
"CSKYISD::NIE"
;
case
CSKYISD
::
NIR
:
return
"CSKYISD::NIR"
;
case
CSKYISD
::
RET
:
return
"CSKYISD::RET"
;
case
CSKYISD
::
BITCAST_TO_LOHI
:
return
"CSKYISD::BITCAST_TO_LOHI"
;
}
}
</s>

getTargetNodeName - This method returns the name of a target specific

CSKY
CSKY
"unknown CSKYISD node"
CSKYISD::NIE
"CSKYISD::NIE"
CSKYISD::NIR
"CSKYISD::NIR"
CSKYISD::RET
"CSKYISD::RET"
CSKYISD::BITCAST_TO_LOHI
"CSKYISD::BITCAST_TO_LOHI"


<s>
MachineBasicBlock
*
CSKYTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
&
MI
,
MachineBasicBlock
*
BB
)
const
{
switch
(
MI
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
case
CSKY
::
FSELS
:
case
CSKY
::
FSELD
:
if
(
Subtarget
.
hasE2
(
)
)
return
emitSelectPseudo
(
MI
,
BB
,
CSKY
::
BT32
)
;
else
return
emitSelectPseudo
(
MI
,
BB
,
CSKY
::
BT16
)
;
case
CSKY
::
ISEL32
:
return
emitSelectPseudo
(
MI
,
BB
,
CSKY
::
BT32
)
;
case
CSKY
::
ISEL16
:
return
emitSelectPseudo
(
MI
,
BB
,
CSKY
::
BT16
)
;
}
}
</s>

This method should be implemented by targets that mark instructions with the 'usesCustomInserter ' flag .


<s> bool CSKYTargetLowering :: CanLowerReturn ( CallingConv :: ID CallConv , MachineFunction & MF , bool IsVarArg , const SmallVectorImpl < ISD :: OutputArg > & Outs , LLVMContext & Context ) const { SmallVector < CCValAssign , 16 > CSKYLocs ; CCState CCInfo ( CallConv , IsVarArg , MF , CSKYLocs , Context ) ; return CCInfo . CheckReturn ( Outs , CCAssignFnForReturn ( CallConv , IsVarArg ) ) ; } </s>

This hook should be implemented to check whether the return values described by the Outs array can fit into the return registers .


<s> CCAssignFn * CSKYTargetLowering :: CCAssignFnForCall ( CallingConv :: ID CC , bool IsVarArg ) const { if ( IsVarArg || ! Subtarget . useHardFloatABI ( ) ) return CC_CSKY_ABIV2_SOFT ; else return CC_CSKY_ABIV2_FP ; } </s>

Selects the correct CCAssignFn for a given CallingConvention value .


<s> CCAssignFn * CSKYTargetLowering :: CCAssignFnForReturn ( CallingConv :: ID CC , bool IsVarArg ) const { if ( IsVarArg || ! Subtarget . useHardFloatABI ( ) ) return RetCC_CSKY_ABIV2_SOFT ; else return RetCC_CSKY_ABIV2_FP ; } </s>


<s>
MachineBasicBlock
*
CSKYTargetLowering
::
EmitInstrWithCustomInserter
(
MachineInstr
&
MI
,
MachineBasicBlock
*
BB
)
const
{
switch
(
MI
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"Unexpected instr type to insert"
)
;
case
CSKY
::
ISEL32
:
return
emitSelectPseudo
(
MI
,
BB
,
CSKY
::
BT32
)
;
case
CSKY
::
ISEL16
:
return
emitSelectPseudo
(
MI
,
BB
,
CSKY
::
BT16
)
;
}
}
</s>


<s> CSKYTargetLowering :: ConstraintType CSKYTargetLowering :: getConstraintType ( StringRef Constraint ) const { if ( Constraint . size ( ) == 1 ) { switch ( Constraint [ 0 ] ) { default : break ; case 'a' : case 'b' : case 'v' : case 'w' : case 'y' : return C_RegisterClass ; case 'c' : case 'l' : case 'h' : case 'z' : return C_Register ; } } return TargetLowering :: getConstraintType ( Constraint ) ; } </s>

Given a constraint letter , return the type of constraint for this target .


<s> Register CSKYTargetLowering :: getExceptionPointerRegister ( const Constant * PersonalityFn ) const { return CSKY :: R0 ; } </s>

If a physical register , this returns the register that receives the exception address on entry to an EH pad .


<s> Register CSKYTargetLowering :: getExceptionSelectorRegister ( const Constant * PersonalityFn ) const { return CSKY :: R1 ; } </s>

If a physical register , this returns the register that receives the exception typeid on entry to a landing pad .


<s> EVT CSKYTargetLowering :: getSetCCResultType ( const DataLayout & DL , LLVMContext & Context , EVT VT ) const { if ( ! VT . isVector ( ) ) return MVT :: i32 ; return VT . changeVectorElementTypeToInteger ( ) ; } </s>

Return the value type to use for ISD : :SETCC .


<s> SDValue CSKYTargetLowering :: getTargetNode ( BlockAddressSDNode * N , SDLoc DL , EVT Ty , SelectionDAG & DAG , unsigned Flags ) const { return DAG . getTargetBlockAddress ( N -> getBlockAddress ( ) , Ty , N -> getOffset ( ) , Flags ) ; } </s>

Retrieve the target node this edge connects to .


<s>
const
char
*
CSKYTargetLowering
::
getTargetNodeName
(
unsigned
Opcode
)
const
{
switch
(
Opcode
)
{
default
:
llvm_unreachable
(
"unknown CSKYISD node"
)
;
case
CSKYISD
::
NIE
:
return
"CSKYISD::NIE"
;
case
CSKYISD
::
NIR
:
return
"CSKYISD::NIR"
;
case
CSKYISD
::
RET
:
return
"CSKYISD::RET"
;
case
CSKYISD
::
CALL
:
return
"CSKYISD::CALL"
;
case
CSKYISD
::
CALLReg
:
return
"CSKYISD::CALLReg"
;
case
CSKYISD
::
TAIL
:
return
"CSKYISD::TAIL"
;
case
CSKYISD
::
TAILReg
:
return
"CSKYISD::TAILReg"
;
case
CSKYISD
::
LOAD_ADDR
:
return
"CSKYISD::LOAD_ADDR"
;
case
CSKYISD
::
BITCAST_TO_LOHI
:
return
"CSKYISD::BITCAST_TO_LOHI"
;
case
CSKYISD
::
BITCAST_FROM_LOHI
:
return
"CSKYISD::BITCAST_FROM_LOHI"
;
}
}
</s>

CSKY
CSKY
"unknown CSKYISD node"
CSKYISD::NIE
"CSKYISD::NIE"
CSKYISD::NIR
"CSKYISD::NIR"
CSKYISD::RET
"CSKYISD::RET"
CSKYISD::CALL
"CSKYISD::CALL"
CSKYISD::CALLReg
"CSKYISD::CALLReg"
CSKYISD::TAIL
"CSKYISD::TAIL"
CSKYISD::TAILReg
"CSKYISD::TAILReg"
CSKYISD::LOAD_ADDR
"CSKYISD::LOAD_ADDR"
CSKYISD::BITCAST_TO_LOHI
"CSKYISD::BITCAST_TO_LOHI"
CSKYISD::BITCAST_FROM_LOHI
"CSKYISD::BITCAST_FROM_LOHI"


<s>
SDValue
CSKYTargetLowering
::
LowerOperation
(
SDValue
Op
,
SelectionDAG
&
DAG
)
const
{
switch
(
Op
.
getOpcode
(
)
)
{
default
:
llvm_unreachable
(
"unimplemented op"
)
;
case
ISD
::
GlobalAddress
:
return
LowerGlobalAddress
(
Op
,
DAG
)
;
case
ISD
::
ExternalSymbol
:
return
LowerExternalSymbol
(
Op
,
DAG
)
;
case
ISD
::
GlobalTLSAddress
:
return
LowerGlobalTLSAddress
(
Op
,
DAG
)
;
case
ISD
::
JumpTable
:
return
LowerJumpTable
(
Op
,
DAG
)
;
case
ISD
::
BlockAddress
:
return
LowerBlockAddress
(
Op
,
DAG
)
;
case
ISD
::
VASTART
:
return
LowerVASTART
(
Op
,
DAG
)
;
case
ISD
::
FRAMEADDR
:
return
LowerFRAMEADDR
(
Op
,
DAG
)
;
case
ISD
::
RETURNADDR
:
return
LowerRETURNADDR
(
Op
,
DAG
)
;
}
}
</s>

LowerOperation - Provide custom lowering hooks for some operations .

CSKY
CSKY
"unimplemented op"
ISD::GlobalAddress
ISD::ExternalSymbol
ISD::GlobalTLSAddress
ISD::JumpTable
ISD::BlockAddress
ISD::VASTART
ISD::FRAMEADDR
ISD::RETURNADDR


<s>
SDValue
CSKYTargetLowering
::
LowerReturn
(
SDValue
Chain
,
CallingConv
::
ID
CallConv
,
bool
IsVarArg
,
const
SmallVectorImpl
<
ISD
::
OutputArg
>
&
Outs
,
const
SmallVectorImpl
<
SDValue
>
&
OutVals
,
const
SDLoc
&
DL
,
SelectionDAG
&
DAG
)
const
{
SmallVector
<
CCValAssign
,
16
>
CSKYLocs
;
CCState
CCInfo
(
CallConv
,
IsVarArg
,
DAG
.
getMachineFunction
(
)
,
CSKYLocs
,
*
DAG
.
getContext
(
)
)
;
CCInfo
.
AnalyzeReturn
(
Outs
,
CCAssignFnForReturn
(
CallConv
,
IsVarArg
)
)
;
SDValue
Glue
;
SmallVector
<
SDValue
,
4
>
RetOps
(
1
,
Chain
)
;
for
(
unsigned
i
=
0
,
e
=
CSKYLocs
.
size
(
)
;
i
<
e
;
++
i
)
{
SDValue
Val
=
OutVals
[
i
]
;
CCValAssign
&
VA
=
CSKYLocs
[
i
]
;
assert
(
VA
.
isRegLoc
(
)
&&
"Can only return in registers!"
)
;
bool
IsF64OnCSKY
=
VA
.
getLocVT
(
)
==
MVT
::
i32
&&
VA
.
getValVT
(
)
==
MVT
::
f64
;
if
(
IsF64OnCSKY
)
{
assert
(
VA
.
isRegLoc
(
)
&&
"Expected return via registers"
)
;
SDValue
Split64
=
DAG
.
getNode
(
CSKYISD
::
BITCAST_TO_LOHI
,
DL
,
DAG
.
getVTList
(
MVT
::
i32
,
MVT
::
i32
)
,
Val
)
;
SDValue
Lo
=
Split64
.
getValue
(
0
)
;
SDValue
Hi
=
Split64
.
getValue
(
1
)
;
Register
RegLo
=
VA
.
getLocReg
(
)
;
assert
(
RegLo
<
CSKY
::
R31
&&
"Invalid register pair"
)
;
Register
RegHi
=
RegLo
+
1
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
RegLo
,
Lo
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
RegLo
,
MVT
::
i32
)
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
RegHi
,
Hi
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
RegHi
,
MVT
::
i32
)
)
;
}
else
{
Val
=
convertValVTToLocVT
(
DAG
,
Val
,
VA
,
DL
)
;
Chain
=
DAG
.
getCopyToReg
(
Chain
,
DL
,
VA
.
getLocReg
(
)
,
Val
,
Glue
)
;
Glue
=
Chain
.
getValue
(
1
)
;
RetOps
.
push_back
(
DAG
.
getRegister
(
VA
.
getLocReg
(
)
,
VA
.
getLocVT
(
)
)
)
;
}
}
RetOps
[
0
]
=
Chain
;
if
(
Glue
.
getNode
(
)
)
{
RetOps
.
push_back
(
Glue
)
;
}
if
(
DAG
.
getMachineFunction
(
)
.
getFunction
(
)
.
hasFnAttribute
(
"interrupt"
)
)
return
DAG
.
getNode
(
CSKYISD
::
NIR
,
DL
,
MVT
::
Other
,
RetOps
)
;
return
DAG
.
getNode
(
CSKYISD
::
RET
,
DL
,
MVT
::
Other
,
RetOps
)
;
}
</s>

This hook must be implemented to lower outgoing return values , described by the Outs array , into the specified DAG .


<s> Register getGlobalBaseReg ( ) const { return GlobalBaseReg ; } </s>

getGlobalBaseReg - Return a virtual register initialized with the the global base register value .


<s> void CSKYMCCodeEmitter :: encodeInstruction ( const MCInst & MI , raw_ostream & OS , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { const MCInstrDesc & Desc = MII . get ( MI . getOpcode ( ) ) ; unsigned Size = Desc . getSize ( ) ; uint32_t Bin = getBinaryCodeForInstr ( MI , Fixups , STI ) ; uint16_t LO16 = static_cast < uint16_t > ( Bin ) ; uint16_t HI16 = static_cast < uint16_t > ( Bin >> 16 ) ; if ( Size == 4 ) support :: endian :: write < uint16_t > ( OS , HI16 , support :: little ) ; support :: endian :: write < uint16_t > ( OS , LO16 , support :: little ) ; ++ MCNumEmitted ; } </s>

Encode the given Inst to bytes and append to CB .

CSKY CSKY 16 4 support::endian support::little support::endian support::little


<s> void CSKYMCCodeEmitter :: encodeInstruction ( const MCInst & MI , raw_ostream & OS , SmallVectorImpl < MCFixup > & Fixups , const MCSubtargetInfo & STI ) const { const MCInstrDesc & Desc = MII . get ( MI . getOpcode ( ) ) ; unsigned Size = Desc . getSize ( ) ; ++ MCNumEmitted ; uint32_t Bin = getBinaryCodeForInstr ( MI , Fixups , STI ) ; uint16_t LO16 = static_cast < uint16_t > ( Bin ) ; uint16_t HI16 = static_cast < uint16_t > ( Bin >> 16 ) ; if ( Size == 4 ) support :: endian :: write < uint16_t > ( OS , HI16 , support :: little ) ; support :: endian :: write < uint16_t > ( OS , LO16 , support :: little ) ; } </s>


<s>
unsigned
CSKYMCCodeEmitter
::
getMachineOpValue
(
const
MCInst
&
MI
,
const
MCOperand
&
MO
,
SmallVectorImpl
<
MCFixup
>
&
Fixups
,
const
MCSubtargetInfo
&
STI
)
const
{
if
(
MO
.
isReg
(
)
)
return
Ctx
.
getRegisterInfo
(
)
->
getEncodingValue
(
MO
.
getReg
(
)
)
;
if
(
MO
.
isImm
(
)
)
return
static_cast
<
unsigned
>
(
MO
.
getImm
(
)
)
;
llvm_unreachable
(
"Unhandled expression!"
)
;
return
0
;
}
</s>

getMachineOpValue - Return binary encoding of operand .


<s>
StringRef
CSKYMCExpr
::
getVariantKindName
(
VariantKind
Kind
)
{
switch
(
Kind
)
{
default
:
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
case
VK_CSKY_ADDR
:
return
""
;
case
VK_CSKY_PCREL
:
return
""
;
case
VK_CSKY_GOT
:
return
"@GOT"
;
case
VK_CSKY_GOTPC
:
return
"@GOTPC"
;
case
VK_CSKY_GOTOFF
:
return
"@GOTOFF"
;
case
VK_CSKY_PLT
:
return
"@PLT"
;
case
VK_CSKY_TPOFF
:
return
"@TPOFF"
;
case
VK_CSKY_TLSGD
:
return
"@TLSGD"
;
}
}
</s>

Convert the variant kind into an ELF-appropriate modifier ( e.g .

CSKY
CSKY
"Invalid ELF symbol kind"
CSKY
""
CSKY
""
CSKY
"@GOT"
CSKY
"@GOTPC"
CSKY
"@GOTOFF"
CSKY
"@PLT"
CSKY
"@TPOFF"
CSKY
"@TLSGD"


<s> static bool classof ( const MCExpr * E ) { return E -> getKind ( ) == MCExpr :: Target ; } </s>

Methods for support type inquiry through isa , cast , and dyn_cast :


<s> const CSKYMCExpr * CSKYMCExpr :: create ( const MCExpr * Expr , VariantKind Kind , MCContext & Ctx ) { return new ( Ctx ) CSKYMCExpr ( Kind , Expr ) ; } </s>


<s> MCFragment * findAssociatedFragment ( ) const override { return getSubExpr ( ) -> findAssociatedFragment ( ) ; } </s>

Find the `` associated section '' for this expression , which is currently defined as the absolute section for constants , or otherwise the section associated with the first defined symbol in the expression .


<s> VariantKind getKind ( ) const { return Kind ; } </s>


<s> const MCExpr * getSubExpr ( ) const { return Expr ; } </s>

getSubExpr - Get the child of this expression .


<s>
StringRef
CSKYMCExpr
::
getVariantKindName
(
VariantKind
Kind
)
{
switch
(
Kind
)
{
default
:
llvm_unreachable
(
"Invalid ELF symbol kind"
)
;
case
VK_CSKY_None
:
case
VK_CSKY_ADDR
:
return
""
;
case
VK_CSKY_ADDR_HI16
:
return
"@HI16"
;
case
VK_CSKY_ADDR_LO16
:
return
"@LO16"
;
case
VK_CSKY_GOT_IMM18_BY4
:
case
VK_CSKY_GOT
:
return
"@GOT"
;
case
VK_CSKY_GOTPC
:
return
"@GOTPC"
;
case
VK_CSKY_GOTOFF
:
return
"@GOTOFF"
;
case
VK_CSKY_PLT_IMM18_BY4
:
case
VK_CSKY_PLT
:
return
"@PLT"
;
case
VK_CSKY_TLSLE
:
return
"@TPOFF"
;
case
VK_CSKY_TLSIE
:
return
"@GOTTPOFF"
;
case
VK_CSKY_TLSGD
:
return
"@TLSGD32"
;
case
VK_CSKY_TLSLDO
:
return
"@TLSLDO32"
;
case
VK_CSKY_TLSLDM
:
return
"@TLSLDM32"
;
}
}
</s>


<s>
bool
CSKYMCInstLower
::
lowerOperand
(
const
MachineOperand
&
MO
,
MCOperand
&
MCOp
)
const
{
switch
(
MO
.
getType
(
)
)
{
default
:
llvm_unreachable
(
"unknown operand type"
)
;
case
MachineOperand
::
MO_RegisterMask
:
break
;
case
MachineOperand
::
MO_Immediate
:
MCOp
=
MCOperand
::
createImm
(
MO
.
getImm
(
)
)
;
break
;
case
MachineOperand
::
MO_Register
:
if
(
MO
.
isImplicit
(
)
)
return
false
;
MCOp
=
MCOperand
::
createReg
(
MO
.
getReg
(
)
)
;
break
;
case
MachineOperand
::
MO_MachineBasicBlock
:
MCOp
=
MCOperand
::
createExpr
(
MCSymbolRefExpr
::
create
(
MO
.
getMBB
(
)
->
getSymbol
(
)
,
Ctx
)
)
;
break
;
case
MachineOperand
::
MO_GlobalAddress
:
MCOp
=
lowerSymbolOperand
(
MO
,
Printer
.
getSymbol
(
MO
.
getGlobal
(
)
)
)
;
break
;
case
MachineOperand
::
MO_BlockAddress
:
MCOp
=
lowerSymbolOperand
(
MO
,
Printer
.
GetBlockAddressSymbol
(
MO
.
getBlockAddress
(
)
)
)
;
break
;
case
MachineOperand
::
MO_ExternalSymbol
:
MCOp
=
lowerSymbolOperand
(
MO
,
Printer
.
GetExternalSymbolSymbol
(
MO
.
getSymbolName
(
)
)
)
;
break
;
case
MachineOperand
::
MO_ConstantPoolIndex
:
MCOp
=
lowerSymbolOperand
(
MO
,
Printer
.
GetCPISymbol
(
MO
.
getIndex
(
)
)
)
;
break
;
case
MachineOperand
::
MO_JumpTableIndex
:
MCOp
=
lowerSymbolOperand
(
MO
,
Printer
.
GetJTISymbol
(
MO
.
getIndex
(
)
)
)
;
break
;
case
MachineOperand
::
MO_MCSymbol
:
MCOp
=
lowerSymbolOperand
(
MO
,
MO
.
getMCSymbol
(
)
)
;
break
;
}
return
true
;
}
</s>

Wrapper for MCInstLowering.lowerOperand ( ) for the tblgen'erated pseudo lowering .


<s> bool evaluateBranch ( const MCInst & Inst , uint64_t Addr , uint64_t Size , uint64_t & Target ) const override { if ( isConditionalBranch ( Inst ) || isUnconditionalBranch ( Inst ) ) { int64_t Imm ; Imm = Inst . getOperand ( Inst . getNumOperands ( ) - 1 ) . getImm ( ) ; Target = Addr + Imm ; return true ; } if ( Inst . getOpcode ( ) == CSKY :: BSR32 ) { Target = Addr + Inst . getOperand ( 0 ) . getImm ( ) ; return true ; } switch ( Inst . getOpcode ( ) ) { default : return false ; case CSKY :: LRW16 : case CSKY :: LRW32 : case CSKY :: JSRI32 : case CSKY :: JMPI32 : int64_t Imm = Inst . getOperand ( Inst . getNumOperands ( ) - 1 ) . getImm ( ) ; Target = ( ( Addr + Imm ) & 0xFFFFFFFC ) ; return true ; } return false ; } </s>

Given a branch instruction try to get the address the branch targets .


<s> const MCPhysReg * CSKYRegisterInfo :: getCalleeSavedRegs ( const MachineFunction * MF ) const { const CSKYSubtarget & STI = MF -> getSubtarget < CSKYSubtarget > ( ) ; if ( MF -> getFunction ( ) . hasFnAttribute ( "interrupt" ) ) { if ( STI . hasFPUv3DoubleFloat ( ) ) return CSR_GPR_FPR64v3_ISR_SaveList ; if ( STI . hasFPUv3SingleFloat ( ) ) return CSR_GPR_FPR32v3_ISR_SaveList ; if ( STI . hasFPUv2DoubleFloat ( ) ) return CSR_GPR_FPR64_ISR_SaveList ; if ( STI . hasFPUv2SingleFloat ( ) ) return CSR_GPR_FPR32_ISR_SaveList ; return CSR_GPR_ISR_SaveList ; } if ( STI . hasFPUv2DoubleFloat ( ) || STI . hasFPUv3DoubleFloat ( ) ) return CSR_GPR_FPR64_SaveList ; if ( STI . hasFPUv2SingleFloat ( ) || STI . hasFPUv3SingleFloat ( ) ) return CSR_GPR_FPR32_SaveList ; return CSR_I32_SaveList ; } </s>


<s> const uint32_t * CSKYRegisterInfo :: getCallPreservedMask ( const MachineFunction & MF , CallingConv :: ID Id ) const { const CSKYSubtarget & STI = MF . getSubtarget < CSKYSubtarget > ( ) ; if ( STI . hasFPUv2DoubleFloat ( ) || STI . hasFPUv3DoubleFloat ( ) ) return CSR_GPR_FPR64_RegMask ; if ( STI . hasFPUv2SingleFloat ( ) || STI . hasFPUv3SingleFloat ( ) ) return CSR_GPR_FPR32_RegMask ; return CSR_I32_RegMask ; } </s>

Return a mask of call-preserved registers for the given calling convention on the current function .


<s> bool requiresFrameIndexScavenging ( const MachineFunction & MF ) const override { return true ; } </s>

Returns true if the target requires post PEI scavenging of registers for materializing frame index constants .


<s> bool requiresRegisterScavenging ( const MachineFunction & MF ) const override { return true ; } </s>

Returns true if the target requires ( and can make use of ) the register scavenger .


<s> bool useFPForScavengingIndex ( const MachineFunction & MF ) const override { return false ; } </s>

Returns true if the target wants to use frame pointer based accesses to spill to the scavenger emergency spill slot .


<s>
void
CSKYRegisterInfo
::
eliminateFrameIndex
(
MachineBasicBlock
::
iterator
II
,
int
SPAdj
,
unsigned
FIOperandNum
,
RegScavenger
*
RS
)
const
{
assert
(
SPAdj
==
0
&&
"Unexpected non-zero SPAdj value"
)
;
}
</s>

This method must be overriden to eliminate abstract frame indices from instructions which may use them .

CSKY
CSKY
0
"Unexpected non-zero SPAdj value"


<s> const MCPhysReg * CSKYRegisterInfo :: getCalleeSavedRegs ( const MachineFunction * MF ) const { const CSKYSubtarget & STI = MF -> getSubtarget < CSKYSubtarget > ( ) ; if ( MF -> getFunction ( ) . hasFnAttribute ( "interrupt" ) ) { return CSR_GPR_ISR_SaveList ; } return CSR_I32_SaveList ; } </s>


<s> const uint32_t * CSKYRegisterInfo :: getCallPreservedMask ( const MachineFunction & MF , CallingConv :: ID Id ) const { const CSKYSubtarget & STI = MF . getSubtarget < CSKYSubtarget > ( ) ; return CSR_I32_RegMask ; } </s>


<s> Register CSKYRegisterInfo :: getFrameRegister ( const MachineFunction & MF ) const { const TargetFrameLowering * TFI = getFrameLowering ( MF ) ; return TFI -> hasFP ( MF ) ? CSKY :: R8 : CSKY :: R14 ; } </s>


<s> const uint32_t * CSKYRegisterInfo :: getNoPreservedMask ( ) const { return CSR_NoRegs_RegMask ; } </s>

Return a register mask that clobbers everything .


<s> BitVector CSKYRegisterInfo :: getReservedRegs ( const MachineFunction & MF ) const { const CSKYFrameLowering * TFI = getFrameLowering ( MF ) ; const CSKYSubtarget & STI = MF . getSubtarget < CSKYSubtarget > ( ) ; BitVector Reserved ( getNumRegs ( ) ) ; if ( TFI -> hasBP ( MF ) ) markSuperRegs ( Reserved , CSKY :: R7 ) ; if ( TFI -> hasFP ( MF ) ) markSuperRegs ( Reserved , CSKY :: R8 ) ; if ( ! STI . hasE2 ( ) ) { for ( unsigned i = 0 ; i < 6 ; i ++ ) markSuperRegs ( Reserved , CSKY :: R8 + i ) ; } markSuperRegs ( Reserved , CSKY :: R14 ) ; markSuperRegs ( Reserved , CSKY :: R15 ) ; if ( ! STI . hasHighRegisters ( ) ) { for ( unsigned i = 0 ; i < 10 ; i ++ ) markSuperRegs ( Reserved , CSKY :: R16 + i ) ; } markSuperRegs ( Reserved , CSKY :: R26 ) ; markSuperRegs ( Reserved , CSKY :: R27 ) ; markSuperRegs ( Reserved , CSKY :: R28 ) ; markSuperRegs ( Reserved , CSKY :: R29 ) ; markSuperRegs ( Reserved , CSKY :: R30 ) ; markSuperRegs ( Reserved , CSKY :: R31 ) ; assert ( checkAllSuperRegsMarked ( Reserved ) ) ; return Reserved ; } </s>

getReservedRegs - Returns a bitset indexed by physical register number indicating if a register is a special register that has particular uses and should be considered unavailable at all times , e.g .


<s> CSKYSubtarget & CSKYSubtarget :: initializeSubtargetDependencies ( const Triple & TT , StringRef CPUName , StringRef TuneCPUName , StringRef FS ) { if ( CPUName . empty ( ) ) CPUName = "generic" ; if ( TuneCPUName . empty ( ) ) TuneCPUName = CPUName ; UseHardFloat = false ; UseHardFloatABI = false ; HasFPUv2SingleFloat = false ; HasFPUv2DoubleFloat = false ; HasFPUv3HalfWord = false ; HasFPUv3HalfFloat = false ; HasFPUv3SingleFloat = false ; HasFPUv3DoubleFloat = false ; HasFdivdu = false ; HasFLOATE1 = false ; HasFLOAT1E2 = false ; HasFLOAT1E3 = false ; HasFLOAT3E4 = false ; HasFLOAT7E60 = false ; HasExtendLrw = false ; HasBTST16 = false ; HasTrust = false ; HasJAVA = false ; HasCache = false ; HasNVIC = false ; HasDSP = false ; HasDSP1E2 = false ; HasDSPE60 = false ; HasDSPV2 = false ; HasDSP_Silan = false ; HasDoloop = false ; HasHardwareDivide = false ; HasHighRegisters = false ; HasVDSPV2 = false ; HasVDSP2E3 = false ; HasVDSP2E60F = false ; ReadTPHard = false ; HasVDSPV1_128 = false ; UseCCRT = false ; DumpConstPool = false ; EnableInterruptAttribute = false ; HasPushPop = false ; HasSTM = false ; SmartMode = false ; EnableStackSize = false ; HasE1 = false ; HasE2 = false ; Has2E3 = false ; HasMP = false ; Has3E3r1 = false ; Has3r1E3r2 = false ; Has3r2E3r3 = false ; Has3E7 = false ; HasMP1E2 = false ; Has7E10 = false ; Has10E60 = false ; ParseSubtargetFeatures ( CPUName , TuneCPUName , FS ) ; return * this ; } </s>

initializeSubtargetDependencies - Initializes using a CPU , a TuneCPU , and feature string so that we can use initializer lists for subtarget initialization .


<s> CSKYSubtarget & CSKYSubtarget :: initializeSubtargetDependencies ( const Triple & TT , StringRef CPUName , StringRef TuneCPUName , StringRef FS ) { if ( CPUName . empty ( ) ) CPUName = "generic" ; if ( TuneCPUName . empty ( ) ) TuneCPUName = CPUName ; UseHardFloat = false ; UseHardFloatABI = false ; HasFPUv2SingleFloat = false ; HasFPUv2DoubleFloat = false ; HasFPUv3SingleFloat = false ; HasFPUv3DoubleFloat = false ; HasBTST16 = false ; HasJAVA = false ; HasExtendLrw = false ; HasDoloop = false ; HasHighRegisters = false ; HasE1 = false ; HasE2 = false ; Has2E3 = false ; HasMP = false ; Has3E3r1 = false ; Has3r1E3r2 = false ; Has3r2E3r3 = false ; Has3E7 = false ; HasMP1E2 = false ; Has7E10 = false ; Has10E60 = false ; ParseSubtargetFeatures ( CPUName , TuneCPUName , FS ) ; return * this ; } </s>


<s> const CSKYInstrInfo * getInstrInfo ( ) const override { return & InstrInfo ; } </s>


<s> const CSKYRegisterInfo * getRegisterInfo ( ) const override { return & RegInfo ; } </s>

getRegisterInfo - TargetInstrInfo is a superset of MRegister info .


<s> CSKYSubtarget & CSKYSubtarget :: initializeSubtargetDependencies ( const Triple & TT , StringRef CPUName , StringRef TuneCPUName , StringRef FS ) { if ( CPUName . empty ( ) ) CPUName = "generic" ; if ( TuneCPUName . empty ( ) ) TuneCPUName = CPUName ; HasE1 = false ; HasE2 = false ; Has2E3 = false ; HasMP = false ; Has3E3r1 = false ; Has3r1E3r2 = false ; Has3r2E3r3 = false ; Has3E7 = false ; HasMP1E2 = false ; Has7E10 = false ; Has10E60 = false ; ParseSubtargetFeatures ( CPUName , TuneCPUName , FS ) ; return * this ; } </s>


<s> bool CSKYPassConfig :: addInstSelector ( ) { addPass ( createCSKYISelDag ( getCSKYTargetMachine ( ) ) ) ; return false ; } </s>

addInstSelector - This method should install an instruction selector pass , which converts from LLVM code to machine instructions .


<s> void CSKYPassConfig :: addIRPasses ( ) { addPass ( createAtomicExpandPass ( ) ) ; TargetPassConfig :: addIRPasses ( ) ; } </s>

Add common target configurable passes that perform LLVM IR to IR transforms following machine independent optimization .


<s> void CSKYPassConfig :: addPreEmitPass ( ) { addPass ( createCSKYConstantIslandPass ( ) ) ; } </s>

This pass may be implemented by targets that want to run passes immediately before machine code is emitted .


<s> TargetPassConfig * CSKYTargetMachine :: createPassConfig ( PassManagerBase & PM ) { return new CSKYPassConfig ( * this , PM ) ; } </s>

Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of CodeGen passes .


<s> TargetLoweringObjectFile * getObjFileLowering ( ) const override { return TLOF . get ( ) ; } </s>

Return information about object file lowering .


"Hard-float can't be used with current CPU,"

Virtual method implemented by subclasses that returns a reference to that target 's TargetSubtargetInfo-derived member variable .


<s> void CSKYELFTargetObjectFile :: Initialize ( MCContext & Ctx , const TargetMachine & TM ) { TargetLoweringObjectFileELF :: Initialize ( Ctx , TM ) ; LSDAEncoding = dwarf :: DW_EH_PE_pcrel | dwarf :: DW_EH_PE_sdata4 ; PersonalityEncoding = dwarf :: DW_EH_PE_indirect | dwarf :: DW_EH_PE_pcrel | dwarf :: DW_EH_PE_sdata4 ; TTypeEncoding = dwarf :: DW_EH_PE_indirect | dwarf :: DW_EH_PE_pcrel | dwarf :: DW_EH_PE_sdata4 ; } </s>

This method must be called before any actual lowering is done .


<s> const MCExpr * CSKYTargetStreamer :: addConstantPoolEntry ( const MCExpr * Expr , SMLoc Loc , const MCExpr * AdjustExpr ) { auto ELFRefKind = CSKYMCExpr :: VK_CSKY_Invalid ; ConstantCounter ++ ; const MCExpr * OrigExpr = Expr ; if ( const CSKYMCExpr * CE = dyn_cast < CSKYMCExpr > ( Expr ) ) { Expr = CE -> getSubExpr ( ) ; ELFRefKind = CE -> getKind ( ) ; } if ( const MCSymbolRefExpr * SymExpr = dyn_cast < MCSymbolRefExpr > ( Expr ) ) { const MCSymbol * Sym = & SymExpr -> getSymbol ( ) ; SymbolIndex Index = { Sym , ELFRefKind } ; if ( ConstantMap . find ( Index ) == ConstantMap . end ( ) ) { ConstantMap [ Index ] = ConstantPool -> addEntry ( getStreamer ( ) , OrigExpr , 4 , Loc , AdjustExpr ) ; } return ConstantMap [ Index ] ; } return ConstantPool -> addEntry ( getStreamer ( ) , Expr , 4 , Loc , AdjustExpr ) ; } </s>

Add a new entry to the constant pool for the current section and return an MCExpr that can be used to refer to the constant pool location .


<s> void CSKYTargetStreamer :: emitCurrentConstantPool ( ) { ConstantPool -> emitAll ( Streamer ) ; ConstantPool -> clearCache ( ) ; } </s>

Callback used to implement the .ltorg directive .


<s> void CSKYTargetStreamer :: emitTargetAttributes ( const MCSubtargetInfo & STI ) { } </s>

Emit the build attributes that only depend on the hardware that we expect .


<s> bool CSKYConstantPool :: empty ( ) { return Entries . empty ( ) ; } </s>

Determine whether this version information is empty ( e.g. , all version components are zero ) .


<s> void CSKYTargetStreamer :: finish ( ) { if ( ConstantCounter != 0 ) { ConstantPool -> emitAll ( Streamer ) ; } finishAttributeSection ( ) ; } </s>

finish - after all the new live ranges have been created , compute the remaining live range , and rewrite instructions to use the new registers .


<s> static inline CSKYTargetStreamer :: SymbolIndex getEmptyKey ( ) { return { nullptr , CSKYMCExpr :: VK_CSKY_Invalid } ; } </s>

Empty key : no key should be generated that has no DILocalVariable .


<s> static unsigned getHashValue ( const CSKYTargetStreamer :: SymbolIndex & V ) { return hash_combine ( DenseMapInfo < const MCSymbol * > :: getHashValue ( V . sym ) , DenseMapInfo < int > :: getHashValue ( V . kind ) ) ; } </s>

Using name and line to get hash value . It should already be mostly unique .


<s> static inline CSKYTargetStreamer :: SymbolIndex getTombstoneKey ( ) { return { nullptr , CSKYMCExpr :: VK_CSKY_Invalid } ; } </s>

Difference in tombstone is that the Optional is meaningful .


<s> static bool isEqual ( const CSKYTargetStreamer :: SymbolIndex & A , const CSKYTargetStreamer :: SymbolIndex & B ) { return A . sym == B . sym && A . kind == B . kind ; } </s>

isEqual - Compares two trees for structural equality and returns true if they are equal .